[Pkg-mysql-commits] r1151 - / trunk trunk/.bzr-builddeb trunk/debian trunk/debian/patches

Monty Taylor mtaylor-guest at alioth.debian.org
Wed Feb 20 15:18:04 UTC 2008


Author: mtaylor-guest
Date: 2008-02-20 15:18:03 +0000 (Wed, 20 Feb 2008)
New Revision: 1151

Added:
   trunk/
   trunk/.bzr-builddeb/
   trunk/.bzr-builddeb/default.conf
   trunk/debian/patches/88_sphinx_se.dpatch
Removed:
   trunk/
   trunk/.bzr-builddeb/
Modified:
   trunk/debian/changelog
   trunk/debian/patches/00list
   trunk/debian/rules
Log:
Merged in Sphinx SE changes. 


Copied: trunk (from rev 1112, trunk)


Property changes on: trunk
___________________________________________________________________
Name: bzr:revision-info
   + timestamp: 2007-12-27 17:49:30.186000109 -0600
committer: Monty Taylor <monty at inaugust.com>
properties: 
	branch-nick: trunk

Name: bzr:ancestry:v3-trunk0
   + svn-v3-trunk0:bb5a2ed9-75f0-0310-a2b8-e46d7b0922c1:trunk:1093
monty at inaugust.com-20071219005821-v5qtsv9qvi70s0mt
monty at inaugust.com-20071227223102-6uiuykhyivk9r6q9

Name: bzr:file-ids
   + .bzr-builddeb	bzrbuilddeb-20071227181200-g5kb62cmn3p06bnq-1
.bzr-builddeb/default.conf	default.conf-20071227181200-g5kb62cmn3p06bnq-2
debian/patches/88_sphinx_se.dpatch	88_sphinx_se.dpatch-20071227190041-o70oy01cua81qy9k-1

Name: bzr:revision-id:v3-trunk0
   + 588 monty at inaugust.com-20071218115655-e9a3qdeanxkm37q0
589 monty at inaugust.com-20071219010144-z07rx72f4aryuxd5
590 monty at inaugust.com-20071219010251-1xj8ebk20xcavzzz
591 monty at inaugust.com-20071219133703-cfc7gcr1mfrbff5k
594 monty at inaugust.com-20071219160333-4t3d5sm5ou2cnx42
600 monty at inaugust.com-20071227231232-38mmb4bf89bai9tz
601 monty at inaugust.com-20071227231533-6u75bgvr52589l9d
602 monty at inaugust.com-20071227232516-5e1uuemjok6gax36
603 monty at inaugust.com-20071227232613-mvmphhlfm3ucfjre
604 monty at inaugust.com-20071227232728-26ik99mzw0yhq4vi
605 monty at inaugust.com-20071227234930-zlri2er7sq9obnot

Name: svk:merge
   + bb5a2ed9-75f0-0310-a2b8-e46d7b0922c1:/trunk:1093


Added: trunk/.bzr-builddeb/default.conf
===================================================================
--- trunk/.bzr-builddeb/default.conf	                        (rev 0)
+++ trunk/.bzr-builddeb/default.conf	2008-02-20 15:18:03 UTC (rev 1151)
@@ -0,0 +1,2 @@
+[BUILDDEB]
+merge = True

Modified: trunk/debian/changelog
===================================================================
--- trunk/debian/changelog	2007-12-27 23:28:35 UTC (rev 1112)
+++ trunk/debian/changelog	2008-02-20 15:18:03 UTC (rev 1151)
@@ -9,13 +9,14 @@
     closed with http://lists.mysql.com/commits/24337
   * Added mysql-community/mysql-enterprise virtual packages in provides and
     conflicts to ease transitions between versions. 
+  * Added Sphinx SE integration
 
   [ Norbert Tretkowski ]
   * Add -fPIC to CFLAGS to allow other packages to be built against
     libmysqld.a on amd64. (closes: #457915)
   * New patch 54_ssl-client-support.dpatch to fix SSL client support.
 
- -- Norbert Tretkowski <nobse at debian.org>  Thu, 27 Dec 2007 09:37:03 +0100
+ -- Monty Taylor <monty at inaugust.com>  Thu, 27 Dec 2007 12:13:36 -0600
 
 mysql-dfsg-5.0 (5.0.51-1) unstable; urgency=low
 

Modified: trunk/debian/patches/00list
===================================================================
--- trunk/debian/patches/00list	2007-12-27 23:28:35 UTC (rev 1112)
+++ trunk/debian/patches/00list	2008-02-20 15:18:03 UTC (rev 1151)
@@ -12,6 +12,7 @@
 53_integer-gcc-4.2.dpatch
 54_ssl-client-support.dpatch
 86_PATH_MAX.dpatch
+88_sphinx_se.dpatch
 89_ndb__staticlib.dpatch
 90_upstreamdebiandir.dpatch
 91_SECURITY_CVE-2007-5925.dpatch

Added: trunk/debian/patches/88_sphinx_se.dpatch
===================================================================
--- trunk/debian/patches/88_sphinx_se.dpatch	                        (rev 0)
+++ trunk/debian/patches/88_sphinx_se.dpatch	2008-02-20 15:18:03 UTC (rev 1151)
@@ -0,0 +1,42463 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 88_sphinx_se.dpatch by Monty Taylor
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Add Sphinx Storage Engine
+
+ at DPATCH@
+diff -urNad trunk~/BUILD/Makefile.in trunk/BUILD/Makefile.in
+--- trunk~/BUILD/Makefile.in	2007-11-15 08:08:10.000000000 -0600
++++ trunk/BUILD/Makefile.in	2007-12-27 15:54:48.310207924 -0600
+@@ -64,6 +64,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/Docs/Makefile.in trunk/Docs/Makefile.in
+--- trunk~/Docs/Makefile.in	2007-12-27 15:54:27.621028915 -0600
++++ trunk/Docs/Makefile.in	2007-12-27 15:54:48.310207924 -0600
+@@ -828,6 +828,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/Makefile.in trunk/Makefile.in
+--- trunk~/Makefile.in	2007-11-15 08:08:52.000000000 -0600
++++ trunk/Makefile.in	2007-12-27 15:54:48.310207924 -0600
+@@ -67,6 +67,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/SSL/Makefile.in trunk/SSL/Makefile.in
+--- trunk~/SSL/Makefile.in	2007-11-15 08:08:10.000000000 -0600
++++ trunk/SSL/Makefile.in	2007-12-27 15:54:48.314208152 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/client/Makefile.in trunk/client/Makefile.in
+--- trunk~/client/Makefile.in	2007-11-15 08:08:11.000000000 -0600
++++ trunk/client/Makefile.in	2007-12-27 15:54:48.314208152 -0600
+@@ -71,6 +71,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/cmd-line-utils/Makefile.in trunk/cmd-line-utils/Makefile.in
+--- trunk~/cmd-line-utils/Makefile.in	2007-11-15 08:08:11.000000000 -0600
++++ trunk/cmd-line-utils/Makefile.in	2007-12-27 15:54:48.314208152 -0600
+@@ -64,6 +64,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/cmd-line-utils/libedit/Makefile.in trunk/cmd-line-utils/libedit/Makefile.in
+--- trunk~/cmd-line-utils/libedit/Makefile.in	2007-11-15 08:08:12.000000000 -0600
++++ trunk/cmd-line-utils/libedit/Makefile.in	2007-12-27 15:54:48.738232316 -0600
+@@ -53,6 +53,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/cmd-line-utils/readline/Makefile.in trunk/cmd-line-utils/readline/Makefile.in
+--- trunk~/cmd-line-utils/readline/Makefile.in	2007-11-15 08:08:13.000000000 -0600
++++ trunk/cmd-line-utils/readline/Makefile.in	2007-12-27 15:54:48.738232316 -0600
+@@ -53,6 +53,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/config/ac-macros/ha_sphinx.m4 trunk/config/ac-macros/ha_sphinx.m4
+--- trunk~/config/ac-macros/ha_sphinx.m4	1969-12-31 18:00:00.000000000 -0600
++++ trunk/config/ac-macros/ha_sphinx.m4	2007-12-27 15:54:48.738232316 -0600
+@@ -0,0 +1,30 @@
++dnl ---------------------------------------------------------------------------
++dnl Macro: MYSQL_CHECK_EXAMPLEDB
++dnl Sets HAVE_SPHINX_DB if --with-sphinx-storage-engine is used
++dnl ---------------------------------------------------------------------------
++AC_DEFUN([MYSQL_CHECK_SPHINXDB], [
++  AC_ARG_WITH([sphinx-storage-engine],
++              [
++  --with-sphinx-storage-engine
++                          Enable the Sphinx Storage Engine],
++              [sphinxdb="$withval"],
++              [sphinxdb=no])
++  AC_MSG_CHECKING([for example storage engine])
++
++  case "$sphinxdb" in
++    yes )
++      AC_DEFINE([HAVE_SPHINX_DB], [1], [Builds Sphinx Engine])
++      AC_MSG_RESULT([yes])
++      [sphinxdb=yes]
++      ;;
++    * )
++      AC_MSG_RESULT([no])
++      [sphinxdb=no]
++      ;;
++  esac
++
++])
++dnl ---------------------------------------------------------------------------
++dnl END OF MYSQL_CHECK_EXAMPLE SECTION
++dnl ---------------------------------------------------------------------------
++
+diff -urNad trunk~/config.h.in trunk/config.h.in
+--- trunk~/config.h.in	2007-11-15 08:08:03.000000000 -0600
++++ trunk/config.h.in	2007-12-27 15:54:48.738232316 -0600
+@@ -703,6 +703,9 @@
+ /* Spatial extentions */
+ #undef HAVE_SPATIAL
+ 
++/* Builds Sphinx Engine */
++#undef HAVE_SPHINX_DB
++
+ /* Define to 1 if you have the <stdarg.h> header file. */
+ #undef HAVE_STDARG_H
+ 
+diff -urNad trunk~/configure trunk/configure
+--- trunk~/configure	2007-11-15 08:08:54.000000000 -0600
++++ trunk/configure	2007-12-27 15:54:48.750232999 -0600
+@@ -1165,6 +1165,9 @@
+   --with-example-storage-engine
+                           Enable the Example Storage Engine
+ 
++  --with-sphinx-storage-engine
++                          Enable the Sphinx Storage Engine
++
+   --with-archive-storage-engine
+                           Enable the Archive Storage Engine
+ 
+@@ -2954,6 +2957,9 @@
+ 
+ 
+ 
++
++
++
+ # Local macros for automake & autoconf
+ 
+ # A local version of AC_CHECK_SIZEOF that includes sys/types.h
+@@ -41123,6 +41129,35 @@
+   esac
+ 
+ 
++# Check whether --with-sphinx-storage-engine was given.
++if test "${with_sphinx_storage_engine+set}" = set; then
++  withval=$with_sphinx_storage_engine; sphinxdb="$withval"
++else
++  sphinxdb=no
++fi
++
++  echo "$as_me:$LINENO: checking for example storage engine" >&5
++  echo $ECHO_N "checking for example storage engine... $ECHO_C" >&6;
++
++  case "$sphinxdb" in
++    yes )
++
++cat >>confdefs.h <<\_ACEOF
++#define HAVE_SPHINX_DB 1
++_ACEOF
++
++       { echo "$as_me:$LINENO: result: yes" >&5
++echo "${ECHO_T}yes" >&6; }
++      sphinxdb=yes
++      ;;
++    * )
++      { echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6; }
++      sphinxdb=no
++      ;;
++  esac
++
++
+ 
+ 
+ # Check whether --with-archive-storage-engine or --without-archive-storage-engine was given.
+diff -urNad trunk~/configure.in trunk/configure.in
+--- trunk~/configure.in	2007-11-15 08:06:32.000000000 -0600
++++ trunk/configure.in	2007-12-27 15:54:48.754233227 -0600
+@@ -48,6 +48,7 @@
+ sinclude(config/ac-macros/ha_berkeley.m4)
+ sinclude(config/ac-macros/ha_blackhole.m4)
+ sinclude(config/ac-macros/ha_example.m4)
++sinclude(config/ac-macros/ha_sphinx.m4)
+ sinclude(config/ac-macros/ha_federated.m4)
+ sinclude(config/ac-macros/ha_innodb.m4)
+ sinclude(config/ac-macros/ha_ndbcluster.m4)
+@@ -2574,6 +2575,7 @@
+ MYSQL_CHECK_BDB
+ MYSQL_CHECK_INNODB
+ MYSQL_CHECK_EXAMPLEDB
++MYSQL_CHECK_SPHINXDB
+ MYSQL_CHECK_ARCHIVEDB
+ MYSQL_CHECK_CSVDB
+ MYSQL_CHECK_BLACKHOLEDB
+diff -urNad trunk~/configure.in.orig trunk/configure.in.orig
+--- trunk~/configure.in.orig	1969-12-31 18:00:00.000000000 -0600
++++ trunk/configure.in.orig	2007-12-27 15:54:48.754233227 -0600
+@@ -0,0 +1,3019 @@
++dnl -*- ksh -*-
++dnl Process this file with autoconf to produce a configure script.
++
++AC_PREREQ(2.52)dnl		Minimum Autoconf version required.
++
++AC_INIT(sql/mysqld.cc)
++AC_CANONICAL_SYSTEM
++# The Docs Makefile.am parses this line!
++# remember to also change ndb version below and update version.c in ndb
++AM_INIT_AUTOMAKE(mysql, 5.0.51)
++AM_CONFIG_HEADER([include/config.h:config.h.in])
++
++PROTOCOL_VERSION=10
++DOT_FRM_VERSION=6
++# See the libtool docs for information on how to do shared lib versions.
++SHARED_LIB_MAJOR_VERSION=15
++SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0
++
++NDB_SHARED_LIB_MAJOR_VERSION=2
++NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0
++
++
++# ndb version
++NDB_VERSION_MAJOR=5
++NDB_VERSION_MINOR=0
++NDB_VERSION_BUILD=51
++NDB_VERSION_STATUS=""
++
++# Set all version vars based on $VERSION. How do we do this more elegant ?
++# Remember that regexps needs to quote [ and ] since this is run through m4
++MYSQL_NO_DASH_VERSION=`echo $VERSION | sed -e "s|[[a-z]]*-.*$||"`
++MYSQL_BASE_VERSION=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|\.[[^.]]*$||"`
++MYSQL_VERSION_ID=`echo $MYSQL_NO_DASH_VERSION | sed -e 's|[[^0-9.]].*$||;s|$|.|' | sed -e 's/[[^0-9.]]//g; s/\./  /g; s/ \([[0-9]]\) / 0\\1 /g; s/ //g'`
++
++# Add previous major version for debian package upgrade path
++MYSQL_PREVIOUS_BASE_VERSION=4.1
++
++# The port should be constant for a LONG time
++MYSQL_TCP_PORT_DEFAULT=3306
++MYSQL_UNIX_ADDR_DEFAULT="/tmp/mysql.sock"
++
++dnl Include m4 
++sinclude(config/ac-macros/alloca.m4)
++sinclude(config/ac-macros/check_cpu.m4)
++sinclude(config/ac-macros/character_sets.m4)
++sinclude(config/ac-macros/compiler_flag.m4)
++sinclude(config/ac-macros/ha_archive.m4)
++sinclude(config/ac-macros/ha_berkeley.m4)
++sinclude(config/ac-macros/ha_blackhole.m4)
++sinclude(config/ac-macros/ha_example.m4)
++sinclude(config/ac-macros/ha_federated.m4)
++sinclude(config/ac-macros/ha_innodb.m4)
++sinclude(config/ac-macros/ha_ndbcluster.m4)
++sinclude(config/ac-macros/ha_tina.m4)
++sinclude(config/ac-macros/large_file.m4)
++sinclude(config/ac-macros/misc.m4)
++sinclude(config/ac-macros/openssl.m4)
++sinclude(config/ac-macros/readline.m4)
++sinclude(config/ac-macros/yassl.m4)
++sinclude(config/ac-macros/zlib.m4)
++
++# Remember to add a directory sql/share/LANGUAGE
++AVAILABLE_LANGUAGES="\
++czech danish dutch english estonian french german greek hungarian \
++italian japanese korean norwegian norwegian-ny polish portuguese \
++romanian russian serbian slovak spanish swedish ukrainian"
++
++#####
++#####
++
++AC_SUBST(MYSQL_NO_DASH_VERSION)
++AC_SUBST(MYSQL_BASE_VERSION)
++AC_SUBST(MYSQL_VERSION_ID)
++AC_SUBST(MYSQL_PREVIOUS_BASE_VERSION)
++AC_SUBST(PROTOCOL_VERSION)
++AC_DEFINE_UNQUOTED([PROTOCOL_VERSION], [$PROTOCOL_VERSION],
++                   [mysql client protocol version])
++AC_SUBST(DOT_FRM_VERSION)
++AC_DEFINE_UNQUOTED([DOT_FRM_VERSION], [$DOT_FRM_VERSION],
++                   [Version of .frm files])
++AC_SUBST(SHARED_LIB_MAJOR_VERSION)
++AC_SUBST(SHARED_LIB_VERSION)
++AC_SUBST(NDB_SHARED_LIB_MAJOR_VERSION)
++AC_SUBST(NDB_SHARED_LIB_VERSION)
++
++AC_SUBST(AVAILABLE_LANGUAGES)
++
++AC_SUBST([NDB_VERSION_MAJOR])
++AC_SUBST([NDB_VERSION_MINOR])
++AC_SUBST([NDB_VERSION_BUILD])
++AC_SUBST([NDB_VERSION_STATUS])
++AC_DEFINE_UNQUOTED([NDB_VERSION_MAJOR], [$NDB_VERSION_MAJOR],
++                   [NDB major version])
++AC_DEFINE_UNQUOTED([NDB_VERSION_MINOR], [$NDB_VERSION_MINOR],
++                   [NDB minor version])
++AC_DEFINE_UNQUOTED([NDB_VERSION_BUILD], [$NDB_VERSION_BUILD],
++                   [NDB build version])
++AC_DEFINE_UNQUOTED([NDB_VERSION_STATUS], ["$NDB_VERSION_STATUS"],
++                   [NDB status version])
++
++
++# Canonicalize the configuration name.
++
++# Check whether --with-system-type or --without-system-type was given.
++AC_ARG_WITH(system-type,
++    [  --with-system-type      Set the system type, like "sun-solaris10"],
++    [SYSTEM_TYPE="$withval"],
++    [SYSTEM_TYPE="$host_vendor-$host_os"])
++AC_ARG_WITH(machine-type,
++    [  --with-machine-type     Set the machine type, like "powerpc"],
++    [MACHINE_TYPE="$withval"],
++    [MACHINE_TYPE="$host_cpu"])
++AC_SUBST(SYSTEM_TYPE)
++AC_DEFINE_UNQUOTED([SYSTEM_TYPE], ["$SYSTEM_TYPE"],
++                   [Name of system, eg sun-solaris])
++AC_SUBST(MACHINE_TYPE)
++AC_DEFINE_UNQUOTED([MACHINE_TYPE], ["$MACHINE_TYPE"],
++                   [Machine type name, eg sparc])
++
++# Detect intel x86 like processor
++BASE_MACHINE_TYPE=$MACHINE_TYPE
++case $MACHINE_TYPE in
++  i?86) BASE_MACHINE_TYPE=i386 ;;
++esac
++
++# Save some variables and the command line options for mysqlbug
++SAVE_ASFLAGS="$ASFLAGS"
++SAVE_CFLAGS="$CFLAGS"
++SAVE_CXXFLAGS="$CXXFLAGS"
++SAVE_LDFLAGS="$LDFLAGS"
++SAVE_CXXLDFLAGS="$CXXLDFLAGS"
++CONF_COMMAND="$0 $ac_configure_args"
++AC_SUBST(CONF_COMMAND)
++AC_SUBST(SAVE_ASFLAGS)
++AC_SUBST(SAVE_CFLAGS)
++AC_SUBST(SAVE_CXXFLAGS)
++AC_SUBST(SAVE_LDFLAGS)
++AC_SUBST(SAVE_CXXLDFLAGS)
++AC_SUBST(CXXLDFLAGS)
++
++#AC_ARG_PROGRAM			# Automaticly invoked by AM_INIT_AUTOMAKE
++
++AM_SANITY_CHECK
++# This is needed is SUBDIRS is set
++AC_PROG_MAKE_SET
++
++##############################################################################
++# The below section needs to be done before AC_PROG_CC
++##############################################################################
++
++# Hack for OS X/Darwin and Metrowerks CodeWarrior
++AC_ARG_WITH(darwin-mwcc,
++[  --with-darwin-mwcc      Use Metrowerks CodeWarrior wrappers on OS X/Darwin],[
++ if [ "with_darwin_mwcc" = yes ] ; then
++  builddir=`pwd`
++  ccwrapper="$builddir/support-files/MacOSX/mwcc-wrapper"
++  arwrapper="$builddir/support-files/MacOSX/mwar-wrapper"
++  CC="$ccwrapper"
++  CXX="$ccwrapper"
++  LD="$ccwrapper"
++  AR="$arwrapper"
++  RANLIB=:
++  export CC CXX LD AR RANLIB
++  AC_SUBST(AR)
++  AC_SUBST(RANLIB)
++ fi
++])
++
++AM_CONDITIONAL(DARWIN_MWCC, test x$with_darwin_mwcc = xyes)
++
++if test "x${CFLAGS-}" = x ; then
++  cflags_is_set=no
++else
++  cflags_is_set=yes
++fi
++
++if test "x${CPPFLAGS-}" = x ; then
++  cppflags_is_set=no
++else
++  cppflags_is_set=yes
++fi
++
++if test "x${LDFLAGS-}" = x ; then
++  ldflags_is_set=no
++else
++  ldflags_is_set=yes
++fi
++
++################ End of section to be done before AC_PROG_CC #################
++
++# The following hack should ensure that configure doesn't add optimizing
++# or debugging flags to CFLAGS or CXXFLAGS
++# C_EXTRA_FLAGS are flags that are automaticly added to both
++# CFLAGS and CXXFLAGS
++CFLAGS="$CFLAGS $C_EXTRA_FLAGS "
++CXXFLAGS="$CXXFLAGS $C_EXTRA_FLAGS "
++
++dnl Checks for programs.
++AC_PROG_AWK
++AC_PROG_CC
++AC_PROG_CXX
++AC_PROG_CPP
++
++# Print version of CC and CXX compiler (if they support --version)
++case $SYSTEM_TYPE in
++  *netware*)
++CC_VERSION=`$CC -version | grep -i version`
++    ;;
++  *)
++CC_VERSION=`$CC --version | sed 1q`
++    ;;
++esac
++if test $? -eq "0"
++then
++  AC_MSG_CHECKING("C Compiler version");
++  AC_MSG_RESULT("$CC $CC_VERSION")
++else
++CC_VERSION=""
++fi
++AC_SUBST(CC_VERSION)
++MYSQL_CHECK_CXX_VERSION
++
++# Fix for sgi gcc / sgiCC which tries to emulate gcc
++if test "$CC" = "sgicc"
++then
++  ac_cv_prog_gcc="no"
++fi
++if test "$CXX" = "sgi++"
++then
++  GXX="no"
++fi
++
++if test "$ac_cv_prog_gcc" = "yes"
++then
++  AS="$CC -c"
++  AC_SUBST(AS)
++else
++  AC_PATH_PROG(AS, as, as)
++fi
++
++# Still need ranlib for readline; local static use only so no libtool.
++AC_PROG_RANLIB
++# We use libtool
++#AC_LIBTOOL_WIN32_DLL
++AC_PROG_LIBTOOL
++
++# Ensure that we have --preserve-dup-deps defines, otherwise we get link
++# problems of 'mysql' with CXX=g++
++LIBTOOL="$LIBTOOL --preserve-dup-deps"
++AC_SUBST(LIBTOOL)dnl
++
++AC_SUBST(NM)dnl
++
++# NM= "$NM -X64"
++#archive_expsym_cmds= `echo "$archive_expsym_cmds" | sed -e '/"$(CC)"//'`
++#archive_expsym_cmds= "$CC -q64 $archive_expsym_cmds"
++#  CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed -e 's/-fbranch-probabilities//; s/-Wall//; s/-ansi//; s/-pedantic//; s/-Wcheck//'`
++
++#AC_LIBTOOL_DLOPEN AC_LIBTOOL_WIN32_DLL AC_DISABLE_FAST_INSTALL AC_DISABLE_SHARED AC_DISABLE_STATIC
++
++# AC_PROG_INSTALL
++AC_PROG_INSTALL
++test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
++
++# Not critical since the generated file is distributed
++AC_CHECK_PROGS(YACC, ['bison -y -p MYSQL'])
++AC_CHECK_PROG(PDFMANUAL, pdftex, manual.pdf)
++AC_CHECK_PROG(DVIS,      tex,    manual.dvi)
++
++AC_MSG_CHECKING("return type of sprintf")
++
++#check the return type of sprintf
++case $SYSTEM_TYPE in
++  *netware*)
++    AC_DEFINE(SPRINTF_RETURNS_INT, [1]) AC_MSG_RESULT("int")
++    ;;
++  *)
++AC_TRY_RUN([
++  int main()
++    {
++      char* s = "hello";
++      char buf[6];
++      if((int)sprintf(buf, s) == strlen(s))
++	return 0;
++      
++      return -1;
++     }
++   ],
++   [AC_DEFINE(SPRINTF_RETURNS_INT, [1], [POSIX sprintf])
++   AC_MSG_RESULT("int")],
++   [AC_TRY_RUN([
++ int main()
++   {
++     char* s = "hello";
++     char buf[6];
++     if((char*)sprintf(buf,s) == buf + strlen(s))
++       return 0;
++     return -1;
++   }           ],
++               [AC_DEFINE(SPRINTF_RETURNS_PTR, [1], [Broken sprintf])
++                AC_MSG_RESULT("ptr")],
++               [AC_DEFINE(SPRINTF_RETURNS_GARBAGE, [1], [Broken sprintf])
++                AC_MSG_RESULT("garbage")])
++   ])
++    ;;
++esac
++
++AC_PATH_PROG(uname_prog, uname, no)
++
++# We should go through this and put all the explictly system dependent
++# stuff in one place
++AC_MSG_CHECKING(operating system)
++AC_CACHE_VAL(mysql_cv_sys_os,
++[
++if test "$uname_prog" != "no"; then
++  mysql_cv_sys_os="`uname`"
++else
++  mysql_cv_sys_os="Not Solaris"
++fi
++])
++AC_MSG_RESULT($mysql_cv_sys_os)
++
++# This should be rewritten to use $target_os
++case "$target_os" in
++  sco3.2v5*) 
++     CFLAGS="$CFLAGS -DSCO"
++     CXXFLAGS="$CXXFLAGS -DSCO"
++     LD='$(CC) $(CFLAGS)'
++     case "$CFLAGS" in
++       *-belf*) 
++         AC_SYS_COMPILER_FLAG(-belf,sco_belf_option,CFLAGS,[],[
++         case "$LDFLAGS" in
++           *-belf*) ;;
++           *) AC_MSG_WARN([Adding -belf option to ldflags.])
++              LDFLAGS="$LDFLAGS -belf"
++           ;;
++         esac
++         ])
++       ;;
++       *)
++         AC_SYS_COMPILER_FLAG(-belf,sco_belf_option,CFLAGS,[],[
++         case "$LDFLAGS" in
++           *-belf*) ;;
++           *)
++	     AC_MSG_WARN([Adding -belf option to ldflags.])
++             LDFLAGS="$LDFLAGS -belf"
++           ;;
++         esac
++         ])
++       ;;
++     esac
++  ;;
++  sysv5UnixWare* | sysv5OpenUNIX8*) 
++    if test "$GCC" != "yes"; then
++      # Use the built-in alloca()
++      CFLAGS="$CFLAGS -Kalloca"
++    fi
++    CXXFLAGS="$CXXFLAGS -DNO_CPLUSPLUS_ALLOCA"
++  ;;
++  sysv5SCO_SV6.0.0*)
++    if test "$GCC" != "yes"; then
++      # 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
++AC_SUBST(CC)
++AC_SUBST(CFLAGS)
++AC_SUBST(CXX)
++AC_SUBST(CXXFLAGS)
++AC_SUBST(LD)
++AC_SUBST(INSTALL_SCRIPT)
++
++export CC CXX CFLAGS LD LDFLAGS AR ARFLAGS
++
++if test "$GCC" = "yes"
++then
++  # mysqld requires -fno-implicit-templates.
++  # Disable exceptions as they seams to create problems with gcc and threads.
++  # mysqld doesn't use run-time-type-checking, so we disable it.
++  # We should use -Wno-invalid-offsetof flag to disable some warnings from gcc
++  # regarding offset() usage in C++ which are done in a safe manner in the
++  # server
++  CXXFLAGS="$CXXFLAGS -fno-implicit-templates -fno-exceptions -fno-rtti"
++  AC_DEFINE([HAVE_EXPLICIT_TEMPLATE_INSTANTIATION],
++    [1], [Defined by configure. Use explicit template instantiation.])
++fi
++
++MYSQL_PROG_AR
++
++# libmysqlclient versioning when linked with GNU ld.
++if $LD --version 2>/dev/null|grep -q GNU; then
++  LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_builddir)/libmysql/libmysql.ver"
++  AC_CONFIG_FILES(libmysql/libmysql.ver)
++fi
++AC_SUBST(LD_VERSION_SCRIPT)
++
++
++# Avoid bug in fcntl on some versions of linux
++AC_MSG_CHECKING([if we should use 'skip-external-locking' as default for $target_os])
++# Any variation of Linux
++if expr "$target_os" : "[[Ll]]inux.*" > /dev/null
++then
++  MYSQLD_DEFAULT_SWITCHES="--skip-external-locking"
++  TARGET_LINUX="true"
++  AC_MSG_RESULT([yes])
++  AC_DEFINE([TARGET_OS_LINUX], [1], [Whether we build for Linux])
++else
++  MYSQLD_DEFAULT_SWITCHES=""
++  TARGET_LINUX="false"
++  AC_MSG_RESULT([no])
++fi
++AC_SUBST(MYSQLD_DEFAULT_SWITCHES)
++AC_SUBST(TARGET_LINUX)
++
++dnl Find paths to some shell programs
++AC_PATH_PROG(LN, ln, ln)
++# This must be able to take a -f flag like normal unix ln.
++AC_PATH_PROG(LN_CP_F, ln, ln)
++if ! ( expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null ); then
++# If ln -f does not exists use -s (AFS systems)
++if test -n "$LN_CP_F"; then
++  LN_CP_F="$LN_CP_F -s"
++fi
++fi
++
++AC_PATH_PROG(MV, mv, mv)
++AC_PATH_PROG(RM, rm, rm)
++AC_PATH_PROG(CP, cp, cp)
++AC_PATH_PROG(SED, sed, sed)
++AC_PATH_PROG(CMP, cmp, cmp)
++AC_PATH_PROG(CHMOD, chmod, chmod)
++AC_PATH_PROG(HOSTNAME, hostname, hostname)
++# Check for a GNU tar named 'gtar', or 'gnutar' (MacOS X) and
++# fall back to 'tar' otherwise and hope that it's a GNU tar as well
++AC_CHECK_PROGS(TAR, gnutar gtar tar)
++
++dnl We use a path for perl so the script startup works
++dnl We make sure to use perl, not perl5, in hopes that the RPMs will
++dnl not depend on the perl5 binary being installed (probably a bug in RPM)
++AC_PATH_PROG(PERL, perl, no)
++if test "$PERL" != "no" && $PERL -e 'require 5' > /dev/null 2>&1
++then
++  PERL5=$PERL
++else
++  AC_PATH_PROG(PERL5, perl5, no)
++  if test "$PERL5" != no
++  then
++    PERL=$PERL5
++    ac_cv_path_PERL=$ac_cv_path_PERL5
++  fi
++fi
++
++AC_SUBST(HOSTNAME)
++AC_SUBST(PERL)
++AC_SUBST(PERL5)
++
++# for build ndb docs
++
++AC_PATH_PROG(DOXYGEN, doxygen, no)
++AC_PATH_PROG(PDFLATEX, pdflatex, no)
++AC_PATH_PROG(MAKEINDEX, makeindex, no)
++AC_SUBST(DOXYGEN)
++AC_SUBST(PDFLATEX)
++AC_SUBST(MAKEINDEX)
++
++# icheck, used for ABI check
++AC_PATH_PROG(ICHECK, icheck, no)
++# "icheck" is also the name of a file system check program on Tru64.
++# Verify the program found is really the interface checker.
++if test "x$ICHECK" != "xno"
++then
++  AC_MSG_CHECKING(if $ICHECK works as expected)
++  echo "int foo;" > conftest.h
++  $ICHECK --canonify -o conftest.ic conftest.h 2>/dev/null
++  if test -f "conftest.ic"
++  then
++    AC_MSG_RESULT(yes)
++  else
++    AC_MSG_RESULT(no)
++    ICHECK=no
++  fi
++  rm -f conftest.ic conftest.h
++fi
++AC_SUBST(ICHECK)
++
++# Lock for PS
++AC_PATH_PROG(PS, ps, ps)
++AC_MSG_CHECKING("how to check if pid exists")
++PS=$ac_cv_path_PS
++# Linux style
++if $PS p $$ 2> /dev/null | grep `echo $0 | sed s/\-//` > /dev/null
++then
++  FIND_PROC="$PS p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null"
++# Solaris
++elif $PS -fp $$ 2> /dev/null | grep $0 > /dev/null
++then
++  FIND_PROC="$PS -p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null"
++# BSD style
++elif $PS -uaxww 2> /dev/null | grep $0 > /dev/null
++then
++  FIND_PROC="$PS -uaxww | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null"
++# SysV style
++elif $PS -ef 2> /dev/null | grep $0 > /dev/null
++then
++  FIND_PROC="$PS -ef | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null"
++# Do anybody use this?
++elif $PS $$ 2> /dev/null | grep $0 > /dev/null
++then
++  FIND_PROC="$PS \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null"
++else
++  case $SYSTEM_TYPE in
++    *freebsd*|*dragonfly*)
++      FIND_PROC="$PS p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null"
++      ;;
++    *darwin*)
++      FIND_PROC="$PS -uaxww | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null"
++      ;;
++    *cygwin*)
++      FIND_PROC="$PS -e | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null"
++      ;;
++    *netware*)
++      FIND_PROC=
++      ;;
++    *)
++      AC_MSG_ERROR([Could not find the right ps switches. Which OS is this ?. See the Installation chapter in the Reference Manual.])
++  esac
++fi
++AC_SUBST(FIND_PROC)
++AC_MSG_RESULT("$FIND_PROC")
++
++# Check if a pid is valid
++AC_PATH_PROG(KILL, kill, kill)
++AC_MSG_CHECKING("for kill switches")
++if $ac_cv_path_KILL -0 $$
++then
++  CHECK_PID="$ac_cv_path_KILL -0 \$\$PID > /dev/null 2> /dev/null"
++elif kill -s 0 $$
++then
++  CHECK_PID="$ac_cv_path_KILL -s 0 \$\$PID > /dev/null 2> /dev/null"
++else
++  AC_MSG_WARN([kill -0 to check for pid seems to fail])
++    CHECK_PID="$ac_cv_path_KILL -s SIGCONT \$\$PID > /dev/null 2> /dev/null"
++fi
++AC_SUBST(CHECK_PID)
++AC_MSG_RESULT("$CHECK_PID")
++
++# We need an ANSI C compiler
++AM_PROG_CC_STDC
++
++# We need an assembler, too
++AM_PROG_AS
++CCASFLAGS="$CCASFLAGS $ASFLAGS"
++
++# Check if we need noexec stack for assembler
++AC_CHECK_NOEXECSTACK
++
++if test "$am_cv_prog_cc_stdc" = "no"
++then
++  AC_MSG_ERROR([MySQL requires an ANSI C compiler (and a C++ compiler). Try gcc. See the Installation chapter in the Reference Manual.])
++fi
++
++NOINST_LDFLAGS="-static"
++
++static_nss=""
++STATIC_NSS_FLAGS=""
++OTHER_LIBC_LIB=""
++AC_ARG_WITH(other-libc,
++ [  --with-other-libc=DIR   Link against libc and other standard libraries 
++                          installed in the specified non-standard location 
++                          overriding default. Originally added to be able to
++                          link against glibc 2.2 without making the user 
++                          upgrade the standard libc installation.],
++ [
++   other_libc_include="$withval/include"
++   other_libc_lib="$withval/lib"
++   with_other_libc="yes"
++   enable_shared="no"
++   all_is_static="yes"
++   CFLAGS="$CFLAGS -I$other_libc_include"
++   # There seems to be a feature in gcc that treats system and libc headers
++   # silently when they violatate ANSI C++ standard, but it is strict otherwise
++   # since gcc cannot now recognize that our headers are libc, we work around
++   # by telling it to be permissive. Note that this option only works with
++   # new versions of gcc (2.95.x and above)
++   CXXFLAGS="$CXXFLAGS -fpermissive -I$other_libc_include"
++   if test -f "$other_libc_lib/libnss_files.a"
++   then
++     # libc has been compiled with --enable-static-nss
++     # we need special flags, but we will have to add those later
++     STATIC_NSS_FLAGS="-lc -lnss_files -lnss_dns -lresolv"
++     STATIC_NSS_FLAGS="$STATIC_NSS_FLAGS $STATIC_NSS_FLAGS"
++     OTHER_LIBC_LIB="-static -L$other_libc_lib"
++     static_nss=1
++   else
++     # this is a dirty hack. We if we detect static nss glibc in the special
++     # location, we do not re-direct the linker to get libraries from there
++     # during check. The reason is that if we did, we would have to find a
++     # way to append the special static nss flags to LIBS every time we do
++     # any check - this is definitely feasible, but not worthwhile the risk
++     # of breaking other things. So for our purposes it would be sufficient
++     # to assume that whoever is using static NSS knows what he is doing and
++     # has sensible libraries in the regular location
++     LDFLAGS="$LDFLAGS -static -L$other_libc_lib "
++   fi
++   
++   # When linking against custom libc installed separately, we want to force
++   # all binary builds to be static, including the build done by configure
++   # itself to test for system features.
++   with_mysqld_ldflags="-all-static"
++   with_client_ldflags="-all-static"
++   NOINST_LDFLAGS="-all-static"
++ ],
++ [
++  other_libc_include=
++  other_libc_lib=
++  with_other_libc="no"
++ ]
++)
++AC_SUBST(NOINST_LDFLAGS)
++
++#
++# Check if we are using Linux and a glibc compiled with static nss
++# (this is true on the MySQL build machines to avoid NSS problems)
++#
++
++if test "$TARGET_LINUX" = "true" -a "$static_nss" = ""
++then
++  tmp=`nm /usr/lib/libc.a  | grep _nss_files_getaliasent_r`
++  if test -n "$tmp"
++  then
++     STATIC_NSS_FLAGS="-lc -lnss_files -lnss_dns -lresolv"
++     STATIC_NSS_FLAGS="$STATIC_NSS_FLAGS $STATIC_NSS_FLAGS"
++     static_nss=1
++  fi
++fi
++
++
++AC_ARG_WITH(server-suffix,
++    [  --with-server-suffix    Append value to the version string.],
++    [ MYSQL_SERVER_SUFFIX=`echo "$withval" | sed -e  's/^\(...................................\)..*$/\1/'` ],
++    [ MYSQL_SERVER_SUFFIX= ]
++    )
++AC_SUBST(MYSQL_SERVER_SUFFIX)
++
++# Set flags if we want to force to use pthreads
++AC_ARG_WITH(pthread,
++    [  --with-pthread          Force use of pthread library.],
++    [ with_pthread=$withval ],
++    [ with_pthread=no ]
++    )
++
++# Force use of thread libs LIBS
++AC_ARG_WITH(named-thread-libs,
++    [  --with-named-thread-libs=ARG
++                          Use specified thread libraries instead of 
++                          those automatically found by configure.],
++    [ with_named_thread=$withval ],
++    [ with_named_thread=no ]
++    )
++
++# Force use of a curses libs
++AC_ARG_WITH(named-curses-libs,
++    [  --with-named-curses-libs=ARG
++                          Use specified curses libraries instead of 
++                          those automatically found by configure.],
++    [ with_named_curses=$withval ],
++    [ with_named_curses=no ]
++    )
++
++# Make thread safe client
++AC_ARG_ENABLE(thread-safe-client,
++    [  --enable-thread-safe-client   
++                          Compile the client with threads.],
++    [ THREAD_SAFE_CLIENT=$enableval ],
++    [ THREAD_SAFE_CLIENT=no ]
++    )
++
++# compile with strings functions in assembler
++AC_ARG_ENABLE(assembler,
++    [  --enable-assembler      Use assembler versions of some string 
++                          functions if available.],
++    [ ENABLE_ASSEMBLER=$enableval ],
++    [ ENABLE_ASSEMBLER=no ]
++    )
++
++AC_MSG_CHECKING(if we should use assembler functions)
++# For now we only support assembler on i386 and sparc systems
++AM_CONDITIONAL(ASSEMBLER_x86, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "i386" && $AS strings/strings-x86.s -o checkassembler >/dev/null 2>&1 && test -f checkassembler && (rm -f checkassembler; exit 0;))
++AM_CONDITIONAL(ASSEMBLER_sparc32, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparc")
++AM_CONDITIONAL(ASSEMBLER_sparc64, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparcv9")
++AM_CONDITIONAL(ASSEMBLER, test "$ASSEMBLER_x86_TRUE" = "" -o "$ASSEMBLER_sparc32_TRUE" = "")
++
++if test "$ASSEMBLER_TRUE" = ""
++then
++  AC_MSG_RESULT([yes])
++else
++  AC_MSG_RESULT([no])
++fi
++
++# Add query profiler
++AC_ARG_ENABLE(profiling,
++    AS_HELP_STRING([--disable-profiling], [Build a version without query profiling code]),
++    [ ENABLED_PROFILING=$enableval ],
++    [ ENABLED_PROFILING=yes ])
++
++if test "$ENABLED_PROFILING" = "yes"
++then
++  AC_DEFINE([ENABLED_PROFILING], [1],
++            [If SHOW PROFILE should be enabled])
++  AC_MSG_RESULT([yes])
++else
++  AC_MSG_RESULT([no])
++fi
++
++# Use this to set the place used for unix socket used to local communication.
++AC_ARG_WITH(unix-socket-path,
++    [  --with-unix-socket-path=SOCKET
++                          Where to put the unix-domain socket.  SOCKET must be 
++                          an absolute file name.],
++    [ MYSQL_UNIX_ADDR=$withval ],
++    [ MYSQL_UNIX_ADDR=$MYSQL_UNIX_ADDR_DEFAULT ]
++    )
++AC_SUBST(MYSQL_UNIX_ADDR)
++
++AC_ARG_WITH(tcp-port,
++    [  --with-tcp-port=port-number
++                          Which port to use for MySQL services (default 3306)],
++    [ MYSQL_TCP_PORT=$withval ],
++    [ MYSQL_TCP_PORT=$MYSQL_TCP_PORT_DEFAULT ]
++    )
++AC_SUBST(MYSQL_TCP_PORT)
++# We might want to document the assigned port in the manual.
++AC_SUBST(MYSQL_TCP_PORT_DEFAULT)
++
++# Use this to set the place used for unix socket used to local communication.
++AC_ARG_WITH(mysqld-user,
++    [  --with-mysqld-user=username   
++                          What user the mysqld daemon shall be run as.],
++    [ MYSQLD_USER=$withval ],
++    [ MYSQLD_USER=mysql ]
++    )
++AC_SUBST(MYSQLD_USER)
++
++# If we should allow LOAD DATA LOCAL
++AC_MSG_CHECKING(If we should should enable LOAD DATA LOCAL by default)
++AC_ARG_ENABLE(local-infile,
++    [  --enable-local-infile   Enable LOAD DATA LOCAL INFILE (default: disabled)],
++    [ ENABLED_LOCAL_INFILE=$enableval ],
++    [ ENABLED_LOCAL_INFILE=no ]
++    )
++if test "$ENABLED_LOCAL_INFILE" = "yes"
++then
++  AC_MSG_RESULT([yes])
++  AC_DEFINE([ENABLED_LOCAL_INFILE], [1],
++            [If LOAD DATA LOCAL INFILE should be enabled by default])
++else
++  AC_MSG_RESULT([no])
++fi
++
++# If we should allow init-file, skip-grant-table and bootstrap options
++AC_MSG_CHECKING(If we should should enable init-file, skip-grant-table options and bootstrap)
++AC_ARG_ENABLE(grant-options,
++    [  --disable-grant-options Disables the use of --init-file, --skip-grant-tables and --bootstrap options],
++    [ mysql_grant_options_enabled=$enableval ],
++    [ mysql_grant_options_enabled=yes ]
++    )
++if test "$mysql_grant_options_enabled" = "yes"
++then
++  AC_MSG_RESULT([yes])
++else
++  AC_DEFINE([DISABLE_GRANT_OPTIONS], [1],
++            [Disables the use of --init-file, --skip-grant-tables and --bootstrap options])
++  AC_MSG_RESULT([no])
++fi
++
++MYSQL_SYS_LARGEFILE
++
++# Types that must be checked AFTER large file support is checked
++AC_TYPE_SIZE_T
++
++#--------------------------------------------------------------------
++# Check for system header files
++#--------------------------------------------------------------------
++
++AC_HEADER_DIRENT
++AC_HEADER_STDC
++AC_HEADER_SYS_WAIT
++AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \
++ memory.h pwd.h select.h \
++ stdlib.h stddef.h \
++ strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \
++ sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
++ unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \
++ sys/ioctl.h malloc.h sys/malloc.h sys/ipc.h sys/shm.h linux/config.h \
++ sys/prctl.h \
++ sys/resource.h sys/param.h)
++
++#--------------------------------------------------------------------
++# Check for system libraries. Adds the library to $LIBS
++# and defines HAVE_LIBM etc
++#--------------------------------------------------------------------
++
++AC_CHECK_LIB(m, floor, [], AC_CHECK_LIB(m, __infinity))
++
++AC_CHECK_LIB(nsl_r, gethostbyname_r, [],
++  AC_CHECK_LIB(nsl, gethostbyname_r))
++AC_CHECK_FUNC(gethostbyname_r)
++
++AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt))
++AC_CHECK_FUNC(yp_get_default_domain, ,
++  AC_CHECK_LIB(nsl, yp_get_default_domain))
++AC_CHECK_FUNC(p2open, , AC_CHECK_LIB(gen, p2open))
++# This may get things to compile even if bind-8 is installed
++AC_CHECK_FUNC(bind, , AC_CHECK_LIB(bind, bind))
++# Check if crypt() exists in libc or libcrypt, sets LIBS if needed
++AC_SEARCH_LIBS(crypt, crypt, AC_DEFINE(HAVE_CRYPT, 1, [crypt]))
++AC_SEARCH_LIBS(inet_aton, [socket nsl resolv])
++
++# For the sched_yield() function on Solaris
++AC_CHECK_FUNC(sched_yield, , AC_CHECK_LIB(posix4, sched_yield))
++
++MYSQL_CHECK_ZLIB_WITH_COMPRESS
++
++# For large pages support
++if test "$TARGET_LINUX" = "true"
++then
++  # For SHM_HUGETLB on Linux
++  AC_CHECK_DECLS(SHM_HUGETLB, 
++      AC_DEFINE([HAVE_LARGE_PAGES], [1], 
++                [Define if you have large pages support])
++      AC_DEFINE([HUGETLB_USE_PROC_MEMINFO], [1],
++                [Define if /proc/meminfo shows the huge page size (Linux only)])
++      , ,
++      [
++#include <sys/shm.h>
++      ]
++  )
++fi
++
++#--------------------------------------------------------------------
++# Check for TCP wrapper support
++#--------------------------------------------------------------------
++
++AC_ARG_WITH(libwrap,
++[  --with-libwrap[=DIR]      Compile in libwrap (tcp_wrappers) support],[
++  case "$with_libwrap" in
++  no) : ;;
++  yes|*)
++    _cppflags=${CPPFLAGS}
++    _ldflags=${LDFLAGS}
++
++    if test "$with_libwrap" != "yes"; then
++      CPPFLAGS="${CPPFLAGS} -I$with_libwrap/include"
++      LDFLAGS="${LDFLAGS} -L$with_libwrap/lib"
++    fi
++
++    _libs=${LIBS}
++    AC_CHECK_HEADER(tcpd.h,
++      LIBS="-lwrap $LIBS"
++      AC_MSG_CHECKING(for TCP wrappers library -lwrap)
++      AC_TRY_LINK([#include <tcpd.h>
++int allow_severity = 0;
++int deny_severity  = 0;
++
++struct request_info *req;
++],[hosts_access (req)],
++        AC_MSG_RESULT(yes)
++        AC_DEFINE([LIBWRAP], [1], [Define if you have -lwrap])
++        AC_DEFINE([HAVE_LIBWRAP], [1], [Define if have -lwrap])
++	if test "$with_libwrap" != "yes"; then
++	    WRAPLIBS="-L${with_libwrap}/lib"
++	fi
++	WRAPLIBS="${WRAPLIBS} -lwrap",
++        AC_MSG_RESULT(no)
++        CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}),
++      CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags})
++    LDFLAGS=${_ldflags} LIBS=${_libs}
++    ;;
++  esac
++])
++AC_SUBST(WRAPLIBS)
++
++if test "$TARGET_LINUX" = "true"; then
++  AC_MSG_CHECKING([for atomic operations])
++
++  AC_LANG_SAVE
++  AC_LANG_CPLUSPLUS
++
++  atom_ops=
++  AC_TRY_RUN([
++#include <asm/atomic.h>
++int main()
++{
++  atomic_t v;
++
++  atomic_set(&v, 23);
++  atomic_add(5, &v);
++  return atomic_read(&v) == 28 ? 0 : -1;
++}
++  ],
++  [AC_DEFINE([HAVE_ATOMIC_ADD], [1],
++             [atomic_add() from <asm/atomic.h> (Linux only)])
++   atom_ops="${atom_ops}atomic_add "],
++  )
++  AC_TRY_RUN([
++#include <asm/atomic.h>
++int main()
++{
++  atomic_t v;
++
++  atomic_set(&v, 23);
++  atomic_sub(5, &v);
++  return atomic_read(&v) == 18 ? 0 : -1;
++}
++  ],
++  [AC_DEFINE([HAVE_ATOMIC_SUB], [1],
++             [atomic_sub() from <asm/atomic.h> (Linux only)])
++   atom_ops="${atom_ops}atomic_sub "],
++  )
++
++  if test -z "$atom_ops"; then atom_ops="no"; fi
++  AC_MSG_RESULT($atom_ops)
++
++  AC_LANG_RESTORE
++
++  AC_ARG_WITH(pstack,
++    [  --with-pstack           Use the pstack backtrace library],
++    [ USE_PSTACK=$withval ],
++    [ USE_PSTACK=no ])
++  pstack_libs=
++  pstack_dirs=
++  if test "$USE_PSTACK" = yes -a "$TARGET_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386"
++  then
++    have_libiberty= have_libbfd=
++    my_save_LIBS="$LIBS"
++dnl I have no idea if this is a good test - can not find docs for libiberty  
++    AC_CHECK_LIB([iberty], [fdmatch],
++      [have_libiberty=yes
++       AC_CHECK_LIB([bfd], [bfd_openr], [have_libbfd=yes], , [-liberty])])
++    LIBS="$my_save_LIBS"
++
++    if test x"$have_libiberty" = xyes -a x"$have_libbfd" = xyes
++    then
++      pstack_dirs='$(top_srcdir)'/pstack
++      pstack_libs="../pstack/libpstack.a -lbfd -liberty"
++      # We must link staticly when using pstack
++      with_mysqld_ldflags="-all-static"
++      AC_SUBST([pstack_dirs])
++      AC_SUBST([pstack_libs])
++      AC_DEFINE([USE_PSTACK], [1], [the pstack backtrace library])
++dnl This check isn't needed, but might be nice to give some feedback....
++dnl    AC_CHECK_HEADER(libiberty.h,
++dnl      have_libiberty_h=yes,
++dnl      have_libiberty_h=no)
++    else
++      USE_PSTACK="no"
++    fi
++  else
++    USE_PSTACK="no"
++  fi
++fi
++AM_CONDITIONAL(COMPILE_PSTACK, test "$USE_PSTACK" = "yes")
++AC_MSG_CHECKING([if we should use pstack])
++AC_MSG_RESULT([$USE_PSTACK])
++
++# Check for gtty if termio.h doesn't exists
++if test "$ac_cv_header_termio_h" = "no" -a "$ac_cv_header_termios_h" = "no"
++then
++  AC_CHECK_FUNC(gtty, , AC_CHECK_LIB(compat, gtty))
++fi
++
++# We make a special variable for non-threaded version of LIBS to avoid
++# including thread libs into non-threaded version of MySQL client library.
++# Later in this script LIBS will be augmented with a threads library.
++NON_THREADED_LIBS="$LIBS"
++
++AC_MSG_CHECKING([for int8])
++case $SYSTEM_TYPE in
++  *netware)
++    AC_MSG_RESULT([no])
++    ;;
++  *)
++AC_TRY_RUN([
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++
++#ifdef HAVE_STDDEF_H
++#include <stddef.h>
++#endif
++
++#ifdef HAVE_SYS_TYPES_H
++#include <sys/types.h>
++#endif
++
++int main()
++{
++  int8 i;
++  return 0;
++}
++],
++[AC_DEFINE([HAVE_INT_8_16_32], [1],
++           [whether int8, int16 and int32 types exist])
++AC_MSG_RESULT([yes])],
++[AC_MSG_RESULT([no])]
++)
++    ;;
++esac
++
++#
++# Some system specific hacks
++#
++
++MAX_C_OPTIMIZE="-O3"
++MAX_CXX_OPTIMIZE="-O3"
++
++ndb_cxxflags_fix=
++case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc in
++# workaround for Sun Forte/x86 see BUG#4681
++  *solaris*-i?86-no)
++    CFLAGS="$CFLAGS -DBIG_TABLES"
++    CXXFLAGS="$CXXFLAGS -DBIG_TABLES"
++    ;;
++  *) ;;
++esac
++case $SYSTEM_TYPE-$ac_cv_prog_gcc in
++# workaround for Sun Forte compile problem for ndb
++  *solaris*-no)
++    ndb_cxxflags_fix="$ndb_cxxflags_fix -instances=static"
++    ;;
++  *) ;;
++esac
++
++
++case $SYSTEM_TYPE in
++  *solaris2.7*)
++    # Solaris 2.7 has a broken /usr/include/widec.h
++    # Make a fixed copy in ./include
++    AC_MSG_WARN([Fixing broken include files for $SYSTEM_TYPE])
++    echo "  - Creating local copy of widec.h"
++    if test ! -d include
++    then
++      mkdir ./include
++    fi
++    builddir=`pwd`
++    sed -e "s|^#if[ 	]*!defined(lint) && !defined(__lint)|#if !defined\(lint\) \&\& !defined\(__lint\) \&\& !defined\(getwc\)|" < /usr/include/widec.h > include/widec.h
++    CFLAGS="$CFLAGS -DHAVE_CURSES_H -I$builddir/include -DHAVE_RWLOCK_T"
++    CXXFLAGS="$CXXFLAGS -DHAVE_CURSES_H -I$builddir/include -DHAVE_RWLOCK_T"
++    ;;
++  *solaris2.8*)
++    # Solaris 2.8 has a broken /usr/include/widec.h
++    # Make a fixed copy in ./include
++    AC_MSG_WARN([Fixing broken include files for $SYSTEM_TYPE])
++    echo "  - Creating local copy of widec.h"
++    if test ! -d include
++    then
++      mkdir ./include
++    fi
++    builddir=`pwd`
++    sed -e "s|^#if[ 	]*!defined(__lint)|#if !defined\(__lint\) \&\& !defined\(getwc\)|" < /usr/include/widec.h > include/widec.h
++    CFLAGS="$CFLAGS -DHAVE_CURSES_H -I$builddir/include -DHAVE_RWLOCK_T"
++    CXXFLAGS="$CXXFLAGS -DHAVE_CURSES_H -I$builddir/include -DHAVE_RWLOCK_T"
++    ;;
++  *solaris2.5.1*)
++    AC_MSG_WARN([Enabling getpass() workaround for Solaris 2.5.1])
++    CFLAGS="$CFLAGS -DHAVE_BROKEN_GETPASS -DSOLARIS -DHAVE_RWLOCK_T";
++    CXXFLAGS="$CXXFLAGS -DHAVE_RWLOCK_T -DSOLARIS"
++    ;;
++  *solaris*)
++    CFLAGS="$CFLAGS -DHAVE_RWLOCK_T"
++    CXXFLAGS="$CXXFLAGS -DHAVE_RWLOCK_T"
++    ;;
++  *SunOS*)
++    AC_MSG_WARN([Enabling getpass() workaround for SunOS])
++    CFLAGS="$CFLAGS -DHAVE_BROKEN_GETPASS -DSOLARIS";
++    ;;
++  *hpux10.20*)
++    AC_MSG_WARN([Enabling workarounds for hpux 10.20])
++    CFLAGS="$CFLAGS -DHAVE_BROKEN_SNPRINTF -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX10 -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
++    CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_SNPRINTF -D_INCLUDE_LONGLONG -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX10 -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
++    if test "$with_named_thread" = "no"
++    then 
++      AC_MSG_WARN([Using --with-named-thread=-lpthread])
++      with_named_thread="-lcma"
++    fi
++    ;;
++  *hpux11.*)
++    AC_MSG_WARN([Enabling workarounds for hpux 11])
++    CFLAGS="$CFLAGS -DHPUX11  -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
++    CXXFLAGS="$CXXFLAGS -DHPUX11  -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
++    if test "$with_named_thread" = "no"
++    then 
++      AC_MSG_WARN([Using --with-named-thread=-lpthread])
++      with_named_thread="-lpthread"
++    fi
++    # Fixes for HPUX 11.0 compiler
++    if test "$ac_cv_prog_gcc" = "no"
++    then
++      CFLAGS="$CFLAGS -DHAVE_BROKEN_INLINE"
++# set working flags first in line, letting override it (i. e. for debug):
++      CXXFLAGS="+O2 $CXXFLAGS"
++      MAX_C_OPTIMIZE=""
++      MAX_CXX_OPTIMIZE=""
++      ndb_cxxflags_fix="$ndb_cxxflags_fix -Aa"
++    fi
++    ;;
++  *rhapsody*)
++    if test "$ac_cv_prog_gcc" = "yes"
++    then
++      CPPFLAGS="$CPPFLAGS -traditional-cpp "
++      CFLAGS="-DHAVE_CTHREADS_WRAPPER -DDO_NOT_REMOVE_THREAD_WRAPPERS"
++      CXXFLAGS="-DHAVE_CTHREADS_WRAPPER"
++      if test $with_named_curses = "no"
++      then
++	with_named_curses=""
++      fi
++    fi
++    ;;
++  *darwin5*)
++    if test "$ac_cv_prog_gcc" = "yes"
++    then
++      FLAGS="-traditional-cpp -DHAVE_DARWIN5_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH"
++      CFLAGS="$CFLAGS $FLAGS"
++      CXXFLAGS="$CXXFLAGS $FLAGS"
++      MAX_C_OPTIMIZE="-O"
++      with_named_curses=""
++    fi
++    ;;
++  *darwin6*)
++    if test "$ac_cv_prog_gcc" = "yes"
++    then
++      FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DDONT_DECLARE_CXA_PURE_VIRTUAL "
++      CFLAGS="$CFLAGS $FLAGS"
++      CXXFLAGS="$CXXFLAGS $FLAGS"
++      MAX_C_OPTIMIZE="-O"
++    fi
++    ;;
++  *darwin*)
++    if test "$ac_cv_prog_gcc" = "yes"
++    then
++      FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT"
++      CFLAGS="$CFLAGS $FLAGS"
++      CXXFLAGS="$CXXFLAGS $FLAGS"
++      MAX_C_OPTIMIZE="-O"
++    fi
++    ;;
++  *freebsd*|*dragonfly*)
++    AC_MSG_WARN([Adding fix for interrupted reads])
++    OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
++    if test "$OSVERSION" -gt "480100" && \
++       test "$OSVERSION" -lt "500000" || \
++       test "$OSVERSION" -gt "500109"
++    then
++       CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000"
++    else
++       CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
++       CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
++    fi
++    ;;
++  *netbsd*)
++    AC_MSG_WARN([Adding flag -Dunix])
++    CFLAGS="$CFLAGS -Dunix"
++    CXXFLAGS="$CXXFLAGS -Dunix"
++    OVERRIDE_MT_LD_ADD="\$(top_srcdir)/mit-pthreads/obj/libpthread.a"
++    ;;
++  *bsdi*)
++    AC_MSG_WARN([Adding fix for BSDI])
++    CFLAGS="$CFLAGS -D__BSD__ -DHAVE_BROKEN_REALPATH"
++    AC_DEFINE_UNQUOTED([SOCKOPT_OPTLEN_TYPE], [size_t],
++                       [Last argument to get/setsockopt])
++    ;;
++   *sgi-irix6*)
++    if test "$with_named_thread" = "no"
++    then 
++      AC_MSG_WARN([Using --with-named-thread=-lpthread])
++      with_named_thread="-lpthread"
++    fi
++    CXXFLAGS="$CXXFLAGS -D_BOOL"
++    ;;
++    *aix4.3*)
++      AC_MSG_WARN([Adding defines for AIX])
++      CFLAGS="$CFLAGS -Wa,-many -DUNDEF_HAVE_INITGROUPS -DSIGNALS_DONT_BREAK_READ"
++      CXXFLAGS="$CXXFLAGS -Wa,-many -DUNDEF_HAVE_INITGROUPS -DSIGNALS_DONT_BREAK_READ"
++    ;;
++dnl Is this the right match for DEC OSF on alpha?
++    *dec-osf*)
++      if test "$ac_cv_prog_gcc" = "yes" && test "$host_cpu" = "alpha"
++      then
++	  AC_MSG_WARN([Adding defines for DEC OSF on alpha])
++	  CFLAGS="$CFLAGS -mieee"
++	  CXXFLAGS="$CXXFLAGS -mieee"
++      fi
++      AC_MSG_WARN([Adding defines for OSF1])
++      # gethostbyname_r is deprecated and doesn't work ok on OSF1
++      CFLAGS="$CFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R -DSNPRINTF_RETURN_TRUNC"
++      CXXFLAGS="$CXXFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R -DSNPRINTF_RETURN_TRUNC"
++      # fix to handle include of <stdint.h> correctly on OSF1 with cxx compiler
++      CXXFLAGS="$CXXFLAGS -I/usr/include/cxx -I/usr/include/cxx_cname -I/usr/include -I/usr/include.dtk"
++    ;;
++  *netware*)
++    # No need for curses library so set it to null
++    with_named_curses=""
++
++    # No thread library - in LibC
++    with_named_thread=""
++    
++    #
++    # Edit Makefile.in files.
++    #
++    echo -n "configuring Makefile.in files for NetWare... "
++    for file in sql/Makefile.in libmysql/Makefile.in libmysql_r/Makefile.in extra/Makefile.in strings/Makefile.in client/Makefile.in
++    do
++    # echo "#### $file ####"
++      filedir="`dirname $file`"
++      filebase="`basename $file`"
++      filesed=$filedir/$filebase.sed
++      #
++      # Backup and always use original file
++      #
++      if test -f $file.bk
++      then
++        cp -fp $file.bk $file
++      else
++        cp -fp $file $file.bk
++      fi
++      case $file in
++        sql/Makefile.in)
++          # Use gen_lex_hash.linux instead of gen_lex_hash
++          # Add library dependencies to mysqld_DEPENDENCIES
++          lib_DEPENDENCIES="\$(bdb_libs_with_path) \$(innodb_libs) \$(ndbcluster_libs) \$(pstack_libs) \$(innodb_system_libs) \$(openssl_libs) \$(yassl_libs)"
++          cat > $filesed << EOF
++s,\(^.*\$(MAKE) gen_lex_hash\)\$(EXEEXT),#\1,
++s,\(\./gen_lex_hash\)\$(EXEEXT),\1.linux,
++s%\(mysqld_DEPENDENCIES = \) %\1$lib_DEPENDENCIES %
++EOF
++          ;;
++        extra/Makefile.in)
++          cat > $filesed << EOF
++s,\(extra/comp_err\)\$(EXEEXT),\1.linux,
++EOF
++          ;;
++        libmysql/Makefile.in)
++          cat > $filesed << EOF
++s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
++s,\(: conf_to_src\),\1.linux,
++s,libyassl.la,.libs/libyassl.a,
++s,libtaocrypt.la,.libs/libtaocrypt.a,
++EOF
++          ;;
++        libmysql_r/Makefile.in)
++          cat > $filesed << EOF
++s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
++s,\(: conf_to_src\),\1.linux,
++s,libyassl.la,.libs/libyassl.a,
++s,libtaocrypt.la,.libs/libtaocrypt.a,
++EOF
++          ;;
++        strings/Makefile.in)
++          cat > $filesed << EOF
++s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
++s,\(: conf_to_src\),\1.linux,
++EOF
++          ;;
++        client/Makefile.in)
++          #
++          cat > $filesed << EOF
++s,libmysqlclient.la,.libs/libmysqlclient.a,
++EOF
++          ;;
++      esac
++      if `sed -f $filesed $file > $file.nw`;\
++      then
++        mv -f $file.nw $file
++        rm -f $filesed
++      else
++        exit 1
++      fi
++      # wait for file system changes to complete
++      sleep 1
++    done
++    echo "done"
++
++    #
++    # Make sure the following files are writable.
++    #
++    # When the files are retrieved from some source code control systems they are read-only.
++    #
++    echo -n "making sure specific build files are writable... "
++    for file in \
++        Docs/manual.chm \
++        Docs/mysql.info \
++        Docs/INSTALL-BINARY \
++        INSTALL-SOURCE \
++        COPYING
++    do
++      if test -e $file; then
++        chmod +w $file
++      fi
++    done
++    echo "done"
++
++    ;;
++esac
++
++
++#---START: Used in for client configure
++# Check if we threads are in libc or if we should use
++# -lpthread, -lpthreads or mit-pthreads
++# We have to check libc last because else it fails on Solaris 2.6
++
++with_posix_threads="no"
++# Search thread lib on Linux
++if test "$with_named_thread" = "no"
++then
++    AC_MSG_CHECKING("Linux threads")
++    if test "$TARGET_LINUX" = "true"
++    then
++        AC_MSG_RESULT("starting")
++        # use getconf to check glibc contents
++        AC_MSG_CHECKING("getconf GNU_LIBPTHREAD_VERSION")
++        case `getconf GNU_LIBPTHREAD_VERSION | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` in
++        NPTL* )
++                AC_MSG_RESULT("NPTL")
++                AC_DEFINE([HAVE_NPTL], [1], [NPTL threads implementation])
++                with_named_thread="-lpthread"
++                ;;
++        LINUXTHREADS* )
++                AC_MSG_RESULT("Linuxthreads")
++                AC_DEFINE([HAVE_LINUXTHREADS], [1], 
++                      [Whether we are using Xavier Leroy's LinuxThreads])
++                with_named_thread="-lpthread"
++                ;;
++        * )
++                AC_MSG_RESULT("unknown")
++                ;;
++        esac
++        if test "$with_named_thread" = "no"
++        then
++          # old method, check headers
++          # Look for LinuxThreads.
++          AC_MSG_CHECKING("LinuxThreads in header file comment")
++          res=`grep Linuxthreads /usr/include/pthread.h 2>/dev/null | wc -l`
++          if test "$res" -gt 0
++          then
++            AC_MSG_RESULT("Found")
++            AC_DEFINE([HAVE_LINUXTHREADS], [1],
++                  [Whether we are using Xavier Leroy's LinuxThreads])
++            # Linux 2.0 sanity check
++            AC_TRY_COMPILE([#include <sched.h>], [int a = sched_get_priority_min(1);], ,
++                  AC_MSG_ERROR([Syntax error in sched.h. Change _P to __P in the /usr/include/sched.h file. See the Installation chapter in the Reference Manual]))
++            # RedHat 5.0 does not work with dynamic linking of this. -static also
++            # gives a speed increase in linux so it does not hurt on other systems.
++            with_named_thread="-lpthread"
++          else
++            AC_MSG_RESULT("Not found")
++            # If this is a linux machine we should barf
++            AC_MSG_ERROR([This is a Linux system without a working getconf, 
++and Linuxthreads was not found. Please install it (or a new glibc) and try again.  
++See the Installation chapter in the Reference Manual for more information.])
++          fi
++        else
++            AC_MSG_RESULT("no need to check headers")
++        fi
++        
++        AC_MSG_CHECKING("for pthread_create in -lpthread");
++        ac_save_LIBS="$LIBS"
++        LIBS="$LIBS -lpthread"
++        AC_TRY_LINK( [#include <pthread.h>],
++              [ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
++              AC_MSG_RESULT("yes"),
++              [ AC_MSG_RESULT("no")
++                AC_MSG_ERROR([
++This is a Linux system claiming to support threads, either Linuxthreads or NPTL, but linking a test program failed.  
++Please install one of these (or a new glibc) and try again.  
++See the Installation chapter in the Reference Manual for more information.]) ]
++              )
++        LIBS="$ac_save_LIBS"
++    else
++        AC_MSG_RESULT("no")
++    fi  # "$TARGET_LINUX" 
++fi  # "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
++
++
++# Hack for DEC-UNIX (OSF1 -> Tru64)
++if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
++then
++    AC_MSG_CHECKING("DEC threads post OSF/1 3.2")
++    if test -f /usr/shlib/libpthread.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a
++    then
++      with_named_thread="-lpthread -lmach -lexc"
++      CFLAGS="$CFLAGS -D_REENTRANT"
++      CXXFLAGS="$CXXFLAGS -D_REENTRANT"
++      AC_DEFINE(HAVE_DEC_THREADS, [1], [Whether we are using DEC threads])
++      AC_MSG_RESULT("yes")
++    else
++      AC_MSG_RESULT("no")
++    fi  # DEC threads
++fi  # "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
++
++
++dnl This is needed because -lsocket has to come after the thread
++dnl library on SCO.
++AC_DEFUN([MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK], [
++  LIBS=`echo " $LIBS " | sed -e 's/ -lsocket / /g'`
++])
++# Hack for SCO UNIX
++if test "$with_named_thread" = "no"
++then
++  AC_MSG_CHECKING("SCO threads")
++  if expr "$SYSTEM_TYPE" : ".*sco.*" > /dev/null
++  then
++    if test -f /usr/lib/libgthreads.a -o -f /usr/lib/libgthreads.so
++    then
++      MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
++      with_named_thread="-lgthreads -lsocket -lgthreads"
++      # sched.h conflicts with fsu-threads
++      touch ./include/sched.h
++      touch ./include/semaphore.h
++
++      # We must have gcc
++      if expr "$CC" : ".*gcc.*"
++      then
++	AC_MSG_RESULT("yes")
++      else
++	AC_MSG_ERROR([On SCO UNIX MySQL must be compiled with gcc. See the Installation chapter in the Reference Manual.]);
++      fi
++      AC_MSG_RESULT("yes")
++    elif test -f /usr/local/lib/libpthread.a -o -f /usr/local/lib/libpthread.so
++    then
++      MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
++      with_named_thread="-lpthread -lsocket"
++      # sched.h conflicts with fsu-threads
++      # touch ./include/sched.h
++
++      AC_MSG_CHECKING("for gcc")
++      # We must have gcc
++      if expr "$CC" : ".*gcc.*"
++      then
++	AC_MSG_RESULT("yes")
++      else
++	AC_MSG_ERROR([On SCO UNIX MySQL must be compiled with gcc. See the Installation chapter in the Reference Manual.]);
++      fi
++      AC_MSG_RESULT("yes")
++    # Hack for SCO UnixWare 7.1.x
++    #
++    elif test "$with_named_thread" = "no"
++    then
++      AC_MSG_RESULT("no")
++      AC_MSG_CHECKING("SCO UnixWare 7.1.x native threads")
++      if expr "$SYSTEM_TYPE" : ".*sco.*" > /dev/null
++      then
++        if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
++        then
++	  MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
++          if expr "$CC" : ".*gcc.*"
++          then
++            with_named_thread="-pthread -lsocket -lnsl"
++          else
++            with_named_thread="-Kthread -lsocket -lnsl"
++          fi
++          if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
++          then
++            AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1])
++          fi
++          AC_MSG_RESULT("yes")
++          # We must have cc
++          AC_MSG_CHECKING("for gcc")
++          if expr "$CC" : ".*gcc.*"
++          then
++	    CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
++	    CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
++          else
++	    CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
++	    CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
++          fi
++        else
++          AC_MSG_ERROR([configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual.]) 
++        fi
++      else
++        AC_MSG_RESULT("no")
++      fi
++    else
++      AC_MSG_ERROR([On SCO UNIX MySQL requires that the FSUThreads package is installed. See the Installation chapter in the Reference Manual.])
++    fi
++  else
++    AC_MSG_RESULT("no")
++  fi
++fi
++
++#
++# Check for SCO threading libraries
++#
++if test "$with_named_thread" = "no"
++then
++  AC_MSG_CHECKING([SCO OpenServer 6, UnixWare 7 or OpenUNIX 8 native threads])
++  if expr "$SYSTEM_TYPE" : ".*UnixWare.*" > /dev/null || \
++     expr "$SYSTEM_TYPE" : ".*SCO_SV6.*" > /dev/null || \
++     expr "$SYSTEM_TYPE" : ".*OpenUNIX.*" > /dev/null
++  then
++    if test -f /usr/lib/libthread.so -o -f /usr/lib/libthreadT.so
++    then
++      MYSQL_REMOVE_SOCKET_FROM_LIBS_HACK
++      if expr "$CC" : ".*gcc.*" > /dev/null
++      then
++        with_named_thread="-pthread -lsocket -lnsl"
++	CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
++	CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
++      else
++        with_named_thread="-Kthread -lsocket -lnsl"
++	CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
++	CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
++      fi
++      if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
++      then
++        AC_DEFINE(HAVE_UNIXWARE7_THREADS, [1], [Have UnixWare 7 (or similar) almost-POSIX threading library])
++      fi
++      AC_MSG_RESULT(yes)
++    else
++      AC_MSG_ERROR([configure: error: Can't find thread library on SCO/Caldera system. See the Installation chapter in the Reference Manual.]) 
++    fi
++  else
++    AC_MSG_RESULT(no)
++  fi
++fi
++
++# Hack for Siemens UNIX
++if test "$with_named_thread" = "no"
++then
++  AC_MSG_CHECKING("Siemens threads")
++  if test -f /usr/lib/libxnet.so -a "$SYSTEM_TYPE" = "sni-sysv4"
++  then
++    LIBS="-lxnet $LIBS"
++    NON_THREADED_LIBS="-lxnet $NON_THREADED_LIBS"
++    with_named_thread="-Kthread $LDFLAGS -lxnet"
++    LD_FLAGS=""
++    CFLAGS="-Kthread $CFLAGS"
++    CXXFLAGS="-Kthread $CXXFLAGS"
++    AC_MSG_RESULT("yes")
++  else
++    AC_MSG_RESULT("no")
++  fi
++fi
++
++# Use library named -lpthread
++if test "$with_named_thread" = "no" -a "$with_pthread" = "yes"
++then
++    with_named_thread="-lpthread"
++fi
++
++#---END:
++
++# Hack for Solaris >= 2.5
++# We want both the new and the old interface
++ 
++if test "$with_named_thread" = "no"
++then
++  AC_MSG_CHECKING("Solaris threads")
++  if test -f /usr/lib/libpthread.so -a -f /usr/lib/libthread.so
++  then
++    with_named_thread="-lpthread -lthread"
++    AC_MSG_RESULT("yes")
++  else
++    AC_MSG_RESULT("no")
++  fi
++fi
++
++# Should we use named pthread library ?
++AC_MSG_CHECKING("named thread libs:")
++if test "$with_named_thread" != "no"
++then
++  LIBS="$with_named_thread $LIBS $with_named_thread"
++  with_posix_threads="yes"
++  AC_MSG_RESULT("$with_named_thread")
++else
++  AC_MSG_RESULT("no")
++  # pthread_create is in standard libraries (As in BSDI 3.0)
++  AC_MSG_CHECKING("for pthread_create in -libc");
++  AC_TRY_LINK(
++  [#include <pthread.h>],
++  [ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
++  with_posix_threads=yes, with_posix_threads=no)
++  AC_MSG_RESULT("$with_posix_threads")
++  if test "$with_posix_threads" = "no"
++  then
++    AC_MSG_CHECKING("for pthread_create in -lpthread");
++    ac_save_LIBS="$LIBS"
++    LIBS="$LIBS -lpthread"
++    AC_TRY_LINK(
++    [#include <pthread.h>],
++    [ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
++    with_posix_threads=yes, with_posix_threads=no)
++    AC_MSG_RESULT("$with_posix_threads")
++    if test "$with_posix_threads" = "no"
++    then
++      LIBS=" $ac_save_LIBS -lpthreads"
++      AC_MSG_CHECKING("for pthread_create in -lpthreads");
++      AC_TRY_LINK(
++      [#include <pthread.h>],
++      [ pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
++      with_posix_threads=yes, with_posix_threads=no)
++      AC_MSG_RESULT("$with_posix_threads")
++      if test "$with_posix_threads" = "no"
++      then
++        # This is for FreeBSD
++        LIBS="$ac_save_LIBS -pthread"
++        AC_MSG_CHECKING("for pthread_create in -pthread");
++        AC_TRY_LINK(
++        [#include <pthread.h>],
++        [ pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
++        with_posix_threads=yes, with_posix_threads=no)
++        AC_MSG_RESULT("$with_posix_threads")
++      fi
++    fi
++  fi
++fi
++
++#---START: Used in for client configure
++# Must be checked after, because strtok_r may be in -lpthread
++# On AIX strtok_r is in libc_r
++
++my_save_LIBS="$LIBS"
++AC_CHECK_LIB(pthread,strtok_r)
++LIBS="$my_save_LIBS"
++if test "$ac_cv_lib_pthread_strtok_r" = "no"
++then
++  AC_CHECK_LIB(c_r,strtok_r)
++  case "$with_osf32_threads---$target_os" in
++    # Don't keep -lc_r in LIBS; -pthread handles it magically
++    yes---* | *---freebsd* | *---hpux*) LIBS="$my_save_LIBS" ;;
++
++  esac
++  AC_CHECK_FUNCS(strtok_r pthread_init)
++else
++  AC_CHECK_FUNCS(strtok_r)
++fi
++#---END:
++
++# dlopen, dlerror
++case "$with_mysqld_ldflags " in
++
++  *"-all-static "*)
++    # No need to check for dlopen when mysqld is linked with
++    # -all-static as it won't be able to load any functions.
++    # NOTE! It would be better if it was possible to test if dlopen
++    # can be used, but a good way to test it couldn't be found
++
++    ;;
++
++  *)
++    # Check for dlopen, needed for user definable functions
++    # This must be checked after threads on AIX
++    # We only need this for mysqld, not for the clients.
++
++    my_save_LIBS="$LIBS"
++    LIBS=""
++    AC_CHECK_LIB(dl,dlopen)
++    LIBDL=$LIBS
++    LIBS="$my_save_LIBS"
++    AC_SUBST(LIBDL)
++
++    my_save_LIBS="$LIBS"
++    LIBS="$LIBS $LIBDL"
++    AC_CHECK_FUNCS(dlopen dlerror)
++    LIBS="$my_save_LIBS"
++
++    ;;
++esac
++
++
++# System characteristics
++case $SYSTEM_TYPE in
++  *netware*) ;;
++  *)
++AC_SYS_RESTARTABLE_SYSCALLS
++    ;;
++esac
++
++# Build optimized or debug version ?
++# First check for gcc and g++
++if test "$ac_cv_prog_gcc" = "yes"
++then
++  DEBUG_CFLAGS="-g"
++  DEBUG_OPTIMIZE_CC="-O"
++  OPTIMIZE_CFLAGS="$MAX_C_OPTIMIZE"
++else
++  DEBUG_CFLAGS="-g"
++  DEBUG_OPTIMIZE_CC=""
++  OPTIMIZE_CFLAGS="-O"
++fi
++if test "$ac_cv_prog_cxx_g" = "yes"
++then
++  DEBUG_CXXFLAGS="-g"
++  DEBUG_OPTIMIZE_CXX="-O"
++  OPTIMIZE_CXXFLAGS="$MAX_CXX_OPTIMIZE"
++else
++  DEBUG_CXXFLAGS="-g"
++  DEBUG_OPTIMIZE_CXX=""
++  OPTIMIZE_CXXFLAGS="-O"
++fi
++
++if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then
++  DEBUG_CFLAGS="-g -DDEBUG -sym internal,codeview4"
++  DEBUG_CXXFLAGS="-g -DDEBUG -sym internal,codeview4"
++  DEBUG_OPTIMIZE_CC="-DDEBUG"
++  DEBUG_OPTIMIZE_CXX="-DDEBUG"
++  OPTIMIZE_CFLAGS="-O3 -DNDEBUG"
++  OPTIMIZE_CXXFLAGS="-O3 -DNDEBUG"
++fi
++
++# If the user specified CFLAGS, we won't add any optimizations
++if test -n "$SAVE_CFLAGS"
++then
++  OPTIMIZE_CFLAGS=""
++  DEBUG_OPTIMIZE_CC=""
++fi
++# Ditto for CXXFLAGS
++if test -n "$SAVE_CXXFLAGS"
++then
++  OPTIMIZE_CXXFLAGS=""
++  DEBUG_OPTIMIZE_CXX=""
++fi
++
++AC_ARG_WITH(debug,
++    [  --without-debug         Build a production version without debugging code],
++    [with_debug=$withval],
++    [with_debug=no])
++if test "$with_debug" = "yes"
++then
++  # Medium debug.
++  CFLAGS="$DEBUG_CFLAGS $DEBUG_OPTIMIZE_CC -DDBUG_ON -DSAFE_MUTEX $CFLAGS"
++  CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DDBUG_ON -DSAFE_MUTEX $CXXFLAGS"
++elif test "$with_debug" = "full"
++then
++  # Full debug. Very slow in some cases
++  CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS"
++  CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS"
++else
++  # Optimized version. No debug
++  CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS"
++  CXXFLAGS="$OPTIMIZE_CXXFLAGS -DDBUG_OFF $CXXFLAGS"
++fi
++
++# Force static compilation to avoid linking problems/get more speed
++AC_ARG_WITH(mysqld-ldflags,
++    [  --with-mysqld-ldflags   Extra linking arguments for mysqld],
++    [MYSQLD_EXTRA_LDFLAGS=$withval],
++    [MYSQLD_EXTRA_LDFLAGS=])
++AC_SUBST(MYSQLD_EXTRA_LDFLAGS)
++
++AC_ARG_WITH(client-ldflags,
++    [  --with-client-ldflags   Extra linking arguments for clients],
++    [CLIENT_EXTRA_LDFLAGS=$withval],
++    [CLIENT_EXTRA_LDFLAGS=])
++AC_SUBST(CLIENT_EXTRA_LDFLAGS)
++
++AC_ARG_WITH(mysqld-libs,
++    [  --with-mysqld-libs   Extra libraries to link with for mysqld],
++    [MYSQLD_EXTRA_LIBS=$withval],
++    [MYSQLD_EXTRA_LIBS=])
++AC_SUBST(MYSQLD_EXTRA_LIBS)
++
++AC_ARG_WITH(lib-ccflags,
++    [  --with-lib-ccflags      Extra CC options for libraries],
++    [LIB_EXTRA_CCFLAGS=$withval],
++    [LIB_EXTRA_CCFLAGS=])
++AC_SUBST(LIB_EXTRA_CCFLAGS)
++
++# Avoid stupid bug on some OS 
++AC_ARG_WITH(low-memory,
++    [  --with-low-memory       Try to use less memory to compile to avoid 
++                          memory limitations.],
++    [with_lowmem=$withval],
++    [with_lowmem=no])
++if test "$with_lowmem" = "yes"
++then
++  if test "$ac_cv_prog_gcc" = "yes" 
++  then 
++    LM_CFLAGS="-fno-inline"
++  else
++    LM_CFLAGS="-O0"
++  fi
++else
++  LM_CFLAGS=""
++fi
++AC_SUBST(LM_CFLAGS)
++
++AC_ARG_WITH(comment,
++    [  --with-comment          Comment about compilation environment.],
++    [with_comment=$withval],
++    [with_comment=no])
++if test "$with_comment" != "no"
++then
++  COMPILATION_COMMENT=$with_comment
++else
++  COMPILATION_COMMENT="Source distribution"
++fi
++AC_SUBST(COMPILATION_COMMENT)
++
++AC_MSG_CHECKING("need of special linking flags")
++if test "$TARGET_LINUX" = "true" -a "$ac_cv_prog_gcc" = "yes" -a "$all_is_static" != "yes"
++then
++  LDFLAGS="$LDFLAGS -rdynamic"
++  AC_MSG_RESULT("-rdynamic")
++else
++  AC_MSG_RESULT("none")
++fi
++
++dnl Checks for typedefs, structures, and compiler characteristics.
++AC_C_CONST
++AC_C_INLINE
++AC_TYPE_OFF_T
++AC_STRUCT_ST_RDEV
++AC_HEADER_TIME
++AC_STRUCT_TM
++MYSQL_NEEDS_MYSYS_NEW
++# AC_CHECK_SIZEOF return 0 when it does not find the size of a
++# type. We want a error instead.
++AC_CHECK_SIZEOF(char, 1)
++if test "$ac_cv_sizeof_char" -eq 0
++then
++  AC_MSG_ERROR([No size for char type.
++A likely cause for this could be that there isn't any
++static libraries installed. You can verify this by checking if you have libm.a
++in /lib, /usr/lib or some other standard place.  If this is the problem,
++install the static libraries and try again.  If this isn't the problem,
++examine config.log for possible errors.  If you want to report this, use
++'scripts/mysqlbug' and include at least the last 20 rows from config.log!])
++fi
++AC_CHECK_SIZEOF(char*, 4)
++AC_CHECK_SIZEOF(short, 2)
++AC_CHECK_SIZEOF(int, 4)
++if test "$ac_cv_sizeof_int" -eq 0
++then
++  AC_MSG_ERROR("No size for int type.")
++fi
++AC_CHECK_SIZEOF(long, 4)
++if test "$ac_cv_sizeof_long" -eq 0
++then
++  AC_MSG_ERROR("No size for long type.")
++fi
++AC_CHECK_SIZEOF(long long, 8)
++if test "$ac_cv_sizeof_long_long" -eq 0
++then
++  AC_MSG_ERROR("MySQL needs a long long type.")
++fi
++# off_t is not a builtin type
++MYSQL_CHECK_SIZEOF(off_t, 4)
++if test "$ac_cv_sizeof_off_t" -eq 0
++then
++  AC_MSG_ERROR("MySQL needs a off_t type.")
++fi
++
++dnl
++dnl check if time_t is unsigned
++dnl
++
++MYSQL_CHECK_TIME_T
++
++
++# do we need #pragma interface/#pragma implementation ?
++# yes if it's gcc 2.x, and not icc pretending to be gcc, and not cygwin
++AC_MSG_CHECKING(the need for @%:@pragma interface/implementation)
++# instead of trying to match SYSTEM_TYPE and CC_VERSION (that doesn't
++# follow any standard), we'll use well-defined preprocessor macros:
++AC_TRY_CPP([
++#if !defined(__CYGWIN__) && !defined(__INTEL_COMPILER) && defined(__GNUC__) && (__GNUC__ < 3)
++#error USE_PRAGMA_IMPLEMENTATION
++#endif
++],AC_MSG_RESULT(no) ,AC_MSG_RESULT(yes) ; CXXFLAGS="$CXXFLAGS -DUSE_PRAGMA_IMPLEMENTATION")
++
++# This always gives a warning. Ignore it unless you are cross compiling
++AC_C_BIGENDIAN
++#---START: Used in for client configure
++# Check base type of last arg to accept
++MYSQL_TYPE_ACCEPT
++#---END:
++# Figure out what type of struct rlimit to use with setrlimit
++MYSQL_TYPE_STRUCT_RLIMIT
++# Find where the stack goes
++MYSQL_STACK_DIRECTION
++# We want to skip alloca on irix unconditionally. It may work on some version..
++MYSQL_FUNC_ALLOCA
++# Do struct timespec have members tv_sec or ts_sec
++MYSQL_TIMESPEC_TS
++# Do we have the tzname variable
++MYSQL_TZNAME
++# Do the system files define ulong
++MYSQL_CHECK_ULONG
++# Do the system files define uchar
++MYSQL_CHECK_UCHAR
++# Do the system files define uint
++MYSQL_CHECK_UINT
++# Check for fp_except in ieeefp.h
++MYSQL_CHECK_FP_EXCEPT
++# Check for IN_ADDR_T
++MYSQL_CHECK_IN_ADDR_T
++# Do the c++ compiler have a bool type
++MYSQL_CXX_BOOL
++# Check some common bugs with gcc 2.8.# on sparc
++if ! ( expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null ); then
++MYSQL_CHECK_LONGLONG_TO_FLOAT
++if test "$ac_cv_conv_longlong_to_float" != "yes"
++then
++  AC_MSG_ERROR([Your compiler cannot convert a longlong value to a float!
++If you are using gcc 2.8.# you should upgrade to egcs 1.0.3 or newer and try
++again]);
++fi
++fi
++AC_CHECK_TYPES([sigset_t, off_t], [], [], [#include <sys/types.h>])
++AC_CHECK_TYPES([size_t], [], [], [#include <stdio.h>])
++AC_CHECK_TYPES([u_int32_t])
++
++MYSQL_PTHREAD_YIELD
++
++######################################################################
++# For readline/libedit (We simply move the mimimum amount of stuff from
++# the readline/libedit configure.in here)
++
++dnl Checks for header files.
++AC_CHECK_HEADERS(malloc.h sys/cdefs.h)
++
++dnl Checks for library functions.
++AC_FUNC_ALLOCA
++AC_PROG_GCC_TRADITIONAL
++AC_TYPE_SIGNAL
++AC_CHECK_FUNCS(re_comp regcomp strdup)
++
++dnl Sun compilers have their own vis.h that is about something
++dnl totally different. So, not to change the libedit source, we
++dnl do some additional checks before we define HAVE_VIS_H.
++AC_CHECK_HEADER(vis.h,
++  [AC_CHECK_FUNC(strvis,
++    [AC_DEFINE([HAVE_VIS_H], [1],[Found vis.h and the strvis() function])])])
++
++AC_CHECK_FUNCS(strlcat strlcpy)
++AC_CHECK_FUNCS(issetugid)
++AC_CHECK_FUNCS(fgetln)
++AC_CHECK_FUNCS(getline flockfile)
++
++# from old readline settting:
++
++MAKE_SHELL=/bin/sh
++AC_SUBST(MAKE_SHELL)
++
++# Already-done: stdlib.h string.h unistd.h termios.h
++AC_CHECK_HEADERS(varargs.h stdarg.h dirent.h locale.h ndir.h sys/dir.h \
++ sys/file.h sys/ndir.h sys/ptem.h sys/pte.h sys/select.h sys/stream.h \
++ sys/mman.h curses.h termcap.h termio.h termbits.h asm/termbits.h grp.h \
++paths.h semaphore.h)
++
++# Already-done: strcasecmp
++AC_CHECK_FUNCS(lstat putenv select setenv setlocale strcoll tcgetattr)
++
++AC_STAT_MACROS_BROKEN
++MYSQL_SIGNAL_CHECK
++MYSQL_CHECK_GETPW_FUNCS
++MYSQL_HAVE_TIOCGWINSZ
++MYSQL_HAVE_FIONREAD
++MYSQL_HAVE_TIOCSTAT
++MYSQL_STRUCT_DIRENT_D_INO
++MYSQL_STRUCT_DIRENT_D_NAMLEN
++MYSQL_TYPE_SIGHANDLER
++MYSQL_CHECK_MULTIBYTE
++if test "$with_named_curses" = "no"
++then
++  MYSQL_CHECK_LIB_TERMCAP
++else
++  TERMCAP_LIB="$with_named_curses"
++fi
++AC_SUBST(TERMCAP_LIB)
++
++# Check if the termcap function 'tgoto' is already declared in
++# system header files or if it need to be declared locally
++AC_CHECK_DECLS(tgoto,,,[
++#ifdef HAVE_CURSES_H
++# include <curses.h>
++#elif HAVE_NCURSES_H
++# include <ncurses.h>
++#endif
++#ifdef HAVE_TERM_H
++# include <term.h>
++#endif
++])
++
++LIBEDIT_LOBJECTS=""
++AC_CHECK_FUNC(strunvis, ,[LIBEDIT_LOBJECTS="$LIBEDIT_LOBJECTS unvis.o"])
++AC_CHECK_FUNC(strvis,   ,[LIBEDIT_LOBJECTS="$LIBEDIT_LOBJECTS vis.o"])
++AC_CHECK_FUNC(strlcpy,  ,[LIBEDIT_LOBJECTS="$LIBEDIT_LOBJECTS strlcpy.o"])
++AC_CHECK_FUNC(strlcat,  ,[LIBEDIT_LOBJECTS="$LIBEDIT_LOBJECTS strlcat.o"])
++AC_CHECK_FUNC(fgetln,   ,[LIBEDIT_LOBJECTS="$LIBEDIT_LOBJECTS fgetln.o"])
++AC_SUBST(LIBEDIT_LOBJECTS)
++enable_readline="yes"
++
++# End of readline/libedit stuff
++#########################################################################
++
++dnl Checks for library functions.
++
++#
++# The following code disables intrinsic function support while we test for
++# library functions.  This is to avoid configure problems with Intel ecc
++# compiler
++
++ORG_CFLAGS="$CFLAGS"
++if test "$GCC" != "yes"; then
++  AC_SYS_COMPILER_FLAG(-nolib_inline,nolib_inline,CFLAGS,[],[])
++fi
++
++#AC_FUNC_MMAP
++AC_TYPE_SIGNAL
++MYSQL_TYPE_QSORT
++AC_FUNC_UTIME_NULL
++AC_FUNC_VPRINTF
++
++AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \
++  fconvert fdatasync finite fpresetsticky fpsetmask fsync ftruncate \
++  getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \
++  getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \
++  localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \
++  mkstemp mlockall perror poll pread pthread_attr_create mmap getpagesize \
++  pthread_attr_getstacksize pthread_attr_setprio pthread_attr_setschedparam \
++  pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \
++  pthread_key_delete pthread_rwlock_rdlock pthread_setprio \
++  pthread_setprio_np pthread_setschedparam pthread_sigmask readlink \
++  realpath rename rint rwlock_init setupterm \
++  shmget shmat shmdt shmctl sigaction sigemptyset sigaddset \
++  sighold sigset sigthreadmask \
++  snprintf socket stpcpy strcasecmp strerror strsignal strnlen strpbrk strstr strtol \
++  strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr)
++
++#
++#
++#
++case "$target" in
++ *-*-aix4* | *-*-sco*)
++	# (grr) aix 4.3 has a stub for clock_gettime, (returning ENOSYS)
++	# and using AC_TRY_RUN is hard when cross-compiling
++	# We also disable for SCO for the time being, the headers for the
++	# thread library we use conflicts with other headers.
++    ;;
++ *) AC_CHECK_FUNCS(clock_gettime)
++    ;;
++esac
++
++# Check that isinf() is available in math.h and can be used in both C and C++ 
++# code
++AC_MSG_CHECKING(for isinf in <math.h>)
++AC_TRY_LINK([#include <math.h>], [float f = 0.0; int r = isinf(f); return r],
++  AC_MSG_RESULT(yes)
++  AC_MSG_CHECKING(whether isinf() can be used in C++ code)
++  AC_LANG_SAVE
++  AC_LANG_CPLUSPLUS
++  AC_TRY_LINK([#include <math.h>], [float f = 0.0; int r = isinf(f); return r],
++    AC_MSG_RESULT(yes)
++    AC_DEFINE(HAVE_ISINF, [1], [isinf() macro or function]),
++    AC_MSG_RESULT(no))
++  AC_LANG_RESTORE,
++  AC_MSG_RESULT(no))
++ 
++CFLAGS="$ORG_CFLAGS"
++
++# Sanity check: We chould not have any fseeko symbol unless
++# large_file_support=yes
++AC_CHECK_FUNC(fseeko,
++[if test "$large_file_support" = no -a "$TARGET_LINUX" = "true";
++then
++  AC_MSG_ERROR("Found fseeko symbol but large_file_support is not enabled!");
++fi]
++)
++
++# Check definition of gethostbyaddr_r (glibc2 defines this with 8 arguments)
++ac_save_CXXFLAGS="$CXXFLAGS"
++AC_CACHE_CHECK([style of gethost* routines], mysql_cv_gethost_style,
++AC_LANG_SAVE
++AC_LANG_CPLUSPLUS
++
++# Test whether madvise() is declared in C++ code -- it is not on some
++# systems, such as Solaris
++AC_CHECK_DECLS(madvise, [], [], [#if HAVE_SYS_MMAN_H
++#include <sys/types.h>
++#include <sys/mman.h>
++#endif])
++
++# Do not treat warnings as errors if we are linking against other libc
++# this is to work around gcc not being permissive on non-system includes
++# with respect to ANSI C++
++# We also remove the -fbranch-probabilities option as this will give warnings
++# about not profiled code, which confuses configure
++# We also must remove -W and -Wcheck which on icc produces warnings that
++# we don't want to catch with -Werror
++
++if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
++then
++  CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed -e 's/-fbranch-probabilities//; s/-Wall//; s/-ansi//; s/-pedantic//; s/-Wcheck//'`
++fi
++
++AC_TRY_COMPILE(
++[#undef inline
++#if !defined(SCO) && !defined(__osf__) && !defined(_REENTRANT)
++#define _REENTRANT
++#endif
++#include <pthread.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <netdb.h>],
++[int skr;
++ struct hostent *foo = gethostbyaddr_r((const char *) 0,
++  0, 0, (struct hostent *) 0, (char *) NULL,  0, &skr); return (foo == 0);],
++mysql_cv_gethost_style=solaris, mysql_cv_gethost_style=other))
++AC_LANG_RESTORE
++CXXFLAGS="$ac_save_CXXFLAGS"
++if test "$mysql_cv_gethost_style" = "solaris"
++then
++  AC_DEFINE([HAVE_SOLARIS_STYLE_GETHOST], [1],
++            [Solaris define gethostbyaddr_r with 7 arguments. glibc2 defines this with 8 arguments])
++fi
++
++#---START: Used in for client configure
++
++# Check definition of gethostbyname_r (glibc2.0.100 is different from Solaris)
++ac_save_CXXFLAGS="$CXXFLAGS"
++AC_CACHE_CHECK([style of gethostname_r routines], mysql_cv_gethostname_style,
++AC_LANG_SAVE
++AC_LANG_CPLUSPLUS
++if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
++then
++  CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed -e 's/-fbranch-probabilities//; s/-Wall//; s/-ansi//; s/-pedantic//; s/-Wcheck//'`
++fi
++AC_TRY_COMPILE(
++[#undef inline
++#if !defined(SCO) && !defined(__osf__) && !defined(_REENTRANT)
++#define _REENTRANT
++#endif
++#include <pthread.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <netdb.h>],
++[int skr;
++
++ skr = gethostbyname_r((const char *) 0,
++  (struct hostent*) 0, (char*) 0, 0, (struct hostent **) 0, &skr);],
++mysql_cv_gethostname_style=glibc2, mysql_cv_gethostname_style=other))
++AC_LANG_RESTORE
++CXXFLAGS="$ac_save_CXXFLAGS"
++if test "$mysql_cv_gethostname_style" = "glibc2"
++then
++  AC_DEFINE([HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE], [1],
++            [Solaris define gethostbyname_r with 5 arguments. glibc2 defines this with 6 arguments])
++fi
++
++# Check 3rd argument of getthostbyname_r
++ac_save_CXXFLAGS="$CXXFLAGS"
++AC_CACHE_CHECK([3 argument to gethostname_r routines], mysql_cv_gethostname_arg,
++AC_LANG_SAVE
++AC_LANG_CPLUSPLUS
++if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
++then
++  CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed -e 's/-fbranch-probabilities//; s/-Wall//; s/-ansi//; s/-pedantic//; s/-Wcheck//'`
++fi
++AC_TRY_COMPILE(
++[#undef inline
++#if !defined(SCO) && !defined(__osf__) && !defined(_REENTRANT)
++#define _REENTRANT
++#endif
++#include <pthread.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
++#include <netdb.h>],
++[int skr;
++
++ skr = gethostbyname_r((const char *) 0, (struct hostent*) 0, (struct hostent_data*) 0);],
++mysql_cv_gethostname_arg=hostent_data, mysql_cv_gethostname_arg=char))
++AC_LANG_RESTORE
++CXXFLAGS="$ac_save_CXXFLAGS"
++if test "$mysql_cv_gethostname_arg" = "hostent_data"
++then
++  AC_DEFINE([HAVE_GETHOSTBYNAME_R_RETURN_INT], [1],
++            [In OSF 4.0f the 3'd argument to gethostname_r is hostent_data *])
++fi
++
++
++# Check definition of pthread_getspecific
++AC_CACHE_CHECK("args to pthread_getspecific", mysql_cv_getspecific_args,
++AC_TRY_COMPILE(
++[#if !defined(SCO) && !defined(__osf__) && !defined(_REENTRANT)
++#define _REENTRANT
++#endif
++#define _POSIX_PTHREAD_SEMANTICS 
++#include <pthread.h> ],
++[ void *pthread_getspecific(pthread_key_t key);
++pthread_getspecific((pthread_key_t) NULL); ],
++mysql_cv_getspecific_args=POSIX, mysql_cv_getspecific_args=other))
++  if test "$mysql_cv_getspecific_args" = "other"
++  then
++    AC_DEFINE([HAVE_NONPOSIX_PTHREAD_GETSPECIFIC], [1],
++              [For some non posix threads])
++  fi
++
++  # Check definition of pthread_mutex_init
++  AC_CACHE_CHECK("args to pthread_mutex_init", mysql_cv_mutex_init_args,
++  AC_TRY_COMPILE(
++[#if !defined(SCO) && !defined(__osf__)
++#define _REENTRANT
++#endif
++#define _POSIX_PTHREAD_SEMANTICS 
++#include <pthread.h> ],
++[ 
++  pthread_mutexattr_t attr;
++  pthread_mutex_t mp;
++  pthread_mutex_init(&mp,&attr); ],
++mysql_cv_mutex_init_args=POSIX, mysql_cv_mutex_init_args=other))
++  if test "$mysql_cv_mutex_init_args" = "other"
++  then
++    AC_DEFINE([HAVE_NONPOSIX_PTHREAD_MUTEX_INIT], [1],
++              [For some non posix threads])
++  fi
++#---END:
++
++#---START: Used in for client configure
++# Check definition of readdir_r
++AC_CACHE_CHECK("args to readdir_r", mysql_cv_readdir_r,
++AC_TRY_LINK(
++[#if !defined(SCO) && !defined(__osf__)
++#define _REENTRANT
++#endif
++#define _POSIX_PTHREAD_SEMANTICS 
++#include <pthread.h>
++#include <dirent.h>],
++[ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
++readdir_r((DIR *) NULL, (struct dirent *) NULL, (struct dirent **) NULL); ],
++mysql_cv_readdir_r=POSIX, mysql_cv_readdir_r=other))
++if test "$mysql_cv_readdir_r" = "POSIX"
++then
++  AC_DEFINE([HAVE_READDIR_R], [1], [POSIX readdir_r])
++fi
++
++# Check definition of posix sigwait()
++AC_CACHE_CHECK("style of sigwait", mysql_cv_sigwait,
++AC_TRY_LINK(
++[#if !defined(SCO) && !defined(__osf__)
++#define _REENTRANT
++#endif
++#define _POSIX_PTHREAD_SEMANTICS 
++#include <pthread.h>
++#include <signal.h>],
++[#ifndef _AIX
++sigset_t set;
++int sig;
++sigwait(&set,&sig);
++#endif],
++mysql_cv_sigwait=POSIX, mysql_cv_sigwait=other))
++if test "$mysql_cv_sigwait" = "POSIX"
++then
++  AC_DEFINE([HAVE_SIGWAIT], [1], [POSIX sigwait])
++fi
++
++if test "$mysql_cv_sigwait" != "POSIX"
++then
++unset mysql_cv_sigwait
++# Check definition of posix sigwait()
++AC_CACHE_CHECK("style of sigwait", mysql_cv_sigwait,
++AC_TRY_LINK(
++[#if !defined(SCO) && !defined(__osf__)
++#define _REENTRANT
++#endif
++#define _POSIX_PTHREAD_SEMANTICS 
++#include <pthread.h>
++#include <signal.h>],
++[sigset_t set;
++int sig;
++sigwait(&set);],
++mysql_cv_sigwait=NONPOSIX, mysql_cv_sigwait=other))
++if test "$mysql_cv_sigwait" = "NONPOSIX"
++then
++  AC_DEFINE([HAVE_NONPOSIX_SIGWAIT], [1], [sigwait with one argument])
++fi
++fi
++#---END:
++
++# Check if pthread_attr_setscope() exists
++AC_CACHE_CHECK("for pthread_attr_setscope", mysql_cv_pthread_attr_setscope,
++AC_TRY_LINK(
++[#if !defined(SCO) && !defined(__osf__)
++#define _REENTRANT
++#endif
++#define _POSIX_PTHREAD_SEMANTICS 
++#include <pthread.h>],
++[pthread_attr_t thr_attr;
++pthread_attr_setscope(&thr_attr,0);],
++mysql_cv_pthread_attr_setscope=yes, mysql_cv_pthread_attr_setscope=no))
++if test "$mysql_cv_pthread_attr_setscope" = "yes"
++then
++  AC_DEFINE([HAVE_PTHREAD_ATTR_SETSCOPE], [1], [pthread_attr_setscope])
++fi
++
++# Check for bad includes
++AC_MSG_CHECKING("can netinet files be included")
++AC_TRY_COMPILE(
++[#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in_systm.h>
++#include <netinet/in.h>
++#include <netinet/ip.h>
++#include <netinet/tcp.h>],
++[ printf("1\n"); ],
++netinet_inc=yes, netinet_inc=no)
++if test "$netinet_inc" = "no"
++then
++  AC_DEFINE([HAVE_BROKEN_NETINET_INCLUDES], [1], [Can netinet be included])
++fi
++AC_MSG_RESULT("$netinet_inc")
++
++# Only build client code?
++AC_ARG_WITH(server,
++    [  --without-server        Only build the client.],
++    [with_server=$withval],
++    [with_server=yes]
++)
++
++AC_ARG_WITH(embedded-server,
++    [  --with-embedded-server  Build the embedded server (libmysqld).],
++    [with_embedded_server=$withval],
++    [with_embedded_server=no]
++)
++
++AC_ARG_WITH(query_cache,
++    [  --without-query-cache   Do not build query cache.],
++    [with_query_cache=$withval],
++    [with_query_cache=yes]
++)
++
++if test "$with_query_cache" = "yes"
++then
++  AC_DEFINE([HAVE_QUERY_CACHE], [1], [If we want to have query cache])
++fi
++
++AC_ARG_WITH(geometry,
++    [  --without-geometry      Do not build geometry-related parts.],
++    [with_geometry=$withval],
++    [with_geometry=yes]
++)
++
++if test "$with_geometry" = "yes"
++then
++  AC_DEFINE([HAVE_SPATIAL], [1], [Spatial extentions])
++  AC_DEFINE([HAVE_RTREE_KEYS], [1], [RTree keys])
++fi
++
++AC_ARG_WITH(embedded_privilege_control,
++    [  --with-embedded-privilege-control
++                          Build parts to check user's privileges.
++			  Only affects embedded library.],
++    [with_embedded_privilege_control=$withval],
++    [with_embedded_privilege_control=no]
++)
++
++if test "$with_embedded_privilege_control" = "yes"
++then
++  AC_DEFINE([HAVE_EMBEDDED_PRIVILEGE_CONTROL], [1],
++            [Access checks in embedded library])
++fi
++
++AC_ARG_WITH(extra-tools,
++    [  --without-extra-tools   Skip building utilites in the tools directory.],
++    [with_tools=$withval],
++    [with_tools=yes]
++)
++
++tools_dirs=""
++if test "$with_tools" = "yes"
++then
++  if test "$THREAD_SAFE_CLIENT" = "no"
++  then
++    AC_MSG_WARN([extra-tools disabled because --enable-thread-safe-client wasn't used])
++  else
++    tools_dirs="tools"
++    AC_CONFIG_FILES(tools/Makefile)
++  fi
++fi
++
++AC_ARG_WITH([mysqlmanager],
++  AC_HELP_STRING([--with-mysqlmanager], [Build the mysqlmanager binary: yes/no (default: build if server is built.)]),
++  [if test "x${withval}" != "xno"; then
++    tools_dirs="$tools_dirs server-tools"
++   fi],
++  [if test "x${with_server}" = "xyes"; then
++     tools_dirs="$tools_dirs server-tools"
++   fi]
++)
++
++AC_SUBST(tools_dirs)
++
++#MYSQL_CHECK_CPU
++MYSQL_CHECK_VIO
++MYSQL_CHECK_OPENSSL
++MYSQL_CHECK_YASSL
++
++libmysqld_dirs=
++linked_libmysqld_targets=
++if test "$with_embedded_server" = "yes"
++then
++  libmysqld_dirs=libmysqld
++  linked_libmysqld_targets="linked_libmysqld_sources linked_libmysqldex_sources"
++  AC_CONFIG_FILES(libmysqld/Makefile libmysqld/examples/Makefile)
++  # We can't build embedded library without building the server, because
++  # we depend on libmysys, libmystrings, libmyisam, etc.
++  with_server=yes
++fi
++# XXX: We need to add @libmysqld_extra_libs@ (or whatever) so that
++# mysql_config --libmysqld-libs will print out something like
++# -L/path/to/lib/mysql -lmysqld -lmyisam -lmysys -lmystrings -ldbug ...
++AC_SUBST([libmysqld_dirs])
++AC_SUBST([linked_libmysqld_targets])
++
++# Shall we build the docs?
++AC_ARG_WITH(docs,
++    [  --without-docs          Skip building of the documentation.],
++    [with_docs=$withval],
++    [with_docs=yes]
++)
++
++if test "$with_docs" = "yes"
++then
++  docs_dirs="Docs"
++else
++  docs_dirs=""
++fi
++AC_SUBST(docs_dirs)
++
++# Shall we build the man pages?
++AC_ARG_WITH(man,
++    [  --without-man          Skip building of the man pages.],
++    [with_man=$withval],
++    [with_man=yes]
++)
++
++# Shall we build the bench code?
++AC_ARG_WITH(bench,
++    [  --without-bench         Skip building of the benchmark suite.],
++    [with_bench=$withval],
++    [with_bench=yes]
++)
++
++if test "$with_bench" = "yes"
++then
++  bench_dirs="sql-bench"
++else
++  bench_dirs=""
++fi
++bench_dirs="$bench_dirs mysql-test"
++AC_SUBST(bench_dirs)
++
++# Don't build readline, i have it already
++AC_ARG_WITH(readline,
++    [  --without-readline      Use system readline instead of bundled copy.],
++    [ with_readline=$withval ],
++    [ with_readline=undefined ]
++    )
++    
++AC_ARG_WITH(libedit,
++    [  --without-libedit       Use system libedit instead of bundled copy.],
++    [ with_libedit=$withval ],
++    [ with_libedit=undefined ]
++    )
++
++#
++# We support next variants of compilation:
++#                              --with-readline
++#                |       yes      |  no  |               undefined
++# --with-libedit |                |      |
++# ---------------+----------------+------+----------------------------------
++#       yes      |      ERROR!    |   use libedit from mysql sources
++# ---------------+----------------+------+----------------------------------
++#       no       | use readline   | use system readline or external libedit
++#                | from mysql     | according to results of m4 tests
++# ---------------+ sources (if it +      +----------------------------------
++#    undefined   | is presented)  |      | use libedit from mysql sources
++                   
++
++compile_readline="no"
++compile_libedit="no"
++
++if [test "$with_libedit" = "yes"] && [test "$with_readline" = "yes"]
++then
++    AC_MSG_ERROR([You can not use --with-readline and --with-libedit at the same time, please choose one of it])
++fi
++
++readline_topdir=""
++readline_basedir=""
++readline_dir=""
++readline_h_ln_cmd=""
++readline_link=""
++want_to_use_readline="no"
++
++if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then
++    # For NetWare, do not need readline
++    echo "Skipping readline"
++else
++
++if [test "$with_libedit" = "yes"] || [test "$with_libedit" = "undefined"] && [test "$with_readline" = "undefined"]
++then
++    readline_topdir="cmd-line-utils"
++    readline_basedir="libedit"
++    readline_dir="$readline_topdir/$readline_basedir"
++    readline_link="\$(top_builddir)/cmd-line-utils/libedit/libedit.a"
++    readline_h_ln_cmd="\$(LN) -s \$(top_srcdir)/cmd-line-utils/libedit/readline readline"
++    compile_libedit=yes
++    AC_DEFINE_UNQUOTED(HAVE_HIST_ENTRY, 1)
++    AC_DEFINE_UNQUOTED(USE_LIBEDIT_INTERFACE, 1)
++elif test "$with_readline" = "yes"
++then
++    readline_topdir="cmd-line-utils"
++    readline_basedir="readline"
++    readline_dir="$readline_topdir/$readline_basedir"
++    readline_link="\$(top_builddir)/cmd-line-utils/readline/libreadline.a"
++    readline_h_ln_cmd="\$(LN) -s \$(top_srcdir)/cmd-line-utils/readline readline"
++    compile_readline=yes
++    want_to_use_readline="yes"
++    AC_DEFINE_UNQUOTED(USE_NEW_READLINE_INTERFACE, 1)
++else
++    # Use system readline library
++    AC_LANG_SAVE
++    AC_LANG_CPLUSPLUS
++    MYSQL_CHECK_LIBEDIT_INTERFACE
++    MYSQL_CHECK_NEW_RL_INTERFACE
++    MYSQL_CHECK_READLINE_DECLARES_HIST_ENTRY
++    AC_LANG_RESTORE
++    if [test "$mysql_cv_new_rl_interface" = "yes"] && [test -d "./cmd-line-utils/readline"]
++    then
++        # Use the new readline interface, but only if the package includes a bundled libreadline
++        # this way we avoid linking commercial source with GPL readline
++        readline_link="-lreadline"
++        want_to_use_readline="yes"
++    elif [test "$mysql_cv_libedit_interface" = "yes"]; then
++        # Use libedit
++        readline_link="-ledit"
++    else
++       AC_MSG_ERROR([Could not find system readline or libedit libraries
++          Use --with-readline or --with-libedit to use the bundled
++          versions of libedit or readline])
++    fi
++fi
++
++# if there is no readline, but we want to build with readline, we fail
++if [test "$want_to_use_readline" = "yes"] && [test ! -d "./cmd-line-utils/readline"]
++then
++    AC_MSG_ERROR([This commercially licensed MySQL source package can't
++          be built with libreadline. Please use --with-libedit to use
++          the bundled version of libedit instead.])
++fi
++
++fi
++
++AC_SUBST(readline_dir)
++AC_SUBST(readline_topdir)
++AC_SUBST(readline_basedir)
++AC_SUBST(readline_link)
++AC_SUBST(readline_h_ln_cmd)
++
++MYSQL_CHECK_BIG_TABLES
++MYSQL_CHECK_MAX_INDEXES
++MYSQL_CHECK_BDB
++MYSQL_CHECK_INNODB
++MYSQL_CHECK_EXAMPLEDB
++MYSQL_CHECK_ARCHIVEDB
++MYSQL_CHECK_CSVDB
++MYSQL_CHECK_BLACKHOLEDB
++MYSQL_CHECK_NDBCLUSTER
++MYSQL_CHECK_FEDERATED
++
++# Include man pages, if desired, adapted to the configured parts.
++if test X"$with_man" = Xyes
++then
++  # First, create the list of all man pages present.
++  MANLISTFIL=manlist.$$
++  TMPLISTFIL=`echo $MANLISTFIL | sed -e 's/manlist/tmplist/'`
++  if test -f $MANLISTFIL -o -f $TMPLISTFIL
++  then
++    echo "Temp file '$MANLISTFIL' or '$TMPLISTFIL' already exists in '`pwd`' - aborting"
++    exit 1
++  fi
++  touch $MANLISTFIL $TMPLISTFIL
++
++  ls $srcdir/man/*.[[18]] > $MANLISTFIL
++
++  # Then, remove all those pages from the list which are specific to parts
++  # (table handlers, features, ...) which are not configured in this run.
++  AC_MSG_CHECKING("for man pages to remove")
++  MAN_DROP="dropping"
++  if test X"$have_ndbcluster" != Xyes
++  then
++    MAN_DROP="$MAN_DROP ndbcluster"
++    grep -v '/ndb' $MANLISTFIL > $TMPLISTFIL ; mv -f $TMPLISTFIL $MANLISTFIL
++  fi
++  if test X"$with_embedded_server" != Xyes
++  then
++    MAN_DROP="$MAN_DROP embedded"
++    grep -v 'embedded' $MANLISTFIL > $TMPLISTFIL ; mv -f $TMPLISTFIL $MANLISTFIL
++  fi
++  if test X"$have_innodb" != Xyes
++  then
++    MAN_DROP="$MAN_DROP innodb"
++    grep -v 'inno' $MANLISTFIL > $TMPLISTFIL ; mv -f $TMPLISTFIL $MANLISTFIL
++  fi
++  AC_MSG_RESULT([$MAN_DROP])
++
++  # Finally, split the man pages into sections 1 and 8.
++  # Get rid of line breaks.
++  man1_files=`sed -n -e '/\.1$/s/^.*man\///p' <$MANLISTFIL`
++  man8_files=`sed -n -e '/\.8$/s/^.*man\///p' <$MANLISTFIL`
++
++  man_dirs="man"
++  man1_files=`echo $man1_files`
++  man8_files=`echo $man8_files`
++  rm -f $MANLISTFIL $TMPLISTFIL
++else
++  man_dirs=""
++  man1_files=""
++  man8_files=""
++fi
++AC_SUBST(man_dirs)
++AC_SUBST(man1_files)
++AC_SUBST(man8_files)
++
++# If we have threads generate some library functions and test programs
++sql_server_dirs=
++server_scripts=
++thread_dirs=
++
++dnl This probably should be cleaned up more - for now the threaded
++dnl client is just using plain-old libs.
++sql_client_dirs="strings regex mysys libmysql client"
++linked_client_targets="linked_libmysql_sources"
++
++if test "$THREAD_SAFE_CLIENT" != "no"
++then
++  sql_client_dirs="libmysql_r $sql_client_dirs"
++  linked_client_targets="$linked_client_targets linked_libmysql_r_sources"
++  AC_CONFIG_FILES(libmysql_r/Makefile)
++  AC_DEFINE([THREAD_SAFE_CLIENT], [1], [Should be client be thread safe])
++fi
++
++CLIENT_LIBS="$NON_THREADED_LIBS $openssl_libs $ZLIB_LIBS $STATIC_NSS_FLAGS"
++
++AC_SUBST(CLIENT_LIBS)
++AC_SUBST(NON_THREADED_LIBS)
++AC_SUBST(STATIC_NSS_FLAGS)
++AC_SUBST(sql_client_dirs)
++AC_SUBST(linked_client_targets)
++
++# If configuring for NetWare, set up to link sources from and build the netware directory
++netware_dir=
++linked_netware_sources=
++if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then
++  netware_dir="netware"
++  linked_netware_sources="linked_netware_sources"
++fi
++AC_SUBST(netware_dir)
++AC_SUBST(linked_netware_sources)
++AM_CONDITIONAL(HAVE_NETWARE, test "$netware_dir" = "netware")
++
++# Ensure that table handlers gets all modifications to CFLAGS/CXXFLAGS
++export CC CXX CFLAGS CXXFLAGS LD LDFLAGS AR
++ac_configure_args="$ac_configure_args CFLAGS='$CFLAGS' CXXFLAGS='$CXXFLAGS'"
++
++if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no"
++then
++  AC_DEFINE([THREAD], [1],
++            [Define if you want to have threaded code. This may be undef on client code])
++  # Avoid _PROGRAMS names
++  THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o mf_keycache.o"
++  AC_SUBST(THREAD_LOBJECTS)
++  server_scripts="mysqld_safe mysql_install_db"
++  sql_server_dirs="strings mysys dbug extra regex"
++
++
++  #
++  # Configuration for optional table handlers
++  #
++
++  if test X"$have_berkeley_db" != Xno; then
++    if test X"$have_berkeley_db" != Xyes; then
++      # we must build berkeley db from source
++      sql_server_dirs="$sql_server_dirs $have_berkeley_db"
++      AC_CONFIG_FILES(bdb/Makefile)
++
++      echo "CONFIGURING FOR BERKELEY DB" 
++      bdb_conf_flags="--disable-shared --build=$build_alias"
++      if test $with_debug = "yes"
++      then
++        bdb_conf_flags="$bdb_conf_flags --enable-debug --enable-diagnostic"
++      fi
++      # NOTICE: if you're compiling BDB, it needs to be a SUBDIR
++      # of $srcdir (i.e., you can 'cd $srcdir/$bdb').  It won't
++      # work otherwise.
++      if test -d "$bdb"; then :
++      else
++	# This should only happen when doing a VPATH build
++	echo "NOTICE: I have to make the BDB directory: `pwd`:$bdb"
++	mkdir "$bdb" || exit 1
++      fi
++      if test -d "$bdb"/build_unix; then :
++      else
++	# This should only happen when doing a VPATH build
++	echo "NOTICE: I have to make the build_unix directory: `pwd`:$bdb/build_unix"
++	mkdir "$bdb/build_unix" || exit 1
++      fi
++      rel_srcdir=
++      case "$srcdir" in
++	/* ) rel_srcdir="$srcdir" ;;
++	* )  rel_srcdir="../../$srcdir" ;;
++      esac
++      (cd $bdb/build_unix && \
++       sh $rel_srcdir/$bdb/dist/configure $bdb_conf_flags) || \
++        AC_MSG_ERROR([could not configure Berkeley DB])
++
++dnl       echo "bdb = '$bdb'; inc = '$bdb_includes', lib = '$bdb_libs'"
++      echo "END OF BERKELEY DB CONFIGURATION"
++    fi
++
++    AC_DEFINE([HAVE_BERKELEY_DB], [1], [Have berkeley db installed])
++  else
++    if test -d bdb; then :
++    else
++      mkdir bdb && mkdir bdb/build_unix
++    fi
++
++    if test -r bdb/build_unix/db.h; then :
++    else
++      cat <<EOF > bdb/build_unix/db.h
++
++This file is a placeholder to fool make.  The way that automake
++and GNU make work together causes some files to depend on this
++header, even if we're not building with Berkeley DB.
++
++Obviously, if this file *is* used, it'll break and hopefully we can find
++out why this file was generated by ${top_srcdir}/configure instead of
++the real db.h.
++
++If you run into some problems because of this file, please use mysql_bug
++to generate a bug report, and give the exact output of make and any
++details you can think of.  Send the message to bugs at lists.mysql.com.
++
++Thank you!
++
++EOF
++    fi
++  fi
++
++  if test X"$have_innodb" = Xyes
++  then
++    innodb_conf_flags=""
++    sql_server_dirs="$sql_server_dirs innobase"
++    AC_CONFIG_SUBDIRS(innobase)
++  fi
++
++case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc-$have_ndbcluster in
++  *solaris*-i?86-no-yes)
++  # ndb fail for whatever strange reason to link Sun Forte/x86
++  # unless using incremental linker
++  CXXFLAGS="$CXXFLAGS -xildon"
++  ;;
++  *) ;;
++esac
++
++  if test X"$have_ndbcluster" = Xyes
++  then
++    if test X"$mysql_cv_compress" != Xyes
++    then
++      echo
++      echo "MySQL Cluster table handler ndbcluster requires compress/uncompress."
++      echo "Commonly available in libzlib.a.  Please install and rerun configure."
++      echo
++      exit 1
++    fi
++    sql_server_dirs="$sql_server_dirs ndb"
++  fi
++  #
++  # END of configuration for optional table handlers
++  #
++  sql_server_dirs="$sql_server_dirs myisam myisammrg heap vio sql"
++fi
++
++# IMPORTANT - do not modify LIBS past this line - this hack is the only way
++# I know to add the static NSS magic if we have static NSS libraries with
++# glibc - Sasha
++
++LDFLAGS="$LDFLAGS $OTHER_LIBC_LIB"
++LIBS="$LIBS $STATIC_NSS_FLAGS"
++
++AC_SUBST(sql_server_dirs)
++AC_SUBST(thread_dirs)
++AC_SUBST(server_scripts)
++
++# Now that sql_client_dirs and sql_server_dirs are stable, determine the union.
++# Start with the (longer) server list, add each client item not yet present.
++sql_union_dirs=" $sql_server_dirs "
++for DIR in $sql_client_dirs
++do
++  if echo " $sql_union_dirs " | grep " $DIR " >/dev/null
++  then
++    :  # already present, skip
++  else
++    sql_union_dirs="$sql_union_dirs $DIR "
++  fi
++done
++AC_SUBST(sql_union_dirs)
++
++# Some usefull subst
++AC_SUBST(CC)
++AC_SUBST(GXX)
++
++# Set configuration options for make_binary_distribution
++case $SYSTEM_TYPE in
++  *netware*)
++    MAKE_BINARY_DISTRIBUTION_OPTIONS=--no-strip
++    ;;
++  *)
++    MAKE_BINARY_DISTRIBUTION_OPTIONS=
++    ;;
++esac
++
++
++if test X"$have_ndbcluster" = Xyes
++then
++  MAKE_BINARY_DISTRIBUTION_OPTIONS="$MAKE_BINARY_DISTRIBUTION_OPTIONS --with-ndbcluster"
++
++  CXXFLAGS="$CXXFLAGS \$(NDB_CXXFLAGS)"
++  if test "$have_ndb_debug" = "default"
++  then
++    have_ndb_debug=$with_debug
++  fi
++
++  if test "$have_ndb_debug" = "yes"
++  then
++    # Medium debug.
++    NDB_DEFS="-DNDB_DEBUG -DVM_TRACE -DERROR_INSERT -DARRAY_GUARD"
++  elif test "$have_ndb_debug" = "full"
++  then
++    NDB_DEFS="-DNDB_DEBUG_FULL -DVM_TRACE -DERROR_INSERT -DARRAY_GUARD"
++  else
++    # no extra ndb debug but still do asserts if debug version
++    if test "$with_debug" = "yes" -o "$with_debug" = "full"
++    then
++      NDB_DEFS=""
++    else
++      NDB_DEFS="-DNDEBUG"
++    fi
++  fi
++
++AC_SUBST([NDB_DEFS])
++AC_SUBST([ndb_cxxflags_fix])
++
++
++if test X"$ndb_port" = Xdefault
++then
++  ndb_port="1186"
++fi
++AC_SUBST([ndb_port])
++
++ndb_transporter_opt_objs=""
++if test "$ac_cv_func_shmget" = "yes" &&
++   test "$ac_cv_func_shmat" = "yes" &&
++   test "$ac_cv_func_shmdt" = "yes" &&
++   test "$ac_cv_func_shmctl" = "yes" &&
++   test "$ac_cv_func_sigaction" = "yes" &&
++   test "$ac_cv_func_sigemptyset" = "yes" &&
++   test "$ac_cv_func_sigaddset" = "yes" &&
++   test "$ac_cv_func_pthread_sigmask" = "yes"
++then
++   AC_DEFINE([NDB_SHM_TRANSPORTER], [1],
++             [Including Ndb Cluster DB shared memory transporter])
++   AC_MSG_RESULT([Including ndb shared memory transporter])
++   ndb_transporter_opt_objs="$ndb_transporter_opt_objs SHM_Transporter.lo SHM_Transporter.unix.lo"
++else
++   AC_MSG_RESULT([Not including ndb shared memory transporter])
++fi
++
++if test X"$have_ndb_sci" = Xyes
++then
++  ndb_transporter_opt_objs="$ndb_transporter_opt_objs SCI_Transporter.lo"
++fi
++AC_SUBST([ndb_transporter_opt_objs])
++
++ndb_opt_subdirs=
++ndb_bin_am_ldflags="-static"
++if test X"$have_ndb_test" = Xyes
++then
++  ndb_opt_subdirs="test"
++  ndb_bin_am_ldflags=""
++fi
++if test X"$have_ndb_docs" = Xyes
++then
++  ndb_opt_subdirs="$ndb_opt_subdirs docs"
++  ndb_bin_am_ldflags=""
++fi
++# building dynamic breaks on AIX. (If you want to try it and get unresolved
++# __vec__delete2 and some such, try linking against libhC.)
++case "$host_os" in
++  aix3.* | aix4.0.* | aix4.1.*) ;;
++  *) ndb_bin_am_ldflags="-static";;
++esac
++AC_SUBST([ndb_bin_am_ldflags])
++AC_SUBST([ndb_opt_subdirs])
++
++NDB_SIZEOF_CHARP="$ac_cv_sizeof_charp"
++NDB_SIZEOF_CHAR="$ac_cv_sizeof_char"
++NDB_SIZEOF_SHORT="$ac_cv_sizeof_short"
++NDB_SIZEOF_INT="$ac_cv_sizeof_int"
++NDB_SIZEOF_LONG="$ac_cv_sizeof_long"
++NDB_SIZEOF_LONG_LONG="$ac_cv_sizeof_long_long"
++AC_SUBST([NDB_SIZEOF_CHARP])
++AC_SUBST([NDB_SIZEOF_CHAR])
++AC_SUBST([NDB_SIZEOF_SHORT])
++AC_SUBST([NDB_SIZEOF_INT])
++AC_SUBST([NDB_SIZEOF_LONG])
++AC_SUBST([NDB_SIZEOF_LONG_LONG])
++
++AC_CONFIG_FILES(ndb/Makefile ndb/include/Makefile dnl
++   ndb/src/Makefile ndb/src/common/Makefile dnl
++   ndb/docs/Makefile dnl
++   ndb/tools/Makefile dnl
++   ndb/src/common/debugger/Makefile dnl
++   ndb/src/common/debugger/signaldata/Makefile dnl
++   ndb/src/common/portlib/Makefile dnl
++   ndb/src/common/util/Makefile dnl
++   ndb/src/common/logger/Makefile dnl
++   ndb/src/common/transporter/Makefile dnl
++   ndb/src/common/mgmcommon/Makefile dnl
++   ndb/src/kernel/Makefile dnl
++   ndb/src/kernel/error/Makefile dnl
++   ndb/src/kernel/blocks/Makefile dnl
++   ndb/src/kernel/blocks/cmvmi/Makefile dnl
++   ndb/src/kernel/blocks/dbacc/Makefile dnl
++   ndb/src/kernel/blocks/dbdict/Makefile dnl
++   ndb/src/kernel/blocks/dbdih/Makefile dnl
++   ndb/src/kernel/blocks/dblqh/Makefile dnl
++   ndb/src/kernel/blocks/dbtc/Makefile dnl
++   ndb/src/kernel/blocks/dbtup/Makefile dnl
++   ndb/src/kernel/blocks/ndbfs/Makefile dnl
++   ndb/src/kernel/blocks/ndbcntr/Makefile dnl
++   ndb/src/kernel/blocks/qmgr/Makefile dnl
++   ndb/src/kernel/blocks/trix/Makefile dnl
++   ndb/src/kernel/blocks/backup/Makefile dnl
++   ndb/src/kernel/blocks/dbutil/Makefile dnl
++   ndb/src/kernel/blocks/suma/Makefile dnl
++   ndb/src/kernel/blocks/dbtux/Makefile dnl
++   ndb/src/kernel/vm/Makefile dnl
++   ndb/src/mgmapi/Makefile dnl
++   ndb/src/ndbapi/Makefile dnl
++   ndb/src/mgmsrv/Makefile dnl
++   ndb/src/mgmclient/Makefile dnl
++   ndb/src/cw/Makefile dnl
++   ndb/src/cw/cpcd/Makefile dnl
++   ndb/test/Makefile dnl
++   ndb/test/src/Makefile dnl
++   ndb/test/ndbapi/Makefile dnl
++   ndb/test/ndbapi/bank/Makefile dnl
++   ndb/test/tools/Makefile dnl
++   ndb/test/run-test/Makefile mysql-test/ndb/Makefile dnl
++   ndb/include/ndb_version.h ndb/include/ndb_global.h dnl
++   ndb/include/ndb_types.h dnl
++   )
++fi
++
++AC_SUBST(MAKE_BINARY_DISTRIBUTION_OPTIONS)
++
++# Output results
++AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
++ strings/Makefile regex/Makefile heap/Makefile dnl
++ myisam/Makefile myisammrg/Makefile dnl
++ os2/Makefile os2/include/Makefile os2/include/sys/Makefile dnl
++ man/Makefile BUILD/Makefile vio/Makefile dnl
++ libmysql/Makefile client/Makefile dnl
++ pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile dnl
++ sql-common/Makefile SSL/Makefile dnl
++ dbug/Makefile scripts/Makefile dnl
++ include/Makefile sql-bench/Makefile dnl
++ server-tools/Makefile server-tools/instance-manager/Makefile dnl
++ tests/Makefile Docs/Makefile support-files/Makefile dnl
++ support-files/MacOSX/Makefile support-files/RHEL4-SElinux/Makefile dnl
++ mysql-test/Makefile dnl
++ netware/Makefile dnl
++ include/mysql_version.h dnl
++ cmd-line-utils/Makefile dnl
++ cmd-line-utils/libedit/Makefile dnl
++ win/Makefile dnl
++ zlib/Makefile dnl
++ debian/Makefile debian/defs.mk debian/control dnl
++ cmd-line-utils/readline/Makefile)
++ AC_CONFIG_COMMANDS([default], , test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h)
++ AC_OUTPUT
++
++echo
++echo "MySQL has a Web site at http://www.mysql.com/ which carries details on the"
++echo "latest release, upcoming features, and other information to make your"
++echo "work or play with MySQL more productive. There you can also find"
++echo "information about mailing lists for MySQL discussion."
++echo
++echo "Remember to check the platform specific part of the reference manual for"
++echo "hints about installing MySQL on your platform. Also have a look at the"
++echo "files in the Docs directory."
++echo
++# The following text is checked in ./Do-compile to verify that configure
++# ended sucessfully - don't remove it.
++echo "Thank you for choosing MySQL!"
++echo
+diff -urNad trunk~/dbug/Makefile.in trunk/dbug/Makefile.in
+--- trunk~/dbug/Makefile.in	2007-11-15 08:08:13.000000000 -0600
++++ trunk/dbug/Makefile.in	2007-12-27 15:54:48.754233227 -0600
+@@ -69,6 +69,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/extra/Makefile.in trunk/extra/Makefile.in
+--- trunk~/extra/Makefile.in	2007-11-15 08:08:14.000000000 -0600
++++ trunk/extra/Makefile.in	2007-12-27 15:54:48.754233227 -0600
+@@ -70,6 +70,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/extra/yassl/Makefile.in trunk/extra/yassl/Makefile.in
+--- trunk~/extra/yassl/Makefile.in	2007-11-15 08:08:14.000000000 -0600
++++ trunk/extra/yassl/Makefile.in	2007-12-27 15:54:48.754233227 -0600
+@@ -48,6 +48,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/extra/yassl/src/Makefile.in trunk/extra/yassl/src/Makefile.in
+--- trunk~/extra/yassl/src/Makefile.in	2007-11-15 08:08:14.000000000 -0600
++++ trunk/extra/yassl/src/Makefile.in	2007-12-27 15:54:48.754233227 -0600
+@@ -48,6 +48,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/extra/yassl/taocrypt/Makefile.in trunk/extra/yassl/taocrypt/Makefile.in
+--- trunk~/extra/yassl/taocrypt/Makefile.in	2007-11-15 08:08:16.000000000 -0600
++++ trunk/extra/yassl/taocrypt/Makefile.in	2007-12-27 15:54:48.758233455 -0600
+@@ -48,6 +48,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/extra/yassl/taocrypt/benchmark/Makefile.in trunk/extra/yassl/taocrypt/benchmark/Makefile.in
+--- trunk~/extra/yassl/taocrypt/benchmark/Makefile.in	2007-11-15 08:08:16.000000000 -0600
++++ trunk/extra/yassl/taocrypt/benchmark/Makefile.in	2007-12-27 15:54:48.758233455 -0600
+@@ -49,6 +49,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/extra/yassl/taocrypt/src/Makefile.in trunk/extra/yassl/taocrypt/src/Makefile.in
+--- trunk~/extra/yassl/taocrypt/src/Makefile.in	2007-11-15 08:08:17.000000000 -0600
++++ trunk/extra/yassl/taocrypt/src/Makefile.in	2007-12-27 15:54:48.758233455 -0600
+@@ -48,6 +48,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/extra/yassl/taocrypt/test/Makefile.in trunk/extra/yassl/taocrypt/test/Makefile.in
+--- trunk~/extra/yassl/taocrypt/test/Makefile.in	2007-11-15 08:08:17.000000000 -0600
++++ trunk/extra/yassl/taocrypt/test/Makefile.in	2007-12-27 15:54:48.758233455 -0600
+@@ -49,6 +49,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/extra/yassl/testsuite/Makefile.in trunk/extra/yassl/testsuite/Makefile.in
+--- trunk~/extra/yassl/testsuite/Makefile.in	2007-11-15 08:08:18.000000000 -0600
++++ trunk/extra/yassl/testsuite/Makefile.in	2007-12-27 15:54:48.758233455 -0600
+@@ -49,6 +49,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/heap/Makefile.in trunk/heap/Makefile.in
+--- trunk~/heap/Makefile.in	2007-11-15 08:08:18.000000000 -0600
++++ trunk/heap/Makefile.in	2007-12-27 15:54:48.758233455 -0600
+@@ -67,6 +67,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/include/Makefile.in trunk/include/Makefile.in
+--- trunk~/include/Makefile.in	2007-11-15 08:08:19.000000000 -0600
++++ trunk/include/Makefile.in	2007-12-27 15:54:48.758233455 -0600
+@@ -67,6 +67,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/libmysql/Makefile.in trunk/libmysql/Makefile.in
+--- trunk~/libmysql/Makefile.in	2007-11-15 08:08:19.000000000 -0600
++++ trunk/libmysql/Makefile.in	2007-12-27 15:54:48.758233455 -0600
+@@ -97,6 +97,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/libmysql_r/Makefile.in trunk/libmysql_r/Makefile.in
+--- trunk~/libmysql_r/Makefile.in	2007-11-15 08:08:20.000000000 -0600
++++ trunk/libmysql_r/Makefile.in	2007-12-27 15:54:48.758233455 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/libmysqld/Makefile.am trunk/libmysqld/Makefile.am
+--- trunk~/libmysqld/Makefile.am	2007-11-15 08:07:10.000000000 -0600
++++ trunk/libmysqld/Makefile.am	2007-12-27 15:54:48.774234367 -0600
+@@ -29,6 +29,7 @@
+ 			-I$(top_builddir)/include -I$(top_srcdir)/include \
+ 			-I$(top_builddir)/sql -I$(top_srcdir)/sql \
+ 			-I$(top_srcdir)/sql/examples \
++			-I$(top_srcdir)/sql/sphinx \
+ 			-I$(top_srcdir)/regex \
+ 			$(openssl_includes) @ZLIB_INCLUDES@
+ 
+@@ -39,6 +40,7 @@
+ libmysqlsources =	errmsg.c get_password.c libmysql.c client.c pack.c \
+                         my_time.c
+ sqlexamplessources =	ha_example.cc ha_tina.cc
++sqlsphinxsources =	ha_sphinx.cc
+ 
+ noinst_HEADERS =	embedded_priv.h emb_qcache.h
+ 
+@@ -67,7 +69,7 @@
+ 	parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
+ 	ha_blackhole.cc ha_archive.cc my_user.c
+ 
+-libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources)
++libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources) $(sqlsphinxsources)
+ libmysqld_a_SOURCES=
+ 
+ # automake misses these
+@@ -147,12 +149,16 @@
+ 	    rm -f $$f; \
+ 	    @LN_CP_F@ $(top_srcdir)/sql/examples/$$f $$f; \
+ 	  done; \
++	  for f in $(sqlsphinxsources); do \
++	    rm -f $$f; \
++	    @LN_CP_F@ $(top_srcdir)/sql/sphinx/$$f $$f; \
++	  done; \
+ 	  rm -f client_settings.h; \
+ 	  @LN_CP_F@ $(top_srcdir)/libmysql/client_settings.h client_settings.h
+ 
+ 
+ clean-local:
+-	rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) | sed "s;\.lo;.c;g"` \
++	rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) $(sqlsphinxsources) | sed "s;\.lo;.c;g"` \
+ 	       $(top_srcdir)/linked_libmysqld_sources; \
+ 	rm -f client_settings.h
+ 
+diff -urNad trunk~/libmysqld/Makefile.in trunk/libmysqld/Makefile.in
+--- trunk~/libmysqld/Makefile.in	2007-11-15 08:08:20.000000000 -0600
++++ trunk/libmysqld/Makefile.in	2007-12-27 15:54:48.774234367 -0600
+@@ -69,6 +69,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+@@ -139,8 +140,9 @@
+ 	sql_view.$(OBJEXT) sql_trigger.$(OBJEXT) my_decimal.$(OBJEXT) \
+ 	ha_blackhole.$(OBJEXT) ha_archive.$(OBJEXT) my_user.$(OBJEXT)
+ am__objects_4 = ha_example.$(OBJEXT) ha_tina.$(OBJEXT)
++am__objects_5 = ha_sphinx.$(OBJEXT)
+ am_libmysqld_int_a_OBJECTS = $(am__objects_1) $(am__objects_2) \
+-	$(am__objects_3) $(am__objects_4)
++	$(am__objects_3) $(am__objects_4) $(am__objects_5)
+ libmysqld_int_a_OBJECTS = $(am_libmysqld_int_a_OBJECTS)
+ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include
+ depcomp = $(SHELL) $(top_srcdir)/depcomp
+@@ -447,6 +449,7 @@
+ 			-I$(top_builddir)/include -I$(top_srcdir)/include \
+ 			-I$(top_builddir)/sql -I$(top_srcdir)/sql \
+ 			-I$(top_srcdir)/sql/examples \
++			-I$(top_srcdir)/sql/sphinx \
+ 			-I$(top_srcdir)/regex \
+ 			$(openssl_includes) @ZLIB_INCLUDES@
+ 
+@@ -458,6 +461,7 @@
+                         my_time.c
+ 
+ sqlexamplessources = ha_example.cc ha_tina.cc
++sqlsphinxsources = ha_sphinx.cc
+ noinst_HEADERS = embedded_priv.h emb_qcache.h
+ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
+ 	ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_federated.cc \
+@@ -484,7 +488,7 @@
+ 	parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
+ 	ha_blackhole.cc ha_archive.cc my_user.c
+ 
+-libmysqld_int_a_SOURCES = $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources)
++libmysqld_int_a_SOURCES = $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources) $(sqlsphinxsources)
+ libmysqld_a_SOURCES = 
+ 
+ # The following libraries should be included in libmysqld.a
+@@ -593,6 +597,7 @@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ha_innodb.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ha_myisam.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ha_myisammrg.Po at am__quote@
++ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ha_sphinx.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ha_tina.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/handler.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/hash_filo.Po at am__quote@
+@@ -1067,11 +1072,15 @@
+ 	    rm -f $$f; \
+ 	    @LN_CP_F@ $(top_srcdir)/sql/examples/$$f $$f; \
+ 	  done; \
++	  for f in $(sqlsphinxsources); do \
++	    rm -f $$f; \
++	    @LN_CP_F@ $(top_srcdir)/sql/sphinx/$$f $$f; \
++	  done; \
+ 	  rm -f client_settings.h; \
+ 	  @LN_CP_F@ $(top_srcdir)/libmysql/client_settings.h client_settings.h
+ 
+ clean-local:
+-	rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) | sed "s;\.lo;.c;g"` \
++	rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) $(sqlsphinxsources) | sed "s;\.lo;.c;g"` \
+ 	       $(top_srcdir)/linked_libmysqld_sources; \
+ 	rm -f client_settings.h
+ 
+diff -urNad trunk~/libmysqld/examples/Makefile.in trunk/libmysqld/examples/Makefile.in
+--- trunk~/libmysqld/examples/Makefile.in	2007-11-15 08:08:21.000000000 -0600
++++ trunk/libmysqld/examples/Makefile.in	2007-12-27 15:54:48.786235051 -0600
+@@ -66,6 +66,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/man/Makefile.in trunk/man/Makefile.in
+--- trunk~/man/Makefile.in	2007-11-15 08:08:21.000000000 -0600
++++ trunk/man/Makefile.in	2007-12-27 15:54:48.786235051 -0600
+@@ -64,6 +64,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/myisam/Makefile.in trunk/myisam/Makefile.in
+--- trunk~/myisam/Makefile.in	2007-11-15 08:08:22.000000000 -0600
++++ trunk/myisam/Makefile.in	2007-12-27 15:54:48.798235735 -0600
+@@ -71,6 +71,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/myisammrg/Makefile.in trunk/myisammrg/Makefile.in
+--- trunk~/myisammrg/Makefile.in	2007-11-15 08:08:22.000000000 -0600
++++ trunk/myisammrg/Makefile.in	2007-12-27 15:54:48.798235735 -0600
+@@ -65,6 +65,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/mysql-test/Makefile.in trunk/mysql-test/Makefile.in
+--- trunk~/mysql-test/Makefile.in	2007-11-15 08:08:22.000000000 -0600
++++ trunk/mysql-test/Makefile.in	2007-12-27 15:54:48.810236419 -0600
+@@ -65,6 +65,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/mysql-test/ndb/Makefile.in trunk/mysql-test/ndb/Makefile.in
+--- trunk~/mysql-test/ndb/Makefile.in	2007-11-15 08:08:23.000000000 -0600
++++ trunk/mysql-test/ndb/Makefile.in	2007-12-27 15:54:48.950244397 -0600
+@@ -51,6 +51,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/mysql-test/r/ps_1general.result trunk/mysql-test/r/ps_1general.result
+--- trunk~/mysql-test/r/ps_1general.result	2007-11-15 08:28:37.000000000 -0600
++++ trunk/mysql-test/r/ps_1general.result	2007-12-27 15:56:06.650672293 -0600
+@@ -329,6 +329,7 @@
+ EXAMPLE	YES/NO	Example storage engine
+ ARCHIVE	YES/NO	Archive storage engine
+ CSV	YES/NO	CSV storage engine
++SPHINX YES/NO  Sphinx storage engine 0.9.8
+ ndbcluster	YES/NO	Clustered, fault-tolerant, memory-based tables
+ FEDERATED	YES/NO	Federated MySQL storage engine
+ MRG_MYISAM	YES/NO	Collection of identical MyISAM tables
+diff -urNad trunk~/mysys/Makefile.in trunk/mysys/Makefile.in
+--- trunk~/mysys/Makefile.in	2007-11-15 08:08:23.000000000 -0600
++++ trunk/mysys/Makefile.in	2007-12-27 15:54:48.950244397 -0600
+@@ -66,6 +66,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/Makefile.in trunk/ndb/Makefile.in
+--- trunk~/ndb/Makefile.in	2007-11-15 08:08:24.000000000 -0600
++++ trunk/ndb/Makefile.in	2007-12-27 15:54:48.954244625 -0600
+@@ -78,6 +78,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/docs/Makefile.in trunk/ndb/docs/Makefile.in
+--- trunk~/ndb/docs/Makefile.in	2007-11-15 08:08:24.000000000 -0600
++++ trunk/ndb/docs/Makefile.in	2007-12-27 15:54:48.954244625 -0600
+@@ -64,6 +64,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/include/Makefile.in trunk/ndb/include/Makefile.in
+--- trunk~/ndb/include/Makefile.in	2007-11-15 08:08:24.000000000 -0600
++++ trunk/ndb/include/Makefile.in	2007-12-27 15:54:48.954244625 -0600
+@@ -82,6 +82,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/Makefile.in trunk/ndb/src/Makefile.in
+--- trunk~/ndb/src/Makefile.in	2007-11-15 08:08:25.000000000 -0600
++++ trunk/ndb/src/Makefile.in	2007-12-27 15:54:48.954244625 -0600
+@@ -79,6 +79,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/common/Makefile.in trunk/ndb/src/common/Makefile.in
+--- trunk~/ndb/src/common/Makefile.in	2007-11-15 08:08:25.000000000 -0600
++++ trunk/ndb/src/common/Makefile.in	2007-12-27 15:54:48.958244853 -0600
+@@ -63,6 +63,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/common/debugger/Makefile.in trunk/ndb/src/common/debugger/Makefile.in
+--- trunk~/ndb/src/common/debugger/Makefile.in	2007-11-15 08:08:25.000000000 -0600
++++ trunk/ndb/src/common/debugger/Makefile.in	2007-12-27 15:54:48.958244853 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/common/debugger/signaldata/Makefile.in trunk/ndb/src/common/debugger/signaldata/Makefile.in
+--- trunk~/ndb/src/common/debugger/signaldata/Makefile.in	2007-11-15 08:08:26.000000000 -0600
++++ trunk/ndb/src/common/debugger/signaldata/Makefile.in	2007-12-27 15:54:48.958244853 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/common/logger/Makefile.in trunk/ndb/src/common/logger/Makefile.in
+--- trunk~/ndb/src/common/logger/Makefile.in	2007-11-15 08:08:26.000000000 -0600
++++ trunk/ndb/src/common/logger/Makefile.in	2007-12-27 15:54:48.958244853 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/common/mgmcommon/Makefile.in trunk/ndb/src/common/mgmcommon/Makefile.in
+--- trunk~/ndb/src/common/mgmcommon/Makefile.in	2007-11-15 08:08:26.000000000 -0600
++++ trunk/ndb/src/common/mgmcommon/Makefile.in	2007-12-27 15:54:48.962245081 -0600
+@@ -111,6 +111,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/common/portlib/Makefile.in trunk/ndb/src/common/portlib/Makefile.in
+--- trunk~/ndb/src/common/portlib/Makefile.in	2007-11-15 08:08:27.000000000 -0600
++++ trunk/ndb/src/common/portlib/Makefile.in	2007-12-27 15:54:48.962245081 -0600
+@@ -97,6 +97,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/common/transporter/Makefile.in trunk/ndb/src/common/transporter/Makefile.in
+--- trunk~/ndb/src/common/transporter/Makefile.in	2007-11-15 08:08:27.000000000 -0600
++++ trunk/ndb/src/common/transporter/Makefile.in	2007-12-27 15:54:48.962245081 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/common/util/Makefile.in trunk/ndb/src/common/util/Makefile.in
+--- trunk~/ndb/src/common/util/Makefile.in	2007-11-15 08:08:28.000000000 -0600
++++ trunk/ndb/src/common/util/Makefile.in	2007-12-27 15:54:48.962245081 -0600
+@@ -96,6 +96,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/cw/Makefile.in trunk/ndb/src/cw/Makefile.in
+--- trunk~/ndb/src/cw/Makefile.in	2007-11-15 08:08:28.000000000 -0600
++++ trunk/ndb/src/cw/Makefile.in	2007-12-27 15:54:48.966245309 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/cw/cpcd/Makefile.in trunk/ndb/src/cw/cpcd/Makefile.in
+--- trunk~/ndb/src/cw/cpcd/Makefile.in	2007-11-15 08:08:29.000000000 -0600
++++ trunk/ndb/src/cw/cpcd/Makefile.in	2007-12-27 15:54:48.966245309 -0600
+@@ -96,6 +96,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/Makefile.in trunk/ndb/src/kernel/Makefile.in
+--- trunk~/ndb/src/kernel/Makefile.in	2007-11-15 08:08:29.000000000 -0600
++++ trunk/ndb/src/kernel/Makefile.in	2007-12-27 15:54:48.966245309 -0600
+@@ -96,6 +96,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/Makefile.in trunk/ndb/src/kernel/blocks/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/Makefile.in	2007-11-15 08:08:29.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/Makefile.in	2007-12-27 15:54:48.966245309 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/backup/Makefile.in trunk/ndb/src/kernel/blocks/backup/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/backup/Makefile.in	2007-11-15 08:08:30.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/backup/Makefile.in	2007-12-27 15:54:48.970245537 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/cmvmi/Makefile.in trunk/ndb/src/kernel/blocks/cmvmi/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/cmvmi/Makefile.in	2007-11-15 08:08:30.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/cmvmi/Makefile.in	2007-12-27 15:54:48.970245537 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/dbacc/Makefile.in trunk/ndb/src/kernel/blocks/dbacc/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/dbacc/Makefile.in	2007-11-15 08:08:30.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/dbacc/Makefile.in	2007-12-27 15:54:48.970245537 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/dbdict/Makefile.in trunk/ndb/src/kernel/blocks/dbdict/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/dbdict/Makefile.in	2007-11-15 08:08:31.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/dbdict/Makefile.in	2007-12-27 15:54:48.970245537 -0600
+@@ -96,6 +96,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/dbdih/Makefile.in trunk/ndb/src/kernel/blocks/dbdih/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/dbdih/Makefile.in	2007-11-15 08:08:31.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/dbdih/Makefile.in	2007-12-27 15:54:48.974245765 -0600
+@@ -96,6 +96,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/dblqh/Makefile.in trunk/ndb/src/kernel/blocks/dblqh/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/dblqh/Makefile.in	2007-11-15 08:08:32.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/dblqh/Makefile.in	2007-12-27 15:54:48.974245765 -0600
+@@ -96,6 +96,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/dbtc/Makefile.in trunk/ndb/src/kernel/blocks/dbtc/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/dbtc/Makefile.in	2007-11-15 08:08:32.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/dbtc/Makefile.in	2007-12-27 15:54:48.974245765 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/dbtup/Makefile.in trunk/ndb/src/kernel/blocks/dbtup/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/dbtup/Makefile.in	2007-11-15 08:08:33.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/dbtup/Makefile.in	2007-12-27 15:54:48.974245765 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/dbtux/Makefile.in trunk/ndb/src/kernel/blocks/dbtux/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/dbtux/Makefile.in	2007-11-15 08:08:33.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/dbtux/Makefile.in	2007-12-27 15:54:49.006247589 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/dbutil/Makefile.in trunk/ndb/src/kernel/blocks/dbutil/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/dbutil/Makefile.in	2007-11-15 08:08:34.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/dbutil/Makefile.in	2007-12-27 15:54:49.006247589 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/ndbcntr/Makefile.in trunk/ndb/src/kernel/blocks/ndbcntr/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/ndbcntr/Makefile.in	2007-11-15 08:08:34.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/ndbcntr/Makefile.in	2007-12-27 15:54:49.006247589 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/ndbfs/Makefile.in trunk/ndb/src/kernel/blocks/ndbfs/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/ndbfs/Makefile.in	2007-11-15 08:08:34.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/ndbfs/Makefile.in	2007-12-27 15:54:49.010247817 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/qmgr/Makefile.in trunk/ndb/src/kernel/blocks/qmgr/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/qmgr/Makefile.in	2007-11-15 08:08:35.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/qmgr/Makefile.in	2007-12-27 15:54:49.018248273 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/suma/Makefile.in trunk/ndb/src/kernel/blocks/suma/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/suma/Makefile.in	2007-11-15 08:08:35.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/suma/Makefile.in	2007-12-27 15:54:49.018248273 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/blocks/trix/Makefile.in trunk/ndb/src/kernel/blocks/trix/Makefile.in
+--- trunk~/ndb/src/kernel/blocks/trix/Makefile.in	2007-11-15 08:08:36.000000000 -0600
++++ trunk/ndb/src/kernel/blocks/trix/Makefile.in	2007-12-27 15:54:49.018248273 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/error/Makefile.in trunk/ndb/src/kernel/error/Makefile.in
+--- trunk~/ndb/src/kernel/error/Makefile.in	2007-11-15 08:08:36.000000000 -0600
++++ trunk/ndb/src/kernel/error/Makefile.in	2007-12-27 15:54:49.030248957 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/kernel/vm/Makefile.in trunk/ndb/src/kernel/vm/Makefile.in
+--- trunk~/ndb/src/kernel/vm/Makefile.in	2007-11-15 08:08:36.000000000 -0600
++++ trunk/ndb/src/kernel/vm/Makefile.in	2007-12-27 15:54:49.030248957 -0600
+@@ -100,6 +100,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/mgmapi/Makefile.in trunk/ndb/src/mgmapi/Makefile.in
+--- trunk~/ndb/src/mgmapi/Makefile.in	2007-11-15 08:08:37.000000000 -0600
++++ trunk/ndb/src/mgmapi/Makefile.in	2007-12-27 15:54:49.030248957 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/mgmclient/Makefile.in trunk/ndb/src/mgmclient/Makefile.in
+--- trunk~/ndb/src/mgmclient/Makefile.in	2007-11-15 08:08:37.000000000 -0600
++++ trunk/ndb/src/mgmclient/Makefile.in	2007-12-27 15:54:49.042249641 -0600
+@@ -97,6 +97,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/mgmsrv/Makefile.in trunk/ndb/src/mgmsrv/Makefile.in
+--- trunk~/ndb/src/mgmsrv/Makefile.in	2007-11-15 08:08:38.000000000 -0600
++++ trunk/ndb/src/mgmsrv/Makefile.in	2007-12-27 15:54:49.110253516 -0600
+@@ -96,6 +96,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/src/ndbapi/Makefile.in trunk/ndb/src/ndbapi/Makefile.in
+--- trunk~/ndb/src/ndbapi/Makefile.in	2007-11-15 08:08:38.000000000 -0600
++++ trunk/ndb/src/ndbapi/Makefile.in	2007-12-27 15:54:49.170256935 -0600
+@@ -97,6 +97,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/test/Makefile.in trunk/ndb/test/Makefile.in
+--- trunk~/ndb/test/Makefile.in	2007-11-15 08:08:38.000000000 -0600
++++ trunk/ndb/test/Makefile.in	2007-12-27 15:54:49.170256935 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/test/ndbapi/Makefile.in trunk/ndb/test/ndbapi/Makefile.in
+--- trunk~/ndb/test/ndbapi/Makefile.in	2007-11-15 08:08:40.000000000 -0600
++++ trunk/ndb/test/ndbapi/Makefile.in	2007-12-27 15:54:49.174257163 -0600
+@@ -114,6 +114,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/test/ndbapi/bank/Makefile.in trunk/ndb/test/ndbapi/bank/Makefile.in
+--- trunk~/ndb/test/ndbapi/bank/Makefile.in	2007-11-15 08:08:40.000000000 -0600
++++ trunk/ndb/test/ndbapi/bank/Makefile.in	2007-12-27 15:54:49.174257163 -0600
+@@ -100,6 +100,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/test/run-test/Makefile.in trunk/ndb/test/run-test/Makefile.in
+--- trunk~/ndb/test/run-test/Makefile.in	2007-11-15 08:08:41.000000000 -0600
++++ trunk/ndb/test/run-test/Makefile.in	2007-12-27 15:54:49.174257163 -0600
+@@ -114,6 +114,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/test/src/Makefile.in trunk/ndb/test/src/Makefile.in
+--- trunk~/ndb/test/src/Makefile.in	2007-11-15 08:08:41.000000000 -0600
++++ trunk/ndb/test/src/Makefile.in	2007-12-27 15:54:49.178257391 -0600
+@@ -95,6 +95,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/test/tools/Makefile.in trunk/ndb/test/tools/Makefile.in
+--- trunk~/ndb/test/tools/Makefile.in	2007-11-15 08:08:42.000000000 -0600
++++ trunk/ndb/test/tools/Makefile.in	2007-12-27 15:54:49.178257391 -0600
+@@ -101,6 +101,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/ndb/tools/Makefile.in trunk/ndb/tools/Makefile.in
+--- trunk~/ndb/tools/Makefile.in	2007-11-15 08:08:42.000000000 -0600
++++ trunk/ndb/tools/Makefile.in	2007-12-27 15:54:49.178257391 -0600
+@@ -104,6 +104,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/netware/Makefile.in trunk/netware/Makefile.in
+--- trunk~/netware/Makefile.in	2007-11-15 08:08:43.000000000 -0600
++++ trunk/netware/Makefile.in	2007-12-27 15:54:49.250261494 -0600
+@@ -67,6 +67,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/os2/Makefile.in trunk/os2/Makefile.in
+--- trunk~/os2/Makefile.in	2007-11-15 08:08:43.000000000 -0600
++++ trunk/os2/Makefile.in	2007-12-27 15:54:49.254261722 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/os2/include/Makefile.in trunk/os2/include/Makefile.in
+--- trunk~/os2/include/Makefile.in	2007-11-15 08:08:44.000000000 -0600
++++ trunk/os2/include/Makefile.in	2007-12-27 15:54:49.254261722 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/os2/include/sys/Makefile.in trunk/os2/include/sys/Makefile.in
+--- trunk~/os2/include/sys/Makefile.in	2007-11-15 08:08:44.000000000 -0600
++++ trunk/os2/include/sys/Makefile.in	2007-12-27 15:54:49.254261722 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/pstack/Makefile.in trunk/pstack/Makefile.in
+--- trunk~/pstack/Makefile.in	2007-11-15 08:08:44.000000000 -0600
++++ trunk/pstack/Makefile.in	2007-12-27 15:54:49.254261722 -0600
+@@ -70,6 +70,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/pstack/aout/Makefile.in trunk/pstack/aout/Makefile.in
+--- trunk~/pstack/aout/Makefile.in	2007-11-15 08:08:45.000000000 -0600
++++ trunk/pstack/aout/Makefile.in	2007-12-27 15:54:49.254261722 -0600
+@@ -49,6 +49,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/regex/Makefile.in trunk/regex/Makefile.in
+--- trunk~/regex/Makefile.in	2007-11-15 08:08:45.000000000 -0600
++++ trunk/regex/Makefile.in	2007-12-27 15:54:49.258261950 -0600
+@@ -69,6 +69,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/scripts/Makefile.in trunk/scripts/Makefile.in
+--- trunk~/scripts/Makefile.in	2007-11-15 08:08:46.000000000 -0600
++++ trunk/scripts/Makefile.in	2007-12-27 15:54:49.258261950 -0600
+@@ -66,6 +66,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/server-tools/Makefile.in trunk/server-tools/Makefile.in
+--- trunk~/server-tools/Makefile.in	2007-11-15 08:08:46.000000000 -0600
++++ trunk/server-tools/Makefile.in	2007-12-27 15:54:49.258261950 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/server-tools/instance-manager/Makefile.in trunk/server-tools/instance-manager/Makefile.in
+--- trunk~/server-tools/instance-manager/Makefile.in	2007-11-15 08:08:46.000000000 -0600
++++ trunk/server-tools/instance-manager/Makefile.in	2007-12-27 15:54:49.258261950 -0600
+@@ -66,6 +66,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/sql/Makefile.am trunk/sql/Makefile.am
+--- trunk~/sql/Makefile.am	2007-11-15 08:06:51.000000000 -0600
++++ trunk/sql/Makefile.am	2007-12-27 15:54:49.262262178 -0600
+@@ -68,6 +68,7 @@
+ 			sql_array.h sql_cursor.h \
+ 			examples/ha_example.h ha_archive.h \
+ 			examples/ha_tina.h ha_blackhole.h  \
++			sphinx/ha_sphinx.h \
+ 			ha_federated.h
+ mysqld_SOURCES =	sql_lex.cc sql_handler.cc \
+ 			item.cc item_sum.cc item_buff.cc item_func.cc \
+@@ -105,6 +106,7 @@
+ 			sp_cache.cc parse_file.cc sql_trigger.cc \
+ 			examples/ha_example.cc ha_archive.cc \
+ 			examples/ha_tina.cc ha_blackhole.cc \
++			sphinx/ha_sphinx.cc \
+ 			ha_federated.cc
+ 
+ gen_lex_hash_SOURCES =	gen_lex_hash.cc
+diff -urNad trunk~/sql/Makefile.am.orig trunk/sql/Makefile.am.orig
+--- trunk~/sql/Makefile.am.orig	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/Makefile.am.orig	2007-12-27 15:54:49.262262178 -0600
+@@ -0,0 +1,179 @@
++# Copyright (C) 2000-2006 MySQL AB
++# 
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; version 2 of the License.
++# 
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++# 
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++
++#called from the top level Makefile
++
++MYSQLDATAdir =		$(localstatedir)
++MYSQLSHAREdir =		$(pkgdatadir)
++MYSQLBASEdir=		$(prefix)
++INCLUDES =		@ZLIB_INCLUDES@ \
++			@bdb_includes@ @innodb_includes@ @ndbcluster_includes@ \
++			-I$(top_builddir)/include -I$(top_srcdir)/include \
++			-I$(top_srcdir)/regex -I$(srcdir) \
++                        $(openssl_includes)
++WRAPLIBS=		@WRAPLIBS@
++SUBDIRS =		share
++libexec_PROGRAMS =	mysqld
++EXTRA_PROGRAMS =	gen_lex_hash
++bin_PROGRAMS =		mysql_tzinfo_to_sql
++gen_lex_hash_LDFLAGS =  @NOINST_LDFLAGS@
++LDADD =			$(top_builddir)/myisam/libmyisam.a \
++			$(top_builddir)/myisammrg/libmyisammrg.a \
++			$(top_builddir)/heap/libheap.a \
++			$(top_builddir)/vio/libvio.a \
++			$(top_builddir)/mysys/libmysys.a \
++			$(top_builddir)/dbug/libdbug.a \
++			$(top_builddir)/regex/libregex.a \
++			$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@ @NDB_SCI_LIBS@
++
++mysqld_LDADD =		@MYSQLD_EXTRA_LDFLAGS@ \
++			@bdb_libs@ @innodb_libs@ @pstack_libs@ \
++                        @innodb_system_libs@ \
++			@ndbcluster_libs@ @ndbcluster_system_libs@ \
++			$(LDADD)  $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ \
++			$(yassl_libs) $(openssl_libs) @MYSQLD_EXTRA_LIBS@
++
++noinst_HEADERS =	item.h item_func.h item_sum.h item_cmpfunc.h \
++			item_strfunc.h item_timefunc.h item_uniq.h \
++			item_create.h item_subselect.h item_row.h \
++			mysql_priv.h item_geofunc.h sql_bitmap.h \
++			procedure.h sql_class.h sql_lex.h sql_list.h \
++			sql_manager.h sql_map.h sql_string.h unireg.h \
++			sql_error.h field.h handler.h mysqld_suffix.h \
++ 			sql_profile.h \
++			ha_myisammrg.h\
++			ha_heap.h ha_myisam.h ha_berkeley.h ha_innodb.h \
++			ha_ndbcluster.h ha_ndbcluster_cond.h \
++			opt_range.h protocol.h \
++			sql_select.h structs.h table.h sql_udf.h hash_filo.h\
++			lex.h lex_symbol.h sql_acl.h sql_crypt.h  \
++			log_event.h sql_repl.h slave.h \
++			stacktrace.h sql_sort.h sql_cache.h set_var.h \
++			spatial.h gstream.h client_settings.h tzfile.h \
++                        tztime.h my_decimal.h\
++			sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
++			parse_file.h sql_view.h	sql_trigger.h \
++			sql_array.h sql_cursor.h \
++			examples/ha_example.h ha_archive.h \
++			examples/ha_tina.h ha_blackhole.h  \
++			ha_federated.h
++mysqld_SOURCES =	sql_lex.cc sql_handler.cc \
++			item.cc item_sum.cc item_buff.cc item_func.cc \
++			item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
++			thr_malloc.cc item_create.cc item_subselect.cc \
++			item_row.cc item_geofunc.cc \
++			field.cc strfunc.cc key.cc sql_class.cc sql_list.cc \
++			net_serv.cc protocol.cc sql_state.c \
++			lock.cc my_lock.c \
++			sql_string.cc sql_manager.cc sql_map.cc \
++			mysqld.cc password.c hash_filo.cc hostname.cc \
++			set_var.cc sql_parse.cc sql_yacc.yy \
++			sql_base.cc table.cc sql_select.cc sql_insert.cc \
++                        sql_prepare.cc sql_error.cc sql_locale.cc \
++			sql_profile.cc \
++			sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
++			procedure.cc item_uniq.cc sql_test.cc \
++			log.cc log_event.cc init.cc derror.cc sql_acl.cc \
++			unireg.cc des_key_file.cc \
++			discover.cc time.cc opt_range.cc opt_sum.cc \
++		   	records.cc filesort.cc handler.cc \
++		        ha_heap.cc ha_myisam.cc ha_myisammrg.cc \
++	                ha_berkeley.cc ha_innodb.cc \
++			ha_ndbcluster.cc ha_ndbcluster_cond.cc \
++			sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
++			sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
++			sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
++			slave.cc sql_repl.cc sql_union.cc sql_derived.cc \
++			client.c sql_client.cc mini_client_errors.c pack.c\
++			stacktrace.c repl_failsafe.h repl_failsafe.cc \
++			sql_olap.cc sql_view.cc \
++			gstream.cc spatial.cc sql_help.cc sql_cursor.cc \
++			tztime.cc my_time.c my_user.c my_decimal.cc\
++			sp_head.cc sp_pcontext.cc  sp_rcontext.cc sp.cc \
++			sp_cache.cc parse_file.cc sql_trigger.cc \
++			examples/ha_example.cc ha_archive.cc \
++			examples/ha_tina.cc ha_blackhole.cc \
++			ha_federated.cc
++
++gen_lex_hash_SOURCES =	gen_lex_hash.cc
++gen_lex_hash_LDADD =	$(LDADD) $(CXXLDFLAGS)
++mysql_tzinfo_to_sql_SOURCES =   mysql_tzinfo_to_sql.cc
++mysql_tzinfo_to_sql_LDADD =  @MYSQLD_EXTRA_LDFLAGS@ $(LDADD) $(CXXLDFLAGS)
++
++DEFS =			-DMYSQL_SERVER \
++			-DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
++			-DDATADIR="\"$(MYSQLDATAdir)\"" \
++			-DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
++			@DEFS@
++
++BUILT_SOURCES =		sql_yacc.cc sql_yacc.h lex_hash.h
++EXTRA_DIST =		$(BUILT_SOURCES) nt_servc.cc nt_servc.h \
++			message.mc examples/CMakeLists.txt CMakeLists.txt \
++			udf_example.c udf_example.def
++DISTCLEANFILES =        lex_hash.h sql_yacc.output
++
++AM_YFLAGS =		-d --debug --verbose
++
++mysql_tzinfo_to_sql.cc:
++	rm -f mysql_tzinfo_to_sql.cc
++	@LN_CP_F@ $(srcdir)/tztime.cc mysql_tzinfo_to_sql.cc
++
++link_sources: mysql_tzinfo_to_sql.cc
++	rm -f mini_client_errors.c
++	@LN_CP_F@ $(top_srcdir)/libmysql/errmsg.c mini_client_errors.c
++	rm -f pack.c
++	@LN_CP_F@ $(top_srcdir)/sql-common/pack.c pack.c
++	rm -f client.c
++	@LN_CP_F@ $(top_srcdir)/sql-common/client.c client.c
++	rm -f my_time.c
++	@LN_CP_F@ $(top_srcdir)/sql-common/my_time.c my_time.c
++	rm -f my_user.c
++	@LN_CP_F@ $(top_srcdir)/sql-common/my_user.c my_user.c
++
++mysql_tzinfo_to_sql.o:	$(mysql_tzinfo_to_sql_SOURCES)
++			$(CXXCOMPILE) -c $(INCLUDES) -DTZINFO2SQL $<
++
++# Try to get better dependencies for the grammar. Othervise really bad
++# things like different grammars for different pars of MySQL can
++# happen if you are unlucky.
++sql_yacc.cc:	sql_yacc.yy
++sql_yacc.h:	sql_yacc.yy
++
++# Be careful here, note that we use VPATH and might or might not have
++# a pregenerated "sql_yacc.cc" in $(srcdir) or one we just built in
++# $(builddir). And it has to work if $(srcdir) == $(builddir).
++sql_yacc.o:	sql_yacc.cc sql_yacc.h $(HEADERS)
++		@SED@ -e 's/__attribute__ ((__unused__))//' $< > sql_yacc.cc-new
++		@MV@ sql_yacc.cc-new sql_yacc.cc
++		@echo "Note: The following compile may take a long time."
++		@echo "If it fails, re-run configure with --with-low-memory"
++		$(CXXCOMPILE) $(LM_CFLAGS) -c sql_yacc.cc
++
++# This generates lex_hash.h
++# NOTE Built sources should depend on their sources not the tool
++# this avoid the rebuild of the built files in a source dist
++lex_hash.h:	gen_lex_hash.cc lex.h
++		$(MAKE) $(AM_MAKEFLAGS) gen_lex_hash$(EXEEXT)
++		./gen_lex_hash$(EXEEXT) > $@-t
++		$(MV) $@-t $@
++
++# For testing of udf_example.so
++noinst_LTLIBRARIES= udf_example.la
++udf_example_la_SOURCES= udf_example.c
++udf_example_la_LDFLAGS= -module -rpath $(pkglibdir)
++
++
++# Don't update the files from bitkeeper
++%::SCCS/s.%
+diff -urNad trunk~/sql/Makefile.in trunk/sql/Makefile.in
+--- trunk~/sql/Makefile.in	2007-11-15 08:08:48.000000000 -0600
++++ trunk/sql/Makefile.in	2007-12-27 15:54:49.262262178 -0600
+@@ -71,6 +71,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+@@ -152,7 +153,8 @@
+ 	sp_rcontext.$(OBJEXT) sp.$(OBJEXT) sp_cache.$(OBJEXT) \
+ 	parse_file.$(OBJEXT) sql_trigger.$(OBJEXT) \
+ 	ha_example.$(OBJEXT) ha_archive.$(OBJEXT) ha_tina.$(OBJEXT) \
+-	ha_blackhole.$(OBJEXT) ha_federated.$(OBJEXT)
++	ha_blackhole.$(OBJEXT) ha_sphinx.$(OBJEXT) \
++	ha_federated.$(OBJEXT)
+ mysqld_OBJECTS = $(am_mysqld_OBJECTS)
+ mysqld_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
+ 	$(am__DEPENDENCIES_2) $(am__DEPENDENCIES_2) \
+@@ -511,6 +513,7 @@
+ 			sql_array.h sql_cursor.h \
+ 			examples/ha_example.h ha_archive.h \
+ 			examples/ha_tina.h ha_blackhole.h  \
++			sphinx/ha_sphinx.h \
+ 			ha_federated.h
+ 
+ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
+@@ -549,6 +552,7 @@
+ 			sp_cache.cc parse_file.cc sql_trigger.cc \
+ 			examples/ha_example.cc ha_archive.cc \
+ 			examples/ha_tina.cc ha_blackhole.cc \
++			sphinx/ha_sphinx.cc \
+ 			ha_federated.cc
+ 
+ gen_lex_hash_SOURCES = gen_lex_hash.cc
+@@ -704,6 +708,7 @@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ha_myisammrg.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ha_ndbcluster.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ha_ndbcluster_cond.Po at am__quote@
++ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ha_sphinx.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ha_tina.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/handler.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/hash_filo.Po at am__quote@
+@@ -871,6 +876,20 @@
+ @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ @am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ha_tina.obj `if test -f 'examples/ha_tina.cc'; then $(CYGPATH_W) 'examples/ha_tina.cc'; else $(CYGPATH_W) '$(srcdir)/examples/ha_tina.cc'; fi`
+ 
++ha_sphinx.o: sphinx/ha_sphinx.cc
++ at am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ha_sphinx.o -MD -MP -MF $(DEPDIR)/ha_sphinx.Tpo -c -o ha_sphinx.o `test -f 'sphinx/ha_sphinx.cc' || echo '$(srcdir)/'`sphinx/ha_sphinx.cc
++ at am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/ha_sphinx.Tpo $(DEPDIR)/ha_sphinx.Po
++ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='sphinx/ha_sphinx.cc' object='ha_sphinx.o' libtool=no @AMDEPBACKSLASH@
++ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
++ at am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ha_sphinx.o `test -f 'sphinx/ha_sphinx.cc' || echo '$(srcdir)/'`sphinx/ha_sphinx.cc
++
++ha_sphinx.obj: sphinx/ha_sphinx.cc
++ at am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ha_sphinx.obj -MD -MP -MF $(DEPDIR)/ha_sphinx.Tpo -c -o ha_sphinx.obj `if test -f 'sphinx/ha_sphinx.cc'; then $(CYGPATH_W) 'sphinx/ha_sphinx.cc'; else $(CYGPATH_W) '$(srcdir)/sphinx/ha_sphinx.cc'; fi`
++ at am__fastdepCXX_TRUE@	mv -f $(DEPDIR)/ha_sphinx.Tpo $(DEPDIR)/ha_sphinx.Po
++ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='sphinx/ha_sphinx.cc' object='ha_sphinx.obj' libtool=no @AMDEPBACKSLASH@
++ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
++ at am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ha_sphinx.obj `if test -f 'sphinx/ha_sphinx.cc'; then $(CYGPATH_W) 'sphinx/ha_sphinx.cc'; else $(CYGPATH_W) '$(srcdir)/sphinx/ha_sphinx.cc'; fi`
++
+ .yy.cc:
+ 	$(YACCCOMPILE) $<
+ 	if test -f y.tab.h; then \
+diff -urNad trunk~/sql/handler.cc trunk/sql/handler.cc
+--- trunk~/sql/handler.cc	2007-11-15 08:06:32.000000000 -0600
++++ trunk/sql/handler.cc	2007-12-27 15:54:49.266262406 -0600
+@@ -77,6 +77,15 @@
+   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+   HTON_NO_FLAGS };
+ #endif
++#ifdef HAVE_SPHINX_DB
++#include "sphinx/ha_sphinx.h"
++extern handlerton sphinx_hton;
++#else
++handlerton sphinx_hton = { "SPHINX", SHOW_OPTION_NO, "SPHINX storage engine",
++  DB_TYPE_SPHINX_DB, NULL, 0, 0, NULL, NULL,
++  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++  HTON_NO_FLAGS };
++#endif
+ #ifdef HAVE_INNOBASE_DB
+ #include "ha_innodb.h"
+ extern handlerton innobase_hton;
+@@ -141,6 +150,7 @@
+   &example_hton,
+   &archive_hton,
+   &tina_hton,
++  &sphinx_hton,
+   &ndbcluster_hton,
+   &federated_hton,
+   &myisammrg_hton,
+@@ -341,6 +351,12 @@
+       return new (alloc) ha_tina(table);
+     return NULL;
+ #endif
++#ifdef HAVE_SPHINX_DB
++  case DB_TYPE_SPHINX_DB:
++    if (have_sphinx_db == SHOW_OPTION_YES)
++      return new (alloc) ha_sphinx(table);
++    return NULL;
++#endif
+ #ifdef HAVE_NDBCLUSTER_DB
+   case DB_TYPE_NDBCLUSTER:
+     if (have_ndbcluster == SHOW_OPTION_YES)
+diff -urNad trunk~/sql/handler.cc.orig trunk/sql/handler.cc.orig
+--- trunk~/sql/handler.cc.orig	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/handler.cc.orig	2007-12-27 15:54:49.270262634 -0600
+@@ -0,0 +1,2797 @@
++/* Copyright (C) 2000-2006 MySQL AB
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; version 2 of the License.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
++
++
++/* Handler-calling-functions */
++
++#ifdef USE_PRAGMA_IMPLEMENTATION
++#pragma implementation				// gcc: Class implementation
++#endif
++
++#include "mysql_priv.h"
++#include "ha_heap.h"
++#include "ha_myisam.h"
++#include "ha_myisammrg.h"
++
++
++/*
++  We have dummy hanldertons in case the handler has not been compiled
++  in. This will be removed in 5.1.
++*/
++#ifdef HAVE_BERKELEY_DB
++#include "ha_berkeley.h"
++extern handlerton berkeley_hton;
++#else
++handlerton berkeley_hton = { "BerkeleyDB", SHOW_OPTION_NO,
++  "Supports transactions and page-level locking", DB_TYPE_BERKELEY_DB, NULL,
++  0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++  NULL, NULL, HTON_NO_FLAGS };
++#endif
++#ifdef HAVE_BLACKHOLE_DB
++#include "ha_blackhole.h"
++extern handlerton blackhole_hton;
++#else
++handlerton blackhole_hton = { "BLACKHOLE", SHOW_OPTION_NO,
++  "/dev/null storage engine (anything you write to it disappears)",
++  DB_TYPE_BLACKHOLE_DB, NULL, 0, 0, NULL, NULL,
++  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++  HTON_NO_FLAGS };
++#endif
++#ifdef HAVE_EXAMPLE_DB
++#include "examples/ha_example.h"
++extern handlerton example_hton;
++#else
++handlerton example_hton = { "EXAMPLE", SHOW_OPTION_NO,
++  "Example storage engine",
++  DB_TYPE_EXAMPLE_DB, NULL, 0, 0, NULL, NULL,
++  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++  HTON_NO_FLAGS };
++#endif
++#if defined(HAVE_ARCHIVE_DB)
++#include "ha_archive.h"
++extern handlerton archive_hton;
++#else
++handlerton archive_hton = { "ARCHIVE", SHOW_OPTION_NO,
++  "Archive storage engine", DB_TYPE_ARCHIVE_DB, NULL, 0, 0, NULL, NULL,
++  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++  HTON_NO_FLAGS };
++#endif
++#ifdef HAVE_CSV_DB
++#include "examples/ha_tina.h"
++extern handlerton tina_hton;
++#else
++handlerton tina_hton = { "CSV", SHOW_OPTION_NO, "CSV storage engine",
++  DB_TYPE_CSV_DB, NULL, 0, 0, NULL, NULL,
++  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++  HTON_NO_FLAGS };
++#endif
++#ifdef HAVE_INNOBASE_DB
++#include "ha_innodb.h"
++extern handlerton innobase_hton;
++#else
++handlerton innobase_hton = { "InnoDB", SHOW_OPTION_NO,
++  "Supports transactions, row-level locking, and foreign keys",
++  DB_TYPE_INNODB, NULL, 0, 0, NULL, NULL,
++  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++  HTON_NO_FLAGS };
++#endif
++#ifdef HAVE_NDBCLUSTER_DB
++#include "ha_ndbcluster.h"
++extern handlerton ndbcluster_hton;
++#else
++handlerton ndbcluster_hton = { "ndbcluster", SHOW_OPTION_NO,
++  "Clustered, fault-tolerant, memory-based tables",
++  DB_TYPE_NDBCLUSTER, NULL, 0, 0, NULL, NULL,
++  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++  HTON_NO_FLAGS };
++#endif
++#ifdef HAVE_FEDERATED_DB
++#include "ha_federated.h"
++extern handlerton federated_hton;
++#else
++handlerton federated_hton = { "FEDERATED", SHOW_OPTION_NO,
++  "Federated MySQL storage engine", DB_TYPE_FEDERATED_DB, NULL, 0, 0, NULL,
++  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++  HTON_NO_FLAGS };
++#endif
++#include <myisampack.h>
++#include <errno.h>
++
++extern handlerton myisam_hton;
++extern handlerton myisammrg_hton;
++extern handlerton heap_hton;
++extern handlerton binlog_hton;
++
++/*
++  Obsolete
++*/
++handlerton isam_hton = { "ISAM", SHOW_OPTION_NO, "Obsolete storage engine",
++  DB_TYPE_ISAM, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++  NULL, NULL, NULL, NULL, NULL, NULL, HTON_NO_FLAGS };
++
++/* number of entries in handlertons[] */
++ulong total_ha;
++/* number of storage engines (from handlertons[]) that support 2pc */
++ulong total_ha_2pc;
++/* size of savepoint storage area (see ha_init) */
++ulong savepoint_alloc_size;
++
++/*
++  This array is used for processing compiled in engines.
++*/
++handlerton *sys_table_types[]=
++{
++  &myisam_hton,
++  &heap_hton,
++  &innobase_hton,
++  &berkeley_hton,
++  &blackhole_hton,
++  &example_hton,
++  &archive_hton,
++  &tina_hton,
++  &ndbcluster_hton,
++  &federated_hton,
++  &myisammrg_hton,
++  &binlog_hton,
++  &isam_hton,
++  NULL
++};
++
++struct show_table_alias_st sys_table_aliases[]=
++{
++  {"INNOBASE",	"InnoDB"},
++  {"NDB", "NDBCLUSTER"},
++  {"BDB", "BERKELEYDB"},
++  {"HEAP", "MEMORY"},
++  {"MERGE", "MRG_MYISAM"},
++  {NullS, NullS}
++};
++
++const char *ha_row_type[] = {
++  "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "?","?","?"
++};
++
++const char *tx_isolation_names[] =
++{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
++  NullS};
++TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
++			       tx_isolation_names, NULL};
++
++static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
++uint known_extensions_id= 0;
++
++enum db_type ha_resolve_by_name(const char *name, uint namelen)
++{
++  THD *thd= current_thd;
++  show_table_alias_st *table_alias;
++  handlerton **types;
++
++  if (thd && !my_strnncoll(&my_charset_latin1,
++                           (const uchar *)name, namelen,
++                           (const uchar *)"DEFAULT", 7))
++    return (enum db_type) thd->variables.table_type;
++
++retest:
++  for (types= sys_table_types; *types; types++)
++  {
++    if (!my_strnncoll(&my_charset_latin1,
++                      (const uchar *)name, namelen,
++                      (const uchar *)(*types)->name, strlen((*types)->name)))
++      return (enum db_type) (*types)->db_type;
++  }
++
++  /*
++    We check for the historical aliases.
++  */
++  for (table_alias= sys_table_aliases; table_alias->type; table_alias++)
++  {
++    if (!my_strnncoll(&my_charset_latin1,
++                      (const uchar *)name, namelen,
++                      (const uchar *)table_alias->alias,
++                      strlen(table_alias->alias)))
++    {
++      name= table_alias->type;
++      namelen= strlen(name);
++      goto retest;
++    }
++  }
++
++  return DB_TYPE_UNKNOWN;
++}
++
++
++const char *ha_get_storage_engine(enum db_type db_type)
++{
++  handlerton **types;
++  for (types= sys_table_types; *types; types++)
++  {
++    if (db_type == (*types)->db_type)
++      return (*types)->name;
++  }
++  return "*NONE*";
++}
++
++
++bool ha_check_storage_engine_flag(enum db_type db_type, uint32 flag)
++{
++  handlerton **types;
++  for (types= sys_table_types; *types; types++)
++  {
++    if (db_type == (*types)->db_type)
++      return test((*types)->flags & flag);
++  }
++  return FALSE;                                 // No matching engine
++}
++
++
++my_bool ha_storage_engine_is_enabled(enum db_type database_type)
++{
++  handlerton **types;
++  for (types= sys_table_types; *types; types++)
++  {
++    if ((database_type == (*types)->db_type) &&
++	((*types)->state == SHOW_OPTION_YES))
++      return TRUE;
++  }
++  return FALSE;
++}
++
++
++/* Use other database handler if databasehandler is not compiled in */
++
++enum db_type ha_checktype(THD *thd, enum db_type database_type,
++                          bool no_substitute, bool report_error)
++{
++  if (ha_storage_engine_is_enabled(database_type))
++    return database_type;
++
++  if (no_substitute)
++  {
++    if (report_error)
++    {
++      const char *engine_name= ha_get_storage_engine(database_type);
++      my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
++    }
++    return DB_TYPE_UNKNOWN;
++  }
++
++  switch (database_type) {
++#ifndef NO_HASH
++  case DB_TYPE_HASH:
++    return (database_type);
++#endif
++  case DB_TYPE_MRG_ISAM:
++    return (DB_TYPE_MRG_MYISAM);
++  default:
++    break;
++  }
++
++  return ((enum db_type) thd->variables.table_type != DB_TYPE_UNKNOWN ?
++          (enum db_type) thd->variables.table_type :
++          ((enum db_type) global_system_variables.table_type !=
++           DB_TYPE_UNKNOWN ?
++           (enum db_type) global_system_variables.table_type : DB_TYPE_MYISAM)
++          );
++} /* ha_checktype */
++
++
++handler *get_new_handler(TABLE *table, MEM_ROOT *alloc, enum db_type db_type)
++{
++  switch (db_type) {
++#ifndef NO_HASH
++  case DB_TYPE_HASH:
++    return new (alloc) ha_hash(table);
++#endif
++  case DB_TYPE_MRG_MYISAM:
++  case DB_TYPE_MRG_ISAM:
++    if (have_merge_db == SHOW_OPTION_YES)
++      return new (alloc) ha_myisammrg(table);
++    return NULL;
++#ifdef HAVE_BERKELEY_DB
++  case DB_TYPE_BERKELEY_DB:
++    if (have_berkeley_db == SHOW_OPTION_YES)
++      return new (alloc) ha_berkeley(table);
++    return NULL;
++#endif
++#ifdef HAVE_INNOBASE_DB
++  case DB_TYPE_INNODB:
++    if (have_innodb == SHOW_OPTION_YES)
++      return new (alloc) ha_innobase(table);
++    return NULL;
++#endif
++#ifdef HAVE_EXAMPLE_DB
++  case DB_TYPE_EXAMPLE_DB:
++    if (have_example_db == SHOW_OPTION_YES)
++      return new (alloc) ha_example(table);
++    return NULL;
++#endif
++#if defined(HAVE_ARCHIVE_DB)
++  case DB_TYPE_ARCHIVE_DB:
++    if (have_archive_db == SHOW_OPTION_YES)
++      return new (alloc) ha_archive(table);
++    return NULL;
++#endif
++#ifdef HAVE_BLACKHOLE_DB
++  case DB_TYPE_BLACKHOLE_DB:
++    if (have_blackhole_db == SHOW_OPTION_YES)
++      return new (alloc) ha_blackhole(table);
++    return NULL;
++#endif
++#ifdef HAVE_FEDERATED_DB
++  case DB_TYPE_FEDERATED_DB:
++    if (have_federated_db == SHOW_OPTION_YES)
++      return new (alloc) ha_federated(table);
++    return NULL;
++#endif
++#ifdef HAVE_CSV_DB
++  case DB_TYPE_CSV_DB:
++    if (have_csv_db == SHOW_OPTION_YES)
++      return new (alloc) ha_tina(table);
++    return NULL;
++#endif
++#ifdef HAVE_NDBCLUSTER_DB
++  case DB_TYPE_NDBCLUSTER:
++    if (have_ndbcluster == SHOW_OPTION_YES)
++      return new (alloc) ha_ndbcluster(table);
++    return NULL;
++#endif
++  case DB_TYPE_HEAP:
++    return new (alloc) ha_heap(table);
++  default:					// should never happen
++  {
++    enum db_type def=(enum db_type) current_thd->variables.table_type;
++    /* Try first with 'default table type' */
++    if (db_type != def)
++      return get_new_handler(table, alloc, def);
++  }
++  /* Fall back to MyISAM */
++  case DB_TYPE_MYISAM:
++    return new (alloc) ha_myisam(table);
++  }
++}
++
++/*
++  Register handler error messages for use with my_error().
++
++  SYNOPSIS
++    ha_init_errors()
++
++  RETURN
++    0           OK
++    != 0        Error
++*/
++
++static int ha_init_errors(void)
++{
++#define SETMSG(nr, msg) errmsgs[(nr) - HA_ERR_FIRST]= (msg)
++  const char    **errmsgs;
++
++  /* Allocate a pointer array for the error message strings. */
++  /* Zerofill it to avoid uninitialized gaps. */
++  if (! (errmsgs= (const char**) my_malloc(HA_ERR_ERRORS * sizeof(char*),
++                                           MYF(MY_WME | MY_ZEROFILL))))
++    return 1;
++
++  /* Set the dedicated error messages. */
++  SETMSG(HA_ERR_KEY_NOT_FOUND,          ER(ER_KEY_NOT_FOUND));
++  SETMSG(HA_ERR_FOUND_DUPP_KEY,         ER(ER_DUP_KEY));
++  SETMSG(HA_ERR_RECORD_CHANGED,         "Update wich is recoverable");
++  SETMSG(HA_ERR_WRONG_INDEX,            "Wrong index given to function");
++  SETMSG(HA_ERR_CRASHED,                ER(ER_NOT_KEYFILE));
++  SETMSG(HA_ERR_WRONG_IN_RECORD,        ER(ER_CRASHED_ON_USAGE));
++  SETMSG(HA_ERR_OUT_OF_MEM,             "Table handler out of memory");
++  SETMSG(HA_ERR_NOT_A_TABLE,            "Incorrect file format '%.64s'");
++  SETMSG(HA_ERR_WRONG_COMMAND,          "Command not supported");
++  SETMSG(HA_ERR_OLD_FILE,               ER(ER_OLD_KEYFILE));
++  SETMSG(HA_ERR_NO_ACTIVE_RECORD,       "No record read in update");
++  SETMSG(HA_ERR_RECORD_DELETED,         "Intern record deleted");
++  SETMSG(HA_ERR_RECORD_FILE_FULL,       ER(ER_RECORD_FILE_FULL));
++  SETMSG(HA_ERR_INDEX_FILE_FULL,        "No more room in index file '%.64s'");
++  SETMSG(HA_ERR_END_OF_FILE,            "End in next/prev/first/last");
++  SETMSG(HA_ERR_UNSUPPORTED,            ER(ER_ILLEGAL_HA));
++  SETMSG(HA_ERR_TO_BIG_ROW,             "Too big row");
++  SETMSG(HA_WRONG_CREATE_OPTION,        "Wrong create option");
++  SETMSG(HA_ERR_FOUND_DUPP_UNIQUE,      ER(ER_DUP_UNIQUE));
++  SETMSG(HA_ERR_UNKNOWN_CHARSET,        "Can't open charset");
++  SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF,    ER(ER_WRONG_MRG_TABLE));
++  SETMSG(HA_ERR_CRASHED_ON_REPAIR,      ER(ER_CRASHED_ON_REPAIR));
++  SETMSG(HA_ERR_CRASHED_ON_USAGE,       ER(ER_CRASHED_ON_USAGE));
++  SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT,      ER(ER_LOCK_WAIT_TIMEOUT));
++  SETMSG(HA_ERR_LOCK_TABLE_FULL,        ER(ER_LOCK_TABLE_FULL));
++  SETMSG(HA_ERR_READ_ONLY_TRANSACTION,  ER(ER_READ_ONLY_TRANSACTION));
++  SETMSG(HA_ERR_LOCK_DEADLOCK,          ER(ER_LOCK_DEADLOCK));
++  SETMSG(HA_ERR_CANNOT_ADD_FOREIGN,     ER(ER_CANNOT_ADD_FOREIGN));
++  SETMSG(HA_ERR_NO_REFERENCED_ROW,      ER(ER_NO_REFERENCED_ROW_2));
++  SETMSG(HA_ERR_ROW_IS_REFERENCED,      ER(ER_ROW_IS_REFERENCED_2));
++  SETMSG(HA_ERR_NO_SAVEPOINT,           "No savepoint with that name");
++  SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE,  "Non unique key block size");
++  SETMSG(HA_ERR_NO_SUCH_TABLE,          "No such table: '%.64s'");
++  SETMSG(HA_ERR_TABLE_EXIST,            ER(ER_TABLE_EXISTS_ERROR));
++  SETMSG(HA_ERR_NO_CONNECTION,          "Could not connect to storage engine");
++  SETMSG(HA_ERR_TABLE_DEF_CHANGED,      ER(ER_TABLE_DEF_CHANGED));
++  SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE,    ER(ER_TABLE_NEEDS_UPGRADE));
++  SETMSG(HA_ERR_TABLE_READONLY,         ER(ER_OPEN_AS_READONLY));
++  SETMSG(HA_ERR_AUTOINC_READ_FAILED,    ER(ER_AUTOINC_READ_FAILED));
++  SETMSG(HA_ERR_AUTOINC_ERANGE,         ER(ER_WARN_DATA_OUT_OF_RANGE));
++
++  /* Register the error messages for use with my_error(). */
++  return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
++}
++
++
++/*
++  Unregister handler error messages.
++
++  SYNOPSIS
++    ha_finish_errors()
++
++  RETURN
++    0           OK
++    != 0        Error
++*/
++
++static int ha_finish_errors(void)
++{
++  const char    **errmsgs;
++
++  /* Allocate a pointer array for the error message strings. */
++  if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
++    return 1;
++  my_free((gptr) errmsgs, MYF(0));
++  return 0;
++}
++
++
++static inline void ha_was_inited_ok(handlerton **ht)
++{
++  uint tmp= (*ht)->savepoint_offset;
++  (*ht)->savepoint_offset= savepoint_alloc_size;
++  savepoint_alloc_size+= tmp;
++  (*ht)->slot= total_ha++;
++  if ((*ht)->prepare)
++    total_ha_2pc++;
++}
++
++int ha_init()
++{
++  int error= 0;
++  handlerton **types;
++  total_ha= savepoint_alloc_size= 0;
++
++  if (ha_init_errors())
++    return 1;
++
++  /*
++    We now initialize everything here.
++  */
++  for (types= sys_table_types; *types; types++)
++  {
++    if (!(*types)->init || !(*types)->init())
++      ha_was_inited_ok(types);
++    else
++      (*types)->state= SHOW_OPTION_DISABLED;
++  }
++
++  DBUG_ASSERT(total_ha < MAX_HA);
++  /*
++    Check if there is a transaction-capable storage engine besides the
++    binary log (which is considered a transaction-capable storage engine in
++    counting total_ha)
++  */
++  opt_using_transactions= total_ha>(ulong)opt_bin_log;
++  savepoint_alloc_size+= sizeof(SAVEPOINT);
++  return error;
++}
++
++	/* close, flush or restart databases */
++	/* Ignore this for other databases than ours */
++
++int ha_panic(enum ha_panic_function flag)
++{
++  int error=0;
++#ifndef NO_HASH
++  error|=h_panic(flag);			/* fix hash */
++#endif
++#ifdef HAVE_ISAM
++  error|=mrg_panic(flag);
++  error|=nisam_panic(flag);
++#endif
++  error|=heap_panic(flag);
++  error|=mi_panic(flag);
++  error|=myrg_panic(flag);
++#ifdef HAVE_BERKELEY_DB
++  if (have_berkeley_db == SHOW_OPTION_YES)
++    error|=berkeley_end();
++#endif
++#ifdef HAVE_INNOBASE_DB
++  if (have_innodb == SHOW_OPTION_YES)
++    error|=innobase_end();
++#endif
++#ifdef HAVE_NDBCLUSTER_DB
++  if (have_ndbcluster == SHOW_OPTION_YES)
++    error|=ndbcluster_end();
++#endif
++#ifdef HAVE_FEDERATED_DB
++  if (have_federated_db == SHOW_OPTION_YES)
++    error|= federated_db_end();
++#endif
++#if defined(HAVE_ARCHIVE_DB)
++  if (have_archive_db == SHOW_OPTION_YES)
++    error|= archive_db_end();
++#endif
++#ifdef HAVE_CSV_DB
++  if (have_csv_db == SHOW_OPTION_YES)
++    error|= tina_end();
++#endif
++  if (ha_finish_errors())
++    error= 1;
++  return error;
++} /* ha_panic */
++
++void ha_drop_database(char* path)
++{
++#ifdef HAVE_INNOBASE_DB
++  if (have_innodb == SHOW_OPTION_YES)
++    innobase_drop_database(path);
++#endif
++#ifdef HAVE_NDBCLUSTER_DB
++  if (have_ndbcluster == SHOW_OPTION_YES)
++    ndbcluster_drop_database(path);
++#endif
++}
++
++/* don't bother to rollback here, it's done already */
++void ha_close_connection(THD* thd)
++{
++  handlerton **types;
++  for (types= sys_table_types; *types; types++)
++    if (thd->ha_data[(*types)->slot])
++      (*types)->close_connection(thd);
++}
++
++/* ========================================================================
++ ======================= TRANSACTIONS ===================================*/
++
++/*
++  Register a storage engine for a transaction
++
++  DESCRIPTION
++    Every storage engine MUST call this function when it starts
++    a transaction or a statement (that is it must be called both for the
++    "beginning of transaction" and "beginning of statement").
++    Only storage engines registered for the transaction/statement
++    will know when to commit/rollback it.
++
++  NOTE
++    trans_register_ha is idempotent - storage engine may register many
++    times per transaction.
++
++*/
++void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
++{
++  THD_TRANS *trans;
++  handlerton **ht;
++  DBUG_ENTER("trans_register_ha");
++  DBUG_PRINT("enter",("%s", all ? "all" : "stmt"));
++
++  if (all)
++  {
++    trans= &thd->transaction.all;
++    thd->server_status|= SERVER_STATUS_IN_TRANS;
++  }
++  else
++    trans= &thd->transaction.stmt;
++
++  for (ht=trans->ht; *ht; ht++)
++    if (*ht == ht_arg)
++      DBUG_VOID_RETURN;  /* already registered, return */
++
++  trans->ht[trans->nht++]=ht_arg;
++  DBUG_ASSERT(*ht == ht_arg);
++  trans->no_2pc|=(ht_arg->prepare==0);
++  if (thd->transaction.xid_state.xid.is_null())
++    thd->transaction.xid_state.xid.set(thd->query_id);
++  DBUG_VOID_RETURN;
++}
++
++/*
++  RETURN
++      0  - ok
++      1  - error, transaction was rolled back
++*/
++int ha_prepare(THD *thd)
++{
++  int error=0, all=1;
++  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
++  handlerton **ht=trans->ht;
++  DBUG_ENTER("ha_prepare");
++#ifdef USING_TRANSACTIONS
++  if (trans->nht)
++  {
++    for (; *ht; ht++)
++    {
++      int err;
++      statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status);
++      if ((*ht)->prepare)
++      {
++        if ((err= (*(*ht)->prepare)(thd, all)))
++        {
++          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
++          ha_rollback_trans(thd, all);
++          error=1;
++          break;
++        }
++      }
++      else
++      {
++        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), (*ht)->name);
++      }
++    }
++  }
++#endif /* USING_TRANSACTIONS */
++  DBUG_RETURN(error);
++}
++
++/*
++  RETURN
++      0  - ok
++      1  - transaction was rolled back
++      2  - error during commit, data may be inconsistent
++*/
++int ha_commit_trans(THD *thd, bool all)
++{
++  int error= 0, cookie= 0;
++  THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
++  bool is_real_trans= all || thd->transaction.all.nht == 0;
++  handlerton **ht= trans->ht;
++  my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
++  DBUG_ENTER("ha_commit_trans");
++
++  if (thd->in_sub_stmt)
++  {
++    /*
++      Since we don't support nested statement transactions in 5.0,
++      we can't commit or rollback stmt transactions while we are inside
++      stored functions or triggers. So we simply do nothing now.
++      TODO: This should be fixed in later ( >= 5.1) releases.
++    */
++    if (!all)
++      DBUG_RETURN(0);
++    /*
++      We assume that all statements which commit or rollback main transaction
++      are prohibited inside of stored functions or triggers. So they should
++      bail out with error even before ha_commit_trans() call. To be 100% safe
++      let us throw error in non-debug builds.
++    */
++    DBUG_ASSERT(0);
++    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
++    DBUG_RETURN(2);
++  }
++#ifdef USING_TRANSACTIONS
++  if (trans->nht)
++  {
++    if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
++    {
++      ha_rollback_trans(thd, all);
++      DBUG_RETURN(1);
++    }
++    DBUG_EXECUTE_IF("crash_commit_before", abort(););
++
++    /* Close all cursors that can not survive COMMIT */
++    if (is_real_trans)                          /* not a statement commit */
++      thd->stmt_map.close_transient_cursors();
++
++    if (!trans->no_2pc && trans->nht > 1)
++    {
++      for (; *ht && !error; ht++)
++      {
++        int err;
++        if ((err= (*(*ht)->prepare)(thd, all)))
++        {
++          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
++          error= 1;
++        }
++        statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status);
++      }
++      DBUG_EXECUTE_IF("crash_commit_after_prepare", abort(););
++      if (error || (is_real_trans && xid &&
++                    (error= !(cookie= tc_log->log_xid(thd, xid)))))
++      {
++        ha_rollback_trans(thd, all);
++        error= 1;
++        goto end;
++      }
++      DBUG_EXECUTE_IF("crash_commit_after_log", abort(););
++    }
++    error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
++    DBUG_EXECUTE_IF("crash_commit_before_unlog", abort(););
++    if (cookie)
++      tc_log->unlog(cookie, xid);
++    DBUG_EXECUTE_IF("crash_commit_after", abort(););
++end:
++    if (is_real_trans)
++      start_waiting_global_read_lock(thd);
++  }
++#endif /* USING_TRANSACTIONS */
++  DBUG_RETURN(error);
++}
++
++/*
++  NOTE - this function does not care about global read lock.
++  A caller should.
++*/
++int ha_commit_one_phase(THD *thd, bool all)
++{
++  int error=0;
++  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
++  bool is_real_trans=all || thd->transaction.all.nht == 0;
++  handlerton **ht=trans->ht;
++  DBUG_ENTER("ha_commit_one_phase");
++#ifdef USING_TRANSACTIONS
++  if (trans->nht)
++  {
++    for (ht=trans->ht; *ht; ht++)
++    {
++      int err;
++      if ((err= (*(*ht)->commit)(thd, all)))
++      {
++        my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
++        error=1;
++      }
++      statistic_increment(thd->status_var.ha_commit_count,&LOCK_status);
++      *ht= 0;
++    }
++    trans->nht=0;
++    trans->no_2pc=0;
++    if (is_real_trans)
++      thd->transaction.xid_state.xid.null();
++    if (all)
++    {
++#ifdef HAVE_QUERY_CACHE
++      if (thd->transaction.changed_tables)
++        query_cache.invalidate(thd->transaction.changed_tables);
++#endif
++      thd->variables.tx_isolation=thd->session_tx_isolation;
++      thd->transaction.cleanup();
++    }
++  }
++#endif /* USING_TRANSACTIONS */
++  DBUG_RETURN(error);
++}
++
++
++int ha_rollback_trans(THD *thd, bool all)
++{
++  int error=0;
++  THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
++  bool is_real_trans=all || thd->transaction.all.nht == 0;
++  DBUG_ENTER("ha_rollback_trans");
++  if (thd->in_sub_stmt)
++  {
++    /*
++      If we are inside stored function or trigger we should not commit or
++      rollback current statement transaction. See comment in ha_commit_trans()
++      call for more information.
++    */
++    if (!all)
++      DBUG_RETURN(0);
++    DBUG_ASSERT(0);
++    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
++    DBUG_RETURN(1);
++  }
++#ifdef USING_TRANSACTIONS
++  if (trans->nht)
++  {
++    /* Close all cursors that can not survive ROLLBACK */
++    if (is_real_trans)                          /* not a statement commit */
++      thd->stmt_map.close_transient_cursors();
++
++    for (handlerton **ht=trans->ht; *ht; ht++)
++    {
++      int err;
++      if ((err= (*(*ht)->rollback)(thd, all)))
++      { // cannot happen
++        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
++        error=1;
++      }
++      statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status);
++      *ht= 0;
++    }
++    trans->nht=0;
++    trans->no_2pc=0;
++    if (is_real_trans)
++      thd->transaction.xid_state.xid.null();
++    if (all)
++    {
++      thd->variables.tx_isolation=thd->session_tx_isolation;
++      thd->transaction.cleanup();
++    }
++  }
++#endif /* USING_TRANSACTIONS */
++  if (all)
++    thd->transaction_rollback_request= FALSE;
++
++  /*
++    If a non-transactional table was updated, warn; don't warn if this is a
++    slave thread (because when a slave thread executes a ROLLBACK, it has
++    been read from the binary log, so it's 100% sure and normal to produce
++    error ER_WARNING_NOT_COMPLETE_ROLLBACK. If we sent the warning to the
++    slave SQL thread, it would not stop the thread but just be printed in
++    the error log; but we don't want users to wonder why they have this
++    message in the error log, so we don't send it.
++  */
++  if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
++      !thd->slave_thread)
++    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
++                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
++  DBUG_RETURN(error);
++}
++
++/*
++  This is used to commit or rollback a single statement depending on the value
++  of error. Note that if the autocommit is on, then the following call inside
++  InnoDB will commit or rollback the whole transaction (= the statement). The
++  autocommit mechanism built into InnoDB is based on counting locks, but if
++  the user has used LOCK TABLES then that mechanism does not know to do the
++  commit.
++*/
++
++int ha_autocommit_or_rollback(THD *thd, int error)
++{
++  DBUG_ENTER("ha_autocommit_or_rollback");
++#ifdef USING_TRANSACTIONS
++  if (thd->transaction.stmt.nht)
++  {
++    if (!error)
++    {
++      if (ha_commit_stmt(thd))
++	error=1;
++    }
++    else if (thd->transaction_rollback_request && !thd->in_sub_stmt)
++      (void) ha_rollback(thd);
++    else
++      (void) ha_rollback_stmt(thd);
++
++    thd->variables.tx_isolation=thd->session_tx_isolation;
++  }
++#endif
++  DBUG_RETURN(error);
++}
++
++
++int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
++{
++  handlerton **types;
++  int res= 1;
++
++  for (types= sys_table_types; *types; types++)
++  {
++    if ((*types)->state == SHOW_OPTION_YES && (*types)->recover)
++    {
++      if ((*(commit ? (*types)->commit_by_xid :
++             (*types)->rollback_by_xid))(xid))
++        res= 0;
++    }
++  }
++  return res;
++}
++
++
++#ifndef DBUG_OFF
++/* this does not need to be multi-byte safe or anything */
++static char* xid_to_str(char *buf, XID *xid)
++{
++  int i;
++  char *s=buf;
++  *s++='\'';
++  for (i=0; i < xid->gtrid_length+xid->bqual_length; i++)
++  {
++    uchar c=(uchar)xid->data[i];
++    /* is_next_dig is set if next character is a number */
++    bool is_next_dig= FALSE;
++    if (i < XIDDATASIZE)
++    {
++      char ch= xid->data[i+1];
++      is_next_dig= (ch >= '0' && ch <='9');
++    }
++    if (i == xid->gtrid_length)
++    {
++      *s++='\'';
++      if (xid->bqual_length)
++      {
++        *s++='.';
++        *s++='\'';
++      }
++    }
++    if (c < 32 || c > 126)
++    {
++      *s++='\\';
++      /*
++        If next character is a number, write current character with
++        3 octal numbers to ensure that the next number is not seen
++        as part of the octal number
++      */
++      if (c > 077 || is_next_dig)
++        *s++=_dig_vec_lower[c >> 6];
++      if (c > 007 || is_next_dig)
++        *s++=_dig_vec_lower[(c >> 3) & 7];
++      *s++=_dig_vec_lower[c & 7];
++    }
++    else
++    {
++      if (c == '\'' || c == '\\')
++        *s++='\\';
++      *s++=c;
++    }
++  }
++  *s++='\'';
++  *s=0;
++  return buf;
++}
++#endif
++
++/*
++  recover() step of xa
++
++  NOTE
++   there are three modes of operation:
++
++   - automatic recover after a crash
++     in this case commit_list != 0, tc_heuristic_recover==0
++     all xids from commit_list are committed, others are rolled back
++
++   - manual (heuristic) recover
++     in this case commit_list==0, tc_heuristic_recover != 0
++     DBA has explicitly specified that all prepared transactions should
++     be committed (or rolled back).
++
++   - no recovery (MySQL did not detect a crash)
++     in this case commit_list==0, tc_heuristic_recover == 0
++     there should be no prepared transactions in this case.
++*/
++int ha_recover(HASH *commit_list)
++{
++  int len, got, found_foreign_xids=0, found_my_xids=0;
++  handlerton **types;
++  XID *list=0;
++  bool dry_run=(commit_list==0 && tc_heuristic_recover==0);
++  DBUG_ENTER("ha_recover");
++
++  /* commit_list and tc_heuristic_recover cannot be set both */
++  DBUG_ASSERT(commit_list==0 || tc_heuristic_recover==0);
++  /* if either is set, total_ha_2pc must be set too */
++  DBUG_ASSERT(dry_run || total_ha_2pc>(ulong)opt_bin_log);
++
++  if (total_ha_2pc <= (ulong)opt_bin_log)
++    DBUG_RETURN(0);
++
++  if (commit_list)
++    sql_print_information("Starting crash recovery...");
++
++#ifndef WILL_BE_DELETED_LATER
++  /*
++    for now, only InnoDB supports 2pc. It means we can always safely
++    rollback all pending transactions, without risking inconsistent data
++  */
++  DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
++  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
++  dry_run=FALSE;
++#endif
++
++  for (len= MAX_XID_LIST_SIZE ; list==0 && len > MIN_XID_LIST_SIZE; len/=2)
++  {
++    list=(XID *)my_malloc(len*sizeof(XID), MYF(0));
++  }
++  if (!list)
++  {
++    sql_print_error(ER(ER_OUTOFMEMORY), len*sizeof(XID));
++    DBUG_RETURN(1);
++  }
++
++  for (types= sys_table_types; *types; types++)
++  {
++    if ((*types)->state != SHOW_OPTION_YES || !(*types)->recover)
++      continue;
++    while ((got=(*(*types)->recover)(list, len)) > 0 )
++    {
++      sql_print_information("Found %d prepared transaction(s) in %s",
++                            got, (*types)->name);
++      for (int i=0; i < got; i ++)
++      {
++        my_xid x=list[i].get_my_xid();
++        if (!x) // not "mine" - that is generated by external TM
++        {
++#ifndef DBUG_OFF
++          char buf[XIDDATASIZE*4+6]; // see xid_to_str
++          sql_print_information("ignore xid %s", xid_to_str(buf, list+i));
++#endif
++          xid_cache_insert(list+i, XA_PREPARED);
++          found_foreign_xids++;
++          continue;
++        }
++        if (dry_run)
++        {
++          found_my_xids++;
++          continue;
++        }
++        // recovery mode
++        if (commit_list ?
++            hash_search(commit_list, (byte *)&x, sizeof(x)) != 0 :
++            tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
++        {
++#ifndef DBUG_OFF
++          char buf[XIDDATASIZE*4+6]; // see xid_to_str
++          sql_print_information("commit xid %s", xid_to_str(buf, list+i));
++#endif
++          (*(*types)->commit_by_xid)(list+i);
++        }
++        else
++        {
++#ifndef DBUG_OFF
++          char buf[XIDDATASIZE*4+6]; // see xid_to_str
++          sql_print_information("rollback xid %s", xid_to_str(buf, list+i));
++#endif
++          (*(*types)->rollback_by_xid)(list+i);
++        }
++      }
++      if (got < len)
++        break;
++    }
++  }
++  my_free((gptr)list, MYF(0));
++  if (found_foreign_xids)
++    sql_print_warning("Found %d prepared XA transactions", found_foreign_xids);
++  if (dry_run && found_my_xids)
++  {
++    sql_print_error("Found %d prepared transactions! It means that mysqld was "
++                    "not shut down properly last time and critical recovery "
++                    "information (last binlog or %s file) was manually deleted "
++                    "after a crash. You have to start mysqld with "
++                    "--tc-heuristic-recover switch to commit or rollback "
++                    "pending transactions.",
++                    found_my_xids, opt_tc_log_file);
++    DBUG_RETURN(1);
++  }
++  if (commit_list)
++    sql_print_information("Crash recovery finished.");
++  DBUG_RETURN(0);
++}
++
++/*
++  return the list of XID's to a client, the same way SHOW commands do
++
++  NOTE
++    I didn't find in XA specs that an RM cannot return the same XID twice,
++    so mysql_xa_recover does not filter XID's to ensure uniqueness.
++    It can be easily fixed later, if necessary.
++*/
++bool mysql_xa_recover(THD *thd)
++{
++  List<Item> field_list;
++  Protocol *protocol= thd->protocol;
++  int i=0;
++  XID_STATE *xs;
++  DBUG_ENTER("mysql_xa_recover");
++
++  field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
++  field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
++  field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
++  field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
++
++  if (protocol->send_fields(&field_list,
++                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
++    DBUG_RETURN(1);
++
++  pthread_mutex_lock(&LOCK_xid_cache);
++  while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
++  {
++    if (xs->xa_state==XA_PREPARED)
++    {
++      protocol->prepare_for_resend();
++      protocol->store_longlong((longlong)xs->xid.formatID, FALSE);
++      protocol->store_longlong((longlong)xs->xid.gtrid_length, FALSE);
++      protocol->store_longlong((longlong)xs->xid.bqual_length, FALSE);
++      protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
++                      &my_charset_bin);
++      if (protocol->write())
++      {
++        pthread_mutex_unlock(&LOCK_xid_cache);
++        DBUG_RETURN(1);
++      }
++    }
++  }
++
++  pthread_mutex_unlock(&LOCK_xid_cache);
++  send_eof(thd);
++  DBUG_RETURN(0);
++}
++
++/*
++  This function should be called when MySQL sends rows of a SELECT result set
++  or the EOF mark to the client. It releases a possible adaptive hash index
++  S-latch held by thd in InnoDB and also releases a possible InnoDB query
++  FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
++  keep them over several calls of the InnoDB handler interface when a join
++  is executed. But when we let the control to pass to the client they have
++  to be released because if the application program uses mysql_use_result(),
++  it may deadlock on the S-latch if the application on another connection
++  performs another SQL query. In MySQL-4.1 this is even more important because
++  there a connection can have several SELECT queries open at the same time.
++
++  arguments:
++  thd:           the thread handle of the current connection
++  return value:  always 0
++*/
++
++int ha_release_temporary_latches(THD *thd)
++{
++#ifdef HAVE_INNOBASE_DB
++  if (opt_innodb)
++    innobase_release_temporary_latches(thd);
++#endif
++  return 0;
++}
++
++
++/*
++  Export statistics for different engines. Currently we use it only for
++  InnoDB.
++*/
++
++int ha_update_statistics()
++{
++#ifdef HAVE_INNOBASE_DB
++  if (opt_innodb)
++    innodb_export_status();
++#endif
++  return 0;
++}
++
++int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
++{
++  int error=0;
++  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
++                                        &thd->transaction.all);
++  handlerton **ht=trans->ht, **end_ht;
++  DBUG_ENTER("ha_rollback_to_savepoint");
++
++  trans->nht=sv->nht;
++  trans->no_2pc=0;
++  end_ht=ht+sv->nht;
++  /*
++    rolling back to savepoint in all storage engines that were part of the
++    transaction when the savepoint was set
++  */
++  for (; ht < end_ht; ht++)
++  {
++    int err;
++    DBUG_ASSERT((*ht)->savepoint_set != 0);
++    if ((err= (*(*ht)->savepoint_rollback)(thd, (byte *)(sv+1)+(*ht)->savepoint_offset)))
++    { // cannot happen
++      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
++      error=1;
++    }
++    statistic_increment(thd->status_var.ha_savepoint_rollback_count,&LOCK_status);
++    trans->no_2pc|=(*ht)->prepare == 0;
++  }
++  /*
++    rolling back the transaction in all storage engines that were not part of
++    the transaction when the savepoint was set
++  */
++  for (; *ht ; ht++)
++  {
++    int err;
++    if ((err= (*(*ht)->rollback)(thd, !thd->in_sub_stmt)))
++    { // cannot happen
++      my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
++      error=1;
++    }
++    statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status);
++    *ht=0; // keep it conveniently zero-filled
++  }
++  DBUG_RETURN(error);
++}
++
++/*
++  note, that according to the sql standard (ISO/IEC 9075-2:2003)
++  section "4.33.4 SQL-statements and transaction states",
++  SAVEPOINT is *not* transaction-initiating SQL-statement
++*/
++
++int ha_savepoint(THD *thd, SAVEPOINT *sv)
++{
++  int error=0;
++  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
++                                        &thd->transaction.all);
++  handlerton **ht=trans->ht;
++  DBUG_ENTER("ha_savepoint");
++#ifdef USING_TRANSACTIONS
++  for (; *ht; ht++)
++  {
++    int err;
++    if (! (*ht)->savepoint_set)
++    {
++      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
++      error=1;
++      break;
++    }
++    if ((err= (*(*ht)->savepoint_set)(thd, (byte *)(sv+1)+(*ht)->savepoint_offset)))
++    { // cannot happen
++      my_error(ER_GET_ERRNO, MYF(0), err);
++      error=1;
++    }
++    statistic_increment(thd->status_var.ha_savepoint_count,&LOCK_status);
++  }
++  sv->nht=trans->nht;
++#endif /* USING_TRANSACTIONS */
++  DBUG_RETURN(error);
++}
++
++int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
++{
++  int error=0;
++  THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
++                                        &thd->transaction.all);
++  handlerton **ht=trans->ht, **end_ht;
++  DBUG_ENTER("ha_release_savepoint");
++
++  end_ht=ht+sv->nht;
++  for (; ht < end_ht; ht++)
++  {
++    int err;
++    if (!(*ht)->savepoint_release)
++      continue;
++    if ((err= (*(*ht)->savepoint_release)(thd, (byte *)(sv+1)+(*ht)->savepoint_offset)))
++    { // cannot happen
++      my_error(ER_GET_ERRNO, MYF(0), err);
++      error=1;
++    }
++  }
++  DBUG_RETURN(error);
++}
++
++
++int ha_start_consistent_snapshot(THD *thd)
++{
++#ifdef HAVE_INNOBASE_DB
++  if ((have_innodb == SHOW_OPTION_YES) &&
++      !innobase_start_trx_and_assign_read_view(thd))
++    return 0;
++#endif
++  /*
++    Same idea as when one wants to CREATE TABLE in one engine which does not
++    exist:
++  */
++  push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
++               "This MySQL server does not support any "
++               "consistent-read capable storage engine");
++  return 0;
++}
++
++
++bool ha_flush_logs()
++{
++  bool result=0;
++#ifdef HAVE_BERKELEY_DB
++  if ((have_berkeley_db == SHOW_OPTION_YES) &&
++      berkeley_flush_logs())
++    result=1;
++#endif
++#ifdef HAVE_INNOBASE_DB
++  if ((have_innodb == SHOW_OPTION_YES) &&
++      innobase_flush_logs())
++    result=1;
++#endif
++  return result;
++}
++
++/*
++  This should return ENOENT if the file doesn't exists.
++  The .frm file will be deleted only if we return 0 or ENOENT
++*/
++
++int ha_delete_table(THD *thd, enum db_type table_type, const char *path,
++                    const char *alias, bool generate_warning)
++{
++  handler *file;
++  char tmp_path[FN_REFLEN];
++  int error;
++  TABLE dummy_table;
++  TABLE_SHARE dummy_share;
++  DBUG_ENTER("ha_delete_table");
++
++  bzero((char*) &dummy_table, sizeof(dummy_table));
++  bzero((char*) &dummy_share, sizeof(dummy_share));
++  dummy_table.s= &dummy_share;
++
++  /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
++  if (table_type == DB_TYPE_UNKNOWN ||
++      ! (file=get_new_handler(&dummy_table, thd->mem_root, table_type)))
++    DBUG_RETURN(ENOENT);
++
++  if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
++  {
++    /* Ensure that table handler get path in lower case */
++    strmov(tmp_path, path);
++    my_casedn_str(files_charset_info, tmp_path);
++    path= tmp_path;
++  }
++  if ((error= file->delete_table(path)) && generate_warning)
++  {
++    /*
++      Because file->print_error() use my_error() to generate the error message
++      we must store the error state in thd, reset it and restore it to
++      be able to get hold of the error message.
++      (We should in the future either rewrite handler::print_error() or make
++      a nice method of this.
++    */
++    bool query_error= thd->query_error;
++    sp_rcontext *spcont= thd->spcont;
++    SELECT_LEX *current_select= thd->lex->current_select;
++    char buff[sizeof(thd->net.last_error)];
++    char new_error[sizeof(thd->net.last_error)];
++    int last_errno= thd->net.last_errno;
++
++    strmake(buff, thd->net.last_error, sizeof(buff)-1);
++    thd->query_error= 0;
++    thd->spcont= NULL;
++    thd->lex->current_select= 0;
++    thd->net.last_error[0]= 0;
++
++    /* Fill up strucutures that print_error may need */
++    dummy_table.s->path= path;
++    dummy_table.alias= alias;
++
++    file->print_error(error, 0);
++    strmake(new_error, thd->net.last_error, sizeof(buff)-1);
++
++    /* restore thd */
++    thd->query_error= query_error;
++    thd->spcont= spcont;
++    thd->lex->current_select= current_select;
++    thd->net.last_errno= last_errno;
++    strmake(thd->net.last_error, buff, sizeof(buff)-1);
++    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, new_error);
++  }
++  delete file;
++  DBUG_RETURN(error);
++}
++
++/****************************************************************************
++** General handler functions
++****************************************************************************/
++handler *handler::clone(MEM_ROOT *mem_root)
++{
++  handler *new_handler= get_new_handler(table, mem_root, table->s->db_type);
++  if (new_handler && !new_handler->ha_open(table->s->path, table->db_stat,
++                                           HA_OPEN_IGNORE_IF_LOCKED))
++    return new_handler;
++  return NULL;
++}
++
++
++	/* Open database-handler. Try O_RDONLY if can't open as O_RDWR */
++	/* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */
++
++int handler::ha_open(const char *name, int mode, int test_if_locked)
++{
++  int error;
++  DBUG_ENTER("handler::ha_open");
++  DBUG_PRINT("enter",("name: %s  db_type: %d  db_stat: %d  mode: %d  lock_test: %d",
++                      name, table->s->db_type, table->db_stat, mode,
++                      test_if_locked));
++
++  if ((error=open(name,mode,test_if_locked)))
++  {
++    if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
++	(table->db_stat & HA_TRY_READ_ONLY))
++    {
++      table->db_stat|=HA_READ_ONLY;
++      error=open(name,O_RDONLY,test_if_locked);
++    }
++  }
++  if (error)
++  {
++    my_errno=error;			/* Safeguard */
++    DBUG_PRINT("error",("error: %d  errno: %d",error,errno));
++  }
++  else
++  {
++    if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
++      table->db_stat|=HA_READ_ONLY;
++    (void) extra(HA_EXTRA_NO_READCHECK);	// Not needed in SQL
++
++    DBUG_ASSERT(alloc_root_inited(&table->mem_root));
++
++    if (!(ref= (byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2)))
++    {
++      close();
++      error=HA_ERR_OUT_OF_MEM;
++    }
++    else
++      dupp_ref=ref+ALIGN_SIZE(ref_length);
++  }
++  DBUG_RETURN(error);
++}
++
++/*
++  Read first row (only) from a table
++  This is never called for InnoDB or BDB tables, as these table types
++  has the HA_NOT_EXACT_COUNT set.
++*/
++
++int handler::read_first_row(byte * buf, uint primary_key)
++{
++  register int error;
++  DBUG_ENTER("handler::read_first_row");
++
++  statistic_increment(current_thd->status_var.ha_read_first_count,&LOCK_status);
++
++  /*
++    If there is very few deleted rows in the table, find the first row by
++    scanning the table.
++    TODO remove the test for HA_READ_ORDER
++  */
++  if (deleted < 10 || primary_key >= MAX_KEY ||
++      !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
++  {
++    (void) ha_rnd_init(1);
++    while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
++    (void) ha_rnd_end();
++  }
++  else
++  {
++    /* Find the first row through the primary key */
++    (void) ha_index_init(primary_key);
++    error=index_first(buf);
++    (void) ha_index_end();
++  }
++  DBUG_RETURN(error);
++}
++
++/*
++  Generate the next auto-increment number based on increment and offset
++
++  In most cases increment= offset= 1, in which case we get:
++  1,2,3,4,5,...
++  If increment=10 and offset=5 and previous number is 1, we get:
++  1,5,15,25,35,...
++*/
++
++inline ulonglong
++next_insert_id(ulonglong nr,struct system_variables *variables)
++{
++  nr= (((nr+ variables->auto_increment_increment -
++         variables->auto_increment_offset)) /
++       (ulonglong) variables->auto_increment_increment);
++  return (nr* (ulonglong) variables->auto_increment_increment +
++          variables->auto_increment_offset);
++}
++
++
++void handler::adjust_next_insert_id_after_explicit_value(ulonglong nr)
++{
++  /*
++    If we have set THD::next_insert_id previously and plan to insert an
++    explicitely-specified value larger than this, we need to increase
++    THD::next_insert_id to be greater than the explicit value.
++  */
++  THD *thd= table->in_use;
++  if (thd->clear_next_insert_id && (nr >= thd->next_insert_id))
++  {
++    if (thd->variables.auto_increment_increment != 1)
++      nr= next_insert_id(nr, &thd->variables);
++    else
++      nr++;
++    thd->next_insert_id= nr;
++    DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr));
++  }
++}
++
++
++/*
++  Computes the largest number X:
++  - smaller than or equal to "nr"
++  - of the form: auto_increment_offset + N * auto_increment_increment
++  where N>=0.
++
++  SYNOPSIS
++    prev_insert_id
++      nr            Number to "round down"
++      variables     variables struct containing auto_increment_increment and
++                    auto_increment_offset
++
++  RETURN
++    The number X if it exists, "nr" otherwise.
++*/
++
++inline ulonglong
++prev_insert_id(ulonglong nr, struct system_variables *variables)
++{
++  if (unlikely(nr < variables->auto_increment_offset))
++  {
++    /*
++      There's nothing good we can do here. That is a pathological case, where
++      the offset is larger than the column's max possible value, i.e. not even
++      the first sequence value may be inserted. User will receive warning.
++    */
++    DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour "
++                       "auto_increment_offset: %lu",
++                       (ulong) nr, variables->auto_increment_offset));
++    return nr;
++  }
++  if (variables->auto_increment_increment == 1)
++    return nr; // optimization of the formula below
++  nr= (((nr - variables->auto_increment_offset)) /
++       (ulonglong) variables->auto_increment_increment);
++  return (nr * (ulonglong) variables->auto_increment_increment +
++          variables->auto_increment_offset);
++}
++
++
++/*
++  Update the auto_increment field if necessary
++
++  SYNOPSIS
++     update_auto_increment()
++
++  RETURN
++    0	ok
++    HA_ERR_AUTOINC_READ_FAILED
++     	get_auto_increment() was called and returned ~(ulonglong) 0
++    HA_ERR_AUTOINC_ERANGE
++        storing value in field caused strict mode failure.
++
++
++  IMPLEMENTATION
++
++    Updates columns with type NEXT_NUMBER if:
++
++  - If column value is set to NULL (in which case
++    auto_increment_field_not_null is 0)
++  - If column is set to 0 and (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) is not
++    set. In the future we will only set NEXT_NUMBER fields if one sets them
++    to NULL (or they are not included in the insert list).
++
++
++  There are two different cases when the above is true:
++
++  - thd->next_insert_id == 0  (This is the normal case)
++    In this case we set the set the column for the first row to the value
++    next_insert_id(get_auto_increment(column))) which is normally
++    max-used-column-value +1.
++
++    We call get_auto_increment() only for the first row in a multi-row
++    statement. For the following rows we generate new numbers based on the
++    last used number.
++
++  - thd->next_insert_id != 0.  This happens when we have read a statement
++    from the binary log or when one has used SET LAST_INSERT_ID=#.
++
++    In this case we will set the column to the value of next_insert_id.
++    The next row will be given the id
++    next_insert_id(next_insert_id)
++
++    The idea is that generated auto_increment values are predictable and
++    independent of the column values in the table.  This is needed to be
++    able to replicate into a table that already has rows with a higher
++    auto-increment value than the one that is inserted.
++
++    After we have already generated an auto-increment number and the user
++    inserts a column with a higher value than the last used one, we will
++    start counting from the inserted value.
++
++    thd->next_insert_id is cleared after it's been used for a statement.
++*/
++
++int handler::update_auto_increment()
++{
++  ulonglong nr;
++  THD *thd= table->in_use;
++  struct system_variables *variables= &thd->variables;
++  bool external_auto_increment= 
++       table->file->table_flags() & HA_EXTERNAL_AUTO_INCREMENT;
++  DBUG_ENTER("handler::update_auto_increment");
++
++  /*
++    We must save the previous value to be able to restore it if the
++    row was not inserted
++  */
++  thd->prev_insert_id= thd->next_insert_id;
++
++  if ((nr= table->next_number_field->val_int()) != 0 ||
++      table->auto_increment_field_not_null &&
++      thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)
++  {
++    /* Mark that we didn't generate a new value **/
++    auto_increment_column_changed=0;
++    adjust_next_insert_id_after_explicit_value(nr);
++    DBUG_RETURN(0);
++  }
++  if (external_auto_increment || !(nr= thd->next_insert_id))
++  {
++    if ((nr= get_auto_increment()) == ~(ulonglong) 0)
++      DBUG_RETURN(HA_ERR_AUTOINC_READ_FAILED);  // Mark failure
++
++    if (!external_auto_increment && variables->auto_increment_increment != 1)
++      nr= next_insert_id(nr-1, variables);
++    /*
++      Update next row based on the found value. This way we don't have to
++      call the handler for every generated auto-increment value on a
++      multi-row statement
++    */
++    thd->next_insert_id= nr;
++  }
++
++  DBUG_PRINT("info",("auto_increment: %lu", (ulong) nr));
++
++  /* Mark that we should clear next_insert_id before next stmt */
++  thd->clear_next_insert_id= 1;
++
++  if (likely(!table->next_number_field->store((longlong) nr, TRUE)))
++    thd->insert_id((ulonglong) nr);
++  else
++  if (thd->killed != THD::KILL_BAD_DATA) /* did we fail strict mode? */
++  {
++    /*
++      overflow of the field; we'll use the max value, however we try to
++      decrease it to honour auto_increment_* variables:
++    */
++    nr= prev_insert_id(table->next_number_field->val_int(), variables);
++    thd->insert_id(nr);
++    if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
++      thd->insert_id(nr= table->next_number_field->val_int());
++  }
++  else
++    DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
++
++  /*
++    We can't set next_insert_id if the auto-increment key is not the
++    first key part, as there is no guarantee that the first parts will be in
++    sequence
++  */
++  if (!table->s->next_number_key_offset)
++  {
++    /*
++      Set next insert id to point to next auto-increment value to be able to
++      handle multi-row statements
++      This works even if auto_increment_increment > 1
++    */
++    thd->next_insert_id= next_insert_id(nr, variables);
++  }
++  else
++    thd->next_insert_id= 0;
++
++  /* Mark that we generated a new value */
++  auto_increment_column_changed=1;
++  DBUG_RETURN(0);
++}
++
++/*
++  restore_auto_increment
++
++  In case of error on write, we restore the last used next_insert_id value
++  because the previous value was not used.
++*/
++
++void handler::restore_auto_increment()
++{
++  THD *thd= table->in_use;
++  if (thd->next_insert_id)
++  {
++    thd->next_insert_id= thd->prev_insert_id;
++    if (thd->next_insert_id == 0)
++    {
++      /* we didn't generate a value, engine will be called again */
++      thd->clear_next_insert_id= 0;
++    }
++  }
++}
++
++
++ulonglong handler::get_auto_increment()
++{
++  ulonglong nr;
++  int error;
++
++  (void) extra(HA_EXTRA_KEYREAD);
++  index_init(table->s->next_number_index);
++  if (!table->s->next_number_key_offset)
++  {						// Autoincrement at key-start
++    error=index_last(table->record[1]);
++  }
++  else
++  {
++    byte key[MAX_KEY_LENGTH];
++    key_copy(key, table->record[0],
++             table->key_info + table->s->next_number_index,
++             table->s->next_number_key_offset);
++    error= index_read(table->record[1], key, table->s->next_number_key_offset,
++                      HA_READ_PREFIX_LAST);
++  }
++
++  if (error)
++    nr=1;
++  else
++    nr= ((ulonglong) table->next_number_field->
++         val_int_offset(table->s->rec_buff_length)+1);
++  index_end();
++  (void) extra(HA_EXTRA_NO_KEYREAD);
++  return nr;
++}
++
++
++/*
++  Print error that we got from handler function
++
++  NOTE
++   In case of delete table it's only safe to use the following parts of
++   the 'table' structure:
++     table->s->path
++     table->alias
++*/
++
++void handler::print_error(int error, myf errflag)
++{
++  DBUG_ENTER("handler::print_error");
++  DBUG_PRINT("enter",("error: %d",error));
++
++  int textno=ER_GET_ERRNO;
++  switch (error) {
++  case EACCES:
++    textno=ER_OPEN_AS_READONLY;
++    break;
++  case EAGAIN:
++    textno=ER_FILE_USED;
++    break;
++  case ENOENT:
++    textno=ER_FILE_NOT_FOUND;
++    break;
++  case HA_ERR_KEY_NOT_FOUND:
++  case HA_ERR_NO_ACTIVE_RECORD:
++  case HA_ERR_END_OF_FILE:
++    textno=ER_KEY_NOT_FOUND;
++    break;
++  case HA_ERR_WRONG_MRG_TABLE_DEF:
++    textno=ER_WRONG_MRG_TABLE;
++    break;
++  case HA_ERR_FOUND_DUPP_KEY:
++  {
++    uint key_nr=get_dup_key(error);
++    if ((int) key_nr >= 0)
++    {
++      /* Write the dupplicated key in the error message */
++      char key[MAX_KEY_LENGTH];
++      String str(key,sizeof(key),system_charset_info);
++
++      if (key_nr == MAX_KEY)
++      {
++	/* Key is unknown */
++	str.copy("", 0, system_charset_info);
++	key_nr= (uint) -1;
++      }
++      else
++      {
++	key_unpack(&str,table,(uint) key_nr);
++	uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY));
++	if (str.length() >= max_length)
++	{
++	    str.length(max_length-4);
++	    str.append(STRING_WITH_LEN("..."));
++	}
++      }
++      my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(), key_nr+1);
++      DBUG_VOID_RETURN;
++    }
++    textno=ER_DUP_KEY;
++    break;
++  }
++  case HA_ERR_NULL_IN_SPATIAL:
++    my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, MYF(0));
++    DBUG_VOID_RETURN;
++  case HA_ERR_FOUND_DUPP_UNIQUE:
++    textno=ER_DUP_UNIQUE;
++    break;
++  case HA_ERR_RECORD_CHANGED:
++    textno=ER_CHECKREAD;
++    break;
++  case HA_ERR_CRASHED:
++    textno=ER_NOT_KEYFILE;
++    break;
++  case HA_ERR_WRONG_IN_RECORD:
++    textno= ER_CRASHED_ON_USAGE;
++    break;
++  case HA_ERR_CRASHED_ON_USAGE:
++    textno=ER_CRASHED_ON_USAGE;
++    break;
++  case HA_ERR_NOT_A_TABLE:
++    textno= error;
++    break;
++  case HA_ERR_CRASHED_ON_REPAIR:
++    textno=ER_CRASHED_ON_REPAIR;
++    break;
++  case HA_ERR_OUT_OF_MEM:
++    textno=ER_OUT_OF_RESOURCES;
++    break;
++  case HA_ERR_WRONG_COMMAND:
++    textno=ER_ILLEGAL_HA;
++    break;
++  case HA_ERR_OLD_FILE:
++    textno=ER_OLD_KEYFILE;
++    break;
++  case HA_ERR_UNSUPPORTED:
++    textno=ER_UNSUPPORTED_EXTENSION;
++    break;
++  case HA_ERR_RECORD_FILE_FULL:
++  case HA_ERR_INDEX_FILE_FULL:
++    textno=ER_RECORD_FILE_FULL;
++    break;
++  case HA_ERR_LOCK_WAIT_TIMEOUT:
++    textno=ER_LOCK_WAIT_TIMEOUT;
++    break;
++  case HA_ERR_LOCK_TABLE_FULL:
++    textno=ER_LOCK_TABLE_FULL;
++    break;
++  case HA_ERR_LOCK_DEADLOCK:
++    textno=ER_LOCK_DEADLOCK;
++    break;
++  case HA_ERR_READ_ONLY_TRANSACTION:
++    textno=ER_READ_ONLY_TRANSACTION;
++    break;
++  case HA_ERR_CANNOT_ADD_FOREIGN:
++    textno=ER_CANNOT_ADD_FOREIGN;
++    break;
++  case HA_ERR_ROW_IS_REFERENCED:
++  {
++    String str;
++    get_error_message(error, &str);
++    my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
++    DBUG_VOID_RETURN;
++  }
++  case HA_ERR_NO_REFERENCED_ROW:
++  {
++    String str;
++    get_error_message(error, &str);
++    my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
++    DBUG_VOID_RETURN;
++  }
++  case HA_ERR_TABLE_DEF_CHANGED:
++    textno=ER_TABLE_DEF_CHANGED;
++    break;
++  case HA_ERR_NO_SUCH_TABLE:
++  {
++    /*
++      We have to use path to find database name instead of using
++      table->table_cache_key because if the table didn't exist, then
++      table_cache_key was not set up
++    */
++    char *db;
++    char buff[FN_REFLEN];
++    uint length= dirname_part(buff,table->s->path);
++    buff[length-1]=0;
++    db=buff+dirname_length(buff);
++    my_error(ER_NO_SUCH_TABLE, MYF(0), db, table->alias);
++    break;
++  }
++  case HA_ERR_TABLE_NEEDS_UPGRADE:
++    textno=ER_TABLE_NEEDS_UPGRADE;
++    break;
++  case HA_ERR_TABLE_READONLY:
++    textno= ER_OPEN_AS_READONLY;
++    break;
++  case HA_ERR_AUTOINC_READ_FAILED:
++    textno= ER_AUTOINC_READ_FAILED;
++    break;
++  case HA_ERR_AUTOINC_ERANGE:
++    textno= ER_WARN_DATA_OUT_OF_RANGE;
++    break;
++  default:
++    {
++      /* The error was "unknown" to this function.
++	 Ask handler if it has got a message for this error */
++      bool temporary= FALSE;
++      String str;
++      temporary= get_error_message(error, &str);
++      if (!str.is_empty())
++      {
++	const char* engine= table_type();
++	if (temporary)
++	  my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
++	else
++	  my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
++      }
++      else
++	my_error(ER_GET_ERRNO,errflag,error);
++      DBUG_VOID_RETURN;
++    }
++  }
++  my_error(textno, errflag, table->alias, error);
++  DBUG_VOID_RETURN;
++}
++
++
++/*
++   Return an error message specific to this handler
++
++   SYNOPSIS
++   error        error code previously returned by handler
++   buf          Pointer to String where to add error message
++
++   Returns true if this is a temporary error
++ */
++
++bool handler::get_error_message(int error, String* buf)
++{
++  return FALSE;
++}
++
++
++int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
++{
++  KEY *keyinfo, *keyend;
++  KEY_PART_INFO *keypart, *keypartend;
++
++  if (!table->s->mysql_version)
++  {
++    /* check for blob-in-key error */
++    keyinfo= table->key_info;
++    keyend= table->key_info + table->s->keys;
++    for (; keyinfo < keyend; keyinfo++)
++    {
++      keypart= keyinfo->key_part;
++      keypartend= keypart + keyinfo->key_parts;
++      for (; keypart < keypartend; keypart++)
++      {
++        if (!keypart->fieldnr)
++          continue;
++        Field *field= table->field[keypart->fieldnr-1];
++        if (field->type() == FIELD_TYPE_BLOB)
++        {
++          if (check_opt->sql_flags & TT_FOR_UPGRADE)
++            check_opt->flags= T_MEDIUM;
++          return HA_ADMIN_NEEDS_CHECK;
++        }
++      }
++    }
++  }
++  return check_for_upgrade(check_opt);
++}
++
++
++int handler::check_old_types()
++{
++  Field** field;
++
++  if (!table->s->mysql_version)
++  {
++    /* check for bad DECIMAL field */
++    for (field= table->field; (*field); field++)
++    {
++      if ((*field)->type() == FIELD_TYPE_NEWDECIMAL)
++      {
++        return HA_ADMIN_NEEDS_ALTER;
++      }
++      if ((*field)->type() == MYSQL_TYPE_VAR_STRING)
++      {
++        return HA_ADMIN_NEEDS_ALTER;
++      }
++    }
++  }
++  return 0;
++}
++
++
++static bool update_frm_version(TABLE *table, bool needs_lock)
++{
++  char path[FN_REFLEN];
++  File file;
++  int result= 1;
++  DBUG_ENTER("update_frm_version");
++
++  /*
++    No need to update frm version in case table was created or checked
++    by server with the same version. This also ensures that we do not
++    update frm version for temporary tables as this code doesn't support
++    temporary tables.
++  */
++  if (table->s->mysql_version == MYSQL_VERSION_ID)
++    DBUG_RETURN(0);
++
++  strxnmov(path, sizeof(path)-1, mysql_data_home, "/", table->s->db, "/",
++           table->s->table_name, reg_ext, NullS);
++  if (!unpack_filename(path, path))
++    DBUG_RETURN(1);
++
++  if (needs_lock)
++    pthread_mutex_lock(&LOCK_open);
++
++  if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
++  {
++    uchar version[4];
++    char *key= table->s->table_cache_key;
++    uint key_length= table->s->key_length;
++    TABLE *entry;
++    HASH_SEARCH_STATE state;
++
++    int4store(version, MYSQL_VERSION_ID);
++
++    if ((result= my_pwrite(file,(byte*) version,4,51L,MYF_RW)))
++      goto err;
++
++    for (entry=(TABLE*) hash_first(&open_cache,(byte*) key,key_length, &state);
++         entry;
++         entry= (TABLE*) hash_next(&open_cache,(byte*) key,key_length, &state))
++      entry->s->mysql_version= MYSQL_VERSION_ID;
++  }
++err:
++  if (file >= 0)
++    VOID(my_close(file,MYF(MY_WME)));
++  if (needs_lock)
++    pthread_mutex_unlock(&LOCK_open);
++  DBUG_RETURN(result);
++}
++
++
++
++/* Return key if error because of duplicated keys */
++
++uint handler::get_dup_key(int error)
++{
++  DBUG_ENTER("handler::get_dup_key");
++  table->file->errkey  = (uint) -1;
++  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE ||
++      error == HA_ERR_NULL_IN_SPATIAL)
++    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
++  DBUG_RETURN(table->file->errkey);
++}
++
++
++/*
++  Delete all files with extension from bas_ext()
++
++  SYNOPSIS
++    delete_table()
++    name		Base name of table
++
++  NOTES
++    We assume that the handler may return more extensions than
++    was actually used for the file.
++
++  RETURN
++    0   If we successfully deleted at least one file from base_ext and
++	didn't get any other errors than ENOENT
++    #   Error
++*/
++
++int handler::delete_table(const char *name)
++{
++  int error= 0;
++  int enoent_or_zero= ENOENT;                   // Error if no file was deleted
++  char buff[FN_REFLEN];
++
++  for (const char **ext=bas_ext(); *ext ; ext++)
++  {
++    fn_format(buff, name, "", *ext, 2 | 4);
++    if (my_delete_with_symlink(buff, MYF(0)))
++    {
++      if ((error= my_errno) != ENOENT)
++	break;
++    }
++    else
++      enoent_or_zero= 0;                        // No error for ENOENT
++    error= enoent_or_zero;
++  }
++  return error;
++}
++
++
++int handler::rename_table(const char * from, const char * to)
++{
++  int error= 0;
++  for (const char **ext= bas_ext(); *ext ; ext++)
++  {
++    if (rename_file_ext(from, to, *ext))
++    {
++      if ((error=my_errno) != ENOENT)
++	break;
++      error= 0;
++    }
++  }
++  return error;
++}
++
++
++/*
++   Performs checks upon the table.
++
++   SYNOPSIS
++   check()
++   thd                thread doing CHECK TABLE operation
++   check_opt          options from the parser
++
++   NOTES
++
++   RETURN
++   HA_ADMIN_OK                 Successful upgrade
++   HA_ADMIN_NEEDS_UPGRADE      Table has structures requiring upgrade
++   HA_ADMIN_NEEDS_ALTER        Table has structures requiring ALTER TABLE
++   HA_ADMIN_NOT_IMPLEMENTED
++*/
++
++int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
++{
++  int error;
++
++  if ((table->s->mysql_version >= MYSQL_VERSION_ID) &&
++      (check_opt->sql_flags & TT_FOR_UPGRADE))
++    return 0;
++
++  if (table->s->mysql_version < MYSQL_VERSION_ID)
++  {
++    if ((error= check_old_types()))
++      return error;
++    error= ha_check_for_upgrade(check_opt);
++    if (error && (error != HA_ADMIN_NEEDS_CHECK))
++      return error;
++    if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
++      return 0;
++  }
++  if ((error= check(thd, check_opt)))
++    return error;
++  return update_frm_version(table, 0);
++}
++
++
++int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
++{
++  int result;
++  if ((result= repair(thd, check_opt)))
++    return result;
++  return update_frm_version(table, 0);
++}
++
++
++/*
++  Tell the storage engine that it is allowed to "disable transaction" in the
++  handler. It is a hint that ACID is not required - it is used in NDB for
++  ALTER TABLE, for example, when data are copied to temporary table.
++  A storage engine may treat this hint any way it likes. NDB for example
++  starts to commit every now and then automatically.
++  This hint can be safely ignored.
++*/
++
++int ha_enable_transaction(THD *thd, bool on)
++{
++  int error=0;
++
++  DBUG_ENTER("ha_enable_transaction");
++  thd->transaction.on= on;
++  if (on)
++  {
++    /*
++      Now all storage engines should have transaction handling enabled.
++      But some may have it enabled all the time - "disabling" transactions
++      is an optimization hint that storage engine is free to ignore.
++      So, let's commit an open transaction (if any) now.
++    */
++    if (!(error= ha_commit_stmt(thd)))
++      error= end_trans(thd, COMMIT);
++  }
++  DBUG_RETURN(error);
++}
++
++int handler::index_next_same(byte *buf, const byte *key, uint keylen)
++{
++  int error;
++  if (!(error=index_next(buf)))
++  {
++    if (key_cmp_if_same(table, key, active_index, keylen))
++    {
++      table->status=STATUS_NOT_FOUND;
++      error=HA_ERR_END_OF_FILE;
++    }
++  }
++  return error;
++}
++
++
++/****************************************************************************
++** Some general functions that isn't in the handler class
++****************************************************************************/
++
++/*
++  Initiates table-file and calls apropriate database-creator
++  Returns 1 if something got wrong
++*/
++
++int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
++		    bool update_create_info)
++{
++  int error;
++  TABLE table;
++  char name_buff[FN_REFLEN];
++  DBUG_ENTER("ha_create_table");
++
++  if (openfrm(current_thd, name,"",0,(uint) READ_ALL, 0, &table))
++    DBUG_RETURN(1);
++  if (update_create_info)
++  {
++    update_create_info_from_table(create_info, &table);
++  }
++  if (lower_case_table_names == 2 &&
++      !(table.file->table_flags() & HA_FILE_BASED))
++  {
++    /* Ensure that handler gets name in lower case */
++    strmov(name_buff, name);
++    my_casedn_str(files_charset_info, name_buff);
++    name= name_buff;
++  }
++
++  error=table.file->create(name,&table,create_info);
++  VOID(closefrm(&table));
++  if (error)
++    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name,error);
++  DBUG_RETURN(error != 0);
++}
++
++/*
++  Try to discover table from engine and
++  if found, write the frm file to disk.
++
++  RETURN VALUES:
++  -1 : Table did not exists
++   0 : Table created ok
++   > 0 : Error, table existed but could not be created
++
++*/
++
++int ha_create_table_from_engine(THD* thd,
++				const char *db,
++				const char *name)
++{
++  int error;
++  const void *frmblob;
++  uint frmlen;
++  char path[FN_REFLEN];
++  HA_CREATE_INFO create_info;
++  TABLE table;
++  DBUG_ENTER("ha_create_table_from_engine");
++  DBUG_PRINT("enter", ("name '%s'.'%s'", db, name));
++
++  bzero((char*) &create_info,sizeof(create_info));
++  if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
++  {
++    /* Table could not be discovered and thus not created */
++    DBUG_RETURN(error);
++  }
++
++  /*
++    Table exists in handler and could be discovered
++    frmblob and frmlen are set, write the frm to disk
++  */
++
++  (void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS);
++  // Save the frm file
++  error= writefrm(path, frmblob, frmlen);
++  my_free((char*) frmblob, MYF(0));
++  if (error)
++    DBUG_RETURN(2);
++
++  if (openfrm(thd, path,"",0,(uint) READ_ALL, 0, &table))
++    DBUG_RETURN(3);
++
++  update_create_info_from_table(&create_info, &table);
++  create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
++
++  if (lower_case_table_names == 2 &&
++      !(table.file->table_flags() & HA_FILE_BASED))
++  {
++    /* Ensure that handler gets name in lower case */
++    my_casedn_str(files_charset_info, path);
++  }
++  error=table.file->create(path,&table,&create_info);
++  VOID(closefrm(&table));
++
++  DBUG_RETURN(error != 0);
++}
++
++void st_ha_check_opt::init()
++{
++  flags= sql_flags= 0;
++  sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
++}
++
++
++/*****************************************************************************
++  Key cache handling.
++
++  This code is only relevant for ISAM/MyISAM tables
++
++  key_cache->cache may be 0 only in the case where a key cache is not
++  initialized or when we where not able to init the key cache in a previous
++  call to ha_init_key_cache() (probably out of memory)
++*****************************************************************************/
++
++/* Init a key cache if it has not been initied before */
++
++
++int ha_init_key_cache(const char *name, KEY_CACHE *key_cache)
++{
++  DBUG_ENTER("ha_init_key_cache");
++
++  if (!key_cache->key_cache_inited)
++  {
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    long tmp_buff_size= (long) key_cache->param_buff_size;
++    long tmp_block_size= (long) key_cache->param_block_size;
++    uint division_limit= key_cache->param_division_limit;
++    uint age_threshold=  key_cache->param_age_threshold;
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++    DBUG_RETURN(!init_key_cache(key_cache,
++				tmp_block_size,
++				tmp_buff_size,
++				division_limit, age_threshold));
++  }
++  DBUG_RETURN(0);
++}
++
++
++/* Resize key cache */
++
++int ha_resize_key_cache(KEY_CACHE *key_cache)
++{
++  DBUG_ENTER("ha_resize_key_cache");
++
++  if (key_cache->key_cache_inited)
++  {
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    long tmp_buff_size= (long) key_cache->param_buff_size;
++    long tmp_block_size= (long) key_cache->param_block_size;
++    uint division_limit= key_cache->param_division_limit;
++    uint age_threshold=  key_cache->param_age_threshold;
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++    DBUG_RETURN(!resize_key_cache(key_cache, tmp_block_size,
++				  tmp_buff_size,
++				  division_limit, age_threshold));
++  }
++  DBUG_RETURN(0);
++}
++
++
++/* Change parameters for key cache (like size) */
++
++int ha_change_key_cache_param(KEY_CACHE *key_cache)
++{
++  if (key_cache->key_cache_inited)
++  {
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    uint division_limit= key_cache->param_division_limit;
++    uint age_threshold=  key_cache->param_age_threshold;
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++    change_key_cache_param(key_cache, division_limit, age_threshold);
++  }
++  return 0;
++}
++
++/* Free memory allocated by a key cache */
++
++int ha_end_key_cache(KEY_CACHE *key_cache)
++{
++  end_key_cache(key_cache, 1);		// Can never fail
++  return 0;
++}
++
++/* Move all tables from one key cache to another one */
++
++int ha_change_key_cache(KEY_CACHE *old_key_cache,
++			KEY_CACHE *new_key_cache)
++{
++  mi_change_key_cache(old_key_cache, new_key_cache);
++  return 0;
++}
++
++
++/*
++  Try to discover one table from handler(s)
++
++  RETURN
++   -1  : Table did not exists
++    0  : OK. In this case *frmblob and *frmlen are set
++    >0 : error.  frmblob and frmlen may not be set
++*/
++
++int ha_discover(THD *thd, const char *db, const char *name,
++		const void **frmblob, uint *frmlen)
++{
++  int error= -1; // Table does not exist in any handler
++  DBUG_ENTER("ha_discover");
++  DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
++  if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
++    DBUG_RETURN(error);
++#ifdef HAVE_NDBCLUSTER_DB
++  if (have_ndbcluster == SHOW_OPTION_YES)
++    error= ndbcluster_discover(thd, db, name, frmblob, frmlen);
++#endif
++  if (!error)
++    statistic_increment(thd->status_var.ha_discover_count,&LOCK_status);
++  DBUG_RETURN(error);
++}
++
++
++/*
++  Call this function in order to give the handler the possiblity
++  to ask engine if there are any new tables that should be written to disk
++  or any dropped tables that need to be removed from disk
++*/
++
++int
++ha_find_files(THD *thd,const char *db,const char *path,
++	      const char *wild, bool dir, List<char> *files)
++{
++  int error= 0;
++  DBUG_ENTER("ha_find_files");
++  DBUG_PRINT("enter", ("db: %s, path: %s, wild: %s, dir: %d",
++		       db, path, wild, dir));
++#ifdef HAVE_NDBCLUSTER_DB
++  if (have_ndbcluster == SHOW_OPTION_YES)
++    error= ndbcluster_find_files(thd, db, path, wild, dir, files);
++#endif
++  DBUG_RETURN(error);
++}
++
++
++/*
++  Ask handler if the table exists in engine
++
++  RETURN
++    HA_ERR_NO_SUCH_TABLE     Table does not exist
++    HA_ERR_TABLE_EXIST       Table exists
++    #                        Error code
++
++ */
++int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
++{
++  int error= HA_ERR_NO_SUCH_TABLE;
++  DBUG_ENTER("ha_table_exists_in_engine");
++  DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
++#ifdef HAVE_NDBCLUSTER_DB
++  if (have_ndbcluster == SHOW_OPTION_YES)
++    error= ndbcluster_table_exists_in_engine(thd, db, name);
++#endif
++  DBUG_PRINT("exit", ("error: %d", error));
++  DBUG_RETURN(error);
++}
++
++
++/*
++  Read the first row of a multi-range set.
++
++  SYNOPSIS
++    read_multi_range_first()
++    found_range_p       Returns a pointer to the element in 'ranges' that
++                        corresponds to the returned row.
++    ranges              An array of KEY_MULTI_RANGE range descriptions.
++    range_count         Number of ranges in 'ranges'.
++    sorted		If result should be sorted per key.
++    buffer              A HANDLER_BUFFER for internal handler usage.
++
++  NOTES
++    Record is read into table->record[0].
++    *found_range_p returns a valid value only if read_multi_range_first()
++    returns 0.
++    Sorting is done within each range. If you want an overall sort, enter
++    'ranges' with sorted ranges.
++
++  RETURN
++    0			OK, found a row
++    HA_ERR_END_OF_FILE	No rows in range
++    #			Error code
++*/
++
++int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
++                                    KEY_MULTI_RANGE *ranges, uint range_count,
++                                    bool sorted, HANDLER_BUFFER *buffer)
++{
++  int result= HA_ERR_END_OF_FILE;
++  DBUG_ENTER("handler::read_multi_range_first");
++  multi_range_sorted= sorted;
++  multi_range_buffer= buffer;
++
++  for (multi_range_curr= ranges, multi_range_end= ranges + range_count;
++       multi_range_curr < multi_range_end;
++       multi_range_curr++)
++  {
++    result= read_range_first(multi_range_curr->start_key.length ?
++                             &multi_range_curr->start_key : 0,
++                             multi_range_curr->end_key.length ?
++                             &multi_range_curr->end_key : 0,
++                             test(multi_range_curr->range_flag & EQ_RANGE),
++                             multi_range_sorted);
++    if (result != HA_ERR_END_OF_FILE)
++      break;
++  }
++
++  *found_range_p= multi_range_curr;
++  DBUG_PRINT("exit",("result %d", result));
++  DBUG_RETURN(result);
++}
++
++
++/*
++  Read the next row of a multi-range set.
++
++  SYNOPSIS
++    read_multi_range_next()
++    found_range_p       Returns a pointer to the element in 'ranges' that
++                        corresponds to the returned row.
++
++  NOTES
++    Record is read into table->record[0].
++    *found_range_p returns a valid value only if read_multi_range_next()
++    returns 0.
++
++  RETURN
++    0			OK, found a row
++    HA_ERR_END_OF_FILE	No (more) rows in range
++    #			Error code
++*/
++
++int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
++{
++  int result;
++  DBUG_ENTER("handler::read_multi_range_next");
++
++  /* We should not be called after the last call returned EOF. */
++  DBUG_ASSERT(multi_range_curr < multi_range_end);
++
++  do
++  {
++    /* Save a call if there can be only one row in range. */
++    if (multi_range_curr->range_flag != (UNIQUE_RANGE | EQ_RANGE))
++    {
++      result= read_range_next();
++
++      /* On success or non-EOF errors jump to the end. */
++      if (result != HA_ERR_END_OF_FILE)
++        break;
++    }
++    else
++    {
++      /*
++        We need to set this for the last range only, but checking this
++        condition is more expensive than just setting the result code.
++      */
++      result= HA_ERR_END_OF_FILE;
++    }
++
++    /* Try the next range(s) until one matches a record. */
++    for (multi_range_curr++;
++         multi_range_curr < multi_range_end;
++         multi_range_curr++)
++    {
++      result= read_range_first(multi_range_curr->start_key.length ?
++                               &multi_range_curr->start_key : 0,
++                               multi_range_curr->end_key.length ?
++                               &multi_range_curr->end_key : 0,
++                               test(multi_range_curr->range_flag & EQ_RANGE),
++                               multi_range_sorted);
++      if (result != HA_ERR_END_OF_FILE)
++        break;
++    }
++  }
++  while ((result == HA_ERR_END_OF_FILE) &&
++         (multi_range_curr < multi_range_end));
++
++  *found_range_p= multi_range_curr;
++  DBUG_PRINT("exit",("handler::read_multi_range_next: result %d", result));
++  DBUG_RETURN(result);
++}
++
++
++/*
++  Read first row between two ranges.
++  Store ranges for future calls to read_range_next
++
++  SYNOPSIS
++    read_range_first()
++    start_key		Start key. Is 0 if no min range
++    end_key		End key.  Is 0 if no max range
++    eq_range_arg	Set to 1 if start_key == end_key and the range endpoints
++                        will not change during query execution.
++    sorted		Set to 1 if result should be sorted per key
++
++  NOTES
++    Record is read into table->record[0]
++
++  RETURN
++    0			Found row
++    HA_ERR_END_OF_FILE	No rows in range
++    #			Error code
++*/
++
++int handler::read_range_first(const key_range *start_key,
++			      const key_range *end_key,
++			      bool eq_range_arg, bool sorted)
++{
++  int result;
++  DBUG_ENTER("handler::read_range_first");
++
++  eq_range= eq_range_arg;
++  end_range= 0;
++  if (end_key)
++  {
++    end_range= &save_end_range;
++    save_end_range= *end_key;
++    key_compare_result_on_equal= ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
++				  (end_key->flag == HA_READ_AFTER_KEY) ? -1 : 0);
++  }
++  range_key_part= table->key_info[active_index].key_part;
++
++  if (!start_key)			// Read first record
++    result= index_first(table->record[0]);
++  else
++    result= index_read(table->record[0],
++		       start_key->key,
++		       start_key->length,
++		       start_key->flag);
++  if (result)
++    DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND)
++		? HA_ERR_END_OF_FILE
++		: result);
++
++  DBUG_RETURN (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
++}
++
++
++/*
++  Read next row between two ranges.
++
++  SYNOPSIS
++    read_range_next()
++
++  NOTES
++    Record is read into table->record[0]
++
++  RETURN
++    0			Found row
++    HA_ERR_END_OF_FILE	No rows in range
++    #			Error code
++*/
++
++int handler::read_range_next()
++{
++  int result;
++  DBUG_ENTER("handler::read_range_next");
++
++  if (eq_range)
++  {
++    /* We trust that index_next_same always gives a row in range */
++    DBUG_RETURN(index_next_same(table->record[0],
++                                end_range->key,
++                                end_range->length));
++  }
++  result= index_next(table->record[0]);
++  if (result)
++    DBUG_RETURN(result);
++  DBUG_RETURN(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
++}
++
++
++/*
++  Compare if found key (in row) is over max-value
++
++  SYNOPSIS
++    compare_key
++    range		range to compare to row. May be 0 for no range
++
++  NOTES
++    See key.cc::key_cmp() for details
++
++  RETURN
++    The return value is SIGN(key_in_row - range_key):
++
++    0			Key is equal to range or 'range' == 0 (no range)
++   -1			Key is less than range
++    1			Key is larger than range
++*/
++
++int handler::compare_key(key_range *range)
++{
++  int cmp;
++  if (!range)
++    return 0;					// No max range
++  cmp= key_cmp(range_key_part, range->key, range->length);
++  if (!cmp)
++    cmp= key_compare_result_on_equal;
++  return cmp;
++}
++
++int handler::index_read_idx(byte * buf, uint index, const byte * key,
++			     uint key_len, enum ha_rkey_function find_flag)
++{
++  int error= ha_index_init(index);
++  if (!error)
++    error= index_read(buf, key, key_len, find_flag);
++  if (!error)
++    error= ha_index_end();
++  return error;
++}
++
++
++/*
++  Returns a list of all known extensions.
++
++  SYNOPSIS
++    ha_known_exts()
++
++  NOTES
++    No mutexes, worst case race is a minor surplus memory allocation
++    We have to recreate the extension map if mysqld is restarted (for example
++    within libmysqld)
++
++  RETURN VALUE
++    pointer		pointer to TYPELIB structure
++*/
++
++TYPELIB *ha_known_exts(void)
++{
++  MEM_ROOT *mem_root= current_thd->mem_root;
++  if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
++  {
++    handlerton **types;
++    List<char> found_exts;
++    List_iterator_fast<char> it(found_exts);
++    const char **ext, *old_ext;
++
++    known_extensions_id= mysys_usage_id;
++    found_exts.push_back((char*) triggers_file_ext);
++    found_exts.push_back((char*) trigname_file_ext);
++    for (types= sys_table_types; *types; types++)
++    {
++      if ((*types)->state == SHOW_OPTION_YES)
++      {
++	handler *file= get_new_handler(0, mem_root,
++                                       (enum db_type) (*types)->db_type);
++	for (ext= file->bas_ext(); *ext; ext++)
++	{
++	  while ((old_ext= it++))
++          {
++	    if (!strcmp(old_ext, *ext))
++	      break;
++          }
++	  if (!old_ext)
++	    found_exts.push_back((char *) *ext);
++
++	  it.rewind();
++	}
++	delete file;
++      }
++    }
++    ext= (const char **) my_once_alloc(sizeof(char *)*
++                                       (found_exts.elements+1),
++                                       MYF(MY_WME | MY_FAE));
++
++    DBUG_ASSERT(ext != 0);
++    known_extensions.count= found_exts.elements;
++    known_extensions.type_names= ext;
++
++    while ((old_ext= it++))
++      *ext++= old_ext;
++    *ext= 0;
++  }
++  return &known_extensions;
++}
+diff -urNad trunk~/sql/handler.h trunk/sql/handler.h
+--- trunk~/sql/handler.h	2007-11-15 08:06:48.000000000 -0600
++++ trunk/sql/handler.h	2007-12-27 15:54:49.270262634 -0600
+@@ -186,8 +186,9 @@
+   DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
+   DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
+   DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
+-  DB_TYPE_FEDERATED_DB,
++  DB_TYPE_FEDERATED_DB, 
+   DB_TYPE_BLACKHOLE_DB,
++  DB_TYPE_SPHINX_DB,
+   DB_TYPE_DEFAULT // Must be last
+ };
+ 
+diff -urNad trunk~/sql/handler.h.orig trunk/sql/handler.h.orig
+--- trunk~/sql/handler.h.orig	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/handler.h.orig	2007-12-27 15:54:49.274262862 -0600
+@@ -0,0 +1,1079 @@
++/* Copyright (C) 2000-2006 MySQL AB
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; version 2 of the License.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
++
++
++/* Definitions for parameters to do with handler-routines */
++
++#ifdef USE_PRAGMA_INTERFACE
++#pragma interface			/* gcc class implementation */
++#endif
++
++#include <ft_global.h>
++#include <keycache.h>
++
++#ifndef NO_HASH
++#define NO_HASH				/* Not yet implemented */
++#endif
++
++#if defined(HAVE_BERKELEY_DB) || defined(HAVE_INNOBASE_DB) || \
++    defined(HAVE_NDBCLUSTER_DB)
++#define USING_TRANSACTIONS
++#endif
++
++// the following is for checking tables
++
++#define HA_ADMIN_ALREADY_DONE	  1
++#define HA_ADMIN_OK               0
++#define HA_ADMIN_NOT_IMPLEMENTED -1
++#define HA_ADMIN_FAILED		 -2
++#define HA_ADMIN_CORRUPT         -3
++#define HA_ADMIN_INTERNAL_ERROR  -4
++#define HA_ADMIN_INVALID         -5
++#define HA_ADMIN_REJECT          -6
++#define HA_ADMIN_TRY_ALTER       -7
++#define HA_ADMIN_WRONG_CHECKSUM  -8
++#define HA_ADMIN_NOT_BASE_TABLE  -9
++#define HA_ADMIN_NEEDS_UPGRADE  -10
++#define HA_ADMIN_NEEDS_ALTER    -11
++#define HA_ADMIN_NEEDS_CHECK    -12
++
++/* Bits in table_flags() to show what database can do */
++
++/*
++  Can switch index during the scan with ::rnd_same() - not used yet.
++  see mi_rsame/heap_rsame/myrg_rsame
++*/
++#define HA_READ_RND_SAME       (1 << 0)
++#define HA_PARTIAL_COLUMN_READ (1 << 1) /* read may not return all columns */
++#define HA_TABLE_SCAN_ON_INDEX (1 << 2) /* No separate data/index file */
++#define HA_REC_NOT_IN_SEQ      (1 << 3) /* ha_info don't return recnumber;
++                                           It returns a position to ha_r_rnd */
++#define HA_CAN_GEOMETRY        (1 << 4)
++/*
++  Reading keys in random order is as fast as reading keys in sort order
++  (Used in records.cc to decide if we should use a record cache and by
++  filesort to decide if we should sort key + data or key + pointer-to-row
++*/
++#define HA_FAST_KEY_READ       (1 << 5)
++#define HA_NULL_IN_KEY         (1 << 7) /* One can have keys with NULL */
++#define HA_DUPP_POS            (1 << 8) /* ha_position() gives dup row */
++#define HA_NO_BLOBS            (1 << 9) /* Doesn't support blobs */
++#define HA_CAN_INDEX_BLOBS     (1 << 10)
++#define HA_AUTO_PART_KEY       (1 << 11) /* auto-increment in multi-part key */
++#define HA_REQUIRE_PRIMARY_KEY (1 << 12) /* .. and can't create a hidden one */
++#define HA_NOT_EXACT_COUNT     (1 << 13)
++/*
++  INSERT_DELAYED only works with handlers that uses MySQL internal table
++  level locks
++*/
++#define HA_CAN_INSERT_DELAYED  (1 << 14)
++#define HA_PRIMARY_KEY_IN_READ_INDEX (1 << 15)
++#define HA_CAN_RTREEKEYS       (1 << 17)
++#define HA_NOT_DELETE_WITH_CACHE (1 << 18)
++#define HA_NO_PREFIX_CHAR_KEYS (1 << 20)
++#define HA_CAN_FULLTEXT        (1 << 21)
++#define HA_CAN_SQL_HANDLER     (1 << 22)
++#define HA_NO_AUTO_INCREMENT   (1 << 23)
++#define HA_HAS_CHECKSUM        (1 << 24)
++/* Table data are stored in separate files (for lower_case_table_names) */
++#define HA_FILE_BASED	       (1 << 26)
++#define HA_NO_VARCHAR	       (1 << 27)
++#define HA_CAN_BIT_FIELD       (1 << 28) /* supports bit fields */
++#define HA_NEED_READ_RANGE_BUFFER (1 << 29) /* for read_multi_range */
++#define HA_ANY_INDEX_MAY_BE_UNIQUE (1 << 30)
++/* The storage engine manages auto_increment itself */
++#define HA_EXTERNAL_AUTO_INCREMENT (1 << 31)
++
++/* bits in index_flags(index_number) for what you can do with index */
++#define HA_READ_NEXT            1       /* TODO really use this flag */
++#define HA_READ_PREV            2       /* supports ::index_prev */
++#define HA_READ_ORDER           4       /* index_next/prev follow sort order */
++#define HA_READ_RANGE           8       /* can find all records in a range */
++#define HA_ONLY_WHOLE_INDEX	16	/* Can't use part key searches */
++#define HA_KEYREAD_ONLY         64	/* Support HA_EXTRA_KEYREAD */
++
++/*
++  Index scan will not return records in rowid order. Not guaranteed to be
++  set for unordered (e.g. HASH) indexes.
++*/
++#define HA_KEY_SCAN_NOT_ROR     128
++
++
++/* operations for disable/enable indexes */
++#define HA_KEY_SWITCH_NONUNIQ      0
++#define HA_KEY_SWITCH_ALL          1
++#define HA_KEY_SWITCH_NONUNIQ_SAVE 2
++#define HA_KEY_SWITCH_ALL_SAVE     3
++
++/*
++  Note: the following includes binlog and closing 0.
++  so: innodb + bdb + ndb + binlog + myisam + myisammrg + archive +
++      example + csv + heap + blackhole + federated + 0
++  (yes, the sum is deliberately inaccurate)
++*/
++#define MAX_HA 14
++
++/*
++  Bits in index_ddl_flags(KEY *wanted_index)
++  for what ddl you can do with index
++  If none is set, the wanted type of index is not supported
++  by the handler at all. See WorkLog 1563.
++*/
++#define HA_DDL_SUPPORT   1 /* Supported by handler */
++#define HA_DDL_WITH_LOCK 2 /* Can create/drop with locked table */
++#define HA_DDL_ONLINE    4 /* Can create/drop without lock */
++
++/*
++  Parameters for open() (in register form->filestat)
++  HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED
++*/
++
++#define HA_OPEN_KEYFILE		1
++#define HA_OPEN_RNDFILE		2
++#define HA_GET_INDEX		4
++#define HA_GET_INFO		8	/* do a ha_info() after open */
++#define HA_READ_ONLY		16	/* File opened as readonly */
++/* Try readonly if can't open with read and write */
++#define HA_TRY_READ_ONLY	32
++#define HA_WAIT_IF_LOCKED	64	/* Wait if locked on open */
++#define HA_ABORT_IF_LOCKED	128	/* skip if locked on open.*/
++#define HA_BLOCK_LOCK		256	/* unlock when reading some records */
++#define HA_OPEN_TEMPORARY	512
++
++	/* Errors on write which is recoverable  (Key exist) */
++#define HA_WRITE_SKIP 121		/* Duplicate key on write */
++#define HA_READ_CHECK 123		/* Update with is recoverable */
++#define HA_CANT_DO_THAT 131		/* Databasehandler can't do it */
++
++	/* Some key definitions */
++#define HA_KEY_NULL_LENGTH	1
++#define HA_KEY_BLOB_LENGTH	2
++
++#define HA_LEX_CREATE_TMP_TABLE	1
++#define HA_LEX_CREATE_IF_NOT_EXISTS 2
++#define HA_LEX_CREATE_TABLE_LIKE 4
++#define HA_OPTION_NO_CHECKSUM	(1L << 17)
++#define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18)
++#define HA_MAX_REC_LENGTH	65535
++
++/* Table caching type */
++#define HA_CACHE_TBL_NONTRANSACT 0
++#define HA_CACHE_TBL_NOCACHE     1
++#define HA_CACHE_TBL_ASKTRANSACT 2
++#define HA_CACHE_TBL_TRANSACT    4
++
++/* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */
++#define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT 1
++
++enum db_type
++{
++  DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1,
++  DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM,
++  DB_TYPE_RMS_ISAM, DB_TYPE_HEAP, DB_TYPE_ISAM,
++  DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM,
++  DB_TYPE_BERKELEY_DB, DB_TYPE_INNODB,
++  DB_TYPE_GEMINI, DB_TYPE_NDBCLUSTER,
++  DB_TYPE_EXAMPLE_DB, DB_TYPE_ARCHIVE_DB, DB_TYPE_CSV_DB,
++  DB_TYPE_FEDERATED_DB,
++  DB_TYPE_BLACKHOLE_DB,
++  DB_TYPE_DEFAULT // Must be last
++};
++
++enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED,
++		ROW_TYPE_DYNAMIC, ROW_TYPE_COMPRESSED,
++		ROW_TYPE_REDUNDANT, ROW_TYPE_COMPACT };
++
++/* struct to hold information about the table that should be created */
++
++/* Bits in used_fields */
++#define HA_CREATE_USED_AUTO             (1L << 0)
++#define HA_CREATE_USED_RAID             (1L << 1)
++#define HA_CREATE_USED_UNION            (1L << 2)
++#define HA_CREATE_USED_INSERT_METHOD    (1L << 3)
++#define HA_CREATE_USED_MIN_ROWS         (1L << 4)
++#define HA_CREATE_USED_MAX_ROWS         (1L << 5)
++#define HA_CREATE_USED_AVG_ROW_LENGTH   (1L << 6)
++#define HA_CREATE_USED_PACK_KEYS        (1L << 7)
++#define HA_CREATE_USED_CHARSET          (1L << 8)
++#define HA_CREATE_USED_DEFAULT_CHARSET  (1L << 9)
++#define HA_CREATE_USED_DATADIR          (1L << 10)
++#define HA_CREATE_USED_INDEXDIR         (1L << 11)
++#define HA_CREATE_USED_ENGINE           (1L << 12)
++#define HA_CREATE_USED_CHECKSUM         (1L << 13)
++#define HA_CREATE_USED_DELAY_KEY_WRITE  (1L << 14)
++#define HA_CREATE_USED_ROW_FORMAT       (1L << 15)
++#define HA_CREATE_USED_COMMENT          (1L << 16)
++#define HA_CREATE_USED_PASSWORD         (1L << 17)
++#define HA_CREATE_USED_CONNECTION       (1L << 18)
++
++typedef ulonglong my_xid; // this line is the same as in log_event.h
++#define MYSQL_XID_PREFIX "MySQLXid"
++#define MYSQL_XID_PREFIX_LEN 8 // must be a multiple of 8
++#define MYSQL_XID_OFFSET (MYSQL_XID_PREFIX_LEN+sizeof(server_id))
++#define MYSQL_XID_GTRID_LEN (MYSQL_XID_OFFSET+sizeof(my_xid))
++
++#define XIDDATASIZE 128
++#define MAXGTRIDSIZE 64
++#define MAXBQUALSIZE 64
++
++struct xid_t {
++  long formatID;
++  long gtrid_length;
++  long bqual_length;
++  char data[XIDDATASIZE];  // not \0-terminated !
++
++  xid_t() {}                                /* Remove gcc warning */
++  bool eq(struct xid_t *xid)
++  { return eq(xid->gtrid_length, xid->bqual_length, xid->data); }
++  bool eq(long g, long b, const char *d)
++  { return g == gtrid_length && b == bqual_length && !memcmp(d, data, g+b); }
++  void set(struct xid_t *xid)
++  { memcpy(this, xid, xid->length()); }
++  void set(long f, const char *g, long gl, const char *b, long bl)
++  {
++    formatID= f;
++    memcpy(data, g, gtrid_length= gl);
++    memcpy(data+gl, b, bqual_length= bl);
++  }
++  void set(ulonglong xid)
++  {
++    my_xid tmp;
++    formatID= 1;
++    set(MYSQL_XID_PREFIX_LEN, 0, MYSQL_XID_PREFIX);
++    memcpy(data+MYSQL_XID_PREFIX_LEN, &server_id, sizeof(server_id));
++    tmp= xid;
++    memcpy(data+MYSQL_XID_OFFSET, &tmp, sizeof(tmp));
++    gtrid_length=MYSQL_XID_GTRID_LEN;
++  }
++  void set(long g, long b, const char *d)
++  {
++    formatID= 1;
++    gtrid_length= g;
++    bqual_length= b;
++    memcpy(data, d, g+b);
++  }
++  bool is_null() { return formatID == -1; }
++  void null() { formatID= -1; }
++  my_xid quick_get_my_xid()
++  {
++    my_xid tmp;
++    memcpy(&tmp, data+MYSQL_XID_OFFSET, sizeof(tmp));
++    return tmp;
++  }
++  my_xid get_my_xid()
++  {
++    return gtrid_length == MYSQL_XID_GTRID_LEN && bqual_length == 0 &&
++           !memcmp(data+MYSQL_XID_PREFIX_LEN, &server_id, sizeof(server_id)) &&
++           !memcmp(data, MYSQL_XID_PREFIX, MYSQL_XID_PREFIX_LEN) ?
++           quick_get_my_xid() : 0;
++  }
++  uint length()
++  {
++    return sizeof(formatID)+sizeof(gtrid_length)+sizeof(bqual_length)+
++           gtrid_length+bqual_length;
++  }
++  byte *key()
++  {
++    return (byte *)&gtrid_length;
++  }
++  uint key_length()
++  {
++    return sizeof(gtrid_length)+sizeof(bqual_length)+gtrid_length+bqual_length;
++  }
++};
++typedef struct xid_t XID;
++
++/* for recover() handlerton call */
++#define MIN_XID_LIST_SIZE  128
++#ifdef SAFEMALLOC
++#define MAX_XID_LIST_SIZE  256
++#else
++#define MAX_XID_LIST_SIZE  (1024*128)
++#endif
++
++/*
++  handlerton is a singleton structure - one instance per storage engine -
++  to provide access to storage engine functionality that works on the
++  "global" level (unlike handler class that works on a per-table basis)
++
++  usually handlerton instance is defined statically in ha_xxx.cc as
++
++  static handlerton { ... } xxx_hton;
++
++  savepoint_*, prepare, recover, and *_by_xid pointers can be 0.
++*/
++typedef struct
++{
++  /*
++    storage engine name as it should be printed to a user
++  */
++  const char *name;
++
++  /*
++    Historical marker for if the engine is available of not
++  */
++  SHOW_COMP_OPTION state;
++
++  /*
++    A comment used by SHOW to describe an engine.
++  */
++  const char *comment;
++
++  /*
++    Historical number used for frm file to determine the correct storage engine.
++    This is going away and new engines will just use "name" for this.
++  */
++  enum db_type db_type;
++  /*
++    Method that initizlizes a storage engine
++  */
++  bool (*init)();
++
++  /*
++    each storage engine has it's own memory area (actually a pointer)
++    in the thd, for storing per-connection information.
++    It is accessed as
++
++      thd->ha_data[xxx_hton.slot]
++
++   slot number is initialized by MySQL after xxx_init() is called.
++   */
++   uint slot;
++   /*
++     to store per-savepoint data storage engine is provided with an area
++     of a requested size (0 is ok here).
++     savepoint_offset must be initialized statically to the size of
++     the needed memory to store per-savepoint information.
++     After xxx_init it is changed to be an offset to savepoint storage
++     area and need not be used by storage engine.
++     see binlog_hton and binlog_savepoint_set/rollback for an example.
++   */
++   uint savepoint_offset;
++   /*
++     handlerton methods:
++
++     close_connection is only called if
++     thd->ha_data[xxx_hton.slot] is non-zero, so even if you don't need
++     this storage area - set it to something, so that MySQL would know
++     this storage engine was accessed in this connection
++   */
++   int  (*close_connection)(THD *thd);
++   /*
++     sv points to an uninitialized storage area of requested size
++     (see savepoint_offset description)
++   */
++   int  (*savepoint_set)(THD *thd, void *sv);
++   /*
++     sv points to a storage area, that was earlier passed
++     to the savepoint_set call
++   */
++   int  (*savepoint_rollback)(THD *thd, void *sv);
++   int  (*savepoint_release)(THD *thd, void *sv);
++   /*
++     'all' is true if it's a real commit, that makes persistent changes
++     'all' is false if it's not in fact a commit but an end of the
++     statement that is part of the transaction.
++     NOTE 'all' is also false in auto-commit mode where 'end of statement'
++     and 'real commit' mean the same event.
++   */
++   int  (*commit)(THD *thd, bool all);
++   int  (*rollback)(THD *thd, bool all);
++   int  (*prepare)(THD *thd, bool all);
++   int  (*recover)(XID *xid_list, uint len);
++   int  (*commit_by_xid)(XID *xid);
++   int  (*rollback_by_xid)(XID *xid);
++   void *(*create_cursor_read_view)();
++   void (*set_cursor_read_view)(void *);
++   void (*close_cursor_read_view)(void *);
++   uint32 flags;                                /* global handler flags */
++} handlerton;
++
++struct show_table_alias_st {
++  const char *alias;
++  const char *type;
++};
++
++/* 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) //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
++
++typedef struct st_thd_trans
++{
++  /* number of entries in the ht[] */
++  uint        nht;
++  /* true is not all entries in the ht[] support 2pc */
++  bool        no_2pc;
++  /* storage engines that registered themselves for this transaction */
++  handlerton *ht[MAX_HA];
++  /* 
++    The purpose of this flag is to keep track of non-transactional
++    tables that were modified in scope of:
++    - transaction, when the variable is a member of
++    THD::transaction.all
++    - top-level statement or sub-statement, when the variable is a
++    member of THD::transaction.stmt
++    This member has the following life cycle:
++    * stmt.modified_non_trans_table is used to keep track of
++    modified non-transactional tables of top-level statements. At
++    the end of the previous statement and at the beginning of the session,
++    it is reset to FALSE.  If such functions
++    as mysql_insert, mysql_update, mysql_delete etc modify a
++    non-transactional table, they set this flag to TRUE.  At the
++    end of the statement, the value of stmt.modified_non_trans_table 
++    is merged with all.modified_non_trans_table and gets reset.
++    * all.modified_non_trans_table is reset at the end of transaction
++    
++    * Since we do not have a dedicated context for execution of a
++    sub-statement, to keep track of non-transactional changes in a
++    sub-statement, we re-use stmt.modified_non_trans_table. 
++    At entrance into a sub-statement, a copy of the value of
++    stmt.modified_non_trans_table (containing the changes of the
++    outer statement) is saved on stack. Then 
++    stmt.modified_non_trans_table is reset to FALSE and the
++    substatement is executed. Then the new value is merged with the
++    saved value.
++  */
++  bool modified_non_trans_table;
++} THD_TRANS;
++
++enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
++			 ISO_REPEATABLE_READ, ISO_SERIALIZABLE};
++
++typedef struct st_ha_create_information
++{
++  CHARSET_INFO *table_charset, *default_table_charset;
++  LEX_STRING connect_string;
++  LEX_STRING comment;
++  const char *password;
++  const char *data_file_name, *index_file_name;
++  const char *alias;
++  ulonglong max_rows,min_rows;
++  ulonglong auto_increment_value;
++  ulong table_options;
++  ulong avg_row_length;
++  ulong raid_chunksize;
++  ulong used_fields;
++  SQL_LIST merge_list;
++  enum db_type db_type;
++  enum row_type row_type;
++  uint null_bits;                       /* NULL bits at start of record */
++  uint options;				/* OR of HA_CREATE_ options */
++  uint raid_type,raid_chunks;
++  uint merge_insert_method;
++  uint extra_size;                      /* length of extra data segment */
++  bool table_existed;			/* 1 in create if table existed */
++  bool frm_only;                        /* 1 if no ha_create_table() */
++  bool varchar;                         /* 1 if table has a VARCHAR */
++} HA_CREATE_INFO;
++
++
++/* The handler for a table type.  Will be included in the TABLE structure */
++
++struct st_table;
++typedef struct st_table TABLE;
++struct st_foreign_key_info;
++typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
++
++typedef struct st_savepoint SAVEPOINT;
++extern ulong savepoint_alloc_size;
++
++/* Forward declaration for condition pushdown to storage engine */
++typedef class Item COND;
++
++typedef struct st_ha_check_opt
++{
++  st_ha_check_opt() {}                        /* Remove gcc warning */
++  ulong sort_buffer_size;
++  uint flags;       /* isam layer flags (e.g. for myisamchk) */
++  uint sql_flags;   /* sql layer flags - for something myisamchk cannot do */
++  KEY_CACHE *key_cache;	/* new key cache when changing key cache */
++  void init();
++} HA_CHECK_OPT;
++
++
++/*
++  This is a buffer area that the handler can use to store rows.
++  'end_of_used_area' should be kept updated after calls to
++  read-functions so that other parts of the code can use the
++  remaining area (until next read calls is issued).
++*/
++
++typedef struct st_handler_buffer
++{
++  const byte *buffer;         /* Buffer one can start using */
++  const byte *buffer_end;     /* End of buffer */
++  byte *end_of_used_area;     /* End of area that was used by handler */
++} HANDLER_BUFFER;
++
++
++class handler :public Sql_alloc
++{
++ protected:
++  struct st_table *table;		/* The table definition */
++
++  virtual int index_init(uint idx) { active_index=idx; return 0; }
++  virtual int index_end() { active_index=MAX_KEY; return 0; }
++  /*
++    rnd_init() can be called two times without rnd_end() in between
++    (it only makes sense if scan=1).
++    then the second call should prepare for the new table scan (e.g
++    if rnd_init allocates the cursor, second call should position it
++    to the start of the table, no need to deallocate and allocate it again
++  */
++  virtual int rnd_init(bool scan) =0;
++  virtual int rnd_end() { return 0; }
++  /**
++    Is not invoked for non-transactional temporary tables.
++
++    Tells the storage engine that we intend to read or write data
++    from the table. This call is prefixed with a call to handler::store_lock()
++    and is invoked only for those handler instances that stored the lock.
++
++    Calls to rnd_init/index_init are prefixed with this call. When table
++    IO is complete, we call external_lock(F_UNLCK).
++    A storage engine writer should expect that each call to
++    ::external_lock(F_[RD|WR]LOCK is followed by a call to
++    ::external_lock(F_UNLCK). If it is not, it is a bug in MySQL.
++
++    The name and signature originate from the first implementation
++    in MyISAM, which would call fcntl to set/clear an advisory
++    lock on the data file in this method.
++
++    @param   lock_type    F_RDLCK, F_WRLCK, F_UNLCK
++
++    @return  non-0 in case of failure, 0 in case of success.
++    When lock_type is F_UNLCK, the return value is ignored.
++  */
++  virtual int external_lock(THD *thd, int lock_type) { return 0; }
++
++public:
++  const handlerton *ht;                 /* storage engine of this handler */
++  byte *ref;				/* Pointer to current row */
++  byte *dupp_ref;			/* Pointer to dupp row */
++  ulonglong data_file_length;		/* Length off data file */
++  ulonglong max_data_file_length;	/* Length off data file */
++  ulonglong index_file_length;
++  ulonglong max_index_file_length;
++  ulonglong delete_length;		/* Free bytes */
++  ulonglong auto_increment_value;
++  ha_rows records;			/* Records in table */
++  ha_rows deleted;			/* Deleted records */
++  ulong raid_chunksize;
++  ulong mean_rec_length;		/* physical reclength */
++  time_t create_time;			/* When table was created */
++  time_t check_time;
++  time_t update_time;
++
++  /* The following are for read_multi_range */
++  bool multi_range_sorted;
++  KEY_MULTI_RANGE *multi_range_curr;
++  KEY_MULTI_RANGE *multi_range_end;
++  HANDLER_BUFFER *multi_range_buffer;
++
++  /* The following are for read_range() */
++  key_range save_end_range, *end_range;
++  KEY_PART_INFO *range_key_part;
++  int key_compare_result_on_equal;
++  bool eq_range;
++
++  uint errkey;				/* Last dup key */
++  uint sortkey, key_used_on_scan;
++  uint active_index;
++  /* Length of ref (1-8 or the clustered key length) */
++  uint ref_length;
++  uint block_size;			/* index block size */
++  uint raid_type,raid_chunks;
++  FT_INFO *ft_handler;
++  enum {NONE=0, INDEX, RND} inited;
++  bool locked;
++  bool  auto_increment_column_changed;
++  bool implicit_emptied;                /* Can be !=0 only if HEAP */
++  const COND *pushed_cond;
++
++  handler(const handlerton *ht_arg, TABLE *table_arg) :table(table_arg),
++    ht(ht_arg),
++    ref(0), data_file_length(0), max_data_file_length(0), index_file_length(0),
++    delete_length(0), auto_increment_value(0),
++    records(0), deleted(0), mean_rec_length(0),
++    create_time(0), check_time(0), update_time(0),
++    key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
++    ref_length(sizeof(my_off_t)), block_size(0),
++    raid_type(0), ft_handler(0), inited(NONE),
++    locked(FALSE), implicit_emptied(0),
++    pushed_cond(NULL)
++    {}
++  virtual ~handler(void) { DBUG_ASSERT(locked == FALSE); /* TODO: DBUG_ASSERT(inited == NONE); */ }
++  virtual handler *clone(MEM_ROOT *mem_root);
++  int ha_open(const char *name, int mode, int test_if_locked);
++  void adjust_next_insert_id_after_explicit_value(ulonglong nr);
++  int update_auto_increment();
++  virtual void print_error(int error, myf errflag);
++  virtual bool get_error_message(int error, String *buf);
++  uint get_dup_key(int error);
++  void change_table_ptr(TABLE *table_arg) { table=table_arg; }
++  virtual double scan_time()
++    { return ulonglong2double(data_file_length) / IO_SIZE + 2; }
++  virtual double read_time(uint index, uint ranges, ha_rows rows)
++ { return rows2double(ranges+rows); }
++  virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; }
++  virtual bool has_transactions(){ return 0;}
++  virtual uint extra_rec_buf_length() { return 0; }
++
++  /*
++    Return upper bound of current number of records in the table
++    (max. of how many records one will retrieve when doing a full table scan)
++    If upper bound is not known, HA_POS_ERROR should be returned as a max
++    possible upper bound.
++  */
++  virtual ha_rows estimate_rows_upper_bound()
++  { return records+EXTRA_RECORDS; }
++
++  /*
++    Get the row type from the storage engine.  If this method returns
++    ROW_TYPE_NOT_USED, the information in HA_CREATE_INFO should be used.
++  */
++  virtual enum row_type get_row_type() const { return ROW_TYPE_NOT_USED; }
++
++  virtual const char *index_type(uint key_number) { DBUG_ASSERT(0); return "";}
++
++  int ha_external_lock(THD *thd, int lock_type)
++  {
++    DBUG_ENTER("ha_external_lock");
++    locked= lock_type != F_UNLCK;
++    DBUG_RETURN(external_lock(thd, lock_type));
++  }
++  int ha_index_init(uint idx)
++  {
++    DBUG_ENTER("ha_index_init");
++    DBUG_ASSERT(inited==NONE);
++    inited=INDEX;
++    DBUG_RETURN(index_init(idx));
++  }
++  int ha_index_end()
++  {
++    DBUG_ENTER("ha_index_end");
++    DBUG_ASSERT(inited==INDEX);
++    inited=NONE;
++    DBUG_RETURN(index_end());
++  }
++  int ha_rnd_init(bool scan)
++  {
++    DBUG_ENTER("ha_rnd_init");
++    DBUG_ASSERT(inited==NONE || (inited==RND && scan));
++    inited=RND;
++    DBUG_RETURN(rnd_init(scan));
++  }
++  int ha_rnd_end()
++  {
++    DBUG_ENTER("ha_rnd_end");
++    DBUG_ASSERT(inited==RND);
++    inited=NONE;
++    DBUG_RETURN(rnd_end());
++  }
++  /* this is necessary in many places, e.g. in HANDLER command */
++  int ha_index_or_rnd_end()
++  {
++    return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
++  }
++  uint get_index(void) const { return active_index; }
++  virtual int open(const char *name, int mode, uint test_if_locked)=0;
++  virtual int close(void)=0;
++  virtual int write_row(byte * buf) { return  HA_ERR_WRONG_COMMAND; }
++  virtual int update_row(const byte * old_data, byte * new_data)
++   { return  HA_ERR_WRONG_COMMAND; }
++  virtual int delete_row(const byte * buf)
++   { return  HA_ERR_WRONG_COMMAND; }
++  virtual int index_read(byte * buf, const byte * key,
++			 uint key_len, enum ha_rkey_function find_flag)
++   { return  HA_ERR_WRONG_COMMAND; }
++  virtual int index_read_idx(byte * buf, uint index, const byte * key,
++			     uint key_len, enum ha_rkey_function find_flag);
++  virtual int index_next(byte * buf)
++   { return  HA_ERR_WRONG_COMMAND; }
++  virtual int index_prev(byte * buf)
++   { return  HA_ERR_WRONG_COMMAND; }
++  virtual int index_first(byte * buf)
++   { return  HA_ERR_WRONG_COMMAND; }
++  virtual int index_last(byte * buf)
++   { return  HA_ERR_WRONG_COMMAND; }
++  virtual int index_next_same(byte *buf, const byte *key, uint keylen);
++  virtual int index_read_last(byte * buf, const byte * key, uint key_len)
++   { return (my_errno=HA_ERR_WRONG_COMMAND); }
++  virtual int read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
++                                     KEY_MULTI_RANGE *ranges, uint range_count,
++                                     bool sorted, HANDLER_BUFFER *buffer);
++  virtual int read_multi_range_next(KEY_MULTI_RANGE **found_range_p);
++  virtual int read_range_first(const key_range *start_key,
++                               const key_range *end_key,
++                               bool eq_range, bool sorted);
++  virtual int read_range_next();
++  int compare_key(key_range *range);
++  virtual int ft_init() { return HA_ERR_WRONG_COMMAND; }
++  void ft_end() { ft_handler=NULL; }
++  virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key)
++    { return NULL; }
++  virtual int ft_read(byte *buf) { return HA_ERR_WRONG_COMMAND; }
++  virtual int rnd_next(byte *buf)=0;
++  virtual int rnd_pos(byte * buf, byte *pos)=0;
++  virtual int read_first_row(byte *buf, uint primary_key);
++  /*
++    The following function is only needed for tables that may be temporary
++    tables during joins
++  */
++  virtual int restart_rnd_next(byte *buf, byte *pos)
++    { return HA_ERR_WRONG_COMMAND; }
++  virtual int rnd_same(byte *buf, uint inx)
++    { return HA_ERR_WRONG_COMMAND; }
++  virtual ha_rows records_in_range(uint inx, key_range *min_key,
++                                   key_range *max_key)
++    { return (ha_rows) 10; }
++  virtual void position(const byte *record)=0;
++  virtual int info(uint)=0; // see my_base.h for full description
++  virtual int extra(enum ha_extra_function operation)
++  { return 0; }
++  virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
++  { return extra(operation); }
++  virtual int reset() { return extra(HA_EXTRA_RESET); }
++  virtual void unlock_row() {}
++  virtual int start_stmt(THD *thd, thr_lock_type lock_type) {return 0;}
++  /*
++    This is called to delete all rows in a table
++    If the handler don't support this, then this function will
++    return HA_ERR_WRONG_COMMAND and MySQL will delete the rows one
++    by one.
++  */
++  virtual int delete_all_rows()
++  { return (my_errno=HA_ERR_WRONG_COMMAND); }
++  virtual ulonglong get_auto_increment();
++  virtual void restore_auto_increment();
++
++  /*
++    Reset the auto-increment counter to the given value, i.e. the next row
++    inserted will get the given value. This is called e.g. after TRUNCATE
++    is emulated by doing a 'DELETE FROM t'. HA_ERR_WRONG_COMMAND is
++    returned by storage engines that don't support this operation.
++  */
++  virtual int reset_auto_increment(ulonglong value)
++  { return HA_ERR_WRONG_COMMAND; }
++
++  virtual void update_create_info(HA_CREATE_INFO *create_info) {}
++protected:
++  /* to be implemented in handlers */
++
++  /* admin commands - called from mysql_admin_table */
++  virtual int check(THD* thd, HA_CHECK_OPT* check_opt)
++  { return HA_ADMIN_NOT_IMPLEMENTED; }
++
++  /*
++     in these two methods check_opt can be modified
++     to specify CHECK option to use to call check()
++     upon the table
++  */
++  virtual int check_for_upgrade(HA_CHECK_OPT *check_opt)
++  { return 0; }
++public:
++  int ha_check_for_upgrade(HA_CHECK_OPT *check_opt);
++  int check_old_types();
++  /* to be actually called to get 'check()' functionality*/
++  int ha_check(THD *thd, HA_CHECK_OPT *check_opt);
++
++  virtual int backup(THD* thd, HA_CHECK_OPT* check_opt)
++  { return HA_ADMIN_NOT_IMPLEMENTED; }
++  /*
++    restore assumes .frm file must exist, and that generate_table() has been
++    called; It will just copy the data file and run repair.
++  */
++  virtual int restore(THD* thd, HA_CHECK_OPT* check_opt)
++  { return HA_ADMIN_NOT_IMPLEMENTED; }
++protected:
++  virtual int repair(THD* thd, HA_CHECK_OPT* check_opt)
++  { return HA_ADMIN_NOT_IMPLEMENTED; }
++public:
++  int ha_repair(THD* thd, HA_CHECK_OPT* check_opt);
++  virtual int optimize(THD* thd, HA_CHECK_OPT* check_opt)
++  { return HA_ADMIN_NOT_IMPLEMENTED; }
++  virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt)
++  { return HA_ADMIN_NOT_IMPLEMENTED; }
++  virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt)
++  { return HA_ADMIN_NOT_IMPLEMENTED; }
++  virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt)
++  { return HA_ADMIN_NOT_IMPLEMENTED; }
++  /* end of the list of admin commands */
++
++  virtual bool check_and_repair(THD *thd) { return HA_ERR_WRONG_COMMAND; }
++  virtual int dump(THD* thd, int fd = -1) { return HA_ERR_WRONG_COMMAND; }
++  virtual int disable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
++  virtual int enable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
++  virtual int indexes_are_disabled(void) {return 0;}
++  virtual void start_bulk_insert(ha_rows rows) {}
++  virtual int end_bulk_insert() {return 0; }
++  virtual int discard_or_import_tablespace(my_bool discard)
++  {return HA_ERR_WRONG_COMMAND;}
++  virtual int net_read_dump(NET* net) { return HA_ERR_WRONG_COMMAND; }
++  virtual char *update_table_comment(const char * comment)
++  { return (char*) comment;}
++  virtual void append_create_info(String *packet) {}
++  virtual char* get_foreign_key_create_info()
++  { return(NULL);}  /* gets foreign key create string from InnoDB */
++  /* used in ALTER TABLE; 1 if changing storage engine is allowed */
++  virtual bool can_switch_engines() { return 1; }
++  /* used in REPLACE; is > 0 if table is referred by a FOREIGN KEY */
++  virtual int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
++  { return 0; }
++  virtual uint referenced_by_foreign_key() { return 0;}
++  virtual void init_table_handle_for_HANDLER()
++  { return; }       /* prepare InnoDB for HANDLER */
++  virtual void free_foreign_key_create_info(char* str) {}
++  /* The following can be called without an open handler */
++  virtual const char *table_type() const =0;
++  /*
++    If frm_error() is called then we will use this to find out what file
++    extentions exist for the storage engine. This is also used by the default
++    rename_table and delete_table method in handler.cc.
++
++    For engines that have two file name extentions (separate meta/index file
++    and data file), the order of elements is relevant. First element of engine
++    file name extentions array should be meta/index file extention. Second
++    element - data file extention. This order is assumed by
++    prepare_for_repair() when REPAIR TABLE ... USE_FRM is issued.
++  */
++  virtual const char **bas_ext() const =0;
++  virtual ulong table_flags(void) const =0;
++  virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0;
++  virtual ulong index_ddl_flags(KEY *wanted_index) const
++  { return (HA_DDL_SUPPORT); }
++  virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys)
++  { return (HA_ERR_WRONG_COMMAND); }
++  virtual int drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys)
++  { return (HA_ERR_WRONG_COMMAND); }
++
++  uint max_record_length() const
++  { return min(HA_MAX_REC_LENGTH, max_supported_record_length()); }
++  uint max_keys() const
++  { return min(MAX_KEY, max_supported_keys()); }
++  uint max_key_parts() const
++  { return min(MAX_REF_PARTS, max_supported_key_parts()); }
++  uint max_key_length() const
++  { return min(MAX_KEY_LENGTH, max_supported_key_length()); }
++  uint max_key_part_length() const
++  { return min(MAX_KEY_LENGTH, max_supported_key_part_length()); }
++
++  virtual uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
++  virtual uint max_supported_keys() const { return 0; }
++  virtual uint max_supported_key_parts() const { return MAX_REF_PARTS; }
++  virtual uint max_supported_key_length() const { return MAX_KEY_LENGTH; }
++  virtual uint max_supported_key_part_length() const { return 255; }
++  virtual uint min_record_length(uint options) const { return 1; }
++
++  virtual bool low_byte_first() const { return 1; }
++  virtual uint checksum() const { return 0; }
++  virtual bool is_crashed() const  { return 0; }
++  virtual bool auto_repair() const { return 0; }
++
++  /*
++    default rename_table() and delete_table() rename/delete files with a
++    given name and extensions from bas_ext()
++  */
++  virtual int rename_table(const char *from, const char *to);
++  virtual int delete_table(const char *name);
++
++  virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
++
++  /* lock_count() can be more than one if the table is a MERGE */
++  virtual uint lock_count(void) const { return 1; }
++  /**
++    Is not invoked for non-transactional temporary tables.
++  */
++  virtual THR_LOCK_DATA **store_lock(THD *thd,
++				     THR_LOCK_DATA **to,
++				     enum thr_lock_type lock_type)=0;
++
++  /* Type of table for caching query */
++  virtual uint8 table_cache_type() { return HA_CACHE_TBL_NONTRANSACT; }
++
++
++  /**
++    @brief Register a named table with a call back function to the query cache.
++
++    @param thd The thread handle
++    @param table_key A pointer to the table name in the table cache
++    @param key_length The length of the table name
++    @param[out] engine_callback The pointer to the storage engine call back
++      function
++    @param[out] engine_data Storage engine specific data which could be
++      anything
++
++    This method offers the storage engine, the possibility to store a reference
++    to a table name which is going to be used with query cache. 
++    The method is called each time a statement is written to the cache and can
++    be used to verify if a specific statement is cachable. It also offers
++    the possibility to register a generic (but static) call back function which
++    is called each time a statement is matched against the query cache.
++
++    @note If engine_data supplied with this function is different from
++      engine_data supplied with the callback function, and the callback returns
++      FALSE, a table invalidation on the current table will occur.
++
++    @return Upon success the engine_callback will point to the storage engine
++      call back function, if any, and engine_data will point to any storage
++      engine data used in the specific implementation.
++      @retval TRUE Success
++      @retval FALSE The specified table or current statement should not be
++        cached
++  */
++
++  virtual my_bool register_query_cache_table(THD *thd, char *table_key,
++                                             uint key_length,
++                                             qc_engine_callback
++                                             *engine_callback,
++                                             ulonglong *engine_data)
++  {
++    *engine_callback= 0;
++    return TRUE;
++  }
++
++
++ /*
++  RETURN
++    true  Primary key (if there is one) is clustered key covering all fields
++    false otherwise
++ */
++ virtual bool primary_key_is_clustered() { return FALSE; }
++
++ virtual int cmp_ref(const byte *ref1, const byte *ref2)
++ {
++   return memcmp(ref1, ref2, ref_length);
++ }
++
++ /*
++   Condition pushdown to storage engines
++ */
++
++ /*
++   Push condition down to the table handler.
++   SYNOPSIS
++     cond_push()
++     cond   Condition to be pushed. The condition tree must not be
++     modified by the by the caller.
++   RETURN
++     The 'remainder' condition that caller must use to filter out records.
++     NULL means the handler will not return rows that do not match the
++     passed condition.
++   NOTES
++   The pushed conditions form a stack (from which one can remove the
++   last pushed condition using cond_pop).
++   The table handler filters out rows using (pushed_cond1 AND pushed_cond2
++   AND ... AND pushed_condN)
++   or less restrictive condition, depending on handler's capabilities.
++
++   handler->extra(HA_EXTRA_RESET) call empties the condition stack.
++   Calls to rnd_init/rnd_end, index_init/index_end etc do not affect the
++   condition stack.
++ */
++ virtual const COND *cond_push(const COND *cond) { return cond; };
++ /*
++   Pop the top condition from the condition stack of the handler instance.
++   SYNOPSIS
++     cond_pop()
++     Pops the top if condition stack, if stack is not empty
++ */
++ virtual void cond_pop() { return; };
++};
++
++	/* Some extern variables used with handlers */
++
++extern handlerton *sys_table_types[];
++extern const char *ha_row_type[];
++extern TYPELIB tx_isolation_typelib;
++extern TYPELIB myisam_stats_method_typelib;
++extern ulong total_ha, total_ha_2pc;
++
++	/* Wrapper functions */
++#define ha_commit_stmt(thd) (ha_commit_trans((thd), FALSE))
++#define ha_rollback_stmt(thd) (ha_rollback_trans((thd), FALSE))
++#define ha_commit(thd) (ha_commit_trans((thd), TRUE))
++#define ha_rollback(thd) (ha_rollback_trans((thd), TRUE))
++
++/* lookups */
++enum db_type ha_resolve_by_name(const char *name, uint namelen);
++const char *ha_get_storage_engine(enum db_type db_type);
++handler *get_new_handler(TABLE *table, MEM_ROOT *alloc, enum db_type db_type);
++enum db_type ha_checktype(THD *thd, enum db_type database_type,
++                          bool no_substitute, bool report_error);
++bool ha_check_storage_engine_flag(enum db_type db_type, uint32 flag);
++
++/* basic stuff */
++int ha_init(void);
++TYPELIB *ha_known_exts(void);
++int ha_panic(enum ha_panic_function flag);
++int ha_update_statistics();
++void ha_close_connection(THD* thd);
++my_bool ha_storage_engine_is_enabled(enum db_type database_type);
++bool ha_flush_logs(void);
++void ha_drop_database(char* path);
++int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
++		    bool update_create_info);
++int ha_delete_table(THD *thd, enum db_type db_type, const char *path,
++                    const char *alias, bool generate_warning);
++
++/* discovery */
++int ha_create_table_from_engine(THD* thd, const char *db, const char *name);
++int ha_discover(THD* thd, const char* dbname, const char* name,
++                const void** frmblob, uint* frmlen);
++int ha_find_files(THD *thd,const char *db,const char *path,
++                  const char *wild, bool dir,List<char>* files);
++int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
++
++/* key cache */
++int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
++int ha_resize_key_cache(KEY_CACHE *key_cache);
++int ha_change_key_cache_param(KEY_CACHE *key_cache);
++int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
++int ha_end_key_cache(KEY_CACHE *key_cache);
++
++/* report to InnoDB that control passes to the client */
++int ha_release_temporary_latches(THD *thd);
++
++/* transactions: interface to handlerton functions */
++int ha_start_consistent_snapshot(THD *thd);
++int ha_commit_or_rollback_by_xid(XID *xid, bool commit);
++int ha_commit_one_phase(THD *thd, bool all);
++int ha_rollback_trans(THD *thd, bool all);
++int ha_prepare(THD *thd);
++int ha_recover(HASH *commit_list);
++
++/* transactions: these functions never call handlerton functions directly */
++int ha_commit_trans(THD *thd, bool all);
++int ha_autocommit_or_rollback(THD *thd, int error);
++int ha_enable_transaction(THD *thd, bool on);
++
++/* savepoints */
++int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv);
++int ha_savepoint(THD *thd, SAVEPOINT *sv);
++int ha_release_savepoint(THD *thd, SAVEPOINT *sv);
++
++/* these are called by storage engines */
++void trans_register_ha(THD *thd, bool all, handlerton *ht);
++
++/*
++  Storage engine has to assume the transaction will end up with 2pc if
++   - there is more than one 2pc-capable storage engine available
++   - in the current transaction 2pc was not disabled yet
++*/
++#define trans_need_2pc(thd, all)                   ((total_ha_2pc > 1) && \
++        !((all ? &thd->transaction.all : &thd->transaction.stmt)->no_2pc))
+diff -urNad trunk~/sql/mysql_priv.h trunk/sql/mysql_priv.h
+--- trunk~/sql/mysql_priv.h	2007-11-15 08:06:52.000000000 -0600
++++ trunk/sql/mysql_priv.h	2007-12-27 15:54:49.274262862 -0600
+@@ -1408,6 +1408,12 @@
+ #else
+ extern SHOW_COMP_OPTION have_csv_db;
+ #endif
++#ifdef HAVE_SPHINX_DB
++extern handlerton sphinx_hton;
++#define have_sphinx_db sphinx_hton.state
++#else
++extern SHOW_COMP_OPTION have_sphinx_db;
++#endif
+ #ifdef HAVE_FEDERATED_DB
+ extern handlerton federated_hton;
+ #define have_federated_db federated_hton.state
+diff -urNad trunk~/sql/mysql_priv.h.orig trunk/sql/mysql_priv.h.orig
+--- trunk~/sql/mysql_priv.h.orig	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/mysql_priv.h.orig	2007-12-27 15:54:49.278263090 -0600
+@@ -0,0 +1,1761 @@
++/* Copyright (C) 2000-2003 MySQL AB
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; version 2 of the License.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
++
++/*
++  Mostly this file is used in the server. But a little part of it is used in
++  mysqlbinlog too (definition of SELECT_DISTINCT and others).
++  The consequence is that 90% of the file is wrapped in #ifndef MYSQL_CLIENT,
++  except the part which must be in the server and in the client.
++*/
++
++#ifndef MYSQL_PRIV_H_INCLUDED
++#define MYSQL_PRIV_H_INCLUDED
++
++#ifndef MYSQL_CLIENT
++
++#include <my_global.h>
++#include <mysql_version.h>
++#include <mysql_embed.h>
++#include <my_sys.h>
++#include <my_time.h>
++#include <m_string.h>
++#include <hash.h>
++#include <signal.h>
++#include <thr_lock.h>
++#include <my_base.h>			/* Needed by field.h */
++#include "sql_bitmap.h"
++#include "sql_array.h"
++
++#ifdef __EMX__
++#undef write  /* remove pthread.h macro definition for EMX */
++#endif
++
++/* TODO convert all these three maps to Bitmap classes */
++typedef ulonglong table_map;          /* Used for table bits in join */
++#if MAX_INDEXES <= 64
++typedef Bitmap<64>  key_map;          /* Used for finding keys */
++#else
++typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */
++#endif
++typedef ulong key_part_map;           /* Used for finding key parts */
++typedef ulong nesting_map;  /* Used for flags of nesting constructs */
++/*
++  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;
++extern query_id_t global_query_id;
++
++/* increment query_id and return it.  */
++inline query_id_t next_query_id() { return global_query_id++; }
++
++/* useful constants */
++extern const key_map key_map_empty;
++extern key_map key_map_full;          /* Should be threaded as const */
++extern const char *primary_key_name;
++
++#include "mysql_com.h"
++#include <violite.h>
++#include "unireg.h"
++
++void init_sql_alloc(MEM_ROOT *root, uint block_size, uint pre_alloc_size);
++gptr sql_alloc(unsigned size);
++gptr sql_calloc(unsigned size);
++char *sql_strdup(const char *str);
++char *sql_strmake(const char *str,uint len);
++gptr sql_memdup(const void * ptr,unsigned size);
++void sql_element_free(void *ptr);
++char *sql_strmake_with_convert(const char *str, uint32 arg_length,
++			       CHARSET_INFO *from_cs,
++			       uint32 max_res_length,
++			       CHARSET_INFO *to_cs, uint32 *result_length);
++void kill_one_thread(THD *thd, ulong id, bool only_kill_query);
++bool net_request_file(NET* net, const char* fname);
++char* query_table_status(THD *thd,const char *db,const char *table_name);
++
++#define x_free(A)	{ my_free((gptr) (A),MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); }
++#define safeFree(x)	{ if(x) { my_free((gptr) x,MYF(0)); x = NULL; } }
++#define PREV_BITS(type,A)	((type) (((type) 1 << (A)) -1))
++#define all_bits_set(A,B) ((A) & (B) != (B))
++
++#define WARN_DEPRECATED(Thd,Ver,Old,New)                                             \
++  do {                                                                               \
++    DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) > 0);              \
++    if (((gptr)Thd) != NULL)                                                         \
++      push_warning_printf(((THD *)Thd), MYSQL_ERROR::WARN_LEVEL_WARN,                \
++                        ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX),    \
++                        (Old), (Ver), (New));                                        \
++    else                                                                             \
++      sql_print_warning("The syntax %s is deprecated and will be removed "           \
++                        "in MySQL %s. Please use %s instead.", (Old), (Ver), (New)); \
++  } while(0)
++
++extern CHARSET_INFO *system_charset_info, *files_charset_info ;
++extern CHARSET_INFO *national_charset_info, *table_alias_charset;
++
++
++enum Derivation
++{
++  DERIVATION_IGNORABLE= 5,
++  DERIVATION_COERCIBLE= 4,
++  DERIVATION_SYSCONST= 3,
++  DERIVATION_IMPLICIT= 2,
++  DERIVATION_NONE= 1,
++  DERIVATION_EXPLICIT= 0
++};
++
++
++typedef struct my_locale_st
++{
++  uint  number;
++  const char *name;
++  const char *description;
++  const bool is_ascii;
++  TYPELIB *month_names;
++  TYPELIB *ab_month_names;
++  TYPELIB *day_names;
++  TYPELIB *ab_day_names;
++#ifdef __cplusplus 
++  my_locale_st(uint number_par,
++               const char *name_par, const char *descr_par, bool is_ascii_par,
++               TYPELIB *month_names_par, TYPELIB *ab_month_names_par,
++               TYPELIB *day_names_par, TYPELIB *ab_day_names_par) : 
++    number(number_par),
++    name(name_par), description(descr_par), is_ascii(is_ascii_par),
++    month_names(month_names_par), ab_month_names(ab_month_names_par),
++    day_names(day_names_par), ab_day_names(ab_day_names_par)
++  {}
++#endif
++} MY_LOCALE;
++
++extern MY_LOCALE my_locale_en_US;
++extern MY_LOCALE *my_locales[];
++extern MY_LOCALE *my_default_lc_time_names;
++
++MY_LOCALE *my_locale_by_name(const char *name);
++MY_LOCALE *my_locale_by_number(uint number);
++
++/***************************************************************************
++  Configuration parameters
++****************************************************************************/
++
++#define ACL_CACHE_SIZE		256
++#define MAX_PASSWORD_LENGTH	32
++#define HOST_CACHE_SIZE		128
++#define MAX_ACCEPT_RETRY	10	// Test accept this many times
++#define MAX_FIELDS_BEFORE_HASH	32
++#define USER_VARS_HASH_SIZE     16
++#define TABLE_OPEN_CACHE_MIN    64
++#define TABLE_OPEN_CACHE_DEFAULT 64
++
++/* 
++ Value of 9236 discovered through binary search 2006-09-26 on Ubuntu Dapper
++ Drake, libc6 2.3.6-0ubuntu2, Linux kernel 2.6.15-27-686, on x86.  (Added 
++ 100 bytes as reasonable buffer against growth and other environments'
++ requirements.)
++
++ Feel free to raise this by the smallest amount you can to get the
++ "execution_constants" test to pass.
++ */
++#define STACK_MIN_SIZE          12000   // Abort if less stack during eval.
++
++#define STACK_MIN_SIZE_FOR_OPEN 1024*80
++#define STACK_BUFF_ALLOC        352     // For stack overrun checks
++#ifndef MYSQLD_NET_RETRY_COUNT
++#define MYSQLD_NET_RETRY_COUNT  10	// Abort read after this many int.
++#endif
++#define TEMP_POOL_SIZE          128
++
++#define QUERY_ALLOC_BLOCK_SIZE		8192
++#define QUERY_ALLOC_PREALLOC_SIZE   	8192
++#define TRANS_ALLOC_BLOCK_SIZE		4096
++#define TRANS_ALLOC_PREALLOC_SIZE	4096
++#define RANGE_ALLOC_BLOCK_SIZE		2048
++#define ACL_ALLOC_BLOCK_SIZE		1024
++#define UDF_ALLOC_BLOCK_SIZE		1024
++#define TABLE_ALLOC_BLOCK_SIZE		1024
++#define BDB_LOG_ALLOC_BLOCK_SIZE	1024
++#define WARN_ALLOC_BLOCK_SIZE		2048
++#define WARN_ALLOC_PREALLOC_SIZE	1024
++#define PROFILE_ALLOC_BLOCK_SIZE  2048
++#define PROFILE_ALLOC_PREALLOC_SIZE 1024
++
++/*
++  The following parameters is to decide when to use an extra cache to
++  optimise seeks when reading a big table in sorted order
++*/
++#define MIN_FILE_LENGTH_TO_USE_ROW_CACHE (10L*1024*1024)
++#define MIN_ROWS_TO_USE_TABLE_CACHE	 100
++#define MIN_ROWS_TO_USE_BULK_INSERT	 100
++
++/*
++  The following is used to decide if MySQL should use table scanning
++  instead of reading with keys.  The number says how many evaluation of the
++  WHERE clause is comparable to reading one extra row from a table.
++*/
++#define TIME_FOR_COMPARE   5	// 5 compares == one read
++
++/*
++  Number of comparisons of table rowids equivalent to reading one row from a 
++  table.
++*/
++#define TIME_FOR_COMPARE_ROWID  (TIME_FOR_COMPARE*2)
++
++/*
++  For sequential disk seeks the cost formula is:
++    DISK_SEEK_BASE_COST + DISK_SEEK_PROP_COST * #blocks_to_skip  
++  
++  The cost of average seek 
++    DISK_SEEK_BASE_COST + DISK_SEEK_PROP_COST*BLOCKS_IN_AVG_SEEK =1.0.
++*/
++#define DISK_SEEK_BASE_COST ((double)0.5)
++
++#define BLOCKS_IN_AVG_SEEK  128
++
++#define DISK_SEEK_PROP_COST ((double)0.5/BLOCKS_IN_AVG_SEEK)
++
++
++/*
++  Number of rows in a reference table when refereed through a not unique key.
++  This value is only used when we don't know anything about the key
++  distribution.
++*/
++#define MATCHING_ROWS_IN_OTHER_TABLE 10
++
++/* Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used) */
++#define KEY_DEFAULT_PACK_LENGTH 8
++
++/* Characters shown for the command in 'show processlist' */
++#define PROCESS_LIST_WIDTH 100
++
++#define PRECISION_FOR_DOUBLE 53
++#define PRECISION_FOR_FLOAT  24
++
++/* The following can also be changed from the command line */
++#define CONNECT_TIMEOUT		5		// Do not wait long for connect
++#define DEFAULT_CONCURRENCY	10
++#define DELAYED_LIMIT		100		/* pause after xxx inserts */
++#define DELAYED_QUEUE_SIZE	1000
++#define DELAYED_WAIT_TIMEOUT	5*60		/* Wait for delayed insert */
++#define FLUSH_TIME		0		/* Don't flush tables */
++#define MAX_CONNECT_ERRORS	10		// errors before disabling host
++
++#ifdef HAVE_INNOBASE_DB
++#define IF_INNOBASE_DB(A, B) (A)
++#else
++#define IF_INNOBASE_DB(A, B) (B)
++#endif
++#ifdef __NETWARE__
++#define IF_NETWARE(A,B) (A)
++#else
++#define IF_NETWARE(A,B) (B)
++#endif
++
++#if defined(__WIN__) || defined(OS2)
++#undef	FLUSH_TIME
++#define FLUSH_TIME	1800			/* Flush every half hour */
++
++#define INTERRUPT_PRIOR -2
++#define CONNECT_PRIOR	-1
++#define WAIT_PRIOR	0
++#define QUERY_PRIOR	2
++#else
++#define INTERRUPT_PRIOR 10
++#define CONNECT_PRIOR	9
++#define WAIT_PRIOR	8
++#define QUERY_PRIOR	6
++#endif /* __WIN92__ */
++
++	/* Bits from testflag */
++#define TEST_PRINT_CACHED_TABLES 1
++#define TEST_NO_KEY_GROUP	 2
++#define TEST_MIT_THREAD		4
++#define TEST_BLOCKING		8
++#define TEST_KEEP_TMP_TABLES	16
++#define TEST_NO_THREADS		32	/* For debugging under Linux */
++#define TEST_READCHECK		64	/* Force use of readcheck */
++#define TEST_NO_EXTRA		128
++#define TEST_CORE_ON_SIGNAL	256	/* Give core if signal */
++#define TEST_NO_STACKTRACE	512
++#define TEST_SIGINT		1024	/* Allow sigint on threads */
++#define TEST_SYNCHRONIZATION    2048    /* get server to do sleep in
++                                           some places */
++#endif
++
++/*
++   This is included in the server and in the client.
++   Options for select set by the yacc parser (stored in lex->options).
++
++   XXX:
++   log_event.h defines OPTIONS_WRITTEN_TO_BIN_LOG to specify what THD
++   options list are written into binlog. These options can NOT change their
++   values, or it will break replication between version.
++
++   context is encoded as following:
++   SELECT - SELECT_LEX_NODE::options
++   THD    - THD::options
++   intern - neither. used only as
++            func(..., select_node->options | thd->options | OPTION_XXX, ...)
++
++   TODO: separate three contexts above, move them to separate bitfields.
++*/
++
++#define SELECT_DISTINCT         (ULL(1) << 0)     // SELECT, user
++#define SELECT_STRAIGHT_JOIN    (ULL(1) << 1)     // SELECT, user
++#define SELECT_DESCRIBE         (ULL(1) << 2)     // SELECT, user
++#define SELECT_SMALL_RESULT     (ULL(1) << 3)     // SELECT, user
++#define SELECT_BIG_RESULT       (ULL(1) << 4)     // SELECT, user
++#define OPTION_FOUND_ROWS       (ULL(1) << 5)     // SELECT, user
++#define OPTION_TO_QUERY_CACHE   (ULL(1) << 6)     // SELECT, user
++#define SELECT_NO_JOIN_CACHE    (ULL(1) << 7)     // intern
++#define OPTION_BIG_TABLES       (ULL(1) << 8)     // THD, user
++#define OPTION_BIG_SELECTS      (ULL(1) << 9)     // THD, user
++#define OPTION_LOG_OFF          (ULL(1) << 10)    // THD, user
++#define OPTION_UPDATE_LOG       (ULL(1) << 11)    // THD, user, unused
++#define TMP_TABLE_ALL_COLUMNS   (ULL(1) << 12)    // SELECT, intern
++#define OPTION_WARNINGS         (ULL(1) << 13)    // THD, user
++#define OPTION_AUTO_IS_NULL     (ULL(1) << 14)    // THD, user, binlog
++#define OPTION_FOUND_COMMENT    (ULL(1) << 15)    // SELECT, intern, parser
++#define OPTION_SAFE_UPDATES     (ULL(1) << 16)    // THD, user
++#define OPTION_BUFFER_RESULT    (ULL(1) << 17)    // SELECT, user
++#define OPTION_BIN_LOG          (ULL(1) << 18)    // THD, user
++#define OPTION_NOT_AUTOCOMMIT   (ULL(1) << 19)    // THD, user
++#define OPTION_BEGIN            (ULL(1) << 20)    // THD, intern
++#define OPTION_TABLE_LOCK       (ULL(1) << 21)    // THD, intern
++#define OPTION_QUICK            (ULL(1) << 22)    // SELECT (for DELETE)
++#define OPTION_QUOTE_SHOW_CREATE (ULL(1) << 23)   // THD, user
++
++/* Thr following is used to detect a conflict with DISTINCT
++   in the user query has requested */
++#define SELECT_ALL              (ULL(1) << 24)    // SELECT, user, parser
++
++/* The following can be set when importing tables in a 'wrong order'
++   to suppress foreign key checks */
++#define OPTION_NO_FOREIGN_KEY_CHECKS    (ULL(1) << 26) // THD, user, binlog
++/* The following speeds up inserts to InnoDB tables by suppressing unique
++   key checks in some cases */
++#define OPTION_RELAXED_UNIQUE_CHECKS    (ULL(1) << 27) // THD, user, binlog
++#define SELECT_NO_UNLOCK                (ULL(1) << 28) // SELECT, intern
++#define OPTION_SCHEMA_TABLE             (ULL(1) << 29) // SELECT, intern
++/* Flag set if setup_tables already done */
++#define OPTION_SETUP_TABLES_DONE        (ULL(1) << 30) // intern
++/* If not set then the thread will ignore all warnings with level notes. */
++#define OPTION_SQL_NOTES                (ULL(1) << 31) // THD, user
++/* 
++  Force the used temporary table to be a MyISAM table (because we will use
++  fulltext functions when reading from it.
++*/
++#define TMP_TABLE_FORCE_MYISAM          (ULL(1) << 32)
++#define OPTION_PROFILING                (ULL(1) << 33)
++
++
++
++/*
++  Maximum length of time zone name that we support
++  (Time zone name is char(64) in db). mysqlbinlog needs it.
++*/
++#define MAX_TIME_ZONE_NAME_LENGTH 72
++
++/* The rest of the file is included in the server only */
++#ifndef MYSQL_CLIENT
++
++/* Bits for different SQL modes modes (including ANSI mode) */
++#define MODE_REAL_AS_FLOAT              1
++#define MODE_PIPES_AS_CONCAT            2
++#define MODE_ANSI_QUOTES                4
++#define MODE_IGNORE_SPACE		8
++#define MODE_NOT_USED			16
++#define MODE_ONLY_FULL_GROUP_BY		32
++#define MODE_NO_UNSIGNED_SUBTRACTION	64
++#define MODE_NO_DIR_IN_CREATE		128
++#define MODE_POSTGRESQL			256
++#define MODE_ORACLE			512
++#define MODE_MSSQL			1024
++#define MODE_DB2			2048
++#define MODE_MAXDB			4096
++#define MODE_NO_KEY_OPTIONS             8192
++#define MODE_NO_TABLE_OPTIONS           16384 
++#define MODE_NO_FIELD_OPTIONS           32768
++#define MODE_MYSQL323                   65536
++#define MODE_MYSQL40                    (MODE_MYSQL323*2)
++#define MODE_ANSI	                (MODE_MYSQL40*2)
++#define MODE_NO_AUTO_VALUE_ON_ZERO      (MODE_ANSI*2)
++#define MODE_NO_BACKSLASH_ESCAPES       (MODE_NO_AUTO_VALUE_ON_ZERO*2)
++#define MODE_STRICT_TRANS_TABLES	(MODE_NO_BACKSLASH_ESCAPES*2)
++#define MODE_STRICT_ALL_TABLES		(MODE_STRICT_TRANS_TABLES*2)
++#define MODE_NO_ZERO_IN_DATE		(MODE_STRICT_ALL_TABLES*2)
++#define MODE_NO_ZERO_DATE		(MODE_NO_ZERO_IN_DATE*2)
++#define MODE_INVALID_DATES		(MODE_NO_ZERO_DATE*2)
++#define MODE_ERROR_FOR_DIVISION_BY_ZERO (MODE_INVALID_DATES*2)
++#define MODE_TRADITIONAL		(MODE_ERROR_FOR_DIVISION_BY_ZERO*2)
++#define MODE_NO_AUTO_CREATE_USER	(MODE_TRADITIONAL*2)
++#define MODE_HIGH_NOT_PRECEDENCE	(MODE_NO_AUTO_CREATE_USER*2)
++#define MODE_NO_ENGINE_SUBSTITUTION     (MODE_HIGH_NOT_PRECEDENCE*2)
++/*
++  Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
++  use strictly more than 64 bits by adding one more define above, you should
++  contact the replication team because the replication code should then be
++  updated (to store more bytes on disk).
++
++  NOTE: When adding new SQL_MODE types, make sure to also add them to
++  the scripts used for creating the MySQL system tables
++  in scripts/mysql_system_tables.sql and scripts/mysql_system_tables_fix.sql
++
++*/
++
++#define RAID_BLOCK_SIZE 1024
++
++#define MY_CHARSET_BIN_MB_MAXLEN 1
++
++// uncachable cause
++#define UNCACHEABLE_DEPENDENT   1
++#define UNCACHEABLE_RAND        2
++#define UNCACHEABLE_SIDEEFFECT	4
++// forcing to save JOIN for explain
++#define UNCACHEABLE_EXPLAIN     8
++/* Don't evaluate subqueries in prepare even if they're not correlated */
++#define UNCACHEABLE_PREPARE    16
++/* For uncorrelated SELECT in an UNION with some correlated SELECTs */
++#define UNCACHEABLE_UNITED     32
++
++/* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */
++#define UNDEF_POS (-1)
++#ifdef EXTRA_DEBUG
++/*
++  Sync points allow us to force the server to reach a certain line of code
++  and block there until the client tells the server it is ok to go on.
++  The client tells the server to block with SELECT GET_LOCK()
++  and unblocks it with SELECT RELEASE_LOCK(). Used for debugging difficult
++  concurrency problems
++*/
++#define DBUG_SYNC_POINT(lock_name,lock_timeout) \
++ debug_sync_point(lock_name,lock_timeout)
++void debug_sync_point(const char* lock_name, uint lock_timeout);
++#else
++#define DBUG_SYNC_POINT(lock_name,lock_timeout)
++#endif /* EXTRA_DEBUG */
++
++/* BINLOG_DUMP options */
++
++#define BINLOG_DUMP_NON_BLOCK   1
++
++/* sql_show.cc:show_log_files() */
++#define SHOW_LOG_STATUS_FREE "FREE"
++#define SHOW_LOG_STATUS_INUSE "IN USE"
++
++struct TABLE_LIST;
++class String;
++void view_store_options(THD *thd, TABLE_LIST *table, String *buff);
++
++/* Options to add_table_to_list() */
++#define TL_OPTION_UPDATING	1
++#define TL_OPTION_FORCE_INDEX	2
++#define TL_OPTION_IGNORE_LEAVES 4
++#define TL_OPTION_ALIAS         8
++
++/* Some portable defines */
++
++#define portable_sizeof_char_ptr 8
++
++#define tmp_file_prefix "#sql"			/* Prefix for tmp tables */
++#define tmp_file_prefix_length 4
++
++/* Flags for calc_week() function.  */
++#define WEEK_MONDAY_FIRST    1
++#define WEEK_YEAR            2
++#define WEEK_FIRST_WEEKDAY   4
++
++#define STRING_BUFFER_USUAL_SIZE 80
++
++enum enum_parsing_place
++{
++  NO_MATTER,
++  IN_HAVING,
++  SELECT_LIST,
++  IN_WHERE,
++  IN_ON
++};
++
++struct st_table;
++class THD;
++
++/* Struct to handle simple linked lists */
++
++typedef struct st_sql_list {
++  uint elements;
++  byte *first;
++  byte **next;
++
++  st_sql_list() {}                              /* Remove gcc warning */
++  inline void empty()
++  {
++    elements=0;
++    first=0;
++    next= &first;
++  }
++  inline void link_in_list(byte *element,byte **next_ptr)
++  {
++    elements++;
++    (*next)=element;
++    next= next_ptr;
++    *next=0;
++  }
++  inline void save_and_clear(struct st_sql_list *save)
++  {
++    *save= *this;
++    empty();
++  }
++  inline void push_front(struct st_sql_list *save)
++  {
++    *save->next= first;				/* link current list last */
++    first= save->first;
++    elements+= save->elements;
++  }
++  inline void push_back(struct st_sql_list *save)
++  {
++    if (save->first)
++    {
++      *next= save->first;
++      next= save->next;
++      elements+= save->elements;
++    }
++  }
++} SQL_LIST;
++
++
++extern pthread_key(THD*, THR_THD);
++inline THD *_current_thd(void)
++{
++  return my_pthread_getspecific_ptr(THD*,THR_THD);
++}
++#define current_thd _current_thd()
++
++/*
++  External variables
++*/
++extern ulong server_id, concurrency;
++
++
++typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key,
++                                      uint key_length,
++                                      ulonglong *engine_data);
++#include "sql_string.h"
++#include "sql_list.h"
++#include "sql_map.h"
++#include "my_decimal.h"
++#include "handler.h"
++#include "parse_file.h"
++#include "table.h"
++#include "sql_error.h"
++#include "field.h"				/* Field definitions */
++#include "protocol.h"
++#include "sql_udf.h"
++#include "sql_profile.h"
++
++class user_var_entry;
++class Security_context;
++enum enum_var_type
++{
++  OPT_DEFAULT= 0, OPT_SESSION, OPT_GLOBAL
++};
++class sys_var;
++class Comp_creator;
++typedef Comp_creator* (*chooser_compare_func_creator)(bool invert);
++#include "item.h"
++extern my_decimal decimal_zero;
++
++/* sql_parse.cc */
++void free_items(Item *item);
++void cleanup_items(Item *item);
++class THD;
++void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
++bool check_one_table_access(THD *thd, ulong privilege,
++			   TABLE_LIST *tables);
++bool check_single_table_access(THD *thd, ulong privilege,
++			   TABLE_LIST *tables);
++bool check_routine_access(THD *thd,ulong want_access,char *db,char *name,
++			  bool is_proc, bool no_errors);
++bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
++bool check_merge_table_access(THD *thd, char *db,
++			      TABLE_LIST *table_list);
++bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
++bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
++bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);
++bool mysql_multi_update_prepare(THD *thd);
++bool mysql_multi_delete_prepare(THD *thd);
++bool mysql_insert_select_prepare(THD *thd);
++bool update_precheck(THD *thd, TABLE_LIST *tables);
++bool delete_precheck(THD *thd, TABLE_LIST *tables);
++bool insert_precheck(THD *thd, TABLE_LIST *tables);
++bool create_table_precheck(THD *thd, TABLE_LIST *tables,
++                           TABLE_LIST *create_table);
++int append_query_string(CHARSET_INFO *csinfo,
++                        String const *from, String *to);
++
++void get_default_definer(THD *thd, LEX_USER *definer);
++LEX_USER *create_default_definer(THD *thd);
++LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name);
++LEX_USER *get_current_user(THD *thd, LEX_USER *user);
++bool check_string_length(LEX_STRING *str,
++                         const char *err_msg, uint max_length);
++
++enum enum_mysql_completiontype {
++  ROLLBACK_RELEASE=-2, ROLLBACK=1,  ROLLBACK_AND_CHAIN=7,
++  COMMIT_RELEASE=-1,   COMMIT=0,    COMMIT_AND_CHAIN=6
++};
++
++int end_trans(THD *thd, enum enum_mysql_completiontype completion);
++
++Item *negate_expression(THD *thd, Item *expr);
++
++/* log.cc */
++void sql_perror(const char *message);
++
++void vprint_msg_to_log(enum loglevel level, const char *format, va_list args);
++void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
++void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
++void sql_print_information(const char *format, ...)
++  ATTRIBUTE_FORMAT(printf, 1, 2);
++
++#include "sql_class.h"
++#include "sql_acl.h"
++#include "tztime.h"
++#include "opt_range.h"
++
++#ifdef HAVE_QUERY_CACHE
++struct Query_cache_query_flags
++{
++  unsigned int client_long_flag:1;
++  unsigned int client_protocol_41:1;
++  unsigned int more_results_exists:1;
++  unsigned int pkt_nr;
++  uint character_set_client_num;
++  uint character_set_results_num;
++  uint collation_connection_num;
++  ha_rows limit;
++  Time_zone *time_zone;
++  ulong sql_mode;
++  ulong max_sort_length;
++  ulong group_concat_max_len;
++  ulong default_week_format;
++  ulong div_precision_increment;
++  MY_LOCALE *lc_time_names;
++};
++#define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags)
++#include "sql_cache.h"
++#define query_cache_store_query(A, B) query_cache.store_query(A, B)
++#define query_cache_destroy() query_cache.destroy()
++#define query_cache_result_size_limit(A) query_cache.result_size_limit(A)
++#define query_cache_init() query_cache.init()
++#define query_cache_resize(A) query_cache.resize(A)
++#define query_cache_set_min_res_unit(A) query_cache.set_min_res_unit(A)
++#define query_cache_invalidate3(A, B, C) query_cache.invalidate(A, B, C)
++#define query_cache_invalidate1(A) query_cache.invalidate(A)
++#define query_cache_send_result_to_client(A, B, C) \
++  query_cache.send_result_to_client(A, B, C)
++#define query_cache_invalidate_by_MyISAM_filename_ref \
++  &query_cache_invalidate_by_MyISAM_filename
++#else
++#define QUERY_CACHE_FLAGS_SIZE 0
++#define query_cache_store_query(A, B)
++#define query_cache_destroy()
++#define query_cache_result_size_limit(A)
++#define query_cache_init()
++#define query_cache_resize(A)
++#define query_cache_set_min_res_unit(A)
++#define query_cache_invalidate3(A, B, C)
++#define query_cache_invalidate1(A)
++#define query_cache_send_result_to_client(A, B, C) 0
++#define query_cache_invalidate_by_MyISAM_filename_ref NULL
++
++#define query_cache_abort(A)
++#define query_cache_end_of_result(A)
++#define query_cache_invalidate_by_MyISAM_filename_ref NULL
++#endif /*HAVE_QUERY_CACHE*/
++
++uint build_table_path(char *buff, size_t bufflen, const char *db,
++                      const char *table, const char *ext);
++bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
++bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
++bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
++void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags);
++bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
++                    my_bool drop_temporary);
++int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
++			 bool drop_temporary, bool drop_view, bool log_query);
++int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
++				   bool if_exists, bool drop_temporary,
++				   bool log_query);
++int quick_rm_table(enum db_type base,const char *db,
++		   const char *table_name);
++void close_cached_table(THD *thd, TABLE *table);
++bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
++bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db,
++                      char *new_table_name, char *new_table_alias,
++                      bool skip_error);
++bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
++                     bool force_switch);
++
++void mysql_parse(THD *thd, const char *inBuf, uint length,
++                 const char ** semicolon);
++
++bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
++bool is_update_query(enum enum_sql_command command);
++bool alloc_query(THD *thd, const char *packet, uint packet_length);
++void mysql_init_select(LEX *lex);
++void mysql_reset_thd_for_next_command(THD *thd);
++bool mysql_new_select(LEX *lex, bool move_down);
++void create_select_for_variable(const char *var_name);
++void mysql_init_multi_delete(LEX *lex);
++bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
++void init_max_user_conn(void);
++void init_update_queries(void);
++void free_max_user_conn(void);
++pthread_handler_t handle_one_connection(void *arg);
++pthread_handler_t handle_bootstrap(void *arg);
++void end_thread(THD *thd,bool put_in_cache);
++void flush_thread_cache();
++bool mysql_execute_command(THD *thd);
++bool do_command(THD *thd);
++bool dispatch_command(enum enum_server_command command, THD *thd,
++		      char* packet, uint packet_length);
++void log_slow_statement(THD *thd);
++bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
++bool compare_record(TABLE *table, query_id_t query_id);
++
++bool table_cache_init(void);
++void table_cache_free(void);
++uint cached_tables(void);
++void kill_mysql(void);
++void close_connection(THD *thd, uint errcode, bool lock);
++bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, 
++                          bool *write_to_binlog);
++bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv,
++		  bool no_grant, bool no_errors, bool schema_db);
++bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
++			bool no_errors);
++bool check_global_access(THD *thd, ulong want_access);
++
++bool mysql_backup_table(THD* thd, TABLE_LIST* table_list);
++bool mysql_restore_table(THD* thd, TABLE_LIST* table_list);
++
++bool mysql_checksum_table(THD* thd, TABLE_LIST* table_list,
++                          HA_CHECK_OPT* check_opt);
++bool mysql_check_table(THD* thd, TABLE_LIST* table_list,
++                       HA_CHECK_OPT* check_opt);
++bool mysql_repair_table(THD* thd, TABLE_LIST* table_list,
++                        HA_CHECK_OPT* check_opt);
++bool mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
++                         HA_CHECK_OPT* check_opt);
++bool mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
++                          HA_CHECK_OPT* check_opt);
++bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list,
++                              LEX_STRING *key_cache_name);
++bool mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
++int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache,
++                             KEY_CACHE *dst_cache);
++TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list);
++
++bool mysql_xa_recover(THD *thd);
++
++bool check_simple_select();
++
++SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length,
++                                  SORT_FIELD *sortorder);
++int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
++		List<Item> &fields, List <Item> &all_fields, ORDER *order);
++int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
++		List<Item> &fields, List<Item> &all_fields, ORDER *order,
++		bool *hidden_group_fields);
++bool fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
++                   Item **ref_pointer_array);
++
++bool handle_select(THD *thd, LEX *lex, select_result *result,
++                   ulong setup_tables_done_option);
++bool mysql_select(THD *thd, Item ***rref_pointer_array,
++                  TABLE_LIST *tables, uint wild_num,  List<Item> &list,
++                  COND *conds, uint og_num, ORDER *order, ORDER *group,
++                  Item *having, ORDER *proc_param, ulonglong select_type, 
++                  select_result *result, SELECT_LEX_UNIT *unit, 
++                  SELECT_LEX *select_lex);
++void free_underlaid_joins(THD *thd, SELECT_LEX *select);
++bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
++                         select_result *result);
++int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
++			 select_result *result);
++bool mysql_union(THD *thd, LEX *lex, select_result *result,
++                 SELECT_LEX_UNIT *unit, ulong setup_tables_done_option);
++bool mysql_handle_derived(LEX *lex, bool (*processor)(THD *thd,
++                                                      LEX *lex,
++                                                      TABLE_LIST *table));
++bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *t);
++bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t);
++Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
++			Item ***copy_func, Field **from_field,
++                        Field **def_field,
++			bool group, bool modify_item,
++			bool table_cant_handle_bit_fields,
++                        bool make_copy_field,
++                        uint convert_blob_length);
++void sp_prepare_create_field(THD *thd, create_field *sql_field);
++int prepare_create_field(create_field *sql_field, 
++			 uint *blob_columns, 
++			 int *timestamps, int *timestamps_with_niladic,
++			 uint table_flags);
++bool mysql_create_table(THD *thd,const char *db, const char *table_name,
++                        HA_CREATE_INFO *create_info,
++                        Alter_info *alter_info,
++                        bool tmp_table, uint select_field_count);
++
++bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
++                       HA_CREATE_INFO *create_info,
++                       TABLE_LIST *table_list,
++                       Alter_info *alter_info,
++                       uint order_num, ORDER *order, bool ignore);
++bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list);
++bool mysql_create_like_table(THD *thd, TABLE_LIST *table, TABLE_LIST *src_table,
++                             HA_CREATE_INFO *create_info);
++bool mysql_rename_table(enum db_type base,
++			const char *old_db,
++			const char * old_name,
++			const char *new_db,
++			const char * new_name);
++bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
++                          Item **conds, uint order_num, ORDER *order);
++int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
++		 List<Item> &values,COND *conds,
++		 uint order_num, ORDER *order, ha_rows limit,
++		 enum enum_duplicates handle_duplicates, bool ignore);
++bool mysql_multi_update(THD *thd, TABLE_LIST *table_list,
++                        List<Item> *fields, List<Item> *values,
++                        COND *conds, ulonglong options,
++                        enum enum_duplicates handle_duplicates, bool ignore,
++                        SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
++bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
++                          List<Item> &fields, List_item *values,
++                          List<Item> &update_fields,
++                          List<Item> &update_values, enum_duplicates duplic,
++                          COND **where, bool select_insert,
++                          bool check_fields, bool abort_on_warning);
++bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
++                  List<List_item> &values, List<Item> &update_fields,
++                  List<Item> &update_values, enum_duplicates flag,
++                  bool ignore);
++int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
++                                           TABLE_LIST *table_list);
++void prepare_triggers_for_insert_stmt(THD *thd, TABLE *table,
++                                      enum_duplicates duplic);
++void mark_fields_used_by_triggers_for_insert_stmt(THD *thd, TABLE *table,
++                                                  enum_duplicates duplic);
++bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
++bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
++                  SQL_LIST *order, ha_rows rows, ulonglong options,
++                  bool reset_auto_increment);
++bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok);
++bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create);
++TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
++TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem,
++		  bool *refresh, uint flags);
++bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in);
++TABLE *table_cache_insert_placeholder(THD *thd, const char *key,
++                                      uint key_length);
++bool table_cache_has_open_placeholder(THD *thd, const char *db,
++                                      const char *table_name);
++TABLE *find_locked_table(THD *thd, const char *db,const char *table_name);
++bool reopen_table(TABLE *table,bool locked);
++bool reopen_tables(THD *thd,bool get_locks,bool in_refresh);
++bool close_data_tables(THD *thd,const char *db, const char *table_name);
++bool wait_for_tables(THD *thd);
++bool table_is_used(TABLE *table, bool wait_for_name_lock);
++bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
++void abort_locked_tables(THD *thd,const char *db, const char *table_name);
++void execute_init_command(THD *thd, sys_var_str *init_command_var,
++			  rw_lock_t *var_mutex);
++extern Field *not_found_field;
++extern Field *view_ref_found;
++
++enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
++				  IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE,
++                                  IGNORE_EXCEPT_NON_UNIQUE};
++Field *
++find_field_in_tables(THD *thd, Item_ident *item,
++                     TABLE_LIST *first_table, TABLE_LIST *last_table,
++                     Item **ref, find_item_error_report_type report_error,
++                     bool check_privileges, bool register_tree_change);
++Field *
++find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
++                        const char *name, uint length,
++                        const char *item_name, const char *db_name,
++                        const char *table_name, Item **ref,
++                        bool check_privileges, bool allow_rowid,
++                        uint *cached_field_index_ptr,
++                        bool register_tree_change, TABLE_LIST **actual_table);
++Field *
++find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
++                    bool allow_rowid, uint *cached_field_index_ptr);
++
++#ifdef HAVE_OPENSSL
++#include <openssl/des.h>
++struct st_des_keyblock
++{
++  DES_cblock key1, key2, key3;
++};
++struct st_des_keyschedule
++{
++  DES_key_schedule ks1, ks2, ks3;
++};
++extern char *des_key_file;
++extern struct st_des_keyschedule des_keyschedule[10];
++extern uint des_default_key;
++extern pthread_mutex_t LOCK_des_key_file;
++bool load_des_key_file(const char *file_name);
++#endif /* HAVE_OPENSSL */
++
++/* sql_do.cc */
++bool mysql_do(THD *thd, List<Item> &values);
++
++/* sql_analyse.h */
++bool append_escaped(String *to_str, String *from_str);
++
++/* sql_show.cc */
++bool mysqld_show_open_tables(THD *thd,const char *wild);
++bool mysqld_show_logs(THD *thd);
++void append_identifier(THD *thd, String *packet, const char *name,
++		       uint length);
++int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
++void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
++int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd);
++bool mysqld_show_create(THD *thd, TABLE_LIST *table_list);
++bool mysqld_show_create_db(THD *thd, char *dbname,
++                           const HA_CREATE_INFO *create);
++
++void mysqld_list_processes(THD *thd,const char *user,bool verbose);
++int mysqld_show_status(THD *thd);
++int mysqld_show_variables(THD *thd,const char *wild);
++bool mysqld_show_storage_engines(THD *thd);
++bool mysqld_show_privileges(THD *thd);
++bool mysqld_show_column_types(THD *thd);
++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,
++                            const char* str, uint length,
++                            bool allocate_lex_string);
++ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name);
++ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx);
++int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
++                         enum enum_schema_tables schema_table_idx);
++int make_schema_select(THD *thd,  SELECT_LEX *sel,
++                       enum enum_schema_tables schema_table_idx);
++int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list);
++int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
++int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
++int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
++int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
++bool get_schema_tables_result(JOIN *join,
++                              enum enum_schema_table_state executed_place);
++enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table);
++
++#define is_schema_db(X) \
++  !my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.str, (X))
++
++/* sql_prepare.cc */
++
++void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length);
++void mysql_stmt_execute(THD *thd, char *packet, uint packet_length);
++void mysql_stmt_close(THD *thd, char *packet);
++void mysql_sql_stmt_prepare(THD *thd);
++void mysql_sql_stmt_execute(THD *thd);
++void mysql_sql_stmt_close(THD *thd);
++void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length);
++void mysql_stmt_reset(THD *thd, char *packet);
++void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
++void reinit_stmt_before_use(THD *thd, LEX *lex);
++
++/* sql_handler.cc */
++bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen);
++bool mysql_ha_close(THD *thd, TABLE_LIST *tables);
++bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
++                   List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
++int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags,
++                   bool is_locked);
++/* mysql_ha_flush mode_flags bits */
++#define MYSQL_HA_CLOSE_FINAL        0x00
++#define MYSQL_HA_REOPEN_ON_USAGE    0x01
++#define MYSQL_HA_FLUSH_ALL          0x02
++
++/* sql_base.cc */
++#define TMP_TABLE_KEY_EXTRA 8
++void set_item_name(Item *item,char *pos,uint length);
++bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type,
++		       char *length, char *decimal,
++		       uint type_modifier,
++		       Item *default_value, Item *on_update_value,
++		       LEX_STRING *comment,
++		       char *change, List<String> *interval_list,
++		       CHARSET_INFO *cs,
++		       uint uint_geom_type);
++create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
++				char *length, char *decimals,
++				uint type_modifier, 
++				Item *default_value, Item *on_update_value,
++				LEX_STRING *comment, char *change, 
++				List<String> *interval_list, CHARSET_INFO *cs,
++				uint uint_geom_type);
++void store_position_for_column(const char *name);
++bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc);
++bool push_new_name_resolution_context(THD *thd,
++                                      TABLE_LIST *left_op,
++                                      TABLE_LIST *right_op);
++void add_join_on(TABLE_LIST *b,Item *expr);
++void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields,
++                      SELECT_LEX *lex);
++bool add_proc_to_list(THD *thd, Item *item);
++TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
++void drop_open_table(THD *thd, TABLE *table, const char *db_name,
++                     const char *table_name);
++void update_non_unique_table_error(TABLE_LIST *update,
++                                   const char *operation,
++                                   TABLE_LIST *duplicate);
++
++SQL_SELECT *make_select(TABLE *head, table_map const_tables,
++			table_map read_tables, COND *conds,
++                        bool allow_null_cond,  int *error);
++extern Item **not_found_item;
++
++/*
++  This enumeration type is used only by the function find_item_in_list
++  to return the info on how an item has been resolved against a list
++  of possibly aliased items.
++  The item can be resolved: 
++   - against an alias name of the list's element (RESOLVED_AGAINST_ALIAS)
++   - against non-aliased field name of the list  (RESOLVED_WITH_NO_ALIAS)
++   - against an aliased field name of the list   (RESOLVED_BEHIND_ALIAS)
++   - ignoring the alias name in cases when SQL requires to ignore aliases
++     (e.g. when the resolved field reference contains a table name or
++     when the resolved item is an expression)   (RESOLVED_IGNORING_ALIAS)    
++*/
++enum enum_resolution_type {
++  NOT_RESOLVED=0,
++  RESOLVED_IGNORING_ALIAS,
++  RESOLVED_BEHIND_ALIAS,
++  RESOLVED_WITH_NO_ALIAS,
++  RESOLVED_AGAINST_ALIAS
++};
++Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
++                          find_item_error_report_type report_error,
++                          enum_resolution_type *resolution);
++bool get_key_map_from_key_list(key_map *map, TABLE *table,
++                               List<String> *index_list);
++bool insert_fields(THD *thd, Name_resolution_context *context,
++		   const char *db_name, const char *table_name,
++                   List_iterator<Item> *it, bool any_privileges);
++bool setup_tables(THD *thd, Name_resolution_context *context,
++                  List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
++                  Item **conds, TABLE_LIST **leaves, bool select_insert);
++bool setup_tables_and_check_access (THD *thd, 
++                                    Name_resolution_context *context,
++                                    List<TABLE_LIST> *from_clause, 
++                                    TABLE_LIST *tables, Item **conds, 
++                                    TABLE_LIST **leaves, 
++                                    bool select_insert,
++                                    ulong want_access_first,
++                                    ulong want_access);
++int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
++	       List<Item> *sum_func_list, uint wild_num);
++bool setup_fields(THD *thd, Item** ref_pointer_array,
++                  List<Item> &item, bool set_query_id,
++                  List<Item> *sum_func_list, bool allow_sum_func);
++inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
++                                     List<Item> &item, bool set_query_id,
++                                     List<Item> *sum_func_list,
++                                     bool allow_sum_func)
++{
++  bool res;
++  thd->lex->select_lex.no_wrap_view_item= TRUE;
++  res= setup_fields(thd, ref_pointer_array, item, set_query_id, sum_func_list,
++                    allow_sum_func);
++  thd->lex->select_lex.no_wrap_view_item= FALSE;
++  return res;
++}
++int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
++		COND **conds);
++int setup_ftfuncs(SELECT_LEX* select);
++int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
++void wait_for_refresh(THD *thd);
++int open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags);
++int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
++bool open_and_lock_tables(THD *thd,TABLE_LIST *tables);
++bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags);
++int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, bool *need_reopen);
++TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
++			    const char *table_name, bool link_in_list);
++bool rm_temporary_table(enum db_type base, char *path);
++void free_io_cache(TABLE *entry);
++void intern_close_table(TABLE *entry);
++bool close_thread_table(THD *thd, TABLE **table_ptr);
++void close_temporary_tables(THD *thd);
++void close_tables_for_reopen(THD *thd, TABLE_LIST **tables);
++TABLE_LIST *find_table_in_list(TABLE_LIST *table,
++                               TABLE_LIST *TABLE_LIST::*link,
++                               const char *db_name,
++                               const char *table_name);
++TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
++                         bool check_alias);
++TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name);
++bool close_temporary_table(THD *thd, const char *db, const char *table_name);
++void close_temporary(TABLE *table, bool delete_table);
++bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
++			    const char *table_name);
++void remove_db_from_cache(const char *db);
++void flush_tables();
++bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
++
++/* bits for last argument to remove_table_from_cache() */
++#define RTFC_NO_FLAG                0x0000
++#define RTFC_OWNED_BY_THD_FLAG      0x0001
++#define RTFC_WAIT_OTHER_THREAD_FLAG 0x0002
++#define RTFC_CHECK_KILLED_FLAG      0x0004
++bool remove_table_from_cache(THD *thd, const char *db, const char *table,
++                             uint flags);
++
++bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables);
++void copy_field_from_tmp_record(Field *field,int offset);
++bool fill_record(THD *thd, Field **field, List<Item> &values,
++                 bool ignore_errors);
++bool fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
++                                          List<Item> &values,
++                                          bool ignore_errors,
++                                          Table_triggers_list *triggers,
++                                          enum trg_event_type event);
++bool fill_record_n_invoke_before_triggers(THD *thd, Field **field,
++                                          List<Item> &values,
++                                          bool ignore_errors,
++                                          Table_triggers_list *triggers,
++                                          enum trg_event_type event);
++OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild);
++
++inline TABLE_LIST *find_table_in_global_list(TABLE_LIST *table,
++                                             const char *db_name,
++                                             const char *table_name)
++{
++  return find_table_in_list(table, &TABLE_LIST::next_global,
++                            db_name, table_name);
++}
++
++inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table,
++                                            const char *db_name,
++                                            const char *table_name)
++{
++  return find_table_in_list(table, &TABLE_LIST::next_local,
++                            db_name, table_name);
++}
++
++
++/* sql_calc.cc */
++bool eval_const_cond(COND *cond);
++
++/* sql_load.cc */
++bool mysql_load(THD *thd, sql_exchange *ex, TABLE_LIST *table_list,
++	        List<Item> &fields_vars, List<Item> &set_fields,
++                List<Item> &set_values_list,
++                enum enum_duplicates handle_duplicates, bool ignore,
++                bool local_file);
++int write_record(THD *thd, TABLE *table, COPY_INFO *info);
++
++/* sql_manager.cc */
++/* bits set in manager_status */
++#define MANAGER_BERKELEY_LOG_CLEANUP    (1L << 0)
++extern ulong volatile manager_status;
++extern bool volatile manager_thread_in_use, mqh_used;
++extern pthread_t manager_thread;
++pthread_handler_t handle_manager(void *arg);
++
++/* sql_test.cc */
++#ifndef DBUG_OFF
++void print_where(COND *cond,const char *info);
++void print_cached_tables(void);
++void TEST_filesort(SORT_FIELD *sortorder,uint s_length);
++void print_plan(JOIN* join,uint idx, double record_count, double read_time,
++                double current_read_time, const char *info);
++#endif
++void mysql_print_status();
++/* key.cc */
++int find_ref_key(TABLE *form,Field *field, uint *offset);
++void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length);
++void key_restore(byte *to_record, byte *from_key, KEY *key_info,
++                 uint key_length);
++bool key_cmp_if_same(TABLE *form,const byte *key,uint index,uint key_length);
++void key_unpack(String *to,TABLE *form,uint index);
++bool is_key_used(TABLE *table, uint idx, List<Item> &fields);
++int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length);
++
++bool init_errmessage(void);
++
++bool fn_format_relative_to_data_home(my_string to, const char *name,
++				     const char *dir, const char *extension);
++File open_binlog(IO_CACHE *log, const char *log_file_name,
++                 const char **errmsg);
++
++/* mysqld.cc */
++extern void MYSQLerror(const char*);
++void refresh_status(THD *thd);
++my_bool mysql_rm_tmp_tables(void);
++
++/* item_func.cc */
++extern bool check_reserved_words(LEX_STRING *name);
++
++/* strfunc.cc */
++ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs,
++		   char **err_pos, uint *err_len, bool *set_warning);
++uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match);
++uint find_type2(TYPELIB *lib, const char *find, uint length, CHARSET_INFO *cs);
++void unhex_type2(TYPELIB *lib);
++uint check_word(TYPELIB *lib, const char *val, const char *end,
++		const char **end_of_word);
++
++
++bool is_keyword(const char *name, uint len);
++
++#define MY_DB_OPT_FILE "db.opt"
++bool check_db_dir_existence(const char *db_name);
++bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create);
++bool load_db_opt_by_name(THD *thd, const char *db_name,
++                         HA_CREATE_INFO *db_create_info);
++bool my_dbopt_init(void);
++void my_dbopt_cleanup(void);
++void my_dbopt_free(void);
++
++/*
++  External variables
++*/
++
++extern time_t server_start_time, flush_status_time;
++extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
++	    mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[],
++            def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
++#define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
++extern MY_TMPDIR mysql_tmpdir_list;
++extern const char *command_name[];
++extern const char *first_keyword, *my_localhost, *delayed_user, *binary_keyword;
++extern const char **errmesg;			/* Error messages */
++extern const char *myisam_recover_options_str;
++extern const char *in_left_expr_name, *in_additional_cond, *in_having_cond;
++extern const char * const triggers_file_ext;
++extern const char * const trigname_file_ext;
++extern Eq_creator eq_creator;
++extern Ne_creator ne_creator;
++extern Gt_creator gt_creator;
++extern Lt_creator lt_creator;
++extern Ge_creator ge_creator;
++extern Le_creator le_creator;
++extern char language[FN_REFLEN], reg_ext[FN_EXTLEN];
++extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
++extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
++extern char log_error_file[FN_REFLEN], *opt_tc_log_file;
++extern ulonglong log_10_int[20];
++extern ulonglong keybuff_size;
++extern ulonglong thd_startup_options;
++extern ulong flush_version, thread_id;
++extern ulong binlog_cache_use, binlog_cache_disk_use;
++extern ulong aborted_threads,aborted_connects;
++extern ulong delayed_insert_timeout;
++extern ulong delayed_insert_limit, delayed_queue_size;
++extern ulong delayed_insert_threads, delayed_insert_writes;
++extern ulong delayed_rows_in_use,delayed_insert_errors;
++extern ulong slave_open_temp_tables;
++extern ulong query_cache_size, query_cache_min_res_unit;
++extern ulong slow_launch_threads, slow_launch_time;
++extern ulong table_cache_size;
++extern ulong max_connections,max_connect_errors, connect_timeout;
++extern ulong slave_net_timeout, slave_trans_retries;
++extern uint max_user_connections;
++extern ulong what_to_log,flush_time;
++extern ulong query_buff_size, thread_stack;
++extern ulong max_prepared_stmt_count, prepared_stmt_count;
++extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
++extern ulong max_binlog_size, max_relay_log_size;
++extern ulong rpl_recovery_rank, thread_cache_size;
++extern ulong back_log;
++extern ulong specialflag, current_pid;
++extern ulong expire_logs_days, sync_binlog_period, sync_binlog_counter;
++extern ulong opt_tc_log_size, tc_log_max_pages_used, tc_log_page_size;
++extern ulong tc_log_page_waits;
++extern my_bool relay_log_purge, opt_innodb_safe_binlog, opt_innodb;
++extern uint test_flags,select_errors,ha_open_options;
++extern uint protocol_version, mysqld_port, dropping_tables;
++extern uint delay_key_write_options, lower_case_table_names;
++extern bool opt_endinfo, using_udf_functions;
++extern my_bool locked_in_memory;
++extern bool opt_using_transactions, mysqld_embedded;
++extern bool using_update_log, opt_large_files, server_id_supplied;
++extern bool opt_log, opt_update_log, opt_bin_log, opt_slow_log, opt_error_log;
++extern my_bool opt_log_queries_not_using_indexes;
++extern bool opt_disable_networking, opt_skip_show_db;
++extern my_bool opt_character_set_client_handshake;
++extern bool volatile abort_loop, shutdown_in_progress, grant_option;
++extern uint volatile thread_count, thread_running, global_read_lock;
++extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
++extern my_bool opt_safe_show_db, opt_local_infile;
++extern my_bool opt_slave_compressed_protocol, use_temp_pool;
++extern my_bool opt_readonly, lower_case_file_system;
++extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
++extern my_bool opt_secure_auth;
++extern char* opt_secure_file_priv;
++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_function_creators;
++extern uint opt_crash_binlog_innodb;
++extern char *shared_memory_base_name, *mysqld_unix_port;
++extern my_bool opt_enable_shared_memory;
++extern char *default_tz_name;
++extern my_bool opt_large_pages;
++extern uint opt_large_page_size;
++
++extern MYSQL_LOG mysql_log,mysql_slow_log,mysql_bin_log;
++extern FILE *bootstrap_file;
++extern int bootstrap_error;
++extern FILE *stderror_file;
++extern pthread_key(MEM_ROOT**,THR_MALLOC);
++extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
++       LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
++       LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
++       LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
++       LOCK_slave_list, LOCK_active_mi, LOCK_manager, LOCK_global_read_lock,
++       LOCK_global_system_variables, LOCK_user_conn,
++       LOCK_prepared_stmt_count,
++       LOCK_bytes_sent, LOCK_bytes_received;
++#ifdef HAVE_OPENSSL
++extern pthread_mutex_t LOCK_des_key_file;
++#endif
++extern rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
++extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager;
++extern pthread_cond_t COND_global_read_lock;
++extern pthread_attr_t connection_attrib;
++extern I_List<THD> threads;
++extern I_List<NAMED_LIST> key_caches;
++extern MY_BITMAP temp_pool;
++extern String my_empty_string;
++extern const String my_null_string;
++extern SHOW_VAR init_vars[],status_vars[], internal_vars[];
++extern struct system_variables global_system_variables;
++extern struct system_variables max_system_variables;
++extern struct system_status_var global_status_var;
++extern struct rand_struct sql_rand;
++
++extern const char *opt_date_time_formats[];
++extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
++
++extern String null_string;
++extern HASH open_cache;
++extern TABLE *unused_tables;
++extern I_List<i_string> binlog_do_db, binlog_ignore_db;
++extern const char* any_db;
++extern struct my_option my_long_options[];
++extern const LEX_STRING view_type;
++
++/* optional things, have_* variables */
++
++#ifdef HAVE_INNOBASE_DB
++extern handlerton innobase_hton;
++#define have_innodb innobase_hton.state
++#else
++extern SHOW_COMP_OPTION have_innodb;
++#endif
++#ifdef HAVE_BERKELEY_DB
++extern handlerton berkeley_hton;
++#define have_berkeley_db berkeley_hton.state
++#else
++extern SHOW_COMP_OPTION have_berkeley_db;
++#endif
++#ifdef HAVE_EXAMPLE_DB
++extern handlerton example_hton;
++#define have_example_db example_hton.state
++#else
++extern SHOW_COMP_OPTION have_example_db;
++#endif
++#ifdef HAVE_ARCHIVE_DB
++extern handlerton archive_hton;
++#define have_archive_db archive_hton.state
++#else
++extern SHOW_COMP_OPTION have_archive_db;
++#endif
++#ifdef HAVE_CSV_DB
++extern handlerton tina_hton;
++#define have_csv_db tina_hton.state
++#else
++extern SHOW_COMP_OPTION have_csv_db;
++#endif
++#ifdef HAVE_FEDERATED_DB
++extern handlerton federated_hton;
++#define have_federated_db federated_hton.state
++#else
++extern SHOW_COMP_OPTION have_federated_db;
++#endif
++#ifdef HAVE_BLACKHOLE_DB
++extern handlerton blackhole_hton;
++#define have_blackhole_db blackhole_hton.state
++#else
++extern SHOW_COMP_OPTION have_blackhole_db;
++#endif
++#ifdef HAVE_NDBCLUSTER_DB
++extern handlerton ndbcluster_hton;
++#define have_ndbcluster ndbcluster_hton.state
++#else
++extern SHOW_COMP_OPTION have_ndbcluster;
++#endif
++
++/* MRG_MYISAM handler is always built, but may be skipped */
++extern handlerton myisammrg_hton;
++#define have_merge_db myisammrg_hton.state
++
++extern SHOW_COMP_OPTION have_isam;
++extern SHOW_COMP_OPTION have_raid, have_ssl, have_symlink, have_dlopen;
++extern SHOW_COMP_OPTION have_query_cache;
++extern SHOW_COMP_OPTION have_geometry, have_rtree_keys;
++extern SHOW_COMP_OPTION have_crypt;
++extern SHOW_COMP_OPTION have_compress;
++
++#ifndef __WIN__
++extern pthread_t signal_thread;
++#endif
++
++#ifdef HAVE_OPENSSL
++extern struct st_VioSSLFd * ssl_acceptor_fd;
++#endif /* HAVE_OPENSSL */
++
++MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
++                              uint flags, bool *need_reopen);
++/* mysql_lock_tables() and open_table() flags bits */
++#define MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK      0x0001
++#define MYSQL_LOCK_IGNORE_FLUSH                 0x0002
++#define MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN        0x0004
++#define MYSQL_OPEN_TEMPORARY_ONLY               0x0008
++
++void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
++void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
++void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
++void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table,
++                       bool always_unlock);
++void mysql_lock_abort(THD *thd, TABLE *table);
++bool mysql_lock_abort_for_thread(THD *thd, TABLE *table);
++MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
++TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle,
++                                      TABLE_LIST *haystack);
++bool lock_global_read_lock(THD *thd);
++void unlock_global_read_lock(THD *thd);
++bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
++                              bool is_not_commit);
++void start_waiting_global_read_lock(THD *thd);
++bool make_global_read_lock_block_commit(THD *thd);
++bool set_protect_against_global_read_lock(void);
++void unset_protect_against_global_read_lock(void);
++void broadcast_refresh(void);
++
++/* Lock based on name */
++int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list);
++int lock_table_name(THD *thd, TABLE_LIST *table_list);
++void unlock_table_name(THD *thd, TABLE_LIST *table_list);
++bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);
++bool lock_table_names(THD *thd, TABLE_LIST *table_list);
++void unlock_table_names(THD *thd, TABLE_LIST *table_list,
++			TABLE_LIST *last_table);
++
++
++/* old unireg functions */
++
++void unireg_init(ulong options);
++void unireg_end(void);
++bool mysql_create_frm(THD *thd, my_string file_name,
++                      const char *db, const char *table,
++		      HA_CREATE_INFO *create_info,
++		      List<create_field> &create_field,
++		      uint key_count,KEY *key_info,handler *db_type);
++int rea_create_table(THD *thd, my_string file_name,
++                     const char *db, const char *table,
++                     HA_CREATE_INFO *create_info,
++		     List<create_field> &create_field,
++		     uint key_count,KEY *key_info);
++int format_number(uint inputflag,uint max_length,my_string pos,uint length,
++		  my_string *errpos);
++int openfrm(THD *thd, const char *name,const char *alias,uint filestat,
++            uint prgflag, uint ha_open_flags, TABLE *outparam);
++int readfrm(const char *name, const void** data, uint* length);
++int writefrm(const char* name, const void* data, uint len);
++int closefrm(TABLE *table);
++int read_string(File file, gptr *to, uint length);
++void free_blobs(TABLE *table);
++int set_zone(int nr,int min_zone,int max_zone);
++ulong convert_period_to_month(ulong period);
++ulong convert_month_to_period(ulong month);
++void get_date_from_daynr(long daynr,uint *year, uint *month,
++			 uint *day);
++my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, my_bool *not_exist);
++bool str_to_time_with_warn(const char *str,uint length,MYSQL_TIME *l_time);
++timestamp_type str_to_datetime_with_warn(const char *str, uint length,
++                                         MYSQL_TIME *l_time, uint flags);
++void localtime_to_TIME(MYSQL_TIME *to, struct tm *from);
++void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds);
++
++void make_truncated_value_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
++                                  const char *str_val,
++  				  uint str_length, timestamp_type time_type,
++                                    const char *field_name);
++  
++bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, INTERVAL interval);
++bool calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign,
++                      longlong *seconds_out, long *microseconds_out);
++
++extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type,
++					       const char *format_str,
++					       uint format_length);
++extern DATE_TIME_FORMAT *date_time_format_copy(THD *thd,
++					       DATE_TIME_FORMAT *format);
++const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format,
++				     timestamp_type type);
++extern bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
++			   timestamp_type type, String *str);
++void make_datetime(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time,
++                   String *str);
++void make_date(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time,
++               String *str);
++void make_time(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time,
++               String *str);
++ulonglong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
++                             Item *warn_item, bool *is_null);
++
++int test_if_number(char *str,int *res,bool allow_wildcards);
++void change_byte(byte *,uint,char,char);
++void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
++		      SQL_SELECT *select,
++		      int use_record_cache, bool print_errors);
++void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, 
++                          bool print_error, uint idx);
++void end_read_record(READ_RECORD *info);
++ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder,
++		 uint s_length, SQL_SELECT *select,
++		 ha_rows max_rows, ha_rows *examined_rows);
++void filesort_free_buffers(TABLE *table, bool full);
++void change_double_for_sort(double nr,byte *to);
++double my_double_round(double value, longlong dec, bool dec_unsigned,
++                       bool truncate);
++int get_quick_record(SQL_SELECT *select);
++int calc_weekday(long daynr,bool sunday_first_day_of_week);
++uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year);
++void find_date(char *pos,uint *vek,uint flag);
++TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
++TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings);
++ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
++ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
++		     const char *newname);
++ulong next_io_size(ulong pos);
++void append_unescaped(String *res, const char *pos, uint length);
++int create_frm(THD *thd, char *name, const char *db, const char *table,
++               uint reclength,uchar *fileinfo,
++	       HA_CREATE_INFO *create_info, uint keys);
++void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form);
++int rename_file_ext(const char * from,const char * to,const char * ext);
++bool check_db_name(char *db);
++bool check_column_name(const char *name);
++bool check_table_name(const char *name, uint length);
++char *get_field(MEM_ROOT *mem, Field *field);
++bool get_field(MEM_ROOT *mem, Field *field, class String *res);
++int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
++
++/* from hostname.cc */
++struct in_addr;
++my_string ip_to_hostname(struct in_addr *in,uint *errors);
++void inc_host_errors(struct in_addr *in);
++void reset_host_errors(struct in_addr *in);
++bool hostname_cache_init();
++void hostname_cache_free();
++void hostname_cache_refresh(void);
++
++/* sql_cache.cc */
++extern bool sql_cache_init();
++extern void sql_cache_free();
++extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
++
++/* item_func.cc */
++Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
++		     LEX_STRING component);
++int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
++                        LEX_STRING &name, user_var_entry **out_entry);
++/* log.cc */
++bool flush_error_log(void);
++
++/* sql_list.cc */
++void free_list(I_List <i_string_pair> *list);
++void free_list(I_List <i_string> *list);
++
++/* sql_yacc.cc */
++extern int MYSQLparse(void *thd);
++#ifndef DBUG_OFF
++extern void turn_parser_debug_on();
++#endif
++
++/* frm_crypt.cc */
++#ifdef HAVE_CRYPTED_FRM
++SQL_CRYPT *get_crypt_for_frm(void);
++#endif
++
++#include "sql_view.h"
++
++/* Some inline functions for more speed */
++
++inline bool add_item_to_list(THD *thd, Item *item)
++{
++  return thd->lex->current_select->add_item_to_list(thd, item);
++}
++
++inline bool add_value_to_list(THD *thd, Item *value)
++{
++  return thd->lex->value_list.push_back(value);
++}
++
++inline bool add_order_to_list(THD *thd, Item *item, bool asc)
++{
++  return thd->lex->current_select->add_order_to_list(thd, item, asc);
++}
++
++inline bool add_group_to_list(THD *thd, Item *item, bool asc)
++{
++  return thd->lex->current_select->add_group_to_list(thd, item, asc);
++}
++
++inline void mark_as_null_row(TABLE *table)
++{
++  table->null_row=1;
++  table->status|=STATUS_NULL_ROW;
++  bfill(table->null_flags,table->s->null_bytes,255);
++}
++
++inline void table_case_convert(char * name, uint length)
++{
++  if (lower_case_table_names)
++    files_charset_info->cset->casedn(files_charset_info,
++                                     name, length, name, length);
++}
++
++inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
++{
++  return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
++}
++
++inline ulong sql_rnd_with_mutex()
++{
++  pthread_mutex_lock(&LOCK_thread_count);
++  ulong tmp=(ulong) (my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */
++  pthread_mutex_unlock(&LOCK_thread_count);
++  return tmp;
++}
++
++Comp_creator *comp_eq_creator(bool invert);
++Comp_creator *comp_ge_creator(bool invert);
++Comp_creator *comp_gt_creator(bool invert);
++Comp_creator *comp_le_creator(bool invert);
++Comp_creator *comp_lt_creator(bool invert);
++Comp_creator *comp_ne_creator(bool invert);
++
++Item * all_any_subquery_creator(Item *left_expr,
++				chooser_compare_func_creator cmp,
++				bool all,
++				SELECT_LEX *select_lex);
++
++/*
++  clean/setup table fields and map
++
++  SYNOPSYS
++    setup_table_map()
++    table - TABLE structure pointer (which should be setup)
++    table_list TABLE_LIST structure pointer (owner of TABLE)
++    tablenr - table number
++*/
++
++inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
++{
++  table->used_fields= 0;
++  table->const_table= 0;
++  table->null_row= 0;
++  table->status= STATUS_NO_RECORD;
++  table->keys_in_use_for_query= table->s->keys_in_use;
++  table->maybe_null= table_list->outer_join;
++  TABLE_LIST *embedding= table_list->embedding;
++  while (!table->maybe_null && embedding)
++  {
++    table->maybe_null= embedding->outer_join;
++    embedding= embedding->embedding;
++  }
++  table->tablenr= tablenr;
++  table->map= (table_map) 1 << tablenr;
++  table->force_index= table_list->force_index;
++}
++
++
++/*
++  SYNOPSYS
++    hexchar_to_int()
++    convert a hex digit into number
++*/
++
++inline int hexchar_to_int(char c)
++{
++  if (c <= '9' && c >= '0')
++    return c-'0';
++  c|=32;
++  if (c <= 'f' && c >= 'a')
++    return c-'a'+10;
++  return -1;
++}
++
++/*
++  is_user_table()
++  return true if the table was created explicitly
++*/
++
++inline bool is_user_table(TABLE * table)
++{
++  const char *name= table->s->table_name;
++  return strncmp(name, tmp_file_prefix, tmp_file_prefix_length);
++}
++
++/*
++  Some functions that are different in the embedded library and the normal
++  server
++*/
++
++#ifndef EMBEDDED_LIBRARY
++extern "C" void unireg_abort(int exit_code);
++void kill_delayed_threads(void);
++bool check_stack_overrun(THD *thd, long margin, char *dummy);
++#else
++#define unireg_abort(exit_code) DBUG_RETURN(exit_code)
++inline void kill_delayed_threads(void) {}
++#define check_stack_overrun(A, B, C) 0
++#endif
++
++#endif /* MYSQL_CLIENT */
++
++#endif
+diff -urNad trunk~/sql/mysqld.cc trunk/sql/mysqld.cc
+--- trunk~/sql/mysqld.cc	2007-11-15 08:06:16.000000000 -0600
++++ trunk/sql/mysqld.cc	2007-12-27 15:54:49.290263774 -0600
+@@ -6688,6 +6688,11 @@
+ #else
+   have_csv_db= SHOW_OPTION_NO;
+ #endif
++#ifdef HAVE_SPHINX_DB
++  have_sphinx_db= SHOW_OPTION_YES;
++#else
++  have_sphinx_db= SHOW_OPTION_NO;
++#endif
+ #ifdef HAVE_NDBCLUSTER_DB
+   have_ndbcluster=SHOW_OPTION_DISABLED;
+ #else
+@@ -7780,6 +7785,7 @@
+ #undef have_example_db
+ #undef have_archive_db
+ #undef have_csv_db
++#undef have_sphinx_db
+ #undef have_federated_db
+ #undef have_partition_db
+ #undef have_blackhole_db
+@@ -7790,6 +7796,7 @@
+ SHOW_COMP_OPTION have_example_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_archive_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_csv_db= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_sphinx_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_federated_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_partition_db= SHOW_OPTION_NO;
+ SHOW_COMP_OPTION have_blackhole_db= SHOW_OPTION_NO;
+diff -urNad trunk~/sql/mysqld.cc.orig trunk/sql/mysqld.cc.orig
+--- trunk~/sql/mysqld.cc.orig	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/mysqld.cc.orig	2007-12-27 15:54:49.306264686 -0600
+@@ -0,0 +1,7811 @@
++/* Copyright (C) 2000-2003 MySQL AB
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; version 2 of the License.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
++
++#include "mysql_priv.h"
++#include <m_ctype.h>
++#include <my_dir.h>
++#include "slave.h"
++#include "sql_repl.h"
++#include "repl_failsafe.h"
++#include "stacktrace.h"
++#include "mysqld_suffix.h"
++#include "mysys_err.h"
++#ifdef HAVE_BERKELEY_DB
++#include "ha_berkeley.h"
++#endif
++#ifdef HAVE_INNOBASE_DB
++#include "ha_innodb.h"
++#endif
++#include "ha_myisam.h"
++#ifdef HAVE_NDBCLUSTER_DB
++#include "ha_ndbcluster.h"
++#endif
++#ifdef HAVE_SYS_PRCTL_H
++#include <sys/prctl.h>
++#endif
++
++#ifdef HAVE_INNOBASE_DB
++#define OPT_INNODB_DEFAULT 1
++#else
++#define OPT_INNODB_DEFAULT 0
++#endif
++#define OPT_BDB_DEFAULT 0
++#ifdef HAVE_NDBCLUSTER_DB
++#define OPT_NDBCLUSTER_DEFAULT 0
++#if defined(NOT_ENOUGH_TESTED) \
++  && defined(NDB_SHM_TRANSPORTER) && MYSQL_VERSION_ID >= 50000
++#define OPT_NDB_SHM_DEFAULT 1
++#else
++#define OPT_NDB_SHM_DEFAULT 0
++#endif
++#else
++#define OPT_NDBCLUSTER_DEFAULT 0
++#endif
++
++#ifndef DEFAULT_SKIP_THREAD_PRIORITY
++#define DEFAULT_SKIP_THREAD_PRIORITY 0
++#endif
++
++#include <thr_alarm.h>
++#include <ft_global.h>
++#include <errmsg.h>
++#include "sp_rcontext.h"
++#include "sp_cache.h"
++
++#define mysqld_charset &my_charset_latin1
++
++#ifndef DBUG_OFF
++#define ONE_THREAD
++#endif
++
++#ifdef HAVE_purify
++#define IF_PURIFY(A,B) (A)
++#else
++#define IF_PURIFY(A,B) (B)
++#endif
++
++#if SIZEOF_CHARP == 4
++#define MAX_MEM_TABLE_SIZE ~(ulong) 0
++#else
++#define MAX_MEM_TABLE_SIZE ~(ulonglong) 0
++#endif
++
++/* stack traces are only supported on linux intel */
++#if defined(__linux__)  && defined(__i386__) && defined(USE_PSTACK)
++#define	HAVE_STACK_TRACE_ON_SEGV
++#include "../pstack/pstack.h"
++char pstack_file_name[80];
++#endif /* __linux__ */
++
++/* We have HAVE_purify below as this speeds up the shutdown of MySQL */
++
++#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ) || defined(HAVE_purify) && defined(__linux__)
++#define HAVE_CLOSE_SERVER_SOCK 1
++#endif
++
++extern "C" {					// Because of SCO 3.2V4.2
++#include <errno.h>
++#include <sys/stat.h>
++#ifndef __GNU_LIBRARY__
++#define __GNU_LIBRARY__				// Skip warnings in getopt.h
++#endif
++#include <my_getopt.h>
++#ifdef HAVE_SYSENT_H
++#include <sysent.h>
++#endif
++#ifdef HAVE_PWD_H
++#include <pwd.h>				// For getpwent
++#endif
++#ifdef HAVE_GRP_H
++#include <grp.h>
++#endif
++#include <my_net.h>
++
++#if defined(OS2)
++#  include <sys/un.h>
++#elif !defined(__WIN__)
++#  ifndef __NETWARE__
++#include <sys/resource.h>
++#  endif /* __NETWARE__ */
++#ifdef HAVE_SYS_UN_H
++#  include <sys/un.h>
++#endif
++#include <netdb.h>
++#ifdef HAVE_SELECT_H
++#  include <select.h>
++#endif
++#ifdef HAVE_SYS_SELECT_H
++#include <sys/select.h>
++#endif
++#include <sys/utsname.h>
++#endif /* __WIN__ */
++
++#include <my_libwrap.h>
++
++#ifdef HAVE_SYS_MMAN_H
++#include <sys/mman.h>
++#endif
++
++#ifdef __NETWARE__
++#define zVOLSTATE_ACTIVE 6
++#define zVOLSTATE_DEACTIVE 2
++#define zVOLSTATE_MAINTENANCE 3
++
++#include <nks/netware.h>
++#include <nks/vm.h>
++#include <library.h>
++#include <monitor.h>
++#include <zOmni.h>                              //For NEB
++#include <neb.h>                                //For NEB
++#include <nebpub.h>                             //For NEB
++#include <zEvent.h>                             //For NSS event structures
++#include <zPublics.h>
++
++static void *neb_consumer_id= NULL;             //For storing NEB consumer id
++static char datavolname[256]= {0};
++static VolumeID_t datavolid;
++static event_handle_t eh;
++static Report_t ref;
++static void *refneb= NULL;
++my_bool event_flag= FALSE;
++static int volumeid= -1;
++
++  /* NEB event callback */
++unsigned long neb_event_callback(struct EventBlock *eblock);
++static void registerwithneb();
++static void getvolumename();
++static void getvolumeID(BYTE *volumeName);
++#endif /* __NETWARE__ */
++
++
++#ifdef _AIX41
++int initgroups(const char *,unsigned int);
++#endif
++
++#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
++#include <ieeefp.h>
++#ifdef HAVE_FP_EXCEPT				// Fix type conflict
++typedef fp_except fp_except_t;
++#endif
++
++  /* We can't handle floating point exceptions with threads, so disable
++     this on freebsd
++  */
++
++inline void reset_floating_point_exceptions()
++{
++  /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */
++#if defined(__i386__)
++  fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
++	      FP_X_IMP));
++#else
++ fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
++	     FP_X_IMP));
++#endif
++}
++#else
++#define reset_floating_point_exceptions()
++#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
++
++} /* cplusplus */
++
++#define MYSQL_KILL_SIGNAL SIGTERM
++
++#ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R
++#include <sys/types.h>
++#else
++#include <my_pthread.h>			// For thr_setconcurency()
++#endif
++
++#ifdef SOLARIS
++extern "C" int gethostname(char *name, int namelen);
++#endif
++
++
++/* Constants */
++
++const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
++static const char *sql_mode_names[]=
++{
++  "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
++  "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
++  "NO_DIR_IN_CREATE",
++  "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS",
++  "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
++  "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES",
++  "STRICT_ALL_TABLES",
++  "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES",
++  "ERROR_FOR_DIVISION_BY_ZERO",
++  "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE",
++  "NO_ENGINE_SUBSTITUTION",
++  NullS
++};
++static const unsigned int sql_mode_names_len[]=
++{
++  /*REAL_AS_FLOAT*/               13,
++  /*PIPES_AS_CONCAT*/             15,
++  /*ANSI_QUOTES*/                 11,
++  /*IGNORE_SPACE*/                12,
++  /*?*/                           1,
++  /*ONLY_FULL_GROUP_BY*/          18,
++  /*NO_UNSIGNED_SUBTRACTION*/     23,
++  /*NO_DIR_IN_CREATE*/            16,
++  /*POSTGRESQL*/                  10,
++  /*ORACLE*/                      6,
++  /*MSSQL*/                       5,
++  /*DB2*/                         3,
++  /*MAXDB*/                       5,
++  /*NO_KEY_OPTIONS*/              14,
++  /*NO_TABLE_OPTIONS*/            16,
++  /*NO_FIELD_OPTIONS*/            16,
++  /*MYSQL323*/                    8,
++  /*MYSQL40*/                     7,
++  /*ANSI*/                        4,
++  /*NO_AUTO_VALUE_ON_ZERO*/       21,
++  /*NO_BACKSLASH_ESCAPES*/        20,
++  /*STRICT_TRANS_TABLES*/         19,
++  /*STRICT_ALL_TABLES*/           17,
++  /*NO_ZERO_IN_DATE*/             15,
++  /*NO_ZERO_DATE*/                12,
++  /*ALLOW_INVALID_DATES*/         19,
++  /*ERROR_FOR_DIVISION_BY_ZERO*/  26,
++  /*TRADITIONAL*/                 11,
++  /*NO_AUTO_CREATE_USER*/         19,
++  /*HIGH_NOT_PRECEDENCE*/         19,
++  /*NO_ENGINE_SUBSTITUTION*/      22
++};
++TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
++			    sql_mode_names,
++                            (unsigned int *)sql_mode_names_len };
++static const char *tc_heuristic_recover_names[]=
++{
++  "COMMIT", "ROLLBACK", NullS
++};
++static TYPELIB tc_heuristic_recover_typelib=
++{
++  array_elements(tc_heuristic_recover_names)-1,"",
++  tc_heuristic_recover_names, NULL
++};
++const char *first_keyword= "first", *binary_keyword= "BINARY";
++const char *my_localhost= "localhost", *delayed_user= "DELAYED";
++#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
++#define GET_HA_ROWS GET_ULL
++#else
++#define GET_HA_ROWS GET_ULONG
++#endif
++
++bool opt_large_files= sizeof(my_off_t) > 4;
++
++/*
++  Used with --help for detailed option
++*/
++static my_bool opt_help= 0, opt_verbose= 0;
++
++arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
++{{&Arg_comparator::compare_string,     &Arg_comparator::compare_e_string},
++ {&Arg_comparator::compare_real,       &Arg_comparator::compare_e_real},
++ {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
++ {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row},
++ {&Arg_comparator::compare_decimal,    &Arg_comparator::compare_e_decimal}};
++
++/* static variables */
++
++static bool lower_case_table_names_used= 0;
++static bool volatile select_thread_in_use, signal_thread_in_use;
++static bool volatile ready_to_exit;
++static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
++static my_bool opt_bdb, opt_isam, opt_ndbcluster, opt_merge;
++static my_bool opt_short_log_format= 0;
++static uint kill_cached_threads, wake_thread;
++static ulong killed_threads, thread_created;
++static ulong max_used_connections;
++static ulong my_bind_addr;			/* the address we bind to */
++static volatile ulong cached_thread_count= 0;
++static const char *sql_mode_str= "OFF";
++static char *mysqld_user, *mysqld_chroot, *log_error_file_ptr;
++static char *opt_init_slave, *language_ptr, *opt_init_connect;
++static char *default_character_set_name;
++static char *character_set_filesystem_name;
++static char *lc_time_names_name;
++static char *my_bind_addr_str;
++static char *default_collation_name;
++static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
++static char mysql_data_home_buff[2];
++static I_List<THD> thread_cache;
++
++#ifndef EMBEDDED_LIBRARY
++static struct passwd *user_info;
++static pthread_t select_thread;
++static uint thr_kill_signal;
++#endif
++
++static pthread_cond_t COND_thread_cache, COND_flush_thread_cache;
++
++#ifdef HAVE_BERKELEY_DB
++static my_bool opt_sync_bdb_logs;
++#endif
++
++/* Global variables */
++
++bool opt_log, opt_update_log, opt_bin_log, opt_slow_log;
++my_bool opt_log_queries_not_using_indexes= 0;
++bool opt_error_log= IF_WIN(1,0);
++bool opt_disable_networking=0, opt_skip_show_db=0;
++my_bool opt_character_set_client_handshake= 1;
++bool server_id_supplied = 0;
++bool opt_endinfo, using_udf_functions;
++my_bool locked_in_memory;
++bool opt_using_transactions, using_update_log;
++bool volatile abort_loop;
++bool volatile shutdown_in_progress;
++/**
++   @brief 'grant_option' is used to indicate if privileges needs
++   to be checked, in which case the lock, LOCK_grant, is used
++   to protect access to the grant table.
++   @note This flag is dropped in 5.1 
++   @see grant_init()
++ */
++bool volatile grant_option;
++
++my_bool opt_skip_slave_start = 0; // If set, slave is not autostarted
++my_bool opt_reckless_slave = 0;
++my_bool opt_enable_named_pipe= 0;
++my_bool opt_local_infile, opt_slave_compressed_protocol;
++my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
++my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
++my_bool opt_log_slave_updates= 0;
++my_bool	opt_innodb;
++bool slave_warning_issued = false; 
++
++#ifdef HAVE_NDBCLUSTER_DB
++const char *opt_ndbcluster_connectstring= 0;
++const char *opt_ndb_connectstring= 0;
++char opt_ndb_constrbuf[1024];
++unsigned opt_ndb_constrbuf_len= 0;
++my_bool	opt_ndb_shm, opt_ndb_optimized_node_selection;
++ulong opt_ndb_cache_check_time;
++const char *opt_ndb_mgmd;
++ulong opt_ndb_nodeid;
++#endif
++my_bool opt_readonly, use_temp_pool, relay_log_purge;
++my_bool opt_sync_frm, opt_allow_suspicious_udfs;
++my_bool opt_secure_auth= 0;
++char* opt_secure_file_priv= 0;
++my_bool opt_log_slow_admin_statements= 0;
++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_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
++  changed). False otherwise.
++*/
++volatile bool mqh_used = 0;
++my_bool opt_noacl;
++my_bool sp_automatic_privileges= 1;
++
++#ifdef HAVE_INITGROUPS
++static bool calling_initgroups= FALSE; /* Used in SIGSEGV handler. */
++#endif
++uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
++uint mysqld_port_timeout;
++uint delay_key_write_options, protocol_version;
++uint lower_case_table_names;
++uint tc_heuristic_recover= 0;
++uint volatile thread_count, thread_running;
++ulonglong thd_startup_options;
++ulong back_log, connect_timeout, concurrency, server_id;
++ulong table_cache_size, thread_stack, what_to_log;
++ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
++ulong open_files_limit, max_binlog_size, max_relay_log_size;
++ulong slave_net_timeout, slave_trans_retries;
++ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
++ulong query_cache_size=0;
++ulong refresh_version, flush_version;	/* Increments on each reload */
++query_id_t global_query_id;
++ulong aborted_threads, aborted_connects;
++ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
++ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
++ulong delayed_insert_errors,flush_time;
++ulong specialflag=0;
++ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
++ulong max_connections, max_connect_errors;
++uint  max_user_connections= 0;
++/*
++  Limit of the total number of prepared statements in the server.
++  Is necessary to protect the server against out-of-memory attacks.
++*/
++ulong max_prepared_stmt_count;
++/*
++  Current total number of prepared statements in the server. This number
++  is exact, and therefore may not be equal to the difference between
++  `com_stmt_prepare' and `com_stmt_close' (global status variables), as
++  the latter ones account for all registered attempts to prepare
++  a statement (including unsuccessful ones).  Prepared statements are
++  currently connection-local: if the same SQL query text is prepared in
++  two different connections, this counts as two distinct prepared
++  statements.
++*/
++ulong prepared_stmt_count=0;
++ulong thread_id=1L,current_pid;
++ulong slow_launch_threads = 0, sync_binlog_period;
++ulong expire_logs_days = 0;
++ulong rpl_recovery_rank=0;
++
++time_t server_start_time, flush_status_time;
++
++char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
++char *default_tz_name;
++char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN];
++char mysql_real_data_home[FN_REFLEN],
++     language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
++     *opt_init_file, *opt_tc_log_file,
++     def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
++
++const key_map key_map_empty(0);
++key_map key_map_full(0);                        // Will be initialized later
++
++const char *opt_date_time_formats[3];
++
++char *mysql_data_home= mysql_real_data_home;
++char server_version[SERVER_VERSION_LENGTH];
++char *mysqld_unix_port, *opt_mysql_tmpdir;
++const char **errmesg;			/* Error messages */
++const char *myisam_recover_options_str="OFF";
++const char *myisam_stats_method_str="nulls_unequal";
++
++/* name of reference on left espression in rewritten IN subquery */
++const char *in_left_expr_name= "<left expr>";
++/* name of additional condition */
++const char *in_additional_cond= "<IN COND>";
++const char *in_having_cond= "<IN HAVING>";
++
++my_decimal decimal_zero;
++/* classes for comparation parsing/processing */
++Eq_creator eq_creator;
++Ne_creator ne_creator;
++Gt_creator gt_creator;
++Lt_creator lt_creator;
++Ge_creator ge_creator;
++Le_creator le_creator;
++
++
++FILE *bootstrap_file;
++int bootstrap_error;
++FILE *stderror_file=0;
++
++I_List<i_string_pair> replicate_rewrite_db;
++I_List<i_string> replicate_do_db, replicate_ignore_db;
++// allow the user to tell us which db to replicate and which to ignore
++I_List<i_string> binlog_do_db, binlog_ignore_db;
++I_List<THD> threads;
++I_List<NAMED_LIST> key_caches;
++
++struct system_variables global_system_variables;
++struct system_variables max_system_variables;
++struct system_status_var global_status_var;
++
++MY_TMPDIR mysql_tmpdir_list;
++MY_BITMAP temp_pool;
++
++CHARSET_INFO *system_charset_info, *files_charset_info ;
++CHARSET_INFO *national_charset_info, *table_alias_charset;
++CHARSET_INFO *character_set_filesystem;
++
++MY_LOCALE *my_default_lc_time_names;
++
++SHOW_COMP_OPTION have_isam;
++SHOW_COMP_OPTION have_raid, have_ssl, have_symlink, have_query_cache;
++SHOW_COMP_OPTION have_geometry, have_rtree_keys, have_dlopen;
++SHOW_COMP_OPTION have_crypt, have_compress;
++
++/* Thread specific variables */
++
++pthread_key(MEM_ROOT**,THR_MALLOC);
++pthread_key(THD*, THR_THD);
++pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
++		LOCK_mapped_file, LOCK_status, LOCK_global_read_lock,
++		LOCK_error_log, LOCK_uuid_generator,
++		LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
++		LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
++	        LOCK_global_system_variables,
++		LOCK_user_conn, LOCK_slave_list, LOCK_active_mi;
++/*
++  The below lock protects access to two global server variables:
++  max_prepared_stmt_count and prepared_stmt_count. These variables
++  set the limit and hold the current total number of prepared statements
++  in the server, respectively. As PREPARE/DEALLOCATE rate in a loaded
++  server may be fairly high, we need a dedicated lock.
++*/
++pthread_mutex_t LOCK_prepared_stmt_count;
++#ifdef HAVE_OPENSSL
++pthread_mutex_t LOCK_des_key_file;
++#endif
++rw_lock_t	LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
++pthread_cond_t COND_refresh,COND_thread_count, COND_global_read_lock;
++pthread_t signal_thread;
++pthread_attr_t connection_attrib;
++
++File_parser_dummy_hook file_parser_dummy_hook;
++
++/* replication parameters, if master_host is not NULL, we are a slave */
++uint master_port= MYSQL_PORT, master_connect_retry = 60;
++uint report_port= MYSQL_PORT;
++ulong master_retry_count=0;
++char *master_user, *master_password, *master_host, *master_info_file;
++char *relay_log_info_file, *report_user, *report_password, *report_host;
++char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
++my_bool master_ssl;
++char *master_ssl_key, *master_ssl_cert;
++char *master_ssl_ca, *master_ssl_capath, *master_ssl_cipher;
++
++/* Static variables */
++
++static bool kill_in_progress, segfaulted;
++static my_bool opt_do_pstack, opt_bootstrap, opt_myisam_log;
++static int cleanup_done;
++static ulong opt_specialflag, opt_myisam_block_size;
++static char *opt_logname, *opt_update_logname, *opt_binlog_index_name;
++static char *opt_slow_logname, *opt_tc_heuristic_recover;
++static char *mysql_home_ptr, *pidfile_name_ptr;
++static char **defaults_argv;
++static char *opt_bin_logname;
++
++static my_socket unix_sock,ip_sock;
++struct rand_struct sql_rand; // used by sql_class.cc:THD::THD()
++
++/* OS specific variables */
++
++#ifdef __WIN__
++#undef	 getpid
++#include <process.h>
++
++static pthread_cond_t COND_handler_count;
++static uint handler_count;
++static bool start_mode=0, use_opt_args;
++static int opt_argc;
++static char **opt_argv;
++
++#if !defined(EMBEDDED_LIBRARY)
++static HANDLE hEventShutdown;
++static char shutdown_event_name[40];
++#include "nt_servc.h"
++static	 NTService  Service;	      // Service object for WinNT
++#endif /* EMBEDDED_LIBRARY */
++#endif /* __WIN__ */
++
++#ifdef __NT__
++static char pipe_name[512];
++static SECURITY_ATTRIBUTES saPipeSecurity;
++static SECURITY_DESCRIPTOR sdPipeDescriptor;
++static HANDLE hPipe = INVALID_HANDLE_VALUE;
++#endif
++
++#ifdef OS2
++pthread_cond_t eventShutdown;
++#endif
++
++#ifndef EMBEDDED_LIBRARY
++bool mysqld_embedded=0;
++#else
++bool mysqld_embedded=1;
++#endif
++
++#ifndef DBUG_OFF
++static const char* default_dbug_option;
++#endif
++#ifdef HAVE_LIBWRAP
++const char *libwrapName= NULL;
++int allow_severity = LOG_INFO;
++int deny_severity = LOG_WARNING;
++#endif
++#ifdef HAVE_QUERY_CACHE
++static ulong query_cache_limit= 0;
++ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
++Query_cache query_cache;
++#endif
++#ifdef HAVE_SMEM
++char *shared_memory_base_name= default_shared_memory_base_name;
++my_bool opt_enable_shared_memory;
++HANDLE smem_event_connect_request= 0;
++#endif
++
++#define SSL_VARS_NOT_STATIC
++#include "sslopt-vars.h"
++#ifdef HAVE_OPENSSL
++#include <openssl/crypto.h>
++#ifndef HAVE_YASSL
++typedef struct CRYPTO_dynlock_value
++{
++  rw_lock_t lock;
++} openssl_lock_t;
++
++static openssl_lock_t *openssl_stdlocks;
++static openssl_lock_t *openssl_dynlock_create(const char *, int);
++static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int);
++static void openssl_lock_function(int, int, const char *, int);
++static void openssl_lock(int, openssl_lock_t *, const char *, int);
++static unsigned long openssl_id_function();
++#endif
++char *des_key_file;
++struct st_VioSSLFd *ssl_acceptor_fd;
++#endif /* HAVE_OPENSSL */
++
++
++/* Function declarations */
++
++pthread_handler_t signal_hand(void *arg);
++static void mysql_init_variables(void);
++static void get_options(int argc,char **argv);
++static void set_server_version(void);
++static int init_thread_environment();
++static char *get_relative_path(const char *path);
++static void fix_paths(void);
++pthread_handler_t handle_connections_sockets(void *arg);
++pthread_handler_t kill_server_thread(void *arg);
++static void bootstrap(FILE *file);
++static bool read_init_file(char *file_name);
++#ifdef __NT__
++pthread_handler_t handle_connections_namedpipes(void *arg);
++#endif
++#ifdef HAVE_SMEM
++pthread_handler_t handle_connections_shared_memory(void *arg);
++#endif
++pthread_handler_t handle_slave(void *arg);
++static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
++static void clean_up(bool print_message);
++static int test_if_case_insensitive(const char *dir_name);
++
++#ifndef EMBEDDED_LIBRARY
++static void start_signal_handler(void);
++static void close_server_sock();
++static void clean_up_mutexes(void);
++static void wait_for_signal_thread_to_end(void);
++static void create_pid_file();
++#endif
++
++
++#ifndef EMBEDDED_LIBRARY
++/****************************************************************************
++** Code to end mysqld
++****************************************************************************/
++
++static void close_connections(void)
++{
++#ifdef EXTRA_DEBUG
++  int count=0;
++#endif
++  DBUG_ENTER("close_connections");
++
++  /* Clear thread cache */
++  kill_cached_threads++;
++  flush_thread_cache();
++
++  /* kill flush thread */
++  (void) pthread_mutex_lock(&LOCK_manager);
++  if (manager_thread_in_use)
++  {
++    DBUG_PRINT("quit",("killing manager thread: 0x%lx",manager_thread));
++   (void) pthread_cond_signal(&COND_manager);
++  }
++  (void) pthread_mutex_unlock(&LOCK_manager);
++
++  /* kill connection thread */
++#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__)
++  DBUG_PRINT("quit",("waiting for select thread: 0x%lx",select_thread));
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++
++  while (select_thread_in_use)
++  {
++    struct timespec abstime;
++    int error;
++    LINT_INIT(error);
++    DBUG_PRINT("info",("Waiting for select thread"));
++
++#ifndef DONT_USE_THR_ALARM
++    if (pthread_kill(select_thread, thr_client_alarm))
++      break;					// allready dead
++#endif
++    set_timespec(abstime, 2);
++    for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
++    {
++      error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count,
++				   &abstime);
++      if (error != EINTR)
++	break;
++    }
++#ifdef EXTRA_DEBUG
++    if (error != 0 && !count++)
++      sql_print_error("Got error %d from pthread_cond_timedwait",error);
++#endif
++    close_server_sock();
++  }
++  (void) pthread_mutex_unlock(&LOCK_thread_count);
++#endif /* __WIN__ */
++
++
++  /* Abort listening to new connections */
++  DBUG_PRINT("quit",("Closing sockets"));
++  if (!opt_disable_networking )
++  {
++    if (ip_sock != INVALID_SOCKET)
++    {
++      (void) shutdown(ip_sock, SHUT_RDWR);
++      (void) closesocket(ip_sock);
++      ip_sock= INVALID_SOCKET;
++    }
++  }
++#ifdef __NT__
++  if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
++  {
++    HANDLE temp;
++    DBUG_PRINT("quit", ("Closing named pipes") );
++
++    /* Create connection to the handle named pipe handler to break the loop */
++    if ((temp = CreateFile(pipe_name,
++			   GENERIC_READ | GENERIC_WRITE,
++			   0,
++			   NULL,
++			   OPEN_EXISTING,
++			   0,
++			   NULL )) != INVALID_HANDLE_VALUE)
++    {
++      WaitNamedPipe(pipe_name, 1000);
++      DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
++      SetNamedPipeHandleState(temp, &dwMode, NULL, NULL);
++      CancelIo(temp);
++      DisconnectNamedPipe(temp);
++      CloseHandle(temp);
++    }
++  }
++#endif
++#ifdef HAVE_SYS_UN_H
++  if (unix_sock != INVALID_SOCKET)
++  {
++    (void) shutdown(unix_sock, SHUT_RDWR);
++    (void) closesocket(unix_sock);
++    (void) unlink(mysqld_unix_port);
++    unix_sock= INVALID_SOCKET;
++  }
++#endif
++  end_thr_alarm(0);			 // Abort old alarms.
++
++  /*
++    First signal all threads that it's time to die
++    This will give the threads some time to gracefully abort their
++    statements and inform their clients that the server is about to die.
++  */
++
++  THD *tmp;
++  (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
++
++  I_List_iterator<THD> it(threads);
++  while ((tmp=it++))
++  {
++    DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
++		       tmp->thread_id));
++    /* We skip slave threads on this first loop through. */
++    if (tmp->slave_thread)
++      continue;
++
++    tmp->killed= THD::KILL_CONNECTION;
++    if (tmp->mysys_var)
++    {
++      tmp->mysys_var->abort=1;
++      pthread_mutex_lock(&tmp->mysys_var->mutex);
++      if (tmp->mysys_var->current_cond)
++      {
++	pthread_mutex_lock(tmp->mysys_var->current_mutex);
++	pthread_cond_broadcast(tmp->mysys_var->current_cond);
++	pthread_mutex_unlock(tmp->mysys_var->current_mutex);
++      }
++      pthread_mutex_unlock(&tmp->mysys_var->mutex);
++    }
++  }
++  (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
++
++  end_slave();
++
++  if (thread_count)
++    sleep(2);					// Give threads time to die
++
++  /*
++    Force remaining threads to die by closing the connection to the client
++    This will ensure that threads that are waiting for a command from the
++    client on a blocking read call are aborted.
++  */
++
++  for (;;)
++  {
++    DBUG_PRINT("quit",("Locking LOCK_thread_count"));
++    (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
++    if (!(tmp=threads.get()))
++    {
++      DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
++      (void) pthread_mutex_unlock(&LOCK_thread_count);
++      break;
++    }
++#ifndef __bsdi__				// Bug in BSDI kernel
++    if (tmp->vio_ok())
++    {
++      if (global_system_variables.log_warnings)
++        sql_print_warning(ER(ER_FORCING_CLOSE),my_progname,
++                          tmp->thread_id,
++                          (tmp->main_security_ctx.user ?
++                           tmp->main_security_ctx.user : ""));
++      close_connection(tmp,0,0);
++    }
++#endif
++    DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
++    (void) pthread_mutex_unlock(&LOCK_thread_count);
++  }
++  /* All threads has now been aborted */
++  DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++  while (thread_count)
++  {
++    (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
++    DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
++  }
++  (void) pthread_mutex_unlock(&LOCK_thread_count);
++
++  DBUG_PRINT("quit",("close_connections thread"));
++  DBUG_VOID_RETURN;
++}
++
++
++static void close_server_sock()
++{
++#ifdef HAVE_CLOSE_SERVER_SOCK
++  DBUG_ENTER("close_server_sock");
++  my_socket tmp_sock;
++  tmp_sock=ip_sock;
++  if (tmp_sock != INVALID_SOCKET)
++  {
++    ip_sock=INVALID_SOCKET;
++    DBUG_PRINT("info",("calling shutdown on TCP/IP socket"));
++    VOID(shutdown(tmp_sock, SHUT_RDWR));
++#if defined(__NETWARE__)
++    /*
++      The following code is disabled for normal systems as it causes MySQL
++      to hang on AIX 4.3 during shutdown
++    */
++    DBUG_PRINT("info",("calling closesocket on TCP/IP socket"));
++    VOID(closesocket(tmp_sock));
++#endif
++  }
++  tmp_sock=unix_sock;
++  if (tmp_sock != INVALID_SOCKET)
++  {
++    unix_sock=INVALID_SOCKET;
++    DBUG_PRINT("info",("calling shutdown on unix socket"));
++    VOID(shutdown(tmp_sock, SHUT_RDWR));
++#if defined(__NETWARE__)
++    /*
++      The following code is disabled for normal systems as it may cause MySQL
++      to hang on AIX 4.3 during shutdown
++    */
++    DBUG_PRINT("info",("calling closesocket on unix/IP socket"));
++    VOID(closesocket(tmp_sock));
++#endif
++    VOID(unlink(mysqld_unix_port));
++  }
++  DBUG_VOID_RETURN;
++#endif
++}
++
++#endif /*EMBEDDED_LIBRARY*/
++
++
++void kill_mysql(void)
++{
++  DBUG_ENTER("kill_mysql");
++
++#if defined(SIGNALS_DONT_BREAK_READ) && !defined(EMBEDDED_LIBRARY)
++  abort_loop=1;					// Break connection loops
++  close_server_sock();				// Force accept to wake up
++#endif
++
++#if defined(__WIN__)
++#if !defined(EMBEDDED_LIBRARY)
++  {
++    if (!SetEvent(hEventShutdown))
++    {
++      DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
++    }
++    /*
++      or:
++      HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
++      SetEvent(hEventShutdown);
++      CloseHandle(hEvent);
++    */
++  }
++#endif
++#elif defined(OS2)
++  pthread_cond_signal(&eventShutdown);		// post semaphore
++#elif defined(HAVE_PTHREAD_KILL)
++  if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
++  {
++    DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
++  }
++#elif !defined(SIGNALS_DONT_BREAK_READ)
++  kill(current_pid, MYSQL_KILL_SIGNAL);
++#endif
++  DBUG_PRINT("quit",("After pthread_kill"));
++  shutdown_in_progress=1;			// Safety if kill didn't work
++#ifdef SIGNALS_DONT_BREAK_READ
++  if (!kill_in_progress)
++  {
++    pthread_t tmp;
++    abort_loop=1;
++    if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
++			   (void*) 0))
++      sql_print_error("Can't create thread to kill server");
++  }
++#endif
++  DBUG_VOID_RETURN;
++}
++
++/*
++  Force server down. Kill all connections and threads and exit
++
++  SYNOPSIS
++  kill_server
++
++  sig_ptr       Signal number that caused kill_server to be called.
++
++  NOTE!
++    A signal number of 0 mean that the function was not called
++    from a signal handler and there is thus no signal to block
++    or stop, we just want to kill the server.
++
++*/
++
++#if defined(OS2) || defined(__NETWARE__)
++extern "C" void kill_server(int sig_ptr)
++#define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN
++#elif !defined(__WIN__)
++static void *kill_server(void *sig_ptr)
++#define RETURN_FROM_KILL_SERVER DBUG_RETURN(0)
++#else
++static void __cdecl kill_server(int sig_ptr)
++#define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN
++#endif
++{
++  DBUG_ENTER("kill_server");
++#ifndef EMBEDDED_LIBRARY
++  int sig=(int) (long) sig_ptr;			// This is passed a int
++  // if there is a signal during the kill in progress, ignore the other
++  if (kill_in_progress)				// Safety
++    RETURN_FROM_KILL_SERVER;
++  kill_in_progress=TRUE;
++  abort_loop=1;					// This should be set
++  if (sig != 0) // 0 is not a valid signal number
++    my_sigset(sig, SIG_IGN);                    /* purify inspected */
++  if (sig == MYSQL_KILL_SIGNAL || sig == 0)
++    sql_print_information(ER(ER_NORMAL_SHUTDOWN),my_progname);
++  else
++    sql_print_error(ER(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
++
++#if defined(HAVE_SMEM) && defined(__WIN__)
++  /*
++   Send event to smem_event_connect_request for aborting
++   */
++  if (!SetEvent(smem_event_connect_request))
++  {
++	  DBUG_PRINT("error",
++		("Got error: %ld from SetEvent of smem_event_connect_request",
++		 GetLastError()));
++  }
++#endif
++
++#if defined(__NETWARE__) || (defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__) && !defined(OS2))
++  my_thread_init();				// If this is a new thread
++#endif
++  close_connections();
++  if (sig != MYSQL_KILL_SIGNAL &&
++#ifdef __WIN__
++      sig != SIGINT &&				/* Bug#18235 */
++#endif
++      sig != 0)
++    unireg_abort(1);				/* purecov: inspected */
++  else
++    unireg_end();
++
++#ifdef __NETWARE__
++  if (!event_flag)
++    pthread_join(select_thread, NULL);		// wait for main thread
++#endif /* __NETWARE__ */
++
++#if defined(__NETWARE__) || (defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__) && !defined(OS2))
++  my_thread_end();
++#endif
++
++  pthread_exit(0);				/* purecov: deadcode */
++
++#endif /* EMBEDDED_LIBRARY */
++  RETURN_FROM_KILL_SERVER;
++}
++
++
++#if defined(USE_ONE_SIGNAL_HAND) || (defined(__NETWARE__) && defined(SIGNALS_DONT_BREAK_READ))
++pthread_handler_t kill_server_thread(void *arg __attribute__((unused)))
++{
++  my_thread_init();				// Initialize new thread
++  kill_server(0);
++  my_thread_end();				// Normally never reached
++  return 0;
++}
++#endif
++
++extern "C" sig_handler print_signal_warning(int sig)
++{
++  if (!DBUG_IN_USE)
++  {
++    if (global_system_variables.log_warnings)
++      sql_print_warning("Got signal %d from thread %ld",
++                        sig, my_thread_id());
++  }
++#ifdef DONT_REMEMBER_SIGNAL
++  my_sigset(sig,print_signal_warning);		/* int. thread system calls */
++#endif
++#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
++  if (sig == SIGALRM)
++    alarm(2);					/* reschedule alarm */
++#endif
++}
++
++/*
++  cleanup all memory and end program nicely
++
++  SYNOPSIS
++    unireg_end()
++
++  NOTES
++    This function never returns.
++
++    If SIGNALS_DONT_BREAK_READ is defined, this function is called
++    by the main thread. To get MySQL to shut down nicely in this case
++    (Mac OS X) we have to call exit() instead if pthread_exit().
++*/
++
++#ifndef EMBEDDED_LIBRARY
++void unireg_end(void)
++{
++  clean_up(1);
++  my_thread_end();
++#if defined(SIGNALS_DONT_BREAK_READ) && !defined(__NETWARE__)
++  exit(0);
++#else
++  pthread_exit(0);				// Exit is in main thread
++#endif
++}
++
++extern "C" void unireg_abort(int exit_code)
++{
++  DBUG_ENTER("unireg_abort");
++  if (exit_code)
++    sql_print_error("Aborting\n");
++  clean_up(exit_code || !opt_bootstrap); /* purecov: inspected */
++  DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
++  wait_for_signal_thread_to_end();
++  clean_up_mutexes();
++  my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
++  exit(exit_code); /* purecov: inspected */
++}
++#endif
++
++
++void clean_up(bool print_message)
++{
++  DBUG_PRINT("exit",("clean_up"));
++  if (cleanup_done++)
++    return; /* purecov: inspected */
++
++  mysql_log.cleanup();
++  mysql_slow_log.cleanup();
++  mysql_bin_log.cleanup();
++
++#ifdef HAVE_REPLICATION
++  if (use_slave_mask)
++    bitmap_free(&slave_error_mask);
++#endif
++  my_tz_free();
++  my_dbopt_free();
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  acl_free(1);
++  grant_free();
++#endif
++  query_cache_destroy();
++  table_cache_free();
++  hostname_cache_free();
++  item_user_lock_free();
++  lex_free();				/* Free some memory */
++  set_var_free();
++  free_charsets();
++#ifdef HAVE_DLOPEN
++  if (!opt_noacl)
++    udf_free();
++#endif
++  (void) ha_panic(HA_PANIC_CLOSE);	/* close all tables and logs */
++  if (tc_log)
++    tc_log->close();
++  xid_cache_free();
++  delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache);
++  multi_keycache_free();
++  end_thr_alarm(1);			/* Free allocated memory */
++#ifdef USE_RAID
++  end_raid();
++#endif
++  my_free_open_file_info();
++  my_free((char*) global_system_variables.date_format,
++	  MYF(MY_ALLOW_ZERO_PTR));
++  my_free((char*) global_system_variables.time_format,
++	  MYF(MY_ALLOW_ZERO_PTR));
++  my_free((char*) global_system_variables.datetime_format,
++	  MYF(MY_ALLOW_ZERO_PTR));
++  if (defaults_argv)
++    free_defaults(defaults_argv);
++  my_free(sys_init_connect.value, MYF(MY_ALLOW_ZERO_PTR));
++  my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR));
++  free_tmpdir(&mysql_tmpdir_list);
++#ifdef HAVE_REPLICATION
++  my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
++#endif
++  x_free(opt_bin_logname);
++  x_free(opt_relay_logname);
++  x_free(opt_secure_file_priv);
++  bitmap_free(&temp_pool);
++  free_max_user_conn();
++#ifdef HAVE_REPLICATION
++  end_slave_list();
++  free_list(&replicate_do_db);
++  free_list(&replicate_ignore_db);
++  free_list(&binlog_do_db);
++  free_list(&binlog_ignore_db);
++  free_list(&replicate_rewrite_db);
++#endif
++#ifdef HAVE_OPENSSL
++  if (ssl_acceptor_fd)
++  {
++    SSL_CTX_free(ssl_acceptor_fd->ssl_context);
++    my_free((gptr) ssl_acceptor_fd, MYF(0));
++  }
++#endif /* HAVE_OPENSSL */
++  vio_end();
++
++#ifdef USE_REGEX
++  my_regex_end();
++#endif
++
++  if (print_message && errmesg)
++    sql_print_information(ER(ER_SHUTDOWN_COMPLETE),my_progname);
++#if !defined(EMBEDDED_LIBRARY)
++  if (!opt_bootstrap)
++    (void) my_delete(pidfile_name,MYF(0));	// This may not always exist
++#endif
++  finish_client_errs();
++  my_free((gptr) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST),
++          MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
++  DBUG_PRINT("quit", ("Error messages freed"));
++  /* Tell main we are ready */
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++  DBUG_PRINT("quit", ("got thread count lock"));
++  ready_to_exit=1;
++  /* do the broadcast inside the lock to ensure that my_end() is not called */
++  (void) pthread_cond_broadcast(&COND_thread_count);
++  (void) pthread_mutex_unlock(&LOCK_thread_count);
++  /*
++    The following lines may never be executed as the main thread may have
++    killed us
++  */
++  DBUG_PRINT("quit", ("done with cleanup"));
++} /* clean_up */
++
++
++#ifndef EMBEDDED_LIBRARY
++
++/*
++  This is mainly needed when running with purify, but it's still nice to
++  know that all child threads have died when mysqld exits
++*/
++
++static void wait_for_signal_thread_to_end()
++{
++#ifndef __NETWARE__
++  uint i;
++  /*
++    Wait up to 10 seconds for signal thread to die. We use this mainly to
++    avoid getting warnings that my_thread_end has not been called
++  */
++  for (i= 0 ; i < 100 && signal_thread_in_use; i++)
++  {
++    if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL) != ESRCH)
++      break;
++    my_sleep(100);				// Give it time to die
++  }
++#endif
++}
++
++
++static void clean_up_mutexes()
++{
++  (void) pthread_mutex_destroy(&LOCK_mysql_create_db);
++  (void) pthread_mutex_destroy(&LOCK_Acl);
++  (void) rwlock_destroy(&LOCK_grant);
++  (void) pthread_mutex_destroy(&LOCK_open);
++  (void) pthread_mutex_destroy(&LOCK_thread_count);
++  (void) pthread_mutex_destroy(&LOCK_mapped_file);
++  (void) pthread_mutex_destroy(&LOCK_status);
++  (void) pthread_mutex_destroy(&LOCK_error_log);
++  (void) pthread_mutex_destroy(&LOCK_delayed_insert);
++  (void) pthread_mutex_destroy(&LOCK_delayed_status);
++  (void) pthread_mutex_destroy(&LOCK_delayed_create);
++  (void) pthread_mutex_destroy(&LOCK_manager);
++  (void) pthread_mutex_destroy(&LOCK_crypt);
++  (void) pthread_mutex_destroy(&LOCK_bytes_sent);
++  (void) pthread_mutex_destroy(&LOCK_bytes_received);
++  (void) pthread_mutex_destroy(&LOCK_user_conn);
++#ifdef HAVE_OPENSSL
++  (void) pthread_mutex_destroy(&LOCK_des_key_file);
++#ifndef HAVE_YASSL
++  for (int i= 0; i < CRYPTO_num_locks(); ++i)
++    (void) rwlock_destroy(&openssl_stdlocks[i].lock);
++  OPENSSL_free(openssl_stdlocks);
++#endif
++#endif
++#ifdef HAVE_REPLICATION
++  (void) pthread_mutex_destroy(&LOCK_rpl_status);
++  (void) pthread_cond_destroy(&COND_rpl_status);
++#endif
++  (void) pthread_mutex_destroy(&LOCK_active_mi);
++  (void) rwlock_destroy(&LOCK_sys_init_connect);
++  (void) rwlock_destroy(&LOCK_sys_init_slave);
++  (void) pthread_mutex_destroy(&LOCK_global_system_variables);
++  (void) pthread_mutex_destroy(&LOCK_global_read_lock);
++  (void) pthread_mutex_destroy(&LOCK_uuid_generator);
++  (void) pthread_mutex_destroy(&LOCK_prepared_stmt_count);
++  (void) pthread_cond_destroy(&COND_thread_count);
++  (void) pthread_cond_destroy(&COND_refresh);
++  (void) pthread_cond_destroy(&COND_global_read_lock);
++  (void) pthread_cond_destroy(&COND_thread_cache);
++  (void) pthread_cond_destroy(&COND_flush_thread_cache);
++  (void) pthread_cond_destroy(&COND_manager);
++}
++
++#endif /*EMBEDDED_LIBRARY*/
++
++
++/****************************************************************************
++** Init IP and UNIX socket
++****************************************************************************/
++
++static void set_ports()
++{
++  char	*env;
++  if (!mysqld_port && !opt_disable_networking)
++  {					// Get port if not from commandline
++    struct  servent *serv_ptr;
++    mysqld_port= MYSQL_PORT;
++    if ((serv_ptr= getservbyname("mysql", "tcp")))
++      mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
++    if ((env = getenv("MYSQL_TCP_PORT")))
++      mysqld_port= (uint) atoi(env);		/* purecov: inspected */
++  }
++  if (!mysqld_unix_port)
++  {
++#ifdef __WIN__
++    mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
++#else
++    mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
++#endif
++    if ((env = getenv("MYSQL_UNIX_PORT")))
++      mysqld_unix_port= env;			/* purecov: inspected */
++  }
++}
++
++#ifndef EMBEDDED_LIBRARY
++/* Change to run as another user if started with --user */
++
++static struct passwd *check_user(const char *user)
++{
++#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
++  struct passwd *tmp_user_info;
++  uid_t user_id= geteuid();
++
++  // Don't bother if we aren't superuser
++  if (user_id)
++  {
++    if (user)
++    {
++      /* Don't give a warning, if real user is same as given with --user */
++      /* purecov: begin tested */
++      tmp_user_info= getpwnam(user);
++      if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
++	  global_system_variables.log_warnings)
++        sql_print_warning(
++                    "One can only use the --user switch if running as root\n");
++      /* purecov: end */    
++    }
++    return NULL;
++  }
++  if (!user)
++  {
++    if (!opt_bootstrap)
++    {
++      sql_print_error("Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n");
++      unireg_abort(1);
++    }
++    return NULL;
++  }
++  /* purecov: begin tested */
++  if (!strcmp(user,"root"))
++    return NULL;                        // Avoid problem with dynamic libraries
++
++  if (!(tmp_user_info= getpwnam(user)))
++  {
++    // Allow a numeric uid to be used
++    const char *pos;
++    for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
++    if (*pos)                                   // Not numeric id
++      goto err;
++    if (!(tmp_user_info= getpwuid(atoi(user))))
++      goto err;
++    else
++      return tmp_user_info;
++  }
++  else
++    return tmp_user_info;
++  /* purecov: end */    
++
++err:
++  sql_print_error("Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!\n",user);
++  unireg_abort(1);
++
++#ifdef PR_SET_DUMPABLE
++  if (test_flags & TEST_CORE_ON_SIGNAL)
++  {
++    /* inform kernel that process is dumpable */
++    (void) prctl(PR_SET_DUMPABLE, 1);
++  }
++#endif
++
++#endif
++  return NULL;
++}
++
++static void set_user(const char *user, struct passwd *user_info_arg)
++{
++  /* purecov: begin tested */
++#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
++  DBUG_ASSERT(user_info_arg != 0);
++#ifdef HAVE_INITGROUPS
++  /*
++    We can get a SIGSEGV when calling initgroups() on some systems when NSS
++    is configured to use LDAP and the server is statically linked.  We set
++    calling_initgroups as a flag to the SIGSEGV handler that is then used to
++    output a specific message to help the user resolve this problem.
++  */
++  calling_initgroups= TRUE;
++  initgroups((char*) user, user_info_arg->pw_gid);
++  calling_initgroups= FALSE;
++#endif
++  if (setgid(user_info_arg->pw_gid) == -1)
++  {
++    sql_perror("setgid");
++    unireg_abort(1);
++  }
++  if (setuid(user_info_arg->pw_uid) == -1)
++  {
++    sql_perror("setuid");
++    unireg_abort(1);
++  }
++#endif
++  /* purecov: end */    
++}
++
++
++static void set_effective_user(struct passwd *user_info_arg)
++{
++#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
++  DBUG_ASSERT(user_info_arg != 0);
++  if (setregid((gid_t)-1, user_info_arg->pw_gid) == -1)
++  {
++    sql_perror("setregid");
++    unireg_abort(1);
++  }
++  if (setreuid((uid_t)-1, user_info_arg->pw_uid) == -1)
++  {
++    sql_perror("setreuid");
++    unireg_abort(1);
++  }
++#endif
++}
++
++
++/* Change root user if started with  --chroot */
++
++static void set_root(const char *path)
++{
++#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__)
++  if (chroot(path) == -1)
++  {
++    sql_perror("chroot");
++    unireg_abort(1);
++  }
++  my_setwd("/", MYF(0));
++#endif
++}
++
++static void network_init(void)
++{
++  struct sockaddr_in	IPaddr;
++#ifdef HAVE_SYS_UN_H
++  struct sockaddr_un	UNIXaddr;
++#endif
++  int	arg=1;
++  int   ret;
++  uint  waited;
++  uint  this_wait;
++  uint  retry;
++  DBUG_ENTER("network_init");
++  LINT_INIT(ret);
++
++  set_ports();
++
++  if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
++  {
++    DBUG_PRINT("general",("IP Socket is %d",mysqld_port));
++    ip_sock = socket(AF_INET, SOCK_STREAM, 0);
++    if (ip_sock == INVALID_SOCKET)
++    {
++      DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
++      sql_perror(ER(ER_IPSOCK_ERROR));		/* purecov: tested */
++      unireg_abort(1);				/* purecov: tested */
++    }
++    bzero((char*) &IPaddr, sizeof(IPaddr));
++    IPaddr.sin_family = AF_INET;
++    IPaddr.sin_addr.s_addr = my_bind_addr;
++    IPaddr.sin_port = (unsigned short) htons((unsigned short) mysqld_port);
++
++#ifndef __WIN__
++    /*
++      We should not use SO_REUSEADDR on windows as this would enable a
++      user to open two mysqld servers with the same TCP/IP port.
++    */
++    (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg));
++#endif /* __WIN__ */
++    /*
++      Sometimes the port is not released fast enough when stopping and
++      restarting the server. This happens quite often with the test suite
++      on busy Linux systems. Retry to bind the address at these intervals:
++      Sleep intervals: 1, 2, 4,  6,  9, 13, 17, 22, ...
++      Retry at second: 1, 3, 7, 13, 22, 35, 52, 74, ...
++      Limit the sequence by mysqld_port_timeout (set --port-open-timeout=#).
++    */
++    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
++    {
++      if (((ret= bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr),
++                      sizeof(IPaddr))) >= 0) ||
++          (socket_errno != SOCKET_EADDRINUSE) ||
++          (waited >= mysqld_port_timeout))
++        break;
++      sql_print_information("Retrying bind on TCP/IP port %u", mysqld_port);
++      this_wait= retry * retry / 3 + 1;
++      sleep(this_wait);
++    }
++    if (ret < 0)
++    {
++      DBUG_PRINT("error",("Got error: %d from bind",socket_errno));
++      sql_perror("Can't start server: Bind on TCP/IP port");
++      sql_print_error("Do you already have another mysqld server running on port: %d ?",mysqld_port);
++      unireg_abort(1);
++    }
++    if (listen(ip_sock,(int) back_log) < 0)
++    {
++      sql_perror("Can't start server: listen() on TCP/IP port");
++      sql_print_error("listen() on TCP/IP failed with error %d",
++		      socket_errno);
++      unireg_abort(1);
++    }
++  }
++
++#ifdef __NT__
++  /* create named pipe */
++  if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
++      opt_enable_named_pipe)
++  {
++
++    pipe_name[sizeof(pipe_name)-1]= 0;		/* Safety if too long string */
++    strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\",
++	     mysqld_unix_port, NullS);
++    bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity));
++    bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor));
++    if (!InitializeSecurityDescriptor(&sdPipeDescriptor,
++				      SECURITY_DESCRIPTOR_REVISION))
++    {
++      sql_perror("Can't start server : Initialize security descriptor");
++      unireg_abort(1);
++    }
++    if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE))
++    {
++      sql_perror("Can't start server : Set security descriptor");
++      unireg_abort(1);
++    }
++    saPipeSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
++    saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
++    saPipeSecurity.bInheritHandle = FALSE;
++    if ((hPipe= CreateNamedPipe(pipe_name,
++				PIPE_ACCESS_DUPLEX,
++				PIPE_TYPE_BYTE |
++				PIPE_READMODE_BYTE |
++				PIPE_WAIT,
++				PIPE_UNLIMITED_INSTANCES,
++				(int) global_system_variables.net_buffer_length,
++				(int) global_system_variables.net_buffer_length,
++				NMPWAIT_USE_DEFAULT_WAIT,
++				&saPipeSecurity)) == INVALID_HANDLE_VALUE)
++      {
++	LPVOID lpMsgBuf;
++	int error=GetLastError();
++	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
++		      FORMAT_MESSAGE_FROM_SYSTEM,
++		      NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
++		      (LPTSTR) &lpMsgBuf, 0, NULL );
++	MessageBox(NULL, (LPTSTR) lpMsgBuf, "Error from CreateNamedPipe",
++		    MB_OK|MB_ICONINFORMATION);
++	LocalFree(lpMsgBuf);
++	unireg_abort(1);
++      }
++  }
++#endif
++
++#if defined(HAVE_SYS_UN_H)
++  /*
++  ** Create the UNIX socket
++  */
++  if (mysqld_unix_port[0] && !opt_bootstrap)
++  {
++    DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
++
++    if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
++    {
++      sql_print_error("The socket file path is too long (> %u): %s",
++                      (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
++      unireg_abort(1);
++    }
++    if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
++    {
++      sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
++      unireg_abort(1);				/* purecov: inspected */
++    }
++    bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
++    UNIXaddr.sun_family = AF_UNIX;
++    strmov(UNIXaddr.sun_path, mysqld_unix_port);
++    (void) unlink(mysqld_unix_port);
++    (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
++		      sizeof(arg));
++    umask(0);
++    if (bind(unix_sock, my_reinterpret_cast(struct sockaddr *) (&UNIXaddr),
++	     sizeof(UNIXaddr)) < 0)
++    {
++      sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
++      sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
++      unireg_abort(1);					/* purecov: tested */
++    }
++    umask(((~my_umask) & 0666));
++#if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
++    (void) chmod(mysqld_unix_port,S_IFSOCK);	/* Fix solaris 2.6 bug */
++#endif
++    if (listen(unix_sock,(int) back_log) < 0)
++      sql_print_warning("listen() on Unix socket failed with error %d",
++		      socket_errno);
++  }
++#endif
++  DBUG_PRINT("info",("server started"));
++  DBUG_VOID_RETURN;
++}
++
++#endif /*!EMBEDDED_LIBRARY*/
++
++
++#ifndef EMBEDDED_LIBRARY
++/*
++  Close a connection
++
++  SYNOPSIS
++    close_connection()
++    thd		Thread handle
++    errcode	Error code to print to console
++    lock	1 if we have have to lock LOCK_thread_count
++
++  NOTES
++    For the connection that is doing shutdown, this is called twice
++*/
++
++void close_connection(THD *thd, uint errcode, bool lock)
++{
++  st_vio *vio;
++  DBUG_ENTER("close_connection");
++  DBUG_PRINT("enter",("fd: %s  error: '%s'",
++		      thd->net.vio ? vio_description(thd->net.vio) :
++		      "(not connected)",
++		      errcode ? ER(errcode) : ""));
++  if (lock)
++    (void) pthread_mutex_lock(&LOCK_thread_count);
++  thd->killed= THD::KILL_CONNECTION;
++  if ((vio= thd->net.vio) != 0)
++  {
++    if (errcode)
++      net_send_error(thd, errcode, ER(errcode)); /* purecov: inspected */
++    vio_close(vio);			/* vio is freed in delete thd */
++  }
++  if (lock)
++    (void) pthread_mutex_unlock(&LOCK_thread_count);
++  DBUG_VOID_RETURN;
++}
++#endif /* EMBEDDED_LIBRARY */
++
++
++	/* Called when a thread is aborted */
++	/* ARGSUSED */
++
++extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
++{
++  THD *thd=current_thd;
++  DBUG_ENTER("end_thread_signal");
++  if (thd && ! thd->bootstrap)
++  {
++    statistic_increment(killed_threads, &LOCK_status);
++    end_thread(thd,0);
++  }
++  DBUG_VOID_RETURN;				/* purecov: deadcode */
++}
++
++
++void end_thread(THD *thd, bool put_in_cache)
++{
++  DBUG_ENTER("end_thread");
++  thd->cleanup();
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++  thread_count--;
++  delete thd;
++
++  if (put_in_cache && cached_thread_count < thread_cache_size &&
++      ! abort_loop && !kill_cached_threads)
++  {
++    /* Don't kill the thread, just put it in cache for reuse */
++    DBUG_PRINT("info", ("Adding thread to cache"));
++    cached_thread_count++;
++    while (!abort_loop && ! wake_thread && ! kill_cached_threads)
++      (void) pthread_cond_wait(&COND_thread_cache, &LOCK_thread_count);
++    cached_thread_count--;
++    if (kill_cached_threads)
++      pthread_cond_signal(&COND_flush_thread_cache);
++    if (wake_thread)
++    {
++      wake_thread--;
++      thd=thread_cache.get();
++      thd->real_id=pthread_self();
++      thd->thread_stack= (char*) &thd;          // For store_globals
++      (void) thd->store_globals();
++      /*
++        THD::mysys_var::abort is associated with physical thread rather
++        than with THD object. So we need to reset this flag before using
++        this thread for handling of new THD object/connection.
++      */
++      thd->mysys_var->abort= 0;
++      thd->thr_create_time= time(NULL);
++      threads.append(thd);
++      pthread_mutex_unlock(&LOCK_thread_count);
++      DBUG_VOID_RETURN;
++    }
++  }
++
++  /* Tell main we are ready */
++  (void) pthread_mutex_unlock(&LOCK_thread_count);
++  /* It's safe to broadcast outside a lock (COND... is not deleted here) */
++  DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
++  (void) pthread_cond_broadcast(&COND_thread_count);
++#ifdef ONE_THREAD
++  if (!(test_flags & TEST_NO_THREADS))	// For debugging under Linux
++#endif
++  {
++    my_thread_end();
++    pthread_exit(0);
++  }
++  DBUG_VOID_RETURN;
++}
++
++
++void flush_thread_cache()
++{
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++  kill_cached_threads++;
++  while (cached_thread_count)
++  {
++    pthread_cond_broadcast(&COND_thread_cache);
++    pthread_cond_wait(&COND_flush_thread_cache,&LOCK_thread_count);
++  }
++  kill_cached_threads--;
++  (void) pthread_mutex_unlock(&LOCK_thread_count);
++}
++
++
++/*
++  Aborts a thread nicely. Commes here on SIGPIPE
++  TODO: One should have to fix that thr_alarm know about this
++  thread too.
++*/
++
++#ifdef THREAD_SPECIFIC_SIGPIPE
++extern "C" sig_handler abort_thread(int sig __attribute__((unused)))
++{
++  THD *thd=current_thd;
++  DBUG_ENTER("abort_thread");
++  if (thd)
++    thd->killed= THD::KILL_CONNECTION;
++  DBUG_VOID_RETURN;
++}
++#endif
++
++/******************************************************************************
++  Setup a signal thread with handles all signals.
++  Because Linux doesn't support schemas use a mutex to check that
++  the signal thread is ready before continuing
++******************************************************************************/
++
++
++#if defined(__WIN__) || defined(OS2)
++static void init_signals(void)
++{
++  int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ;
++  for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
++    signal(signals[i], kill_server) ;
++#if defined(__WIN__)
++  signal(SIGBREAK,SIG_IGN);	//ignore SIGBREAK for NT
++#else
++  signal(SIGBREAK, kill_server);
++#endif
++}
++
++static void start_signal_handler(void)
++{
++  // Save vm id of this process
++  if (!opt_bootstrap)
++    create_pid_file();
++}
++
++static void check_data_home(const char *path)
++{}
++
++
++#elif defined(__NETWARE__)
++
++// down server event callback
++void mysql_down_server_cb(void *, void *)
++{
++  event_flag= TRUE;
++  kill_server(0);
++}
++
++
++// destroy callback resources
++void mysql_cb_destroy(void *)
++{
++  UnRegisterEventNotification(eh);  // cleanup down event notification
++  NX_UNWRAP_INTERFACE(ref);
++  /* Deregister NSS volume deactivation event */
++  NX_UNWRAP_INTERFACE(refneb);
++  if (neb_consumer_id)
++    UnRegisterConsumer(neb_consumer_id, NULL);
++}
++
++
++// initialize callbacks
++void mysql_cb_init()
++{
++  // register for down server event
++  void *handle = getnlmhandle();
++  rtag_t rt= AllocateResourceTag(handle, "MySQL Down Server Callback",
++                                 EventSignature);
++  NX_WRAP_INTERFACE((void *)mysql_down_server_cb, 2, (void **)&ref);
++  eh= RegisterForEventNotification(rt, EVENT_PRE_DOWN_SERVER,
++                                   EVENT_PRIORITY_APPLICATION,
++                                   NULL, ref, NULL);
++
++  /*
++    Register for volume deactivation event
++    Wrap the callback function, as it is called by non-LibC thread
++  */
++  (void *) NX_WRAP_INTERFACE(neb_event_callback, 1, &refneb);
++  registerwithneb();
++
++  NXVmRegisterExitHandler(mysql_cb_destroy, NULL);  // clean-up
++}
++
++
++/* To get the name of the NetWare volume having MySQL data folder */
++
++static void getvolumename()
++{
++  char *p;
++  /*
++    We assume that data path is already set.
++    If not it won't come here. Terminate after volume name
++  */
++  if ((p= strchr(mysql_real_data_home, ':')))
++    strmake(datavolname, mysql_real_data_home,
++            (uint) (p - mysql_real_data_home));
++}
++
++
++/*
++  Registering with NEB for NSS Volume Deactivation event
++*/
++
++static void registerwithneb()
++{
++
++  ConsumerRegistrationInfo reg_info;
++
++  /* Clear NEB registration structure */
++  bzero((char*) &reg_info, sizeof(struct ConsumerRegistrationInfo));
++
++  /* Fill the NEB consumer information structure */
++  reg_info.CRIVersion= 1;  	            // NEB version
++  /* NEB Consumer name */
++  reg_info.CRIConsumerName= (BYTE *) "MySQL Database Server";
++  /* Event of interest */
++  reg_info.CRIEventName= (BYTE *) "NSS.ChangeVolState.Enter";
++  reg_info.CRIUserParameter= NULL;	    // Consumer Info
++  reg_info.CRIEventFlags= 0;	            // Event flags
++  /* Consumer NLM handle */
++  reg_info.CRIOwnerID= (LoadDefinitionStructure *)getnlmhandle();
++  reg_info.CRIConsumerESR= NULL;	    // No consumer ESR required
++  reg_info.CRISecurityToken= 0;	            // No security token for the event
++  reg_info.CRIConsumerFlags= 0;             // SMP_ENABLED_BIT;
++  reg_info.CRIFilterName= 0;	            // No event filtering
++  reg_info.CRIFilterDataLength= 0;          // No filtering data
++  reg_info.CRIFilterData= 0;	            // No filtering data
++  /* Callback function for the event */
++  (void *)reg_info.CRIConsumerCallback= (void *) refneb;
++  reg_info.CRIOrder= 0;	                    // Event callback order
++  reg_info.CRIConsumerType= CHECK_CONSUMER; // Consumer type
++
++  /* Register for the event with NEB */
++  if (RegisterConsumer(&reg_info))
++  {
++    consoleprintf("Failed to register for NSS Volume Deactivation event \n");
++    return;
++  }
++  /* This ID is required for deregistration */
++  neb_consumer_id= reg_info.CRIConsumerID;
++
++  /* Get MySQL data volume name, stored in global variable datavolname */
++  getvolumename();
++
++  /*
++    Get the NSS volume ID of the MySQL Data volume.
++    Volume ID is stored in a global variable
++  */
++  getvolumeID((BYTE*) datavolname);
++}
++
++
++/*
++  Callback for NSS Volume Deactivation event
++*/
++
++ulong neb_event_callback(struct EventBlock *eblock)
++{
++  EventChangeVolStateEnter_s *voldata;
++  extern bool nw_panic;
++
++  voldata= (EventChangeVolStateEnter_s *)eblock->EBEventData;
++
++  /* Deactivation of a volume */
++  if ((voldata->oldState == zVOLSTATE_ACTIVE &&
++       voldata->newState == zVOLSTATE_DEACTIVE ||
++       voldata->newState == zVOLSTATE_MAINTENANCE))
++  {
++    /*
++      Ensure that we bring down MySQL server only for MySQL data
++      volume deactivation
++    */
++    if (!memcmp(&voldata->volID, &datavolid, sizeof(VolumeID_t)))
++    {
++      consoleprintf("MySQL data volume is deactivated, shutting down MySQL Server \n");
++      event_flag= TRUE;
++      nw_panic = TRUE;
++      event_flag= TRUE;
++      kill_server(0);
++    }
++  }
++  return 0;
++}
++
++
++/*
++  Function to get NSS volume ID of the MySQL data
++*/
++
++#define ADMIN_VOL_PATH					"_ADMIN:/Volumes/"
++
++static void getvolumeID(BYTE *volumeName)
++{
++  char path[zMAX_FULL_NAME];
++  Key_t rootKey= 0, fileKey= 0;
++  QUAD getInfoMask;
++  zInfo_s info;
++  STATUS status;
++
++  /* Get the root key */
++  if ((status= zRootKey(0, &rootKey)) != zOK)
++  {
++    consoleprintf("\nGetNSSVolumeProperties - Failed to get root key, status: %d\n.", (int) status);
++    goto exit;
++  }
++
++  /*
++    Get the file key. This is the key to the volume object in the
++    NSS admin volumes directory.
++  */
++
++  strxmov(path, (const char *) ADMIN_VOL_PATH, (const char *) volumeName,
++          NullS);
++  if ((status= zOpen(rootKey, zNSS_TASK, zNSPACE_LONG|zMODE_UTF8,
++                     (BYTE *) path, zRR_READ_ACCESS, &fileKey)) != zOK)
++  {
++    consoleprintf("\nGetNSSVolumeProperties - Failed to get file, status: %d\n.", (int) status);
++    goto exit;
++  }
++
++  getInfoMask= zGET_IDS | zGET_VOLUME_INFO ;
++  if ((status= zGetInfo(fileKey, getInfoMask, sizeof(info),
++                        zINFO_VERSION_A, &info)) != zOK)
++  {
++    consoleprintf("\nGetNSSVolumeProperties - Failed in zGetInfo, status: %d\n.", (int) status);
++    goto exit;
++  }
++
++  /* Copy the data to global variable */
++  datavolid.timeLow= info.vol.volumeID.timeLow;
++  datavolid.timeMid= info.vol.volumeID.timeMid;
++  datavolid.timeHighAndVersion= info.vol.volumeID.timeHighAndVersion;
++  datavolid.clockSeqHighAndReserved= info.vol.volumeID.clockSeqHighAndReserved;
++  datavolid.clockSeqLow= info.vol.volumeID.clockSeqLow;
++  /* This is guranteed to be 6-byte length (but sizeof() would be better) */
++  memcpy(datavolid.node, info.vol.volumeID.node, (unsigned int) 6);
++
++exit:
++  if (rootKey)
++    zClose(rootKey);
++  if (fileKey)
++    zClose(fileKey);
++}
++
++
++static void init_signals(void)
++{
++  int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT};
++
++  for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
++    signal(signals[i], kill_server);
++  mysql_cb_init();  // initialize callbacks
++
++}
++
++
++static void start_signal_handler(void)
++{
++  // Save vm id of this process
++  if (!opt_bootstrap)
++    create_pid_file();
++  // no signal handler
++}
++
++
++/*
++  Warn if the data is on a Traditional volume
++
++  NOTE
++    Already done by mysqld_safe
++*/
++
++static void check_data_home(const char *path)
++{
++}
++
++#elif defined(__EMX__)
++static void sig_reload(int signo)
++{
++ // Flush everything
++  bool not_used;
++  reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0, &not_used);
++  signal(signo, SIG_ACK);
++}
++
++static void sig_kill(int signo)
++{
++  if (!kill_in_progress)
++  {
++    abort_loop=1;				// mark abort for threads
++    kill_server((void*) signo);
++  }
++  signal(signo, SIG_ACK);
++}
++
++static void init_signals(void)
++{
++  signal(SIGQUIT, sig_kill);
++  signal(SIGKILL, sig_kill);
++  signal(SIGTERM, sig_kill);
++  signal(SIGINT,  sig_kill);
++  signal(SIGHUP,  sig_reload);	// Flush everything
++  signal(SIGALRM, SIG_IGN);
++  signal(SIGBREAK,SIG_IGN);
++  signal_thread = pthread_self();
++}
++
++
++static void start_signal_handler(void)
++{}
++
++static void check_data_home(const char *path)
++{}
++
++#else /* if ! __WIN__ && ! __EMX__ */
++
++#ifdef HAVE_LINUXTHREADS
++#define UNSAFE_DEFAULT_LINUX_THREADS 200
++#endif
++
++extern "C" sig_handler handle_segfault(int sig)
++{
++  time_t curr_time;
++  struct tm tm;
++  THD *thd=current_thd;
++
++  /*
++    Strictly speaking, one needs a mutex here
++    but since we have got SIGSEGV already, things are a mess
++    so not having the mutex is not as bad as possibly using a buggy
++    mutex - so we keep things simple
++  */
++  if (segfaulted)
++  {
++    fprintf(stderr, "Fatal signal %d while backtracing\n", sig);
++    exit(1);
++  }
++
++  segfaulted = 1;
++
++  curr_time= time(NULL);
++  localtime_r(&curr_time, &tm);
++
++  fprintf(stderr,"\
++%02d%02d%02d %2d:%02d:%02d - mysqld got signal %d;\n\
++This could be because you hit a bug. It is also possible that this binary\n\
++or one of the libraries it was linked against is corrupt, improperly built,\n\
++or misconfigured. This error can also be caused by malfunctioning hardware.\n",
++          tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
++          tm.tm_hour, tm.tm_min, tm.tm_sec,
++	  sig);
++  fprintf(stderr, "\
++We will try our best to scrape up some info that will hopefully help diagnose\n\
++the problem, but since we have already crashed, something is definitely wrong\n\
++and this may fail.\n\n");
++  fprintf(stderr, "key_buffer_size=%lu\n",
++          (ulong) dflt_key_cache->key_cache_mem_size);
++  fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
++  fprintf(stderr, "max_used_connections=%lu\n", max_used_connections);
++  fprintf(stderr, "max_connections=%lu\n", max_connections);
++  fprintf(stderr, "threads_connected=%u\n", thread_count);
++  fprintf(stderr, "It is possible that mysqld could use up to \n\
++key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %lu K\n\
++bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size +
++		     (global_system_variables.read_buff_size +
++		      global_system_variables.sortbuff_size) *
++		     max_connections)/ 1024);
++  fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
++
++#if defined(HAVE_LINUXTHREADS)
++  if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
++  {
++    fprintf(stderr, "\
++You seem to be running 32-bit Linux and have %d concurrent connections.\n\
++If you have not changed STACK_SIZE in LinuxThreads and built the binary \n\
++yourself, LinuxThreads is quite likely to steal a part of the global heap for\n\
++the thread stack. Please read http://www.mysql.com/doc/en/Linux.html\n\n",
++	    thread_count);
++  }
++#endif /* HAVE_LINUXTHREADS */
++
++#ifdef HAVE_STACKTRACE
++  if (!(test_flags & TEST_NO_STACKTRACE))
++  {
++    fprintf(stderr,"thd=%p\n",thd);
++    print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0,
++		     thread_stack);
++  }
++  if (thd)
++  {
++    fprintf(stderr, "Trying to get some variables.\n\
++Some pointers may be invalid and cause the dump to abort...\n");
++    safe_print_str("thd->query", thd->query, 1024);
++    fprintf(stderr, "thd->thread_id=%lu\n", (ulong) thd->thread_id);
++  }
++  fprintf(stderr, "\
++The manual page at http://www.mysql.com/doc/en/Crashing.html contains\n\
++information that should help you find out what is causing the crash.\n");
++  fflush(stderr);
++#endif /* HAVE_STACKTRACE */
++
++#ifdef HAVE_INITGROUPS
++  if (calling_initgroups)
++    fprintf(stderr, "\n\
++This crash occured while the server was calling initgroups(). This is\n\
++often due to the use of a mysqld that is statically linked against glibc\n\
++and configured to use LDAP in /etc/nsswitch.conf. You will need to either\n\
++upgrade to a version of glibc that does not have this problem (2.3.4 or\n\
++later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\
++mysqld that is not statically linked.\n");
++#endif
++
++#ifdef HAVE_NPTL
++  if (thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL"))
++    fprintf(stderr,"\n\
++You are running a statically-linked LinuxThreads binary on an NPTL system.\n\
++This can result in crashes on some distributions due to LT/NPTL conflicts.\n\
++You should either build a dynamically-linked binary, or force LinuxThreads\n\
++to be used with the LD_ASSUME_KERNEL environment variable. Please consult\n\
++the documentation for your distribution on how to do that.\n");
++#endif
++  
++  if (locked_in_memory)
++  {
++    fprintf(stderr, "\n\
++The \"--memlock\" argument, which was enabled, uses system calls that are\n\
++unreliable and unstable on some operating systems and operating-system\n\
++versions (notably, some versions of Linux).  This crash could be due to use\n\
++of those buggy OS calls.  You should consider whether you really need the\n\
++\"--memlock\" parameter and/or consult the OS distributer about \"mlockall\"\n\
++bugs.\n");
++  }
++
++  if (test_flags & TEST_CORE_ON_SIGNAL)
++  {
++    fprintf(stderr, "Writing a core file\n");
++    fflush(stderr);
++    write_core(sig);
++  }
++  exit(1);
++}
++
++#ifndef SA_RESETHAND
++#define SA_RESETHAND 0
++#endif
++#ifndef SA_NODEFER
++#define SA_NODEFER 0
++#endif
++
++#ifndef EMBEDDED_LIBRARY
++
++static void init_signals(void)
++{
++  sigset_t set;
++  struct sigaction sa;
++  DBUG_ENTER("init_signals");
++
++  if (test_flags & TEST_SIGINT)
++  {
++    my_sigset(thr_kill_signal, end_thread_signal);
++  }
++  my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
++
++  if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
++  {
++    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
++    sigemptyset(&sa.sa_mask);
++    sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
++
++    init_stacktrace();
++#if defined(__amiga__)
++    sa.sa_handler=(void(*)())handle_segfault;
++#else
++    sa.sa_handler=handle_segfault;
++#endif
++    sigaction(SIGSEGV, &sa, NULL);
++    sigaction(SIGABRT, &sa, NULL);
++#ifdef SIGBUS
++    sigaction(SIGBUS, &sa, NULL);
++#endif
++    sigaction(SIGILL, &sa, NULL);
++    sigaction(SIGFPE, &sa, NULL);
++  }
++
++#ifdef HAVE_GETRLIMIT
++  if (test_flags & TEST_CORE_ON_SIGNAL)
++  {
++    /* Change limits so that we will get a core file */
++    STRUCT_RLIMIT rl;
++    rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
++    if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
++      sql_print_warning("setrlimit could not change the size of core files to 'infinity';  We may not be able to generate a core file on signals");
++  }
++#endif
++  (void) sigemptyset(&set);
++  my_sigset(SIGPIPE,SIG_IGN);
++  sigaddset(&set,SIGPIPE);
++  sigaddset(&set,SIGINT);
++#ifndef IGNORE_SIGHUP_SIGQUIT
++  sigaddset(&set,SIGQUIT);
++  sigaddset(&set,SIGHUP);
++#endif
++  sigaddset(&set,SIGTERM);
++
++  /* Fix signals if blocked by parents (can happen on Mac OS X) */
++  sigemptyset(&sa.sa_mask);
++  sa.sa_flags = 0;
++  sa.sa_handler = print_signal_warning;
++  sigaction(SIGTERM, &sa, (struct sigaction*) 0);
++  sa.sa_flags = 0;
++  sa.sa_handler = print_signal_warning;
++  sigaction(SIGHUP, &sa, (struct sigaction*) 0);
++#ifdef SIGTSTP
++  sigaddset(&set,SIGTSTP);
++#endif
++  if (thd_lib_detected != THD_LIB_LT)
++    sigaddset(&set,THR_SERVER_ALARM);
++  if (test_flags & TEST_SIGINT)
++  {
++    // May be SIGINT
++    sigdelset(&set, thr_kill_signal);
++  }
++  sigprocmask(SIG_SETMASK,&set,NULL);
++  pthread_sigmask(SIG_SETMASK,&set,NULL);
++  DBUG_VOID_RETURN;
++}
++
++
++static void start_signal_handler(void)
++{
++  int error;
++  pthread_attr_t thr_attr;
++  DBUG_ENTER("start_signal_handler");
++
++  (void) pthread_attr_init(&thr_attr);
++#if !defined(HAVE_DEC_3_2_THREADS)
++  pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
++  (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
++  if (!(opt_specialflag & SPECIAL_NO_PRIOR))
++    my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
++#if defined(__ia64__) || defined(__ia64)
++  /*
++    Peculiar things with ia64 platforms - it seems we only have half the
++    stack size in reality, so we have to double it here
++  */
++  pthread_attr_setstacksize(&thr_attr,thread_stack*2);
++#else
++  pthread_attr_setstacksize(&thr_attr,thread_stack);
++#endif
++#endif
++
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++  if ((error=pthread_create(&signal_thread,&thr_attr,signal_hand,0)))
++  {
++    sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
++		    error,errno);
++    exit(1);
++  }
++  (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
++  pthread_mutex_unlock(&LOCK_thread_count);
++
++  (void) pthread_attr_destroy(&thr_attr);
++  DBUG_VOID_RETURN;
++}
++
++
++/* This threads handles all signals and alarms */
++
++/* ARGSUSED */
++pthread_handler_t signal_hand(void *arg __attribute__((unused)))
++{
++  sigset_t set;
++  int sig;
++  my_thread_init();				// Init new thread
++  DBUG_ENTER("signal_hand");
++  signal_thread_in_use= 1;
++
++  /*
++    Setup alarm handler
++    This should actually be '+ max_number_of_slaves' instead of +10,
++    but the +10 should be quite safe.
++  */
++  init_thr_alarm(max_connections +
++		 global_system_variables.max_insert_delayed_threads + 10);
++  if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
++  {
++    (void) sigemptyset(&set);			// Setup up SIGINT for debug
++    (void) sigaddset(&set,SIGINT);		// For debugging
++    (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
++  }
++  (void) sigemptyset(&set);			// Setup up SIGINT for debug
++#ifdef USE_ONE_SIGNAL_HAND
++  (void) sigaddset(&set,THR_SERVER_ALARM);	// For alarms
++#endif
++#ifndef IGNORE_SIGHUP_SIGQUIT
++  (void) sigaddset(&set,SIGQUIT);
++  (void) sigaddset(&set,SIGHUP);
++#endif
++  (void) sigaddset(&set,SIGTERM);
++  (void) sigaddset(&set,SIGTSTP);
++
++  /* Save pid to this process (or thread on Linux) */
++  if (!opt_bootstrap)
++    create_pid_file();
++
++#ifdef HAVE_STACK_TRACE_ON_SEGV
++  if (opt_do_pstack)
++  {
++    sprintf(pstack_file_name,"mysqld-%lu-%%d-%%d.backtrace", (ulong)getpid());
++    pstack_install_segv_action(pstack_file_name);
++  }
++#endif /* HAVE_STACK_TRACE_ON_SEGV */
++
++  /*
++    signal to start_signal_handler that we are ready
++    This works by waiting for start_signal_handler to free mutex,
++    after which we signal it that we are ready.
++    At this pointer there is no other threads running, so there
++    should not be any other pthread_cond_signal() calls.
++  */
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++  (void) pthread_mutex_unlock(&LOCK_thread_count);
++  (void) pthread_cond_broadcast(&COND_thread_count);
++
++  (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
++  for (;;)
++  {
++    int error;					// Used when debugging
++    if (shutdown_in_progress && !abort_loop)
++    {
++      sig= SIGTERM;
++      error=0;
++    }
++    else
++      while ((error=my_sigwait(&set,&sig)) == EINTR) ;
++    if (cleanup_done)
++    {
++      DBUG_PRINT("quit",("signal_handler: calling my_thread_end()"));
++      my_thread_end();
++      signal_thread_in_use= 0;
++      pthread_exit(0);				// Safety
++    }
++    switch (sig) {
++    case SIGTERM:
++    case SIGQUIT:
++    case SIGKILL:
++#ifdef EXTRA_DEBUG
++      sql_print_information("Got signal %d to shutdown mysqld",sig);
++#endif
++      DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
++      if (!abort_loop)
++      {
++	abort_loop=1;				// mark abort for threads
++#ifdef USE_ONE_SIGNAL_HAND
++	pthread_t tmp;
++	if (!(opt_specialflag & SPECIAL_NO_PRIOR))
++	  my_pthread_attr_setprio(&connection_attrib,INTERRUPT_PRIOR);
++	if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
++			   (void*) &sig))
++	  sql_print_error("Can't create thread to kill server");
++#else
++	kill_server((void*) sig);	// MIT THREAD has a alarm thread
++#endif
++      }
++      break;
++    case SIGHUP:
++      if (!abort_loop)
++      {
++        bool not_used;
++	mysql_print_status();		// Print some debug info
++	reload_acl_and_cache((THD*) 0,
++			     (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
++			      REFRESH_GRANT |
++			      REFRESH_THREADS | REFRESH_HOSTS),
++			     (TABLE_LIST*) 0, &not_used); // Flush logs
++      }
++      break;
++#ifdef USE_ONE_SIGNAL_HAND
++    case THR_SERVER_ALARM:
++      process_alarm(sig);			// Trigger alarms.
++      break;
++#endif
++    default:
++#ifdef EXTRA_DEBUG
++      sql_print_warning("Got signal: %d  error: %d",sig,error); /* purecov: tested */
++#endif
++      break;					/* purecov: tested */
++    }
++  }
++  return(0);					/* purecov: deadcode */
++}
++
++static void check_data_home(const char *path)
++{}
++
++#endif /*!EMBEDDED_LIBRARY*/
++#endif	/* __WIN__*/
++
++
++/*
++  All global error messages are sent here where the first one is stored
++  for the client
++*/
++
++
++/* ARGSUSED */
++static int my_message_sql(uint error, const char *str, myf MyFlags)
++{
++  THD *thd;
++  DBUG_ENTER("my_message_sql");
++  DBUG_PRINT("error", ("error: %u  message: '%s'", error, str));
++  /*
++    Put here following assertion when situation with EE_* error codes
++    will be fixed
++    DBUG_ASSERT(error != 0);
++  */
++  if ((thd= current_thd))
++  {
++    /*
++      TODO: There are two exceptions mechanism (THD and sp_rcontext),
++      this could be improved by having a common stack of handlers.
++    */
++    if (thd->handle_error(error,
++                          MYSQL_ERROR::WARN_LEVEL_ERROR))
++      DBUG_RETURN(0);
++
++    if (thd->spcont &&
++        thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd))
++    {
++      DBUG_RETURN(0);
++    }
++
++    thd->query_error=  1; // needed to catch query errors during replication
++
++    if (!thd->no_warnings_for_error)
++      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
++    /*
++      thd->lex->current_select == 0 if lex structure is not inited
++      (not query command (COM_QUERY))
++    */
++    if (thd->lex->current_select &&
++	thd->lex->current_select->no_error && !thd->is_fatal_error)
++    {
++      DBUG_PRINT("error", ("Error converted to warning: current_select: no_error %d  fatal_error: %d",
++                           (thd->lex->current_select ?
++                            thd->lex->current_select->no_error : 0),
++                           (int) thd->is_fatal_error));
++    }
++    else
++    {
++      NET *net= &thd->net;
++      net->report_error= 1;
++      query_cache_abort(net);
++      if (!net->last_error[0])			// Return only first message
++      {
++	strmake(net->last_error, str, sizeof(net->last_error)-1);
++	net->last_errno= error ? error : ER_UNKNOWN_ERROR;
++      }
++    }
++  }
++  if (!thd || MyFlags & ME_NOREFRESH)
++    sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
++  DBUG_RETURN(0);
++}
++
++
++#ifndef EMBEDDED_LIBRARY
++static void *my_str_malloc_mysqld(size_t size)
++{
++  return my_malloc(size, MYF(MY_FAE));
++}
++
++
++static void my_str_free_mysqld(void *ptr)
++{
++  my_free((gptr)ptr, MYF(MY_FAE));
++}
++#endif /* EMBEDDED_LIBRARY */
++
++
++#ifdef __WIN__
++
++struct utsname
++{
++  char nodename[FN_REFLEN];
++};
++
++
++int uname(struct utsname *a)
++{
++  return -1;
++}
++
++
++pthread_handler_t handle_shutdown(void *arg)
++{
++  MSG msg;
++  my_thread_init();
++
++  /* this call should create the message queue for this thread */
++  PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
++#if !defined(EMBEDDED_LIBRARY)
++  if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
++#endif /* EMBEDDED_LIBRARY */
++     kill_server(MYSQL_KILL_SIGNAL);
++  return 0;
++}
++
++
++int STDCALL handle_kill(ulong ctrl_type)
++{
++  if (ctrl_type == CTRL_CLOSE_EVENT ||
++      ctrl_type == CTRL_SHUTDOWN_EVENT)
++  {
++    kill_server(MYSQL_KILL_SIGNAL);
++    return TRUE;
++  }
++  return FALSE;
++}
++#endif
++
++
++#ifdef OS2
++pthread_handler_t handle_shutdown(void *arg)
++{
++  my_thread_init();
++
++  // wait semaphore
++  pthread_cond_wait(&eventShutdown, NULL);
++
++  // close semaphore and kill server
++  pthread_cond_destroy(&eventShutdown);
++
++  /*
++    Exit main loop on main thread, so kill will be done from
++    main thread (this is thread 2)
++  */
++  abort_loop = 1;
++
++  // unblock select()
++  so_cancel(ip_sock);
++  so_cancel(unix_sock);
++
++  return 0;
++}
++#endif
++
++
++static const char *load_default_groups[]= {
++#ifdef HAVE_NDBCLUSTER_DB
++"mysql_cluster",
++#endif
++"mysqld","server", MYSQL_BASE_VERSION, 0, 0};
++
++#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
++static const int load_default_groups_sz=
++sizeof(load_default_groups)/sizeof(load_default_groups[0]);
++#endif
++
++
++/*
++  Initialize one of the global date/time format variables
++
++  SYNOPSIS
++    init_global_datetime_format()
++    format_type		What kind of format should be supported
++    var_ptr		Pointer to variable that should be updated
++
++  NOTES
++    The default value is taken from either opt_date_time_formats[] or
++    the ISO format (ANSI SQL)
++
++  RETURN
++    0 ok
++    1 error
++*/
++
++static bool init_global_datetime_format(timestamp_type format_type,
++                                        DATE_TIME_FORMAT **var_ptr)
++{
++  /* Get command line option */
++  const char *str= opt_date_time_formats[format_type];
++
++  if (!str)					// No specified format
++  {
++    str= get_date_time_format_str(&known_date_time_formats[ISO_FORMAT],
++				  format_type);
++    /*
++      Set the "command line" option to point to the generated string so
++      that we can set global formats back to default
++    */
++    opt_date_time_formats[format_type]= str;
++  }
++  if (!(*var_ptr= date_time_format_make(format_type, str, strlen(str))))
++  {
++    fprintf(stderr, "Wrong date/time format specifier: %s\n", str);
++    return 1;
++  }
++  return 0;
++}
++
++
++static int init_common_variables(const char *conf_file_name, int argc,
++				 char **argv, const char **groups)
++{
++  umask(((~my_umask) & 0666));
++  my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
++  tzset();			// Set tzname
++
++  max_system_variables.pseudo_thread_id= (ulong)~0;
++  server_start_time= flush_status_time= time((time_t*) 0);
++  if (init_thread_environment())
++    return 1;
++  mysql_init_variables();
++
++#ifdef OS2
++  {
++    // fix timezone for daylight saving
++    struct tm *ts = localtime(&start_time);
++    if (ts->tm_isdst > 0)
++      _timezone -= 3600;
++  }
++#endif
++#ifdef HAVE_TZNAME
++  {
++    struct tm tm_tmp;
++    localtime_r(&server_start_time,&tm_tmp);
++    strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
++            sizeof(system_time_zone)-1);
++
++ }
++#endif
++  /*
++    We set SYSTEM time zone as reasonable default and
++    also for failure of my_tz_init() and bootstrap mode.
++    If user explicitly set time zone with --default-time-zone
++    option we will change this value in my_tz_init().
++  */
++  global_system_variables.time_zone= my_tz_SYSTEM;
++
++  /*
++    Init mutexes for the global MYSQL_LOG objects.
++    As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
++    global MYSQL_LOGs in their constructors, because then they would be inited
++    before MY_INIT(). So we do it here.
++  */
++  mysql_log.init_pthread_objects();
++  mysql_slow_log.init_pthread_objects();
++  mysql_bin_log.init_pthread_objects();
++
++  if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
++  {
++    strmake(glob_hostname, STRING_WITH_LEN("localhost"));
++    sql_print_warning("gethostname failed, using '%s' as hostname",
++                      glob_hostname);
++    strmake(pidfile_name, STRING_WITH_LEN("mysql"));
++  }
++  else
++    strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
++  strmov(fn_ext(pidfile_name),".pid");		// Add proper extension
++
++  load_defaults(conf_file_name, groups, &argc, &argv);
++  defaults_argv=argv;
++  get_options(argc,argv);
++  set_server_version();
++
++  DBUG_PRINT("info",("%s  Ver %s for %s on %s\n",my_progname,
++		     server_version, SYSTEM_TYPE,MACHINE_TYPE));
++
++#ifdef HAVE_LARGE_PAGES
++  /* Initialize large page size */
++  if (opt_large_pages && (opt_large_page_size= my_get_large_page_size()))
++  {
++      my_use_large_pages= 1;
++      my_large_page_size= opt_large_page_size;
++#ifdef HAVE_INNOBASE_DB
++      innobase_use_large_pages= 1;
++      innobase_large_page_size= opt_large_page_size;
++#endif
++  }
++#endif /* HAVE_LARGE_PAGES */
++
++  /* connections and databases needs lots of files */
++  {
++    uint files, wanted_files, max_open_files;
++
++    /* MyISAM requires two file handles per table. */
++    wanted_files= 10+max_connections+table_cache_size*2;
++    /*
++      We are trying to allocate no less than max_connections*5 file
++      handles (i.e. we are trying to set the limit so that they will
++      be available).  In addition, we allocate no less than how much
++      was already allocated.  However below we report a warning and
++      recompute values only if we got less file handles than were
++      explicitly requested.  No warning and re-computation occur if we
++      can't get max_connections*5 but still got no less than was
++      requested (value of wanted_files).
++    */
++    max_open_files= max(max(wanted_files, max_connections*5),
++                        open_files_limit);
++    files= my_set_max_open_files(max_open_files);
++
++    if (files < wanted_files)
++    {
++      if (!open_files_limit)
++      {
++        /*
++          If we have requested too much file handles than we bring
++          max_connections in supported bounds.
++        */
++        max_connections= (ulong) min(files-10-TABLE_OPEN_CACHE_MIN*2,
++                                     max_connections);
++        /*
++          Decrease table_cache_size according to max_connections, but
++          not below TABLE_OPEN_CACHE_MIN.  Outer min() ensures that we
++          never increase table_cache_size automatically (that could
++          happen if max_connections is decreased above).
++        */
++        table_cache_size= (ulong) min(max((files-10-max_connections)/2,
++                                          TABLE_OPEN_CACHE_MIN),
++                                      table_cache_size);    
++	DBUG_PRINT("warning",
++		   ("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
++		    files, max_connections, table_cache_size));
++	if (global_system_variables.log_warnings)
++	  sql_print_warning("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
++			files, max_connections, table_cache_size);
++      }
++      else if (global_system_variables.log_warnings)
++	sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files);
++    }
++    open_files_limit= files;
++  }
++  unireg_init(opt_specialflag); /* Set up extern variabels */
++  if (init_errmessage())	/* Read error messages from file */
++    return 1;
++  init_client_errs();
++  lex_init();
++  item_init();
++  set_var_init();
++  mysys_uses_curses=0;
++#ifdef USE_REGEX
++  my_regex_init(&my_charset_latin1);
++#endif
++  /*
++    Process a comma-separated character set list and choose
++    the first available character set. This is mostly for
++    test purposes, to be able to start "mysqld" even if
++    the requested character set is not available (see bug#18743).
++  */
++  for (;;)
++  {
++    char *next_character_set_name= strchr(default_character_set_name, ',');
++    if (next_character_set_name)
++      *next_character_set_name++= '\0';
++    if (!(default_charset_info=
++          get_charset_by_csname(default_character_set_name,
++                                MY_CS_PRIMARY, MYF(MY_WME))))
++    {
++      if (next_character_set_name)
++      {
++        default_character_set_name= next_character_set_name;
++        default_collation_name= 0;          // Ignore collation
++      }
++      else
++        return 1;                           // Eof of the list
++    }
++    else
++      break;
++  }
++
++  if (default_collation_name)
++  {
++    CHARSET_INFO *default_collation;
++    default_collation= get_charset_by_name(default_collation_name, MYF(0));
++    if (!default_collation)
++    {
++      sql_print_error(ER(ER_UNKNOWN_COLLATION), default_collation_name);
++      return 1;
++    }
++    if (!my_charset_same(default_charset_info, default_collation))
++    {
++      sql_print_error(ER(ER_COLLATION_CHARSET_MISMATCH),
++		      default_collation_name,
++		      default_charset_info->csname);
++      return 1;
++    }
++    default_charset_info= default_collation;
++  }
++  /* Set collactions that depends on the default collation */
++  global_system_variables.collation_server=	 default_charset_info;
++  global_system_variables.collation_database=	 default_charset_info;
++  global_system_variables.collation_connection=  default_charset_info;
++  global_system_variables.character_set_results= default_charset_info;
++  global_system_variables.character_set_client= default_charset_info;
++  global_system_variables.collation_connection= default_charset_info;
++
++  if (!(character_set_filesystem=
++        get_charset_by_csname(character_set_filesystem_name,
++                              MY_CS_PRIMARY, MYF(MY_WME))))
++    return 1;
++  global_system_variables.character_set_filesystem= character_set_filesystem;
++
++  if (!(my_default_lc_time_names=
++        my_locale_by_name(lc_time_names_name)))
++  {
++    sql_print_error("Unknown locale: '%s'", lc_time_names_name);
++    return 1;
++  }
++  global_system_variables.lc_time_names= my_default_lc_time_names;
++  
++  sys_init_connect.value_length= 0;
++  if ((sys_init_connect.value= opt_init_connect))
++    sys_init_connect.value_length= strlen(opt_init_connect);
++  else
++    sys_init_connect.value=my_strdup("",MYF(0));
++
++  sys_init_slave.value_length= 0;
++  if ((sys_init_slave.value= opt_init_slave))
++    sys_init_slave.value_length= strlen(opt_init_slave);
++  else
++    sys_init_slave.value=my_strdup("",MYF(0));
++
++  if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
++    return 1;
++  if (my_dbopt_init())
++    return 1;
++
++  /*
++    Ensure that lower_case_table_names is set on system where we have case
++    insensitive names.  If this is not done the users MyISAM tables will
++    get corrupted if accesses with names of different case.
++  */
++  DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
++  lower_case_file_system= test_if_case_insensitive(mysql_real_data_home);
++  if (!lower_case_table_names && lower_case_file_system == 1)
++  {
++    if (lower_case_table_names_used)
++    {
++      if (global_system_variables.log_warnings)
++	sql_print_warning("\
++You have forced lower_case_table_names to 0 through a command-line \
++option, even though your file system '%s' is case insensitive.  This means \
++that you can corrupt a MyISAM table by accessing it with different cases. \
++You should consider changing lower_case_table_names to 1 or 2",
++			mysql_real_data_home);
++    }
++    else
++    {
++      if (global_system_variables.log_warnings)
++	sql_print_warning("Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home);
++      lower_case_table_names= 2;
++    }
++  }
++  else if (lower_case_table_names == 2 &&
++           !(lower_case_file_system=
++             (test_if_case_insensitive(mysql_real_data_home) == 1)))
++  {
++    if (global_system_variables.log_warnings)
++      sql_print_warning("lower_case_table_names was set to 2, even though your "
++                        "the file system '%s' is case sensitive.  Now setting "
++                        "lower_case_table_names to 0 to avoid future problems.",
++			mysql_real_data_home);
++    lower_case_table_names= 0;
++  }
++  else
++  {
++    lower_case_file_system=
++      (test_if_case_insensitive(mysql_real_data_home) == 1);
++  }
++
++  /* Reset table_alias_charset, now that lower_case_table_names is set. */
++  table_alias_charset= (lower_case_table_names ?
++			files_charset_info :
++			&my_charset_bin);
++
++  return 0;
++}
++
++
++static int init_thread_environment()
++{
++  (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
++  (void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
++  (void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
++  (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW);
++  (void) pthread_mutex_init(&LOCK_manager,MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_global_read_lock, MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST);
++  (void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
++#ifdef HAVE_OPENSSL
++  (void) pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST);
++#ifndef HAVE_YASSL
++  openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
++                                                     sizeof(openssl_lock_t));
++  for (int i= 0; i < CRYPTO_num_locks(); ++i)
++    (void) my_rwlock_init(&openssl_stdlocks[i].lock, NULL);
++  CRYPTO_set_dynlock_create_callback(openssl_dynlock_create);
++  CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
++  CRYPTO_set_dynlock_lock_callback(openssl_lock);
++  CRYPTO_set_locking_callback(openssl_lock_function);
++  CRYPTO_set_id_callback(openssl_id_function);
++#endif
++#endif
++  (void) my_rwlock_init(&LOCK_sys_init_connect, NULL);
++  (void) my_rwlock_init(&LOCK_sys_init_slave, NULL);
++  (void) my_rwlock_init(&LOCK_grant, NULL);
++  (void) pthread_cond_init(&COND_thread_count,NULL);
++  (void) pthread_cond_init(&COND_refresh,NULL);
++  (void) pthread_cond_init(&COND_global_read_lock,NULL);
++  (void) pthread_cond_init(&COND_thread_cache,NULL);
++  (void) pthread_cond_init(&COND_flush_thread_cache,NULL);
++  (void) pthread_cond_init(&COND_manager,NULL);
++#ifdef HAVE_REPLICATION
++  (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
++  (void) pthread_cond_init(&COND_rpl_status, NULL);
++#endif
++  sp_cache_init();
++  /* Parameter for threads created for connections */
++  (void) pthread_attr_init(&connection_attrib);
++  (void) pthread_attr_setdetachstate(&connection_attrib,
++				     PTHREAD_CREATE_DETACHED);
++  pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
++  if (!(opt_specialflag & SPECIAL_NO_PRIOR))
++    my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR);
++
++  if (pthread_key_create(&THR_THD,NULL) ||
++      pthread_key_create(&THR_MALLOC,NULL))
++  {
++    sql_print_error("Can't create thread-keys");
++    return 1;
++  }
++  return 0;
++}
++
++
++#if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
++static unsigned long openssl_id_function()
++{
++  return (unsigned long) pthread_self();
++}
++
++
++static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
++{
++  openssl_lock_t *lock= new openssl_lock_t;
++  my_rwlock_init(&lock->lock, NULL);
++  return lock;
++}
++
++
++static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file,
++				    int line)
++{
++  rwlock_destroy(&lock->lock);
++  delete lock;
++}
++
++
++static void openssl_lock_function(int mode, int n, const char *file, int line)
++{
++  if (n < 0 || n > CRYPTO_num_locks())
++  {
++    /* Lock number out of bounds. */
++    sql_print_error("Fatal: OpenSSL interface problem (n = %d)", n);
++    abort();
++  }
++  openssl_lock(mode, &openssl_stdlocks[n], file, line);
++}
++
++
++static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
++			 int line)
++{
++  int err;
++  char const *what;
++
++  switch (mode) {
++  case CRYPTO_LOCK|CRYPTO_READ:
++    what = "read lock";
++    err = rw_rdlock(&lock->lock);
++    break;
++  case CRYPTO_LOCK|CRYPTO_WRITE:
++    what = "write lock";
++    err = rw_wrlock(&lock->lock);
++    break;
++  case CRYPTO_UNLOCK|CRYPTO_READ:
++  case CRYPTO_UNLOCK|CRYPTO_WRITE:
++    what = "unlock";
++    err = rw_unlock(&lock->lock);
++    break;
++  default:
++    /* Unknown locking mode. */
++    sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode);
++    abort();
++  }
++  if (err)
++  {
++    sql_print_error("Fatal: can't %s OpenSSL lock", what);
++    abort();
++  }
++}
++#endif /* HAVE_OPENSSL */
++
++
++#ifndef EMBEDDED_LIBRARY
++
++static void init_ssl()
++{
++#ifdef HAVE_OPENSSL
++  if (opt_use_ssl)
++  {
++    /* having ssl_acceptor_fd != 0 signals the use of SSL */
++    ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
++					  opt_ssl_ca, opt_ssl_capath,
++					  opt_ssl_cipher);
++    DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd));
++    if (!ssl_acceptor_fd)
++    {
++      sql_print_warning("Failed to setup SSL");
++      opt_use_ssl = 0;
++      have_ssl= SHOW_OPTION_DISABLED;
++    }
++  }
++  else
++  {
++    have_ssl= SHOW_OPTION_DISABLED;
++  }
++  if (des_key_file)
++    load_des_key_file(des_key_file);
++#endif /* HAVE_OPENSSL */
++}
++
++#endif /* EMBEDDED_LIBRARY */
++
++static int init_server_components()
++{
++  DBUG_ENTER("init_server_components");
++  if (table_cache_init() || hostname_cache_init())
++    unireg_abort(1);
++
++  query_cache_result_size_limit(query_cache_limit);
++  query_cache_set_min_res_unit(query_cache_min_res_unit);
++  query_cache_init();
++  query_cache_resize(query_cache_size);
++  randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
++  reset_floating_point_exceptions();
++  init_thr_lock();
++#ifdef HAVE_REPLICATION
++  init_slave_list();
++#endif
++  /* Setup log files */
++  if (opt_log)
++    mysql_log.open_query_log(opt_logname);
++  if (opt_update_log)
++  {
++    /*
++      Update log is removed since 5.0. But we still accept the option.
++      The idea is if the user already uses the binlog and the update log,
++      we completely ignore any option/variable related to the update log, like
++      if the update log did not exist. But if the user uses only the update
++      log, then we translate everything into binlog for him (with warnings).
++      Implementation of the above :
++      - If mysqld is started with --log-update and --log-bin,
++      ignore --log-update (print a warning), push a warning when SQL_LOG_UPDATE
++      is used, and turn off --sql-bin-update-same.
++      This will completely ignore SQL_LOG_UPDATE
++      - If mysqld is started with --log-update only,
++      change it to --log-bin (with the filename passed to log-update,
++      plus '-bin') (print a warning), push a warning when SQL_LOG_UPDATE is
++      used, and turn on --sql-bin-update-same.
++      This will translate SQL_LOG_UPDATE to SQL_LOG_BIN.
++
++      Note that we tell the user that --sql-bin-update-same is deprecated and
++      does nothing, and we don't take into account if he used this option or
++      not; but internally we give this variable a value to have the behaviour
++      we want (i.e. have SQL_LOG_UPDATE influence SQL_LOG_BIN or not).
++      As sql-bin-update-same, log-update and log-bin cannot be changed by the
++      user after starting the server (they are not variables), the user will
++      not later interfere with the settings we do here.
++    */
++    if (opt_bin_log)
++    {
++      opt_sql_bin_update= 0;
++      sql_print_error("The update log is no longer supported by MySQL in \
++version 5.0 and above. It is replaced by the binary log.");
++    }
++    else
++    {
++      opt_sql_bin_update= 1;
++      opt_bin_log= 1;
++      if (opt_update_logname)
++      {
++        /* as opt_bin_log==0, no need to free opt_bin_logname */
++        if (!(opt_bin_logname= my_strdup(opt_update_logname, MYF(MY_WME))))
++          exit(EXIT_OUT_OF_MEMORY);
++        sql_print_error("The update log is no longer supported by MySQL in \
++version 5.0 and above. It is replaced by the binary log. Now starting MySQL \
++with --log-bin='%s' instead.",opt_bin_logname);
++      }
++      else
++        sql_print_error("The update log is no longer supported by MySQL in \
++version 5.0 and above. It is replaced by the binary log. Now starting MySQL \
++with --log-bin instead.");
++    }
++  }
++  if (opt_log_slave_updates && !opt_bin_log)
++  {
++    sql_print_warning("You need to use --log-bin to make "
++                      "--log-slave-updates work.");
++      unireg_abort(1);
++  }
++
++  if (opt_slow_log)
++    mysql_slow_log.open_slow_log(opt_slow_logname);
++
++#ifdef HAVE_REPLICATION
++  if (opt_log_slave_updates && replicate_same_server_id)
++  {
++    sql_print_error("\
++using --replicate-same-server-id in conjunction with \
++--log-slave-updates is impossible, it would lead to infinite loops in this \
++server.");
++    unireg_abort(1);
++  }
++#endif
++
++  if (opt_error_log)
++  {
++    if (!log_error_file_ptr[0])
++      fn_format(log_error_file, pidfile_name, mysql_data_home, ".err",
++                MY_REPLACE_EXT); /* replace '.<domain>' by '.err', bug#4997 */
++    else
++      fn_format(log_error_file, log_error_file_ptr, mysql_data_home, ".err",
++		MY_UNPACK_FILENAME | MY_SAFE_PATH);
++    if (!log_error_file[0])
++      opt_error_log= 1;				// Too long file name
++    else
++    {
++#ifndef EMBEDDED_LIBRARY
++      if (freopen(log_error_file, "a+", stdout))
++#endif
++	stderror_file= freopen(log_error_file, "a+", stderr);
++    }
++  }
++
++  if (opt_bin_log)
++  {
++    char buf[FN_REFLEN];
++    const char *ln;
++    ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
++    if (!opt_bin_logname && !opt_binlog_index_name)
++    {
++      /*
++        User didn't give us info to name the binlog index file.
++        Picking `hostname`-bin.index like did in 4.x, causes replication to
++        fail if the hostname is changed later. So, we would like to instead
++        require a name. But as we don't want to break many existing setups, we
++        only give warning, not error.
++      */
++      sql_print_warning("No argument was provided to --log-bin, and "
++                        "--log-bin-index was not used; so replication "
++                        "may break when this MySQL server acts as a "
++                        "master and has his hostname changed!! Please "
++                        "use '--log-bin=%s' to avoid this problem.", ln);
++    }
++    if (ln == buf)
++    {
++      my_free(opt_bin_logname, MYF(MY_ALLOW_ZERO_PTR));
++      opt_bin_logname=my_strdup(buf, MYF(0));
++    }
++    if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln))
++    {
++      unireg_abort(1);
++    }
++
++    /*
++      Used to specify which type of lock we need to use for queries of type
++      INSERT ... SELECT. This will change when we have row level logging.
++    */
++    using_update_log=1;
++  }
++
++  if (xid_cache_init())
++  {
++    sql_print_error("Out of memory");
++    unireg_abort(1);
++  }
++  if (ha_init())
++  {
++    sql_print_error("Can't init databases");
++    unireg_abort(1);
++  }
++
++  /*
++    Check that the default storage engine is actually available.
++  */
++  if (!ha_storage_engine_is_enabled((enum db_type)
++                                    global_system_variables.table_type))
++  {
++    if (!opt_bootstrap)
++    {
++      sql_print_error("Default storage engine (%s) is not available",
++                      ha_get_storage_engine((enum db_type)
++                                            global_system_variables.table_type));
++      unireg_abort(1);
++    }
++    global_system_variables.table_type= DB_TYPE_MYISAM;
++  }
++
++  tc_log= (total_ha_2pc > 1 ? (opt_bin_log  ?
++                               (TC_LOG *) &mysql_bin_log :
++                               (TC_LOG *) &tc_log_mmap) :
++           (TC_LOG *) &tc_log_dummy);
++
++  if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
++  {
++    sql_print_error("Can't init tc log");
++    unireg_abort(1);
++  }
++
++  if (ha_recover(0))
++  {
++    unireg_abort(1);
++  }
++
++  if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
++                                        WRITE_CACHE, 0, max_binlog_size, 0))
++    unireg_abort(1);
++
++#ifdef HAVE_REPLICATION
++  if (opt_bin_log && expire_logs_days)
++  {
++    time_t purge_time= time(0) - expire_logs_days*24*60*60;
++    if (purge_time >= 0)
++      mysql_bin_log.purge_logs_before_date(purge_time);
++  }
++#endif
++
++  if (opt_myisam_log)
++    (void) mi_log(1);
++
++  /* call ha_init_key_cache() on all key caches to init them */
++  process_key_caches(&ha_init_key_cache);
++
++#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
++  if (locked_in_memory && !getuid())
++  {
++    if (setreuid((uid_t)-1, 0) == -1)
++    {                        // this should never happen
++      sql_perror("setreuid");
++      unireg_abort(1);
++    }
++    if (mlockall(MCL_CURRENT))
++    {
++      if (global_system_variables.log_warnings)
++	sql_print_warning("Failed to lock memory. Errno: %d\n",errno);
++      locked_in_memory= 0;
++    }
++    if (user_info)
++      set_user(mysqld_user, user_info);
++  }
++  else
++#endif
++    locked_in_memory=0;
++
++  ft_init_stopwords();
++
++  init_max_user_conn();
++  init_update_queries();
++  DBUG_RETURN(0);
++}
++
++
++#ifndef EMBEDDED_LIBRARY
++static void create_maintenance_thread()
++{
++  if (
++#ifdef HAVE_BERKELEY_DB
++      (have_berkeley_db == SHOW_OPTION_YES) ||
++#endif
++      (flush_time && flush_time != ~(ulong) 0L))
++  {
++    pthread_t hThread;
++    if (pthread_create(&hThread,&connection_attrib,handle_manager,0))
++      sql_print_warning("Can't create thread to manage maintenance");
++  }
++}
++
++
++static void create_shutdown_thread()
++{
++#ifdef __WIN__
++  hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
++  pthread_t hThread;
++  if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
++    sql_print_warning("Can't create thread to handle shutdown requests");
++
++  // On "Stop Service" we have to do regular shutdown
++  Service.SetShutdownEvent(hEventShutdown);
++#endif
++#ifdef OS2
++  pthread_cond_init(&eventShutdown, NULL);
++  pthread_t hThread;
++  if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
++    sql_print_warning("Can't create thread to handle shutdown requests");
++#endif
++}
++
++#endif /* EMBEDDED_LIBRARY */
++
++#if defined(__NT__) || defined(HAVE_SMEM)
++static void handle_connections_methods()
++{
++  pthread_t hThread;
++  DBUG_ENTER("handle_connections_methods");
++#ifdef __NT__
++  if (hPipe == INVALID_HANDLE_VALUE &&
++      (!have_tcpip || opt_disable_networking) &&
++      !opt_enable_shared_memory)
++  {
++    sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
++    unireg_abort(1);				// Will not return
++  }
++#endif
++
++  pthread_mutex_lock(&LOCK_thread_count);
++  (void) pthread_cond_init(&COND_handler_count,NULL);
++  handler_count=0;
++#ifdef __NT__
++  if (hPipe != INVALID_HANDLE_VALUE)
++  {
++    handler_count++;
++    if (pthread_create(&hThread,&connection_attrib,
++		       handle_connections_namedpipes, 0))
++    {
++      sql_print_warning("Can't create thread to handle named pipes");
++      handler_count--;
++    }
++  }
++#endif /* __NT__ */
++  if (have_tcpip && !opt_disable_networking)
++  {
++    handler_count++;
++    if (pthread_create(&hThread,&connection_attrib,
++		       handle_connections_sockets, 0))
++    {
++      sql_print_warning("Can't create thread to handle TCP/IP");
++      handler_count--;
++    }
++  }
++#ifdef HAVE_SMEM
++  if (opt_enable_shared_memory)
++  {
++    handler_count++;
++    if (pthread_create(&hThread,&connection_attrib,
++		       handle_connections_shared_memory, 0))
++    {
++      sql_print_warning("Can't create thread to handle shared memory");
++      handler_count--;
++    }
++  }
++#endif
++
++  while (handler_count > 0)
++    pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
++  pthread_mutex_unlock(&LOCK_thread_count);
++  DBUG_VOID_RETURN;
++}
++
++void decrement_handler_count()
++{
++  pthread_mutex_lock(&LOCK_thread_count);
++  handler_count--;
++  pthread_cond_signal(&COND_handler_count);
++  pthread_mutex_unlock(&LOCK_thread_count);  
++  my_thread_end();
++}
++#else
++#define decrement_handler_count()
++#endif /* defined(__NT__) || defined(HAVE_SMEM) */
++
++
++#ifndef EMBEDDED_LIBRARY
++#ifdef __WIN__
++int win_main(int argc, char **argv)
++#else
++int main(int argc, char **argv)
++#endif
++{
++  MY_INIT(argv[0]);		// init my_sys library & pthreads
++  /* ^^^  Nothing should be before this line! */
++
++  DEBUGGER_OFF;
++
++  /* Set signal used to kill MySQL */
++#if defined(SIGUSR2)
++  thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
++#else
++  thr_kill_signal= SIGINT;
++#endif
++  
++#ifdef _CUSTOMSTARTUPCONFIG_
++  if (_cust_check_startup())
++  {
++    / * _cust_check_startup will report startup failure error * /
++    exit(1);
++  }
++#endif
++
++#ifdef	__WIN__
++  /*
++    Before performing any socket operation (like retrieving hostname
++    in init_common_variables we have to call WSAStartup
++  */
++  {
++    WSADATA WsaData;
++    if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
++    {
++      /* errors are not read yet, so we use english text here */
++      my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0));
++      unireg_abort(1);
++    }
++  }
++#endif /* __WIN__ */
++
++  if (init_common_variables(MYSQL_CONFIG_NAME,
++			    argc, argv, load_default_groups))
++    unireg_abort(1);				// Will do exit
++
++  init_signals();
++  if (!(opt_specialflag & SPECIAL_NO_PRIOR))
++    my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
++#if defined(__ia64__) || defined(__ia64)
++  /*
++    Peculiar things with ia64 platforms - it seems we only have half the
++    stack size in reality, so we have to double it here
++  */
++  pthread_attr_setstacksize(&connection_attrib,thread_stack*2);
++#else
++  pthread_attr_setstacksize(&connection_attrib,thread_stack);
++#endif
++#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
++  {
++    /* Retrieve used stack size;  Needed for checking stack overflows */
++    size_t stack_size= 0;
++    pthread_attr_getstacksize(&connection_attrib, &stack_size);
++#if defined(__ia64__) || defined(__ia64)
++    stack_size/= 2;
++#endif
++    /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
++    if (stack_size && stack_size < thread_stack)
++    {
++      if (global_system_variables.log_warnings)
++	sql_print_warning("Asked for %lu thread stack, but got %ld",
++			  thread_stack, (long) stack_size);
++#if defined(__ia64__) || defined(__ia64)
++      thread_stack= stack_size*2;
++#else
++      thread_stack= stack_size;
++#endif
++    }
++  }
++#endif
++#ifdef __NETWARE__
++  /* Increasing stacksize of threads on NetWare */
++
++  pthread_attr_setstacksize(&connection_attrib, NW_THD_STACKSIZE);
++#endif
++
++  (void) thr_setconcurrency(concurrency);	// 10 by default
++
++  select_thread=pthread_self();
++  select_thread_in_use=1;
++  init_ssl();
++
++#ifdef HAVE_LIBWRAP
++  libwrapName= my_progname+dirname_length(my_progname);
++  openlog(libwrapName, LOG_PID, LOG_AUTH);
++#endif
++
++  /*
++    We have enough space for fiddling with the argv, continue
++  */
++  check_data_home(mysql_real_data_home);
++  if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
++  {
++    unireg_abort(1);				/* purecov: inspected */
++  }
++  mysql_data_home= mysql_data_home_buff;
++  mysql_data_home[0]=FN_CURLIB;		// all paths are relative from here
++  mysql_data_home[1]=0;
++
++  if ((user_info= check_user(mysqld_user)))
++  {
++#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
++    if (locked_in_memory) // getuid() == 0 here
++      set_effective_user(user_info);
++    else
++#endif
++      set_user(mysqld_user, user_info);
++  }
++
++
++  if (opt_bin_log && !server_id)
++  {
++    server_id= !master_host ? 1 : 2;
++#ifdef EXTRA_DEBUG
++    switch (server_id) {
++    case 1:
++      sql_print_warning("\
++You have enabled the binary log, but you haven't set server-id to \
++a non-zero value: we force server id to 1; updates will be logged to the \
++binary log, but connections from slaves will not be accepted.");
++      break;
++    case 2:
++      sql_print_warning("\
++You should set server-id to a non-0 value if master_host is set; \
++we force server id to 2, but this MySQL server will not act as a slave.");
++      break;
++    }
++#endif
++  }
++
++  if (init_server_components())
++    exit(1);
++
++  network_init();
++
++#ifdef __WIN__
++  if (!opt_console)
++  {
++    freopen(log_error_file,"a+",stdout);
++    freopen(log_error_file,"a+",stderr);
++    FreeConsole();				// Remove window
++  }
++  else
++  {
++    /* Don't show error dialog box when on foreground: it stops the server */ 
++    SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
++  }
++#endif
++
++  /*
++   Initialize my_str_malloc() and my_str_free()
++  */
++  my_str_malloc= &my_str_malloc_mysqld;
++  my_str_free= &my_str_free_mysqld;
++
++  /*
++    init signals & alarm
++    After this we can't quit by a simple unireg_abort
++  */
++  error_handler_hook= my_message_sql;
++  start_signal_handler();				// Creates pidfile
++  if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||
++      my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
++  {
++    abort_loop=1;
++    select_thread_in_use=0;
++#ifndef __NETWARE__
++    (void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
++#endif /* __NETWARE__ */
++
++    if (!opt_bootstrap)
++      (void) my_delete(pidfile_name,MYF(MY_WME));	// Not needed anymore
++
++    if (unix_sock != INVALID_SOCKET)
++      unlink(mysqld_unix_port);
++    exit(1);
++  }
++  if (!opt_noacl)
++    (void) grant_init();
++
++#ifdef HAVE_DLOPEN
++  if (!opt_noacl)
++    udf_init();
++#endif
++  if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
++    opt_skip_slave_start= 1;
++  /*
++    init_slave() must be called after the thread keys are created.
++    Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other
++    places) assume that active_mi != 0, so let's fail if it's 0 (out of
++    memory); a message has already been printed.
++  */
++  if (init_slave() && !active_mi)
++  {
++    end_thr_alarm(1);				// Don't allow alarms
++    unireg_abort(1);
++  }
++
++  if (opt_bootstrap)
++  {
++    select_thread_in_use= 0;                    // Allow 'kill' to work
++    bootstrap(stdin);
++    end_thr_alarm(1);				// Don't allow alarms
++    unireg_abort(bootstrap_error ? 1 : 0);
++  }
++  if (opt_init_file)
++  {
++    if (read_init_file(opt_init_file))
++    {
++      end_thr_alarm(1);				// Don't allow alarms
++      unireg_abort(1);
++    }
++  }
++
++  create_shutdown_thread();
++  create_maintenance_thread();
++
++  sql_print_information(ER(ER_STARTUP),my_progname,server_version,
++                        ((unix_sock == INVALID_SOCKET) ? (char*) ""
++                                                       : mysqld_unix_port),
++                         mysqld_port,
++                         MYSQL_COMPILATION_COMMENT);
++
++#if defined(__NT__) || defined(HAVE_SMEM)
++  handle_connections_methods();
++#else
++#ifdef __WIN__
++  if (!have_tcpip || opt_disable_networking)
++  {
++    sql_print_error("TCP/IP unavailable or disabled with --skip-networking; no available interfaces");
++    unireg_abort(1);
++  }
++#endif
++  handle_connections_sockets(0);
++#endif /* __NT__ */
++
++  /* (void) pthread_attr_destroy(&connection_attrib); */
++
++  DBUG_PRINT("quit",("Exiting main thread"));
++
++#ifndef __WIN__
++#ifdef EXTRA_DEBUG2
++  sql_print_error("Before Lock_thread_count");
++#endif
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++  DBUG_PRINT("quit", ("Got thread_count mutex"));
++  select_thread_in_use=0;			// For close_connections
++  (void) pthread_mutex_unlock(&LOCK_thread_count);
++  (void) pthread_cond_broadcast(&COND_thread_count);
++#ifdef EXTRA_DEBUG2
++  sql_print_error("After lock_thread_count");
++#endif
++#endif /* __WIN__ */
++
++  /* Wait until cleanup is done */
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++  while (!ready_to_exit)
++    pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
++  (void) pthread_mutex_unlock(&LOCK_thread_count);
++
++#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
++  if (Service.IsNT() && start_mode)
++    Service.Stop();
++  else
++  {
++    Service.SetShutdownEvent(0);
++    if (hEventShutdown)
++      CloseHandle(hEventShutdown);
++  }
++#endif
++  wait_for_signal_thread_to_end();
++  clean_up_mutexes();
++  my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
++
++  exit(0);
++  return(0);					/* purecov: deadcode */
++}
++
++#endif /* EMBEDDED_LIBRARY */
++
++
++/****************************************************************************
++  Main and thread entry function for Win32
++  (all this is needed only to run mysqld as a service on WinNT)
++****************************************************************************/
++
++#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
++int mysql_service(void *p)
++{
++  if (use_opt_args)
++    win_main(opt_argc, opt_argv);
++  else
++    win_main(Service.my_argc, Service.my_argv);
++  return 0;
++}
++
++
++/* Quote string if it contains space, else copy */
++
++static char *add_quoted_string(char *to, const char *from, char *to_end)
++{
++  uint length= (uint) (to_end-to);
++
++  if (!strchr(from, ' '))
++    return strnmov(to, from, length);
++  return strxnmov(to, length, "\"", from, "\"", NullS);
++}
++
++
++/*
++  Handle basic handling of services, like installation and removal
++
++  SYNOPSIS
++    default_service_handling()
++    argv		Pointer to argument list
++    servicename		Internal name of service
++    displayname		Display name of service (in taskbar ?)
++    file_path		Path to this program
++    startup_option	Startup option to mysqld
++
++  RETURN VALUES
++    0		option handled
++    1		Could not handle option
++ */
++
++static bool
++default_service_handling(char **argv,
++			 const char *servicename,
++			 const char *displayname,
++			 const char *file_path,
++			 const char *extra_opt,
++			 const char *account_name)
++{
++  char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
++  end= path_and_service + sizeof(path_and_service)-3;
++
++  /* We have to quote filename if it contains spaces */
++  pos= add_quoted_string(path_and_service, file_path, end);
++  if (*extra_opt)
++  {
++    /* Add (possible quoted) option after file_path */
++    *pos++= ' ';
++    pos= add_quoted_string(pos, extra_opt, end);
++  }
++  /* We must have servicename last */
++  *pos++= ' ';
++  (void) add_quoted_string(pos, servicename, end);
++
++  if (Service.got_service_option(argv, "install"))
++  {
++    Service.Install(1, servicename, displayname, path_and_service,
++                    account_name);
++    return 0;
++  }
++  if (Service.got_service_option(argv, "install-manual"))
++  {
++    Service.Install(0, servicename, displayname, path_and_service,
++                    account_name);
++    return 0;
++  }
++  if (Service.got_service_option(argv, "remove"))
++  {
++    Service.Remove(servicename);
++    return 0;
++  }
++  return 1;
++}
++
++
++int main(int argc, char **argv)
++{
++
++  /*
++    When several instances are running on the same machine, we
++    need to have an  unique  named  hEventShudown  through the
++    application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
++  */
++  int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
++                                                  "MySQLShutdown"), 10);
++
++  /* Must be initialized early for comparison of service name */
++  system_charset_info= &my_charset_utf8_general_ci;
++
++  if (Service.GetOS())	/* true NT family */
++  {
++    char file_path[FN_REFLEN];
++    my_path(file_path, argv[0], "");		      /* Find name in path */
++    fn_format(file_path,argv[0],file_path,"",
++	      MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
++
++    if (argc == 2)
++    {
++      if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
++				   file_path, "", NULL))
++	return 0;
++      if (Service.IsService(argv[1]))        /* Start an optional service */
++      {
++	/*
++	  Only add the service name to the groups read from the config file
++	  if it's not "MySQL". (The default service name should be 'mysqld'
++	  but we started a bad tradition by calling it MySQL from the start
++	  and we are now stuck with it.
++	*/
++	if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
++	  load_default_groups[load_default_groups_sz-2]= argv[1];
++        start_mode= 1;
++        Service.Init(argv[1], mysql_service);
++        return 0;
++      }
++    }
++    else if (argc == 3) /* install or remove any optional service */
++    {
++      if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
++                                    NULL))
++	return 0;
++      if (Service.IsService(argv[2]))
++      {
++	/*
++	  mysqld was started as
++	  mysqld --defaults-file=my_path\my.ini service-name
++	*/
++	use_opt_args=1;
++	opt_argc= 2;				// Skip service-name
++	opt_argv=argv;
++	start_mode= 1;
++	if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
++	  load_default_groups[load_default_groups_sz-2]= argv[2];
++	Service.Init(argv[2], mysql_service);
++	return 0;
++      }
++    }
++    else if (argc == 4 || argc == 5)
++    {
++      /*
++        This may seem strange, because we handle --local-service while
++        preserving 4.1's behavior of allowing any one other argument that is
++        passed to the service on startup. (The assumption is that this is
++        --defaults-file=file, but that was not enforced in 4.1, so we don't
++        enforce it here.)
++      */
++      const char *extra_opt= NullS;
++      const char *account_name = NullS;
++      int index;
++      for (index = 3; index < argc; index++)
++      {
++        if (!strcmp(argv[index], "--local-service"))
++          account_name= "NT AUTHORITY\\LocalService";
++        else
++          extra_opt= argv[index];
++      }
++
++      if (argc == 4 || account_name)
++        if (!default_service_handling(argv, argv[2], argv[2], file_path,
++                                      extra_opt, account_name))
++          return 0;
++    }
++    else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
++    {
++      /* start the default service */
++      start_mode= 1;
++      Service.Init(MYSQL_SERVICENAME, mysql_service);
++      return 0;
++    }
++  }
++  /* Start as standalone server */
++  Service.my_argc=argc;
++  Service.my_argv=argv;
++  mysql_service(NULL);
++  return 0;
++}
++#endif
++
++
++/*
++  Execute all commands from a file. Used by the mysql_install_db script to
++  create MySQL privilege tables without having to start a full MySQL server.
++*/
++
++static void bootstrap(FILE *file)
++{
++  DBUG_ENTER("bootstrap");
++
++  THD *thd= new THD;
++  thd->bootstrap=1;
++  my_net_init(&thd->net,(st_vio*) 0);
++  thd->max_client_packet_length= thd->net.max_packet;
++  thd->security_ctx->master_access= ~(ulong)0;
++  thd->thread_id=thread_id++;
++  thread_count++;
++
++  bootstrap_file=file;
++#ifndef EMBEDDED_LIBRARY			// TODO:  Enable this
++  if (pthread_create(&thd->real_id,&connection_attrib,handle_bootstrap,
++		     (void*) thd))
++  {
++    sql_print_warning("Can't create thread to handle bootstrap");
++    bootstrap_error=-1;
++    DBUG_VOID_RETURN;
++  }
++  /* Wait for thread to die */
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++  while (thread_count)
++  {
++    (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
++    DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
++  }
++  (void) pthread_mutex_unlock(&LOCK_thread_count);
++#else
++  thd->mysql= 0;
++  handle_bootstrap((void *)thd);
++#endif
++
++  DBUG_VOID_RETURN;
++}
++
++
++static bool read_init_file(char *file_name)
++{
++  FILE *file;
++  DBUG_ENTER("read_init_file");
++  DBUG_PRINT("enter",("name: %s",file_name));
++  if (!(file=my_fopen(file_name,O_RDONLY,MYF(MY_WME))))
++    return(1);
++  bootstrap(file);
++  (void) my_fclose(file,MYF(MY_WME));
++  return 0;
++}
++
++
++#ifndef EMBEDDED_LIBRARY
++/*
++  Create new thread to handle incoming connection.
++
++  SYNOPSIS
++    create_new_thread()
++      thd in/out    Thread handle of future thread.
++
++  DESCRIPTION
++    This function will create new thread to handle the incoming
++    connection.  If there are idle cached threads one will be used.
++    'thd' will be pushed into 'threads'.
++
++    In single-threaded mode (#define ONE_THREAD) connection will be
++    handled inside this function.
++
++  RETURN VALUE
++    none
++*/
++
++static void create_new_thread(THD *thd)
++{
++  NET *net=&thd->net;
++  DBUG_ENTER("create_new_thread");
++
++  if (protocol_version > 9)
++    net->return_errno=1;
++
++  /* don't allow too many connections */
++  if (thread_count - delayed_insert_threads >= max_connections+1 || abort_loop)
++  {
++    DBUG_PRINT("error",("Too many connections"));
++    close_connection(thd, ER_CON_COUNT_ERROR, 1);
++    delete thd;
++    DBUG_VOID_RETURN;
++  }
++  pthread_mutex_lock(&LOCK_thread_count);
++  thd->thread_id=thread_id++;
++
++  thd->real_id=pthread_self();			// Keep purify happy
++
++  /* Start a new thread to handle connection */
++  thread_count++;
++
++#ifdef ONE_THREAD
++  if (test_flags & TEST_NO_THREADS)		// For debugging under Linux
++  {
++    thread_cache_size=0;			// Safety
++    threads.append(thd);
++    thd->real_id=pthread_self();
++    (void) pthread_mutex_unlock(&LOCK_thread_count);
++    handle_one_connection((void*) thd);
++  }
++  else
++#endif
++  {
++    if (thread_count-delayed_insert_threads > max_used_connections)
++      max_used_connections=thread_count-delayed_insert_threads;
++
++    if (cached_thread_count > wake_thread)
++    {
++      thread_cache.append(thd);
++      wake_thread++;
++      pthread_cond_signal(&COND_thread_cache);
++    }
++    else
++    {
++      int error;
++      thread_created++;
++      threads.append(thd);
++      DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
++      thd->connect_time = time(NULL);
++      if ((error=pthread_create(&thd->real_id,&connection_attrib,
++				handle_one_connection,
++				(void*) thd)))
++      {
++	DBUG_PRINT("error",
++		   ("Can't create thread to handle request (error %d)",
++		    error));
++	thread_count--;
++	thd->killed= THD::KILL_CONNECTION;			// Safety
++	(void) pthread_mutex_unlock(&LOCK_thread_count);
++	statistic_increment(aborted_connects,&LOCK_status);
++	net_printf_error(thd, ER_CANT_CREATE_THREAD, error);
++	(void) pthread_mutex_lock(&LOCK_thread_count);
++	close_connection(thd,0,0);
++	delete thd;
++	(void) pthread_mutex_unlock(&LOCK_thread_count);
++	DBUG_VOID_RETURN;
++      }
++    }
++    (void) pthread_mutex_unlock(&LOCK_thread_count);
++
++  }
++  DBUG_PRINT("info",("Thread created"));
++  DBUG_VOID_RETURN;
++}
++#endif /* EMBEDDED_LIBRARY */
++
++
++#ifdef SIGNALS_DONT_BREAK_READ
++inline void kill_broken_server()
++{
++  /* hack to get around signals ignored in syscalls for problem OS's */
++  if (
++#if !defined(__NETWARE__)
++      unix_sock == INVALID_SOCKET ||
++#endif
++      (!opt_disable_networking && ip_sock == INVALID_SOCKET))
++  {
++    select_thread_in_use = 0;
++    /* The following call will never return */
++    kill_server(IF_NETWARE(MYSQL_KILL_SIGNAL, (void*) MYSQL_KILL_SIGNAL));
++  }
++}
++#define MAYBE_BROKEN_SYSCALL kill_broken_server();
++#else
++#define MAYBE_BROKEN_SYSCALL
++#endif
++
++	/* Handle new connections and spawn new process to handle them */
++
++#ifndef EMBEDDED_LIBRARY
++pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
++{
++  my_socket sock,new_sock;
++  uint error_count=0;
++  uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1);
++  fd_set readFDs,clientFDs;
++  THD *thd;
++  struct sockaddr_in cAddr;
++  int ip_flags=0,socket_flags=0,flags;
++  st_vio *vio_tmp;
++  DBUG_ENTER("handle_connections_sockets");
++
++  LINT_INIT(new_sock);
++
++  (void) my_pthread_getprio(pthread_self());		// For debugging
++
++  FD_ZERO(&clientFDs);
++  if (ip_sock != INVALID_SOCKET)
++  {
++    FD_SET(ip_sock,&clientFDs);
++#ifdef HAVE_FCNTL
++    ip_flags = fcntl(ip_sock, F_GETFL, 0);
++#endif
++  }
++#ifdef HAVE_SYS_UN_H
++  FD_SET(unix_sock,&clientFDs);
++#ifdef HAVE_FCNTL
++  socket_flags=fcntl(unix_sock, F_GETFL, 0);
++#endif
++#endif
++
++  DBUG_PRINT("general",("Waiting for connections."));
++  MAYBE_BROKEN_SYSCALL;
++  while (!abort_loop)
++  {
++    readFDs=clientFDs;
++#ifdef HPUX10
++    if (select(max_used_connection,(int*) &readFDs,0,0,0) < 0)
++      continue;
++#else
++    if (select((int) max_used_connection,&readFDs,0,0,0) < 0)
++    {
++      if (socket_errno != SOCKET_EINTR)
++      {
++	if (!select_errors++ && !abort_loop)	/* purecov: inspected */
++	  sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
++      }
++      MAYBE_BROKEN_SYSCALL
++      continue;
++    }
++#endif	/* HPUX10 */
++    if (abort_loop)
++    {
++      MAYBE_BROKEN_SYSCALL;
++      break;
++    }
++
++    /* Is this a new connection request ? */
++#ifdef HAVE_SYS_UN_H
++    if (FD_ISSET(unix_sock,&readFDs))
++    {
++      sock = unix_sock;
++      flags= socket_flags;
++    }
++    else
++#endif
++    {
++      sock = ip_sock;
++      flags= ip_flags;
++    }
++
++#if !defined(NO_FCNTL_NONBLOCK)
++    if (!(test_flags & TEST_BLOCKING))
++    {
++#if defined(O_NONBLOCK)
++      fcntl(sock, F_SETFL, flags | O_NONBLOCK);
++#elif defined(O_NDELAY)
++      fcntl(sock, F_SETFL, flags | O_NDELAY);
++#endif
++    }
++#endif /* NO_FCNTL_NONBLOCK */
++    for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
++    {
++      size_socket length=sizeof(struct sockaddr_in);
++      new_sock = accept(sock, my_reinterpret_cast(struct sockaddr *) (&cAddr),
++			&length);
++#ifdef __NETWARE__
++      // TODO: temporary fix, waiting for TCP/IP fix - DEFECT000303149
++      if ((new_sock == INVALID_SOCKET) && (socket_errno == EINVAL))
++      {
++        kill_server(SIGTERM);
++      }
++#endif
++      if (new_sock != INVALID_SOCKET ||
++	  (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
++	break;
++      MAYBE_BROKEN_SYSCALL;
++#if !defined(NO_FCNTL_NONBLOCK)
++      if (!(test_flags & TEST_BLOCKING))
++      {
++	if (retry == MAX_ACCEPT_RETRY - 1)
++	  fcntl(sock, F_SETFL, flags);		// Try without O_NONBLOCK
++      }
++#endif
++    }
++#if !defined(NO_FCNTL_NONBLOCK)
++    if (!(test_flags & TEST_BLOCKING))
++      fcntl(sock, F_SETFL, flags);
++#endif
++    if (new_sock == INVALID_SOCKET)
++    {
++      if ((error_count++ & 255) == 0)		// This can happen often
++	sql_perror("Error in accept");
++      MAYBE_BROKEN_SYSCALL;
++      if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
++	sleep(1);				// Give other threads some time
++      continue;
++    }
++
++#ifdef HAVE_LIBWRAP
++    {
++      if (sock == ip_sock)
++      {
++	struct request_info req;
++	signal(SIGCHLD, SIG_DFL);
++	request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL);
++	my_fromhost(&req);
++	if (!my_hosts_access(&req))
++	{
++	  /*
++	    This may be stupid but refuse() includes an exit(0)
++	    which we surely don't want...
++	    clean_exit() - same stupid thing ...
++	  */
++	  syslog(deny_severity, "refused connect from %s",
++		 my_eval_client(&req));
++
++	  /*
++	    C++ sucks (the gibberish in front just translates the supplied
++	    sink function pointer in the req structure from a void (*sink)();
++	    to a void(*sink)(int) if you omit the cast, the C++ compiler
++	    will cry...
++	  */
++	  if (req.sink)
++	    ((void (*)(int))req.sink)(req.fd);
++
++	  (void) shutdown(new_sock, SHUT_RDWR);
++	  (void) closesocket(new_sock);
++	  continue;
++	}
++      }
++    }
++#endif /* HAVE_LIBWRAP */
++
++    {
++      size_socket dummyLen;
++      struct sockaddr dummy;
++      dummyLen = sizeof(struct sockaddr);
++      if (getsockname(new_sock,&dummy, &dummyLen) < 0)
++      {
++	sql_perror("Error on new connection socket");
++	(void) shutdown(new_sock, SHUT_RDWR);
++	(void) closesocket(new_sock);
++	continue;
++      }
++    }
++
++    /*
++    ** Don't allow too many connections
++    */
++
++    if (!(thd= new THD))
++    {
++      (void) shutdown(new_sock, SHUT_RDWR);
++      VOID(closesocket(new_sock));
++      continue;
++    }
++    if (!(vio_tmp=vio_new(new_sock,
++			  sock == unix_sock ? VIO_TYPE_SOCKET :
++			  VIO_TYPE_TCPIP,
++			  sock == unix_sock ? VIO_LOCALHOST: 0)) ||
++	my_net_init(&thd->net,vio_tmp))
++    {
++      if (vio_tmp)
++	vio_delete(vio_tmp);
++      else
++      {
++	(void) shutdown(new_sock, SHUT_RDWR);
++	(void) closesocket(new_sock);
++      }
++      delete thd;
++      continue;
++    }
++    if (sock == unix_sock)
++      thd->security_ctx->host=(char*) my_localhost;
++
++    create_new_thread(thd);
++  }
++
++#ifdef OS2
++  // kill server must be invoked from thread 1!
++  kill_server(MYSQL_KILL_SIGNAL);
++#endif
++  decrement_handler_count();
++  DBUG_RETURN(0);
++}
++
++
++#ifdef __NT__
++pthread_handler_t handle_connections_namedpipes(void *arg)
++{
++  HANDLE hConnectedPipe;
++  BOOL fConnected;
++  THD *thd;
++  my_thread_init();
++  DBUG_ENTER("handle_connections_namedpipes");
++  (void) my_pthread_getprio(pthread_self());		// For debugging
++
++  DBUG_PRINT("general",("Waiting for named pipe connections."));
++  while (!abort_loop)
++  {
++    /* wait for named pipe connection */
++    fConnected = ConnectNamedPipe(hPipe, NULL);
++    if (abort_loop)
++      break;
++    if (!fConnected)
++      fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
++    if (!fConnected)
++    {
++      CloseHandle(hPipe);
++      if ((hPipe= CreateNamedPipe(pipe_name,
++                                  PIPE_ACCESS_DUPLEX,
++                                  PIPE_TYPE_BYTE |
++                                  PIPE_READMODE_BYTE |
++                                  PIPE_WAIT,
++                                  PIPE_UNLIMITED_INSTANCES,
++                                  (int) global_system_variables.
++                                  net_buffer_length,
++                                  (int) global_system_variables.
++                                  net_buffer_length,
++                                  NMPWAIT_USE_DEFAULT_WAIT,
++                                  &saPipeSecurity)) ==
++	  INVALID_HANDLE_VALUE)
++      {
++	sql_perror("Can't create new named pipe!");
++	break;					// Abort
++      }
++    }
++    hConnectedPipe = hPipe;
++    /* create new pipe for new connection */
++    if ((hPipe = CreateNamedPipe(pipe_name,
++				 PIPE_ACCESS_DUPLEX,
++				 PIPE_TYPE_BYTE |
++				 PIPE_READMODE_BYTE |
++				 PIPE_WAIT,
++				 PIPE_UNLIMITED_INSTANCES,
++				 (int) global_system_variables.net_buffer_length,
++				 (int) global_system_variables.net_buffer_length,
++				 NMPWAIT_USE_DEFAULT_WAIT,
++				 &saPipeSecurity)) ==
++	INVALID_HANDLE_VALUE)
++    {
++      sql_perror("Can't create new named pipe!");
++      hPipe=hConnectedPipe;
++      continue;					// We have to try again
++    }
++
++    if (!(thd = new THD))
++    {
++      DisconnectNamedPipe(hConnectedPipe);
++      CloseHandle(hConnectedPipe);
++      continue;
++    }
++    if (!(thd->net.vio = vio_new_win32pipe(hConnectedPipe)) ||
++	my_net_init(&thd->net, thd->net.vio))
++    {
++      close_connection(thd, ER_OUT_OF_RESOURCES, 1);
++      delete thd;
++      continue;
++    }
++    /* Host is unknown */
++    thd->security_ctx->host= my_strdup(my_localhost, MYF(0));
++    create_new_thread(thd);
++  }
++
++  decrement_handler_count();
++  DBUG_RETURN(0);
++}
++#endif /* __NT__ */
++
++
++/*
++  Thread of shared memory's service
++
++  SYNOPSIS
++    handle_connections_shared_memory()
++    arg                              Arguments of thread
++*/
++
++#ifdef HAVE_SMEM
++pthread_handler_t handle_connections_shared_memory(void *arg)
++{
++  /* file-mapping object, use for create shared memory */
++  HANDLE handle_connect_file_map= 0;
++  char  *handle_connect_map= 0;                 // pointer on shared memory
++  HANDLE event_connect_answer= 0;
++  ulong smem_buffer_length= shared_memory_buffer_length + 4;
++  ulong connect_number= 1;
++  char *tmp= NULL;
++  char *suffix_pos;
++  char connect_number_char[22], *p;
++  const char *errmsg= 0;
++  SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0;
++  my_thread_init();
++  DBUG_ENTER("handle_connections_shared_memorys");
++  DBUG_PRINT("general",("Waiting for allocated shared memory."));
++
++  /*
++     get enough space base-name + '_' + longest suffix we might ever send
++   */
++  if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE))))
++    goto error;
++
++  if (my_security_attr_create(&sa_event, &errmsg,
++                              GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE))
++    goto error;
++
++  if (my_security_attr_create(&sa_mapping, &errmsg,
++                             GENERIC_ALL, FILE_MAP_READ | FILE_MAP_WRITE))
++    goto error;
++
++  /*
++    The name of event and file-mapping events create agree next rule:
++      shared_memory_base_name+unique_part
++    Where:
++      shared_memory_base_name is unique value for each server
++      unique_part is unique value for each object (events and file-mapping)
++  */
++  suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
++  strmov(suffix_pos, "CONNECT_REQUEST");
++  if ((smem_event_connect_request= CreateEvent(sa_event,
++                                               FALSE, FALSE, tmp)) == 0)
++  {
++    errmsg= "Could not create request event";
++    goto error;
++  }
++  strmov(suffix_pos, "CONNECT_ANSWER");
++  if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
++  {
++    errmsg="Could not create answer event";
++    goto error;
++  }
++  strmov(suffix_pos, "CONNECT_DATA");
++  if ((handle_connect_file_map=
++       CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
++                         PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0)
++  {
++    errmsg= "Could not create file mapping";
++    goto error;
++  }
++  if ((handle_connect_map= (char *)MapViewOfFile(handle_connect_file_map,
++						  FILE_MAP_WRITE,0,0,
++						  sizeof(DWORD))) == 0)
++  {
++    errmsg= "Could not create shared memory service";
++    goto error;
++  }
++
++  while (!abort_loop)
++  {
++    /* Wait a request from client */
++    WaitForSingleObject(smem_event_connect_request,INFINITE);
++
++    /*
++       it can be after shutdown command
++    */
++    if (abort_loop)
++      goto error;
++
++    HANDLE handle_client_file_map= 0;
++    char  *handle_client_map= 0;
++    HANDLE event_client_wrote= 0;
++    HANDLE event_client_read= 0;    // for transfer data server <-> client
++    HANDLE event_server_wrote= 0;
++    HANDLE event_server_read= 0;
++    HANDLE event_conn_closed= 0;
++    THD *thd= 0;
++
++    p= int10_to_str(connect_number, connect_number_char, 10);
++    /*
++      The name of event and file-mapping events create agree next rule:
++        shared_memory_base_name+unique_part+number_of_connection
++        Where:
++	  shared_memory_base_name is uniquel value for each server
++	  unique_part is unique value for each object (events and file-mapping)
++	  number_of_connection is connection-number between server and client
++    */
++    suffix_pos= strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
++			 "_",NullS);
++    strmov(suffix_pos, "DATA");
++    if ((handle_client_file_map=
++         CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
++                           PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0)
++    {
++      errmsg= "Could not create file mapping";
++      goto errorconn;
++    }
++    if ((handle_client_map= (char*)MapViewOfFile(handle_client_file_map,
++						  FILE_MAP_WRITE,0,0,
++						  smem_buffer_length)) == 0)
++    {
++      errmsg= "Could not create memory map";
++      goto errorconn;
++    }
++    strmov(suffix_pos, "CLIENT_WROTE");
++    if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
++    {
++      errmsg= "Could not create client write event";
++      goto errorconn;
++    }
++    strmov(suffix_pos, "CLIENT_READ");
++    if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
++    {
++      errmsg= "Could not create client read event";
++      goto errorconn;
++    }
++    strmov(suffix_pos, "SERVER_READ");
++    if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
++    {
++      errmsg= "Could not create server read event";
++      goto errorconn;
++    }
++    strmov(suffix_pos, "SERVER_WROTE");
++    if ((event_server_wrote= CreateEvent(sa_event,
++                                         FALSE, FALSE, tmp)) == 0)
++    {
++      errmsg= "Could not create server write event";
++      goto errorconn;
++    }
++    strmov(suffix_pos, "CONNECTION_CLOSED");
++    if ((event_conn_closed= CreateEvent(sa_event,
++                                        TRUE, FALSE, tmp)) == 0)
++    {
++      errmsg= "Could not create closed connection event";
++      goto errorconn;
++    }
++    if (abort_loop)
++      goto errorconn;
++    if (!(thd= new THD))
++      goto errorconn;
++    /* Send number of connection to client */
++    int4store(handle_connect_map, connect_number);
++    if (!SetEvent(event_connect_answer))
++    {
++      errmsg= "Could not send answer event";
++      goto errorconn;
++    }
++    /* Set event that client should receive data */
++    if (!SetEvent(event_client_read))
++    {
++      errmsg= "Could not set client to read mode";
++      goto errorconn;
++    }
++    if (!(thd->net.vio= vio_new_win32shared_memory(&thd->net,
++                                                   handle_client_file_map,
++                                                   handle_client_map,
++                                                   event_client_wrote,
++                                                   event_client_read,
++                                                   event_server_wrote,
++                                                   event_server_read,
++                                                   event_conn_closed)) ||
++                        my_net_init(&thd->net, thd->net.vio))
++    {
++      close_connection(thd, ER_OUT_OF_RESOURCES, 1);
++      errmsg= 0;
++      goto errorconn;
++    }
++    thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */
++    create_new_thread(thd);
++    connect_number++;
++    continue;
++
++errorconn:
++    /* Could not form connection;  Free used handlers/memort and retry */
++    if (errmsg)
++    {
++      char buff[180];
++      strxmov(buff, "Can't create shared memory connection: ", errmsg, ".",
++	      NullS);
++      sql_perror(buff);
++    }
++    if (handle_client_file_map)
++      CloseHandle(handle_client_file_map);
++    if (handle_client_map)
++      UnmapViewOfFile(handle_client_map);
++    if (event_server_wrote)
++      CloseHandle(event_server_wrote);
++    if (event_server_read)
++      CloseHandle(event_server_read);
++    if (event_client_wrote)
++      CloseHandle(event_client_wrote);
++    if (event_client_read)
++      CloseHandle(event_client_read);
++    if (event_conn_closed)
++      CloseHandle(event_conn_closed);
++    delete thd;
++  }
++
++  /* End shared memory handling */
++error:
++  if (tmp)
++    my_free(tmp, MYF(0));
++
++  if (errmsg)
++  {
++    char buff[180];
++    strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS);
++    sql_perror(buff);
++  }
++  my_security_attr_free(sa_event);
++  my_security_attr_free(sa_mapping);
++  if (handle_connect_map)	UnmapViewOfFile(handle_connect_map);
++  if (handle_connect_file_map)	CloseHandle(handle_connect_file_map);
++  if (event_connect_answer)	CloseHandle(event_connect_answer);
++  if (smem_event_connect_request) CloseHandle(smem_event_connect_request);
++
++  decrement_handler_count();
++  DBUG_RETURN(0);
++}
++#endif /* HAVE_SMEM */
++#endif /* EMBEDDED_LIBRARY */
++
++
++/****************************************************************************
++  Handle start options
++******************************************************************************/
++
++enum options_mysqld
++{
++  OPT_ISAM_LOG=256,            OPT_SKIP_NEW,
++  OPT_SKIP_GRANT,              OPT_SKIP_LOCK,
++  OPT_ENABLE_LOCK,             OPT_USE_LOCKING,
++  OPT_SOCKET,                  OPT_UPDATE_LOG,
++  OPT_BIN_LOG,                 OPT_SKIP_RESOLVE,
++  OPT_SKIP_NETWORKING,         OPT_BIN_LOG_INDEX,
++  OPT_BIND_ADDRESS,            OPT_PID_FILE,
++  OPT_SKIP_PRIOR,              OPT_BIG_TABLES,
++  OPT_STANDALONE,              OPT_ONE_THREAD,
++  OPT_CONSOLE,                 OPT_LOW_PRIORITY_UPDATES,
++  OPT_SKIP_HOST_CACHE,         OPT_SHORT_LOG_FORMAT,
++  OPT_FLUSH,                   OPT_SAFE,
++  OPT_BOOTSTRAP,               OPT_SKIP_SHOW_DB,
++  OPT_STORAGE_ENGINE,          OPT_INIT_FILE,
++  OPT_DELAY_KEY_WRITE_ALL,     OPT_SLOW_QUERY_LOG,
++  OPT_DELAY_KEY_WRITE,	       OPT_CHARSETS_DIR,
++  OPT_BDB_HOME,                OPT_BDB_LOG,
++  OPT_BDB_TMP,                 OPT_BDB_SYNC,
++  OPT_BDB_LOCK,                OPT_BDB,
++  OPT_BDB_NO_RECOVER,	    OPT_BDB_SHARED,
++  OPT_MASTER_HOST,             OPT_MASTER_USER,
++  OPT_MASTER_PASSWORD,         OPT_MASTER_PORT,
++  OPT_MASTER_INFO_FILE,        OPT_MASTER_CONNECT_RETRY,
++  OPT_MASTER_RETRY_COUNT,      OPT_LOG_TC, OPT_LOG_TC_SIZE,
++  OPT_MASTER_SSL,              OPT_MASTER_SSL_KEY,
++  OPT_MASTER_SSL_CERT,         OPT_MASTER_SSL_CAPATH,
++  OPT_MASTER_SSL_CIPHER,       OPT_MASTER_SSL_CA,
++  OPT_SQL_BIN_UPDATE_SAME,     OPT_REPLICATE_DO_DB,
++  OPT_REPLICATE_IGNORE_DB,     OPT_LOG_SLAVE_UPDATES,
++  OPT_BINLOG_DO_DB,            OPT_BINLOG_IGNORE_DB,
++  OPT_WANT_CORE,               OPT_CONCURRENT_INSERT,
++  OPT_MEMLOCK,                 OPT_MYISAM_RECOVER,
++  OPT_REPLICATE_REWRITE_DB,    OPT_SERVER_ID,
++  OPT_SKIP_SLAVE_START,        OPT_SKIP_INNOBASE,
++  OPT_SAFEMALLOC_MEM_LIMIT,    OPT_REPLICATE_DO_TABLE,
++  OPT_REPLICATE_IGNORE_TABLE,  OPT_REPLICATE_WILD_DO_TABLE,
++  OPT_REPLICATE_WILD_IGNORE_TABLE, OPT_REPLICATE_SAME_SERVER_ID,
++  OPT_DISCONNECT_SLAVE_EVENT_COUNT, OPT_TC_HEURISTIC_RECOVER,
++  OPT_ABORT_SLAVE_EVENT_COUNT,
++  OPT_INNODB_DATA_HOME_DIR,
++  OPT_INNODB_DATA_FILE_PATH,
++  OPT_INNODB_LOG_GROUP_HOME_DIR,
++  OPT_INNODB_LOG_ARCH_DIR,
++  OPT_INNODB_LOG_ARCHIVE,
++  OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
++  OPT_INNODB_FLUSH_METHOD,
++  OPT_INNODB_DOUBLEWRITE,
++  OPT_INNODB_CHECKSUMS,
++  OPT_INNODB_FAST_SHUTDOWN,
++  OPT_INNODB_FILE_PER_TABLE, OPT_CRASH_BINLOG_INNODB,
++  OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
++  OPT_LOG_BIN_TRUST_FUNCTION_CREATORS,
++  OPT_SAFE_SHOW_DB, OPT_INNODB_SAFE_BINLOG,
++  OPT_INNODB, OPT_ISAM,
++  OPT_ENGINE_CONDITION_PUSHDOWN, OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, 
++  OPT_NDB_USE_EXACT_COUNT, OPT_NDB_USE_TRANSACTIONS,
++  OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
++  OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION, OPT_NDB_CACHE_CHECK_TIME,
++  OPT_NDB_MGMD, OPT_NDB_NODEID,
++  OPT_SKIP_SAFEMALLOC,
++  OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
++  OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
++  OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
++  OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
++  OPT_HAVE_NAMED_PIPE,
++  OPT_DO_PSTACK, OPT_REPORT_HOST,
++  OPT_REPORT_USER, OPT_REPORT_PASSWORD, OPT_REPORT_PORT,
++  OPT_SHOW_SLAVE_AUTH_INFO,
++  OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE,
++  OPT_RPL_RECOVERY_RANK,OPT_INIT_RPL_ROLE,
++  OPT_RELAY_LOG, OPT_RELAY_LOG_INDEX, OPT_RELAY_LOG_INFO_FILE,
++  OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE, OPT_LOCAL_INFILE,
++  OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA,
++  OPT_SSL_CAPATH, OPT_SSL_CIPHER,
++  OPT_BACK_LOG, OPT_BINLOG_CACHE_SIZE,
++  OPT_CONNECT_TIMEOUT, OPT_DELAYED_INSERT_TIMEOUT,
++  OPT_DELAYED_INSERT_LIMIT, OPT_DELAYED_QUEUE_SIZE,
++  OPT_FLUSH_TIME, OPT_FT_MIN_WORD_LEN, OPT_FT_BOOLEAN_SYNTAX,
++  OPT_FT_MAX_WORD_LEN, OPT_FT_QUERY_EXPANSION_LIMIT, OPT_FT_STOPWORD_FILE,
++  OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE,
++  OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE,
++  OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD,
++  OPT_LONG_QUERY_TIME,
++  OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET,
++  OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
++  OPT_MAX_CONNECTIONS, OPT_MAX_CONNECT_ERRORS,
++  OPT_MAX_DELAYED_THREADS, OPT_MAX_HEP_TABLE_SIZE,
++  OPT_MAX_JOIN_SIZE, OPT_MAX_PREPARED_STMT_COUNT,
++  OPT_MAX_RELAY_LOG_SIZE, OPT_MAX_SORT_LENGTH,
++  OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS,
++  OPT_MAX_LENGTH_FOR_SORT_DATA,
++  OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE,
++  OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
++  OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
++  OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
++  OPT_MYISAM_STATS_METHOD,
++  OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT,
++  OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT,
++  OPT_OPEN_FILES_LIMIT,
++  OPT_PRELOAD_BUFFER_SIZE,
++  OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE,
++  OPT_QUERY_CACHE_TYPE, OPT_QUERY_CACHE_WLOCK_INVALIDATE, OPT_RECORD_BUFFER,
++  OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT, OPT_RELAY_LOG_SPACE_LIMIT,
++  OPT_RELAY_LOG_PURGE,
++  OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
++  OPT_SLAVE_TRANS_RETRIES, OPT_READONLY, OPT_DEBUGGING,
++  OPT_SORT_BUFFER, OPT_TABLE_CACHE,
++  OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE,
++  OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
++  OPT_WAIT_TIMEOUT, OPT_MYISAM_REPAIR_THREADS,
++  OPT_INNODB_MIRRORED_LOG_GROUPS,
++  OPT_INNODB_LOG_FILES_IN_GROUP,
++  OPT_INNODB_LOG_FILE_SIZE,
++  OPT_INNODB_LOG_BUFFER_SIZE,
++  OPT_INNODB_BUFFER_POOL_SIZE,
++  OPT_INNODB_BUFFER_POOL_AWE_MEM_MB,
++  OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
++  OPT_INNODB_MAX_PURGE_LAG,
++  OPT_INNODB_FILE_IO_THREADS,
++  OPT_INNODB_LOCK_WAIT_TIMEOUT,
++  OPT_INNODB_THREAD_CONCURRENCY,
++  OPT_INNODB_COMMIT_CONCURRENCY,
++  OPT_INNODB_FORCE_RECOVERY,
++  OPT_INNODB_STATUS_FILE,
++  OPT_INNODB_MAX_DIRTY_PAGES_PCT,
++  OPT_INNODB_TABLE_LOCKS,
++  OPT_INNODB_SUPPORT_XA,
++  OPT_INNODB_OPEN_FILES,
++  OPT_INNODB_AUTOEXTEND_INCREMENT,
++  OPT_INNODB_SYNC_SPIN_LOOPS,
++  OPT_INNODB_CONCURRENCY_TICKETS,
++  OPT_INNODB_THREAD_SLEEP_DELAY,
++  OPT_BDB_CACHE_SIZE,
++  OPT_BDB_LOG_BUFFER_SIZE,
++  OPT_BDB_MAX_LOCK,
++  OPT_ERROR_LOG_FILE,
++  OPT_DEFAULT_WEEK_FORMAT,
++  OPT_RANGE_ALLOC_BLOCK_SIZE, OPT_ALLOW_SUSPICIOUS_UDFS,
++  OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
++  OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE,
++  OPT_SYNC_FRM, OPT_SYNC_BINLOG,
++  OPT_SYNC_REPLICATION,
++  OPT_SYNC_REPLICATION_SLAVE_ID,
++  OPT_SYNC_REPLICATION_TIMEOUT,
++  OPT_BDB_NOSYNC,
++  OPT_ENABLE_SHARED_MEMORY,
++  OPT_SHARED_MEMORY_BASE_NAME,
++  OPT_OLD_PASSWORDS,
++  OPT_EXPIRE_LOGS_DAYS,
++  OPT_GROUP_CONCAT_MAX_LEN,
++  OPT_DEFAULT_COLLATION,
++  OPT_CHARACTER_SET_CLIENT_HANDSHAKE,
++  OPT_CHARACTER_SET_FILESYSTEM,
++  OPT_LC_TIME_NAMES,
++  OPT_INIT_CONNECT,
++  OPT_INIT_SLAVE,
++  OPT_SECURE_AUTH,
++  OPT_DATE_FORMAT,
++  OPT_TIME_FORMAT,
++  OPT_DATETIME_FORMAT,
++  OPT_LOG_QUERIES_NOT_USING_INDEXES,
++  OPT_DEFAULT_TIME_ZONE,
++  OPT_SYSDATE_IS_NOW,
++  OPT_OPTIMIZER_SEARCH_DEPTH,
++  OPT_OPTIMIZER_PRUNE_LEVEL,
++  OPT_UPDATABLE_VIEWS_WITH_LIMIT,
++  OPT_SP_AUTOMATIC_PRIVILEGES,
++  OPT_MAX_SP_RECURSION_DEPTH,
++  OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
++  OPT_ENABLE_LARGE_PAGES,
++  OPT_TIMED_MUTEXES,
++  OPT_OLD_STYLE_USER_LIMITS,
++  OPT_LOG_SLOW_ADMIN_STATEMENTS,
++  OPT_TABLE_LOCK_WAIT_TIMEOUT,
++  OPT_PORT_OPEN_TIMEOUT,
++  OPT_MERGE,
++  OPT_PROFILING,
++  OPT_INNODB_ROLLBACK_ON_TIMEOUT,
++  OPT_SECURE_FILE_PRIV,
++  OPT_KEEP_FILES_ON_CREATE
++};
++
++
++#define LONG_TIMEOUT ((ulong) 3600L*24L*365L)
++
++struct my_option my_long_options[] =
++{
++  {"help", '?', "Display this help and exit.",
++   (gptr*) &opt_help, (gptr*) &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
++   0, 0},
++#ifdef HAVE_REPLICATION
++  {"abort-slave-event-count", OPT_ABORT_SLAVE_EVENT_COUNT,
++   "Option used by mysql-test for debugging and testing of replication.",
++   (gptr*) &abort_slave_event_count,  (gptr*) &abort_slave_event_count,
++   0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#endif /* HAVE_REPLICATION */
++  {"allow-suspicious-udfs", OPT_ALLOW_SUSPICIOUS_UDFS,
++   "Allows use of UDFs consisting of only one symbol xxx() "
++   "without corresponding xxx_init() or xxx_deinit(). That also means "
++   "that one can load any function from any library, for example exit() "
++   "from libc.so",
++   (gptr*) &opt_allow_suspicious_udfs, (gptr*) &opt_allow_suspicious_udfs,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode will also set transaction isolation level 'serializable'.", 0, 0, 0,
++   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"auto-increment-increment", OPT_AUTO_INCREMENT,
++   "Auto-increment columns are incremented by this",
++   (gptr*) &global_system_variables.auto_increment_increment,
++   (gptr*) &max_system_variables.auto_increment_increment, 0, GET_ULONG,
++   OPT_ARG, 1, 1, 65535, 0, 1, 0 },
++  {"auto-increment-offset", OPT_AUTO_INCREMENT_OFFSET,
++   "Offset added to Auto-increment columns. Used when auto-increment-increment != 1",
++   (gptr*) &global_system_variables.auto_increment_offset,
++   (gptr*) &max_system_variables.auto_increment_offset, 0, GET_ULONG, OPT_ARG,
++   1, 1, 65535, 0, 1, 0 },
++  {"automatic-sp-privileges", OPT_SP_AUTOMATIC_PRIVILEGES,
++   "Creating and dropping stored procedures alters ACLs. Disable with --skip-automatic-sp-privileges.",
++   (gptr*) &sp_automatic_privileges, (gptr*) &sp_automatic_privileges,
++   0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
++  {"basedir", 'b',
++   "Path to installation directory. All paths are usually resolved relative to this.",
++   (gptr*) &mysql_home_ptr, (gptr*) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"bdb", OPT_BDB, "Enable Berkeley DB (if this version of MySQL supports it). \
++Disable with --skip-bdb (will save memory).",
++   (gptr*) &opt_bdb, (gptr*) &opt_bdb, 0, GET_BOOL, NO_ARG, OPT_BDB_DEFAULT, 0, 0,
++   0, 0, 0},
++#ifdef HAVE_BERKELEY_DB
++  {"bdb-home", OPT_BDB_HOME, "Berkeley home directory.", (gptr*) &berkeley_home,
++   (gptr*) &berkeley_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"bdb-lock-detect", OPT_BDB_LOCK,
++   "Berkeley lock detect (DEFAULT, OLDEST, RANDOM or YOUNGEST, # sec).",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"bdb-logdir", OPT_BDB_LOG, "Berkeley DB log file directory.",
++   (gptr*) &berkeley_logdir, (gptr*) &berkeley_logdir, 0, GET_STR,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"bdb-no-recover", OPT_BDB_NO_RECOVER,
++   "Don't try to recover Berkeley DB tables on start.", 0, 0, 0, GET_NO_ARG,
++   NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"bdb-no-sync", OPT_BDB_NOSYNC,
++   "This option is deprecated, use --skip-sync-bdb-logs instead",
++   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"bdb-shared-data", OPT_BDB_SHARED,
++   "Start Berkeley DB in multi-process mode.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
++   0, 0, 0, 0, 0},
++  {"bdb-tmpdir", OPT_BDB_TMP, "Berkeley DB tempfile name.",
++   (gptr*) &berkeley_tmpdir, (gptr*) &berkeley_tmpdir, 0, GET_STR,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#endif /* HAVE_BERKELEY_DB */
++  {"big-tables", OPT_BIG_TABLES,
++   "Allow big result sets by saving all temporary sets on file (Solves most 'table full' errors).",
++   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.",
++   (gptr*) &my_bind_addr_str, (gptr*) &my_bind_addr_str, 0, GET_STR,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"binlog-do-db", OPT_BINLOG_DO_DB,
++   "Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
++   "Tells the master that updates to the given database should not be logged tothe binary log.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#ifndef DISABLE_GRANT_OPTIONS
++  {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
++   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++#endif
++  {"character-set-client-handshake", OPT_CHARACTER_SET_CLIENT_HANDSHAKE,
++   "Don't ignore client side character set value sent during handshake.",
++   (gptr*) &opt_character_set_client_handshake,
++   (gptr*) &opt_character_set_client_handshake,
++    0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
++  {"character-set-filesystem", OPT_CHARACTER_SET_FILESYSTEM,
++   "Set the filesystem character set.",
++   (gptr*) &character_set_filesystem_name,
++   (gptr*) &character_set_filesystem_name,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
++  {"character-set-server", 'C', "Set the default character set.",
++   (gptr*) &default_character_set_name, (gptr*) &default_character_set_name,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
++  {"character-sets-dir", OPT_CHARSETS_DIR,
++   "Directory where character sets are.", (gptr*) &charsets_dir,
++   (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"chroot", 'r', "Chroot mysqld daemon during startup.",
++   (gptr*) &mysqld_chroot, (gptr*) &mysqld_chroot, 0, GET_STR, REQUIRED_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"collation-server", OPT_DEFAULT_COLLATION, "Set the default collation.",
++   (gptr*) &default_collation_name, (gptr*) &default_collation_name,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
++  {"completion-type", OPT_COMPLETION_TYPE, "Default completion type.",
++   (gptr*) &global_system_variables.completion_type,
++   (gptr*) &max_system_variables.completion_type, 0, GET_ULONG,
++   REQUIRED_ARG, 0, 0, 2, 0, 1, 0},
++  {"concurrent-insert", OPT_CONCURRENT_INSERT,
++   "Use concurrent insert with MyISAM. Disable with --concurrent-insert=0",
++   (gptr*) &myisam_concurrent_insert, (gptr*) &myisam_concurrent_insert,
++   0, GET_LONG, OPT_ARG, 1, 0, 2, 0, 0, 0},
++  {"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows.",
++   (gptr*) &opt_console, (gptr*) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0,
++   0, 0, 0},
++  {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG,
++   NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"datadir", 'h', "Path to the database root.", (gptr*) &mysql_data_home,
++   (gptr*) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#ifndef DBUG_OFF
++  {"debug", '#', "Debug log.", (gptr*) &default_dbug_option,
++   (gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
++#endif
++  {"default-character-set", 'C', "Set the default character set (deprecated option, use --character-set-server instead).",
++   (gptr*) &default_character_set_name, (gptr*) &default_character_set_name,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
++  {"default-collation", OPT_DEFAULT_COLLATION, "Set the default collation (deprecated option, use --collation-server instead).",
++   (gptr*) &default_collation_name, (gptr*) &default_collation_name,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
++  {"default-storage-engine", OPT_STORAGE_ENGINE,
++   "Set the default storage engine (table type) for tables.", 0, 0,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"default-table-type", OPT_STORAGE_ENGINE,
++   "(deprecated) Use --default-storage-engine.", 0, 0,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"default-time-zone", OPT_DEFAULT_TIME_ZONE, "Set the default time zone.",
++   (gptr*) &default_tz_name, (gptr*) &default_tz_name,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
++  {"delay-key-write", OPT_DELAY_KEY_WRITE, "Type of DELAY_KEY_WRITE.",
++   0,0,0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"delay-key-write-for-all-tables", OPT_DELAY_KEY_WRITE_ALL,
++   "Don't flush key buffers between writes for any MyISAM table (Deprecated option, use --delay-key-write=all instead).",
++   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++#ifdef HAVE_OPENSSL
++  {"des-key-file", OPT_DES_KEY_FILE,
++   "Load keys for des_encrypt() and des_encrypt from given file.",
++   (gptr*) &des_key_file, (gptr*) &des_key_file, 0, GET_STR, REQUIRED_ARG,
++   0, 0, 0, 0, 0, 0},
++#endif /* HAVE_OPENSSL */
++#ifdef HAVE_REPLICATION
++  {"disconnect-slave-event-count", OPT_DISCONNECT_SLAVE_EVENT_COUNT,
++   "Option used by mysql-test for debugging and testing of replication.",
++   (gptr*) &disconnect_slave_event_count,
++   (gptr*) &disconnect_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0,
++   0, 0, 0},
++#endif /* HAVE_REPLICATION */
++  {"enable-locking", OPT_ENABLE_LOCK,
++   "Deprecated option, use --external-locking instead.",
++   (gptr*) &opt_external_locking, (gptr*) &opt_external_locking,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++#ifdef __NT__
++  {"enable-named-pipe", OPT_HAVE_NAMED_PIPE, "Enable the named pipe (NT).",
++   (gptr*) &opt_enable_named_pipe, (gptr*) &opt_enable_named_pipe, 0, GET_BOOL,
++   NO_ARG, 0, 0, 0, 0, 0, 0},
++#endif
++  {"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure.",
++   (gptr*) &opt_do_pstack, (gptr*) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0,
++   0, 0, 0, 0},
++  {"engine-condition-pushdown",
++   OPT_ENGINE_CONDITION_PUSHDOWN,
++   "Push supported query conditions to the storage engine.",
++   (gptr*) &global_system_variables.engine_condition_pushdown,
++   (gptr*) &global_system_variables.engine_condition_pushdown,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"exit-info", 'T', "Used for debugging;  Use at your own risk!", 0, 0, 0,
++   GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"external-locking", OPT_USE_LOCKING, "Use system (external) locking (disabled by default). With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running. \
++Disable with --skip-external-locking.",
++   (gptr*) &opt_external_locking, (gptr*) &opt_external_locking,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"flush", OPT_FLUSH, "Flush tables to disk between SQL commands.", 0, 0, 0,
++   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++  /* We must always support the next option to make scripts like mysqltest
++     easier to do */
++  {"gdb", OPT_DEBUGGING,
++   "Set up signals usable for debugging",
++   (gptr*) &opt_debugging, (gptr*) &opt_debugging,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++#ifdef HAVE_LARGE_PAGES
++  {"large-pages", OPT_ENABLE_LARGE_PAGES, "Enable support for large pages. \
++Disable with --skip-large-pages.",
++   (gptr*) &opt_large_pages, (gptr*) &opt_large_pages, 0, GET_BOOL, NO_ARG, 0, 0, 0,
++   0, 0, 0},
++#endif
++  {"init-connect", OPT_INIT_CONNECT, "Command(s) that are executed for each new connection",
++   (gptr*) &opt_init_connect, (gptr*) &opt_init_connect, 0, GET_STR_ALLOC,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#ifndef DISABLE_GRANT_OPTIONS
++  {"init-file", OPT_INIT_FILE, "Read SQL commands from this file at startup.",
++   (gptr*) &opt_init_file, (gptr*) &opt_init_file, 0, GET_STR, REQUIRED_ARG,
++   0, 0, 0, 0, 0, 0},
++#endif
++  {"init-rpl-role", OPT_INIT_RPL_ROLE, "Set the replication role.", 0, 0, 0,
++   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed when a slave connects to this master",
++   (gptr*) &opt_init_slave, (gptr*) &opt_init_slave, 0, GET_STR_ALLOC,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"innodb", OPT_INNODB, "Enable InnoDB (if this version of MySQL supports it). \
++Disable with --skip-innodb (will save memory).",
++   (gptr*) &opt_innodb, (gptr*) &opt_innodb, 0, GET_BOOL, NO_ARG, OPT_INNODB_DEFAULT, 0, 0,
++   0, 0, 0},
++#ifdef HAVE_INNOBASE_DB
++  {"innodb_checksums", OPT_INNODB_CHECKSUMS, "Enable InnoDB checksums validation (enabled by default). \
++Disable with --skip-innodb-checksums.", (gptr*) &innobase_use_checksums,
++   (gptr*) &innobase_use_checksums, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
++#endif
++  {"innodb_data_file_path", OPT_INNODB_DATA_FILE_PATH,
++   "Path to individual files and their sizes.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#ifdef HAVE_INNOBASE_DB
++  {"innodb_data_home_dir", OPT_INNODB_DATA_HOME_DIR,
++   "The common part for InnoDB table spaces.", (gptr*) &innobase_data_home_dir,
++   (gptr*) &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0,
++   0},
++  {"innodb_doublewrite", OPT_INNODB_DOUBLEWRITE, "Enable InnoDB doublewrite buffer (enabled by default). \
++Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite,
++   (gptr*) &innobase_use_doublewrite, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
++  {"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN,
++   "Speeds up the shutdown process of the InnoDB storage engine. Possible "
++   "values are 0, 1 (faster)"
++   /*
++     NetWare can't close unclosed files, can't automatically kill remaining
++     threads, etc, so on this OS we disable the crash-like InnoDB shutdown.
++   */
++#ifndef __NETWARE__
++   " or 2 (fastest - crash-like)"
++#endif
++   ".",
++   (gptr*) &innobase_fast_shutdown,
++   (gptr*) &innobase_fast_shutdown, 0, GET_ULONG, OPT_ARG, 1, 0,
++   IF_NETWARE(1,2), 0, 0, 0},
++  {"innodb_file_per_table", OPT_INNODB_FILE_PER_TABLE,
++   "Stores each InnoDB table to an .ibd file in the database dir.",
++   (gptr*) &innobase_file_per_table,
++   (gptr*) &innobase_file_per_table, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"innodb_flush_log_at_trx_commit", OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT,
++   "Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).",
++   (gptr*) &srv_flush_log_at_trx_commit,
++   (gptr*) &srv_flush_log_at_trx_commit,
++   0, GET_ULONG, OPT_ARG,  1, 0, 2, 0, 0, 0},
++  {"innodb_flush_method", OPT_INNODB_FLUSH_METHOD,
++   "With which method to flush data.", (gptr*) &innobase_unix_file_flush_method,
++   (gptr*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
++   0, 0, 0},
++  {"innodb_locks_unsafe_for_binlog", OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
++   "Force InnoDB not to use next-key locking. Instead use only row-level locking",
++   (gptr*) &innobase_locks_unsafe_for_binlog,
++   (gptr*) &innobase_locks_unsafe_for_binlog, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"innodb_log_arch_dir", OPT_INNODB_LOG_ARCH_DIR,
++   "Where full logs should be archived.", (gptr*) &innobase_log_arch_dir,
++   (gptr*) &innobase_log_arch_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"innodb_log_archive", OPT_INNODB_LOG_ARCHIVE,
++   "Set to 1 if you want to have logs archived.", 0, 0, 0, GET_LONG, OPT_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"innodb_log_group_home_dir", OPT_INNODB_LOG_GROUP_HOME_DIR,
++   "Path to InnoDB log files.", (gptr*) &innobase_log_group_home_dir,
++   (gptr*) &innobase_log_group_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
++   0, 0},
++  {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT,
++   "Percentage of dirty pages allowed in bufferpool.", (gptr*) &srv_max_buf_pool_modified_pct,
++   (gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0},
++  {"innodb_max_purge_lag", OPT_INNODB_MAX_PURGE_LAG,
++   "Desired maximum length of the purge queue (0 = no limit)",
++   (gptr*) &srv_max_purge_lag,
++   (gptr*) &srv_max_purge_lag, 0, GET_LONG, REQUIRED_ARG, 0, 0, ~0L,
++   0, 1L, 0},
++  {"innodb_rollback_on_timeout", OPT_INNODB_ROLLBACK_ON_TIMEOUT,
++   "Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
++   (gptr*) &innobase_rollback_on_timeout, (gptr*) &innobase_rollback_on_timeout,
++   0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"innodb_status_file", OPT_INNODB_STATUS_FILE,
++   "Enable SHOW INNODB STATUS output in the innodb_status.<pid> file",
++   (gptr*) &innobase_create_status_file, (gptr*) &innobase_create_status_file,
++   0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"innodb_support_xa", OPT_INNODB_SUPPORT_XA,
++   "Enable InnoDB support for the XA two-phase commit",
++   (gptr*) &global_system_variables.innodb_support_xa,
++   (gptr*) &global_system_variables.innodb_support_xa,
++   0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
++  {"innodb_table_locks", OPT_INNODB_TABLE_LOCKS,
++   "Enable InnoDB locking in LOCK TABLES",
++   (gptr*) &global_system_variables.innodb_table_locks,
++   (gptr*) &global_system_variables.innodb_table_locks,
++   0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
++#endif /* End HAVE_INNOBASE_DB */
++  {"isam", OPT_ISAM, "Obsolete. ISAM storage engine is no longer supported.",
++   (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, 0, 0, 0,
++   0, 0, 0},
++   {"language", 'L',
++   "Client error messages in given language. May be given as a full path.",
++   (gptr*) &language_ptr, (gptr*) &language_ptr, 0, GET_STR, REQUIRED_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"lc-time-names", OPT_LC_TIME_NAMES,
++   "Set the language used for the month names and the days of the week.",
++   (gptr*) &lc_time_names_name,
++   (gptr*) &lc_time_names_name,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
++  {"local-infile", OPT_LOCAL_INFILE,
++   "Enable/disable LOAD DATA LOCAL INFILE (takes values 1|0).",
++   (gptr*) &opt_local_infile,
++   (gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG,
++   1, 0, 0, 0, 0, 0},
++  {"log", 'l', "Log connections and queries to file.", (gptr*) &opt_logname,
++   (gptr*) &opt_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"log-bin", OPT_BIN_LOG,
++   "Log update queries in binary format. Optional (but strongly recommended "
++   "to avoid replication problems if server's hostname changes) argument "
++   "should be the chosen location for the binary log files.",
++   (gptr*) &opt_bin_logname, (gptr*) &opt_bin_logname, 0, GET_STR_ALLOC,
++   OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"log-bin-index", OPT_BIN_LOG_INDEX,
++   "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},
++  /*
++    This option starts with "log-bin" to emphasize that it is specific of
++    binary logging.
++  */
++  {"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 stored 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},
++#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
++  {"log-error", OPT_ERROR_LOG_FILE, "Error log file.",
++   (gptr*) &log_error_file_ptr, (gptr*) &log_error_file_ptr, 0, GET_STR,
++   OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
++   (gptr*) &myisam_log_filename, (gptr*) &myisam_log_filename, 0, GET_STR,
++   OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"log-long-format", '0',
++   "Log some extra information to update log. Please note that this option is deprecated; see --log-short-format option.",
++   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"log-queries-not-using-indexes", OPT_LOG_QUERIES_NOT_USING_INDEXES,
++   "Log queries that are executed without benefit of any index to the slow log if it is open.",
++   (gptr*) &opt_log_queries_not_using_indexes, (gptr*) &opt_log_queries_not_using_indexes,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"log-short-format", OPT_SHORT_LOG_FORMAT,
++   "Don't log extra information to update and slow-query logs.",
++   (gptr*) &opt_short_log_format, (gptr*) &opt_short_log_format,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"log-slave-updates", OPT_LOG_SLAVE_UPDATES,
++   "Tells the slave to log the updates from the slave thread to the binary log. You will need to turn it on if you plan to daisy-chain the slaves.",
++   (gptr*) &opt_log_slave_updates, (gptr*) &opt_log_slave_updates, 0, GET_BOOL,
++   NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"log-slow-admin-statements", OPT_LOG_SLOW_ADMIN_STATEMENTS,
++   "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to the slow log if it is open.",
++   (gptr*) &opt_log_slow_admin_statements,
++   (gptr*) &opt_log_slow_admin_statements,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"log-slow-queries", OPT_SLOW_QUERY_LOG,
++    "Log slow queries to this log file. Defaults logging to hostname-slow.log file. Must be enabled to activate other slow log options.",
++   (gptr*) &opt_slow_logname, (gptr*) &opt_slow_logname, 0, GET_STR, OPT_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"log-tc", OPT_LOG_TC,
++   "Path to transaction coordinator log (used for transactions that affect "
++   "more than one storage engine, when binary log is disabled)",
++   (gptr*) &opt_tc_log_file, (gptr*) &opt_tc_log_file, 0, GET_STR,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#ifdef HAVE_MMAP
++  {"log-tc-size", OPT_LOG_TC_SIZE, "Size of transaction coordinator log.",
++   (gptr*) &opt_tc_log_size, (gptr*) &opt_tc_log_size, 0, GET_ULONG,
++   REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ~0L, 0, TC_LOG_PAGE_SIZE, 0},
++#endif
++  {"log-update", OPT_UPDATE_LOG,
++   "The update log is deprecated since version 5.0, is replaced by the binary \
++log and this option justs turns on --log-bin instead.",
++   (gptr*) &opt_update_logname, (gptr*) &opt_update_logname, 0, GET_STR,
++   OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"log-warnings", 'W', "Log some not critical warnings to the log file.",
++   (gptr*) &global_system_variables.log_warnings,
++   (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0,
++   0, 0, 0},
++  {"low-priority-updates", OPT_LOW_PRIORITY_UPDATES,
++   "INSERT/DELETE/UPDATE has lower priority than selects.",
++   (gptr*) &global_system_variables.low_priority_updates,
++   (gptr*) &max_system_variables.low_priority_updates,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"master-connect-retry", OPT_MASTER_CONNECT_RETRY,
++   "The number of seconds the slave thread will sleep before retrying to connect to the master in case the master goes down or the connection is lost.",
++   (gptr*) &master_connect_retry, (gptr*) &master_connect_retry, 0, GET_UINT,
++   REQUIRED_ARG, 60, 0, 0, 0, 0, 0},
++  {"master-host", OPT_MASTER_HOST,
++   "Master hostname or IP address for replication. If not set, the slave thread will not be started. Note that the setting of master-host will be ignored if there exists a valid master.info file.",
++   (gptr*) &master_host, (gptr*) &master_host, 0, GET_STR, REQUIRED_ARG, 0, 0,
++   0, 0, 0, 0},
++  {"master-info-file", OPT_MASTER_INFO_FILE,
++   "The location and name of the file that remembers the master and where the I/O replication \
++thread is in the master's binlogs.",
++   (gptr*) &master_info_file, (gptr*) &master_info_file, 0, GET_STR,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"master-password", OPT_MASTER_PASSWORD,
++   "The password the slave thread will authenticate with when connecting to the master. If not set, an empty password is assumed.The value in master.info will take precedence if it can be read.",
++   (gptr*)&master_password, (gptr*)&master_password, 0,
++   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"master-port", OPT_MASTER_PORT,
++   "The port the master is listening on. If not set, the compiled setting of MYSQL_PORT is assumed. If you have not tinkered with configure options, this should be 3306. The value in master.info will take precedence if it can be read.",
++   (gptr*) &master_port, (gptr*) &master_port, 0, GET_UINT, REQUIRED_ARG,
++   MYSQL_PORT, 0, 0, 0, 0, 0},
++  {"master-retry-count", OPT_MASTER_RETRY_COUNT,
++   "The number of tries the slave will make to connect to the master before giving up.",
++   (gptr*) &master_retry_count, (gptr*) &master_retry_count, 0, GET_ULONG,
++   REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
++  {"master-ssl", OPT_MASTER_SSL,
++   "Enable the slave to connect to the master using SSL.",
++   (gptr*) &master_ssl, (gptr*) &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
++   0, 0},
++  {"master-ssl-ca", OPT_MASTER_SSL_CA,
++   "Master SSL CA file. Only applies if you have enabled master-ssl.",
++   (gptr*) &master_ssl_ca, (gptr*) &master_ssl_ca, 0, GET_STR, OPT_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"master-ssl-capath", OPT_MASTER_SSL_CAPATH,
++   "Master SSL CA path. Only applies if you have enabled master-ssl.",
++   (gptr*) &master_ssl_capath, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"master-ssl-cert", OPT_MASTER_SSL_CERT,
++   "Master SSL certificate file name. Only applies if you have enabled \
++master-ssl",
++   (gptr*) &master_ssl_cert, (gptr*) &master_ssl_cert, 0, GET_STR, OPT_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"master-ssl-cipher", OPT_MASTER_SSL_CIPHER,
++   "Master SSL cipher. Only applies if you have enabled master-ssl.",
++   (gptr*) &master_ssl_cipher, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"master-ssl-key", OPT_MASTER_SSL_KEY,
++   "Master SSL keyfile name. Only applies if you have enabled master-ssl.",
++   (gptr*) &master_ssl_key, (gptr*) &master_ssl_key, 0, GET_STR, OPT_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"master-user", OPT_MASTER_USER,
++   "The username the slave thread will use for authentication when connecting to the master. The user must have FILE privilege. If the master user is not set, user test is assumed. The value in master.info will take precedence if it can be read.",
++   (gptr*) &master_user, (gptr*) &master_user, 0, GET_STR, REQUIRED_ARG, 0, 0,
++   0, 0, 0, 0},
++#ifdef HAVE_REPLICATION
++  {"max-binlog-dump-events", OPT_MAX_BINLOG_DUMP_EVENTS,
++   "Option used by mysql-test for debugging and testing of replication.",
++   (gptr*) &max_binlog_dump_events, (gptr*) &max_binlog_dump_events, 0,
++   GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#endif /* HAVE_REPLICATION */
++  {"memlock", OPT_MEMLOCK, "Lock mysqld in memory.", (gptr*) &locked_in_memory,
++   (gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"merge", OPT_MERGE, "Enable Merge storage engine. Disable with \
++--skip-merge.",
++   (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
++  {"myisam-recover", OPT_MYISAM_RECOVER,
++   "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.",
++   (gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0,
++   GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"ndbcluster", OPT_NDBCLUSTER, "Enable NDB Cluster (if this version of MySQL supports it). \
++Disable with --skip-ndbcluster (will save memory).",
++   (gptr*) &opt_ndbcluster, (gptr*) &opt_ndbcluster, 0, GET_BOOL, NO_ARG,
++   OPT_NDBCLUSTER_DEFAULT, 0, 0, 0, 0, 0},
++#ifdef HAVE_NDBCLUSTER_DB
++  {"ndb-connectstring", OPT_NDB_CONNECTSTRING,
++   "Connect string for ndbcluster.",
++   (gptr*) &opt_ndb_connectstring,
++   (gptr*) &opt_ndb_connectstring,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"ndb-mgmd-host", OPT_NDB_MGMD,
++   "Set host and port for ndb_mgmd. Syntax: hostname[:port]",
++   (gptr*) &opt_ndb_mgmd,
++   (gptr*) &opt_ndb_mgmd,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"ndb-nodeid", OPT_NDB_NODEID,
++   "Nodeid for this mysqlserver in the cluster.",
++   (gptr*) &opt_ndb_nodeid,
++   (gptr*) &opt_ndb_nodeid,
++   0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"ndb-autoincrement-prefetch-sz", OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
++   "Specify number of autoincrement values that are prefetched.",
++   (gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
++   (gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
++   0, GET_ULONG, REQUIRED_ARG, 32, 1, 256, 0, 0, 0},
++  {"ndb-force-send", OPT_NDB_FORCE_SEND,
++   "Force send of buffers to ndb immediately without waiting for "
++   "other threads.",
++   (gptr*) &global_system_variables.ndb_force_send,
++   (gptr*) &global_system_variables.ndb_force_send,
++   0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
++  {"ndb_force_send", OPT_NDB_FORCE_SEND,
++   "same as --ndb-force-send.",
++   (gptr*) &global_system_variables.ndb_force_send,
++   (gptr*) &global_system_variables.ndb_force_send,
++   0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
++  {"ndb-use-exact-count", OPT_NDB_USE_EXACT_COUNT,
++   "Use exact records count during query planning and for fast "
++   "select count(*), disable for faster queries.",
++   (gptr*) &global_system_variables.ndb_use_exact_count,
++   (gptr*) &global_system_variables.ndb_use_exact_count,
++   0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
++  {"ndb_use_exact_count", OPT_NDB_USE_EXACT_COUNT,
++   "same as --ndb-use-exact-count.",
++   (gptr*) &global_system_variables.ndb_use_exact_count,
++   (gptr*) &global_system_variables.ndb_use_exact_count,
++   0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
++  {"ndb-use-transactions", OPT_NDB_USE_TRANSACTIONS,
++   "Use transactions for large inserts, if enabled then large "
++   "inserts will be split into several smaller transactions",
++   (gptr*) &global_system_variables.ndb_use_transactions,
++   (gptr*) &global_system_variables.ndb_use_transactions,
++   0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
++  {"ndb_use_transactions", OPT_NDB_USE_TRANSACTIONS,
++   "same as --ndb-use-transactions.",
++   (gptr*) &global_system_variables.ndb_use_transactions,
++   (gptr*) &global_system_variables.ndb_use_transactions,
++   0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
++  {"ndb-shm", OPT_NDB_SHM,
++   "Use shared memory connections when available.",
++   (gptr*) &opt_ndb_shm,
++   (gptr*) &opt_ndb_shm,
++   0, GET_BOOL, OPT_ARG, OPT_NDB_SHM_DEFAULT, 0, 0, 0, 0, 0},
++  {"ndb-optimized-node-selection", OPT_NDB_OPTIMIZED_NODE_SELECTION,
++   "Select nodes for transactions in a more optimal way.",
++   (gptr*) &opt_ndb_optimized_node_selection,
++   (gptr*) &opt_ndb_optimized_node_selection,
++   0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
++  { "ndb-cache-check-time", OPT_NDB_CACHE_CHECK_TIME,
++    "A dedicated thread is created to, at the given millisecons interval, invalidate the query cache if another MySQL server in the cluster has changed the data in the database.",
++    (gptr*) &opt_ndb_cache_check_time, (gptr*) &opt_ndb_cache_check_time, 0, GET_ULONG, REQUIRED_ARG,
++    0, 0, LONG_TIMEOUT, 0, 1, 0},
++#endif
++  {"new", 'n', "Use very new possible 'unsafe' functions.",
++   (gptr*) &global_system_variables.new_mode,
++   (gptr*) &max_system_variables.new_mode,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++#ifdef NOT_YET
++  {"no-mix-table-types", OPT_NO_MIX_TYPE, "Don't allow commands with uses two different table types.",
++   (gptr*) &opt_no_mix_types, (gptr*) &opt_no_mix_types, 0, GET_BOOL, NO_ARG,
++   0, 0, 0, 0, 0, 0},
++#endif
++  {"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients).",
++   (gptr*) &global_system_variables.old_passwords,
++   (gptr*) &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG,
++   0, 0, 0, 0, 0, 0},
++#ifdef ONE_THREAD
++  {"one-thread", OPT_ONE_THREAD,
++   "Only use one thread (for debugging under Linux).", 0, 0, 0, GET_NO_ARG,
++   NO_ARG, 0, 0, 0, 0, 0, 0},
++#endif
++  {"old-style-user-limits", OPT_OLD_STYLE_USER_LIMITS,
++   "Enable old-style user limits (before 5.0.3 user resources were counted per each user+host vs. per account)",
++   (gptr*) &opt_old_style_user_limits, (gptr*) &opt_old_style_user_limits,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"pid-file", OPT_PID_FILE, "Pid file used by safe_mysqld.",
++   (gptr*) &pidfile_name_ptr, (gptr*) &pidfile_name_ptr, 0, GET_STR,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"port", 'P', "Port number to use for connection.", (gptr*) &mysqld_port,
++   (gptr*) &mysqld_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"port-open-timeout", OPT_PORT_OPEN_TIMEOUT,
++   "Maximum time in seconds to wait for the port to become free. "
++   "(Default: no wait)", (gptr*) &mysqld_port_timeout,
++   (gptr*) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#ifdef ENABLED_PROFILING
++  {"profiling_history_size", OPT_PROFILING, "Limit of query profiling memory",
++   (gptr*) &global_system_variables.profiling_history_size,
++   (gptr*) &max_system_variables.profiling_history_size,
++   0, GET_ULONG, REQUIRED_ARG, 15, 0, 100, 0, 0, 0},
++#endif
++  {"relay-log", OPT_RELAY_LOG,
++   "The location and name to use for relay logs.",
++   (gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0,
++   GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"relay-log-index", OPT_RELAY_LOG_INDEX,
++   "The location and name to use for the file that keeps a list of the last \
++relay logs.",
++   (gptr*) &opt_relaylog_index_name, (gptr*) &opt_relaylog_index_name, 0,
++   GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE,
++   "The location and name of the file that remembers where the SQL replication \
++thread is in the relay logs.",
++   (gptr*) &relay_log_info_file, (gptr*) &relay_log_info_file, 0, GET_STR,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"replicate-do-db", OPT_REPLICATE_DO_DB,
++   "Tells the slave thread to restrict replication to the specified database. To specify more than one database, use the directive multiple times, once for each database. Note that this will only work if you do not use cross-database queries such as UPDATE some_db.some_table SET foo='bar' while having selected a different or no database. If you need cross database updates to work, make sure you have 3.23.28 or later, and use replicate-wild-do-table=db_name.%.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
++   "Tells the slave thread to restrict replication to the specified table. To specify more than one table, use the directive multiple times, once for each table. This will work for cross-database updates, in contrast to replicate-do-db.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
++   "Tells the slave thread to not replicate to the specified database. To specify more than one database to ignore, use the directive multiple times, once for each database. This option will not work if you use cross database updates. If you need cross database updates to work, make sure you have 3.23.28 or later, and use replicate-wild-ignore-table=db_name.%. ",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
++   "Tells the slave thread to not replicate to the specified table. To specify more than one table to ignore, use the directive multiple times, once for each table. This will work for cross-datbase updates, in contrast to replicate-ignore-db.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
++   "Updates to a database with a different name than the original. Example: replicate-rewrite-db=master_db_name->slave_db_name.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#ifdef HAVE_REPLICATION
++  {"replicate-same-server-id", OPT_REPLICATE_SAME_SERVER_ID,
++   "In replication, if set to 1, do not skip events having our server id. \
++Default value is 0 (to break infinite loops in circular replication). \
++Can't be set to 1 if --log-slave-updates is used.",
++   (gptr*) &replicate_same_server_id,
++   (gptr*) &replicate_same_server_id,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++#endif
++  {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
++   "Tells the slave thread to restrict replication to the tables that match the specified wildcard pattern. To specify more than one table, use the directive multiple times, once for each table. This will work for cross-database updates. Example: replicate-wild-do-table=foo%.bar% will replicate only updates to tables in all databases that start with foo and whose table names start with bar.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
++   "Tells the slave thread to not replicate to the tables that match the given wildcard pattern. To specify more than one table to ignore, use the directive multiple times, once for each table. This will work for cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% will not do updates to tables in databases that start with foo and whose table names start with bar.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  // In replication, we may need to tell the other servers how to connect
++  {"report-host", OPT_REPORT_HOST,
++   "Hostname or IP of the slave to be reported to to the master during slave registration. Will appear in the output of SHOW SLAVE HOSTS. Leave unset if you do not want the slave to register itself with the master. Note that it is not sufficient for the master to simply read the IP of the slave off the socket once the slave connects. Due to NAT and other routing issues, that IP may not be valid for connecting to the slave from the master or other hosts.",
++   (gptr*) &report_host, (gptr*) &report_host, 0, GET_STR, REQUIRED_ARG, 0, 0,
++   0, 0, 0, 0},
++  {"report-password", OPT_REPORT_PASSWORD, "Undocumented.",
++   (gptr*) &report_password, (gptr*) &report_password, 0, GET_STR,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"report-port", OPT_REPORT_PORT,
++   "Port for connecting to slave reported to the master during slave registration. Set it only if the slave is listening on a non-default port or if you have a special tunnel from the master or other clients to the slave. If not sure, leave this option unset.",
++   (gptr*) &report_port, (gptr*) &report_port, 0, GET_UINT, REQUIRED_ARG,
++   MYSQL_PORT, 0, 0, 0, 0, 0},
++  {"report-user", OPT_REPORT_USER, "Undocumented.", (gptr*) &report_user,
++   (gptr*) &report_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented.",
++   (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_ULONG,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).",
++   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++#ifndef TO_BE_DELETED
++  {"safe-show-database", OPT_SAFE_SHOW_DB,
++   "Deprecated option; use GRANT SHOW DATABASES instead...",
++   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++#endif
++  {"safe-user-create", OPT_SAFE_USER_CREATE,
++   "Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
++   (gptr*) &opt_safe_user_create, (gptr*) &opt_safe_user_create, 0, GET_BOOL,
++   NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"safemalloc-mem-limit", OPT_SAFEMALLOC_MEM_LIMIT,
++   "Simulate memory shortage when compiled with the --with-debug=full option.",
++   0, 0, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"secure-auth", OPT_SECURE_AUTH, "Disallow authentication for accounts that have old (pre-4.1) passwords.",
++   (gptr*) &opt_secure_auth, (gptr*) &opt_secure_auth, 0, GET_BOOL, NO_ARG,
++   my_bool(0), 0, 0, 0, 0, 0},
++  {"secure-file-priv", OPT_SECURE_FILE_PRIV,
++   "Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory",
++   (gptr*) &opt_secure_file_priv, (gptr*) &opt_secure_file_priv, 0,
++   GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"server-id",	OPT_SERVER_ID,
++   "Uniquely identifies the server instance in the community of replication partners.",
++   (gptr*) &server_id, (gptr*) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0,
++   0, 0, 0},
++  {"set-variable", 'O',
++   "Change the value of a variable. Please note that this option is deprecated;you can set variables directly with --variable-name=value.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#ifdef HAVE_SMEM
++  {"shared-memory", OPT_ENABLE_SHARED_MEMORY,
++   "Enable the shared memory.",(gptr*) &opt_enable_shared_memory, (gptr*) &opt_enable_shared_memory,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++#endif
++#ifdef HAVE_SMEM
++  {"shared-memory-base-name",OPT_SHARED_MEMORY_BASE_NAME,
++   "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#endif
++  {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO,
++   "Show user and password in SHOW SLAVE HOSTS on this master",
++   (gptr*) &opt_show_slave_auth_info, (gptr*) &opt_show_slave_auth_info, 0,
++   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++#ifndef DISABLE_GRANT_OPTIONS
++  {"skip-grant-tables", OPT_SKIP_GRANT,
++   "Start without grant tables. This gives all users FULL ACCESS to all tables!",
++   (gptr*) &opt_noacl, (gptr*) &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
++   0},
++#endif
++  {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", 0, 0, 0,
++   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"skip-locking", OPT_SKIP_LOCK,
++   "Deprecated option, use --skip-external-locking instead.",
++   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"skip-name-resolve", OPT_SKIP_RESOLVE,
++   "Don't resolve hostnames. All hostnames are IP's or 'localhost'.",
++   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"skip-networking", OPT_SKIP_NETWORKING,
++   "Don't allow connection with TCP/IP.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0,
++   0, 0, 0},
++  {"skip-new", OPT_SKIP_NEW, "Don't use new, possible wrong routines.",
++   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++#ifndef DBUG_OFF
++#ifdef SAFEMALLOC
++  {"skip-safemalloc", OPT_SKIP_SAFEMALLOC,
++   "Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG,
++   0, 0, 0, 0, 0, 0},
++#endif
++#endif
++  {"skip-show-database", OPT_SKIP_SHOW_DB,
++   "Don't allow 'SHOW DATABASE' commands.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
++   0, 0, 0, 0},
++  {"skip-slave-start", OPT_SKIP_SLAVE_START,
++   "If set, slave is not autostarted.", (gptr*) &opt_skip_slave_start,
++   (gptr*) &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
++   "Don't print a stack trace on failure.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
++   0, 0, 0, 0},
++  {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables. Deprecated option.  Use --skip-symbolic-links instead.",
++   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"skip-thread-priority", OPT_SKIP_PRIOR,
++   "Don't give threads different priorities.", 0, 0, 0, GET_NO_ARG, NO_ARG,
++   DEFAULT_SKIP_THREAD_PRIORITY, 0, 0, 0, 0, 0},
++#ifdef HAVE_REPLICATION
++  {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR,
++   "The location where the slave should put its temporary files when \
++replicating a LOAD DATA INFILE command.",
++   (gptr*) &slave_load_tmpdir, (gptr*) &slave_load_tmpdir, 0, GET_STR_ALLOC,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"slave-skip-errors", OPT_SLAVE_SKIP_ERRORS,
++   "Tells the slave thread to continue replication when a query returns an error from the provided list.",
++   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#endif
++  {"socket", OPT_SOCKET, "Socket file to use for connection.",
++   (gptr*) &mysqld_unix_port, (gptr*) &mysqld_unix_port, 0, GET_STR,
++   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++#ifdef HAVE_REPLICATION
++  {"sporadic-binlog-dump-fail", OPT_SPORADIC_BINLOG_DUMP_FAIL,
++   "Option used by mysql-test for debugging and testing of replication.",
++   (gptr*) &opt_sporadic_binlog_dump_fail,
++   (gptr*) &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
++   0},
++#endif /* HAVE_REPLICATION */
++  {"sql-bin-update-same", OPT_SQL_BIN_UPDATE_SAME,
++   "The update log is deprecated since version 5.0, is replaced by the binary \
++log and this option does nothing anymore.",
++   0, 0, 0, GET_DISABLED, NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"sql-mode", OPT_SQL_MODE,
++   "Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.",
++   (gptr*) &sql_mode_str, (gptr*) &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0,
++   0, 0, 0, 0, 0},
++#ifdef HAVE_OPENSSL
++#include "sslopt-longopts.h"
++#endif
++#ifdef __WIN__
++  {"standalone", OPT_STANDALONE,
++  "Dummy option to start as a standalone program (NT).", 0, 0, 0, GET_NO_ARG,
++   NO_ARG, 0, 0, 0, 0, 0, 0},
++#endif
++  {"symbolic-links", 's', "Enable symbolic link support.",
++   (gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
++   IF_PURIFY(0,1), 0, 0, 0, 0, 0},
++  {"sysdate-is-now", OPT_SYSDATE_IS_NOW,
++   "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. Since 5.0, SYSDATE() returns a `dynamic' value different for different invocations, even within the same statement.",
++   (gptr*) &global_system_variables.sysdate_is_now,
++   0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
++  {"tc-heuristic-recover", OPT_TC_HEURISTIC_RECOVER,
++   "Decision to use in heuristic recover process. Possible values are COMMIT or ROLLBACK.",
++   (gptr*) &opt_tc_heuristic_recover, (gptr*) &opt_tc_heuristic_recover,
++   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"temp-pool", OPT_TEMP_POOL,
++   "Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.",
++   (gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
++   0, 0, 0, 0, 0},
++  {"timed_mutexes", OPT_TIMED_MUTEXES,
++   "Specify whether to time mutexes (only InnoDB mutexes are currently supported)",
++   (gptr*) &timed_mutexes, (gptr*) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0,
++    0, 0, 0, 0, 0},
++  {"tmpdir", 't',
++   "Path for temporary files. Several paths may be specified, separated by a "
++#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
++   "semicolon (;)"
++#else
++   "colon (:)"
++#endif
++   ", in this case they are used in a round-robin fashion.",
++   (gptr*) &opt_mysql_tmpdir,
++   (gptr*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"transaction-isolation", OPT_TX_ISOLATION,
++   "Default transaction isolation level.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0,
++   0, 0, 0, 0, 0},
++  {"use-symbolic-links", 's', "Enable symbolic link support. Deprecated option; use --symbolic-links instead.",
++   (gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
++   /*
++     The system call realpath() produces warnings under valgrind and
++     purify. These are not suppressed: instead we disable symlinks
++     option if compiled with valgrind support. 
++   */
++   IF_PURIFY(0,1), 0, 0, 0, 0, 0},
++  {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
++   0, 0, 0, 0, 0, 0},
++  {"verbose", 'v', "Used with --help option for detailed help",
++   (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
++   0, 0},
++  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
++   NO_ARG, 0, 0, 0, 0, 0, 0},
++  {"warnings", 'W', "Deprecated; use --log-warnings instead.",
++   (gptr*) &global_system_variables.log_warnings,
++   (gptr*) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, ~0L,
++   0, 0, 0},
++  { "back_log", OPT_BACK_LOG,
++    "The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.",
++    (gptr*) &back_log, (gptr*) &back_log, 0, GET_ULONG,
++    REQUIRED_ARG, 50, 1, 65535, 0, 1, 0 },
++#ifdef HAVE_BERKELEY_DB
++  { "bdb_cache_size", OPT_BDB_CACHE_SIZE,
++    "The buffer that is allocated to cache index and rows for BDB tables.",
++    (gptr*) &berkeley_cache_size, (gptr*) &berkeley_cache_size, 0, GET_ULONG,
++    REQUIRED_ARG, KEY_CACHE_SIZE, 20*1024, (long) ~0, 0, IO_SIZE, 0},
++  /* QQ: The following should be removed soon! (bdb_max_lock preferred) */
++  {"bdb_lock_max", OPT_BDB_MAX_LOCK, "Synonym for bdb_max_lock.",
++   (gptr*) &berkeley_max_lock, (gptr*) &berkeley_max_lock, 0, GET_ULONG,
++   REQUIRED_ARG, 10000, 0, (long) ~0, 0, 1, 0},
++  {"bdb_log_buffer_size", OPT_BDB_LOG_BUFFER_SIZE,
++   "The buffer that is allocated to cache index and rows for BDB tables.",
++   (gptr*) &berkeley_log_buffer_size, (gptr*) &berkeley_log_buffer_size, 0,
++   GET_ULONG, REQUIRED_ARG, 0, 256*1024L, ~0L, 0, 1024, 0},
++  {"bdb_max_lock", OPT_BDB_MAX_LOCK,
++   "The maximum number of locks you can have active on a BDB table.",
++   (gptr*) &berkeley_max_lock, (gptr*) &berkeley_max_lock, 0, GET_ULONG,
++   REQUIRED_ARG, 10000, 0, (long) ~0, 0, 1, 0},
++#endif /* HAVE_BERKELEY_DB */
++  {"binlog_cache_size", OPT_BINLOG_CACHE_SIZE,
++   "The size of the cache to hold the SQL statements for the binary log during a transaction. If you often use big, multi-statement transactions you can increase this to get more performance.",
++   (gptr*) &binlog_cache_size, (gptr*) &binlog_cache_size, 0, GET_ULONG,
++   REQUIRED_ARG, 32*1024L, IO_SIZE, ~0L, 0, IO_SIZE, 0},
++  {"bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE,
++   "Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread!",
++   (gptr*) &global_system_variables.bulk_insert_buff_size,
++   (gptr*) &max_system_variables.bulk_insert_buff_size,
++   0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ~0L, 0, 1, 0},
++  {"connect_timeout", OPT_CONNECT_TIMEOUT,
++   "The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake'.",
++    (gptr*) &connect_timeout, (gptr*) &connect_timeout,
++   0, GET_ULONG, REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 },
++  { "date_format", OPT_DATE_FORMAT,
++    "The DATE format (For future).",
++    (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE],
++    (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE],
++    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  { "datetime_format", OPT_DATETIME_FORMAT,
++    "The DATETIME/TIMESTAMP format (for future).",
++    (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME],
++    (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME],
++    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  { "default_week_format", OPT_DEFAULT_WEEK_FORMAT,
++    "The default week format used by WEEK() functions.",
++    (gptr*) &global_system_variables.default_week_format,
++    (gptr*) &max_system_variables.default_week_format,
++    0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0},
++  {"delayed_insert_limit", OPT_DELAYED_INSERT_LIMIT,
++   "After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing.",
++    (gptr*) &delayed_insert_limit, (gptr*) &delayed_insert_limit, 0, GET_ULONG,
++    REQUIRED_ARG, DELAYED_LIMIT, 1, ~0L, 0, 1, 0},
++  {"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT,
++   "How long a INSERT DELAYED thread should wait for INSERT statements before terminating.",
++   (gptr*) &delayed_insert_timeout, (gptr*) &delayed_insert_timeout, 0,
++   GET_ULONG, REQUIRED_ARG, DELAYED_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
++  { "delayed_queue_size", OPT_DELAYED_QUEUE_SIZE,
++    "What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again.",
++    (gptr*) &delayed_queue_size, (gptr*) &delayed_queue_size, 0, GET_ULONG,
++    REQUIRED_ARG, DELAYED_QUEUE_SIZE, 1, ~0L, 0, 1, 0},
++  {"div_precision_increment", OPT_DIV_PRECINCREMENT,
++   "Precision of the result of '/' operator will be increased on that value.",
++   (gptr*) &global_system_variables.div_precincrement,
++   (gptr*) &max_system_variables.div_precincrement, 0, GET_ULONG,
++   REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0},
++  {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS,
++   "If non-zero, binary logs will be purged after expire_logs_days "
++   "days; possible purges happen at startup and at binary log rotation.",
++   (gptr*) &expire_logs_days,
++   (gptr*) &expire_logs_days, 0, GET_ULONG,
++   REQUIRED_ARG, 0, 0, 99, 0, 1, 0},
++  { "flush_time", OPT_FLUSH_TIME,
++    "A dedicated thread is created to flush all tables at the given interval.",
++    (gptr*) &flush_time, (gptr*) &flush_time, 0, GET_ULONG, REQUIRED_ARG,
++    FLUSH_TIME, 0, LONG_TIMEOUT, 0, 1, 0},
++  { "ft_boolean_syntax", OPT_FT_BOOLEAN_SYNTAX,
++    "List of operators for MATCH ... AGAINST ( ... IN BOOLEAN MODE)",
++    0, 0, 0, GET_STR,
++    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  { "ft_max_word_len", OPT_FT_MAX_WORD_LEN,
++    "The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.",
++    (gptr*) &ft_max_word_len, (gptr*) &ft_max_word_len, 0, GET_ULONG,
++    REQUIRED_ARG, HA_FT_MAXCHARLEN, 10, HA_FT_MAXCHARLEN, 0, 1, 0},
++  { "ft_min_word_len", OPT_FT_MIN_WORD_LEN,
++    "The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.",
++    (gptr*) &ft_min_word_len, (gptr*) &ft_min_word_len, 0, GET_ULONG,
++    REQUIRED_ARG, 4, 1, HA_FT_MAXCHARLEN, 0, 1, 0},
++  { "ft_query_expansion_limit", OPT_FT_QUERY_EXPANSION_LIMIT,
++    "Number of best matches to use for query expansion",
++    (gptr*) &ft_query_expansion_limit, (gptr*) &ft_query_expansion_limit, 0, GET_ULONG,
++    REQUIRED_ARG, 20, 0, 1000, 0, 1, 0},
++  { "ft_stopword_file", OPT_FT_STOPWORD_FILE,
++    "Use stopwords from this file instead of built-in list.",
++    (gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR,
++    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  { "group_concat_max_len", OPT_GROUP_CONCAT_MAX_LEN,
++    "The maximum length of the result of function  group_concat.",
++    (gptr*) &global_system_variables.group_concat_max_len,
++    (gptr*) &max_system_variables.group_concat_max_len, 0, GET_ULONG,
++    REQUIRED_ARG, 1024, 4, (long) ~0, 0, 1, 0},
++#ifdef HAVE_INNOBASE_DB
++  {"innodb_additional_mem_pool_size", OPT_INNODB_ADDITIONAL_MEM_POOL_SIZE,
++   "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
++   (gptr*) &innobase_additional_mem_pool_size,
++   (gptr*) &innobase_additional_mem_pool_size, 0, GET_LONG, REQUIRED_ARG,
++   1*1024*1024L, 512*1024L, ~0L, 0, 1024, 0},
++  {"innodb_autoextend_increment", OPT_INNODB_AUTOEXTEND_INCREMENT,
++   "Data file autoextend increment in megabytes",
++   (gptr*) &srv_auto_extend_increment,
++   (gptr*) &srv_auto_extend_increment,
++   0, GET_LONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0},
++  {"innodb_buffer_pool_awe_mem_mb", OPT_INNODB_BUFFER_POOL_AWE_MEM_MB,
++   "If Windows AWE is used, the size of InnoDB buffer pool allocated from the AWE memory.",
++   (gptr*) &innobase_buffer_pool_awe_mem_mb, (gptr*) &innobase_buffer_pool_awe_mem_mb, 0,
++   GET_LONG, REQUIRED_ARG, 0, 0, 63000, 0, 1, 0},
++  {"innodb_buffer_pool_size", OPT_INNODB_BUFFER_POOL_SIZE,
++   "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
++   (gptr*) &innobase_buffer_pool_size, (gptr*) &innobase_buffer_pool_size, 0,
++   GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 0,
++   1024*1024L, 0},
++  {"innodb_commit_concurrency", OPT_INNODB_COMMIT_CONCURRENCY,
++   "Helps in performance tuning in heavily concurrent environments.",
++   (gptr*) &srv_commit_concurrency, (gptr*) &srv_commit_concurrency,
++   0, GET_LONG, REQUIRED_ARG, 0, 0, 1000, 0, 1, 0},
++  {"innodb_concurrency_tickets", OPT_INNODB_CONCURRENCY_TICKETS,
++   "Number of times a thread is allowed to enter InnoDB within the same \
++    SQL query after it has once got the ticket",
++   (gptr*) &srv_n_free_tickets_to_enter,
++   (gptr*) &srv_n_free_tickets_to_enter,
++   0, GET_LONG, REQUIRED_ARG, 500L, 1L, ~0L, 0, 1L, 0},
++  {"innodb_file_io_threads", OPT_INNODB_FILE_IO_THREADS,
++   "Number of file I/O threads in InnoDB.", (gptr*) &innobase_file_io_threads,
++   (gptr*) &innobase_file_io_threads, 0, GET_LONG, REQUIRED_ARG, 4, 4, 64, 0,
++   1, 0},
++  {"innodb_force_recovery", OPT_INNODB_FORCE_RECOVERY,
++   "Helps to save your data in case the disk image of the database becomes corrupt.",
++   (gptr*) &innobase_force_recovery, (gptr*) &innobase_force_recovery, 0,
++   GET_LONG, REQUIRED_ARG, 0, 0, 6, 0, 1, 0},
++  {"innodb_lock_wait_timeout", OPT_INNODB_LOCK_WAIT_TIMEOUT,
++   "Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back.",
++   (gptr*) &innobase_lock_wait_timeout, (gptr*) &innobase_lock_wait_timeout,
++   0, GET_LONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
++  {"innodb_log_buffer_size", OPT_INNODB_LOG_BUFFER_SIZE,
++   "The size of the buffer which InnoDB uses to write log to the log files on disk.",
++   (gptr*) &innobase_log_buffer_size, (gptr*) &innobase_log_buffer_size, 0,
++   GET_LONG, REQUIRED_ARG, 1024*1024L, 256*1024L, ~0L, 0, 1024, 0},
++  {"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE,
++   "Size of each log file in a log group.",
++   (gptr*) &innobase_log_file_size, (gptr*) &innobase_log_file_size, 0,
++   GET_LL, REQUIRED_ARG, 5*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 0,
++   1024*1024L, 0},
++  {"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP,
++   "Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
++   (gptr*) &innobase_log_files_in_group, (gptr*) &innobase_log_files_in_group,
++   0, GET_LONG, REQUIRED_ARG, 2, 2, 100, 0, 1, 0},
++  {"innodb_mirrored_log_groups", OPT_INNODB_MIRRORED_LOG_GROUPS,
++   "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
++   (gptr*) &innobase_mirrored_log_groups,
++   (gptr*) &innobase_mirrored_log_groups, 0, GET_LONG, REQUIRED_ARG, 1, 1, 10,
++   0, 1, 0},
++  {"innodb_open_files", OPT_INNODB_OPEN_FILES,
++   "How many files at the maximum InnoDB keeps open at the same time.",
++   (gptr*) &innobase_open_files, (gptr*) &innobase_open_files, 0,
++   GET_LONG, REQUIRED_ARG, 300L, 10L, ~0L, 0, 1L, 0},
++  {"innodb_sync_spin_loops", OPT_INNODB_SYNC_SPIN_LOOPS,
++   "Count of spin-loop rounds in InnoDB mutexes",
++   (gptr*) &srv_n_spin_wait_rounds,
++   (gptr*) &srv_n_spin_wait_rounds,
++   0, GET_LONG, REQUIRED_ARG, 20L, 0L, ~0L, 0, 1L, 0},
++  {"innodb_thread_concurrency", OPT_INNODB_THREAD_CONCURRENCY,
++   "Helps in performance tuning in heavily concurrent environments. "
++   "Sets the maximum number of threads allowed inside InnoDB. Value 0"
++   " will disable the thread throttling.",
++   (gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency,
++   0, GET_LONG, REQUIRED_ARG, 8, 0, 1000, 0, 1, 0},
++  {"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY,
++   "Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0"
++    " disable a sleep",
++   (gptr*) &srv_thread_sleep_delay,
++   (gptr*) &srv_thread_sleep_delay,
++   0, GET_LONG, REQUIRED_ARG, 10000L, 0L, ~0L, 0, 1L, 0},
++#endif /* HAVE_INNOBASE_DB */
++  {"interactive_timeout", OPT_INTERACTIVE_TIMEOUT,
++   "The number of seconds the server waits for activity on an interactive connection before closing it.",
++   (gptr*) &global_system_variables.net_interactive_timeout,
++   (gptr*) &max_system_variables.net_interactive_timeout, 0,
++   GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
++  {"join_buffer_size", OPT_JOIN_BUFF_SIZE,
++   "The size of the buffer that is used for full joins.",
++   (gptr*) &global_system_variables.join_buff_size,
++   (gptr*) &max_system_variables.join_buff_size, 0, GET_ULONG,
++   REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD,
++   IO_SIZE, 0},
++  {"keep_files_on_create", OPT_KEEP_FILES_ON_CREATE,
++   "Don't overwrite stale .MYD and .MYI even if no directory is specified.",
++   (gptr*) &global_system_variables.keep_files_on_create,
++   (gptr*) &max_system_variables.keep_files_on_create,
++   0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
++  {"key_buffer_size", OPT_KEY_BUFFER_SIZE,
++   "The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
++   (gptr*) &dflt_key_cache_var.param_buff_size,
++   (gptr*) 0,
++   0, (GET_ULL | GET_ASK_ADDR),
++   REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, ~(ulong) 0, MALLOC_OVERHEAD,
++   IO_SIZE, 0},
++  {"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
++   "This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache",
++   (gptr*) &dflt_key_cache_var.param_age_threshold,
++   (gptr*) 0,
++   0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG,
++   300, 100, ~0L, 0, 100, 0},
++  {"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE,
++   "The default size of key cache blocks",
++   (gptr*) &dflt_key_cache_var.param_block_size,
++   (gptr*) 0,
++   0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG,
++   KEY_CACHE_BLOCK_SIZE, 512, 1024 * 16, 0, 512, 0},
++  {"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT,
++   "The minimum percentage of warm blocks in key cache",
++   (gptr*) &dflt_key_cache_var.param_division_limit,
++   (gptr*) 0,
++   0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
++   1, 100, 0, 1, 0},
++  {"long_query_time", OPT_LONG_QUERY_TIME,
++   "Log all queries that have taken more than long_query_time seconds to execute to file.",
++   (gptr*) &global_system_variables.long_query_time,
++   (gptr*) &max_system_variables.long_query_time, 0, GET_ULONG,
++   REQUIRED_ARG, 10, 1, LONG_TIMEOUT, 0, 1, 0},
++  {"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES,
++   "If set to 1 table names are stored in lowercase on disk and table names will be case-insensitive.  Should be set to 2 if you are using a case insensitive file system",
++   (gptr*) &lower_case_table_names,
++   (gptr*) &lower_case_table_names, 0, GET_UINT, OPT_ARG,
++#ifdef FN_NO_CASE_SENCE
++    1
++#else
++    0
++#endif
++   , 0, 2, 0, 1, 0},
++  {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
++   "Max packetlength to send/receive from to server.",
++   (gptr*) &global_system_variables.max_allowed_packet,
++   (gptr*) &max_system_variables.max_allowed_packet, 0, GET_ULONG,
++   REQUIRED_ARG, 1024*1024L, 1024, 1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
++  {"max_binlog_cache_size", OPT_MAX_BINLOG_CACHE_SIZE,
++   "Can be used to restrict the total size used to cache a multi-transaction query.",
++   (gptr*) &max_binlog_cache_size, (gptr*) &max_binlog_cache_size, 0,
++   GET_ULONG, REQUIRED_ARG, ~0L, IO_SIZE, ~0L, 0, IO_SIZE, 0},
++  {"max_binlog_size", OPT_MAX_BINLOG_SIZE,
++   "Binary log will be rotated automatically when the size exceeds this \
++value. Will also apply to relay logs if max_relay_log_size is 0. \
++The minimum value for this variable is 4096.",
++   (gptr*) &max_binlog_size, (gptr*) &max_binlog_size, 0, GET_ULONG,
++   REQUIRED_ARG, 1024*1024L*1024L, IO_SIZE, 1024*1024L*1024L, 0, IO_SIZE, 0},
++  {"max_connect_errors", OPT_MAX_CONNECT_ERRORS,
++   "If there is more than this number of interrupted connections from a host this host will be blocked from further connections.",
++   (gptr*) &max_connect_errors, (gptr*) &max_connect_errors, 0, GET_ULONG,
++    REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ~0L, 0, 1, 0},
++  {"max_connections", OPT_MAX_CONNECTIONS,
++   "The number of simultaneous clients allowed.", (gptr*) &max_connections,
++   (gptr*) &max_connections, 0, GET_ULONG, REQUIRED_ARG, 100, 1, 16384, 0, 1,
++   0},
++  {"max_delayed_threads", OPT_MAX_DELAYED_THREADS,
++   "Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero, which means INSERT DELAYED is not used.",
++   (gptr*) &global_system_variables.max_insert_delayed_threads,
++   (gptr*) &max_system_variables.max_insert_delayed_threads,
++   0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0},
++  {"max_error_count", OPT_MAX_ERROR_COUNT,
++   "Max number of errors/warnings to store for a statement.",
++   (gptr*) &global_system_variables.max_error_count,
++   (gptr*) &max_system_variables.max_error_count,
++   0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 0, 65535, 0, 1, 0},
++  {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
++   "Don't allow creation of heap tables bigger than this.",
++   (gptr*) &global_system_variables.max_heap_table_size,
++   (gptr*) &max_system_variables.max_heap_table_size, 0, GET_ULL,
++   REQUIRED_ARG, 16*1024*1024L, 16384, MAX_MEM_TABLE_SIZE,
++   MALLOC_OVERHEAD, 1024, 0},
++  {"max_join_size", OPT_MAX_JOIN_SIZE,
++   "Joins that are probably going to read more than max_join_size records return an error.",
++   (gptr*) &global_system_variables.max_join_size,
++   (gptr*) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG,
++   ~0L, 1, ~0L, 0, 1, 0},
++   {"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA,
++    "Max number of bytes in sorted records.",
++    (gptr*) &global_system_variables.max_length_for_sort_data,
++    (gptr*) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG,
++    REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
++  {"max_prepared_stmt_count", OPT_MAX_PREPARED_STMT_COUNT,
++   "Maximum number of prepared statements in the server.",
++   (gptr*) &max_prepared_stmt_count, (gptr*) &max_prepared_stmt_count,
++   0, GET_ULONG, REQUIRED_ARG, 16382, 0, 1*1024*1024, 0, 1, 0},
++  {"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE,
++   "If non-zero: relay log will be rotated automatically when the size exceeds this value; if zero (the default): when the size exceeds max_binlog_size. 0 excepted, the minimum value for this variable is 4096.",
++   (gptr*) &max_relay_log_size, (gptr*) &max_relay_log_size, 0, GET_ULONG,
++   REQUIRED_ARG, 0L, 0L, 1024*1024L*1024L, 0, IO_SIZE, 0},
++  { "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY,
++    "Limit assumed max number of seeks when looking up rows based on a key",
++    (gptr*) &global_system_variables.max_seeks_for_key,
++    (gptr*) &max_system_variables.max_seeks_for_key, 0, GET_ULONG,
++    REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0 },
++  {"max_sort_length", OPT_MAX_SORT_LENGTH,
++   "The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored).",
++   (gptr*) &global_system_variables.max_sort_length,
++   (gptr*) &max_system_variables.max_sort_length, 0, GET_ULONG,
++   REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0},
++  {"max_sp_recursion_depth", OPT_MAX_SP_RECURSION_DEPTH,
++   "Maximum stored procedure recursion depth. (discussed with docs).",
++   (gptr*) &global_system_variables.max_sp_recursion_depth,
++   (gptr*) &max_system_variables.max_sp_recursion_depth, 0, GET_ULONG,
++   OPT_ARG, 0, 0, 255, 0, 1, 0 },
++  {"max_tmp_tables", OPT_MAX_TMP_TABLES,
++   "Maximum number of temporary tables a client can keep open at a time.",
++   (gptr*) &global_system_variables.max_tmp_tables,
++   (gptr*) &max_system_variables.max_tmp_tables, 0, GET_ULONG,
++   REQUIRED_ARG, 32, 1, ~0L, 0, 1, 0},
++  {"max_user_connections", OPT_MAX_USER_CONNECTIONS,
++   "The maximum number of active connections for a single user (0 = no limit).",
++   (gptr*) &max_user_connections, (gptr*) &max_user_connections, 0, GET_UINT,
++   REQUIRED_ARG, 0, 1, ~0, 0, 1, 0},
++  {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT,
++   "After this many write locks, allow some read locks to run in between.",
++   (gptr*) &max_write_lock_count, (gptr*) &max_write_lock_count, 0, GET_ULONG,
++   REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0},
++  {"multi_range_count", OPT_MULTI_RANGE_COUNT,
++   "Number of key ranges to request at once.",
++   (gptr*) &global_system_variables.multi_range_count,
++   (gptr*) &max_system_variables.multi_range_count, 0,
++   GET_ULONG, REQUIRED_ARG, 256, 1, ~0L, 0, 1, 0},
++  {"myisam_block_size", OPT_MYISAM_BLOCK_SIZE,
++   "Block size to be used for MyISAM index pages.",
++   (gptr*) &opt_myisam_block_size,
++   (gptr*) &opt_myisam_block_size, 0, GET_ULONG, REQUIRED_ARG,
++   MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH,
++   0, MI_MIN_KEY_BLOCK_LENGTH, 0},
++  {"myisam_data_pointer_size", OPT_MYISAM_DATA_POINTER_SIZE,
++   "Default pointer size to be used for MyISAM tables.",
++   (gptr*) &myisam_data_pointer_size,
++   (gptr*) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG,
++   6, 2, 7, 0, 1, 0},
++  {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
++   "Deprecated option",
++   (gptr*) &global_system_variables.myisam_max_extra_sort_file_size,
++   (gptr*) &max_system_variables.myisam_max_extra_sort_file_size,
++   0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH,
++   0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0},
++  {"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE,
++   "Don't use the fast sort index method to created index if the temporary file would get bigger than this.",
++   (gptr*) &global_system_variables.myisam_max_sort_file_size,
++   (gptr*) &max_system_variables.myisam_max_sort_file_size, 0,
++   GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE,
++   0, 1024*1024, 0},
++  {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS,
++   "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.",
++   (gptr*) &global_system_variables.myisam_repair_threads,
++   (gptr*) &max_system_variables.myisam_repair_threads, 0,
++   GET_ULONG, REQUIRED_ARG, 1, 1, ~0L, 0, 1, 0},
++  {"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE,
++   "The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.",
++   (gptr*) &global_system_variables.myisam_sort_buff_size,
++   (gptr*) &max_system_variables.myisam_sort_buff_size, 0,
++   GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0},
++  {"myisam_stats_method", OPT_MYISAM_STATS_METHOD,
++   "Specifies how MyISAM index statistics collection code should threat NULLs. "
++   "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), "
++   "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".",
++   (gptr*) &myisam_stats_method_str, (gptr*) &myisam_stats_method_str, 0,
++    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"net_buffer_length", OPT_NET_BUFFER_LENGTH,
++   "Buffer length for TCP/IP and socket communication.",
++   (gptr*) &global_system_variables.net_buffer_length,
++   (gptr*) &max_system_variables.net_buffer_length, 0, GET_ULONG,
++   REQUIRED_ARG, 16384, 1024, 1024*1024L, 0, 1024, 0},
++  {"net_read_timeout", OPT_NET_READ_TIMEOUT,
++   "Number of seconds to wait for more data from a connection before aborting the read.",
++   (gptr*) &global_system_variables.net_read_timeout,
++   (gptr*) &max_system_variables.net_read_timeout, 0, GET_ULONG,
++   REQUIRED_ARG, NET_READ_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
++  {"net_retry_count", OPT_NET_RETRY_COUNT,
++   "If a read on a communication port is interrupted, retry this many times before giving up.",
++   (gptr*) &global_system_variables.net_retry_count,
++   (gptr*) &max_system_variables.net_retry_count,0,
++   GET_ULONG, REQUIRED_ARG, MYSQLD_NET_RETRY_COUNT, 1, ~0L, 0, 1, 0},
++  {"net_write_timeout", OPT_NET_WRITE_TIMEOUT,
++   "Number of seconds to wait for a block to be written to a connection  before aborting the write.",
++   (gptr*) &global_system_variables.net_write_timeout,
++   (gptr*) &max_system_variables.net_write_timeout, 0, GET_ULONG,
++   REQUIRED_ARG, NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
++  {"open_files_limit", OPT_OPEN_FILES_LIMIT,
++   "If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.",
++   (gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG,
++   REQUIRED_ARG, 0, 0, OS_FILE_LIMIT, 0, 1, 0},
++  {"optimizer_prune_level", OPT_OPTIMIZER_PRUNE_LEVEL,
++   "Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows.",
++   (gptr*) &global_system_variables.optimizer_prune_level,
++   (gptr*) &max_system_variables.optimizer_prune_level,
++   0, GET_ULONG, OPT_ARG, 1, 0, 1, 0, 1, 0},
++  {"optimizer_search_depth", OPT_OPTIMIZER_SEARCH_DEPTH,
++   "Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Smaller values than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value; if set to MAX_TABLES+2, the optimizer will switch to the original find_best (used for testing/comparison).",
++   (gptr*) &global_system_variables.optimizer_search_depth,
++   (gptr*) &max_system_variables.optimizer_search_depth,
++   0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0},
++   {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
++    "The size of the buffer that is allocated when preloading indexes",
++    (gptr*) &global_system_variables.preload_buff_size,
++    (gptr*) &max_system_variables.preload_buff_size, 0, GET_ULONG,
++    REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0},
++  {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE,
++   "Allocation block size for query parsing and execution",
++   (gptr*) &global_system_variables.query_alloc_block_size,
++   (gptr*) &max_system_variables.query_alloc_block_size, 0, GET_ULONG,
++   REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
++#ifdef HAVE_QUERY_CACHE
++  {"query_cache_limit", OPT_QUERY_CACHE_LIMIT,
++   "Don't cache results that are bigger than this.",
++   (gptr*) &query_cache_limit, (gptr*) &query_cache_limit, 0, GET_ULONG,
++   REQUIRED_ARG, 1024*1024L, 0, (longlong) ULONG_MAX, 0, 1, 0},
++  {"query_cache_min_res_unit", OPT_QUERY_CACHE_MIN_RES_UNIT,
++   "minimal size of unit in wich space for results is allocated (last unit will be trimed after writing all result data.",
++   (gptr*) &query_cache_min_res_unit, (gptr*) &query_cache_min_res_unit,
++   0, GET_ULONG, REQUIRED_ARG, QUERY_CACHE_MIN_RESULT_DATA_SIZE,
++   0, (longlong) ULONG_MAX, 0, 1, 0},
++#endif /*HAVE_QUERY_CACHE*/
++  {"query_cache_size", OPT_QUERY_CACHE_SIZE,
++   "The memory allocated to store results from old queries.",
++   (gptr*) &query_cache_size, (gptr*) &query_cache_size, 0, GET_ULONG,
++   REQUIRED_ARG, 0, 0, (longlong) ULONG_MAX, 0, 1024, 0},
++#ifdef HAVE_QUERY_CACHE
++  {"query_cache_type", OPT_QUERY_CACHE_TYPE,
++   "0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT SQL_CACHE ... queries.",
++   (gptr*) &global_system_variables.query_cache_type,
++   (gptr*) &max_system_variables.query_cache_type,
++   0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0},
++  {"query_cache_wlock_invalidate", OPT_QUERY_CACHE_WLOCK_INVALIDATE,
++   "Invalidate queries in query cache on LOCK for write",
++   (gptr*) &global_system_variables.query_cache_wlock_invalidate,
++   (gptr*) &max_system_variables.query_cache_wlock_invalidate,
++   0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
++#endif /*HAVE_QUERY_CACHE*/
++  {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE,
++   "Persistent buffer for query parsing and execution",
++   (gptr*) &global_system_variables.query_prealloc_size,
++   (gptr*) &max_system_variables.query_prealloc_size, 0, GET_ULONG,
++   REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE,
++   ~0L, 0, 1024, 0},
++  {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE,
++   "Allocation block size for storing ranges during optimization",
++   (gptr*) &global_system_variables.range_alloc_block_size,
++   (gptr*) &max_system_variables.range_alloc_block_size, 0, GET_ULONG,
++   REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 4096, ~0L, 0, 1024, 0},
++  {"read_buffer_size", OPT_RECORD_BUFFER,
++   "Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.",
++   (gptr*) &global_system_variables.read_buff_size,
++   (gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
++   128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, SSIZE_MAX, MALLOC_OVERHEAD, IO_SIZE,
++   0},
++  {"read_only", OPT_READONLY,
++   "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},
++  {"read_rnd_buffer_size", OPT_RECORD_RND_BUFFER,
++   "When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks. If not set, then it's set to the value of record_buffer.",
++   (gptr*) &global_system_variables.read_rnd_buff_size,
++   (gptr*) &max_system_variables.read_rnd_buff_size, 0,
++   GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD,
++   SSIZE_MAX, MALLOC_OVERHEAD, IO_SIZE, 0},
++  {"record_buffer", OPT_RECORD_BUFFER,
++   "Alias for read_buffer_size",
++   (gptr*) &global_system_variables.read_buff_size,
++   (gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
++   128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, SSIZE_MAX, MALLOC_OVERHEAD, IO_SIZE, 0},
++#ifdef HAVE_REPLICATION
++  {"relay_log_purge", OPT_RELAY_LOG_PURGE,
++   "0 = do not purge relay logs. 1 = purge them as soon as they are no more needed.",
++   (gptr*) &relay_log_purge,
++   (gptr*) &relay_log_purge, 0, GET_BOOL, NO_ARG,
++   1, 0, 1, 0, 1, 0},
++  {"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT,
++   "Maximum space to use for all relay logs.",
++   (gptr*) &relay_log_space_limit,
++   (gptr*) &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L,
++   (longlong) ULONG_MAX, 0, 1, 0},
++  {"slave_compressed_protocol", OPT_SLAVE_COMPRESSED_PROTOCOL,
++   "Use compression on master/slave protocol.",
++   (gptr*) &opt_slave_compressed_protocol,
++   (gptr*) &opt_slave_compressed_protocol,
++   0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
++  {"slave_net_timeout", OPT_SLAVE_NET_TIMEOUT,
++   "Number of seconds to wait for more data from a master/slave connection before aborting the read.",
++   (gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0,
++   GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
++  {"slave_transaction_retries", OPT_SLAVE_TRANS_RETRIES,
++   "Number of times the slave SQL thread will retry a transaction in case "
++   "it failed with a deadlock or elapsed lock wait timeout, "
++   "before giving up and stopping.",
++   (gptr*) &slave_trans_retries, (gptr*) &slave_trans_retries, 0,
++   GET_ULONG, REQUIRED_ARG, 10L, 0L, (longlong) ULONG_MAX, 0, 1, 0},
++#endif /* HAVE_REPLICATION */
++  {"slow_launch_time", OPT_SLOW_LAUNCH_TIME,
++   "If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.",
++   (gptr*) &slow_launch_time, (gptr*) &slow_launch_time, 0, GET_ULONG,
++   REQUIRED_ARG, 2L, 0L, LONG_TIMEOUT, 0, 1, 0},
++  {"sort_buffer_size", OPT_SORT_BUFFER,
++   "Each thread that needs to do a sort allocates a buffer of this size.",
++   (gptr*) &global_system_variables.sortbuff_size,
++   (gptr*) &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG,
++   MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD,
++   1, 0},
++#ifdef HAVE_BERKELEY_DB
++  {"sync-bdb-logs", OPT_BDB_SYNC,
++   "Synchronously flush Berkeley DB logs. Enabled by default",
++   (gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL,
++   NO_ARG, 1, 0, 0, 0, 0, 0},
++#endif /* HAVE_BERKELEY_DB */
++  {"sync-binlog", OPT_SYNC_BINLOG,
++   "Synchronously flush binary log to disk after every #th event. "
++   "Use 0 (default) to disable synchronous flushing.",
++   (gptr*) &sync_binlog_period, (gptr*) &sync_binlog_period, 0, GET_ULONG,
++   REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0},
++  {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.",
++   (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0,
++   0, 0, 0, 0},
++  {"table_cache", OPT_TABLE_CACHE,
++   "The number of open tables for all threads.", (gptr*) &table_cache_size,
++   (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG,
++   TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
++  {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT, "Timeout in "
++    "seconds to wait for a table level lock before returning an error. Used"
++     " only if the connection has active cursors.",
++   (gptr*) &table_lock_wait_timeout, (gptr*) &table_lock_wait_timeout,
++   0, GET_ULONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
++  {"thread_cache_size", OPT_THREAD_CACHE_SIZE,
++   "How many threads we should keep in a cache for reuse.",
++   (gptr*) &thread_cache_size, (gptr*) &thread_cache_size, 0, GET_ULONG,
++   REQUIRED_ARG, 0, 0, 16384, 0, 1, 0},
++  {"thread_concurrency", OPT_THREAD_CONCURRENCY,
++   "Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.",
++   (gptr*) &concurrency, (gptr*) &concurrency, 0, GET_ULONG, REQUIRED_ARG,
++   DEFAULT_CONCURRENCY, 1, 512, 0, 1, 0},
++  {"thread_stack", OPT_THREAD_STACK,
++   "The stack size for each thread.", (gptr*) &thread_stack,
++   (gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK,
++   1024L*128L, ~0L, 0, 1024, 0},
++  { "time_format", OPT_TIME_FORMAT,
++    "The TIME format (for future).",
++    (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME],
++    (gptr*) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME],
++    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"tmp_table_size", OPT_TMP_TABLE_SIZE,
++   "If an internal in-memory temporary table exceeds this size, MySQL will"
++   " automatically convert it to an on-disk MyISAM table.",
++   (gptr*) &global_system_variables.tmp_table_size,
++   (gptr*) &max_system_variables.tmp_table_size, 0, GET_ULL,
++   REQUIRED_ARG, 32*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0},
++  {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE,
++   "Allocation block size for various transaction-related structures",
++   (gptr*) &global_system_variables.trans_alloc_block_size,
++   (gptr*) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG,
++   REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
++  {"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE,
++   "Persistent buffer for various transaction-related structures",
++   (gptr*) &global_system_variables.trans_prealloc_size,
++   (gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG,
++   REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
++  {"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT,
++   "1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a key of the underlying table is used in queries with a LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which does not contain a key of the underlying table and the query uses a LIMIT clause (usually get from GUI tools).",
++   (gptr*) &global_system_variables.updatable_views_with_limit,
++   (gptr*) &max_system_variables.updatable_views_with_limit,
++   0, GET_ULONG, REQUIRED_ARG, 1, 0, 1, 0, 1, 0},
++  {"wait_timeout", OPT_WAIT_TIMEOUT,
++   "The number of seconds the server waits for activity on a connection before closing it.",
++   (gptr*) &global_system_variables.net_wait_timeout,
++   (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG,
++   REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT),
++   0, 1, 0},
++  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
++};
++
++
++/*
++  Variables shown by SHOW STATUS in alphabetical order
++*/
++
++struct show_var_st status_vars[]= {
++  {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONG},
++  {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONG},
++  {"Binlog_cache_disk_use",    (char*) &binlog_cache_disk_use,  SHOW_LONG},
++  {"Binlog_cache_use",         (char*) &binlog_cache_use,       SHOW_LONG},
++  {"Bytes_received",           (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
++  {"Bytes_sent",               (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
++  {"Com_admin_commands",       (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS},
++  {"Com_alter_db",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS},
++  {"Com_alter_table",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS},
++  {"Com_analyze",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]), SHOW_LONG_STATUS},
++  {"Com_backup_table",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BACKUP_TABLE]), SHOW_LONG_STATUS},
++  {"Com_begin",		       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]), SHOW_LONG_STATUS},
++  {"Com_call_procedure",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CALL]), SHOW_LONG_STATUS},
++  {"Com_change_db",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS},
++  {"Com_change_master",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_MASTER]), SHOW_LONG_STATUS},
++  {"Com_check",		       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECK]), SHOW_LONG_STATUS},
++  {"Com_checksum",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS},
++  {"Com_commit",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMMIT]), SHOW_LONG_STATUS},
++  {"Com_create_db",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS},
++  {"Com_create_function",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS},
++  {"Com_create_index",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS},
++  {"Com_create_table",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS},
++  {"Com_create_user",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_USER]), SHOW_LONG_STATUS},
++  {"Com_dealloc_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS},
++  {"Com_delete",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS},
++  {"Com_delete_multi",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS},
++  {"Com_do",                   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DO]), SHOW_LONG_STATUS},
++  {"Com_drop_db",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_DB]), SHOW_LONG_STATUS},
++  {"Com_drop_function",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]), SHOW_LONG_STATUS},
++  {"Com_drop_index",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS},
++  {"Com_drop_table",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS},
++  {"Com_drop_user",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS},
++  {"Com_execute_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS},
++  {"Com_flush",		       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
++  {"Com_grant",		       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},
++  {"Com_ha_close",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS},
++  {"Com_ha_open",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS},
++  {"Com_ha_read",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]), SHOW_LONG_STATUS},
++  {"Com_help",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HELP]), SHOW_LONG_STATUS},
++  {"Com_insert",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT]), SHOW_LONG_STATUS},
++  {"Com_insert_select",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS},
++  {"Com_kill",		       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]), SHOW_LONG_STATUS},
++  {"Com_load",		       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]), SHOW_LONG_STATUS},
++  {"Com_load_master_data",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_DATA]), SHOW_LONG_STATUS},
++  {"Com_load_master_table",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_TABLE]), SHOW_LONG_STATUS},
++  {"Com_lock_tables",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]), SHOW_LONG_STATUS},
++  {"Com_optimize",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]), SHOW_LONG_STATUS},
++  {"Com_preload_keys",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]), SHOW_LONG_STATUS},
++  {"Com_prepare_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PREPARE]), SHOW_LONG_STATUS},
++  {"Com_purge",		       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE]), SHOW_LONG_STATUS},
++  {"Com_purge_before_date",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE_BEFORE]), SHOW_LONG_STATUS},
++  {"Com_rename_table",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS},
++  {"Com_repair",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPAIR]), SHOW_LONG_STATUS},
++  {"Com_replace",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]), SHOW_LONG_STATUS},
++  {"Com_replace_select",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS},
++  {"Com_reset",		       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS},
++  {"Com_restore_table",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESTORE_TABLE]), SHOW_LONG_STATUS},
++  {"Com_revoke",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS},
++  {"Com_revoke_all",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS},
++  {"Com_rollback",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS},
++  {"Com_savepoint",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS},
++  {"Com_select",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]), SHOW_LONG_STATUS},
++  {"Com_set_option",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS},
++  {"Com_show_binlog_events",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS},
++  {"Com_show_binlogs",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS},
++  {"Com_show_charsets",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS},
++  {"Com_show_collations",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS},
++  {"Com_show_column_types",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLUMN_TYPES]), SHOW_LONG_STATUS},
++  {"Com_show_create_db",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS},
++  {"Com_show_create_table",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS},
++  {"Com_show_databases",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS},
++  {"Com_show_errors",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
++  {"Com_show_fields",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS},
++  {"Com_show_grants",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
++  {"Com_show_innodb_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INNODB_STATUS]), SHOW_LONG_STATUS},
++  {"Com_show_keys",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
++  {"Com_show_logs",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_LOGS]), SHOW_LONG_STATUS},
++  {"Com_show_master_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
++  {"Com_show_ndb_status",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NDBCLUSTER_STATUS]), SHOW_LONG_STATUS},
++  {"Com_show_new_master",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS},
++  {"Com_show_open_tables",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
++  {"Com_show_privileges",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS},
++  {"Com_show_processlist",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS},
++  {"Com_show_slave_hosts",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS},
++  {"Com_show_slave_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
++  {"Com_show_status",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
++  {"Com_show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
++  {"Com_show_tables",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS},
++  {"Com_show_triggers",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS},
++  {"Com_show_variables",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
++  {"Com_show_warnings",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
++  {"Com_slave_start",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
++  {"Com_slave_stop",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS},
++  {"Com_stmt_close",           (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS},
++  {"Com_stmt_execute",         (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS},
++  {"Com_stmt_fetch",           (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS},
++  {"Com_stmt_prepare",         (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS},
++  {"Com_stmt_reset",           (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS},
++  {"Com_stmt_send_long_data",  (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS},
++  {"Com_truncate",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
++  {"Com_unlock_tables",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS},
++  {"Com_update",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]), SHOW_LONG_STATUS},
++  {"Com_update_multi",	       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE_MULTI]), SHOW_LONG_STATUS},
++  {"Com_xa_commit",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_COMMIT]),SHOW_LONG_STATUS},
++  {"Com_xa_end",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_END]),SHOW_LONG_STATUS},
++  {"Com_xa_prepare",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_PREPARE]),SHOW_LONG_STATUS},
++  {"Com_xa_recover",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),SHOW_LONG_STATUS},
++  {"Com_xa_rollback",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS},
++  {"Com_xa_start",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS},
++  {"Compression",              (char*) 0,                        SHOW_NET_COMPRESSION},
++  {"Connections",              (char*) &thread_id,              SHOW_LONG_CONST},
++  {"Created_tmp_disk_tables",  (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS},
++  {"Created_tmp_files",	       (char*) &my_tmp_file_created,	SHOW_LONG},
++  {"Created_tmp_tables",       (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS},
++  {"Delayed_errors",           (char*) &delayed_insert_errors,  SHOW_LONG},
++  {"Delayed_insert_threads",   (char*) &delayed_insert_threads, SHOW_LONG_CONST},
++  {"Delayed_writes",           (char*) &delayed_insert_writes,  SHOW_LONG},
++  {"Flush_commands",           (char*) &refresh_version,        SHOW_LONG_CONST},
++  {"Handler_commit",           (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
++  {"Handler_delete",           (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
++  {"Handler_discover",         (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS},
++  {"Handler_prepare",          (char*) offsetof(STATUS_VAR, ha_prepare_count),  SHOW_LONG_STATUS},
++  {"Handler_read_first",       (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONG_STATUS},
++  {"Handler_read_key",         (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONG_STATUS},
++  {"Handler_read_next",        (char*) offsetof(STATUS_VAR, ha_read_next_count), SHOW_LONG_STATUS},
++  {"Handler_read_prev",        (char*) offsetof(STATUS_VAR, ha_read_prev_count), SHOW_LONG_STATUS},
++  {"Handler_read_rnd",         (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONG_STATUS},
++  {"Handler_read_rnd_next",    (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count), SHOW_LONG_STATUS},
++  {"Handler_rollback",         (char*) offsetof(STATUS_VAR, ha_rollback_count), SHOW_LONG_STATUS},
++  {"Handler_savepoint",        (char*) offsetof(STATUS_VAR, ha_savepoint_count), SHOW_LONG_STATUS},
++  {"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONG_STATUS},
++  {"Handler_update",           (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
++  {"Handler_write",            (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
++#ifdef HAVE_INNOBASE_DB
++  {"Innodb_",                  (char*) &innodb_status_variables, SHOW_VARS},
++#endif /*HAVE_INNOBASE_DB*/
++  {"Key_blocks_not_flushed",   (char*) &dflt_key_cache_var.global_blocks_changed, SHOW_KEY_CACHE_LONG},
++  {"Key_blocks_unused",        (char*) &dflt_key_cache_var.blocks_unused, SHOW_KEY_CACHE_CONST_LONG},
++  {"Key_blocks_used",          (char*) &dflt_key_cache_var.blocks_used, SHOW_KEY_CACHE_CONST_LONG},
++  {"Key_read_requests",        (char*) &dflt_key_cache_var.global_cache_r_requests, SHOW_KEY_CACHE_LONGLONG},
++  {"Key_reads",                (char*) &dflt_key_cache_var.global_cache_read, SHOW_KEY_CACHE_LONGLONG},
++  {"Key_write_requests",       (char*) &dflt_key_cache_var.global_cache_w_requests, SHOW_KEY_CACHE_LONGLONG},
++  {"Key_writes",               (char*) &dflt_key_cache_var.global_cache_write, SHOW_KEY_CACHE_LONGLONG},
++  {"Last_query_cost",          (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
++  {"Max_used_connections",     (char*) &max_used_connections,  SHOW_LONG},
++#ifdef HAVE_NDBCLUSTER_DB
++  {"Ndb_",                     (char*) &ndb_status_variables,   SHOW_VARS},
++#endif /*HAVE_NDBCLUSTER_DB*/
++  {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use,    SHOW_LONG_CONST},
++  {"Open_files",               (char*) &my_file_opened,         SHOW_LONG_CONST},
++  {"Open_streams",             (char*) &my_stream_opened,       SHOW_LONG_CONST},
++  {"Open_tables",              (char*) 0,                       SHOW_OPENTABLES},
++  {"Opened_tables",            (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
++  {"Prepared_stmt_count",      (char*) &prepared_stmt_count,    SHOW_LONG_CONST},
++#ifdef HAVE_QUERY_CACHE
++  {"Qcache_free_blocks",       (char*) &query_cache.free_memory_blocks, SHOW_LONG_CONST},
++  {"Qcache_free_memory",       (char*) &query_cache.free_memory, SHOW_LONG_CONST},
++  {"Qcache_hits",              (char*) &query_cache.hits,       SHOW_LONG},
++  {"Qcache_inserts",           (char*) &query_cache.inserts,    SHOW_LONG},
++  {"Qcache_lowmem_prunes",     (char*) &query_cache.lowmem_prunes, SHOW_LONG},
++  {"Qcache_not_cached",        (char*) &query_cache.refused,    SHOW_LONG},
++  {"Qcache_queries_in_cache",  (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST},
++  {"Qcache_total_blocks",      (char*) &query_cache.total_blocks, SHOW_LONG_CONST},
++#endif /*HAVE_QUERY_CACHE*/
++  {"Questions",                (char*) 0,                       SHOW_QUESTION},
++  {"Rpl_status",               (char*) 0,                 SHOW_RPL_STATUS},
++  {"Select_full_join",         (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONG_STATUS},
++  {"Select_full_range_join",   (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONG_STATUS},
++  {"Select_range",             (char*) offsetof(STATUS_VAR, select_range_count), SHOW_LONG_STATUS},
++  {"Select_range_check",       (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONG_STATUS},
++  {"Select_scan",	       (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONG_STATUS},
++  {"Slave_open_temp_tables",   (char*) &slave_open_temp_tables, SHOW_LONG},
++  {"Slave_retried_transactions",(char*) 0,                      SHOW_SLAVE_RETRIED_TRANS},
++  {"Slave_running",            (char*) 0,                       SHOW_SLAVE_RUNNING},
++  {"Slow_launch_threads",      (char*) &slow_launch_threads,    SHOW_LONG},
++  {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS},
++  {"Sort_merge_passes",	       (char*) offsetof(STATUS_VAR, filesort_merge_passes), SHOW_LONG_STATUS},
++  {"Sort_range",	       (char*) offsetof(STATUS_VAR, filesort_range_count), SHOW_LONG_STATUS},
++  {"Sort_rows",		       (char*) offsetof(STATUS_VAR, filesort_rows), SHOW_LONG_STATUS},
++  {"Sort_scan",		       (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONG_STATUS},
++#ifdef HAVE_OPENSSL
++  {"Ssl_accept_renegotiates",  (char*) 0, 	SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE},
++  {"Ssl_accepts",              (char*) 0,  	SHOW_SSL_CTX_SESS_ACCEPT},
++  {"Ssl_callback_cache_hits",  (char*) 0,	SHOW_SSL_CTX_SESS_CB_HITS},
++  {"Ssl_cipher",               (char*) 0,  	SHOW_SSL_GET_CIPHER},
++  {"Ssl_cipher_list",          (char*) 0,  	SHOW_SSL_GET_CIPHER_LIST},
++  {"Ssl_client_connects",      (char*) 0,	SHOW_SSL_CTX_SESS_CONNECT},
++  {"Ssl_connect_renegotiates", (char*) 0, 	SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE},
++  {"Ssl_ctx_verify_depth",     (char*) 0,	SHOW_SSL_CTX_GET_VERIFY_DEPTH},
++  {"Ssl_ctx_verify_mode",      (char*) 0,	SHOW_SSL_CTX_GET_VERIFY_MODE},
++  {"Ssl_default_timeout",      (char*) 0,  	SHOW_SSL_GET_DEFAULT_TIMEOUT},
++  {"Ssl_finished_accepts",     (char*) 0,  	SHOW_SSL_CTX_SESS_ACCEPT_GOOD},
++  {"Ssl_finished_connects",    (char*) 0,  	SHOW_SSL_CTX_SESS_CONNECT_GOOD},
++  {"Ssl_session_cache_hits",   (char*) 0,	SHOW_SSL_CTX_SESS_HITS},
++  {"Ssl_session_cache_misses", (char*) 0,	SHOW_SSL_CTX_SESS_MISSES},
++  {"Ssl_session_cache_mode",   (char*) 0,	SHOW_SSL_CTX_GET_SESSION_CACHE_MODE},
++  {"Ssl_session_cache_overflows", (char*) 0,	SHOW_SSL_CTX_SESS_CACHE_FULL},
++  {"Ssl_session_cache_size",   (char*) 0,	SHOW_SSL_CTX_SESS_GET_CACHE_SIZE},
++  {"Ssl_session_cache_timeouts", (char*) 0,	SHOW_SSL_CTX_SESS_TIMEOUTS},
++  {"Ssl_sessions_reused",      (char*) 0,	SHOW_SSL_SESSION_REUSED},
++  {"Ssl_used_session_cache_entries",(char*) 0,	SHOW_SSL_CTX_SESS_NUMBER},
++  {"Ssl_verify_depth",         (char*) 0,	SHOW_SSL_GET_VERIFY_DEPTH},
++  {"Ssl_verify_mode",          (char*) 0,	SHOW_SSL_GET_VERIFY_MODE},
++  {"Ssl_version",   	       (char*) 0,  	SHOW_SSL_GET_VERSION},
++#endif /* HAVE_OPENSSL */
++  {"Table_locks_immediate",    (char*) &locks_immediate,        SHOW_LONG},
++  {"Table_locks_waited",       (char*) &locks_waited,           SHOW_LONG},
++#ifdef HAVE_MMAP
++  {"Tc_log_max_pages_used",    (char*) &tc_log_max_pages_used,  SHOW_LONG},
++  {"Tc_log_page_size",         (char*) &tc_log_page_size,       SHOW_LONG},
++  {"Tc_log_page_waits",        (char*) &tc_log_page_waits,      SHOW_LONG},
++#endif
++  {"Threads_cached",           (char*) &cached_thread_count,    SHOW_LONG_CONST},
++  {"Threads_connected",        (char*) &thread_count,           SHOW_INT_CONST},
++  {"Threads_created",	       (char*) &thread_created,		SHOW_LONG_CONST},
++  {"Threads_running",          (char*) &thread_running,         SHOW_INT_CONST},
++  {"Uptime",                   (char*) 0,                       SHOW_STARTTIME},
++  {"Uptime_since_flush_status",(char*) 0,                       SHOW_FLUSHTIME},
++  {NullS, NullS, SHOW_LONG}
++};
++
++static void print_version(void)
++{
++  set_server_version();
++  printf("%s  Ver %s for %s on %s (%s)\n",my_progname,
++	 server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT);
++}
++
++static void usage(void)
++{
++  if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
++					           MY_CS_PRIMARY,
++						   MYF(MY_WME))))
++    exit(1);
++  if (!default_collation_name)
++    default_collation_name= (char*) default_charset_info->name;
++  print_version();
++  puts("\
++Copyright (C) 2000 MySQL AB, by Monty and others\n\
++This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
++and you are welcome to modify and redistribute it under the GPL license\n\n\
++Starts the MySQL database server\n");
++
++  printf("Usage: %s [OPTIONS]\n", my_progname);
++  if (!opt_verbose)
++    puts("\nFor more help options (several pages), use mysqld --verbose --help\n");
++  else
++  {
++#ifdef __WIN__
++  puts("NT and Win32 specific options:\n\
++  --install                     Install the default service (NT)\n\
++  --install-manual              Install the default service started manually (NT)\n\
++  --install service_name        Install an optional service (NT)\n\
++  --install-manual service_name Install an optional service started manually (NT)\n\
++  --remove                      Remove the default service from the service list (NT)\n\
++  --remove service_name         Remove the service_name from the service list (NT)\n\
++  --enable-named-pipe           Only to be used for the	default server (NT)\n\
++  --standalone                  Dummy option to start as a standalone server (NT)\
++");
++  puts("");
++#endif
++  print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
++  puts("");
++  fix_paths();
++  set_ports();
++
++  my_print_help(my_long_options);
++  my_print_variables(my_long_options);
++
++  puts("\n\
++To see what values a running MySQL server is using, type\n\
++'mysqladmin variables' instead of 'mysqld --verbose --help'.\n");
++  }
++}
++
++
++/*
++  Initialize all MySQL global variables to default values
++
++  SYNOPSIS
++    mysql_init_variables()
++
++  NOTES
++    The reason to set a lot of global variables to zero is to allow one to
++    restart the embedded server with a clean environment
++    It's also needed on some exotic platforms where global variables are
++    not set to 0 when a program starts.
++
++    We don't need to set numeric variables refered to in my_long_options
++    as these are initialized by my_getopt.
++*/
++
++static void mysql_init_variables(void)
++{
++  /* Things reset to zero */
++  opt_skip_slave_start= opt_reckless_slave = 0;
++  mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
++  opt_log= opt_update_log= opt_slow_log= 0;
++  opt_bin_log= 0;
++  opt_disable_networking= opt_skip_show_db=0;
++  opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
++  opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
++  opt_secure_auth= 0;
++  opt_secure_file_priv= 0;
++  opt_bootstrap= opt_myisam_log= 0;
++  mqh_used= 0;
++  segfaulted= kill_in_progress= 0;
++  cleanup_done= 0;
++  defaults_argv= 0;
++  server_id_supplied= 0;
++  test_flags= select_errors= dropping_tables= ha_open_options=0;
++  thread_count= thread_running= kill_cached_threads= wake_thread=0;
++  slave_open_temp_tables= 0;
++  cached_thread_count= 0;
++  opt_endinfo= using_udf_functions= 0;
++  opt_using_transactions= using_update_log= 0;
++  abort_loop= select_thread_in_use= signal_thread_in_use= 0;
++  ready_to_exit= shutdown_in_progress= grant_option= 0;
++  aborted_threads= aborted_connects= 0;
++  delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0;
++  delayed_insert_errors= thread_created= 0;
++  specialflag= 0;
++  binlog_cache_use=  binlog_cache_disk_use= 0;
++  max_used_connections= slow_launch_threads = 0;
++  mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
++  prepared_stmt_count= 0;
++  errmesg= 0;
++  mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
++  bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
++  bzero((char *) &global_status_var, sizeof(global_status_var));
++  opt_large_pages= 0;
++  key_map_full.set_all();
++
++  /* Character sets */
++  system_charset_info= &my_charset_utf8_general_ci;
++  files_charset_info= &my_charset_utf8_general_ci;
++  national_charset_info= &my_charset_utf8_general_ci;
++  table_alias_charset= &my_charset_bin;
++  character_set_filesystem= &my_charset_bin;
++
++  opt_date_time_formats[0]= opt_date_time_formats[1]= opt_date_time_formats[2]= 0;
++
++  /* Things with default values that are not zero */
++  delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
++  opt_specialflag= SPECIAL_ENGLISH;
++  unix_sock= ip_sock= INVALID_SOCKET;
++  mysql_home_ptr= mysql_home;
++  pidfile_name_ptr= pidfile_name;
++  log_error_file_ptr= log_error_file;
++  language_ptr= language;
++  mysql_data_home= mysql_real_data_home;
++  thd_startup_options= (OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL |
++			OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE |
++			OPTION_SQL_NOTES);
++  protocol_version= PROTOCOL_VERSION;
++  what_to_log= ~ (1L << (uint) COM_TIME);
++  refresh_version= flush_version= 1L;	/* Increments on each reload */
++  global_query_id= thread_id= 1L;
++  strmov(server_version, MYSQL_SERVER_VERSION);
++  myisam_recover_options_str= sql_mode_str= "OFF";
++  myisam_stats_method_str= "nulls_unequal";
++  my_bind_addr = htonl(INADDR_ANY);
++  threads.empty();
++  thread_cache.empty();
++  key_caches.empty();
++  if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str,
++					       default_key_cache_base.length)))
++    exit(1);
++  multi_keycache_init(); /* set key_cache_hash.default_value = dflt_key_cache */
++
++  /* Initialize structures that is used when processing options */
++  replicate_rewrite_db.empty();
++  replicate_do_db.empty();
++  replicate_ignore_db.empty();
++  binlog_do_db.empty();
++  binlog_ignore_db.empty();
++
++  /* Set directory paths */
++  strmake(language, LANGUAGE, sizeof(language)-1);
++  strmake(mysql_real_data_home, get_relative_path(DATADIR),
++	  sizeof(mysql_real_data_home)-1);
++  mysql_data_home_buff[0]=FN_CURLIB;	// all paths are relative from here
++  mysql_data_home_buff[1]=0;
++
++  /* Replication parameters */
++  master_user= (char*) "test";
++  master_password= master_host= 0;
++  master_info_file= (char*) "master.info",
++    relay_log_info_file= (char*) "relay-log.info";
++  master_ssl_key= master_ssl_cert= master_ssl_ca=
++    master_ssl_capath= master_ssl_cipher= 0;
++  report_user= report_password = report_host= 0;	/* TO BE DELETED */
++  opt_relay_logname= opt_relaylog_index_name= 0;
++
++  /* Variables in libraries */
++  charsets_dir= 0;
++  default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME;
++  default_collation_name= compiled_default_collation_name;
++  sys_charset_system.value= (char*) system_charset_info->csname;
++  character_set_filesystem_name= (char*) "binary";
++  lc_time_names_name= (char*) "en_US";
++
++  /* Set default values for some option variables */
++  global_system_variables.table_type=   DB_TYPE_MYISAM;
++  global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
++  global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
++  max_system_variables.select_limit=    (ulonglong) HA_POS_ERROR;
++  global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
++  max_system_variables.max_join_size=   (ulonglong) HA_POS_ERROR;
++  global_system_variables.old_passwords= 0;
++
++  /*
++    Default behavior for 4.1 and 5.0 is to treat NULL values as unequal
++    when collecting index statistics for MyISAM tables.
++  */
++  global_system_variables.myisam_stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
++
++  /* Variables that depends on compile options */
++#ifndef DBUG_OFF
++  default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace",
++			     "d:t:i:o,/tmp/mysqld.trace");
++#endif
++  opt_error_log= IF_WIN(1,0);
++#ifdef HAVE_BERKELEY_DB
++  have_berkeley_db= SHOW_OPTION_YES;
++#else
++  have_berkeley_db= SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_INNOBASE_DB
++  have_innodb=SHOW_OPTION_YES;
++#else
++  have_innodb=SHOW_OPTION_NO;
++#endif
++  have_isam=SHOW_OPTION_NO;
++#ifdef HAVE_EXAMPLE_DB
++  have_example_db= SHOW_OPTION_YES;
++#else
++  have_example_db= SHOW_OPTION_NO;
++#endif
++#if defined(HAVE_ARCHIVE_DB)
++  have_archive_db= SHOW_OPTION_YES;
++#else
++  have_archive_db= SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_BLACKHOLE_DB
++  have_blackhole_db= SHOW_OPTION_YES;
++#else
++  have_blackhole_db= SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_FEDERATED_DB
++  have_federated_db= SHOW_OPTION_YES;
++#else
++  have_federated_db= SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_CSV_DB
++  have_csv_db= SHOW_OPTION_YES;
++#else
++  have_csv_db= SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_NDBCLUSTER_DB
++  have_ndbcluster=SHOW_OPTION_DISABLED;
++#else
++  have_ndbcluster=SHOW_OPTION_NO;
++#endif
++#ifdef USE_RAID
++  have_raid=SHOW_OPTION_YES;
++#else
++  have_raid=SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_OPENSSL
++  have_ssl=SHOW_OPTION_YES;
++#else
++  have_ssl=SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_BROKEN_REALPATH
++  have_symlink=SHOW_OPTION_NO;
++#else
++  have_symlink=SHOW_OPTION_YES;
++#endif
++#ifdef HAVE_DLOPEN
++  have_dlopen=SHOW_OPTION_YES;
++#else
++  have_dlopen=SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_QUERY_CACHE
++  have_query_cache=SHOW_OPTION_YES;
++#else
++  have_query_cache=SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_SPATIAL
++  have_geometry=SHOW_OPTION_YES;
++#else
++  have_geometry=SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_RTREE_KEYS
++  have_rtree_keys=SHOW_OPTION_YES;
++#else
++  have_rtree_keys=SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_CRYPT
++  have_crypt=SHOW_OPTION_YES;
++#else
++  have_crypt=SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_COMPRESS
++  have_compress= SHOW_OPTION_YES;
++#else
++  have_compress= SHOW_OPTION_NO;
++#endif
++#ifdef HAVE_LIBWRAP
++  libwrapName= NullS;
++#endif
++#ifdef HAVE_OPENSSL
++  des_key_file = 0;
++  ssl_acceptor_fd= 0;
++#endif
++#ifdef HAVE_SMEM
++  shared_memory_base_name= default_shared_memory_base_name;
++#endif
++#if !defined(my_pthread_setprio) && !defined(HAVE_PTHREAD_SETSCHEDPARAM)
++  opt_specialflag |= SPECIAL_NO_PRIOR;
++#endif
++
++#if defined(__WIN__) || defined(__NETWARE__)
++  /* Allow Win32 and NetWare users to move MySQL anywhere */
++  {
++    char prg_dev[LIBLEN];
++    my_path(prg_dev,my_progname,"mysql/bin");
++    strcat(prg_dev,"/../");			// Remove 'bin' to get base dir
++    cleanup_dirname(mysql_home,prg_dev);
++  }
++#else
++  const char *tmpenv;
++  if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
++    tmpenv = DEFAULT_MYSQL_HOME;
++  (void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1);
++#endif
++}
++
++
++static my_bool
++get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
++	       char *argument)
++{
++  switch(optid) {
++  case '#':
++#ifndef DBUG_OFF
++    DBUG_PUSH(argument ? argument : default_dbug_option);
++#endif
++    opt_endinfo=1;				/* unireg: memory allocation */
++    break;
++  case 'a':
++    global_system_variables.sql_mode= fix_sql_mode(MODE_ANSI);
++    global_system_variables.tx_isolation= ISO_SERIALIZABLE;
++    break;
++  case 'b':
++    strmake(mysql_home,argument,sizeof(mysql_home)-1);
++    break;
++  case 'C':
++    if (default_collation_name == compiled_default_collation_name)
++      default_collation_name= 0;
++    break;
++  case 'l':
++    opt_log=1;
++    break;
++  case 'h':
++    strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
++    /* Correct pointer set by my_getopt (for embedded library) */
++    mysql_data_home= mysql_real_data_home;
++    break;
++  case 'u':
++    if (!mysqld_user || !strcmp(mysqld_user, argument))
++      mysqld_user= argument;
++    else
++      sql_print_warning("Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
++    break;
++  case 'L':
++    strmake(language, argument, sizeof(language)-1);
++    break;
++#ifdef HAVE_REPLICATION
++  case OPT_SLAVE_SKIP_ERRORS:
++    init_slave_skip_errors(argument);
++    break;
++#endif
++  case OPT_SAFEMALLOC_MEM_LIMIT:
++#if !defined(DBUG_OFF) && defined(SAFEMALLOC)
++    sf_malloc_mem_limit = atoi(argument);
++#endif
++    break;
++#include <sslopt-case.h>
++  case 'V':
++    print_version();
++    exit(0);
++  case 'W':
++    if (!argument)
++      global_system_variables.log_warnings++;
++    else if (argument == disabled_my_option)
++      global_system_variables.log_warnings= 0L;
++    else
++      global_system_variables.log_warnings= atoi(argument);
++    break;
++  case 'T':
++    test_flags= argument ? (uint) atoi(argument) : 0;
++    test_flags&= ~TEST_NO_THREADS;
++    opt_endinfo=1;
++    break;
++  case (int) OPT_BIG_TABLES:
++    thd_startup_options|=OPTION_BIG_TABLES;
++    break;
++  case (int) OPT_ISAM_LOG:
++    opt_myisam_log=1;
++    break;
++  case (int) OPT_UPDATE_LOG:
++    opt_update_log=1;
++    break;
++  case (int) OPT_BIN_LOG:
++    opt_bin_log= test(argument != disabled_my_option);
++    break;
++  case (int) OPT_ERROR_LOG_FILE:
++    opt_error_log= 1;
++    break;
++#ifdef HAVE_REPLICATION
++  case (int) OPT_INIT_RPL_ROLE:
++  {
++    int role;
++    if ((role=find_type(argument, &rpl_role_typelib, 2)) <= 0)
++    {
++      fprintf(stderr, "Unknown replication role: %s\n", argument);
++      exit(1);
++    }
++    rpl_status = (role == 1) ?  RPL_AUTH_MASTER : RPL_IDLE_SLAVE;
++    break;
++  }
++  case (int)OPT_REPLICATE_IGNORE_DB:
++  {
++    i_string *db = new i_string(argument);
++    replicate_ignore_db.push_back(db);
++    break;
++  }
++  case (int)OPT_REPLICATE_DO_DB:
++  {
++    i_string *db = new i_string(argument);
++    replicate_do_db.push_back(db);
++    break;
++  }
++  case (int)OPT_REPLICATE_REWRITE_DB:
++  {
++    char* key = argument,*p, *val;
++
++    if (!(p= strstr(argument, "->")))
++    {
++      fprintf(stderr,
++	      "Bad syntax in replicate-rewrite-db - missing '->'!\n");
++      exit(1);
++    }
++    val= p--;
++    while (my_isspace(mysqld_charset, *p) && p > argument)
++      *p-- = 0;
++    if (p == argument)
++    {
++      fprintf(stderr,
++	      "Bad syntax in replicate-rewrite-db - empty FROM db!\n");
++      exit(1);
++    }
++    *val= 0;
++    val+= 2;
++    while (*val && my_isspace(mysqld_charset, *val))
++      *val++;
++    if (!*val)
++    {
++      fprintf(stderr,
++	      "Bad syntax in replicate-rewrite-db - empty TO db!\n");
++      exit(1);
++    }
++
++    i_string_pair *db_pair = new i_string_pair(key, val);
++    replicate_rewrite_db.push_back(db_pair);
++    break;
++  }
++
++  case (int)OPT_BINLOG_IGNORE_DB:
++  {
++    i_string *db = new i_string(argument);
++    binlog_ignore_db.push_back(db);
++    break;
++  }
++  case (int)OPT_BINLOG_DO_DB:
++  {
++    i_string *db = new i_string(argument);
++    binlog_do_db.push_back(db);
++    break;
++  }
++  case (int)OPT_REPLICATE_DO_TABLE:
++  {
++    if (!do_table_inited)
++      init_table_rule_hash(&replicate_do_table, &do_table_inited);
++    if (add_table_rule(&replicate_do_table, argument))
++    {
++      fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
++      exit(1);
++    }
++    table_rules_on = 1;
++    break;
++  }
++  case (int)OPT_REPLICATE_WILD_DO_TABLE:
++  {
++    if (!wild_do_table_inited)
++      init_table_rule_array(&replicate_wild_do_table,
++			    &wild_do_table_inited);
++    if (add_wild_table_rule(&replicate_wild_do_table, argument))
++    {
++      fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
++      exit(1);
++    }
++    table_rules_on = 1;
++    break;
++  }
++  case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
++  {
++    if (!wild_ignore_table_inited)
++      init_table_rule_array(&replicate_wild_ignore_table,
++			    &wild_ignore_table_inited);
++    if (add_wild_table_rule(&replicate_wild_ignore_table, argument))
++    {
++      fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
++      exit(1);
++    }
++    table_rules_on = 1;
++    break;
++  }
++  case (int)OPT_REPLICATE_IGNORE_TABLE:
++  {
++    if (!ignore_table_inited)
++      init_table_rule_hash(&replicate_ignore_table, &ignore_table_inited);
++    if (add_table_rule(&replicate_ignore_table, argument))
++    {
++      fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
++      exit(1);
++    }
++    table_rules_on = 1;
++    break;
++  }
++#endif /* HAVE_REPLICATION */
++  case (int) OPT_SLOW_QUERY_LOG:
++    opt_slow_log=1;
++    break;
++  case (int) OPT_SKIP_NEW:
++    opt_specialflag|= SPECIAL_NO_NEW_FUNC;
++    delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
++    myisam_concurrent_insert=0;
++    myisam_recover_options= HA_RECOVER_NONE;
++    sp_automatic_privileges=0;
++    my_use_symdir=0;
++    ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
++#ifdef HAVE_QUERY_CACHE
++    query_cache_size=0;
++#endif
++    break;
++  case (int) OPT_SAFE:
++    opt_specialflag|= SPECIAL_SAFE_MODE;
++    delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
++    myisam_recover_options= HA_RECOVER_DEFAULT;
++    ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE);
++    break;
++  case (int) OPT_SKIP_PRIOR:
++    opt_specialflag|= SPECIAL_NO_PRIOR;
++    break;
++  case (int) OPT_SKIP_LOCK:
++    opt_external_locking=0;
++    break;
++  case (int) OPT_SKIP_HOST_CACHE:
++    opt_specialflag|= SPECIAL_NO_HOST_CACHE;
++    break;
++  case (int) OPT_SKIP_RESOLVE:
++    opt_specialflag|=SPECIAL_NO_RESOLVE;
++    break;
++  case (int) OPT_SKIP_NETWORKING:
++#if defined(__NETWARE__)
++    sql_perror("Can't start server: skip-networking option is currently not supported on NetWare");
++    exit(1);
++#endif
++    opt_disable_networking=1;
++    mysqld_port=0;
++    break;
++  case (int) OPT_SKIP_SHOW_DB:
++    opt_skip_show_db=1;
++    opt_specialflag|=SPECIAL_SKIP_SHOW_DB;
++    break;
++#ifdef ONE_THREAD
++  case (int) OPT_ONE_THREAD:
++    test_flags |= TEST_NO_THREADS;
++#endif
++    break;
++  case (int) OPT_WANT_CORE:
++    test_flags |= TEST_CORE_ON_SIGNAL;
++    break;
++  case (int) OPT_SKIP_STACK_TRACE:
++    test_flags|=TEST_NO_STACKTRACE;
++    break;
++  case (int) OPT_SKIP_SYMLINKS:
++    my_use_symdir=0;
++    break;
++  case (int) OPT_BIND_ADDRESS:
++    if ((my_bind_addr= (ulong) inet_addr(argument)) == INADDR_NONE)
++    {
++      struct hostent *ent;
++      if (argument[0])
++	ent=gethostbyname(argument);
++      else
++      {
++	char myhostname[255];
++	if (gethostname(myhostname,sizeof(myhostname)) < 0)
++	{
++	  sql_perror("Can't start server: cannot get my own hostname!");
++	  exit(1);
++	}
++	ent=gethostbyname(myhostname);
++      }
++      if (!ent)
++      {
++	sql_perror("Can't start server: cannot resolve hostname!");
++	exit(1);
++      }
++      my_bind_addr = (ulong) ((in_addr*)ent->h_addr_list[0])->s_addr;
++    }
++    break;
++  case (int) OPT_PID_FILE:
++    strmake(pidfile_name, argument, sizeof(pidfile_name)-1);
++    break;
++#ifdef __WIN__
++  case (int) OPT_STANDALONE:		/* Dummy option for NT */
++    break;
++#endif
++  /*
++    The following change issues a deprecation warning if the slave
++    configuration is specified either in the my.cnf file or on
++    the command-line. See BUG#21490.
++  */
++  case OPT_MASTER_HOST:
++  case OPT_MASTER_USER:
++  case OPT_MASTER_PASSWORD:
++  case OPT_MASTER_PORT:
++  case OPT_MASTER_CONNECT_RETRY:
++  case OPT_MASTER_SSL:          
++  case OPT_MASTER_SSL_KEY:
++  case OPT_MASTER_SSL_CERT:       
++  case OPT_MASTER_SSL_CAPATH:
++  case OPT_MASTER_SSL_CIPHER:
++  case OPT_MASTER_SSL_CA:
++    if (!slave_warning_issued)                 //only show the warning once
++    {
++      slave_warning_issued = true;   
++      WARN_DEPRECATED(NULL, "5.2", "for replication startup options", 
++        "'CHANGE MASTER'");
++    }
++    break;
++  case OPT_CONSOLE:
++    if (opt_console)
++      opt_error_log= 0;			// Force logs to stdout
++    break;
++  case (int) OPT_FLUSH:
++    myisam_flush=1;
++    flush_time=0;			// No auto flush
++    break;
++  case OPT_LOW_PRIORITY_UPDATES:
++    thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY;
++    global_system_variables.low_priority_updates=1;
++    break;
++  case OPT_BOOTSTRAP:
++    opt_noacl=opt_bootstrap=1;
++    break;
++  case OPT_STORAGE_ENGINE:
++  {
++    if ((enum db_type)((global_system_variables.table_type=
++                        ha_resolve_by_name(argument, strlen(argument)))) ==
++        DB_TYPE_UNKNOWN)
++    {
++      fprintf(stderr,"Unknown/unsupported table type: %s\n",argument);
++      exit(1);
++    }
++    break;
++  }
++  case OPT_SERVER_ID:
++    server_id_supplied = 1;
++    break;
++  case OPT_DELAY_KEY_WRITE_ALL:
++    if (argument != disabled_my_option)
++      argument= (char*) "ALL";
++    /* Fall through */
++  case OPT_DELAY_KEY_WRITE:
++    if (argument == disabled_my_option)
++      delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
++    else if (! argument)
++      delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
++    else
++    {
++      int type;
++      if ((type=find_type(argument, &delay_key_write_typelib, 2)) <= 0)
++      {
++	fprintf(stderr,"Unknown delay_key_write type: %s\n",argument);
++	exit(1);
++      }
++      delay_key_write_options= (uint) type-1;
++    }
++    break;
++  case OPT_CHARSETS_DIR:
++    strmake(mysql_charsets_dir, argument, sizeof(mysql_charsets_dir)-1);
++    charsets_dir = mysql_charsets_dir;
++    break;
++  case OPT_TX_ISOLATION:
++  {
++    int type;
++    if ((type=find_type(argument, &tx_isolation_typelib, 2)) <= 0)
++    {
++      fprintf(stderr,"Unknown transaction isolation type: %s\n",argument);
++      exit(1);
++    }
++    global_system_variables.tx_isolation= (type-1);
++    break;
++  }
++  case OPT_MERGE:
++    if (opt_merge)
++      have_merge_db= SHOW_OPTION_YES;
++    else
++      have_merge_db= SHOW_OPTION_DISABLED;
++#ifdef HAVE_BERKELEY_DB
++  case OPT_BDB_NOSYNC:
++    /* Deprecated option */
++    opt_sync_bdb_logs= 0;
++    /* Fall through */
++  case OPT_BDB_SYNC:
++    if (!opt_sync_bdb_logs)
++      berkeley_env_flags|= DB_TXN_NOSYNC;
++    else
++      berkeley_env_flags&= ~DB_TXN_NOSYNC;
++    break;
++  case OPT_BDB_NO_RECOVER:
++    berkeley_init_flags&= ~(DB_RECOVER);
++    break;
++  case OPT_BDB_LOCK:
++  {
++    int type;
++    if ((type=find_type(argument, &berkeley_lock_typelib, 2)) > 0)
++      berkeley_lock_type=berkeley_lock_types[type-1];
++    else
++    {
++      int err;
++      char *end;
++      uint length= strlen(argument);
++      long value= my_strntol(&my_charset_latin1, argument, length, 10, &end, &err);
++      if (end == argument+length)
++	berkeley_lock_scan_time= value;
++      else
++      {
++	fprintf(stderr,"Unknown lock type: %s\n",argument);
++	exit(1);
++      }
++    }
++    break;
++  }
++  case OPT_BDB_SHARED:
++    berkeley_init_flags&= ~(DB_PRIVATE);
++    berkeley_shared_data= 1;
++    break;
++#endif /* HAVE_BERKELEY_DB */
++  case OPT_BDB:
++#ifdef HAVE_BERKELEY_DB
++    if (opt_bdb)
++      have_berkeley_db= SHOW_OPTION_YES;
++    else
++      have_berkeley_db= SHOW_OPTION_DISABLED;
++#endif
++    break;
++  case OPT_NDBCLUSTER:
++#ifdef HAVE_NDBCLUSTER_DB
++    if (opt_ndbcluster)
++      have_ndbcluster= SHOW_OPTION_YES;
++    else
++      have_ndbcluster= SHOW_OPTION_DISABLED;
++#endif
++    break;
++#ifdef HAVE_NDBCLUSTER_DB
++  case OPT_NDB_MGMD:
++  case OPT_NDB_NODEID:
++  {
++    int len= my_snprintf(opt_ndb_constrbuf+opt_ndb_constrbuf_len,
++			 sizeof(opt_ndb_constrbuf)-opt_ndb_constrbuf_len,
++			 "%s%s%s",opt_ndb_constrbuf_len > 0 ? ",":"",
++			 optid == OPT_NDB_NODEID ? "nodeid=" : "",
++			 argument);
++    opt_ndb_constrbuf_len+= len;
++  }
++  /* fall through to add the connectstring to the end
++   * and set opt_ndbcluster_connectstring
++   */
++  case OPT_NDB_CONNECTSTRING:
++    if (opt_ndb_connectstring && opt_ndb_connectstring[0])
++      my_snprintf(opt_ndb_constrbuf+opt_ndb_constrbuf_len,
++		  sizeof(opt_ndb_constrbuf)-opt_ndb_constrbuf_len,
++		  "%s%s", opt_ndb_constrbuf_len > 0 ? ",":"",
++		  opt_ndb_connectstring);
++    else
++      opt_ndb_constrbuf[opt_ndb_constrbuf_len]= 0;
++    opt_ndbcluster_connectstring= opt_ndb_constrbuf;
++    break;
++#endif
++  case OPT_INNODB:
++#ifdef HAVE_INNOBASE_DB
++    if (opt_innodb)
++      have_innodb= SHOW_OPTION_YES;
++    else
++      have_innodb= SHOW_OPTION_DISABLED;
++#endif
++    break;
++  case OPT_INNODB_DATA_FILE_PATH:
++#ifdef HAVE_INNOBASE_DB
++    innobase_data_file_path= argument;
++#endif
++    break;
++#ifdef HAVE_INNOBASE_DB
++  case OPT_INNODB_LOG_ARCHIVE:
++    innobase_log_archive= argument ? test(atoi(argument)) : 1;
++    break;
++#endif /* HAVE_INNOBASE_DB */
++  case OPT_MYISAM_RECOVER:
++  {
++    if (!argument)
++    {
++      myisam_recover_options=    HA_RECOVER_DEFAULT;
++      myisam_recover_options_str= myisam_recover_typelib.type_names[0];
++    }
++    else if (!argument[0])
++    {
++      myisam_recover_options= HA_RECOVER_NONE;
++      myisam_recover_options_str= "OFF";
++    }
++    else
++    {
++      myisam_recover_options_str=argument;
++      if ((myisam_recover_options=
++	   find_bit_type(argument, &myisam_recover_typelib)) == ~(ulong) 0)
++      {
++	fprintf(stderr, "Unknown option to myisam-recover: %s\n",argument);
++	exit(1);
++      }
++    }
++    ha_open_options|=HA_OPEN_ABORT_IF_CRASHED;
++    break;
++  }
++  case OPT_CONCURRENT_INSERT:
++    /* The following code is mainly here to emulate old behavior */
++    if (!argument)                      /* --concurrent-insert */
++      myisam_concurrent_insert= 1;
++    else if (argument == disabled_my_option)
++      myisam_concurrent_insert= 0;      /* --skip-concurrent-insert */
++    break;
++  case OPT_TC_HEURISTIC_RECOVER:
++  {
++    if ((tc_heuristic_recover=find_type(argument,
++                                        &tc_heuristic_recover_typelib, 2)) <=0)
++    {
++      fprintf(stderr, "Unknown option to tc-heuristic-recover: %s\n",argument);
++      exit(1);
++    }
++  }
++  case OPT_MYISAM_STATS_METHOD:
++  {
++    ulong method_conv;
++    int method;
++    LINT_INIT(method_conv);
++
++    myisam_stats_method_str= argument;
++    if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0)
++    {
++      fprintf(stderr, "Invalid value of myisam_stats_method: %s.\n", argument);
++      exit(1);
++    }
++    switch (method-1) {
++    case 2:
++      method_conv= MI_STATS_METHOD_IGNORE_NULLS;
++      break;
++    case 1:
++      method_conv= MI_STATS_METHOD_NULLS_EQUAL;
++      break;
++    case 0:
++    default:
++      method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL;
++      break;
++    }
++    global_system_variables.myisam_stats_method= method_conv;
++    break;
++  }
++  case OPT_SQL_MODE:
++  {
++    sql_mode_str= argument;
++    if ((global_system_variables.sql_mode=
++         find_bit_type(argument, &sql_mode_typelib)) == ~(ulong) 0)
++    {
++      fprintf(stderr, "Unknown option to sql-mode: %s\n", argument);
++      exit(1);
++    }
++    global_system_variables.sql_mode= fix_sql_mode(global_system_variables.
++						   sql_mode);
++    break;
++  }
++  case OPT_FT_BOOLEAN_SYNTAX:
++    if (ft_boolean_check_syntax_string((byte*) argument))
++    {
++      fprintf(stderr, "Invalid ft-boolean-syntax string: %s\n", argument);
++      exit(1);
++    }
++    strmake(ft_boolean_syntax, argument, sizeof(ft_boolean_syntax)-1);
++    break;
++  case OPT_SKIP_SAFEMALLOC:
++#ifdef SAFEMALLOC
++    sf_malloc_quick=1;
++#endif
++    break;
++  case OPT_LOWER_CASE_TABLE_NAMES:
++    lower_case_table_names= argument ? atoi(argument) : 1;
++    lower_case_table_names_used= 1;
++    break;
++  }
++  return 0;
++}
++	/* Initiates DEBUG - but no debugging here ! */
++
++static gptr *
++mysql_getopt_value(const char *keyname, uint key_length,
++		   const struct my_option *option)
++{
++  switch (option->id) {
++  case OPT_KEY_BUFFER_SIZE:
++  case OPT_KEY_CACHE_BLOCK_SIZE:
++  case OPT_KEY_CACHE_DIVISION_LIMIT:
++  case OPT_KEY_CACHE_AGE_THRESHOLD:
++  {
++    KEY_CACHE *key_cache;
++    if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
++      exit(1);
++    switch (option->id) {
++    case OPT_KEY_BUFFER_SIZE:
++      return (gptr*) &key_cache->param_buff_size;
++    case OPT_KEY_CACHE_BLOCK_SIZE:
++      return (gptr*) &key_cache->param_block_size;
++    case OPT_KEY_CACHE_DIVISION_LIMIT:
++      return (gptr*) &key_cache->param_division_limit;
++    case OPT_KEY_CACHE_AGE_THRESHOLD:
++      return (gptr*) &key_cache->param_age_threshold;
++    }
++  }
++  }
++ return option->value;
++}
++
++
++static void option_error_reporter(enum loglevel level, const char *format, ...)
++{
++  va_list args;
++  va_start(args, format);
++  vprint_msg_to_log(level, format, args);
++  va_end(args);
++}
++
++
++static void get_options(int argc,char **argv)
++{
++  int ho_error;
++
++  my_getopt_register_get_addr(mysql_getopt_value);
++  strmake(def_ft_boolean_syntax, ft_boolean_syntax,
++	  sizeof(ft_boolean_syntax)-1);
++  my_getopt_error_reporter= option_error_reporter;
++  if ((ho_error= handle_options(&argc, &argv, my_long_options,
++                                get_one_option)))
++    exit(ho_error);
++
++#ifndef HAVE_NDBCLUSTER_DB
++  if (opt_ndbcluster)
++    sql_print_warning("this binary does not contain NDBCLUSTER storage engine");
++#endif
++#ifndef HAVE_INNOBASE_DB
++  if (opt_innodb)
++    sql_print_warning("this binary does not contain INNODB storage engine");
++#endif
++#ifndef HAVE_ISAM
++  if (opt_isam)
++    sql_print_warning("this binary does not contain ISAM storage engine");
++#endif
++#ifndef HAVE_BERKELEY_DB
++  if (opt_bdb)
++    sql_print_warning("this binary does not contain BDB storage engine");
++#endif
++  if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes) &&
++      !opt_slow_log)
++    sql_print_warning("options --log-slow-admin-statements and --log-queries-not-using-indexes have no effect if --log-slow-queries is not set");
++
++  if (argc > 0)
++  {
++    fprintf(stderr, "%s: Too many arguments (first extra is '%s').\nUse --help to get a list of available options\n", my_progname, *argv);
++    /* FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code? */
++    exit(1);
++  }
++
++  if (opt_help)
++  {
++    usage();
++    exit(0);
++  }
++#if defined(HAVE_BROKEN_REALPATH)
++  my_use_symdir=0;
++  my_disable_symlinks=1;
++  have_symlink=SHOW_OPTION_NO;
++#else
++  if (!my_use_symdir)
++  {
++    my_disable_symlinks=1;
++    have_symlink=SHOW_OPTION_DISABLED;
++  }
++#endif
++  if (opt_debugging)
++  {
++    /* Allow break with SIGINT, no core or stack trace */
++    test_flags|= TEST_SIGINT | TEST_NO_STACKTRACE;
++    test_flags&= ~TEST_CORE_ON_SIGNAL;
++  }
++  /* Set global MyISAM variables from delay_key_write_options */
++  fix_delay_key_write((THD*) 0, OPT_GLOBAL);
++
++#ifndef EMBEDDED_LIBRARY
++  if (mysqld_chroot)
++    set_root(mysqld_chroot);
++#else
++  max_allowed_packet= global_system_variables.max_allowed_packet;
++  net_buffer_length= global_system_variables.net_buffer_length;
++#endif
++  fix_paths();
++
++  /*
++    Set some global variables from the global_system_variables
++    In most cases the global variables will not be used
++  */
++  my_disable_locking= myisam_single_user= test(opt_external_locking == 0);
++  my_default_record_cache_size=global_system_variables.read_buff_size;
++  myisam_max_temp_length=
++    (my_off_t) global_system_variables.myisam_max_sort_file_size;
++
++  /* Set global variables based on startup options */
++  myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
++
++  if (opt_short_log_format)
++    opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
++
++  if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE,
++				  &global_system_variables.date_format) ||
++      init_global_datetime_format(MYSQL_TIMESTAMP_TIME,
++				  &global_system_variables.time_format) ||
++      init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
++				  &global_system_variables.datetime_format))
++    exit(1);
++}
++
++
++/*
++  Create version name for running mysqld version
++  We automaticly add suffixes -debug, -embedded and -log to the version
++  name to make the version more descriptive.
++  (MYSQL_SERVER_SUFFIX is set by the compilation environment)
++*/
++
++static void set_server_version(void)
++{
++  char *end= strxmov(server_version, MYSQL_SERVER_VERSION,
++                     MYSQL_SERVER_SUFFIX_STR, NullS);
++#ifdef EMBEDDED_LIBRARY
++  end= strmov(end, "-embedded");
++#endif
++#ifndef DBUG_OFF
++  if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
++    end= strmov(end, "-debug");
++#endif
++  if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
++    strmov(end, "-log");                        // This may slow down system
++}
++
++
++static char *get_relative_path(const char *path)
++{
++  if (test_if_hard_path(path) &&
++      is_prefix(path,DEFAULT_MYSQL_HOME) &&
++      strcmp(DEFAULT_MYSQL_HOME,FN_ROOTDIR))
++  {
++    path+=(uint) strlen(DEFAULT_MYSQL_HOME);
++    while (*path == FN_LIBCHAR)
++      path++;
++  }
++  return (char*) path;
++}
++
++
++/*
++  Fix filename and replace extension where 'dir' is relative to
++  mysql_real_data_home.
++  Return 1 if len(path) > FN_REFLEN
++*/
++
++bool
++fn_format_relative_to_data_home(my_string to, const char *name,
++				const char *dir, const char *extension)
++{
++  char tmp_path[FN_REFLEN];
++  if (!test_if_hard_path(dir))
++  {
++    strxnmov(tmp_path,sizeof(tmp_path)-1, mysql_real_data_home,
++	     dir, NullS);
++    dir=tmp_path;
++  }
++  return !fn_format(to, name, dir, extension,
++		    MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
++}
++
++
++static void fix_paths(void)
++{
++  char buff[FN_REFLEN],*pos;
++  convert_dirname(mysql_home,mysql_home,NullS);
++  /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
++  my_realpath(mysql_home,mysql_home,MYF(0));
++  /* Ensure that mysql_home ends in FN_LIBCHAR */
++  pos=strend(mysql_home);
++  if (pos[-1] != FN_LIBCHAR)
++  {
++    pos[0]= FN_LIBCHAR;
++    pos[1]= 0;
++  }
++  convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
++  convert_dirname(language,language,NullS);
++  (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
++  (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
++  (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home);
++
++  char *sharedir=get_relative_path(SHAREDIR);
++  if (test_if_hard_path(sharedir))
++    strmake(buff,sharedir,sizeof(buff)-1);		/* purecov: tested */
++  else
++    strxnmov(buff,sizeof(buff)-1,mysql_home,sharedir,NullS);
++  convert_dirname(buff,buff,NullS);
++  (void) my_load_path(language,language,buff);
++
++  /* If --character-sets-dir isn't given, use shared library dir */
++  if (charsets_dir != mysql_charsets_dir)
++  {
++    strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff,
++	     CHARSET_DIR, NullS);
++  }
++  (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
++  convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
++  charsets_dir=mysql_charsets_dir;
++
++  if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
++    exit(1);
++#ifdef HAVE_REPLICATION
++  if (!slave_load_tmpdir)
++  {
++    if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE))))
++      exit(1);
++  }
++#endif /* HAVE_REPLICATION */
++  /*
++    Convert the secure-file-priv option to system format, allowing
++    a quick strcmp to check if read or write is in an allowed dir
++   */
++  if (opt_secure_file_priv)
++  {
++    convert_dirname(buff, opt_secure_file_priv, NullS);
++    my_free(opt_secure_file_priv, MYF(0));
++    opt_secure_file_priv= my_strdup(buff, MYF(MY_FAE));
++  }
++}
++
++
++/*
++  Return a bitfield from a string of substrings separated by ','
++  returns ~(ulong) 0 on error.
++*/
++
++static ulong find_bit_type(const char *x, TYPELIB *bit_lib)
++{
++  bool found_end;
++  int  found_count;
++  const char *end,*i,*j;
++  const char **array, *pos;
++  ulong found,found_int,bit;
++  DBUG_ENTER("find_bit_type");
++  DBUG_PRINT("enter",("x: '%s'",x));
++
++  found=0;
++  found_end= 0;
++  pos=(my_string) x;
++  while (*pos == ' ') pos++;
++  found_end= *pos == 0;
++  while (!found_end)
++  {
++    if (!*(end=strcend(pos,',')))		/* Let end point at fieldend */
++    {
++      while (end > pos && end[-1] == ' ')
++	end--;					/* Skip end-space */
++      found_end=1;
++    }
++    found_int=0; found_count=0;
++    for (array=bit_lib->type_names, bit=1 ; (i= *array++) ; bit<<=1)
++    {
++      j=pos;
++      while (j != end)
++      {
++	if (my_toupper(mysqld_charset,*i++) !=
++            my_toupper(mysqld_charset,*j++))
++	  goto skip;
++      }
++      found_int=bit;
++      if (! *i)
++      {
++	found_count=1;
++	break;
++      }
++      else if (j != pos)			// Half field found
++      {
++	found_count++;				// Could be one of two values
++      }
++skip: ;
++    }
++    if (found_count != 1)
++      DBUG_RETURN(~(ulong) 0);				// No unique value
++    found|=found_int;
++    pos=end+1;
++  }
++
++  DBUG_PRINT("exit",("bit-field: %ld",(ulong) found));
++  DBUG_RETURN(found);
++} /* find_bit_type */
++
++
++/*
++  Check if file system used for databases is case insensitive
++
++  SYNOPSIS
++    test_if_case_sensitive()
++    dir_name			Directory to test
++
++  RETURN
++    -1  Don't know (Test failed)
++    0   File system is case sensitive
++    1   File system is case insensitive
++*/
++
++static int test_if_case_insensitive(const char *dir_name)
++{
++  int result= 0;
++  File file;
++  char buff[FN_REFLEN], buff2[FN_REFLEN];
++  MY_STAT stat_info;
++  DBUG_ENTER("test_if_case_insensitive");
++
++  fn_format(buff, glob_hostname, dir_name, ".lower-test",
++	    MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
++  fn_format(buff2, glob_hostname, dir_name, ".LOWER-TEST",
++	    MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
++  (void) my_delete(buff2, MYF(0));
++  if ((file= my_create(buff, 0666, O_RDWR, MYF(0))) < 0)
++  {
++    sql_print_warning("Can't create test file %s", buff);
++    DBUG_RETURN(-1);
++  }
++  my_close(file, MYF(0));
++  if (my_stat(buff2, &stat_info, MYF(0)))
++    result= 1;					// Can access file
++  (void) my_delete(buff, MYF(MY_WME));
++  DBUG_PRINT("exit", ("result: %d", result));
++  DBUG_RETURN(result);
++}
++
++
++/* Create file to store pid number */
++
++#ifndef EMBEDDED_LIBRARY
++
++static void create_pid_file()
++{
++  File file;
++  if ((file = my_create(pidfile_name,0664,
++			O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
++  {
++    char buff[21], *end;
++    end= int10_to_str((long) getpid(), buff, 10);
++    *end++= '\n';
++    if (!my_write(file, (byte*) buff, (uint) (end-buff), MYF(MY_WME | MY_NABP)))
++    {
++      (void) my_close(file, MYF(0));
++      return;
++    }
++    (void) my_close(file, MYF(0));
++  }
++  sql_perror("Can't start server: can't create PID file");
++  exit(1);
++}
++#endif /* EMBEDDED_LIBRARY */
++
++/* Clear most status variables */
++void refresh_status(THD *thd)
++{
++  pthread_mutex_lock(&LOCK_status);
++
++  /* Add thread's status variabes to global status */
++  add_to_status(&global_status_var, &thd->status_var);
++
++  /* Reset thread's status variables */
++  bzero((char*) &thd->status_var, sizeof(thd->status_var));
++
++  /* Reset some global variables */
++  for (struct show_var_st *ptr=status_vars; ptr->name; ptr++)
++  {
++    if (ptr->type == SHOW_LONG)
++      *(ulong*) ptr->value= 0;
++  }
++
++  /* Reset the counters of all key caches (default and named). */
++  process_key_caches(reset_key_cache_counters);
++  flush_status_time= time((time_t*) 0);
++  pthread_mutex_unlock(&LOCK_status);
++
++  /*
++    Set max_used_connections to the number of currently open
++    connections.  Lock LOCK_thread_count out of LOCK_status to avoid
++    deadlocks.  Status reset becomes not atomic, but status data is
++    not exact anyway.
++  */
++  pthread_mutex_lock(&LOCK_thread_count);
++  max_used_connections= thread_count-delayed_insert_threads;
++  pthread_mutex_unlock(&LOCK_thread_count);
++}
++
++
++/*****************************************************************************
++  Instantiate have_xyx for missing storage engines
++*****************************************************************************/
++#undef have_berkeley_db
++#undef have_innodb
++#undef have_ndbcluster
++#undef have_example_db
++#undef have_archive_db
++#undef have_csv_db
++#undef have_federated_db
++#undef have_partition_db
++#undef have_blackhole_db
++
++SHOW_COMP_OPTION have_berkeley_db= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_innodb= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_ndbcluster= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_example_db= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_archive_db= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_csv_db= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_federated_db= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_partition_db= SHOW_OPTION_NO;
++SHOW_COMP_OPTION have_blackhole_db= SHOW_OPTION_NO;
++
++
++/*****************************************************************************
++  Instantiate templates
++*****************************************************************************/
++
++#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
++/* Used templates */
++template class I_List<THD>;
++template class I_List_iterator<THD>;
++template class I_List<i_string>;
++template class I_List<i_string_pair>;
++template class I_List<NAMED_LIST>;
++template class I_List<Statement>;
++template class I_List_iterator<Statement>;
++#endif
+diff -urNad trunk~/sql/set_var.cc trunk/sql/set_var.cc
+--- trunk~/sql/set_var.cc	2007-11-15 08:06:50.000000000 -0600
++++ trunk/sql/set_var.cc	2007-12-27 15:54:49.310264914 -0600
+@@ -882,6 +882,7 @@
+   {"have_compress",	      (char*) &have_compress,		    SHOW_HAVE},
+   {"have_crypt",	      (char*) &have_crypt,		    SHOW_HAVE},
+   {"have_csv",	              (char*) &have_csv_db,	            SHOW_HAVE},
++  {"have_sphinx",             (char*) &have_sphinx_db,              SHOW_HAVE},
+   {"have_dynamic_loading",    (char*) &have_dlopen,	            SHOW_HAVE},
+   {"have_example_engine",     (char*) &have_example_db,	            SHOW_HAVE},
+   {"have_federated_engine",   (char*) &have_federated_db,           SHOW_HAVE},
+diff -urNad trunk~/sql/set_var.cc.orig trunk/sql/set_var.cc.orig
+--- trunk~/sql/set_var.cc.orig	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/set_var.cc.orig	2007-12-27 15:54:49.318265370 -0600
+@@ -0,0 +1,3751 @@
++/* Copyright (C) 2000-2003 MySQL AB
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; version 2 of the License.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
++
++/*
++  Handling of MySQL SQL variables
++
++  To add a new variable, one has to do the following:
++
++  - Use one of the 'sys_var... classes from set_var.h or write a specific
++    one for the variable type.
++  - Define it in the 'variable definition list' in this file.
++  - If the variable should be changeable or one should be able to access it
++    with @@variable_name, it should be added to the 'list of all variables'
++    list (sys_variables) in this file.
++  - If the variable is thread specific, add it to 'system_variables' struct.
++    If not, add it to mysqld.cc and an declaration in 'mysql_priv.h'
++  - If the variable should be changed from the command line, add a definition
++    of it in the my_option structure list in mysqld.cc
++  - Don't forget to initialize new fields in global_system_variables and
++    max_system_variables!
++  - If the variable should show up in 'show variables' add it to the
++    init_vars[] struct in this file
++
++  NOTES:
++    - Be careful with var->save_result: sys_var::check() only updates
++    ulonglong_value; so other members of the union are garbage then; to use
++    them you must first assign a value to them (in specific ::check() for
++    example).
++
++  TODO:
++    - Add full support for the variable character_set (for 4.1)
++
++    - When updating myisam_delay_key_write, we should do a 'flush tables'
++      of all MyISAM tables to ensure that they are reopen with the
++      new attribute.
++*/
++
++#ifdef USE_PRAGMA_IMPLEMENTATION
++#pragma implementation				// gcc: Class implementation
++#endif
++
++#include "mysql_priv.h"
++#include <mysql.h>
++#include "slave.h"
++#include <my_getopt.h>
++#include <thr_alarm.h>
++#include <myisam.h>
++
++#ifdef HAVE_BERKELEY_DB
++#include "ha_berkeley.h"
++#endif
++#ifdef HAVE_INNOBASE_DB
++#include "ha_innodb.h"
++#endif
++#ifdef HAVE_NDBCLUSTER_DB
++#include "ha_ndbcluster.h"
++#endif
++
++static HASH system_variable_hash;
++const char *bool_type_names[]= { "OFF", "ON", NullS };
++TYPELIB bool_typelib=
++{
++  array_elements(bool_type_names)-1, "", bool_type_names, NULL
++};
++
++const char *delay_key_write_type_names[]= { "OFF", "ON", "ALL", NullS };
++TYPELIB delay_key_write_typelib=
++{
++  array_elements(delay_key_write_type_names)-1, "",
++  delay_key_write_type_names, NULL
++};
++
++static int  sys_check_ftb_syntax(THD *thd,  set_var *var);
++static bool sys_update_ftb_syntax(THD *thd, set_var * var);
++static void sys_default_ftb_syntax(THD *thd, enum_var_type type);
++static bool sys_update_init_connect(THD*, set_var*);
++static void sys_default_init_connect(THD*, enum_var_type type);
++static bool sys_update_init_slave(THD*, set_var*);
++static void sys_default_init_slave(THD*, enum_var_type type);
++static bool set_option_bit(THD *thd, set_var *var);
++static bool set_option_autocommit(THD *thd, set_var *var);
++static int  check_log_update(THD *thd, set_var *var);
++static bool set_log_update(THD *thd, set_var *var);
++static int  check_pseudo_thread_id(THD *thd, set_var *var);
++static bool set_log_bin(THD *thd, set_var *var);
++static void fix_low_priority_updates(THD *thd, enum_var_type type);
++static void fix_tx_isolation(THD *thd, enum_var_type type);
++static int check_completion_type(THD *thd, set_var *var);
++static void fix_completion_type(THD *thd, enum_var_type type);
++static void fix_net_read_timeout(THD *thd, enum_var_type type);
++static void fix_net_write_timeout(THD *thd, enum_var_type type);
++static void fix_net_retry_count(THD *thd, enum_var_type type);
++static void fix_max_join_size(THD *thd, enum_var_type type);
++static void fix_query_cache_size(THD *thd, enum_var_type type);
++static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
++static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
++static void fix_max_binlog_size(THD *thd, enum_var_type type);
++static void fix_max_relay_log_size(THD *thd, enum_var_type type);
++static void fix_max_connections(THD *thd, enum_var_type type);
++static int check_max_delayed_threads(THD *thd, set_var *var);
++static void fix_thd_mem_root(THD *thd, enum_var_type type);
++static void fix_trans_mem_root(THD *thd, enum_var_type type);
++static void fix_server_id(THD *thd, enum_var_type type);
++static KEY_CACHE *create_key_cache(const char *name, uint length);
++void fix_sql_mode_var(THD *thd, enum_var_type type);
++static byte *get_error_count(THD *thd);
++static byte *get_warning_count(THD *thd);
++static byte *get_have_innodb(THD *thd);
++static byte *get_tmpdir(THD *thd);
++
++/*
++  Variable definition list
++
++  These are variables that can be set from the command line, in
++  alphabetic order
++*/
++
++sys_var_thd_ulong	sys_auto_increment_increment("auto_increment_increment",
++                                                     &SV::auto_increment_increment);
++sys_var_thd_ulong	sys_auto_increment_offset("auto_increment_offset",
++                                                  &SV::auto_increment_offset);
++
++sys_var_bool_ptr	sys_automatic_sp_privileges("automatic_sp_privileges",
++					      &sp_automatic_privileges);
++
++sys_var_const_str       sys_basedir("basedir", mysql_home);
++sys_var_long_ptr	sys_binlog_cache_size("binlog_cache_size",
++					      &binlog_cache_size);
++sys_var_thd_ulong	sys_bulk_insert_buff_size("bulk_insert_buffer_size",
++						  &SV::bulk_insert_buff_size);
++sys_var_character_set_server	sys_character_set_server("character_set_server");
++sys_var_const_str       sys_charset_system("character_set_system",
++                                           (char *)my_charset_utf8_general_ci.name);
++sys_var_character_set_database	sys_character_set_database("character_set_database");
++sys_var_character_set_client  sys_character_set_client("character_set_client");
++sys_var_character_set_connection  sys_character_set_connection("character_set_connection");
++sys_var_character_set_results sys_character_set_results("character_set_results");
++sys_var_character_set_filesystem  sys_character_set_filesystem("character_set_filesystem");
++sys_var_thd_ulong	sys_completion_type("completion_type",
++					 &SV::completion_type,
++					 check_completion_type,
++					 fix_completion_type);
++sys_var_collation_connection sys_collation_connection("collation_connection");
++sys_var_collation_database sys_collation_database("collation_database");
++sys_var_collation_server sys_collation_server("collation_server");
++sys_var_long_ptr	sys_concurrent_insert("concurrent_insert",
++                                              &myisam_concurrent_insert);
++sys_var_long_ptr	sys_connect_timeout("connect_timeout",
++					    &connect_timeout);
++sys_var_const_str       sys_datadir("datadir", mysql_real_data_home);
++sys_var_enum		sys_delay_key_write("delay_key_write",
++					    &delay_key_write_options,
++					    &delay_key_write_typelib,
++					    fix_delay_key_write);
++sys_var_long_ptr	sys_delayed_insert_limit("delayed_insert_limit",
++						 &delayed_insert_limit);
++sys_var_long_ptr	sys_delayed_insert_timeout("delayed_insert_timeout",
++						   &delayed_insert_timeout);
++sys_var_long_ptr	sys_delayed_queue_size("delayed_queue_size",
++					       &delayed_queue_size);
++sys_var_long_ptr	sys_expire_logs_days("expire_logs_days",
++					     &expire_logs_days);
++sys_var_bool_ptr	sys_flush("flush", &myisam_flush);
++sys_var_long_ptr	sys_flush_time("flush_time", &flush_time);
++sys_var_str             sys_ft_boolean_syntax("ft_boolean_syntax",
++                                         sys_check_ftb_syntax,
++                                         sys_update_ftb_syntax,
++                                         sys_default_ftb_syntax,
++                                         ft_boolean_syntax);
++sys_var_str             sys_init_connect("init_connect", 0,
++                                         sys_update_init_connect,
++                                         sys_default_init_connect,0);
++sys_var_str             sys_init_slave("init_slave", 0,
++                                       sys_update_init_slave,
++                                       sys_default_init_slave,0);
++sys_var_thd_ulong	sys_interactive_timeout("interactive_timeout",
++						&SV::net_interactive_timeout);
++sys_var_thd_ulong	sys_join_buffer_size("join_buffer_size",
++					     &SV::join_buff_size);
++sys_var_key_buffer_size	sys_key_buffer_size("key_buffer_size");
++sys_var_key_cache_long  sys_key_cache_block_size("key_cache_block_size",
++						 offsetof(KEY_CACHE,
++							  param_block_size));
++sys_var_key_cache_long	sys_key_cache_division_limit("key_cache_division_limit",
++						     offsetof(KEY_CACHE,
++							      param_division_limit));
++sys_var_key_cache_long  sys_key_cache_age_threshold("key_cache_age_threshold",
++						     offsetof(KEY_CACHE,
++							      param_age_threshold));
++sys_var_bool_ptr	sys_local_infile("local_infile",
++					 &opt_local_infile);
++sys_var_trust_routine_creators
++sys_trust_routine_creators("log_bin_trust_routine_creators",
++                           &trust_function_creators);
++sys_var_bool_ptr
++sys_trust_function_creators("log_bin_trust_function_creators",
++                            &trust_function_creators);
++sys_var_bool_ptr
++  sys_log_queries_not_using_indexes("log_queries_not_using_indexes",
++                                    &opt_log_queries_not_using_indexes);
++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);
++sys_var_thd_bool	sys_low_priority_updates("low_priority_updates",
++						 &SV::low_priority_updates,
++						 fix_low_priority_updates);
++#ifndef TO_BE_DELETED	/* Alias for the low_priority_updates */
++sys_var_thd_bool	sys_sql_low_priority_updates("sql_low_priority_updates",
++						     &SV::low_priority_updates,
++						     fix_low_priority_updates);
++#endif
++sys_var_thd_ulong	sys_max_allowed_packet("max_allowed_packet",
++					       &SV::max_allowed_packet);
++sys_var_long_ptr	sys_max_binlog_cache_size("max_binlog_cache_size",
++						  &max_binlog_cache_size);
++sys_var_long_ptr	sys_max_binlog_size("max_binlog_size",
++					    &max_binlog_size,
++                                            fix_max_binlog_size);
++sys_var_long_ptr	sys_max_connections("max_connections",
++					    &max_connections,
++                                            fix_max_connections);
++sys_var_long_ptr	sys_max_connect_errors("max_connect_errors",
++					       &max_connect_errors);
++sys_var_thd_ulong       sys_max_insert_delayed_threads("max_insert_delayed_threads",
++						       &SV::max_insert_delayed_threads,
++                                                       check_max_delayed_threads,
++                                                       fix_max_connections);
++sys_var_thd_ulong	sys_max_delayed_threads("max_delayed_threads",
++						&SV::max_insert_delayed_threads,
++                                                check_max_delayed_threads,
++                                                fix_max_connections);
++sys_var_thd_ulong	sys_max_error_count("max_error_count",
++					    &SV::max_error_count);
++sys_var_thd_ulonglong	sys_max_heap_table_size("max_heap_table_size",
++						&SV::max_heap_table_size);
++sys_var_thd_ulong       sys_pseudo_thread_id("pseudo_thread_id",
++					     &SV::pseudo_thread_id,
++                                             check_pseudo_thread_id, 0);
++sys_var_thd_ha_rows	sys_max_join_size("max_join_size",
++					  &SV::max_join_size,
++					  fix_max_join_size);
++sys_var_thd_ulong	sys_max_seeks_for_key("max_seeks_for_key",
++					      &SV::max_seeks_for_key);
++sys_var_thd_ulong   sys_max_length_for_sort_data("max_length_for_sort_data",
++                                                 &SV::max_length_for_sort_data);
++#ifndef TO_BE_DELETED	/* Alias for max_join_size */
++sys_var_thd_ha_rows	sys_sql_max_join_size("sql_max_join_size",
++					      &SV::max_join_size,
++					      fix_max_join_size);
++#endif
++static sys_var_long_ptr_global
++sys_max_prepared_stmt_count("max_prepared_stmt_count",
++                            &max_prepared_stmt_count,
++                            &LOCK_prepared_stmt_count);
++sys_var_long_ptr	sys_max_relay_log_size("max_relay_log_size",
++                                               &max_relay_log_size,
++                                               fix_max_relay_log_size);
++sys_var_thd_ulong	sys_max_sort_length("max_sort_length",
++					    &SV::max_sort_length);
++sys_var_thd_ulong	sys_max_sp_recursion_depth("max_sp_recursion_depth",
++                                                   &SV::max_sp_recursion_depth);
++sys_var_max_user_conn   sys_max_user_connections("max_user_connections");
++sys_var_thd_ulong	sys_max_tmp_tables("max_tmp_tables",
++					   &SV::max_tmp_tables);
++sys_var_long_ptr	sys_max_write_lock_count("max_write_lock_count",
++						 &max_write_lock_count);
++sys_var_thd_ulong       sys_multi_range_count("multi_range_count",
++                                              &SV::multi_range_count);
++sys_var_long_ptr	sys_myisam_data_pointer_size("myisam_data_pointer_size",
++                                                    &myisam_data_pointer_size);
++sys_var_thd_ulonglong	sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1);
++sys_var_thd_ulong       sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads);
++sys_var_thd_ulong	sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size);
++
++sys_var_thd_enum        sys_myisam_stats_method("myisam_stats_method",
++                                                &SV::myisam_stats_method,
++                                                &myisam_stats_method_typelib,
++                                                NULL);
++
++sys_var_thd_ulong	sys_net_buffer_length("net_buffer_length",
++					      &SV::net_buffer_length);
++sys_var_thd_ulong	sys_net_read_timeout("net_read_timeout",
++					     &SV::net_read_timeout,
++					     0, fix_net_read_timeout);
++sys_var_thd_ulong	sys_net_write_timeout("net_write_timeout",
++					      &SV::net_write_timeout,
++					      0, fix_net_write_timeout);
++sys_var_thd_ulong	sys_net_retry_count("net_retry_count",
++					    &SV::net_retry_count,
++					    0, fix_net_retry_count);
++sys_var_thd_bool	sys_new_mode("new", &SV::new_mode);
++sys_var_thd_bool	sys_old_passwords("old_passwords", &SV::old_passwords);
++sys_var_thd_ulong       sys_optimizer_prune_level("optimizer_prune_level",
++                                                  &SV::optimizer_prune_level);
++sys_var_thd_ulong       sys_optimizer_search_depth("optimizer_search_depth",
++                                                   &SV::optimizer_search_depth);
++sys_var_thd_ulong       sys_preload_buff_size("preload_buffer_size",
++                                              &SV::preload_buff_size);
++sys_var_thd_ulong	sys_read_buff_size("read_buffer_size",
++					   &SV::read_buff_size);
++sys_var_bool_ptr	sys_readonly("read_only", &opt_readonly);
++sys_var_thd_ulong	sys_read_rnd_buff_size("read_rnd_buffer_size",
++					       &SV::read_rnd_buff_size);
++sys_var_thd_ulong	sys_div_precincrement("div_precision_increment",
++                                              &SV::div_precincrement);
++#ifdef HAVE_REPLICATION
++sys_var_bool_ptr	sys_relay_log_purge("relay_log_purge",
++                                            &relay_log_purge);
++#endif
++sys_var_long_ptr	sys_rpl_recovery_rank("rpl_recovery_rank",
++					      &rpl_recovery_rank);
++sys_var_long_ptr	sys_query_cache_size("query_cache_size",
++					     &query_cache_size,
++					     fix_query_cache_size);
++
++sys_var_thd_ulong	sys_range_alloc_block_size("range_alloc_block_size",
++						   &SV::range_alloc_block_size);
++sys_var_thd_ulong	sys_query_alloc_block_size("query_alloc_block_size",
++						   &SV::query_alloc_block_size,
++						   0, fix_thd_mem_root);
++sys_var_thd_ulong	sys_query_prealloc_size("query_prealloc_size",
++						&SV::query_prealloc_size,
++						0, fix_thd_mem_root);
++sys_var_readonly        sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir);
++sys_var_thd_ulong	sys_trans_alloc_block_size("transaction_alloc_block_size",
++						   &SV::trans_alloc_block_size,
++						   0, fix_trans_mem_root);
++sys_var_thd_ulong	sys_trans_prealloc_size("transaction_prealloc_size",
++						&SV::trans_prealloc_size,
++						0, fix_trans_mem_root);
++
++#ifdef HAVE_QUERY_CACHE
++sys_var_long_ptr	sys_query_cache_limit("query_cache_limit",
++					      &query_cache.query_cache_limit);
++sys_var_long_ptr        sys_query_cache_min_res_unit("query_cache_min_res_unit",
++						     &query_cache_min_res_unit,
++						     fix_query_cache_min_res_unit);
++sys_var_thd_enum	sys_query_cache_type("query_cache_type",
++					     &SV::query_cache_type,
++					     &query_cache_type_typelib);
++sys_var_thd_bool
++sys_query_cache_wlock_invalidate("query_cache_wlock_invalidate",
++				 &SV::query_cache_wlock_invalidate);
++#endif /* HAVE_QUERY_CACHE */
++sys_var_bool_ptr	sys_secure_auth("secure_auth", &opt_secure_auth);
++sys_var_const_str_ptr   sys_secure_file_priv("secure_file_priv",
++                                             &opt_secure_file_priv);
++sys_var_long_ptr	sys_server_id("server_id", &server_id, fix_server_id);
++sys_var_bool_ptr	sys_slave_compressed_protocol("slave_compressed_protocol",
++						      &opt_slave_compressed_protocol);
++#ifdef HAVE_REPLICATION
++sys_var_long_ptr	sys_slave_net_timeout("slave_net_timeout",
++					      &slave_net_timeout);
++sys_var_long_ptr	sys_slave_trans_retries("slave_transaction_retries",
++                                                &slave_trans_retries);
++#endif
++sys_var_long_ptr	sys_slow_launch_time("slow_launch_time",
++					     &slow_launch_time);
++sys_var_thd_ulong	sys_sort_buffer("sort_buffer_size",
++					&SV::sortbuff_size);
++sys_var_thd_sql_mode    sys_sql_mode("sql_mode",
++                                     &SV::sql_mode);
++#ifdef HAVE_OPENSSL
++extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher,
++            *opt_ssl_key;
++sys_var_const_str_ptr	sys_ssl_ca("ssl_ca", &opt_ssl_ca);
++sys_var_const_str_ptr	sys_ssl_capath("ssl_capath", &opt_ssl_capath);
++sys_var_const_str_ptr	sys_ssl_cert("ssl_cert", &opt_ssl_cert);
++sys_var_const_str_ptr	sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher);
++sys_var_const_str_ptr	sys_ssl_key("ssl_key", &opt_ssl_key);
++#else
++sys_var_const_str	sys_ssl_ca("ssl_ca", NULL);
++sys_var_const_str	sys_ssl_capath("ssl_capath", NULL);
++sys_var_const_str	sys_ssl_cert("ssl_cert", NULL);
++sys_var_const_str	sys_ssl_cipher("ssl_cipher", NULL);
++sys_var_const_str	sys_ssl_key("ssl_key", NULL);
++#endif
++sys_var_thd_enum
++sys_updatable_views_with_limit("updatable_views_with_limit",
++                               &SV::updatable_views_with_limit,
++                               &updatable_views_with_limit_typelib);
++
++sys_var_thd_table_type  sys_table_type("table_type",
++				       &SV::table_type);
++sys_var_thd_storage_engine sys_storage_engine("storage_engine",
++				       &SV::table_type);
++#ifdef HAVE_REPLICATION
++sys_var_sync_binlog_period sys_sync_binlog_period("sync_binlog", &sync_binlog_period);
++#endif
++sys_var_bool_ptr	sys_sync_frm("sync_frm", &opt_sync_frm);
++sys_var_const_str	sys_system_time_zone("system_time_zone",
++                                             system_time_zone);
++sys_var_long_ptr	sys_table_cache_size("table_cache",
++					     &table_cache_size);
++sys_var_long_ptr	sys_table_lock_wait_timeout("table_lock_wait_timeout",
++                                                    &table_lock_wait_timeout);
++sys_var_long_ptr	sys_thread_cache_size("thread_cache_size",
++					      &thread_cache_size);
++sys_var_thd_enum	sys_tx_isolation("tx_isolation",
++					 &SV::tx_isolation,
++					 &tx_isolation_typelib,
++					 fix_tx_isolation);
++sys_var_thd_ulonglong	sys_tmp_table_size("tmp_table_size",
++					   &SV::tmp_table_size);
++sys_var_bool_ptr  sys_timed_mutexes("timed_mutexes",
++                                    &timed_mutexes);
++sys_var_const_str	sys_version("version", server_version);
++#ifdef HAVE_BERKELEY_DB
++sys_var_const_str	sys_version_bdb("version_bdb", DB_VERSION_STRING);
++#endif
++sys_var_const_str	sys_version_comment("version_comment",
++                                            MYSQL_COMPILATION_COMMENT);
++sys_var_const_str	sys_version_compile_machine("version_compile_machine",
++                                                    MACHINE_TYPE);
++sys_var_const_str	sys_version_compile_os("version_compile_os",
++                                               SYSTEM_TYPE);
++sys_var_thd_ulong	sys_net_wait_timeout("wait_timeout",
++					     &SV::net_wait_timeout);
++
++#ifdef HAVE_INNOBASE_DB
++sys_var_long_ptr	sys_innodb_fast_shutdown("innodb_fast_shutdown",
++						 &innobase_fast_shutdown);
++sys_var_long_ptr        sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct",
++                                                        &srv_max_buf_pool_modified_pct);
++sys_var_long_ptr	sys_innodb_max_purge_lag("innodb_max_purge_lag",
++							&srv_max_purge_lag);
++sys_var_thd_bool	sys_innodb_table_locks("innodb_table_locks",
++                                               &SV::innodb_table_locks);
++sys_var_thd_bool	sys_innodb_support_xa("innodb_support_xa",
++                                               &SV::innodb_support_xa);
++sys_var_long_ptr	sys_innodb_autoextend_increment("innodb_autoextend_increment",
++							&srv_auto_extend_increment);
++sys_var_long_ptr	sys_innodb_sync_spin_loops("innodb_sync_spin_loops",
++                                             &srv_n_spin_wait_rounds);
++sys_var_long_ptr  sys_innodb_concurrency_tickets("innodb_concurrency_tickets",
++                                             &srv_n_free_tickets_to_enter);
++sys_var_long_ptr  sys_innodb_thread_sleep_delay("innodb_thread_sleep_delay",
++                                                &srv_thread_sleep_delay);
++sys_var_long_ptr  sys_innodb_thread_concurrency("innodb_thread_concurrency",
++                                                &srv_thread_concurrency);
++sys_var_long_ptr  sys_innodb_commit_concurrency("innodb_commit_concurrency",
++                                                &srv_commit_concurrency);
++sys_var_long_ptr  sys_innodb_flush_log_at_trx_commit(
++                                        "innodb_flush_log_at_trx_commit",
++                                        &srv_flush_log_at_trx_commit);
++#endif
++
++/* Condition pushdown to storage engine */
++sys_var_thd_bool
++sys_engine_condition_pushdown("engine_condition_pushdown",
++			      &SV::engine_condition_pushdown);
++
++#ifdef HAVE_NDBCLUSTER_DB
++/* ndb thread specific variable settings */
++sys_var_thd_ulong
++sys_ndb_autoincrement_prefetch_sz("ndb_autoincrement_prefetch_sz",
++				  &SV::ndb_autoincrement_prefetch_sz);
++sys_var_thd_bool
++sys_ndb_force_send("ndb_force_send", &SV::ndb_force_send);
++sys_var_thd_bool
++sys_ndb_use_exact_count("ndb_use_exact_count", &SV::ndb_use_exact_count);
++sys_var_thd_bool
++sys_ndb_use_transactions("ndb_use_transactions", &SV::ndb_use_transactions);
++sys_var_long_ptr
++sys_ndb_cache_check_time("ndb_cache_check_time", &ndb_cache_check_time);
++sys_var_const_str
++sys_ndb_connectstring("ndb_connectstring", opt_ndb_constrbuf);
++#endif
++
++/* Time/date/datetime formats */
++
++sys_var_thd_date_time_format sys_time_format("time_format",
++					     &SV::time_format,
++					     MYSQL_TIMESTAMP_TIME);
++sys_var_thd_date_time_format sys_date_format("date_format",
++					     &SV::date_format,
++					     MYSQL_TIMESTAMP_DATE);
++sys_var_thd_date_time_format sys_datetime_format("datetime_format",
++						 &SV::datetime_format,
++						 MYSQL_TIMESTAMP_DATETIME);
++
++/* Variables that are bits in THD */
++
++sys_var_thd_bit sys_autocommit("autocommit", 0,
++                               set_option_autocommit,
++                               OPTION_NOT_AUTOCOMMIT,
++                               1);
++static sys_var_thd_bit	sys_big_tables("big_tables", 0,
++				       set_option_bit,
++				       OPTION_BIG_TABLES);
++#ifndef TO_BE_DELETED	/* Alias for big_tables */
++static sys_var_thd_bit	sys_sql_big_tables("sql_big_tables", 0,
++					   set_option_bit,
++					   OPTION_BIG_TABLES);
++#endif
++static sys_var_thd_bit	sys_big_selects("sql_big_selects", 0,
++					set_option_bit,
++					OPTION_BIG_SELECTS);
++static sys_var_thd_bit	sys_log_off("sql_log_off",
++				    check_log_update,
++				    set_option_bit,
++				    OPTION_LOG_OFF);
++static sys_var_thd_bit	sys_log_update("sql_log_update",
++                                       check_log_update,
++				       set_log_update,
++				       OPTION_UPDATE_LOG);
++static sys_var_thd_bit	sys_log_binlog("sql_log_bin",
++                                       check_log_update,
++				       set_log_bin,
++				       OPTION_BIN_LOG);
++static sys_var_thd_bit	sys_sql_warnings("sql_warnings", 0,
++					 set_option_bit,
++					 OPTION_WARNINGS);
++static sys_var_thd_bit	sys_sql_notes("sql_notes", 0,
++					 set_option_bit,
++					 OPTION_SQL_NOTES);
++static sys_var_thd_bit	sys_auto_is_null("sql_auto_is_null", 0,
++					 set_option_bit,
++					 OPTION_AUTO_IS_NULL);
++static sys_var_thd_bit	sys_safe_updates("sql_safe_updates", 0,
++					 set_option_bit,
++					 OPTION_SAFE_UPDATES);
++static sys_var_thd_bit	sys_buffer_results("sql_buffer_result", 0,
++					   set_option_bit,
++					   OPTION_BUFFER_RESULT);
++static sys_var_thd_bit	sys_quote_show_create("sql_quote_show_create", 0,
++					      set_option_bit,
++					      OPTION_QUOTE_SHOW_CREATE);
++static sys_var_thd_bit	sys_foreign_key_checks("foreign_key_checks", 0,
++					       set_option_bit,
++					       OPTION_NO_FOREIGN_KEY_CHECKS,
++					       1);
++static sys_var_thd_bit	sys_unique_checks("unique_checks", 0,
++					  set_option_bit,
++					  OPTION_RELAXED_UNIQUE_CHECKS,
++					  1);
++#ifdef ENABLED_PROFILING
++static sys_var_thd_bit  sys_profiling("profiling", NULL, set_option_bit,
++                                      ulonglong(OPTION_PROFILING));
++static sys_var_thd_ulong	sys_profiling_history_size("profiling_history_size",
++					      &SV::profiling_history_size);
++#endif
++
++/* Local state variables */
++
++static sys_var_thd_ha_rows	sys_select_limit("sql_select_limit",
++						 &SV::select_limit);
++static sys_var_timestamp	sys_timestamp("timestamp");
++static sys_var_last_insert_id	sys_last_insert_id("last_insert_id");
++static sys_var_last_insert_id	sys_identity("identity");
++
++static sys_var_thd_lc_time_names       sys_lc_time_names("lc_time_names");
++
++static sys_var_insert_id	sys_insert_id("insert_id");
++static sys_var_readonly		sys_error_count("error_count",
++						OPT_SESSION,
++						SHOW_LONG,
++						get_error_count);
++static sys_var_readonly		sys_warning_count("warning_count",
++						  OPT_SESSION,
++						  SHOW_LONG,
++						  get_warning_count);
++
++/* alias for last_insert_id() to be compatible with Sybase */
++#ifdef HAVE_REPLICATION
++static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter");
++#endif
++static sys_var_rand_seed1	sys_rand_seed1("rand_seed1");
++static sys_var_rand_seed2	sys_rand_seed2("rand_seed2");
++
++static sys_var_thd_ulong        sys_default_week_format("default_week_format",
++					                &SV::default_week_format);
++
++sys_var_thd_ulong               sys_group_concat_max_len("group_concat_max_len",
++                                                         &SV::group_concat_max_len);
++
++sys_var_thd_time_zone            sys_time_zone("time_zone");
++
++/* Read only variables */
++
++sys_var_readonly                sys_have_innodb("have_innodb", OPT_GLOBAL,
++                                                SHOW_CHAR, get_have_innodb);
++/* Global read-only variable describing server license */
++sys_var_const_str		sys_license("license", STRINGIFY_ARG(LICENSE));
++
++/* Global read-only variable containing hostname */
++sys_var_const_str		sys_hostname("hostname", glob_hostname);
++
++sys_var_thd_bool  sys_keep_files_on_create("keep_files_on_create", 
++                                           &SV::keep_files_on_create);
++							    
++
++
++
++/*
++  List of all variables for initialisation and storage in hash
++  This is sorted in alphabetical order to make it easy to add new variables
++
++  If the variable is not in this list, it can't be changed with
++  SET variable_name=
++*/
++
++sys_var *sys_variables[]=
++{
++  &sys_auto_is_null,
++  &sys_auto_increment_increment,
++  &sys_auto_increment_offset,
++  &sys_autocommit,
++  &sys_automatic_sp_privileges,
++  &sys_basedir,
++  &sys_big_tables,
++  &sys_big_selects,
++  &sys_binlog_cache_size,
++  &sys_buffer_results,
++  &sys_bulk_insert_buff_size,
++  &sys_character_set_server,
++  &sys_character_set_database,
++  &sys_character_set_client,
++  &sys_character_set_connection,
++  &sys_character_set_results,
++  &sys_character_set_filesystem,
++  &sys_charset_system,
++  &sys_collation_connection,
++  &sys_collation_database,
++  &sys_collation_server,
++  &sys_completion_type,
++  &sys_concurrent_insert,
++  &sys_connect_timeout,
++  &sys_datadir,
++  &sys_date_format,
++  &sys_datetime_format,
++  &sys_div_precincrement,
++  &sys_default_week_format,
++  &sys_delay_key_write,
++  &sys_delayed_insert_limit,
++  &sys_delayed_insert_timeout,
++  &sys_delayed_queue_size,
++  &sys_keep_files_on_create,
++  &sys_error_count,
++  &sys_expire_logs_days,
++  &sys_flush,
++  &sys_flush_time,
++  &sys_ft_boolean_syntax,
++  &sys_foreign_key_checks,
++  &sys_group_concat_max_len,
++  &sys_have_innodb,
++  &sys_hostname,
++  &sys_identity,
++  &sys_init_connect,
++  &sys_init_slave,
++  &sys_insert_id,
++  &sys_interactive_timeout,
++  &sys_join_buffer_size,
++  &sys_key_buffer_size,
++  &sys_key_cache_block_size,
++  &sys_key_cache_division_limit,
++  &sys_key_cache_age_threshold,
++  &sys_last_insert_id,
++  &sys_lc_time_names,
++  &sys_license,
++  &sys_local_infile,
++  &sys_log_binlog,
++  &sys_log_off,
++  &sys_log_queries_not_using_indexes,
++  &sys_log_update,
++  &sys_log_warnings,
++  &sys_long_query_time,
++  &sys_low_priority_updates,
++  &sys_max_allowed_packet,
++  &sys_max_binlog_cache_size,
++  &sys_max_binlog_size,
++  &sys_max_connect_errors,
++  &sys_max_connections,
++  &sys_max_delayed_threads,
++  &sys_max_error_count,
++  &sys_max_insert_delayed_threads,
++  &sys_max_heap_table_size,
++  &sys_max_join_size,
++  &sys_max_length_for_sort_data,
++  &sys_max_prepared_stmt_count,
++  &sys_max_relay_log_size,
++  &sys_max_seeks_for_key,
++  &sys_max_sort_length,
++  &sys_max_sp_recursion_depth,
++  &sys_max_tmp_tables,
++  &sys_max_user_connections,
++  &sys_max_write_lock_count,
++  &sys_multi_range_count,
++  &sys_myisam_data_pointer_size,
++  &sys_myisam_max_sort_file_size,
++  &sys_myisam_repair_threads,
++  &sys_myisam_sort_buffer_size,
++  &sys_myisam_stats_method,
++  &sys_net_buffer_length,
++  &sys_net_read_timeout,
++  &sys_net_retry_count,
++  &sys_net_wait_timeout,
++  &sys_net_write_timeout,
++  &sys_new_mode,
++  &sys_old_passwords,
++  &sys_optimizer_prune_level,
++  &sys_optimizer_search_depth,
++  &sys_preload_buff_size,
++#ifdef ENABLED_PROFILING
++  &sys_profiling,
++  &sys_profiling_history_size,
++#endif
++  &sys_pseudo_thread_id,
++  &sys_query_alloc_block_size,
++  &sys_query_cache_size,
++  &sys_query_prealloc_size,
++#ifdef HAVE_QUERY_CACHE
++  &sys_query_cache_limit,
++  &sys_query_cache_min_res_unit,
++  &sys_query_cache_type,
++  &sys_query_cache_wlock_invalidate,
++#endif /* HAVE_QUERY_CACHE */
++  &sys_quote_show_create,
++  &sys_rand_seed1,
++  &sys_rand_seed2,
++  &sys_range_alloc_block_size,
++  &sys_readonly,
++  &sys_read_buff_size,
++  &sys_read_rnd_buff_size,
++#ifdef HAVE_REPLICATION
++  &sys_relay_log_purge,
++#endif
++  &sys_rpl_recovery_rank,
++  &sys_safe_updates,
++  &sys_secure_auth,
++  &sys_secure_file_priv,
++  &sys_select_limit,
++  &sys_server_id,
++#ifdef HAVE_REPLICATION
++  &sys_slave_compressed_protocol,
++  &sys_slave_net_timeout,
++  &sys_slave_trans_retries,
++  &sys_slave_skip_counter,
++#endif
++  &sys_slow_launch_time,
++  &sys_sort_buffer,
++  &sys_sql_big_tables,
++  &sys_sql_low_priority_updates,
++  &sys_sql_max_join_size,
++  &sys_sql_mode,
++  &sys_sql_warnings,
++  &sys_sql_notes,
++  &sys_ssl_ca,
++  &sys_ssl_capath,
++  &sys_ssl_cert,
++  &sys_ssl_cipher,
++  &sys_ssl_key,
++  &sys_storage_engine,
++#ifdef HAVE_REPLICATION
++  &sys_sync_binlog_period,
++#endif
++  &sys_sync_frm,
++  &sys_system_time_zone,
++  &sys_table_cache_size,
++  &sys_table_lock_wait_timeout,
++  &sys_table_type,
++  &sys_thread_cache_size,
++  &sys_time_format,
++  &sys_timed_mutexes,
++  &sys_timestamp,
++  &sys_time_zone,
++  &sys_tmpdir,
++  &sys_tmp_table_size,
++  &sys_trans_alloc_block_size,
++  &sys_trans_prealloc_size,
++  &sys_tx_isolation,
++  &sys_version,
++#ifdef HAVE_BERKELEY_DB
++  &sys_version_bdb,
++#endif
++  &sys_version_comment,
++  &sys_version_compile_machine,
++  &sys_version_compile_os,
++#ifdef HAVE_INNOBASE_DB
++  &sys_innodb_fast_shutdown,
++  &sys_innodb_max_dirty_pages_pct,
++  &sys_innodb_max_purge_lag,
++  &sys_innodb_table_locks,
++  &sys_innodb_support_xa,
++  &sys_innodb_max_purge_lag,
++  &sys_innodb_autoextend_increment,
++  &sys_innodb_sync_spin_loops,
++  &sys_innodb_concurrency_tickets,
++  &sys_innodb_thread_sleep_delay,
++  &sys_innodb_thread_concurrency,
++  &sys_innodb_commit_concurrency,
++  &sys_innodb_flush_log_at_trx_commit,
++#endif
++  &sys_trust_routine_creators,
++  &sys_trust_function_creators,
++  &sys_engine_condition_pushdown,
++#ifdef HAVE_NDBCLUSTER_DB
++  &sys_ndb_autoincrement_prefetch_sz,
++  &sys_ndb_cache_check_time,
++  &sys_ndb_connectstring,
++  &sys_ndb_force_send,
++  &sys_ndb_use_exact_count,
++  &sys_ndb_use_transactions,
++#endif
++  &sys_unique_checks,
++  &sys_updatable_views_with_limit,
++  &sys_warning_count
++};
++
++
++/*
++  Variables shown by SHOW VARIABLES in alphabetical order
++*/
++
++struct show_var_st init_vars[]= {
++  {"auto_increment_increment", (char*) &sys_auto_increment_increment, SHOW_SYS},
++  {"auto_increment_offset",   (char*) &sys_auto_increment_offset, SHOW_SYS},
++  {sys_automatic_sp_privileges.name,(char*) &sys_automatic_sp_privileges,       SHOW_SYS},
++  {"back_log",                (char*) &back_log,                    SHOW_LONG},
++  {sys_basedir.name,          (char*) &sys_basedir,                 SHOW_SYS},
++#ifdef HAVE_BERKELEY_DB
++  {"bdb_cache_size",          (char*) &berkeley_cache_size,         SHOW_LONG},
++  {"bdb_home",                (char*) &berkeley_home,               SHOW_CHAR_PTR},
++  {"bdb_log_buffer_size",     (char*) &berkeley_log_buffer_size,    SHOW_LONG},
++  {"bdb_logdir",              (char*) &berkeley_logdir,             SHOW_CHAR_PTR},
++  {"bdb_max_lock",            (char*) &berkeley_max_lock,	    SHOW_LONG},
++  {"bdb_shared_data",	      (char*) &berkeley_shared_data,	    SHOW_BOOL},
++  {"bdb_tmpdir",              (char*) &berkeley_tmpdir,             SHOW_CHAR_PTR},
++#endif
++  {sys_binlog_cache_size.name,(char*) &sys_binlog_cache_size,	    SHOW_SYS},
++  {sys_bulk_insert_buff_size.name,(char*) &sys_bulk_insert_buff_size,SHOW_SYS},
++  {sys_character_set_client.name,(char*) &sys_character_set_client, SHOW_SYS},
++  {sys_character_set_connection.name,(char*) &sys_character_set_connection,SHOW_SYS},
++  {sys_character_set_database.name, (char*) &sys_character_set_database,SHOW_SYS},
++  {sys_character_set_filesystem.name,(char*) &sys_character_set_filesystem, SHOW_SYS},
++  {sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS},
++  {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS},
++  {sys_charset_system.name,   (char*) &sys_charset_system,          SHOW_SYS},
++  {"character_sets_dir",      mysql_charsets_dir,                   SHOW_CHAR},
++  {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS},
++  {sys_collation_database.name,(char*) &sys_collation_database,     SHOW_SYS},
++  {sys_collation_server.name,(char*) &sys_collation_server,         SHOW_SYS},
++  {sys_completion_type.name,  (char*) &sys_completion_type,	    SHOW_SYS},
++  {sys_concurrent_insert.name,(char*) &sys_concurrent_insert,       SHOW_SYS},
++  {sys_connect_timeout.name,  (char*) &sys_connect_timeout,         SHOW_SYS},
++  {sys_datadir.name,          (char*) &sys_datadir,                 SHOW_SYS},
++  {sys_date_format.name,      (char*) &sys_date_format,		    SHOW_SYS},
++  {sys_datetime_format.name,  (char*) &sys_datetime_format,	    SHOW_SYS},
++  {sys_default_week_format.name, (char*) &sys_default_week_format,  SHOW_SYS},
++  {sys_delay_key_write.name,  (char*) &sys_delay_key_write,         SHOW_SYS},
++  {sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS},
++  {sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS},
++  {sys_delayed_queue_size.name,(char*) &sys_delayed_queue_size,     SHOW_SYS},
++  {sys_div_precincrement.name,(char*) &sys_div_precincrement,SHOW_SYS},
++  {sys_keep_files_on_create.name,(char*) &sys_keep_files_on_create, SHOW_SYS},
++  {sys_engine_condition_pushdown.name,
++   (char*) &sys_engine_condition_pushdown,                          SHOW_SYS},
++  {sys_expire_logs_days.name, (char*) &sys_expire_logs_days,        SHOW_SYS},
++  {sys_flush.name,             (char*) &sys_flush,                  SHOW_SYS},
++  {sys_flush_time.name,        (char*) &sys_flush_time,             SHOW_SYS},
++  {sys_ft_boolean_syntax.name,(char*) &ft_boolean_syntax,	    SHOW_CHAR},
++  {"ft_max_word_len",         (char*) &ft_max_word_len,             SHOW_LONG},
++  {"ft_min_word_len",         (char*) &ft_min_word_len,             SHOW_LONG},
++  {"ft_query_expansion_limit",(char*) &ft_query_expansion_limit,    SHOW_LONG},
++  {"ft_stopword_file",        (char*) &ft_stopword_file,            SHOW_CHAR_PTR},
++  {sys_group_concat_max_len.name, (char*) &sys_group_concat_max_len,  SHOW_SYS},
++  {"have_archive",	      (char*) &have_archive_db,	            SHOW_HAVE},
++  {"have_bdb",		      (char*) &have_berkeley_db,	    SHOW_HAVE},
++  {"have_blackhole_engine",   (char*) &have_blackhole_db,	    SHOW_HAVE},
++  {"have_compress",	      (char*) &have_compress,		    SHOW_HAVE},
++  {"have_crypt",	      (char*) &have_crypt,		    SHOW_HAVE},
++  {"have_csv",	              (char*) &have_csv_db,	            SHOW_HAVE},
++  {"have_dynamic_loading",    (char*) &have_dlopen,	            SHOW_HAVE},
++  {"have_example_engine",     (char*) &have_example_db,	            SHOW_HAVE},
++  {"have_federated_engine",   (char*) &have_federated_db,           SHOW_HAVE},
++  {"have_geometry",           (char*) &have_geometry,               SHOW_HAVE},
++  {"have_innodb",	      (char*) &have_innodb,		    SHOW_HAVE},
++  {"have_isam",		      (char*) &have_isam,		    SHOW_HAVE},
++  {"have_merge_engine",       (char*) &have_merge_db,               SHOW_HAVE},
++  {"have_ndbcluster",         (char*) &have_ndbcluster,             SHOW_HAVE},
++  /* have_openssl is just and alias for have_ssl */
++  {"have_openssl",	      (char*) &have_ssl,		    SHOW_HAVE},
++  {"have_ssl",	              (char*) &have_ssl,		    SHOW_HAVE},
++  {"have_query_cache",        (char*) &have_query_cache,            SHOW_HAVE},
++  {"have_raid",		      (char*) &have_raid,		    SHOW_HAVE},
++  {"have_rtree_keys",         (char*) &have_rtree_keys,             SHOW_HAVE},
++  {"have_symlink",            (char*) &have_symlink,                SHOW_HAVE},
++  {sys_hostname.name,         (char*) &sys_hostname,                SHOW_SYS},
++  {"init_connect",            (char*) &sys_init_connect,            SHOW_SYS},
++  {"init_file",               (char*) &opt_init_file,               SHOW_CHAR_PTR},
++  {"init_slave",              (char*) &sys_init_slave,              SHOW_SYS},
++#ifdef HAVE_INNOBASE_DB
++  {"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
++  {sys_innodb_autoextend_increment.name, (char*) &sys_innodb_autoextend_increment, SHOW_SYS},
++  {"innodb_buffer_pool_awe_mem_mb", (char*) &innobase_buffer_pool_awe_mem_mb, SHOW_LONG },
++  {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONGLONG },
++  {"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL},
++  {sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS},
++  {sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS},
++  {"innodb_data_file_path", (char*) &innobase_data_file_path,	    SHOW_CHAR_PTR},
++  {"innodb_data_home_dir",  (char*) &innobase_data_home_dir,	    SHOW_CHAR_PTR},
++  {"innodb_doublewrite", (char*) &innobase_use_doublewrite, SHOW_MY_BOOL},
++  {sys_innodb_fast_shutdown.name,(char*) &sys_innodb_fast_shutdown, SHOW_SYS},
++  {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG },
++  {"innodb_file_per_table", (char*) &innobase_file_per_table, SHOW_MY_BOOL},
++  {sys_innodb_flush_log_at_trx_commit.name, (char*) &sys_innodb_flush_log_at_trx_commit, SHOW_SYS},
++  {"innodb_flush_method",    (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR},
++  {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG },
++  {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG },
++  {"innodb_locks_unsafe_for_binlog", (char*) &innobase_locks_unsafe_for_binlog, SHOW_MY_BOOL},
++  {"innodb_log_arch_dir",   (char*) &innobase_log_arch_dir, 	    SHOW_CHAR_PTR},
++  {"innodb_log_archive",    (char*) &innobase_log_archive, 	    SHOW_MY_BOOL},
++  {"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG },
++  {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONGLONG},
++  {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group,	SHOW_LONG},
++  {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR},
++  {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS},
++  {sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS},
++  {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
++  {"innodb_open_files", (char*) &innobase_open_files, SHOW_LONG },
++  {"innodb_rollback_on_timeout", (char*) &innobase_rollback_on_timeout, SHOW_MY_BOOL},
++  {sys_innodb_support_xa.name, (char*) &sys_innodb_support_xa, SHOW_SYS},
++  {sys_innodb_sync_spin_loops.name, (char*) &sys_innodb_sync_spin_loops, SHOW_SYS},
++  {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS},
++  {sys_innodb_thread_concurrency.name, (char*) &sys_innodb_thread_concurrency, SHOW_SYS},
++  {sys_innodb_thread_sleep_delay.name, (char*) &sys_innodb_thread_sleep_delay, SHOW_SYS},
++#endif
++  {sys_interactive_timeout.name,(char*) &sys_interactive_timeout,   SHOW_SYS},
++  {sys_join_buffer_size.name,   (char*) &sys_join_buffer_size,	    SHOW_SYS},
++  {sys_key_buffer_size.name,	(char*) &sys_key_buffer_size,	    SHOW_SYS},
++  {sys_key_cache_age_threshold.name,   (char*) &sys_key_cache_age_threshold,
++                                                                    SHOW_SYS},
++  {sys_key_cache_block_size.name,   (char*) &sys_key_cache_block_size,
++                                                                    SHOW_SYS},
++  {sys_key_cache_division_limit.name,   (char*) &sys_key_cache_division_limit,
++                                                                    SHOW_SYS},
++  {"language",                language,                             SHOW_CHAR},
++  {"large_files_support",     (char*) &opt_large_files,             SHOW_BOOL},
++  {"large_page_size",         (char*) &opt_large_page_size,         SHOW_INT},
++  {"large_pages",             (char*) &opt_large_pages,             SHOW_MY_BOOL},
++  {sys_lc_time_names.name,    (char*) &sys_lc_time_names,           SHOW_SYS},
++  {sys_license.name,	      (char*) &sys_license,                 SHOW_SYS},
++  {sys_local_infile.name,     (char*) &sys_local_infile,	    SHOW_SYS},
++#ifdef HAVE_MLOCKALL
++  {"locked_in_memory",	      (char*) &locked_in_memory,	    SHOW_BOOL},
++#endif
++  {"log",                     (char*) &opt_log,                     SHOW_BOOL},
++  {"log_bin",                 (char*) &opt_bin_log,                 SHOW_BOOL},
++  {sys_trust_function_creators.name,(char*) &sys_trust_function_creators, SHOW_SYS},
++  {"log_error",               (char*) log_error_file,               SHOW_CHAR},
++  {sys_log_queries_not_using_indexes.name,
++    (char*) &sys_log_queries_not_using_indexes, SHOW_SYS},
++#ifdef HAVE_REPLICATION
++  {"log_slave_updates",       (char*) &opt_log_slave_updates,       SHOW_MY_BOOL},
++#endif
++  {"log_slow_queries",        (char*) &opt_slow_log,                SHOW_BOOL},
++  {sys_log_warnings.name,     (char*) &sys_log_warnings,	    SHOW_SYS},
++  {sys_long_query_time.name,  (char*) &sys_long_query_time, 	    SHOW_SYS},
++  {sys_low_priority_updates.name, (char*) &sys_low_priority_updates, SHOW_SYS},
++  {"lower_case_file_system",  (char*) &lower_case_file_system,      SHOW_MY_BOOL},
++  {"lower_case_table_names",  (char*) &lower_case_table_names,      SHOW_INT},
++  {sys_max_allowed_packet.name,(char*) &sys_max_allowed_packet,	    SHOW_SYS},
++  {sys_max_binlog_cache_size.name,(char*) &sys_max_binlog_cache_size, SHOW_SYS},
++  {sys_max_binlog_size.name,    (char*) &sys_max_binlog_size,	    SHOW_SYS},
++  {sys_max_connect_errors.name, (char*) &sys_max_connect_errors,    SHOW_SYS},
++  {sys_max_connections.name,    (char*) &sys_max_connections,	    SHOW_SYS},
++  {sys_max_delayed_threads.name,(char*) &sys_max_delayed_threads,   SHOW_SYS},
++  {sys_max_error_count.name,	(char*) &sys_max_error_count,	    SHOW_SYS},
++  {sys_max_heap_table_size.name,(char*) &sys_max_heap_table_size,   SHOW_SYS},
++  {sys_max_insert_delayed_threads.name,
++   (char*) &sys_max_insert_delayed_threads,   SHOW_SYS},
++  {sys_max_join_size.name,	(char*) &sys_max_join_size,	    SHOW_SYS},
++  {sys_max_length_for_sort_data.name, (char*) &sys_max_length_for_sort_data,
++   SHOW_SYS},
++  {sys_max_prepared_stmt_count.name, (char*) &sys_max_prepared_stmt_count,
++    SHOW_SYS},
++  {sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size,    SHOW_SYS},
++  {sys_max_seeks_for_key.name,  (char*) &sys_max_seeks_for_key,	    SHOW_SYS},
++  {sys_max_sort_length.name,	(char*) &sys_max_sort_length,	    SHOW_SYS},
++  {sys_max_sp_recursion_depth.name,
++    (char*) &sys_max_sp_recursion_depth, SHOW_SYS},
++  {sys_max_tmp_tables.name,	(char*) &sys_max_tmp_tables,	    SHOW_SYS},
++  {sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS},
++  {sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS},
++  {sys_multi_range_count.name,  (char*) &sys_multi_range_count,     SHOW_SYS},
++  {sys_myisam_data_pointer_size.name, (char*) &sys_myisam_data_pointer_size, SHOW_SYS},
++  {sys_myisam_max_sort_file_size.name, (char*) &sys_myisam_max_sort_file_size,
++   SHOW_SYS},
++  {"myisam_recover_options",  (char*) &myisam_recover_options_str,  SHOW_CHAR_PTR},
++  {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads,
++   SHOW_SYS},
++  {sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS},
++
++  {sys_myisam_stats_method.name, (char*) &sys_myisam_stats_method, SHOW_SYS},
++
++#ifdef __NT__
++  {"named_pipe",	      (char*) &opt_enable_named_pipe,       SHOW_MY_BOOL},
++#endif
++#ifdef HAVE_NDBCLUSTER_DB
++  {sys_ndb_autoincrement_prefetch_sz.name,
++   (char*) &sys_ndb_autoincrement_prefetch_sz,                      SHOW_SYS},
++  {sys_ndb_force_send.name,   (char*) &sys_ndb_force_send,          SHOW_SYS},
++  {sys_ndb_use_exact_count.name,(char*) &sys_ndb_use_exact_count,   SHOW_SYS},
++  {sys_ndb_use_transactions.name,(char*) &sys_ndb_use_transactions, SHOW_SYS},
++  {sys_ndb_cache_check_time.name,(char*) &sys_ndb_cache_check_time, SHOW_SYS},
++  {sys_ndb_connectstring.name,(char*) &sys_ndb_connectstring,       SHOW_SYS},
++#endif
++  {sys_net_buffer_length.name,(char*) &sys_net_buffer_length,       SHOW_SYS},
++  {sys_net_read_timeout.name, (char*) &sys_net_read_timeout,        SHOW_SYS},
++  {sys_net_retry_count.name,  (char*) &sys_net_retry_count,	    SHOW_SYS},
++  {sys_net_write_timeout.name,(char*) &sys_net_write_timeout,       SHOW_SYS},
++  {sys_new_mode.name,         (char*) &sys_new_mode,                SHOW_SYS},
++  {sys_old_passwords.name,    (char*) &sys_old_passwords,           SHOW_SYS},
++  {"open_files_limit",	      (char*) &open_files_limit,	    SHOW_LONG},
++  {sys_optimizer_prune_level.name, (char*) &sys_optimizer_prune_level,
++   SHOW_SYS},
++  {sys_optimizer_search_depth.name,(char*) &sys_optimizer_search_depth,
++   SHOW_SYS},
++  {"pid_file",                (char*) pidfile_name,                 SHOW_CHAR},
++  {"port",                    (char*) &mysqld_port,                  SHOW_INT},
++  {sys_preload_buff_size.name, (char*) &sys_preload_buff_size,      SHOW_SYS},
++#ifdef ENABLED_PROFILING
++  {sys_profiling.name,        (char*) &sys_profiling,               SHOW_SYS},
++  {sys_profiling_history_size.name, (char*) &sys_profiling_history_size, SHOW_SYS},
++#endif
++  {"protocol_version",        (char*) &protocol_version,            SHOW_INT},
++  {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size,
++   SHOW_SYS},
++#ifdef HAVE_QUERY_CACHE
++  {sys_query_cache_limit.name,(char*) &sys_query_cache_limit,	    SHOW_SYS},
++  {sys_query_cache_min_res_unit.name, (char*) &sys_query_cache_min_res_unit,
++   SHOW_SYS},
++  {sys_query_cache_size.name, (char*) &sys_query_cache_size,	    SHOW_SYS},
++  {sys_query_cache_type.name, (char*) &sys_query_cache_type,        SHOW_SYS},
++  {sys_query_cache_wlock_invalidate.name,
++   (char *) &sys_query_cache_wlock_invalidate, SHOW_SYS},
++#endif /* HAVE_QUERY_CACHE */
++  {sys_query_prealloc_size.name, (char*) &sys_query_prealloc_size,  SHOW_SYS},
++  {sys_range_alloc_block_size.name, (char*) &sys_range_alloc_block_size,
++   SHOW_SYS},
++  {sys_read_buff_size.name,   (char*) &sys_read_buff_size,	    SHOW_SYS},
++  {sys_readonly.name,         (char*) &sys_readonly,                SHOW_SYS},
++  {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size,	    SHOW_SYS},
++#ifdef HAVE_REPLICATION
++  {sys_relay_log_purge.name,  (char*) &sys_relay_log_purge,         SHOW_SYS},
++  {"relay_log_space_limit",  (char*) &relay_log_space_limit,        SHOW_LONGLONG},
++#endif
++  {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank,       SHOW_SYS},
++  {"secure_auth",             (char*) &sys_secure_auth,             SHOW_SYS},
++  {"secure_file_priv",        (char*) &sys_secure_file_priv,        SHOW_SYS},
++#ifdef HAVE_SMEM
++  {"shared_memory",           (char*) &opt_enable_shared_memory,    SHOW_MY_BOOL},
++  {"shared_memory_base_name", (char*) &shared_memory_base_name,     SHOW_CHAR_PTR},
++#endif
++  {sys_server_id.name,	      (char*) &sys_server_id,		    SHOW_SYS},
++  {"skip_external_locking",   (char*) &my_disable_locking,          SHOW_MY_BOOL},
++  {"skip_networking",         (char*) &opt_disable_networking,      SHOW_BOOL},
++  {"skip_show_database",      (char*) &opt_skip_show_db,            SHOW_BOOL},
++#ifdef HAVE_REPLICATION
++  {sys_slave_compressed_protocol.name,
++    (char*) &sys_slave_compressed_protocol,           SHOW_SYS},
++  {"slave_load_tmpdir",       (char*) &slave_load_tmpdir,           SHOW_CHAR_PTR},
++  {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout,	    SHOW_SYS},
++  {"slave_skip_errors",       (char*) &slave_error_mask,            SHOW_SLAVE_SKIP_ERRORS},
++  {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries,   SHOW_SYS},
++#endif
++  {sys_slow_launch_time.name, (char*) &sys_slow_launch_time,        SHOW_SYS},
++#ifdef HAVE_SYS_UN_H
++  {"socket",                  (char*) &mysqld_unix_port,             SHOW_CHAR_PTR},
++#endif
++  {sys_sort_buffer.name,      (char*) &sys_sort_buffer,             SHOW_SYS},
++  {sys_big_selects.name,      (char*) &sys_big_selects,             SHOW_SYS},
++  {sys_sql_mode.name,         (char*) &sys_sql_mode,                SHOW_SYS},
++  {"sql_notes",               (char*) &sys_sql_notes,               SHOW_SYS},
++  {"sql_warnings",            (char*) &sys_sql_warnings,            SHOW_SYS},
++  {sys_ssl_ca.name,           (char*) &sys_ssl_ca,                  SHOW_SYS},
++  {sys_ssl_capath.name,       (char*) &sys_ssl_capath,              SHOW_SYS},
++  {sys_ssl_cert.name,         (char*) &sys_ssl_cert,                SHOW_SYS},
++  {sys_ssl_cipher.name,       (char*) &sys_ssl_cipher,              SHOW_SYS},
++  {sys_ssl_key.name,          (char*) &sys_ssl_key,                 SHOW_SYS},
++  {sys_storage_engine.name,   (char*) &sys_storage_engine,          SHOW_SYS},
++#ifdef HAVE_REPLICATION
++  {sys_sync_binlog_period.name,(char*) &sys_sync_binlog_period,     SHOW_SYS},
++#endif
++  {sys_sync_frm.name,         (char*) &sys_sync_frm,               SHOW_SYS},
++#ifdef HAVE_TZNAME
++  {"system_time_zone",        system_time_zone,                     SHOW_CHAR},
++#endif
++  {"table_cache",             (char*) &table_cache_size,            SHOW_LONG},
++  {"table_lock_wait_timeout", (char*) &table_lock_wait_timeout,     SHOW_LONG },
++  {sys_table_type.name,	      (char*) &sys_table_type,	            SHOW_SYS},
++  {sys_thread_cache_size.name,(char*) &sys_thread_cache_size,       SHOW_SYS},
++#ifdef HAVE_THR_SETCONCURRENCY
++  {"thread_concurrency",      (char*) &concurrency,                 SHOW_LONG},
++#endif
++  {"thread_stack",            (char*) &thread_stack,                SHOW_LONG},
++  {sys_time_format.name,      (char*) &sys_time_format,		    SHOW_SYS},
++  {"time_zone",               (char*) &sys_time_zone,               SHOW_SYS},
++  {sys_timed_mutexes.name,    (char*) &sys_timed_mutexes,       SHOW_SYS},
++  {sys_tmp_table_size.name,   (char*) &sys_tmp_table_size,	    SHOW_SYS},
++  {sys_tmpdir.name,           (char*) &sys_tmpdir,	            SHOW_SYS},
++  {sys_trans_alloc_block_size.name, (char*) &sys_trans_alloc_block_size,
++   SHOW_SYS},
++  {sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size,  SHOW_SYS},
++  {sys_tx_isolation.name,     (char*) &sys_tx_isolation,	    SHOW_SYS},
++  {sys_updatable_views_with_limit.name,
++                              (char*) &sys_updatable_views_with_limit,SHOW_SYS},
++  {sys_version.name,          (char*) &sys_version,                 SHOW_SYS},
++#ifdef HAVE_BERKELEY_DB
++  {sys_version_bdb.name,      (char*) &sys_version_bdb,             SHOW_SYS},
++#endif
++  {sys_version_comment.name,  (char*) &sys_version_comment,         SHOW_SYS},
++  {sys_version_compile_machine.name, (char*) &sys_version_compile_machine,
++   SHOW_SYS},
++  {sys_version_compile_os.name,	(char*) &sys_version_compile_os,    SHOW_SYS},
++  {sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout,	    SHOW_SYS},
++  {NullS, NullS, SHOW_LONG}
++};
++
++
++bool sys_var::check(THD *thd, set_var *var)
++{
++  var->save_result.ulonglong_value= var->value->val_int();
++  return 0;
++}
++
++bool sys_var_str::check(THD *thd, set_var *var)
++{
++  int res;
++  if (!check_func)
++    return 0;
++
++  if ((res=(*check_func)(thd, var)) < 0)
++    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
++             name, var->value->str_value.ptr());
++  return res;
++}
++
++/*
++  Functions to check and update variables
++*/
++
++
++/*
++  Update variables 'init_connect, init_slave'.
++
++  In case of 'DEFAULT' value
++  (for example: 'set GLOBAL init_connect=DEFAULT')
++  'var' parameter is NULL pointer.
++*/
++
++bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex,
++			set_var *var)
++{
++  char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
++  uint new_length= (var ? var->value->str_value.length() : 0);
++  if (!old_value)
++    old_value= (char*) "";
++  if (!(res= my_strdup_with_length(old_value, new_length, MYF(0))))
++    return 1;
++  /*
++    Replace the old value in such a way that the any thread using
++    the value will work.
++  */
++  rw_wrlock(var_mutex);
++  old_value= var_str->value;
++  var_str->value= res;
++  var_str->value_length= new_length;
++  rw_unlock(var_mutex);
++  my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
++  return 0;
++}
++
++
++static bool sys_update_init_connect(THD *thd, set_var *var)
++{
++  return update_sys_var_str(&sys_init_connect, &LOCK_sys_init_connect, var);
++}
++
++
++static void sys_default_init_connect(THD* thd, enum_var_type type)
++{
++  update_sys_var_str(&sys_init_connect, &LOCK_sys_init_connect, 0);
++}
++
++
++static bool sys_update_init_slave(THD *thd, set_var *var)
++{
++  return update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, var);
++}
++
++
++static void sys_default_init_slave(THD* thd, enum_var_type type)
++{
++  update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, 0);
++}
++
++static int sys_check_ftb_syntax(THD *thd,  set_var *var)
++{
++  if (thd->security_ctx->master_access & SUPER_ACL)
++    return (ft_boolean_check_syntax_string((byte*)
++                                           var->value->str_value.c_ptr()) ?
++            -1 : 0);
++  else
++  {
++    my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
++    return 1;
++  }
++}
++
++static bool sys_update_ftb_syntax(THD *thd, set_var * var)
++{
++  strmake(ft_boolean_syntax, var->value->str_value.c_ptr(),
++	  sizeof(ft_boolean_syntax)-1);
++
++#ifdef HAVE_QUERY_CACHE
++  query_cache.flush();
++#endif /* HAVE_QUERY_CACHE */
++
++  return 0;
++}
++
++static void sys_default_ftb_syntax(THD *thd, enum_var_type type)
++{
++  strmake(ft_boolean_syntax, def_ft_boolean_syntax,
++	  sizeof(ft_boolean_syntax)-1);
++}
++
++
++/*
++  If one sets the LOW_PRIORIY UPDATES flag, we also must change the
++  used lock type
++*/
++
++static void fix_low_priority_updates(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    thr_upgraded_concurrent_insert_lock= 
++      (global_system_variables.low_priority_updates ?
++       TL_WRITE_LOW_PRIORITY : TL_WRITE);
++  else
++    thd->update_lock_default= (thd->variables.low_priority_updates ?
++			       TL_WRITE_LOW_PRIORITY : TL_WRITE);
++}
++
++
++static void
++fix_myisam_max_sort_file_size(THD *thd, enum_var_type type)
++{
++  myisam_max_temp_length=
++    (my_off_t) global_system_variables.myisam_max_sort_file_size;
++}
++
++/*
++  Set the OPTION_BIG_SELECTS flag if max_join_size == HA_POS_ERROR
++*/
++
++static void fix_max_join_size(THD *thd, enum_var_type type)
++{
++  if (type != OPT_GLOBAL)
++  {
++    if (thd->variables.max_join_size == HA_POS_ERROR)
++      thd->options|= OPTION_BIG_SELECTS;
++    else
++      thd->options&= ~OPTION_BIG_SELECTS;
++  }
++}
++
++
++/*
++  If one doesn't use the SESSION modifier, the isolation level
++  is only active for the next command
++*/
++
++static void fix_tx_isolation(THD *thd, enum_var_type type)
++{
++  if (type == OPT_SESSION)
++    thd->session_tx_isolation= ((enum_tx_isolation)
++				thd->variables.tx_isolation);
++}
++
++static void fix_completion_type(THD *thd __attribute__((unused)),
++				enum_var_type type __attribute__((unused))) {}
++
++static int check_completion_type(THD *thd, set_var *var)
++{
++  longlong val= var->value->val_int();
++  if (val < 0 || val > 2)
++  {
++    char buf[64];
++    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf));
++    return 1;
++  }
++  return 0;
++}
++
++
++/*
++  If we are changing the thread variable, we have to copy it to NET too
++*/
++
++#ifdef HAVE_REPLICATION
++static void fix_net_read_timeout(THD *thd, enum_var_type type)
++{
++  if (type != OPT_GLOBAL)
++    my_net_set_read_timeout(&thd->net, thd->variables.net_read_timeout);
++}
++
++
++static void fix_net_write_timeout(THD *thd, enum_var_type type)
++{
++  if (type != OPT_GLOBAL)
++    my_net_set_write_timeout(&thd->net, thd->variables.net_write_timeout);
++}
++
++static void fix_net_retry_count(THD *thd, enum_var_type type)
++{
++  if (type != OPT_GLOBAL)
++    thd->net.retry_count=thd->variables.net_retry_count;
++}
++#else /* HAVE_REPLICATION */
++static void fix_net_read_timeout(THD *thd __attribute__((unused)),
++				 enum_var_type type __attribute__((unused)))
++{}
++static void fix_net_write_timeout(THD *thd __attribute__((unused)),
++				  enum_var_type type __attribute__((unused)))
++{}
++static void fix_net_retry_count(THD *thd __attribute__((unused)),
++				enum_var_type type __attribute__((unused)))
++{}
++#endif /* HAVE_REPLICATION */
++
++
++static void fix_query_cache_size(THD *thd, enum_var_type type)
++{
++#ifdef HAVE_QUERY_CACHE
++  ulong requested= query_cache_size;
++  query_cache.resize(query_cache_size);
++  if (requested != query_cache_size)
++    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++			ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE),
++			requested, query_cache_size);
++#endif
++}
++
++
++#ifdef HAVE_QUERY_CACHE
++static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type)
++{
++  query_cache_min_res_unit=
++    query_cache.set_min_res_unit(query_cache_min_res_unit);
++}
++#endif
++
++
++extern void fix_delay_key_write(THD *thd, enum_var_type type)
++{
++  switch ((enum_delay_key_write) delay_key_write_options) {
++  case DELAY_KEY_WRITE_NONE:
++    myisam_delay_key_write=0;
++    break;
++  case DELAY_KEY_WRITE_ON:
++    myisam_delay_key_write=1;
++    break;
++  case DELAY_KEY_WRITE_ALL:
++    myisam_delay_key_write=1;
++    ha_open_options|= HA_OPEN_DELAY_KEY_WRITE;
++    break;
++  }
++}
++
++static void fix_max_binlog_size(THD *thd, enum_var_type type)
++{
++  DBUG_ENTER("fix_max_binlog_size");
++  DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
++                     max_binlog_size, max_relay_log_size));
++  mysql_bin_log.set_max_size(max_binlog_size);
++#ifdef HAVE_REPLICATION
++  if (!max_relay_log_size)
++    active_mi->rli.relay_log.set_max_size(max_binlog_size);
++#endif
++  DBUG_VOID_RETURN;
++}
++
++static void fix_max_relay_log_size(THD *thd, enum_var_type type)
++{
++  DBUG_ENTER("fix_max_relay_log_size");
++  DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
++                     max_binlog_size, max_relay_log_size));
++#ifdef HAVE_REPLICATION
++  active_mi->rli.relay_log.set_max_size(max_relay_log_size ?
++                                        max_relay_log_size: max_binlog_size);
++#endif
++  DBUG_VOID_RETURN;
++}
++
++
++static int check_max_delayed_threads(THD *thd, set_var *var)
++{
++  longlong val= var->value->val_int();
++  if (var->type != OPT_GLOBAL && val != 0 &&
++      val != (longlong) global_system_variables.max_insert_delayed_threads)
++  {
++    char buf[64];
++    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf));
++    return 1;
++  }
++  return 0;
++}
++
++static void fix_max_connections(THD *thd, enum_var_type type)
++{
++#ifndef EMBEDDED_LIBRARY
++  resize_thr_alarm(max_connections +
++		   global_system_variables.max_insert_delayed_threads + 10);
++#endif
++}
++
++
++static void fix_thd_mem_root(THD *thd, enum_var_type type)
++{
++  if (type != OPT_GLOBAL)
++    reset_root_defaults(thd->mem_root,
++                        thd->variables.query_alloc_block_size,
++                        thd->variables.query_prealloc_size);
++}
++
++
++static void fix_trans_mem_root(THD *thd, enum_var_type type)
++{
++#ifdef USING_TRANSACTIONS
++  if (type != OPT_GLOBAL)
++    reset_root_defaults(&thd->transaction.mem_root,
++                        thd->variables.trans_alloc_block_size,
++                        thd->variables.trans_prealloc_size);
++#endif
++}
++
++
++static void fix_server_id(THD *thd, enum_var_type type)
++{
++  server_id_supplied = 1;
++}
++
++
++sys_var_long_ptr::
++sys_var_long_ptr(const char *name_arg, ulong *value_ptr_arg,
++                 sys_after_update_func after_update_arg)
++  :sys_var_long_ptr_global(name_arg, value_ptr_arg,
++                           &LOCK_global_system_variables, after_update_arg)
++{}
++
++
++bool sys_var_long_ptr_global::check(THD *thd, set_var *var)
++{
++  longlong v= var->value->val_int();
++  var->save_result.ulonglong_value= v < 0 ? 0 : v;
++  return 0;
++}
++
++bool sys_var_long_ptr_global::update(THD *thd, set_var *var)
++{
++  ulonglong tmp= var->save_result.ulonglong_value;
++  pthread_mutex_lock(guard);
++  if (option_limits)
++    *value= (ulong) getopt_ull_limit_value(tmp, option_limits);
++  else
++    *value= (ulong) tmp;
++  pthread_mutex_unlock(guard);
++  return 0;
++}
++
++
++void sys_var_long_ptr_global::set_default(THD *thd, enum_var_type type)
++{
++  pthread_mutex_lock(guard);
++  *value= (ulong) option_limits->def_value;
++  pthread_mutex_unlock(guard);
++}
++
++
++bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var)
++{
++  ulonglong tmp= var->save_result.ulonglong_value;
++  pthread_mutex_lock(&LOCK_global_system_variables);
++  if (option_limits)
++    *value= (ulonglong) getopt_ull_limit_value(tmp, option_limits);
++  else
++    *value= (ulonglong) tmp;
++  pthread_mutex_unlock(&LOCK_global_system_variables);
++  return 0;
++}
++
++
++void sys_var_ulonglong_ptr::set_default(THD *thd, enum_var_type type)
++{
++  pthread_mutex_lock(&LOCK_global_system_variables);
++  *value= (ulonglong) option_limits->def_value;
++  pthread_mutex_unlock(&LOCK_global_system_variables);
++}
++
++
++bool sys_var_bool_ptr::update(THD *thd, set_var *var)
++{
++  *value= (my_bool) var->save_result.ulong_value;
++  return 0;
++}
++
++
++void sys_var_bool_ptr::set_default(THD *thd, enum_var_type type)
++{
++  *value= (my_bool) option_limits->def_value;
++}
++
++
++bool sys_var_enum::update(THD *thd, set_var *var)
++{
++  *value= (uint) var->save_result.ulong_value;
++  return 0;
++}
++
++
++byte *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
++{
++  return (byte*) enum_names->type_names[*value];
++}
++
++bool sys_var_thd_ulong::check(THD *thd, set_var *var)
++{
++  return (sys_var_thd::check(thd, var) ||
++          (check_func && (*check_func)(thd, var)));
++}
++
++bool sys_var_thd_ulong::update(THD *thd, set_var *var)
++{
++  ulonglong tmp= var->save_result.ulonglong_value;
++
++  /* Don't use bigger value than given with --maximum-variable-name=.. */
++  if ((ulong) tmp > max_system_variables.*offset)
++    tmp= max_system_variables.*offset;
++
++#if SIZEOF_LONG == 4
++  /* Avoid overflows on 32 bit systems */
++  if (tmp > (ulonglong) ~(ulong) 0)
++    tmp= ((ulonglong) ~(ulong) 0);
++#endif
++
++  if (option_limits)
++    tmp= (ulong) getopt_ull_limit_value(tmp, option_limits);
++  if (var->type == OPT_GLOBAL)
++    global_system_variables.*offset= (ulong) tmp;
++  else
++    thd->variables.*offset= (ulong) tmp;
++  return 0;
++}
++
++
++void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++  {
++    /* We will not come here if option_limits is not set */
++    global_system_variables.*offset= (ulong) option_limits->def_value;
++  }
++  else
++    thd->variables.*offset= global_system_variables.*offset;
++}
++
++
++byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type,
++				   LEX_STRING *base)
++{
++  if (type == OPT_GLOBAL)
++    return (byte*) &(global_system_variables.*offset);
++  return (byte*) &(thd->variables.*offset);
++}
++
++
++bool sys_var_thd_ha_rows::update(THD *thd, set_var *var)
++{
++  ulonglong tmp= var->save_result.ulonglong_value;
++
++  /* Don't use bigger value than given with --maximum-variable-name=.. */
++  if ((ha_rows) tmp > max_system_variables.*offset)
++    tmp= max_system_variables.*offset;
++
++  if (option_limits)
++    tmp= (ha_rows) getopt_ull_limit_value(tmp, option_limits);
++  if (var->type == OPT_GLOBAL)
++  {
++    /* Lock is needed to make things safe on 32 bit systems */
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    global_system_variables.*offset= (ha_rows) tmp;
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++  }
++  else
++    thd->variables.*offset= (ha_rows) tmp;
++  return 0;
++}
++
++
++void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++  {
++    /* We will not come here if option_limits is not set */
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    global_system_variables.*offset= (ha_rows) option_limits->def_value;
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++  }
++  else
++    thd->variables.*offset= global_system_variables.*offset;
++}
++
++
++byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type,
++				     LEX_STRING *base)
++{
++  if (type == OPT_GLOBAL)
++    return (byte*) &(global_system_variables.*offset);
++  return (byte*) &(thd->variables.*offset);
++}
++
++bool sys_var_thd_ulonglong::update(THD *thd,  set_var *var)
++{
++  ulonglong tmp= var->save_result.ulonglong_value;
++
++  if (tmp > max_system_variables.*offset)
++    tmp= max_system_variables.*offset;
++
++  if (option_limits)
++    tmp= getopt_ull_limit_value(tmp, option_limits);
++  if (var->type == OPT_GLOBAL)
++  {
++    /* Lock is needed to make things safe on 32 bit systems */
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    global_system_variables.*offset= (ulonglong) tmp;
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++  }
++  else
++    thd->variables.*offset= (ulonglong) tmp;
++  return 0;
++}
++
++
++void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++  {
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    global_system_variables.*offset= (ulonglong) option_limits->def_value;
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++  }
++  else
++    thd->variables.*offset= global_system_variables.*offset;
++}
++
++
++byte *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type,
++				       LEX_STRING *base)
++{
++  if (type == OPT_GLOBAL)
++    return (byte*) &(global_system_variables.*offset);
++  return (byte*) &(thd->variables.*offset);
++}
++
++
++bool sys_var_thd_bool::update(THD *thd,  set_var *var)
++{
++  if (var->type == OPT_GLOBAL)
++    global_system_variables.*offset= (my_bool) var->save_result.ulong_value;
++  else
++    thd->variables.*offset= (my_bool) var->save_result.ulong_value;
++  return 0;
++}
++
++
++void sys_var_thd_bool::set_default(THD *thd,  enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    global_system_variables.*offset= (my_bool) option_limits->def_value;
++  else
++    thd->variables.*offset= global_system_variables.*offset;
++}
++
++
++byte *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type,
++				  LEX_STRING *base)
++{
++  if (type == OPT_GLOBAL)
++    return (byte*) &(global_system_variables.*offset);
++  return (byte*) &(thd->variables.*offset);
++}
++
++
++bool sys_var::check_enum(THD *thd, set_var *var, TYPELIB *enum_names)
++{
++  char buff[STRING_BUFFER_USUAL_SIZE];
++  const char *value;
++  String str(buff, sizeof(buff), system_charset_info), *res;
++
++  if (var->value->result_type() == STRING_RESULT)
++  {
++    if (!(res=var->value->val_str(&str)) ||
++	((long) (var->save_result.ulong_value=
++		 (ulong) find_type(enum_names, res->ptr(),
++				   res->length(),1)-1)) < 0)
++    {
++      value= res ? res->c_ptr() : "NULL";
++      goto err;
++    }
++  }
++  else
++  {
++    ulonglong tmp=var->value->val_int();
++    if (tmp >= enum_names->count)
++    {
++      llstr(tmp,buff);
++      value=buff;				// Wrong value is here
++      goto err;
++    }
++    var->save_result.ulong_value= (ulong) tmp;	// Save for update
++  }
++  return 0;
++
++err:
++  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, value);
++  return 1;
++}
++
++
++bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names)
++{
++  bool not_used;
++  char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
++  uint error_len= 0;
++  String str(buff, sizeof(buff), system_charset_info), *res;
++
++  if (var->value->result_type() == STRING_RESULT)
++  {
++    if (!(res= var->value->val_str(&str)))
++    {
++      strmov(buff, "NULL");
++      goto err;
++    }
++    var->save_result.ulong_value= ((ulong)
++				   find_set(enum_names, res->c_ptr(),
++					    res->length(),
++                                            NULL,
++                                            &error, &error_len,
++					    &not_used));
++    if (error_len)
++    {
++      strmake(buff, error, min(sizeof(buff), error_len));
++      goto err;
++    }
++  }
++  else
++  {
++    ulonglong tmp= var->value->val_int();
++   /*
++     For when the enum is made to contain 64 elements, as 1ULL<<64 is
++     undefined, we guard with a "count<64" test.
++   */
++    if (unlikely((tmp >= ((ULL(1)) << enum_names->count)) &&
++                 (enum_names->count < 64)))
++    {
++      llstr(tmp, buff);
++      goto err;
++    }
++    var->save_result.ulong_value= (ulong) tmp;  // Save for update
++  }
++  return 0;
++
++err:
++  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buff);
++  return 1;
++}
++
++
++/*
++  Return an Item for a variable.  Used with @@[global.]variable_name
++  If type is not given, return local value if exists, else global
++*/
++
++Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
++{
++  if (check_type(var_type))
++  {
++    if (var_type != OPT_DEFAULT)
++    {
++      my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0),
++               name, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL");
++      return 0;
++    }
++    /* As there was no local variable, return the global value */
++    var_type= OPT_GLOBAL;
++  }
++  switch (show_type()) {
++  case SHOW_INT:
++  {
++    uint value;
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    value= *(uint*) value_ptr(thd, var_type, base);
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++    return new Item_uint((ulonglong) value);
++  }
++  case SHOW_LONG:
++  {
++    ulong value;
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    value= *(ulong*) value_ptr(thd, var_type, base);
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++    return new Item_uint((ulonglong) value);
++  }
++  case SHOW_LONGLONG:
++  {
++    longlong value;
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    value= *(longlong*) value_ptr(thd, var_type, base);
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++    return new Item_int(value);
++  }
++  case SHOW_HA_ROWS:
++  {
++    ha_rows value;
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    value= *(ha_rows*) value_ptr(thd, var_type, base);
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++    return new Item_int((longlong) value);
++  }
++  case SHOW_MY_BOOL:
++    return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type, base),1);
++  case SHOW_CHAR:
++  {
++    Item *tmp;
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    char *str= (char*) value_ptr(thd, var_type, base);
++    if (str)
++      tmp= new Item_string(str, strlen(str),
++                           system_charset_info, DERIVATION_SYSCONST);
++    else
++    {
++      tmp= new Item_null();
++      tmp->collation.set(system_charset_info, DERIVATION_SYSCONST);
++    }
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++    return tmp;
++  }
++  default:
++    my_error(ER_VAR_CANT_BE_READ, MYF(0), name);
++  }
++  return 0;
++}
++
++
++bool sys_var_thd_enum::update(THD *thd, set_var *var)
++{
++  if (var->type == OPT_GLOBAL)
++    global_system_variables.*offset= var->save_result.ulong_value;
++  else
++    thd->variables.*offset= var->save_result.ulong_value;
++  return 0;
++}
++
++
++void sys_var_thd_enum::set_default(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    global_system_variables.*offset= (ulong) option_limits->def_value;
++  else
++    thd->variables.*offset= global_system_variables.*offset;
++}
++
++
++byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type,
++				  LEX_STRING *base)
++{
++  ulong tmp= ((type == OPT_GLOBAL) ?
++	      global_system_variables.*offset :
++	      thd->variables.*offset);
++  return (byte*) enum_names->type_names[tmp];
++}
++
++bool sys_var_thd_bit::check(THD *thd, set_var *var)
++{
++  return (check_enum(thd, var, &bool_typelib) ||
++          (check_func && (*check_func)(thd, var)));
++}
++
++bool sys_var_thd_bit::update(THD *thd, set_var *var)
++{
++  int res= (*update_func)(thd, var);
++  return res;
++}
++
++
++byte *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type,
++				 LEX_STRING *base)
++{
++  /*
++    If reverse is 0 (default) return 1 if bit is set.
++    If reverse is 1, return 0 if bit is set
++  */
++  thd->sys_var_tmp.my_bool_value= ((thd->options & bit_flag) ?
++				   !reverse : reverse);
++  return (byte*) &thd->sys_var_tmp.my_bool_value;
++}
++
++
++/* Update a date_time format variable based on given value */
++
++void sys_var_thd_date_time_format::update2(THD *thd, enum_var_type type,
++					   DATE_TIME_FORMAT *new_value)
++{
++  DATE_TIME_FORMAT *old;
++  DBUG_ENTER("sys_var_date_time_format::update2");
++  DBUG_DUMP("positions",(char*) new_value->positions,
++	    sizeof(new_value->positions));
++
++  if (type == OPT_GLOBAL)
++  {
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    old= (global_system_variables.*offset);
++    (global_system_variables.*offset)= new_value;
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++  }
++  else
++  {
++    old= (thd->variables.*offset);
++    (thd->variables.*offset)= new_value;
++  }
++  my_free((char*) old, MYF(MY_ALLOW_ZERO_PTR));
++  DBUG_VOID_RETURN;
++}
++
++
++bool sys_var_thd_date_time_format::update(THD *thd, set_var *var)
++{
++  DATE_TIME_FORMAT *new_value;
++  /* We must make a copy of the last value to get it into normal memory */
++  new_value= date_time_format_copy((THD*) 0,
++				   var->save_result.date_time_format);
++  if (!new_value)
++    return 1;					// Out of memory
++  update2(thd, var->type, new_value);		// Can't fail
++  return 0;
++}
++
++
++bool sys_var_thd_date_time_format::check(THD *thd, set_var *var)
++{
++  char buff[STRING_BUFFER_USUAL_SIZE];
++  String str(buff,sizeof(buff), system_charset_info), *res;
++  DATE_TIME_FORMAT *format;
++
++  if (!(res=var->value->val_str(&str)))
++    res= &my_empty_string;
++
++  if (!(format= date_time_format_make(date_time_type,
++				      res->ptr(), res->length())))
++  {
++    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, res->c_ptr());
++    return 1;
++  }
++
++  /*
++    We must copy result to thread space to not get a memory leak if
++    update is aborted
++  */
++  var->save_result.date_time_format= date_time_format_copy(thd, format);
++  my_free((char*) format, MYF(0));
++  return var->save_result.date_time_format == 0;
++}
++
++
++void sys_var_thd_date_time_format::set_default(THD *thd, enum_var_type type)
++{
++  DATE_TIME_FORMAT *res= 0;
++
++  if (type == OPT_GLOBAL)
++  {
++    const char *format;
++    if ((format= opt_date_time_formats[date_time_type]))
++      res= date_time_format_make(date_time_type, format, strlen(format));
++  }
++  else
++  {
++    /* Make copy with malloc */
++    res= date_time_format_copy((THD *) 0, global_system_variables.*offset);
++  }
++
++  if (res)					// Should always be true
++    update2(thd, type, res);
++}
++
++
++byte *sys_var_thd_date_time_format::value_ptr(THD *thd, enum_var_type type,
++					      LEX_STRING *base)
++{
++  if (type == OPT_GLOBAL)
++  {
++    char *res;
++    /*
++      We do a copy here just to be sure things will work even if someone
++      is modifying the original string while the copy is accessed
++      (Can't happen now in SQL SHOW, but this is a good safety for the future)
++    */
++    res= thd->strmake((global_system_variables.*offset)->format.str,
++		      (global_system_variables.*offset)->format.length);
++    return (byte*) res;
++  }
++  return (byte*) (thd->variables.*offset)->format.str;
++}
++
++
++typedef struct old_names_map_st
++{
++  const char *old_name;
++  const char *new_name;
++} my_old_conv;
++
++static my_old_conv old_conv[]=
++{
++  {	"cp1251_koi8"		,	"cp1251"	},
++  {	"cp1250_latin2"		,	"cp1250"	},
++  {	"kam_latin2"		,	"keybcs2"	},
++  {	"mac_latin2"		,	"MacRoman"	},
++  {	"macce_latin2"		,	"MacCE"		},
++  {	"pc2_latin2"		,	"pclatin2"	},
++  {	"vga_latin2"		,	"pclatin1"	},
++  {	"koi8_cp1251"		,	"koi8r"		},
++  {	"win1251ukr_koi8_ukr"	,	"win1251ukr"	},
++  {	"koi8_ukr_win1251ukr"	,	"koi8u"		},
++  {	NULL			,	NULL		}
++};
++
++CHARSET_INFO *get_old_charset_by_name(const char *name)
++{
++  my_old_conv *conv;
++
++  for (conv= old_conv; conv->old_name; conv++)
++  {
++    if (!my_strcasecmp(&my_charset_latin1, name, conv->old_name))
++      return get_charset_by_csname(conv->new_name, MY_CS_PRIMARY, MYF(0));
++  }
++  return NULL;
++}
++
++
++bool sys_var_collation::check(THD *thd, set_var *var)
++{
++  CHARSET_INFO *tmp;
++
++  if (var->value->result_type() == STRING_RESULT)
++  {
++    char buff[STRING_BUFFER_USUAL_SIZE];
++    String str(buff,sizeof(buff), system_charset_info), *res;
++    if (!(res=var->value->val_str(&str)))
++    {
++      my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
++      return 1;
++    }
++    if (!(tmp=get_charset_by_name(res->c_ptr(),MYF(0))))
++    {
++      my_error(ER_UNKNOWN_COLLATION, MYF(0), res->c_ptr());
++      return 1;
++    }
++  }
++  else // INT_RESULT
++  {
++    if (!(tmp=get_charset((int) var->value->val_int(),MYF(0))))
++    {
++      char buf[20];
++      int10_to_str((int) var->value->val_int(), buf, -10);
++      my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
++      return 1;
++    }
++  }
++  var->save_result.charset= tmp;	// Save for update
++  return 0;
++}
++
++
++bool sys_var_character_set::check(THD *thd, set_var *var)
++{
++  CHARSET_INFO *tmp;
++
++  if (var->value->result_type() == STRING_RESULT)
++  {
++    char buff[STRING_BUFFER_USUAL_SIZE];
++    String str(buff,sizeof(buff), system_charset_info), *res;
++    if (!(res=var->value->val_str(&str)))
++    {
++      if (!nullable)
++      {
++        my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
++        return 1;
++      }
++      tmp= NULL;
++    }
++    else if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) &&
++             !(tmp=get_old_charset_by_name(res->c_ptr())))
++    {
++      my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), res->c_ptr());
++      return 1;
++    }
++  }
++  else // INT_RESULT
++  {
++    if (!(tmp=get_charset((int) var->value->val_int(),MYF(0))))
++    {
++      char buf[20];
++      int10_to_str((int) var->value->val_int(), buf, -10);
++      my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), buf);
++      return 1;
++    }
++  }
++  var->save_result.charset= tmp;	// Save for update
++  return 0;
++}
++
++
++bool sys_var_character_set::update(THD *thd, set_var *var)
++{
++  ci_ptr(thd,var->type)[0]= var->save_result.charset;
++  thd->update_charset();
++  return 0;
++}
++
++
++byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type,
++				       LEX_STRING *base)
++{
++  CHARSET_INFO *cs= ci_ptr(thd,type)[0];
++  return cs ? (byte*) cs->csname : (byte*) NULL;
++}
++
++
++CHARSET_INFO ** sys_var_character_set_connection::ci_ptr(THD *thd,
++							 enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    return &global_system_variables.collation_connection;
++  else
++    return &thd->variables.collation_connection;
++}
++
++
++void sys_var_character_set_connection::set_default(THD *thd,
++						   enum_var_type type)
++{
++ if (type == OPT_GLOBAL)
++   global_system_variables.collation_connection= default_charset_info;
++ else
++ {
++   thd->variables.collation_connection= global_system_variables.collation_connection;
++   thd->update_charset();
++ }
++}
++
++
++CHARSET_INFO ** sys_var_character_set_client::ci_ptr(THD *thd,
++						     enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    return &global_system_variables.character_set_client;
++  else
++    return &thd->variables.character_set_client;
++}
++
++
++void sys_var_character_set_client::set_default(THD *thd, enum_var_type type)
++{
++ if (type == OPT_GLOBAL)
++   global_system_variables.character_set_client= default_charset_info;
++ else
++ {
++   thd->variables.character_set_client= (global_system_variables.
++					 character_set_client);
++   thd->update_charset();
++ }
++}
++
++
++CHARSET_INFO **
++sys_var_character_set_filesystem::ci_ptr(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    return &global_system_variables.character_set_filesystem;
++  else
++    return &thd->variables.character_set_filesystem;
++}
++
++
++extern CHARSET_INFO *character_set_filesystem;
++
++void
++sys_var_character_set_filesystem::set_default(THD *thd, enum_var_type type)
++{
++ if (type == OPT_GLOBAL)
++   global_system_variables.character_set_filesystem= character_set_filesystem;
++ else
++ {
++   thd->variables.character_set_filesystem= (global_system_variables.
++					     character_set_filesystem);
++   thd->update_charset();
++ }
++}
++
++
++CHARSET_INFO **
++sys_var_character_set_results::ci_ptr(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    return &global_system_variables.character_set_results;
++  else
++    return &thd->variables.character_set_results;
++}
++
++
++void sys_var_character_set_results::set_default(THD *thd, enum_var_type type)
++{
++ if (type == OPT_GLOBAL)
++   global_system_variables.character_set_results= default_charset_info;
++ else
++ {
++   thd->variables.character_set_results= (global_system_variables.
++					  character_set_results);
++   thd->update_charset();
++ }
++}
++
++
++CHARSET_INFO **
++sys_var_character_set_server::ci_ptr(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    return &global_system_variables.collation_server;
++  else
++    return &thd->variables.collation_server;
++}
++
++
++void sys_var_character_set_server::set_default(THD *thd, enum_var_type type)
++{
++ if (type == OPT_GLOBAL)
++   global_system_variables.collation_server= default_charset_info;
++ else
++ {
++   thd->variables.collation_server= global_system_variables.collation_server;
++   thd->update_charset();
++ }
++}
++
++CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd,
++						       enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    return &global_system_variables.collation_database;
++  else
++    return &thd->variables.collation_database;
++}
++
++
++void sys_var_character_set_database::set_default(THD *thd, enum_var_type type)
++{
++ if (type == OPT_GLOBAL)
++    global_system_variables.collation_database= default_charset_info;
++  else
++  {
++    thd->variables.collation_database= thd->db_charset;
++    thd->update_charset();
++  }
++}
++
++
++bool sys_var_collation_connection::update(THD *thd, set_var *var)
++{
++  if (var->type == OPT_GLOBAL)
++    global_system_variables.collation_connection= var->save_result.charset;
++  else
++  {
++    thd->variables.collation_connection= var->save_result.charset;
++    thd->update_charset();
++  }
++  return 0;
++}
++
++
++byte *sys_var_collation_connection::value_ptr(THD *thd, enum_var_type type,
++					      LEX_STRING *base)
++{
++  CHARSET_INFO *cs= ((type == OPT_GLOBAL) ?
++		  global_system_variables.collation_connection :
++		  thd->variables.collation_connection);
++  return cs ? (byte*) cs->name : (byte*) "NULL";
++}
++
++
++void sys_var_collation_connection::set_default(THD *thd, enum_var_type type)
++{
++ if (type == OPT_GLOBAL)
++   global_system_variables.collation_connection= default_charset_info;
++ else
++ {
++   thd->variables.collation_connection= (global_system_variables.
++					 collation_connection);
++   thd->update_charset();
++ }
++}
++
++bool sys_var_collation_database::update(THD *thd, set_var *var)
++{
++  if (var->type == OPT_GLOBAL)
++    global_system_variables.collation_database= var->save_result.charset;
++  else
++  {
++    thd->variables.collation_database= var->save_result.charset;
++    thd->update_charset();
++  }
++  return 0;
++}
++
++
++byte *sys_var_collation_database::value_ptr(THD *thd, enum_var_type type,
++					      LEX_STRING *base)
++{
++  CHARSET_INFO *cs= ((type == OPT_GLOBAL) ?
++		  global_system_variables.collation_database :
++		  thd->variables.collation_database);
++  return cs ? (byte*) cs->name : (byte*) "NULL";
++}
++
++
++void sys_var_collation_database::set_default(THD *thd, enum_var_type type)
++{
++ if (type == OPT_GLOBAL)
++   global_system_variables.collation_database= default_charset_info;
++ else
++ {
++   thd->variables.collation_database= (global_system_variables.
++					 collation_database);
++   thd->update_charset();
++ }
++}
++
++
++bool sys_var_collation_server::update(THD *thd, set_var *var)
++{
++  if (var->type == OPT_GLOBAL)
++    global_system_variables.collation_server= var->save_result.charset;
++  else
++  {
++    thd->variables.collation_server= var->save_result.charset;
++    thd->update_charset();
++  }
++  return 0;
++}
++
++
++byte *sys_var_collation_server::value_ptr(THD *thd, enum_var_type type,
++					      LEX_STRING *base)
++{
++  CHARSET_INFO *cs= ((type == OPT_GLOBAL) ?
++		  global_system_variables.collation_server :
++		  thd->variables.collation_server);
++  return cs ? (byte*) cs->name : (byte*) "NULL";
++}
++
++
++void sys_var_collation_server::set_default(THD *thd, enum_var_type type)
++{
++ if (type == OPT_GLOBAL)
++   global_system_variables.collation_server= default_charset_info;
++ else
++ {
++   thd->variables.collation_server= (global_system_variables.
++					 collation_server);
++   thd->update_charset();
++ }
++}
++
++
++LEX_STRING default_key_cache_base= {(char *) "default", 7 };
++
++static KEY_CACHE zero_key_cache;
++
++KEY_CACHE *get_key_cache(LEX_STRING *cache_name)
++{
++  safe_mutex_assert_owner(&LOCK_global_system_variables);
++  if (!cache_name || ! cache_name->length)
++    cache_name= &default_key_cache_base;
++  return ((KEY_CACHE*) find_named(&key_caches,
++                                      cache_name->str, cache_name->length, 0));
++}
++
++
++byte *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type,
++					 LEX_STRING *base)
++{
++  KEY_CACHE *key_cache= get_key_cache(base);
++  if (!key_cache)
++    key_cache= &zero_key_cache;
++  return (byte*) key_cache + offset ;
++}
++
++
++bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
++{
++  ulonglong tmp= var->save_result.ulonglong_value;
++  LEX_STRING *base_name= &var->base;
++  KEY_CACHE *key_cache;
++  bool error= 0;
++
++  /* If no basename, assume it's for the key cache named 'default' */
++  if (!base_name->length)
++    base_name= &default_key_cache_base;
++
++  pthread_mutex_lock(&LOCK_global_system_variables);
++  key_cache= get_key_cache(base_name);
++
++  if (!key_cache)
++  {
++    /* Key cache didn't exists */
++    if (!tmp)					// Tried to delete cache
++      goto end;					// Ok, nothing to do
++    if (!(key_cache= create_key_cache(base_name->str, base_name->length)))
++    {
++      error= 1;
++      goto end;
++    }
++  }
++
++  /*
++    Abort if some other thread is changing the key cache
++    TODO: This should be changed so that we wait until the previous
++    assignment is done and then do the new assign
++  */
++  if (key_cache->in_init)
++    goto end;
++
++  if (!tmp)					// Zero size means delete
++  {
++    if (key_cache == dflt_key_cache)
++    {
++      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++                          ER_WARN_CANT_DROP_DEFAULT_KEYCACHE,
++                          ER(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE));
++      goto end;					// Ignore default key cache
++    }
++
++    if (key_cache->key_cache_inited)		// If initied
++    {
++      /*
++	Move tables using this key cache to the default key cache
++	and clear the old key cache.
++      */
++      NAMED_LIST *list;
++      key_cache= (KEY_CACHE *) find_named(&key_caches, base_name->str,
++					      base_name->length, &list);
++      key_cache->in_init= 1;
++      pthread_mutex_unlock(&LOCK_global_system_variables);
++      error= reassign_keycache_tables(thd, key_cache, dflt_key_cache);
++      pthread_mutex_lock(&LOCK_global_system_variables);
++      key_cache->in_init= 0;
++    }
++    /*
++      We don't delete the key cache as some running threads my still be
++      in the key cache code with a pointer to the deleted (empty) key cache
++    */
++    goto end;
++  }
++
++  key_cache->param_buff_size=
++    (ulonglong) getopt_ull_limit_value(tmp, option_limits);
++
++  /* If key cache didn't existed initialize it, else resize it */
++  key_cache->in_init= 1;
++  pthread_mutex_unlock(&LOCK_global_system_variables);
++
++  if (!key_cache->key_cache_inited)
++    error= (bool) (ha_init_key_cache("", key_cache));
++  else
++    error= (bool)(ha_resize_key_cache(key_cache));
++
++  pthread_mutex_lock(&LOCK_global_system_variables);
++  key_cache->in_init= 0;
++
++end:
++  pthread_mutex_unlock(&LOCK_global_system_variables);
++  return error;
++}
++
++
++bool sys_var_key_cache_long::update(THD *thd, set_var *var)
++{
++  ulong tmp= (ulong) var->value->val_int();
++  LEX_STRING *base_name= &var->base;
++  bool error= 0;
++
++  if (!base_name->length)
++    base_name= &default_key_cache_base;
++
++  pthread_mutex_lock(&LOCK_global_system_variables);
++  KEY_CACHE *key_cache= get_key_cache(base_name);
++
++  if (!key_cache && !(key_cache= create_key_cache(base_name->str,
++				                  base_name->length)))
++  {
++    error= 1;
++    goto end;
++  }
++
++  /*
++    Abort if some other thread is changing the key cache
++    TODO: This should be changed so that we wait until the previous
++    assignment is done and then do the new assign
++  */
++  if (key_cache->in_init)
++    goto end;
++
++  *((ulong*) (((char*) key_cache) + offset))=
++    (ulong) getopt_ull_limit_value(tmp, option_limits);
++
++  /*
++    Don't create a new key cache if it didn't exist
++    (key_caches are created only when the user sets block_size)
++  */
++  key_cache->in_init= 1;
++
++  pthread_mutex_unlock(&LOCK_global_system_variables);
++
++  error= (bool) (ha_resize_key_cache(key_cache));
++
++  pthread_mutex_lock(&LOCK_global_system_variables);
++  key_cache->in_init= 0;
++
++end:
++  pthread_mutex_unlock(&LOCK_global_system_variables);
++  return error;
++}
++
++
++/*****************************************************************************
++  Functions to handle SET NAMES and SET CHARACTER SET
++*****************************************************************************/
++
++int set_var_collation_client::check(THD *thd)
++{
++  return 0;
++}
++
++int set_var_collation_client::update(THD *thd)
++{
++  thd->variables.character_set_client= character_set_client;
++  thd->variables.character_set_results= character_set_results;
++  thd->variables.collation_connection= collation_connection;
++  thd->update_charset();
++  thd->protocol_simple.init(thd);
++  thd->protocol_prep.init(thd);
++  return 0;
++}
++
++/****************************************************************************/
++
++bool sys_var_timestamp::update(THD *thd,  set_var *var)
++{
++  thd->set_time((time_t) var->save_result.ulonglong_value);
++  return 0;
++}
++
++
++void sys_var_timestamp::set_default(THD *thd, enum_var_type type)
++{
++  thd->user_time=0;
++}
++
++
++byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type,
++				   LEX_STRING *base)
++{
++  thd->sys_var_tmp.long_value= (long) thd->start_time;
++  return (byte*) &thd->sys_var_tmp.long_value;
++}
++
++
++bool sys_var_last_insert_id::update(THD *thd, set_var *var)
++{
++  thd->insert_id(var->save_result.ulonglong_value);
++  return 0;
++}
++
++
++byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type,
++					LEX_STRING *base)
++{
++  if (!thd->last_insert_id_used)
++  {
++    /*
++      As this statement reads @@LAST_INSERT_ID, set
++      THD::last_insert_id_used and remember first generated insert id
++      of the previous statement in THD::current_insert_id.
++    */
++    thd->last_insert_id_used= TRUE;
++    thd->last_insert_id_used_bin_log= TRUE;
++    thd->current_insert_id= thd->last_insert_id;
++  }
++  return (byte*) &thd->current_insert_id;
++}
++
++
++bool sys_var_insert_id::update(THD *thd, set_var *var)
++{
++  thd->next_insert_id= var->save_result.ulonglong_value;
++  return 0;
++}
++
++
++byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type,
++				   LEX_STRING *base)
++{
++  return (byte*) &thd->next_insert_id;
++}
++
++
++#ifdef HAVE_REPLICATION
++bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
++{
++  int result= 0;
++  pthread_mutex_lock(&LOCK_active_mi);
++  pthread_mutex_lock(&active_mi->rli.run_lock);
++  if (active_mi->rli.slave_running)
++  {
++    my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
++    result=1;
++  }
++  pthread_mutex_unlock(&active_mi->rli.run_lock);
++  pthread_mutex_unlock(&LOCK_active_mi);
++  var->save_result.ulong_value= (ulong) var->value->val_int();
++  return result;
++}
++
++
++bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
++{
++  pthread_mutex_lock(&LOCK_active_mi);
++  pthread_mutex_lock(&active_mi->rli.run_lock);
++  /*
++    The following test should normally never be true as we test this
++    in the check function;  To be safe against multiple
++    SQL_SLAVE_SKIP_COUNTER request, we do the check anyway
++  */
++  if (!active_mi->rli.slave_running)
++  {
++    pthread_mutex_lock(&active_mi->rli.data_lock);
++    active_mi->rli.slave_skip_counter= var->save_result.ulong_value;
++    pthread_mutex_unlock(&active_mi->rli.data_lock);
++  }
++  pthread_mutex_unlock(&active_mi->rli.run_lock);
++  pthread_mutex_unlock(&LOCK_active_mi);
++  return 0;
++}
++
++
++bool sys_var_sync_binlog_period::update(THD *thd, set_var *var)
++{
++  sync_binlog_period= (ulong) var->save_result.ulonglong_value;
++  return 0;
++}
++#endif /* HAVE_REPLICATION */
++
++bool sys_var_rand_seed1::update(THD *thd, set_var *var)
++{
++  thd->rand.seed1= (ulong) var->save_result.ulonglong_value;
++  return 0;
++}
++
++bool sys_var_rand_seed2::update(THD *thd, set_var *var)
++{
++  thd->rand.seed2= (ulong) var->save_result.ulonglong_value;
++  return 0;
++}
++
++
++bool sys_var_thd_time_zone::check(THD *thd, set_var *var)
++{
++  char buff[MAX_TIME_ZONE_NAME_LENGTH];
++  String str(buff, sizeof(buff), &my_charset_latin1);
++  String *res= var->value->val_str(&str);
++
++  if (!(var->save_result.time_zone=
++        my_tz_find(res, thd->lex->time_zone_tables_used)))
++  {
++    my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), res ? res->c_ptr() : "NULL");
++    return 1;
++  }
++  return 0;
++}
++
++
++bool sys_var_thd_time_zone::update(THD *thd, set_var *var)
++{
++  /* We are using Time_zone object found during check() phase. */
++  if (var->type == OPT_GLOBAL)
++  {
++    pthread_mutex_lock(&LOCK_global_system_variables);
++    global_system_variables.time_zone= var->save_result.time_zone;
++    pthread_mutex_unlock(&LOCK_global_system_variables);
++  }
++  else
++    thd->variables.time_zone= var->save_result.time_zone;
++  return 0;
++}
++
++
++byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type,
++				       LEX_STRING *base)
++{
++  /*
++    We can use ptr() instead of c_ptr() here because String contaning
++    time zone name is guaranteed to be zero ended.
++  */
++  if (type == OPT_GLOBAL)
++    return (byte *)(global_system_variables.time_zone->get_name()->ptr());
++  else
++  {
++    /*
++      This is an ugly fix for replication: we don't replicate properly queries
++      invoking system variables' values to update tables; but
++      CONVERT_TZ(,,@@session.time_zone) is so popular that we make it
++      replicable (i.e. we tell the binlog code to store the session
++      timezone). If it's the global value which was used we can't replicate
++      (binlog code stores session value only).
++    */
++    thd->time_zone_used= 1;
++    return (byte *)(thd->variables.time_zone->get_name()->ptr());
++  }
++}
++
++
++void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type)
++{
++ pthread_mutex_lock(&LOCK_global_system_variables);
++ if (type == OPT_GLOBAL)
++ {
++   if (default_tz_name)
++   {
++     String str(default_tz_name, &my_charset_latin1);
++     /*
++       We are guaranteed to find this time zone since its existence
++       is checked during start-up.
++     */
++     global_system_variables.time_zone=
++       my_tz_find(&str, thd->lex->time_zone_tables_used);
++   }
++   else
++     global_system_variables.time_zone= my_tz_SYSTEM;
++ }
++ else
++   thd->variables.time_zone= global_system_variables.time_zone;
++ pthread_mutex_unlock(&LOCK_global_system_variables);
++}
++
++
++bool sys_var_max_user_conn::check(THD *thd, set_var *var)
++{
++  if (var->type == OPT_GLOBAL)
++    return sys_var_thd::check(thd, var);
++  else
++  {
++    /*
++      Per-session values of max_user_connections can't be set directly.
++      QQ: May be we should have a separate error message for this?
++    */
++    my_error(ER_GLOBAL_VARIABLE, MYF(0), name);
++    return TRUE;
++  }
++}
++
++bool sys_var_max_user_conn::update(THD *thd, set_var *var)
++{
++  DBUG_ASSERT(var->type == OPT_GLOBAL);
++  pthread_mutex_lock(&LOCK_global_system_variables);
++  max_user_connections= (uint)var->save_result.ulonglong_value;
++  pthread_mutex_unlock(&LOCK_global_system_variables);
++  return 0;
++}
++
++
++void sys_var_max_user_conn::set_default(THD *thd, enum_var_type type)
++{
++  DBUG_ASSERT(type == OPT_GLOBAL);
++  pthread_mutex_lock(&LOCK_global_system_variables);
++  max_user_connections= (ulong) option_limits->def_value;
++  pthread_mutex_unlock(&LOCK_global_system_variables);
++}
++
++
++byte *sys_var_max_user_conn::value_ptr(THD *thd, enum_var_type type,
++                                       LEX_STRING *base)
++{
++  if (type != OPT_GLOBAL &&
++      thd->user_connect && thd->user_connect->user_resources.user_conn)
++    return (byte*) &(thd->user_connect->user_resources.user_conn);
++  return (byte*) &(max_user_connections);
++}
++
++
++bool sys_var_thd_lc_time_names::check(THD *thd, set_var *var)
++{
++  MY_LOCALE *locale_match;
++
++  if (var->value->result_type() == INT_RESULT)
++  {
++    if (!(locale_match= my_locale_by_number((uint) var->value->val_int())))
++    {
++      char buf[20];
++      int10_to_str((int) var->value->val_int(), buf, -10);
++      my_printf_error(ER_UNKNOWN_ERROR, "Unknown locale: '%s'", MYF(0), buf);
++      return 1;
++    }
++  }
++  else // STRING_RESULT
++  {
++    char buff[6]; 
++    String str(buff, sizeof(buff), &my_charset_latin1), *res;
++    if (!(res=var->value->val_str(&str)))
++    {
++      my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
++      return 1;
++    }
++    const char *locale_str= res->c_ptr();
++    if (!(locale_match= my_locale_by_name(locale_str)))
++    {
++      my_printf_error(ER_UNKNOWN_ERROR,
++                      "Unknown locale: '%s'", MYF(0), locale_str);
++      return 1;
++    }
++  }
++
++  var->save_result.locale_value= locale_match;
++  return 0;
++}
++
++
++bool sys_var_thd_lc_time_names::update(THD *thd, set_var *var)
++{
++  if (var->type == OPT_GLOBAL)
++    global_system_variables.lc_time_names= var->save_result.locale_value;
++  else
++    thd->variables.lc_time_names= var->save_result.locale_value;
++  return 0;
++}
++
++
++byte *sys_var_thd_lc_time_names::value_ptr(THD *thd, enum_var_type type,
++					  LEX_STRING *base)
++{
++  return type == OPT_GLOBAL ?
++                 (byte *) global_system_variables.lc_time_names->name :
++                 (byte *) thd->variables.lc_time_names->name;
++}
++
++
++void sys_var_thd_lc_time_names::set_default(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    global_system_variables.lc_time_names= my_default_lc_time_names;
++  else
++    thd->variables.lc_time_names= global_system_variables.lc_time_names;
++}
++
++/*
++  Functions to update thd->options bits
++*/
++
++static bool set_option_bit(THD *thd, set_var *var)
++{
++  sys_var_thd_bit *sys_var= ((sys_var_thd_bit*) var->var);
++  if ((var->save_result.ulong_value != 0) == sys_var->reverse)
++    thd->options&= ~sys_var->bit_flag;
++  else
++    thd->options|= sys_var->bit_flag;
++  return 0;
++}
++
++
++static bool set_option_autocommit(THD *thd, set_var *var)
++{
++  /* The test is negative as the flag we use is NOT autocommit */
++
++  ulonglong org_options= thd->options;
++
++  if (var->save_result.ulong_value != 0)
++    thd->options&= ~((sys_var_thd_bit*) var->var)->bit_flag;
++  else
++    thd->options|= ((sys_var_thd_bit*) var->var)->bit_flag;
++
++  if ((org_options ^ thd->options) & OPTION_NOT_AUTOCOMMIT)
++  {
++    if ((org_options & OPTION_NOT_AUTOCOMMIT))
++    {
++      /* We changed to auto_commit mode */
++      thd->options&= ~OPTION_BEGIN;
++      thd->transaction.all.modified_non_trans_table= FALSE;
++      thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
++      if (ha_commit(thd))
++	return 1;
++    }
++    else
++    {
++      thd->transaction.all.modified_non_trans_table= FALSE;
++      thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
++    }
++  }
++  return 0;
++}
++
++static int check_log_update(THD *thd, set_var *var)
++{
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  if (!(thd->security_ctx->master_access & SUPER_ACL))
++  {
++    my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
++    return 1;
++  }
++#endif
++  return 0;
++}
++
++static bool set_log_update(THD *thd, set_var *var)
++{
++  /*
++    The update log is not supported anymore since 5.0.
++    See sql/mysqld.cc/, comments in function init_server_components() for an
++    explaination of the different warnings we send below
++  */
++
++  if (opt_sql_bin_update)
++  {
++    ((sys_var_thd_bit*) var->var)->bit_flag|= (OPTION_BIN_LOG |
++					       OPTION_UPDATE_LOG);
++    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
++                 ER_UPDATE_LOG_DEPRECATED_TRANSLATED,
++                 ER(ER_UPDATE_LOG_DEPRECATED_TRANSLATED));
++  }
++  else
++    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
++                 ER_UPDATE_LOG_DEPRECATED_IGNORED,
++                 ER(ER_UPDATE_LOG_DEPRECATED_IGNORED));
++  set_option_bit(thd, var);
++  return 0;
++}
++
++static bool set_log_bin(THD *thd, set_var *var)
++{
++  if (opt_sql_bin_update)
++    ((sys_var_thd_bit*) var->var)->bit_flag|= (OPTION_BIN_LOG |
++					       OPTION_UPDATE_LOG);
++  set_option_bit(thd, var);
++  return 0;
++}
++
++static int check_pseudo_thread_id(THD *thd, set_var *var)
++{
++  var->save_result.ulonglong_value= var->value->val_int();
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  if (thd->security_ctx->master_access & SUPER_ACL)
++    return 0;
++  else
++  {
++    my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
++    return 1;
++  }
++#else
++  return 0;
++#endif
++}
++
++static byte *get_warning_count(THD *thd)
++{
++  thd->sys_var_tmp.long_value=
++    (thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
++     thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
++     thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
++  return (byte*) &thd->sys_var_tmp.long_value;
++}
++
++static byte *get_error_count(THD *thd)
++{
++  thd->sys_var_tmp.long_value=
++    thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
++  return (byte*) &thd->sys_var_tmp.long_value;
++}
++
++
++static byte *get_have_innodb(THD *thd)
++{
++  return (byte*) show_comp_option_name[have_innodb];
++}
++
++
++/*
++  Get the tmpdir that was specified or chosen by default
++
++  SYNOPSIS
++    get_tmpdir()
++    thd		thread handle
++
++  DESCRIPTION
++    This is necessary because if the user does not specify a temporary
++    directory via the command line, one is chosen based on the environment
++    or system defaults.  But we can't just always use mysql_tmpdir, because
++    that is actually a call to my_tmpdir() which cycles among possible
++    temporary directories.
++
++  RETURN VALUES
++    ptr		pointer to NUL-terminated string
++ */
++static byte *get_tmpdir(THD *thd)
++{
++  if (opt_mysql_tmpdir)
++    return (byte *)opt_mysql_tmpdir;
++  return (byte*)mysql_tmpdir;
++}
++
++/****************************************************************************
++  Main handling of variables:
++  - Initialisation
++  - Searching during parsing
++  - Update loop
++****************************************************************************/
++
++/*
++  Find variable name in option my_getopt structure used for command line args
++
++  SYNOPSIS
++    find_option()
++    opt		option structure array to search in
++    name	variable name
++
++  RETURN VALUES
++    0		Error
++    ptr		pointer to option structure
++*/
++
++static struct my_option *find_option(struct my_option *opt, const char *name)
++{
++  uint length=strlen(name);
++  for (; opt->name; opt++)
++  {
++    if (!getopt_compare_strings(opt->name, name, length) &&
++	!opt->name[length])
++    {
++      /*
++	Only accept the option if one can set values through it.
++	If not, there is no default value or limits in the option.
++      */
++      return (opt->value) ? opt : 0;
++    }
++  }
++  return 0;
++}
++
++
++/*
++  Return variable name and length for hashing of variables
++*/
++
++static byte *get_sys_var_length(const sys_var *var, uint *length,
++				my_bool first)
++{
++  *length= var->name_length;
++  return (byte*) var->name;
++}
++
++
++/*
++  Initialises sys variables and put them in system_variable_hash
++*/
++
++
++void set_var_init()
++{
++  hash_init(&system_variable_hash, system_charset_info,
++	    array_elements(sys_variables),0,0,
++	    (hash_get_key) get_sys_var_length,0,0);
++  sys_var **var, **end;
++  for (var= sys_variables, end= sys_variables+array_elements(sys_variables) ;
++       var < end;
++       var++)
++  {
++    (*var)->name_length= strlen((*var)->name);
++    (*var)->option_limits= find_option(my_long_options, (*var)->name);
++    my_hash_insert(&system_variable_hash, (byte*) *var);
++  }
++  /*
++    Special cases
++    Needed because MySQL can't find the limits for a variable it it has
++    a different name than the command line option.
++    As these variables are deprecated, this code will disappear soon...
++  */
++  sys_sql_max_join_size.option_limits= sys_max_join_size.option_limits;
++}
++
++
++void set_var_free()
++{
++  hash_free(&system_variable_hash);
++}
++
++
++/*
++  Find a user set-table variable
++
++  SYNOPSIS
++    find_sys_var()
++    str		Name of system variable to find
++    length	Length of variable.  zero means that we should use strlen()
++		on the variable
++
++  RETURN VALUES
++    pointer	pointer to variable definitions
++    0		Unknown variable (error message is given)
++*/
++
++sys_var *find_sys_var(const char *str, uint length)
++{
++  sys_var *var= (sys_var*) hash_search(&system_variable_hash,
++				       (byte*) str,
++				       length ? length :
++				       strlen(str));
++  if (!var)
++    my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
++  return var;
++}
++
++
++/*
++  Execute update of all variables
++
++  SYNOPSIS
++
++  sql_set
++    THD		Thread id
++    set_var	List of variables to update
++
++  DESCRIPTION
++    First run a check of all variables that all updates will go ok.
++    If yes, then execute all updates, returning an error if any one failed.
++
++    This should ensure that in all normal cases none all or variables are
++    updated
++
++    RETURN VALUE
++    0	ok
++    1	ERROR, message sent (normally no variables was updated)
++    -1  ERROR, message not sent
++*/
++
++int sql_set_variables(THD *thd, List<set_var_base> *var_list)
++{
++  int error;
++  List_iterator_fast<set_var_base> it(*var_list);
++  DBUG_ENTER("sql_set_variables");
++
++  set_var_base *var;
++  while ((var=it++))
++  {
++    if ((error= var->check(thd)))
++      goto err;
++  }
++  if (!(error= test(thd->net.report_error)))
++  {
++    it.rewind();
++    while ((var= it++))
++      error|= var->update(thd);         // Returns 0, -1 or 1
++  }
++
++err:
++  free_underlaid_joins(thd, &thd->lex->select_lex);
++  DBUG_RETURN(error);
++}
++
++
++/*
++  Say if all variables set by a SET support the ONE_SHOT keyword (currently,
++  only character set and collation do; later timezones will).
++
++  SYNOPSIS
++
++  not_all_support_one_shot
++    set_var	List of variables to update
++
++  NOTES
++    It has a "not_" because it makes faster tests (no need to "!")
++
++    RETURN VALUE
++    0	all variables of the list support ONE_SHOT
++    1	at least one does not support ONE_SHOT
++*/
++
++bool not_all_support_one_shot(List<set_var_base> *var_list)
++{
++  List_iterator_fast<set_var_base> it(*var_list);
++  set_var_base *var;
++  while ((var= it++))
++  {
++    if (var->no_support_one_shot())
++      return 1;
++  }
++  return 0;
++}
++
++
++/*****************************************************************************
++  Functions to handle SET mysql_internal_variable=const_expr
++*****************************************************************************/
++
++int set_var::check(THD *thd)
++{
++  if (var->is_readonly())
++  {
++    my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name, "read only");
++    return -1;
++  }
++  if (var->check_type(type))
++  {
++    int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
++    my_error(err, MYF(0), var->name);
++    return -1;
++  }
++  if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))
++    return 1;
++  /* value is a NULL pointer if we are using SET ... = DEFAULT */
++  if (!value)
++  {
++    if (var->check_default(type))
++    {
++      my_error(ER_NO_DEFAULT, MYF(0), var->name);
++      return -1;
++    }
++    return 0;
++  }
++
++  if ((!value->fixed &&
++       value->fix_fields(thd, &value)) || value->check_cols(1))
++    return -1;
++  if (var->check_update_type(value->result_type()))
++  {
++    my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name);
++    return -1;
++  }
++  return var->check(thd, this) ? -1 : 0;
++}
++
++
++/*
++  Check variable, but without assigning value (used by PS)
++
++  SYNOPSIS
++    set_var::light_check()
++    thd		thread handler
++
++  RETURN VALUE
++    0	ok
++    1	ERROR, message sent (normally no variables was updated)
++    -1  ERROR, message not sent
++*/
++int set_var::light_check(THD *thd)
++{
++  if (var->check_type(type))
++  {
++    int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
++    my_error(err, MYF(0), var->name);
++    return -1;
++  }
++  if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
++    return 1;
++
++  if (value && ((!value->fixed && value->fix_fields(thd, &value)) ||
++                value->check_cols(1)))
++    return -1;
++  return 0;
++}
++
++
++int set_var::update(THD *thd)
++{
++  if (!value)
++    var->set_default(thd, type);
++  else if (var->update(thd, this))
++    return -1;				// should never happen
++  if (var->after_update)
++    (*var->after_update)(thd, type);
++  return 0;
++}
++
++
++/*****************************************************************************
++  Functions to handle SET @user_variable=const_expr
++*****************************************************************************/
++
++int set_var_user::check(THD *thd)
++{
++  /*
++    Item_func_set_user_var can't substitute something else on its place =>
++    0 can be passed as last argument (reference on item)
++  */
++  return (user_var_item->fix_fields(thd, (Item**) 0) ||
++	  user_var_item->check(0)) ? -1 : 0;
++}
++
++
++/*
++  Check variable, but without assigning value (used by PS)
++
++  SYNOPSIS
++    set_var_user::light_check()
++    thd		thread handler
++
++  RETURN VALUE
++    0	ok
++    1	ERROR, message sent (normally no variables was updated)
++    -1  ERROR, message not sent
++*/
++int set_var_user::light_check(THD *thd)
++{
++  /*
++    Item_func_set_user_var can't substitute something else on its place =>
++    0 can be passed as last argument (reference on item)
++  */
++  return (user_var_item->fix_fields(thd, (Item**) 0));
++}
++
++
++int set_var_user::update(THD *thd)
++{
++  if (user_var_item->update())
++  {
++    /* Give an error if it's not given already */
++    my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
++    return -1;
++  }
++  return 0;
++}
++
++
++/*****************************************************************************
++  Functions to handle SET PASSWORD
++*****************************************************************************/
++
++int set_var_password::check(THD *thd)
++{
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  if (!user->host.str)
++  {
++    if (*thd->security_ctx->priv_host != 0)
++    {
++      user->host.str= (char *) thd->security_ctx->priv_host;
++      user->host.length= strlen(thd->security_ctx->priv_host);
++    }
++    else
++    {
++      user->host.str= (char *)"%";
++      user->host.length= 1;
++    }
++  }
++  /* Returns 1 as the function sends error to client */
++  return check_change_password(thd, user->host.str, user->user.str,
++                               password, strlen(password)) ? 1 : 0;
++#else
++  return 0;
++#endif
++}
++
++int set_var_password::update(THD *thd)
++{
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  /* Returns 1 as the function sends error to client */
++  return change_password(thd, user->host.str, user->user.str, password) ?
++	  1 : 0;
++#else
++  return 0;
++#endif
++}
++
++/****************************************************************************
++ Functions to handle table_type
++****************************************************************************/
++
++/* Based upon sys_var::check_enum() */
++
++bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
++{
++  char buff[STRING_BUFFER_USUAL_SIZE];
++  const char *value;
++  String str(buff, sizeof(buff), &my_charset_latin1), *res;
++
++  if (var->value->result_type() == STRING_RESULT)
++  {
++    enum db_type db_type;
++    if (!(res=var->value->val_str(&str)) ||
++	!(var->save_result.ulong_value=
++          (ulong) (db_type= ha_resolve_by_name(res->ptr(), res->length()))) ||
++        ha_checktype(thd, db_type, 1, 0) != db_type)
++    {
++      value= res ? res->c_ptr() : "NULL";
++      goto err;
++    }
++    return 0;
++  }
++  value= "unknown";
++
++err:
++  my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), value);
++  return 1;
++}
++
++
++byte *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type,
++					    LEX_STRING *base)
++{
++  ulong val;
++  val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
++        thd->variables.*offset);
++  const char *table_type= ha_get_storage_engine((enum db_type)val);
++  return (byte *) table_type;
++}
++
++
++void sys_var_thd_storage_engine::set_default(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    global_system_variables.*offset= (ulong) DB_TYPE_MYISAM;
++  else
++    thd->variables.*offset= (ulong) (global_system_variables.*offset);
++}
++
++
++bool sys_var_thd_storage_engine::update(THD *thd, set_var *var)
++{
++  if (var->type == OPT_GLOBAL)
++    global_system_variables.*offset= var->save_result.ulong_value;
++  else
++    thd->variables.*offset= var->save_result.ulong_value;
++  return 0;
++}
++
++void sys_var_thd_table_type::warn_deprecated(THD *thd)
++{
++  push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++		      ER_WARN_DEPRECATED_SYNTAX,
++		      ER(ER_WARN_DEPRECATED_SYNTAX), "table_type",
++                      "storage_engine");
++}
++
++void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type)
++{
++  warn_deprecated(thd);
++  sys_var_thd_storage_engine::set_default(thd, type);
++}
++
++bool sys_var_thd_table_type::update(THD *thd, set_var *var)
++{
++  warn_deprecated(thd);
++  return sys_var_thd_storage_engine::update(thd, var);
++}
++
++
++/****************************************************************************
++ Functions to handle sql_mode
++****************************************************************************/
++
++/*
++  Make string representation of mode
++
++  SYNOPSIS
++    thd   in  thread handler
++    val   in  sql_mode value
++    len   out pointer on length of string
++
++  RETURN
++    pointer to string with sql_mode representation
++*/
++
++byte *sys_var_thd_sql_mode::symbolic_mode_representation(THD *thd, ulong val,
++                                                         ulong *len)
++{
++  char buff[256];
++  String tmp(buff, sizeof(buff), &my_charset_latin1);
++  ulong length;
++
++  tmp.length(0);
++  for (uint i= 0; val; val>>= 1, i++)
++  {
++    if (val & 1)
++    {
++      tmp.append(sql_mode_typelib.type_names[i],
++                 sql_mode_typelib.type_lengths[i]);
++      tmp.append(',');
++    }
++  }
++
++  if ((length= tmp.length()))
++    length--;
++  *len= length;
++  return (byte*) thd->strmake(tmp.ptr(), length);
++}
++
++
++byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type,
++				      LEX_STRING *base)
++{
++  ulong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
++              thd->variables.*offset);
++  ulong length_unused;
++  return symbolic_mode_representation(thd, val, &length_unused);
++}
++
++
++void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    global_system_variables.*offset= 0;
++  else
++    thd->variables.*offset= global_system_variables.*offset;
++}
++
++
++void fix_sql_mode_var(THD *thd, enum_var_type type)
++{
++  if (type == OPT_GLOBAL)
++    global_system_variables.sql_mode=
++      fix_sql_mode(global_system_variables.sql_mode);
++  else
++  {
++    thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode);
++    /*
++      Update thd->server_status
++     */
++    if (thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
++      thd->server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
++    else
++      thd->server_status&= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES;
++  }
++}
++
++/* Map database specific bits to function bits */
++
++ulong fix_sql_mode(ulong sql_mode)
++{
++  /*
++    Note that we dont set
++    MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS
++    to allow one to get full use of MySQL in this mode.
++  */
++
++  if (sql_mode & MODE_ANSI)
++  {
++    sql_mode|= (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
++		MODE_IGNORE_SPACE);
++    /*
++      MODE_ONLY_FULL_GROUP_BY removed from ANSI mode because it is currently
++      overly restrictive (see BUG#8510).
++    */
++  }
++  if (sql_mode & MODE_ORACLE)
++    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
++		MODE_IGNORE_SPACE |
++		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
++		MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
++  if (sql_mode & MODE_MSSQL)
++    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
++		MODE_IGNORE_SPACE |
++		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
++		MODE_NO_FIELD_OPTIONS);
++  if (sql_mode & MODE_POSTGRESQL)
++    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
++		MODE_IGNORE_SPACE |
++		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
++		MODE_NO_FIELD_OPTIONS);
++  if (sql_mode & MODE_DB2)
++    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
++		MODE_IGNORE_SPACE |
++		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
++		MODE_NO_FIELD_OPTIONS);
++  if (sql_mode & MODE_MAXDB)
++    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
++		MODE_IGNORE_SPACE |
++		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
++		MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
++  if (sql_mode & MODE_MYSQL40)
++    sql_mode|= MODE_HIGH_NOT_PRECEDENCE;
++  if (sql_mode & MODE_MYSQL323)
++    sql_mode|= MODE_HIGH_NOT_PRECEDENCE;
++  if (sql_mode & MODE_TRADITIONAL)
++    sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES |
++                MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
++                MODE_ERROR_FOR_DIVISION_BY_ZERO | MODE_NO_AUTO_CREATE_USER);
++  return sql_mode;
++}
++
++
++/****************************************************************************
++  Named list handling
++****************************************************************************/
++
++gptr find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
++		NAMED_LIST **found)
++{
++  I_List_iterator<NAMED_LIST> it(*list);
++  NAMED_LIST *element;
++  while ((element= it++))
++  {
++    if (element->cmp(name, length))
++    {
++      if (found)
++        *found= element;
++      return element->data;
++    }
++  }
++  return 0;
++}
++
++
++void delete_elements(I_List<NAMED_LIST> *list,
++		     void (*free_element)(const char *name, gptr))
++{
++  NAMED_LIST *element;
++  DBUG_ENTER("delete_elements");
++  while ((element= list->get()))
++  {
++    (*free_element)(element->name, element->data);
++    delete element;
++  }
++  DBUG_VOID_RETURN;
++}
++
++
++/* Key cache functions */
++
++static KEY_CACHE *create_key_cache(const char *name, uint length)
++{
++  KEY_CACHE *key_cache;
++  DBUG_ENTER("create_key_cache");
++  DBUG_PRINT("enter",("name: %.*s", length, name));
++
++  if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE),
++					     MYF(MY_ZEROFILL | MY_WME))))
++  {
++    if (!new NAMED_LIST(&key_caches, name, length, (gptr) key_cache))
++    {
++      my_free((char*) key_cache, MYF(0));
++      key_cache= 0;
++    }
++    else
++    {
++      /*
++	Set default values for a key cache
++	The values in dflt_key_cache_var is set by my_getopt() at startup
++
++	We don't set 'buff_size' as this is used to enable the key cache
++      */
++      key_cache->param_block_size=     dflt_key_cache_var.param_block_size;
++      key_cache->param_division_limit= dflt_key_cache_var.param_division_limit;
++      key_cache->param_age_threshold=  dflt_key_cache_var.param_age_threshold;
++    }
++  }
++  DBUG_RETURN(key_cache);
++}
++
++
++KEY_CACHE *get_or_create_key_cache(const char *name, uint length)
++{
++  LEX_STRING key_cache_name;
++  KEY_CACHE *key_cache;
++
++  key_cache_name.str= (char *) name;
++  key_cache_name.length= length;
++  pthread_mutex_lock(&LOCK_global_system_variables);
++  if (!(key_cache= get_key_cache(&key_cache_name)))
++    key_cache= create_key_cache(name, length);
++  pthread_mutex_unlock(&LOCK_global_system_variables);
++  return key_cache;
++}
++
++
++void free_key_cache(const char *name, KEY_CACHE *key_cache)
++{
++  ha_end_key_cache(key_cache);
++  my_free((char*) key_cache, MYF(0));
++}
++
++
++bool process_key_caches(int (* func) (const char *name, KEY_CACHE *))
++{
++  I_List_iterator<NAMED_LIST> it(key_caches);
++  NAMED_LIST *element;
++
++  while ((element= it++))
++  {
++    KEY_CACHE *key_cache= (KEY_CACHE *) element->data;
++    func(element->name, key_cache);
++  }
++  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
++****************************************************************************/
++
++#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
++template class List<set_var_base>;
++template class List_iterator_fast<set_var_base>;
++template class I_List_iterator<NAMED_LIST>;
++#endif
+diff -urNad trunk~/sql/share/Makefile.in trunk/sql/share/Makefile.in
+--- trunk~/sql/share/Makefile.in	2007-11-15 08:08:48.000000000 -0600
++++ trunk/sql/share/Makefile.in	2007-12-27 15:54:49.322265598 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/sql/sphinx/cmakelists.txt trunk/sql/sphinx/cmakelists.txt
+--- trunk~/sql/sphinx/cmakelists.txt	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/sphinx/cmakelists.txt	2007-12-27 15:54:49.322265598 -0600
+@@ -0,0 +1,6 @@
++SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
++SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
++
++INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
++                    ${CMAKE_SOURCE_DIR}/extra/yassl/include)
++ADD_LIBRARY(example ha_example.cc)
+diff -urNad trunk~/sql/sphinx/gen_data.php trunk/sql/sphinx/gen_data.php
+--- trunk~/sql/sphinx/gen_data.php	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/sphinx/gen_data.php	2007-12-27 15:54:49.322265598 -0600
+@@ -0,0 +1,37 @@
++<?php
++
++$file_name= $argv[1];
++
++//echo $file_name;
++
++$cont= file_get_contents($file_name);
++
++$words= explode(" ", $cont);
++
++//echo "words: ".(count($words))."\n";
++
++$cw = count($words);
++
++echo "REPLACE INTO test.documents ( id, group_id, date_added, title, content ) VALUES\n";
++
++
++for ($i=1; $i<=100000; $i++)
++{
++  $count_words= mt_rand(10,30);
++  $pred = "";
++  for ($j=0; $j<$count_words; $j++)
++  {
++    $pred .= chop($words[mt_rand(1, $cw-1)])." ";
++  }
++  $count_words= mt_rand(3,5);
++  $tit = "";
++  for ($j=0; $j<$count_words; $j++)
++  {
++    $tit .= chop($words[mt_rand(1, $cw-1)])." ";
++  }
++  echo "($i,".mt_rand(1,20).",NOW(),'".addslashes($tit)."','".addslashes($pred)."'),\n";
++}       
++  echo "(0,1,now(),'end','eND');\n";
++  
++
++?>
+diff -urNad trunk~/sql/sphinx/ha_sphinx.cc trunk/sql/sphinx/ha_sphinx.cc
+--- trunk~/sql/sphinx/ha_sphinx.cc	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/sphinx/ha_sphinx.cc	2007-12-27 15:54:49.326265826 -0600
+@@ -0,0 +1,2357 @@
++//
++// $Id: ha_sphinx.cc 870 2007-10-13 15:45:44Z shodan $
++//
++
++#ifdef USE_PRAGMA_IMPLEMENTATION
++#pragma implementation // gcc: Class implementation
++#endif
++
++#if _MSC_VER>=1400
++#define _CRT_SECURE_NO_DEPRECATE 1
++#define _CRT_NONSTDC_NO_DEPRECATE 1
++#endif
++
++#include <mysql_version.h>
++
++#if MYSQL_VERSION_ID>50100
++#include "mysql_priv.h"
++#include <mysql/plugin.h>
++#else
++#include "../mysql_priv.h"
++#endif
++
++#include <mysys_err.h>
++#include <my_sys.h>
++
++#ifndef __WIN__
++	// UNIX-specific
++	#include <my_net.h>
++	#include <netdb.h>
++#else
++	// Windows-specific
++	#include <io.h>
++	#define strcasecmp	stricmp
++	#define snprintf	_snprintf
++#endif
++
++#include <ctype.h>
++#include "ha_sphinx.h"
++
++#ifndef MSG_WAITALL
++#define MSG_WAITALL 0
++#endif
++
++#if _MSC_VER>=1400
++#pragma warning(push,4)
++#endif
++
++/////////////////////////////////////////////////////////////////////////////
++
++// FIXME! make this all dynamic
++#define SPHINXSE_MAX_FILTERS		32
++
++#define SPHINXSE_DEFAULT_HOST		"127.0.0.1"
++#define SPHINXSE_DEFAULT_PORT		3312
++#define SPHINXSE_DEFAULT_INDEX		"*"
++
++#define SPHINXSE_SYSTEM_COLUMNS		3
++
++#define SPHINXSE_MAX_ALLOC			(16*1024*1024)
++
++// FIXME! all the following is cut-n-paste from sphinx.h and searchd.cpp
++#define SPHINX_VERSION		"0.9.8"
++
++enum
++{
++	SPHINX_SEARCHD_PROTO	= 1,
++	SEARCHD_COMMAND_SEARCH	= 0,
++	VER_COMMAND_SEARCH		= 0x10B,
++};
++
++/// search query sorting orders
++enum ESphSortOrder
++{
++	SPH_SORT_RELEVANCE		= 0,	///< sort by document relevance desc, then by date
++	SPH_SORT_ATTR_DESC		= 1,	///< sort by document date desc, then by relevance desc
++	SPH_SORT_ATTR_ASC		= 2,	///< sort by document date asc, then by relevance desc
++	SPH_SORT_TIME_SEGMENTS	= 3,	///< sort by time segments (hour/day/week/etc) desc, then by relevance desc
++	SPH_SORT_EXTENDED		= 4,	///< sort by SQL-like expression (eg. "@relevance DESC, price ASC, @id DESC")
++
++	SPH_SORT_TOTAL
++};
++
++/// search query matching mode
++enum ESphMatchMode
++{
++	SPH_MATCH_ALL = 0,			///< match all query words
++	SPH_MATCH_ANY,				///< match any query word
++	SPH_MATCH_PHRASE,			///< match this exact phrase
++	SPH_MATCH_BOOLEAN,			///< match this boolean query
++	SPH_MATCH_EXTENDED,			///< match this extended query
++
++	SPH_MATCH_TOTAL
++};
++
++/// search query grouping mode
++enum ESphGroupBy
++{
++	SPH_GROUPBY_DAY		= 0,	///< group by day
++	SPH_GROUPBY_WEEK	= 1,	///< group by week
++	SPH_GROUPBY_MONTH	= 2,	///< group by month
++	SPH_GROUPBY_YEAR	= 3,	///< group by year
++	SPH_GROUPBY_ATTR	= 4		///< group by attribute value
++};
++
++/// known attribute types
++enum ESphAttrType
++{
++	SPH_ATTR_NONE		= 0,	///< not an attribute at all
++	SPH_ATTR_INTEGER	= 1,	///< this attr is just an integer
++	SPH_ATTR_TIMESTAMP	= 2		///< this attr is a timestamp
++};
++
++/// known answers
++enum
++{
++	SEARCHD_OK		= 0,	///< general success, command-specific reply follows
++	SEARCHD_ERROR	= 1,	///< general failure, error message follows
++	SEARCHD_RETRY	= 2,	///< temporary failure, error message follows, client should retry later
++	SEARCHD_WARNING	= 3		///< general success, warning message and command-specific reply follow
++};
++
++//////////////////////////////////////////////////////////////////////////////
++
++#define SPHINX_DEBUG_OUTPUT		0
++#define SPHINX_DEBUG_CALLS		0
++
++#include <stdarg.h>
++
++inline void SPH_DEBUG ( const char * format, ... )
++{
++	#if SPHINX_DEBUG_OUTPUT
++	va_list ap;
++	va_start ( ap, format );
++	fprintf ( stderr, "SphinxSE: " );
++	vfprintf ( stderr, format, ap );
++	fprintf ( stderr, "\n" );
++	va_end ( ap );
++	#endif
++}
++
++#if SPHINX_DEBUG_CALLS
++
++#define SPH_ENTER_FUNC() { SPH_DEBUG ( "enter %s", __FUNCTION__ ); }
++#define SPH_ENTER_METHOD() { SPH_DEBUG ( "enter %s(this=%08x)", __FUNCTION__, this ); }
++#define SPH_RET(_arg) { SPH_DEBUG ( "leave %s", __FUNCTION__ ); return _arg; }
++#define SPH_VOID_RET() { SPH_DEBUG ( "leave %s", __FUNCTION__ ); return; }
++
++#else
++
++#define SPH_ENTER_FUNC()
++#define SPH_ENTER_METHOD()
++#define SPH_RET(_arg) { return(_arg); }
++#define SPH_VOID_RET() { return; }
++
++#endif
++
++
++#define SafeDelete(_arg)		{ if ( _arg ) delete ( _arg );		(_arg) = NULL; }
++#define SafeDeleteArray(_arg)	{ if ( _arg ) delete [] ( _arg );	(_arg) = NULL; }
++
++//////////////////////////////////////////////////////////////////////////////
++
++/// a structure that will be shared among all open Sphinx SE handlers
++struct CSphSEShare
++{
++	pthread_mutex_t	m_tMutex;
++	THR_LOCK		m_tLock;
++
++	char *			m_sTable;
++	char *			m_sScheme;
++	char *			m_sHost;	///< points into m_sScheme buffer, DO NOT FREE EXPLICITLY
++	char *			m_sSocket;	///< points into m_sScheme buffer, DO NOT FREE EXPLICITLY
++	char *			m_sIndex;	///< points into m_sScheme buffer, DO NOT FREE EXPLICITLY
++	ushort			m_iPort;
++	uint			m_iTableNameLen;
++	uint			m_iUseCount;
++
++	int					m_iTableFields;
++	char **				m_sTableField;
++	enum_field_types *	m_eTableFieldType;
++
++	CSphSEShare ()
++		: m_sTable ( NULL )
++		, m_sScheme ( NULL )
++		, m_sHost ( NULL )
++		, m_sSocket ( NULL )
++		, m_sIndex ( NULL )
++		, m_iPort ( 0 )
++		, m_iTableNameLen ( 0 )
++		, m_iUseCount ( 1 )
++
++		, m_iTableFields ( 0 )
++		, m_sTableField ( NULL )
++		, m_eTableFieldType ( NULL )
++	{
++		thr_lock_init ( &m_tLock );
++		pthread_mutex_init ( &m_tMutex, MY_MUTEX_INIT_FAST );
++	}
++
++	~CSphSEShare ()
++	{
++		pthread_mutex_destroy ( &m_tMutex );
++		thr_lock_delete ( &m_tLock );
++
++		SafeDeleteArray ( m_sTable );
++		SafeDeleteArray ( m_sScheme );
++		ResetTable ();
++	}
++
++	void ResetTable ()
++	{
++		for ( int i=0; i<m_iTableFields; i++ )
++			SafeDeleteArray ( m_sTableField[i] );
++		SafeDeleteArray ( m_sTableField );
++		SafeDeleteArray ( m_eTableFieldType );
++	}
++};
++
++/// schema attribute
++struct CSphSEAttr
++{
++	char *			m_sName;		///< attribute name (received from Sphinx)
++	ESphAttrType	m_eType;		///< attribute type (received from Sphinx)
++	int				m_iField;		///< field index in current table (-1 if none)
++
++	CSphSEAttr()
++		: m_sName ( NULL )
++		, m_eType ( SPH_ATTR_NONE )
++		, m_iField ( -1 )
++	{}
++
++	~CSphSEAttr ()
++	{
++		SafeDeleteArray ( m_sName );
++	}
++};
++
++/// word stats
++struct CSphSEWordStats
++{
++	char *			m_sWord;
++	int				m_iDocs;
++	int				m_iHits;
++
++	CSphSEWordStats ()
++		: m_sWord ( NULL )
++		, m_iDocs ( 0 )
++		, m_iHits ( 0 )
++	{}
++
++	~CSphSEWordStats ()
++	{
++		SafeDeleteArray ( m_sWord );
++	}
++};
++
++/// request stats
++struct CSphSEStats
++{
++public:
++	int					m_iMatchesTotal;
++	int					m_iMatchesFound;
++	int					m_iQueryMsec;
++	int					m_iWords;
++	CSphSEWordStats *	m_dWords;
++	bool				m_bLastError;
++	char				m_sLastMessage[1024];
++
++	CSphSEStats()
++		: m_dWords ( NULL )
++	{
++		Reset ();
++	}
++
++	void Reset ()
++	{
++		m_iMatchesTotal = 0;
++		m_iMatchesFound = 0;
++		m_iQueryMsec = 0;
++		m_iWords = 0;
++		SafeDeleteArray ( m_dWords );
++		m_bLastError = false;
++		m_sLastMessage[0] = '\0';
++	}
++
++	~CSphSEStats()
++	{
++		Reset ();
++	}
++};
++
++/// search query filter
++struct CSphSEFilter
++{
++public:
++	char *			m_sAttrName;
++	uint32			m_uMinValue;
++	uint32			m_uMaxValue;
++	int				m_iValues;
++	uint32 *		m_pValues;
++	int				m_bExclude;
++
++public:
++	CSphSEFilter ()
++		: m_sAttrName ( NULL )
++		, m_uMinValue ( 0 )
++		, m_uMaxValue ( UINT_MAX )
++		, m_iValues ( 0 )
++		, m_pValues ( NULL )
++		, m_bExclude ( 0 )
++	{
++	}
++
++	~CSphSEFilter ()
++	{
++		SafeDeleteArray ( m_pValues );
++	}
++};
++
++/// client-side search query
++struct CSphSEQuery
++{
++private:
++	char *			m_sQueryBuffer;
++
++	const char *	m_sIndex;
++	int				m_iOffset;
++	int				m_iLimit;
++
++	char *			m_sQuery;
++	uint32 *		m_pWeights;
++	int				m_iWeights;
++	ESphMatchMode	m_eMode;
++	ESphSortOrder	m_eSort;
++	char *			m_sSortBy;
++	int				m_iMaxMatches;
++	uint32			m_iMinID;
++	uint32			m_iMaxID;
++
++	int				m_iFilters;
++	CSphSEFilter	m_dFilters[SPHINXSE_MAX_FILTERS];
++
++	ESphGroupBy		m_eGroupFunc;
++	char *			m_sGroupBy;
++	char *			m_sGroupSortBy;
++	int				m_iCutoff;
++	int				m_iRetryCount;
++	int				m_iRetryDelay;
++	char *			m_sGroupDistinct;							///< points to query buffer; do NOT delete
++	int				m_iIndexWeights;
++	char *			m_sIndexWeight[SPHINXSE_MAX_FILTERS];		///< points to query buffer; do NOT delete
++	int				m_iIndexWeight[SPHINXSE_MAX_FILTERS];
++
++public:
++	char			m_sParseError[256];
++
++public:
++	CSphSEQuery ( const char * sQuery, int iLength, const char * sIndex );
++	~CSphSEQuery ();
++
++	bool			Parse ();
++	int				BuildRequest ( char ** ppBuffer );
++
++protected:
++	char *			m_pBuf;
++	char *			m_pCur;
++	int				m_iBufLeft;
++	bool			m_bBufOverrun;
++
++	int				ParseArray ( uint32 ** ppValues, const char * sValue );
++	bool			ParseField ( char * sField );
++
++	void			SendBytes ( const void * pBytes, int iBytes );
++	void			SendWord ( short int v )		{ v = ntohs(v); SendBytes ( &v, sizeof(short int) ); }
++	void			SendInt ( int v )				{ v = ntohl(v); SendBytes ( &v, sizeof(int) ); }
++	void			SendDword ( uint v )			{ v = ntohl(v) ;SendBytes ( &v, sizeof(uint) ); }
++	void			SendString ( const char * v )	{ int iLen = strlen(v); SendDword(iLen); SendBytes ( v, iLen ); }
++};
++
++//////////////////////////////////////////////////////////////////////////////
++
++#if MYSQL_VERSION_ID>50100
++
++#if MYSQL_VERSION_ID<50114
++#error Sphinx SE requires MySQL 5.1.14 or higher if compiling for 5.1.x series!
++#endif
++
++static handler *	sphinx_create_handler ( handlerton * hton, TABLE_SHARE * table, MEM_ROOT * mem_root );
++static int			sphinx_init_func ( void * p );
++static int			sphinx_close_connection ( handlerton * hton, THD * thd );
++static int			sphinx_panic ( handlerton * hton, enum ha_panic_function flag );
++static bool			sphinx_show_status ( handlerton * hton, THD * thd, stat_print_fn * stat_print, enum ha_stat_type stat_type );
++
++#else
++
++static bool			sphinx_init_func_for_handlerton ();
++static int			sphinx_close_connection ( THD * thd );
++bool				sphinx_show_status ( THD * thd );
++
++#endif // >50100
++
++//////////////////////////////////////////////////////////////////////////////
++
++static const char	sphinx_hton_name[]		= "SPHINX";
++static const char	sphinx_hton_comment[]	= "Sphinx storage engine " SPHINX_VERSION;
++
++#if MYSQL_VERSION_ID<50100
++handlerton sphinx_hton =
++{
++	#ifdef MYSQL_HANDLERTON_INTERFACE_VERSION
++	MYSQL_HANDLERTON_INTERFACE_VERSION,
++	#endif
++	sphinx_hton_name,
++	SHOW_OPTION_YES,
++	sphinx_hton_comment,
++	DB_TYPE_SPHINX_DB,
++	sphinx_init_func_for_handlerton,
++	0,							// slot
++	0,							// savepoint size
++	sphinx_close_connection,	// close_connection
++	NULL,	// savepoint
++	NULL,	// rollback to savepoint
++	NULL,	// release savepoint
++	NULL,	// commit
++	NULL,	// rollback
++	NULL,	// prepare
++	NULL,	// recover
++	NULL,	// commit_by_xid
++	NULL,	// rollback_by_xid
++	NULL,	// create_cursor_read_view
++	NULL,	// set_cursor_read_view
++	NULL,	// close_cursor_read_view
++	HTON_CAN_RECREATE
++};
++#endif
++
++//////////////////////////////////////////////////////////////////////////////
++
++// variables for Sphinx shared methods
++pthread_mutex_t		sphinx_mutex;		// mutex to init the hash
++static int			sphinx_init = 0;	// flag whether the hash was initialized
++static HASH			sphinx_open_tables;	// hash used to track open tables
++
++//////////////////////////////////////////////////////////////////////////////
++// INITIALIZATION AND SHUTDOWN
++//////////////////////////////////////////////////////////////////////////////
++
++// hashing function
++#if MYSQL_VERSION_ID>=50120
++typedef size_t GetKeyLength_t;
++#else
++typedef uint GetKeyLength_t;
++#endif
++
++static byte * sphinx_get_key ( const byte * pSharePtr, GetKeyLength_t * pLength, my_bool )
++{
++	CSphSEShare * pShare = (CSphSEShare *) pSharePtr;
++	*pLength = (size_t) pShare->m_iTableNameLen;
++	return (byte*) pShare->m_sTable;
++}
++
++static int sphinx_init_func ( void * p )
++{
++	SPH_ENTER_FUNC();
++	if ( !sphinx_init )
++	{
++		sphinx_init = 1;
++		VOID ( pthread_mutex_init ( &sphinx_mutex, MY_MUTEX_INIT_FAST ) );
++		hash_init ( &sphinx_open_tables, system_charset_info, 32, 0, 0,
++			sphinx_get_key, 0, 0 );
++
++		#if MYSQL_VERSION_ID > 50100
++		handlerton * hton = (handlerton*) p;
++		hton->state				= SHOW_OPTION_YES;
++		hton->db_type			= DB_TYPE_DEFAULT;
++		hton->create			= sphinx_create_handler;
++		hton->close_connection	= sphinx_close_connection;
++		hton->show_status		= sphinx_show_status;
++		hton->panic				= sphinx_panic;
++		hton->flags				= HTON_CAN_RECREATE;
++		#endif
++	}
++	SPH_RET(0);
++}
++
++
++#if MYSQL_VERSION_ID<50100
++static bool sphinx_init_func_for_handlerton ()
++{
++	return sphinx_init_func ( &sphinx_hton );
++}
++#endif
++
++
++#if MYSQL_VERSION_ID>50100
++
++static int sphinx_close_connection ( handlerton * hton, THD * thd )
++{
++	// deallocate common handler data
++	SPH_ENTER_FUNC();
++	void ** tmp = thd_ha_data ( thd, hton );
++	CSphSEStats * pStats = (CSphSEStats*) (*tmp);
++	SafeDelete ( pStats );
++	*tmp = NULL;
++	SPH_RET(0);
++}
++
++
++static int sphinx_done_func ( void * p )
++{
++	SPH_ENTER_FUNC();
++
++	int error = 0;
++	if ( sphinx_init )
++	{
++		sphinx_init = 0;
++		if ( sphinx_open_tables.records )
++			error = 1;
++		hash_free ( &sphinx_open_tables );
++		pthread_mutex_destroy ( &sphinx_mutex );
++	}
++
++	SPH_RET(0);
++}
++
++
++static int sphinx_panic ( handlerton * hton, enum ha_panic_function flag )
++{
++	return sphinx_done_func ( hton );
++}
++
++#else
++
++static int sphinx_close_connection ( THD * thd )
++{
++	// deallocate common handler data
++	SPH_ENTER_FUNC();
++	CSphSEStats * pStats = (CSphSEStats*) thd->ha_data[sphinx_hton.slot];
++	SafeDelete ( pStats );
++	thd->ha_data[sphinx_hton.slot] = NULL;
++	SPH_RET(0);
++}
++
++#endif // >50100
++
++//////////////////////////////////////////////////////////////////////////////
++// SHOW STATUS
++//////////////////////////////////////////////////////////////////////////////
++
++#if MYSQL_VERSION_ID>50100
++static bool sphinx_show_status ( handlerton * hton, THD * thd, stat_print_fn * stat_print,
++	enum ha_stat_type stat_type )
++#else
++bool sphinx_show_status ( THD * thd )
++#endif
++{
++	SPH_ENTER_FUNC();
++
++#if MYSQL_VERSION_ID<50100
++	Protocol * protocol = thd->protocol;
++	List<Item> field_list;
++#endif
++
++	char buf1[IO_SIZE];
++	uint buf1len;
++	char buf2[IO_SIZE];
++	uint buf2len= 0;
++	String words;
++
++	buf1[0] = '\0';
++	buf2[0] = '\0';
++
++#if MYSQL_VERSION_ID>50100
++	CSphSEStats * pStats = (CSphSEStats*) ( *thd_ha_data ( thd, hton ) );
++#else
++	if ( have_sphinx_db!=SHOW_OPTION_YES )
++	{
++		my_message ( ER_NOT_SUPPORTED_YET,
++			"failed to call SHOW SPHINX STATUS: --skip-sphinx was specified",
++			MYF(0) );
++		SPH_RET(TRUE);
++	}
++	CSphSEStats * pStats = (CSphSEStats*) thd->ha_data[sphinx_hton.slot];
++#endif
++
++	if ( pStats )
++	{
++		buf1len = my_snprintf ( buf1, sizeof(buf1),
++			"total: %d, total found: %d, time: %d, words: %d", 
++			pStats->m_iMatchesTotal, pStats->m_iMatchesFound, pStats->m_iQueryMsec, pStats->m_iWords );
++
++#if MYSQL_VERSION_ID>50100
++		stat_print ( thd, sphinx_hton_name, strlen(sphinx_hton_name),
++			STRING_WITH_LEN("stats"), buf1, buf1len );
++#else
++		field_list.push_back ( new Item_empty_string ( "Type",10 ) );
++		field_list.push_back ( new Item_empty_string ( "Name",FN_REFLEN ) );
++		field_list.push_back ( new Item_empty_string ( "Status",10 ) );
++		if ( protocol->send_fields ( &field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF ) )
++			SPH_RET(TRUE);
++
++		protocol->prepare_for_resend ();
++		protocol->store ( STRING_WITH_LEN("SPHINX"), system_charset_info );
++		protocol->store ( STRING_WITH_LEN("stats"), system_charset_info );
++		protocol->store ( buf1, buf1len, system_charset_info );
++		if ( protocol->write() )
++			SPH_RET(TRUE);
++#endif
++
++		if ( pStats->m_iWords )
++		{
++			for ( int i=0; i<pStats->m_iWords; i++ )
++			{
++				CSphSEWordStats & tWord = pStats->m_dWords[i];
++				buf2len = my_snprintf ( buf2, sizeof(buf2), "%s%s:%d:%d ",
++					buf2, tWord.m_sWord, tWord.m_iDocs, tWord.m_iHits );
++			}
++
++#if MYSQL_VERSION_ID>50100
++			stat_print ( thd, sphinx_hton_name, strlen(sphinx_hton_name),
++				STRING_WITH_LEN("words"), buf2, buf2len );
++#else
++			protocol->prepare_for_resend ();
++			protocol->store ( STRING_WITH_LEN("SPHINX"), system_charset_info );
++			protocol->store ( STRING_WITH_LEN("words"), system_charset_info );
++			protocol->store ( buf2, buf2len, system_charset_info );
++			if ( protocol->write() )
++				SPH_RET(TRUE);
++#endif
++		}
++
++		// send last error or warning
++		if ( pStats->m_sLastMessage && pStats->m_sLastMessage[0] )
++		{
++			const char * sMessageType = pStats->m_bLastError ? "error" : "warning";
++
++#if MYSQL_VERSION_ID>50100
++			stat_print ( thd, sphinx_hton_name, strlen(sphinx_hton_name),
++				sMessageType, strlen(sMessageType), pStats->m_sLastMessage, strlen(pStats->m_sLastMessage) );
++#else
++			protocol->prepare_for_resend ();
++			protocol->store ( STRING_WITH_LEN("SPHINX"), system_charset_info );
++			protocol->store ( sMessageType, strlen(sMessageType), system_charset_info );
++			protocol->store ( pStats->m_sLastMessage, strlen(pStats->m_sLastMessage), system_charset_info );
++			if ( protocol->write() )
++				SPH_RET(TRUE);
++#endif
++		}
++
++	} else
++	{
++		#if MYSQL_VERSION_ID < 50100
++		field_list.push_back ( new Item_empty_string ( "Type", 10 ) );
++		field_list.push_back ( new Item_empty_string ( "Name", FN_REFLEN ) );
++		field_list.push_back ( new Item_empty_string ( "Status", 10 ) );
++		if ( protocol->send_fields ( &field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF ) )
++			SPH_RET(TRUE);
++
++		protocol->prepare_for_resend ();
++		protocol->store ( STRING_WITH_LEN("SPHINX"), system_charset_info );
++		protocol->store ( STRING_WITH_LEN("stats"), system_charset_info );
++		protocol->store ( STRING_WITH_LEN("no query has been executed yet"), system_charset_info );
++		if ( protocol->write() )
++			SPH_RET(TRUE);
++		#endif
++	}
++
++	#if MYSQL_VERSION_ID < 50100
++	send_eof(thd);
++	#endif
++
++	SPH_RET(FALSE);
++}
++
++//////////////////////////////////////////////////////////////////////////////
++// HELPERS
++//////////////////////////////////////////////////////////////////////////////
++
++static char * sphDup ( const char * sSrc, int iLen=-1 )
++{
++	if ( !sSrc )
++		return NULL;
++
++	if ( iLen<0 )
++		iLen = strlen(sSrc);
++
++	char * sRes = new char [ 1+iLen ];
++	memcpy ( sRes, sSrc, iLen );
++	sRes[iLen] = '\0';
++	return sRes;
++}
++
++
++static void sphLogError ( const char * sFmt, ... )
++{
++	// emit timestamp
++#ifdef __WIN__
++	SYSTEMTIME t;
++	GetLocalTime ( &t );
++
++	fprintf ( stderr, "%02d%02d%02d %2d:%02d:%02d SphinxSE: internal error: ",
++		(int)t.wYear % 100, (int)t.wMonth, (int)t.wDay,
++		(int)t.wHour, (int)t.wMinute, (int)t.wSecond );
++#else
++	// Unix version
++	time_t tStamp;
++	time ( &tStamp );
++
++	struct tm * pParsed;
++#ifdef HAVE_LOCALTIME_R
++	struct tm tParsed;
++	localtime_r ( &tStamp, &tParsed );
++	pParsed = &tParsed;
++#else
++	pParsed = localtime ( &tStamp );
++#endif // HAVE_LOCALTIME_R
++
++	fprintf ( stderr, "%02d%02d%02d %2d:%02d:%02d SphinxSE: internal error: ",
++		pParsed->tm_year % 100, pParsed->tm_mon + 1, pParsed->tm_mday,
++		pParsed->tm_hour, pParsed->tm_min, pParsed->tm_sec);
++#endif // __WIN__
++
++	// emit message
++	va_list ap;
++	va_start ( ap, sFmt );
++	vfprintf ( stderr, sFmt, ap );
++	va_end ( ap );
++
++	// emit newline
++	fprintf ( stderr, "\n" );
++}
++
++
++
++// the following scheme variants are recognized
++//
++// sphinx://host/index
++// sphinx://host:port/index
++static bool ParseUrl ( CSphSEShare * share, TABLE * table, bool bCreate )
++{
++	SPH_ENTER_FUNC();
++
++	if ( share )
++	{
++		// check incoming stuff
++		if ( !table )
++		{
++			sphLogError ( "table==NULL in ParseUrl()" ); 
++			return false;
++		}
++		if ( !table->s )
++		{
++			sphLogError ( "(table->s)==NULL in ParseUrl()" ); 
++			return false;
++		}
++
++		// free old stuff
++		share->ResetTable ();
++
++		// fill new stuff
++		share->m_iTableFields = table->s->fields;
++		if ( share->m_iTableFields )
++		{
++			share->m_sTableField = new char * [ share->m_iTableFields ];
++			share->m_eTableFieldType = new enum_field_types [ share->m_iTableFields ];
++
++			for ( int i=0; i<share->m_iTableFields; i++ )
++			{
++				share->m_sTableField[i] = sphDup ( table->field[i]->field_name );
++				share->m_eTableFieldType[i] = table->field[i]->type();
++			}
++		}
++	}
++
++	char * sScheme = NULL;
++	char * sHost = SPHINXSE_DEFAULT_HOST;
++	char * sIndex = SPHINXSE_DEFAULT_INDEX;
++	int iPort = SPHINXSE_DEFAULT_PORT;
++
++	bool bOk = true;
++	while ( table->s->connect_string.length!=0 )
++	{
++		bOk = false;
++		sScheme = sphDup ( table->s->connect_string.str, table->s->connect_string.length );
++
++		sHost = strstr ( sScheme, "://" );
++		if ( !sHost )
++			break;
++		sHost[0] = '\0';
++		sHost += 3;
++
++		if ( strcmp ( sScheme, "sphinx" )!=0 )
++			break;
++
++		char * sPort = strchr ( sHost, ':' );
++		if ( sPort )
++		{
++			*sPort++ = '\0';
++			if ( *sPort )
++			{
++				sIndex = strchr ( sPort, '/' );
++				if ( sIndex )
++					*sIndex++ = '\0'; 
++				else
++					sIndex = SPHINXSE_DEFAULT_INDEX;
++
++				iPort = atoi(sPort);
++				if ( !iPort )
++					iPort = SPHINXSE_DEFAULT_PORT;
++			}
++		} else
++		{
++			sIndex = strchr ( sHost, '/' );
++			if ( sIndex )
++				*sIndex++ = '\0';
++			else
++				sIndex = SPHINXSE_DEFAULT_INDEX;
++		}
++
++		bOk = true;
++		break;
++	}
++
++	if ( !bOk )
++	{
++		my_error ( bCreate ? ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE : ER_FOREIGN_DATA_STRING_INVALID,
++			MYF(0), table->s->connect_string );
++	} else
++	{
++		if ( share )
++		{
++			SafeDeleteArray ( share->m_sScheme );
++			share->m_sScheme = sScheme;
++			share->m_sHost = sHost;
++			share->m_sIndex = sIndex;
++			share->m_iPort = (ushort)iPort;
++		}
++	}
++	if ( !bOk && !share )
++		SafeDeleteArray ( sScheme );
++
++	SPH_RET(bOk);
++}
++
++
++// Example of simple lock controls. The "share" it creates is structure we will
++// pass to each sphinx handler. Do you have to have one of these? Well, you have
++// pieces that are used for locking, and they are needed to function.
++static CSphSEShare * get_share ( const char * table_name, TABLE * table )
++{
++	SPH_ENTER_FUNC();
++	pthread_mutex_lock ( &sphinx_mutex );
++
++	CSphSEShare * pShare = NULL;
++	for ( ;; )
++	{
++		// check if we already have this share
++#if MYSQL_VERSION_ID>=50120
++		pShare = (CSphSEShare*) hash_search ( &sphinx_open_tables, (const uchar *) table_name, strlen(table_name) );
++#else
++		pShare = (CSphSEShare*) hash_search ( &sphinx_open_tables, table_name, strlen(table_name) );
++#endif
++
++		if ( pShare )
++		{
++			pShare->m_iUseCount++;
++			break;
++		}
++
++		// try to allocate new share
++		pShare = new CSphSEShare ();
++		if ( !pShare )
++			break;
++
++		// try to setup it
++		if ( !ParseUrl ( pShare, table, false ) )
++		{
++			SafeDelete ( pShare );
++			break;
++		}
++
++		// try to hash it
++		pShare->m_iTableNameLen = strlen(table_name);
++		pShare->m_sTable = sphDup ( table_name );
++		if ( my_hash_insert ( &sphinx_open_tables, (const byte *)pShare ) )
++		{
++			SafeDelete ( pShare );
++			break;
++		}
++
++		// all seems fine
++		break;
++	}
++
++	pthread_mutex_unlock ( &sphinx_mutex );
++	SPH_RET(pShare);
++}
++
++
++// Free lock controls. We call this whenever we close a table. If the table had
++// the last reference to the share then we free memory associated with it.
++static int free_share ( CSphSEShare * pShare )
++{
++	SPH_ENTER_FUNC();
++	pthread_mutex_lock ( &sphinx_mutex );
++
++	if ( !--pShare->m_iUseCount )
++	{
++		hash_delete ( &sphinx_open_tables, (byte *)pShare );
++		SafeDelete ( pShare );
++	}
++
++	pthread_mutex_unlock ( &sphinx_mutex );
++	SPH_RET(0);
++}
++
++
++#if MYSQL_VERSION_ID>50100
++static handler * sphinx_create_handler ( handlerton * hton, TABLE_SHARE * table, MEM_ROOT * mem_root )
++{
++	return new ( mem_root ) ha_sphinx ( hton, table );
++}
++#endif
++
++//////////////////////////////////////////////////////////////////////////////
++// CLIENT-SIDE REQUEST STUFF
++//////////////////////////////////////////////////////////////////////////////
++
++CSphSEQuery::CSphSEQuery ( const char * sQuery, int iLength, const char * sIndex )
++	: m_sIndex ( sIndex ? sIndex : "*" )
++	, m_iOffset ( 0 )
++	, m_iLimit ( 20 )
++	, m_sQuery ( "" )
++	, m_pWeights ( NULL )
++	, m_iWeights ( 0 )
++	, m_eMode ( SPH_MATCH_ALL )
++	, m_eSort ( SPH_SORT_RELEVANCE )
++	, m_sSortBy ( "" )
++	, m_iMaxMatches ( 1000 )
++	, m_iMinID ( 0 )
++	, m_iMaxID ( UINT_MAX )
++	, m_iFilters ( 0 )
++	, m_eGroupFunc ( SPH_GROUPBY_DAY )
++	, m_sGroupBy ( "" )
++	, m_sGroupSortBy ( "@group desc" )
++	, m_iCutoff ( 0 )
++	, m_iRetryCount ( 0 )
++	, m_iRetryDelay ( 0 )
++	, m_sGroupDistinct ( "" )
++	, m_iIndexWeights ( 0 )
++
++	, m_pBuf ( NULL )
++	, m_pCur ( NULL )
++	, m_iBufLeft ( 0 )
++	, m_bBufOverrun ( false )
++{
++	m_sQueryBuffer = new char [ iLength+2 ];
++	memcpy ( m_sQueryBuffer, sQuery, iLength );
++	m_sQueryBuffer[iLength]= ';';
++	m_sQueryBuffer[iLength+1]= '\0';
++}
++
++
++CSphSEQuery::~CSphSEQuery ()
++{
++	SPH_ENTER_METHOD();
++	SafeDeleteArray ( m_sQueryBuffer );
++	SafeDeleteArray ( m_pWeights );
++	SafeDeleteArray ( m_pBuf );
++	SPH_VOID_RET();
++}
++
++
++int CSphSEQuery::ParseArray ( uint32 ** ppValues, const char * sValue )
++{
++	SPH_ENTER_METHOD();
++
++//	assert ( ppValues );
++//	assert ( !(*ppValues) );
++
++	const char * p;
++	bool bPrevDigit = false;
++	int iValues = 0;
++
++	// count the values
++	for ( p=sValue; *p; p++ )
++	{
++		bool bDigit = ( (*p)>='0' && (*p)<='9' );
++		if ( bDigit && !bPrevDigit )
++			iValues++;
++		bPrevDigit = bDigit;
++	}
++	if ( !iValues )
++		SPH_RET(0);
++
++	// extract the values
++	uint32 * pValues = new uint32 [ iValues ];
++	*ppValues = pValues;
++
++	int iIndex = 0;
++	uint32 uValue = 0;
++
++	bPrevDigit = false;
++	for ( p=sValue; ; p++ )
++	{
++		bool bDigit = ( (*p)>='0' && (*p)<='9' );
++
++		if ( bDigit )
++		{
++			if ( !bPrevDigit )
++				uValue = 0;
++			uValue = uValue*10 + ( (*p)-'0' );
++		}
++
++		if ( !bDigit && bPrevDigit )
++		{
++			assert ( iIndex<iValues );
++			pValues [ iIndex++ ] = uValue;
++		}
++
++		bPrevDigit = bDigit;
++
++		if ( !(*p) )
++			break;
++	}
++
++	SPH_RET(iValues);
++}
++
++
++static char * chop ( char * s )
++{
++	while ( *s && isspace(*s) )
++		s++;
++
++	char * p = s + strlen(s);
++	while ( p>s && isspace(p[-1]) )
++		p--;
++	*p = '\0';
++
++	return s;
++}
++
++
++static bool myisattr ( char c )
++{
++	return
++		( c>='0' && c<='9' ) ||
++		( c>='a' && c<='z' ) ||
++		( c>='A' && c<='Z' ) ||
++		c=='_';
++}
++
++
++bool CSphSEQuery::ParseField ( char * sField )
++{
++	SPH_ENTER_METHOD();
++
++	// look for option name/value separator
++	char * sValue = strchr ( sField, '=' );
++	if ( !sValue )
++	{
++		// by default let's assume it's just query
++		if ( sField[0] )
++			m_sQuery = sField;
++		SPH_RET(true);
++	}
++
++	// split
++	*sValue++ = '\0';
++	sValue = chop ( sValue );
++	int iValue = atoi ( sValue );
++
++	// handle options
++	char * sName = chop ( sField );
++
++	if ( !strcmp ( sName, "query" ) )			m_sQuery = sValue;
++	else if ( !strcmp ( sName, "index" ) )		m_sIndex = sValue;
++	else if ( !strcmp ( sName, "offset" ) )		m_iOffset = iValue;
++	else if ( !strcmp ( sName, "limit" ) )		m_iLimit = iValue;
++	else if ( !strcmp ( sName, "weights" ) )	m_iWeights = ParseArray ( &m_pWeights, sValue );
++	else if ( !strcmp ( sName, "minid" ) )		m_iMinID = iValue;
++	else if ( !strcmp ( sName, "maxid" ) )		m_iMaxID = iValue;
++	else if ( !strcmp ( sName, "maxmatches" ) )	m_iMaxMatches = iValue;
++	else if ( !strcmp ( sName, "groupsort" ) )	m_sGroupSortBy = sValue;
++	else if ( !strcmp ( sName, "distinct" ) )	m_sGroupDistinct = sValue;
++	else if ( !strcmp ( sName, "cutoff" ) )		m_iCutoff = iValue;
++
++	else if ( !strcmp ( sName, "mode" ) )
++	{
++
++		m_eMode = SPH_MATCH_ALL;
++		if ( !strcmp ( sValue, "any") )				m_eMode = SPH_MATCH_ANY;
++		else if ( !strcmp ( sValue, "phrase" ) )	m_eMode = SPH_MATCH_PHRASE;
++		else if ( !strcmp ( sValue, "boolean") )	m_eMode = SPH_MATCH_BOOLEAN;
++		else if ( !strcmp ( sValue, "extended") )	m_eMode = SPH_MATCH_EXTENDED;
++		else if ( !strcmp ( sValue, "all") )		m_eMode = SPH_MATCH_ALL;
++		else
++		{
++			snprintf ( m_sParseError, sizeof(m_sParseError), "unknown matching mode '%s'", sValue );
++			SPH_RET(false);
++		}
++
++	} else if ( !strcmp ( sName, "sort" ) )
++	{
++		static const struct 
++		{
++			const char *	m_sName;
++			ESphSortOrder	m_eSort;
++		} dSortModes[] = 
++		{
++			{ "relevance",		SPH_SORT_RELEVANCE },
++			{ "attr_desc:",		SPH_SORT_ATTR_DESC },
++			{ "attr_asc:",		SPH_SORT_ATTR_ASC },
++			{ "time_segments:",	SPH_SORT_TIME_SEGMENTS },
++			{ "extended:",		SPH_SORT_EXTENDED },
++		};
++
++		int i;
++		const int nModes = sizeof(dSortModes)/sizeof(dSortModes[0]);
++		for ( i=0; i<nModes; i++ )
++			if ( !strncmp ( sValue, dSortModes[i].m_sName, strlen(dSortModes[i].m_sName) ) )
++		{
++			m_eSort = dSortModes[i].m_eSort;
++			m_sSortBy = sValue + strlen(dSortModes[i].m_sName);
++			break;
++		}
++		if ( i==nModes )
++		{
++			snprintf ( m_sParseError, sizeof(m_sParseError), "unknown sorting mode '%s'", sValue );
++			SPH_RET(false);
++		}
++
++	} else if ( !strcmp ( sName, "groupby" ) )
++	{
++		static const struct 
++		{
++			const char *	m_sName;
++			ESphGroupBy		m_eFunc;
++		} dGroupModes[] = 
++		{
++			{ "day:",	SPH_GROUPBY_DAY },
++			{ "week:",	SPH_GROUPBY_WEEK },
++			{ "month:",	SPH_GROUPBY_MONTH },
++			{ "year:",	SPH_GROUPBY_YEAR },
++			{ "attr:",	SPH_GROUPBY_ATTR },
++		};
++
++		int i;
++		const int nModes = sizeof(dGroupModes)/sizeof(dGroupModes[0]);
++		for ( i=0; i<nModes; i++ )
++			if ( !strncmp ( sValue, dGroupModes[i].m_sName, strlen(dGroupModes[i].m_sName) ) )
++		{
++			m_eGroupFunc = dGroupModes[i].m_eFunc;
++			m_sGroupBy = sValue + strlen(dGroupModes[i].m_sName);
++			break;
++		}
++		if ( i==nModes )
++		{
++			snprintf ( m_sParseError, sizeof(m_sParseError), "unknown groupby mode '%s'", sValue );
++			SPH_RET(false);
++		}
++
++	} else if ( m_iFilters<SPHINXSE_MAX_FILTERS &&
++		( !strcmp ( sName, "range" ) || !strcmp ( sName, "!range" ) ) )
++	{
++		for ( ;; )
++		{
++			CSphSEFilter & tFilter = m_dFilters [ m_iFilters ];
++			tFilter.m_bExclude = ( strcmp ( sName, "!range")==0 );
++			char * p;
++
++			if (!( p = strchr ( sValue, ',' ) ))
++				break;
++			*p++ = '\0';
++
++			tFilter.m_sAttrName = chop ( sValue );
++			sValue = p;
++
++			if (!( p = strchr ( sValue, ',' ) ))
++				break;
++			*p++ = '\0';
++
++			tFilter.m_uMinValue = atoi(sValue);
++			tFilter.m_uMaxValue = atoi(p);
++
++			// all ok
++			m_iFilters++;
++			break;
++		}
++
++	} else if ( m_iFilters<SPHINXSE_MAX_FILTERS &&
++		( !strcmp ( sName, "filter" ) || !strcmp ( sName, "!filter" ) ) )
++	{
++		for ( ;; )
++		{
++			CSphSEFilter & tFilter = m_dFilters [ m_iFilters ];
++			tFilter.m_bExclude = ( strcmp ( sName, "!filter")==0 );
++
++			// get the attr name
++			while ( (*sValue) && !myisattr(*sValue) )
++				sValue++;
++			if ( !*sValue )
++				break;
++
++			tFilter.m_sAttrName = sValue;
++			while ( (*sValue) && myisattr(*sValue) )
++				sValue++;
++			if ( !*sValue )
++				break;
++			*sValue++ = '\0';
++
++			// get the values
++			tFilter.m_iValues = ParseArray ( &tFilter.m_pValues, sValue );
++			if ( !tFilter.m_iValues )
++			{
++				assert ( !tFilter.m_pValues );
++				break;
++			}
++
++			// all ok
++			m_iFilters++;
++			break;
++		}
++
++	} else if ( !strcmp ( sName, "indexweights" ) )
++	{
++		m_iIndexWeights = 0;
++
++		char * p = sValue;
++		while ( *p && m_iIndexWeights<SPHINXSE_MAX_FILTERS )
++		{
++			// extract attr name
++			if ( !myisattr(*p) )
++			{
++				snprintf ( m_sParseError, sizeof(m_sParseError), "indexweights: index name expected near '%s'", p );
++				SPH_RET(false);
++			}
++
++			m_sIndexWeight[m_iIndexWeights] = p;
++			while ( myisattr(*p) ) p++;
++
++			if ( *p!=',' )
++			{
++				snprintf ( m_sParseError, sizeof(m_sParseError), "indexweights: comma expected near '%s'", p );
++				SPH_RET(false);
++			}
++			*p++ = '\0';
++
++			// extract attr value
++			char * sVal = p;
++			while ( isdigit(*p) ) p++;
++			if ( p==sVal )
++			{
++				snprintf ( m_sParseError, sizeof(m_sParseError), "indexweights: integer weight expected near '%s'", sVal );
++				SPH_RET(false);
++			}
++			m_iIndexWeight[m_iIndexWeights] = atoi(sVal);
++			m_iIndexWeights++;
++
++			if ( !*p )  break;
++			if ( *p!=',' )
++			{
++				snprintf ( m_sParseError, sizeof(m_sParseError), "indexweights: comma expected near '%s'", p );
++				SPH_RET(false);
++			}
++			p++;
++		}
++
++	} else
++	{
++		snprintf ( m_sParseError, sizeof(m_sParseError), "unknown parameter '%s'", sName );
++		SPH_RET(false);
++	}
++
++	// !COMMIT handle syntax errors
++
++	SPH_RET(true);
++}
++
++
++bool CSphSEQuery::Parse ()
++{
++	SPH_ENTER_METHOD();
++	SPH_DEBUG ( "query [[ %s ]]", m_sQueryBuffer );
++
++	char * pNext;
++	char * pCur = m_sQueryBuffer;
++
++	while (( pNext = strchr(  pCur, ';' ) ))
++	{
++		*pNext++ = '\0';
++		if ( !ParseField ( pCur ) )
++			SPH_RET(false);
++		pCur = pNext;
++	}
++
++	SPH_RET(true);
++}
++
++
++void CSphSEQuery::SendBytes ( const void * pBytes, int iBytes )
++{
++	SPH_ENTER_METHOD();
++	if ( m_iBufLeft<iBytes )
++	{
++		m_bBufOverrun = true;
++		SPH_VOID_RET();
++	}
++
++	memcpy ( m_pCur, pBytes, iBytes );
++
++	m_pCur += iBytes;
++	m_iBufLeft -= iBytes;
++	SPH_VOID_RET();
++}
++
++
++int CSphSEQuery::BuildRequest ( char ** ppBuffer )
++{
++	SPH_ENTER_METHOD();
++
++	// calc request length
++	int iReqSize = 88 + 4*m_iWeights
++		+ strlen ( m_sSortBy )
++		+ strlen ( m_sQuery )
++		+ strlen ( m_sIndex )
++		+ strlen ( m_sGroupBy )
++		+ strlen ( m_sGroupSortBy )
++		+ strlen ( m_sGroupDistinct );
++	for ( int i=0; i<m_iFilters; i++ )
++	{
++		const CSphSEFilter & tFilter = m_dFilters[i];
++		iReqSize +=
++			12
++			+ strlen ( tFilter.m_sAttrName )
++			+ 4*tFilter.m_iValues
++			+ ( tFilter.m_iValues ? 0 : 8 );
++	}
++
++#if 0
++	for ( int i=0; i<m_iIndexWeights; i++ ) // 1.12+
++		iReqSize += 8 + strlen(m_sIndexWeight[i] );
++#endif
++
++	m_iBufLeft = 0;
++	SafeDeleteArray ( m_pBuf );
++
++	m_pBuf = new char [ iReqSize ];
++	if ( !m_pBuf )
++		SPH_RET(-1);
++
++	m_pCur = m_pBuf;
++	m_iBufLeft = iReqSize;
++	m_bBufOverrun = false;
++	(*ppBuffer) = m_pBuf;
++
++	// build request
++	SendWord ( SEARCHD_COMMAND_SEARCH ); // command id
++	SendWord ( VER_COMMAND_SEARCH ); // command version
++	SendInt ( iReqSize-8 ); // request body length
++
++	SendInt ( m_iOffset );
++	SendInt ( m_iLimit );
++	SendInt ( m_eMode );
++	SendInt ( m_eSort );
++	SendString ( m_sSortBy ); // sort attr
++	SendString ( m_sQuery ); // query
++	SendInt ( m_iWeights );
++	for ( int j=0; j<m_iWeights; j++ )
++		SendInt ( m_pWeights[j] ); // weights
++	SendString ( m_sIndex ); // indexes
++	SendInt ( 0 ); // id32 range follows
++	SendInt ( m_iMinID ); // id/ts ranges
++	SendInt ( m_iMaxID );
++
++	SendInt ( m_iFilters );
++	for ( int j=0; j<m_iFilters; j++ )
++	{
++		const CSphSEFilter & tFilter = m_dFilters[j];
++		SendString ( tFilter.m_sAttrName );
++		SendInt ( tFilter.m_iValues );
++		for ( int k=0; k<tFilter.m_iValues; k++ )
++			SendInt ( tFilter.m_pValues[k] );
++		if ( !tFilter.m_iValues )
++		{
++			SendDword ( tFilter.m_uMinValue );
++			SendDword ( tFilter.m_uMaxValue );
++		}
++		SendInt ( tFilter.m_bExclude );
++	}
++
++	SendInt ( m_eGroupFunc );
++	SendString ( m_sGroupBy );
++	SendInt ( m_iMaxMatches );
++	SendString ( m_sGroupSortBy );
++	SendInt ( m_iCutoff ); // 1.9+
++	SendInt ( m_iRetryCount ); // 1.10+
++	SendInt ( m_iRetryDelay );
++	SendString ( m_sGroupDistinct ); // 1.11+
++
++#if 0
++	SendInt ( m_iIndexWeights );
++	for ( int i=0; i<m_iIndexWeights; i++ ) // 1.12+
++	{
++		SendString ( m_sIndexWeight[i] );
++		SendInt ( m_iIndexWeight[i] );
++	}
++#endif
++
++	// detect buffer overruns and underruns, and report internal error
++	if ( m_bBufOverrun || m_iBufLeft!=0 || m_pCur-m_pBuf!=iReqSize )
++		SPH_RET(-1);
++
++	// all fine
++	SPH_RET(iReqSize);
++}
++
++//////////////////////////////////////////////////////////////////////////////
++// SPHINX HANDLER
++//////////////////////////////////////////////////////////////////////////////
++
++static const char * ha_sphinx_exts[] = { NullS };
++
++
++#if MYSQL_VERSION_ID<50100
++ha_sphinx::ha_sphinx ( TABLE_ARG * table )
++	: handler ( &sphinx_hton, table )
++#else
++ha_sphinx::ha_sphinx ( handlerton * hton, TABLE_ARG * table )
++	: handler ( hton, table )
++#endif
++	, m_pShare ( NULL )
++	, m_iStartOfScan ( 0 )
++	, m_iMatchesTotal ( 0 )
++	, m_iCurrentPos ( 0 )
++	, m_pCurrentKey ( NULL )
++	, m_iCurrentKeyLen ( 0 )
++	, m_pResponse ( NULL )
++	, m_pResponseEnd ( NULL )
++	, m_pCur ( NULL )
++	, m_bUnpackError ( false )
++	, m_iFields ( 0 )
++	, m_dFields ( NULL )
++	, m_iAttrs ( 0 )
++	, m_dAttrs ( NULL )
++	, m_bId64 ( 0 )
++	, m_dUnboundFields ( NULL )
++{
++	SPH_ENTER_METHOD();
++	SPH_VOID_RET();
++}
++
++
++// If frm_error() is called then we will use this to to find out what file extentions
++// exist for the storage engine. This is also used by the default rename_table and
++// delete_table method in handler.cc.
++const char ** ha_sphinx::bas_ext() const
++{
++	return ha_sphinx_exts;
++}
++
++
++// Used for opening tables. The name will be the name of the file.
++// A table is opened when it needs to be opened. For instance
++// when a request comes in for a select on the table (tables are not
++// open and closed for each request, they are cached).
++//
++// Called from handler.cc by handler::ha_open(). The server opens all tables by
++// calling ha_open() which then calls the handler specific open().
++int ha_sphinx::open ( const char * name, int, uint )
++{
++	SPH_ENTER_METHOD();
++	m_pShare = get_share ( name, table );
++	if ( !m_pShare )
++		SPH_RET(1);
++
++	thr_lock_data_init ( &m_pShare->m_tLock, &m_tLock, NULL );
++
++	#if MYSQL_VERSION_ID>50100
++	*thd_ha_data ( table->in_use, ht ) = NULL;
++	#else
++	table->in_use->ha_data [ sphinx_hton.slot ] = NULL;
++	#endif
++
++	SPH_RET(0);
++}
++
++
++int ha_sphinx::ConnectToSearchd ()
++{
++	SPH_ENTER_METHOD();
++
++	struct sockaddr_in sa;
++	in_addr_t ip_addr;
++	int version;
++	uint uClientVersion = htonl ( SPHINX_SEARCHD_PROTO );
++
++	memset ( &sa, 0, sizeof(sa) );
++	sa.sin_family = AF_INET;
++
++	// prepare host address
++	if ( (int)( ip_addr=inet_addr(m_pShare->m_sHost) ) != (int)INADDR_NONE )
++	{ 
++		memcpy ( &sa.sin_addr, &ip_addr, sizeof(ip_addr) );
++	} else
++	{
++		int tmp_errno;
++		struct hostent tmp_hostent, *hp;
++		char buff2 [ GETHOSTBYNAME_BUFF_SIZE ];
++
++		hp = my_gethostbyname_r ( m_pShare->m_sHost, &tmp_hostent,
++			buff2, sizeof(buff2), &tmp_errno );
++		if ( !hp )
++		{ 
++			my_gethostbyname_r_free();
++
++			char sError[256];
++			my_snprintf ( sError, sizeof(sError), "failed to resolve searchd host (name=%s)", m_pShare->m_sHost );
++
++			my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
++			SPH_RET(-1);
++		}
++
++		memcpy ( &sa.sin_addr, hp->h_addr,
++			min ( sizeof(sa.sin_addr), (size_t)hp->h_length ) );
++		my_gethostbyname_r_free();
++	}
++
++	sa.sin_port = htons(m_pShare->m_iPort);
++
++	char sError[256];
++	int iSocket = socket ( AF_INET, SOCK_STREAM, 0 );
++
++	if ( iSocket<0 )
++	{
++		my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), "failed to create client socket" );
++		SPH_RET(-1);
++	}
++
++	if ( connect ( iSocket, (struct sockaddr *) &sa, sizeof(sa) )<0 )
++	{
++		my_snprintf ( sError, sizeof(sError), "failed to connect to searchd (host=%s, port=%d)",
++			m_pShare->m_sHost, m_pShare->m_iPort );
++		my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
++		SPH_RET(-1);
++	}
++
++	if ( ::recv ( iSocket, (char *)&version, sizeof(version), 0 )!=sizeof(version) )
++	{
++		::closesocket ( iSocket );
++		my_snprintf ( sError, sizeof(sError), "failed to receive searchd version (host=%s, port=%d)",
++			m_pShare->m_sHost, m_pShare->m_iPort );
++		my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
++		SPH_RET(-1);
++	}
++
++	if ( ::send ( iSocket, (char*)&uClientVersion, sizeof(uClientVersion), 0 )!=sizeof(uClientVersion) )
++	{
++		::closesocket ( iSocket );
++		my_snprintf ( sError, sizeof(sError), "failed to send client version (host=%s, port=%d)",
++			m_pShare->m_sHost, m_pShare->m_iPort );
++		my_error ( ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), sError );
++		SPH_RET(-1);
++	}
++
++	SPH_RET(iSocket);
++}
++
++
++// Closes a table. We call the free_share() function to free any resources
++// that we have allocated in the "shared" structure.
++//
++// Called from sql_base.cc, sql_select.cc, and table.cc.
++// In sql_select.cc it is only used to close up temporary tables or during
++// the process where a temporary table is converted over to being a
++// myisam table.
++// For sql_base.cc look at close_data_tables().
++int ha_sphinx::close()
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( free_share(m_pShare) );
++}
++
++
++int ha_sphinx::write_row ( uchar * )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( HA_ERR_WRONG_COMMAND );
++}
++
++
++int ha_sphinx::update_row ( const uchar *, uchar * )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( HA_ERR_WRONG_COMMAND );
++}
++
++
++int ha_sphinx::delete_row ( const uchar * )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( HA_ERR_WRONG_COMMAND );
++}
++
++
++// keynr is key (index) number
++// sorted is 1 if result MUST be sorted according to index
++int ha_sphinx::index_init ( uint keynr, bool )
++{
++	SPH_ENTER_METHOD();
++	m_iStartOfScan = 1;
++	active_index = keynr;
++	SPH_RET(0);
++}
++
++
++int ha_sphinx::index_end()
++{
++	SPH_ENTER_METHOD();
++	SPH_RET(0);
++}
++
++
++uint32 ha_sphinx::UnpackDword ()
++{
++	if ( m_pCur+sizeof(uint32)>m_pResponseEnd )
++	{
++		m_pCur = m_pResponseEnd;
++		m_bUnpackError = true;
++		return 0;
++	}
++
++	uint32 uRes = ntohl ( *( (uint32*)m_pCur ) );
++	m_pCur += sizeof(uint32);
++	return uRes;
++}
++
++
++char * ha_sphinx::UnpackString ()
++{
++	uint32 iLen = UnpackDword ();
++	if ( !iLen )
++		return NULL;
++
++	if ( m_pCur+iLen>m_pResponseEnd )
++	{
++		m_pCur = m_pResponseEnd;
++		m_bUnpackError = true;
++		return NULL;
++	}
++
++	char * sRes = new char [ 1+iLen ];
++	memcpy ( sRes, m_pCur, iLen );
++	sRes[iLen] = '\0';
++	m_pCur += iLen;
++	return sRes;
++}
++
++
++static inline const char * FixNull ( const char * s )
++{
++	return s ? s : "(null)";
++}
++
++
++bool ha_sphinx::UnpackSchema ()
++{
++	SPH_ENTER_METHOD();
++
++	// unpack network packet
++	if ( m_dFields )
++		for ( int i=0; i<(int)m_iFields; i++ )
++			SafeDeleteArray ( m_dFields[i] );
++	SafeDeleteArray ( m_dFields );
++
++	m_iFields = UnpackDword ();
++	m_dFields = new char * [ m_iFields ];
++	if ( !m_dFields )
++		SPH_RET(false);
++
++	for ( uint32 i=0; i<m_iFields; i++ )
++		m_dFields[i] = UnpackString ();
++
++	SafeDeleteArray ( m_dAttrs );
++	m_iAttrs = UnpackDword ();
++	m_dAttrs = new CSphSEAttr [ m_iAttrs ];
++	if ( !m_dAttrs )
++	{
++		for ( int i=0; i<(int)m_iFields; i++ )
++			SafeDeleteArray ( m_dFields[i] );
++		SafeDeleteArray ( m_dFields );
++		SPH_RET(false);
++	}
++
++	for ( uint32 i=0; i<m_iAttrs; i++ )
++	{
++		m_dAttrs[i].m_sName = UnpackString ();
++		m_dAttrs[i].m_eType = (ESphAttrType) UnpackDword ();
++
++		m_dAttrs[i].m_iField = -1;
++		for ( int j=SPHINXSE_SYSTEM_COLUMNS; j<m_pShare->m_iTableFields; j++ )
++		{
++			const char * sTableField = m_pShare->m_sTableField[j];
++			const char * sAttrField = m_dAttrs[i].m_sName;
++			if ( m_dAttrs[i].m_sName[0]=='@' )
++			{
++				const char * sAtPrefix = "_sph_";
++				if ( strncmp ( sTableField, sAtPrefix, strlen(sAtPrefix) ) )
++					continue;
++				sTableField += strlen(sAtPrefix);
++				sAttrField++;
++			}
++
++			if ( !strcasecmp ( sAttrField, sTableField ) )
++			{
++				m_dAttrs[i].m_iField = j;
++				break;
++			}
++		}
++	}
++
++	m_iMatchesTotal = UnpackDword ();
++	m_bId64 = UnpackDword ();
++
++	// network packet unpacked; build unbound fields map
++	SafeDeleteArray ( m_dUnboundFields );
++	m_dUnboundFields = new int [ m_pShare->m_iTableFields ];
++
++	for ( int i=0; i<m_pShare->m_iTableFields; i++ )
++	{
++		if ( i<SPHINXSE_SYSTEM_COLUMNS )
++			m_dUnboundFields[i] = SPH_ATTR_NONE;
++
++		else if ( m_pShare->m_eTableFieldType[i]==MYSQL_TYPE_TIMESTAMP )
++			m_dUnboundFields[i] = SPH_ATTR_TIMESTAMP;
++
++		else
++			m_dUnboundFields[i] = SPH_ATTR_INTEGER;
++	}
++
++	for ( uint32 i=0; i<m_iAttrs; i++ )
++		if ( m_dAttrs[i].m_iField>=0 )
++			m_dUnboundFields [ m_dAttrs[i].m_iField ] = SPH_ATTR_NONE;
++
++	SPH_RET(!m_bUnpackError);
++}
++
++
++bool ha_sphinx::UnpackStats ( CSphSEStats * pStats )
++{
++	assert ( pStats );
++
++	char * pCurSave = m_pCur;
++	m_pCur = m_pCur + m_iMatchesTotal*(2+m_bId64+m_iAttrs)*sizeof(uint); // id+weight+attrs
++
++	pStats->m_iMatchesTotal = UnpackDword ();
++	pStats->m_iMatchesFound = UnpackDword ();
++	pStats->m_iQueryMsec = UnpackDword ();
++	pStats->m_iWords = UnpackDword ();
++
++	if ( m_bUnpackError )
++		return false;
++
++	SafeDeleteArray ( pStats->m_dWords );
++	pStats->m_dWords = new CSphSEWordStats [ pStats->m_iWords ]; // !COMMIT not bad-value safe
++	if ( !pStats->m_dWords )
++		return false;
++
++	for ( int i=0; i<pStats->m_iWords; i++ )
++	{
++		CSphSEWordStats & tWord = pStats->m_dWords[i];
++		tWord.m_sWord = UnpackString ();
++		tWord.m_iDocs = UnpackDword ();
++		tWord.m_iHits = UnpackDword ();
++	}
++
++	if ( m_bUnpackError )
++		return false;
++
++	m_pCur = pCurSave;
++	return true;
++}
++
++
++// Positions an index cursor to the index specified in the handle. Fetches the
++// row if available. If the key value is null, begin at the first key of the
++// index.
++int ha_sphinx::index_read ( byte * buf, const byte * key, uint key_len, enum ha_rkey_function )
++{
++	SPH_ENTER_METHOD();
++	char sError[256];
++
++	m_pCurrentKey = key;
++	m_iCurrentKeyLen = key_len;
++	m_iStartOfScan = 1;
++
++	// parse query
++	CSphSEQuery q ( (char*)key+HA_KEY_BLOB_LENGTH, uint2korr(key), m_pShare->m_sIndex );
++	if ( !q.Parse () )
++	{
++		my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), q.m_sParseError );
++		SPH_RET ( HA_ERR_END_OF_FILE );
++	}
++
++	// do connect
++	int iSocket = ConnectToSearchd ();
++	if ( iSocket<0 )
++		SPH_RET ( HA_ERR_END_OF_FILE );
++
++	// my buffer
++	char * pBuffer; // will be free by CSphSEQuery dtor; do NOT free manually
++	int iReqLen = q.BuildRequest ( &pBuffer );
++
++	if ( iReqLen<=0 )
++	{
++		my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: q.BuildRequest() failed" );
++		SPH_RET ( HA_ERR_END_OF_FILE );
++	}
++
++	// send request
++	::send ( iSocket, pBuffer, iReqLen, 0 );
++
++	// receive reply
++	char sHeader[8];
++	if ( ::recv ( iSocket, sHeader, sizeof(sHeader), MSG_WAITALL )!=sizeof(sHeader) )
++	{
++		my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "failed to receive response header (searchd went away?)" );
++		SPH_RET ( HA_ERR_END_OF_FILE );
++	}
++
++	short int uRespStatus = ntohs ( *(short int*)( &sHeader[0] ) );
++	short int uRespVersion = ntohs ( *(short int*)( &sHeader[2] ) );
++	uint uRespLength = ntohl ( *(uint *)( &sHeader[4] ) );
++	SPH_DEBUG ( "got response header (status=%d version=%d length=%d)",
++		uRespStatus, uRespVersion, uRespLength );
++
++	SafeDeleteArray ( m_pResponse );
++	if ( uRespLength<=SPHINXSE_MAX_ALLOC )
++		m_pResponse = new char [ uRespLength+1 ];
++
++	if ( !m_pResponse )
++	{
++		my_snprintf ( sError, sizeof(sError), "bad searchd response length (length=%u)", uRespLength );
++		my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), sError );
++		SPH_RET ( HA_ERR_END_OF_FILE );
++	}
++
++	int iRecvLength = 0;
++	while ( iRecvLength<(int)uRespLength )
++	{
++		int iRecv = ::recv ( iSocket, m_pResponse+iRecvLength, uRespLength-iRecvLength, MSG_WAITALL );
++		if ( iRecv<0 )
++			break;
++		iRecvLength += iRecv;
++	}
++
++	::closesocket ( iSocket );
++	iSocket = -1;
++
++	if ( iRecvLength!=(int)uRespLength )
++	{
++		my_snprintf ( sError, sizeof(sError), "net read error (expected=%d, got=%d)", uRespLength, iRecvLength );
++		my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), sError );
++		SPH_RET ( HA_ERR_END_OF_FILE );
++	}
++
++	// set new data for thd->ha_data, it is used in show_status
++	#if MYSQL_VERSION_ID>50100
++	void ** tmp_ha_data = thd_ha_data ( table->in_use, ht );
++	#define TARGET (*tmp_ha_data)
++	#else
++	#define TARGET (current_thd->ha_data[sphinx_hton.slot])
++	#endif // >50100
++
++	CSphSEStats * pStats = (CSphSEStats *) TARGET;
++	if ( !pStats )
++	{
++		pStats = new CSphSEStats ();
++		TARGET = pStats;
++		if ( !pStats )
++		{
++			my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: malloc() failed" );
++			SPH_RET ( HA_ERR_END_OF_FILE );
++		}
++	} else
++	{
++		pStats->Reset ();
++	}
++
++	// parse reply
++	m_iCurrentPos = 0;
++	m_pCur = m_pResponse;
++	m_pResponseEnd = m_pResponse + uRespLength;
++	m_bUnpackError = false;
++
++	if ( uRespStatus!=SEARCHD_OK )
++	{
++		char * sMessage = UnpackString ();
++		if ( !sMessage )
++		{
++			my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "no valid response from searchd (status=%d, resplen=%d)",
++				uRespStatus, uRespLength );
++			SPH_RET ( HA_ERR_END_OF_FILE );
++		}
++
++		strncpy ( pStats->m_sLastMessage, sMessage, sizeof(pStats->m_sLastMessage) );
++		SafeDeleteArray ( sMessage );
++
++		if ( uRespStatus!=SEARCHD_WARNING )
++		{
++			my_snprintf ( sError, sizeof(sError), "searchd error: %s", pStats->m_sLastMessage );
++			my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), sError );
++
++			pStats->m_bLastError = true;
++			SPH_RET ( HA_ERR_END_OF_FILE );
++		}
++	}
++
++	if ( !UnpackSchema () )
++	{
++		my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: UnpackSchema() failed" );
++		SPH_RET ( HA_ERR_END_OF_FILE );
++	}
++
++	if ( !UnpackStats ( pStats ) )
++	{
++		my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: UnpackStats() failed" );
++		SPH_RET ( HA_ERR_END_OF_FILE );
++	}
++
++	SPH_RET ( get_rec ( buf, key, key_len ) );
++}
++
++
++// Positions an index cursor to the index specified in key. Fetches the
++// row if any. This is only used to read whole keys.
++int ha_sphinx::index_read_idx ( byte *, uint, const byte *, uint, enum ha_rkey_function )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( HA_ERR_WRONG_COMMAND );
++}
++
++
++// Used to read forward through the index.
++int ha_sphinx::index_next ( byte * buf )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( get_rec ( buf, m_pCurrentKey, m_iCurrentKeyLen ) );
++}
++
++
++int ha_sphinx::index_next_same ( byte * buf, const byte * key, uint keylen )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( get_rec ( buf, key, keylen ) );
++}
++
++
++int ha_sphinx::get_rec ( byte * buf, const byte * key, uint keylen )
++{
++	SPH_ENTER_METHOD();
++
++	if ( m_iCurrentPos>=m_iMatchesTotal )
++	{
++		SafeDeleteArray ( m_pResponse );
++		SPH_RET ( HA_ERR_END_OF_FILE ); 
++	}
++
++	#if MYSQL_VERSION_ID>50100
++	my_bitmap_map * org_bitmap = dbug_tmp_use_all_columns ( table, table->write_set );
++	#endif
++	Field ** field = table->field;
++
++	// unpack and return the match
++	if ( m_bId64 )
++		UnpackDword (); // FIXME! add full id64 support later here; for now, it ignores high bits
++	uint32 uMatchID = UnpackDword ();
++	uint32 uMatchWeight = UnpackDword ();
++
++	field[0]->store ( uMatchID, 1 );
++	field[1]->store ( uMatchWeight, 1 );
++	#if MYSQL_VERSION_ID>=50120
++	field[2]->set_key_image ( key, keylen ); // store requested query. it's necessary, otherwise mysql goes crazy
++	#else
++	field[2]->set_key_image ( (char*)key, keylen ); // store requested query. it's necessary, otherwise mysql goes crazy
++	#endif
++
++	for ( uint32 i=0; i<m_iAttrs; i++ )
++	{
++		uint32 uValue = UnpackDword ();
++		if ( m_dAttrs[i].m_iField<0 )
++			continue;
++
++		Field * af = field [ m_dAttrs[i].m_iField ];
++		switch ( m_dAttrs[i].m_eType )
++		{
++			case SPH_ATTR_INTEGER:		af->store ( uValue, 1 ); break;
++			case SPH_ATTR_TIMESTAMP:	longstore ( af->ptr, uValue ); break;
++			default:
++				my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0),
++					"INTERNAL ERROR: unhandled attr type %d", m_dAttrs[i].m_eType );
++				SafeDeleteArray ( m_pResponse );
++				SPH_RET ( HA_ERR_END_OF_FILE ); 
++		}
++	}
++
++	if ( m_bUnpackError )
++	{
++		my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0), "INTERNAL ERROR: response unpacker failed" );
++		SafeDeleteArray ( m_pResponse );
++		SPH_RET ( HA_ERR_END_OF_FILE ); 
++	}
++
++	// zero out unmapped fields
++	for ( int i=SPHINXSE_SYSTEM_COLUMNS; i<(int)table->s->fields; i++ )
++		if ( m_dUnboundFields[i]!=SPH_ATTR_NONE )
++			switch ( m_dUnboundFields[i] )
++	{
++		case SPH_ATTR_INTEGER:		table->field[i]->store ( 0, 1 ); break;
++		case SPH_ATTR_TIMESTAMP:	longstore ( table->field[i]->ptr, 0 ); break;
++		default:
++			my_error ( ER_QUERY_ON_FOREIGN_DATA_SOURCE, MYF(0),
++				"INTERNAL ERROR: unhandled unbound field type %d", m_dUnboundFields[i] );
++			SafeDeleteArray ( m_pResponse );
++			SPH_RET ( HA_ERR_END_OF_FILE );
++	}
++
++	memset ( buf, 0, table->s->null_bytes );
++	m_iCurrentPos++;
++
++	#if MYSQL_VERSION_ID > 50100
++	dbug_tmp_restore_column_map(table->write_set, org_bitmap);
++	#endif
++
++	SPH_RET(0);
++}
++
++
++// Used to read backwards through the index.
++int ha_sphinx::index_prev ( byte * )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( HA_ERR_WRONG_COMMAND );
++}
++
++
++// index_first() asks for the first key in the index.
++//
++// Called from opt_range.cc, opt_sum.cc, sql_handler.cc,
++// and sql_select.cc.
++int ha_sphinx::index_first ( byte * )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( HA_ERR_END_OF_FILE );
++}
++
++// index_last() asks for the last key in the index.
++//
++// Called from opt_range.cc, opt_sum.cc, sql_handler.cc,
++// and sql_select.cc.
++int ha_sphinx::index_last ( byte * )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( HA_ERR_WRONG_COMMAND );
++}
++
++
++int ha_sphinx::rnd_init ( bool )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET(0);
++}
++
++
++int ha_sphinx::rnd_end()
++{
++	SPH_ENTER_METHOD();
++	SPH_RET(0);
++}
++
++
++int ha_sphinx::rnd_next ( byte * )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( HA_ERR_END_OF_FILE );
++}
++
++
++void ha_sphinx::position ( const byte * )
++{
++	SPH_ENTER_METHOD();
++	SPH_VOID_RET();
++}
++
++
++// This is like rnd_next, but you are given a position to use
++// to determine the row. The position will be of the type that you stored in
++// ref. You can use ha_get_ptr(pos,ref_length) to retrieve whatever key
++// or position you saved when position() was called.
++// Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc.
++int ha_sphinx::rnd_pos ( byte *, byte * )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( HA_ERR_WRONG_COMMAND );
++}
++
++
++#if MYSQL_VERSION_ID>=50030
++int ha_sphinx::info ( uint )
++#else
++void ha_sphinx::info ( uint )
++#endif
++{
++	SPH_ENTER_METHOD();
++
++	if ( table->s->keys>0 )
++		table->key_info[0].rec_per_key[0] = 1;
++
++	#if MYSQL_VERSION_ID>50100
++	stats.records = 20;
++	#else
++	records = 20;
++	#endif
++
++#if MYSQL_VERSION_ID>=50030
++	SPH_RET(0);
++#else
++	SPH_VOID_RET();
++#endif
++}
++
++
++int ha_sphinx::extra ( enum ha_extra_function )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET(0);
++}
++
++
++int ha_sphinx::reset()
++{
++	SPH_ENTER_METHOD();
++	SPH_RET(0);
++}
++
++
++int ha_sphinx::delete_all_rows()
++{
++	SPH_ENTER_METHOD();
++	SPH_RET ( HA_ERR_WRONG_COMMAND );
++}
++
++
++// First you should go read the section "locking functions for mysql" in
++// lock.cc to understand this.
++// This create a lock on the table. If you are implementing a storage engine
++// that can handle transacations look at ha_berkely.cc to see how you will
++// want to go about doing this. Otherwise you should consider calling flock()
++// here.
++//
++// Called from lock.cc by lock_external() and unlock_external(). Also called
++// from sql_table.cc by copy_data_between_tables().
++int ha_sphinx::external_lock ( THD *, int )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET(0);
++}
++
++
++THR_LOCK_DATA ** ha_sphinx::store_lock ( THD *, THR_LOCK_DATA ** to,
++	enum thr_lock_type lock_type )
++{
++	SPH_ENTER_METHOD();
++
++	if ( lock_type!=TL_IGNORE && m_tLock.type==TL_UNLOCK )
++		m_tLock.type=lock_type;
++
++	*to++ = &m_tLock;
++	SPH_RET(to);
++}
++
++
++int ha_sphinx::delete_table ( const char * )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET(0);
++}
++
++
++// Renames a table from one name to another from alter table call.
++//
++// If you do not implement this, the default rename_table() is called from
++// handler.cc and it will delete all files with the file extentions returned
++// by bas_ext().
++//
++// Called from sql_table.cc by mysql_rename_table().
++int ha_sphinx::rename_table ( const char *, const char * )
++{
++	SPH_ENTER_METHOD();
++	SPH_RET(0);
++}
++
++
++// Given a starting key, and an ending key estimate the number of rows that
++// will exist between the two. end_key may be empty which in case determine
++// if start_key matches any rows.
++//
++// Called from opt_range.cc by check_quick_keys().
++ha_rows ha_sphinx::records_in_range ( uint, key_range * min_key, key_range * max_key )
++{
++	SPH_ENTER_METHOD();
++
++#if SPHINX_DEBUG_OUTPUT
++	String varchar;
++	uint var_length = uint2korr(min_key->key);
++	varchar.set_quick ( (char*)min_key->key+HA_KEY_BLOB_LENGTH, var_length, &my_charset_bin );
++	SPH_DEBUG ( "%s: key_val=%s, key_len=%d", __FUNCTION__, varchar.ptr(), var_length );
++#endif
++
++	SPH_RET(3); // low number to force index usage
++}
++
++
++static inline bool IsIntegerFieldType ( enum_field_types eType )
++{
++	return eType==MYSQL_TYPE_LONG;
++}
++
++
++// create() is called to create a database. The variable name will have the name
++// of the table. When create() is called you do not need to worry about opening
++// the table. Also, the FRM file will have already been created so adjusting
++// create_info will not do you any good. You can overwrite the frm file at this
++// point if you wish to change the table definition, but there are no methods
++// currently provided for doing that.
++//
++// Called from handle.cc by ha_create_table().
++int ha_sphinx::create ( const char * name, TABLE * table, HA_CREATE_INFO * )
++{
++	SPH_ENTER_METHOD();
++	char sError[256];
++
++	if ( !ParseUrl ( NULL, table, true ) )
++		SPH_RET(-1);
++
++	for ( ;; )
++	{
++		// check system fields (count and types)
++		if ( table->s->fields<SPHINXSE_SYSTEM_COLUMNS )
++		{
++			my_snprintf ( sError, sizeof(sError), "%s: there MUST be at least %d columns",
++				name, SPHINXSE_SYSTEM_COLUMNS );
++			break;
++		}
++
++		if ( !IsIntegerFieldType ( table->field[0]->type() ) )
++		{
++			my_snprintf ( sError, sizeof(sError), "%s: 1st column (docid) MUST be integer", name );
++			break;
++		}
++
++		if ( !IsIntegerFieldType ( table->field[1]->type() ) )
++		{
++			my_snprintf ( sError, sizeof(sError), "%s: 2nd column (weight) MUST be integer", name );
++			break;
++		}
++
++		if ( table->field[2]->type()!=MYSQL_TYPE_VARCHAR )
++		{
++			my_snprintf ( sError, sizeof(sError), "%s: 3rd column (search query) MUST be varchar", name );
++			break;
++		}
++
++		// check attributes
++		int i;
++		for ( i=3; i<(int)table->s->fields; i++ )
++		{
++			enum_field_types eType = table->field[i]->type();
++			if ( eType!=MYSQL_TYPE_TIMESTAMP && !IsIntegerFieldType(eType) )
++			{
++				my_snprintf ( sError, sizeof(sError), "%s: %dth column (attribute %s) MUST be integer or timestamp",
++					name, i+1, table->field[i]->field_name );
++				break;
++			}
++		}
++
++		if ( i!=(int)table->s->fields )
++			break;
++
++		// check index
++		if (
++			table->s->keys!=1 ||
++			table->key_info[0].key_parts!=1 ||
++			strcasecmp ( table->key_info[0].key_part[0].field->field_name, table->field[2]->field_name ) )
++		{
++			my_snprintf ( sError, sizeof(sError), "%s: there must be an index on '%s' column",
++				name, table->field[2]->field_name );
++			break;
++		}
++
++		// all good
++		sError[0] = '\0';
++		break;
++	}
++	if ( sError[0] )
++	{
++		my_error ( ER_CANT_CREATE_TABLE, MYF(0), sError, -1 );
++		SPH_RET(-1);
++	}
++
++
++/*
++		MYSQL_TYPE_DECIMAL,
++		MYSQL_TYPE_LONG,
++		MYSQL_TYPE_LONGLONG,
++
++		MYSQL_TYPE_TIMESTAMP,
++		MYSQL_TYPE_DATETIME,
++		MYSQL_TYPE_NEWDATE,
++		
++		MYSQL_TYPE_VARCHAR,
++		MYSQL_TYPE_VAR_STRING,
++		MYSQL_TYPE_STRING,
++*/
++
++	SPH_RET(0);
++}
++
++
++#if MYSQL_VERSION_ID>50100
++struct st_mysql_storage_engine sphinx_storage_engine =
++{
++	MYSQL_HANDLERTON_INTERFACE_VERSION
++};
++
++
++mysql_declare_plugin(sphinx)
++{
++	MYSQL_STORAGE_ENGINE_PLUGIN,
++	&sphinx_storage_engine,
++	sphinx_hton_name,
++	"Sphinx developers",
++	sphinx_hton_comment,
++	PLUGIN_LICENSE_GPL,
++	sphinx_init_func, // Plugin Init
++	sphinx_done_func, // Plugin Deinit
++	0x0001, // 0.1
++	NULL, NULL, NULL
++}
++mysql_declare_plugin_end;
++
++#endif // >50100
++
++//
++// $Id: ha_sphinx.cc 870 2007-10-13 15:45:44Z shodan $
++//
+diff -urNad trunk~/sql/sphinx/ha_sphinx.h trunk/sql/sphinx/ha_sphinx.h
+--- trunk~/sql/sphinx/ha_sphinx.h	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/sphinx/ha_sphinx.h	2007-12-27 15:54:49.326265826 -0600
+@@ -0,0 +1,154 @@
++//
++// $Id: ha_sphinx.h 869 2007-10-13 15:24:22Z shodan $
++//
++
++#ifdef USE_PRAGMA_INTERFACE
++#pragma interface // gcc class implementation
++#endif
++
++
++#if MYSQL_VERSION_ID>50100
++#define TABLE_ARG	st_table_share
++#else
++#define TABLE_ARG	st_table
++#endif
++
++
++#if MYSQL_VERSION_ID>=50120
++typedef uchar byte;
++#endif
++
++
++/// forward decls
++class THD;
++struct CSphReqQuery;
++struct CSphSEShare;
++struct CSphSEAttr;
++struct CSphSEStats;
++
++
++/// Sphinx SE handler class
++class ha_sphinx : public handler
++{
++protected:
++	THR_LOCK_DATA	m_tLock;				///< MySQL lock
++
++	CSphSEShare *	m_pShare;				///< shared lock info
++
++	int				m_iStartOfScan;
++	uint			m_iMatchesTotal;
++	uint			m_iCurrentPos;
++	const byte *	m_pCurrentKey;
++	uint			m_iCurrentKeyLen;
++
++	char *			m_pResponse;			///< searchd response storage
++	char *			m_pResponseEnd;			///< searchd response storage end (points to wilderness!)
++	char *			m_pCur;					///< current position into response
++	bool			m_bUnpackError;			///< any errors while unpacking response
++
++public:
++#if MYSQL_VERSION_ID<50100
++					ha_sphinx ( TABLE_ARG * table_arg );
++#else
++					ha_sphinx ( handlerton * hton, TABLE_ARG * table_arg );
++#endif
++					~ha_sphinx () {}
++
++	const char *	table_type () const		{ return "SPHINX"; }	///< SE name for display purposes
++	const char *	index_type ( uint )		{ return "HASH"; }		///< index type name for display purposes
++	const char **	bas_ext () const;								///< my file extensions
++
++	#if MYSQL_VERSION_ID>50100
++	ulonglong		table_flags () const	{ return 0; }			///< bitmap of implemented flags (see handler.h for more info)
++	#else
++	ulong			table_flags () const	{ return 0; }			///< bitmap of implemented flags (see handler.h for more info)
++	#endif
++
++	ulong			index_flags ( uint, uint, bool ) const	{ return 0; }	///< bitmap of flags that says how SE implements indexes
++	uint			max_supported_record_length () const	{ return HA_MAX_REC_LENGTH; }
++	uint			max_supported_keys () const				{ return 1; }
++	uint			max_supported_key_parts () const		{ return 1; }
++	uint			max_supported_key_length () const		{ return MAX_KEY_LENGTH; }
++	uint			max_supported_key_part_length () const	{ return MAX_KEY_LENGTH; }
++
++	#if MYSQL_VERSION_ID>50100
++	virtual double	scan_time ()	{ return (double)( stats.records+stats.deleted )/20.0 + 10; }	///< called in test_quick_select to determine if indexes should be used
++	#else
++	virtual double	scan_time ()	{ return (double)( records+deleted )/20.0 + 10; }				///< called in test_quick_select to determine if indexes should be used
++	#endif
++
++	virtual double	read_time ( ha_rows rows )	{ return (double)rows/20.0 + 1; }					///< index read time estimate
++
++public:
++	int				open ( const char * name, int mode, uint test_if_locked );
++	int				close ();
++
++	int				write_row ( uchar * buf );
++	int				update_row ( const uchar * old_data, uchar * new_data );
++	int				delete_row ( const uchar * buf );
++
++	int				index_init ( uint keynr, bool sorted ); // 5.1.x
++	int				index_init ( uint keynr ) { return index_init ( keynr, false ); } // 5.0.x
++
++	int				index_end (); 
++	int				index_read ( byte * buf, const byte * key, uint key_len, enum ha_rkey_function find_flag );
++	int				index_read_idx ( byte * buf, uint idx, const byte * key, uint key_len, enum ha_rkey_function find_flag );
++	int				index_next ( byte * buf );
++	int				index_next_same ( byte * buf, const byte * key, uint keylen );
++	int				index_prev ( byte * buf );
++	int				index_first ( byte * buf );
++	int				index_last ( byte * buf );
++
++	int				get_rec ( byte * buf, const byte * key, uint keylen );
++
++	int				rnd_init ( bool scan );
++	int				rnd_end ();
++	int				rnd_next ( byte * buf );
++	int				rnd_pos ( byte * buf, byte * pos );
++	void			position ( const byte * record );
++
++#if MYSQL_VERSION_ID>=50030
++	int				info ( uint );
++#else
++	void			info ( uint );
++#endif
++
++	int				extra ( enum ha_extra_function operation );
++	int				reset ();
++	int				external_lock ( THD * thd, int lock_type );
++	int				delete_all_rows ();
++	ha_rows			records_in_range ( uint inx, key_range * min_key, key_range * max_key );
++
++	int				delete_table ( const char * from );
++	int				rename_table ( const char * from, const char * to );
++	int				create ( const char * name, TABLE * form, HA_CREATE_INFO * create_info );
++
++	THR_LOCK_DATA **store_lock ( THD * thd, THR_LOCK_DATA ** to, enum thr_lock_type lock_type );
++
++private:
++	uint32			m_iFields;
++	char **			m_dFields;
++
++	uint32			m_iAttrs;
++	CSphSEAttr *	m_dAttrs;
++	int				m_bId64;
++
++	int *			m_dUnboundFields;
++
++private:
++	int				ConnectToSearchd ();
++
++	uint32			UnpackDword ();
++	char *			UnpackString ();
++	bool			UnpackSchema ();
++	bool			UnpackStats ( CSphSEStats * pStats );
++};
++
++
++#if MYSQL_VERSION_ID < 50100
++bool sphinx_show_status ( THD * thd );
++#endif
++
++//
++// $Id: ha_sphinx.h 869 2007-10-13 15:24:22Z shodan $
++//
+diff -urNad trunk~/sql/sphinx/plug.in trunk/sql/sphinx/plug.in
+--- trunk~/sql/sphinx/plug.in	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/sphinx/plug.in	2007-12-27 15:54:49.326265826 -0600
+@@ -0,0 +1,5 @@
++MYSQL_STORAGE_ENGINE(sphinx,,  [Sphinx Storage Engine],
++        [Sphinx Storage Engines], [max,max-no-ndb])
++MYSQL_PLUGIN_DIRECTORY(sphinx, [storage/sphinx])
++MYSQL_PLUGIN_STATIC(sphinx,    [libsphinx.a])
++MYSQL_PLUGIN_DYNAMIC(sphinx,   [ha_sphinx.la])
+diff -urNad trunk~/sql/sql_lex.h trunk/sql/sql_lex.h
+--- trunk~/sql/sql_lex.h	2007-11-15 08:06:15.000000000 -0600
++++ trunk/sql/sql_lex.h	2007-12-27 15:54:49.330266054 -0600
+@@ -57,6 +57,7 @@
+   SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
+   SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
+   SQLCOM_SHOW_INNODB_STATUS, SQLCOM_SHOW_NDBCLUSTER_STATUS, SQLCOM_SHOW_MUTEX_STATUS,
++  SQLCOM_SHOW_SPHINX_STATUS,
+   SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
+   SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
+   SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
+diff -urNad trunk~/sql/sql_parse.cc trunk/sql/sql_parse.cc
+--- trunk~/sql/sql_parse.cc	2007-11-15 08:06:52.000000000 -0600
++++ trunk/sql/sql_parse.cc	2007-12-27 15:54:49.546278363 -0600
+@@ -24,6 +24,9 @@
+ #ifdef HAVE_INNOBASE_DB
+ #include "ha_innodb.h"
+ #endif
++#ifdef HAVE_SPHINX_DB
++#include "sphinx/ha_sphinx.h"
++#endif
+ 
+ #ifdef HAVE_NDBCLUSTER_DB
+ #include "ha_ndbcluster.h"
+@@ -2913,6 +2916,15 @@
+       break;
+     }
+ #endif
++#ifdef HAVE_SPHINX_DB
++  case SQLCOM_SHOW_SPHINX_STATUS:
++    {
++      if (check_global_access(thd, SUPER_ACL))
++	goto error;
++      res = sphinx_show_status(thd);
++      break;
++    }
++#endif
+ #ifdef HAVE_REPLICATION
+   case SQLCOM_LOAD_MASTER_TABLE:
+   {
+diff -urNad trunk~/sql/sql_parse.cc.orig trunk/sql/sql_parse.cc.orig
+--- trunk~/sql/sql_parse.cc.orig	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/sql_parse.cc.orig	2007-12-27 15:54:49.570279731 -0600
+@@ -0,0 +1,7845 @@
++/* Copyright (C) 2000-2003 MySQL AB
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; version 2 of the License.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
++
++#define MYSQL_LEX 1
++#include "mysql_priv.h"
++#include "sql_repl.h"
++#include "repl_failsafe.h"
++#include <m_ctype.h>
++#include <myisam.h>
++#include <my_dir.h>
++
++#ifdef HAVE_INNOBASE_DB
++#include "ha_innodb.h"
++#endif
++
++#ifdef HAVE_NDBCLUSTER_DB
++#include "ha_ndbcluster.h"
++#endif
++
++#include "sp_head.h"
++#include "sp.h"
++#include "sp_cache.h"
++#include "sql_trigger.h"
++
++#ifdef HAVE_OPENSSL
++/*
++  Without SSL the handshake consists of one packet. This packet
++  has both client capabilites and scrambled password.
++  With SSL the handshake might consist of two packets. If the first
++  packet (client capabilities) has CLIENT_SSL flag set, we have to
++  switch to SSL and read the second packet. The scrambled password
++  is in the second packet and client_capabilites field will be ignored.
++  Maybe it is better to accept flags other than CLIENT_SSL from the
++  second packet?
++*/
++#define SSL_HANDSHAKE_SIZE      2
++#define NORMAL_HANDSHAKE_SIZE   6
++#define MIN_HANDSHAKE_SIZE      2
++#else
++#define MIN_HANDSHAKE_SIZE      6
++#endif /* HAVE_OPENSSL */
++
++/* Used in error handling only */
++#define SP_TYPE_STRING(LP) \
++  ((LP)->sphead->m_type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE")
++#define SP_COM_STRING(LP) \
++  ((LP)->sql_command == SQLCOM_CREATE_SPFUNCTION || \
++   (LP)->sql_command == SQLCOM_ALTER_FUNCTION || \
++   (LP)->sql_command == SQLCOM_SHOW_CREATE_FUNC || \
++   (LP)->sql_command == SQLCOM_DROP_FUNCTION ? \
++   "FUNCTION" : "PROCEDURE")
++
++#ifdef SOLARIS
++extern "C" int gethostname(char *name, int namelen);
++#endif
++
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++static void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
++static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
++static void decrease_user_connections(USER_CONN *uc);
++#endif /* NO_EMBEDDED_ACCESS_CHECKS */
++static bool check_db_used(THD *thd,TABLE_LIST *tables);
++static void remove_escape(char *name);
++static bool append_file_to_dir(THD *thd, const char **filename_ptr,
++			       const char *table_name);
++static bool check_show_create_table_access(THD *thd, TABLE_LIST *table);
++
++const char *any_db="*any*";	// Special symbol for check_access
++
++const char *command_name[]={
++  "Sleep", "Quit", "Init DB", "Query", "Field List", "Create DB",
++  "Drop DB", "Refresh", "Shutdown", "Statistics", "Processlist",
++  "Connect","Kill","Debug","Ping","Time","Delayed insert","Change user",
++  "Binlog Dump","Table Dump",  "Connect Out", "Register Slave",
++  "Prepare", "Execute", "Long Data", "Close stmt",
++  "Reset stmt", "Set option", "Fetch",
++  "Error"					// Last command number
++};
++
++const char *xa_state_names[]={
++  "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
++};
++
++#ifdef __WIN__
++static void  test_signal(int sig_ptr)
++{
++#if !defined( DBUG_OFF)
++  MessageBox(NULL,"Test signal","DBUG",MB_OK);
++#endif
++#if defined(OS2)
++  fprintf(stderr, "Test signal %d\n", sig_ptr);
++  fflush(stderr);
++#endif
++}
++static void init_signals(void)
++{
++  int signals[7] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGBREAK,SIGABRT } ;
++  for (int i=0 ; i < 7 ; i++)
++    signal( signals[i], test_signal) ;
++}
++#endif
++
++static void unlock_locked_tables(THD *thd)
++{
++  if (thd->locked_tables)
++  {
++    thd->lock=thd->locked_tables;
++    thd->locked_tables=0;			// Will be automatically closed
++    close_thread_tables(thd);			// Free tables
++  }
++}
++
++
++static bool end_active_trans(THD *thd)
++{
++  int error=0;
++  DBUG_ENTER("end_active_trans");
++  if (unlikely(thd->in_sub_stmt))
++  {
++    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
++    DBUG_RETURN(1);
++  }
++  if (thd->transaction.xid_state.xa_state != XA_NOTR)
++  {
++    my_error(ER_XAER_RMFAIL, MYF(0),
++             xa_state_names[thd->transaction.xid_state.xa_state]);
++    DBUG_RETURN(1);
++  }
++  if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
++		      OPTION_TABLE_LOCK))
++  {
++    DBUG_PRINT("info",("options: 0x%llx", thd->options));
++    /* Safety if one did "drop table" on locked tables */
++    if (!thd->locked_tables)
++      thd->options&= ~OPTION_TABLE_LOCK;
++    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
++    if (ha_commit(thd))
++      error=1;
++    thd->options&= ~OPTION_BEGIN;
++    thd->transaction.all.modified_non_trans_table= FALSE;
++  }
++  DBUG_RETURN(error);
++}
++
++static bool begin_trans(THD *thd)
++{
++  int error=0;
++  if (unlikely(thd->in_sub_stmt))
++  {
++    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
++    return 1;
++  }
++  if (thd->locked_tables)
++  {
++    thd->lock=thd->locked_tables;
++    thd->locked_tables=0;			// Will be automatically closed
++    close_thread_tables(thd);			// Free tables
++  }
++  if (end_active_trans(thd))
++    error= -1;
++  else
++  {
++    LEX *lex= thd->lex;
++    thd->transaction.all.modified_non_trans_table= FALSE;
++    thd->options|= OPTION_BEGIN;
++    thd->server_status|= SERVER_STATUS_IN_TRANS;
++    if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
++      error= ha_start_consistent_snapshot(thd);
++  }
++  return error;
++}
++
++#ifdef HAVE_REPLICATION
++/*
++  Returns true if all tables should be ignored
++*/
++inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
++{
++  return table_rules_on && tables && !tables_ok(thd,tables);
++}
++#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;
++}
++
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++static HASH hash_user_connections;
++
++static int get_or_create_user_conn(THD *thd, const char *user,
++				   const char *host,
++				   USER_RESOURCES *mqh)
++{
++  int return_val= 0;
++  uint temp_len, user_len;
++  char temp_user[USER_HOST_BUFF_SIZE];
++  struct  user_conn *uc;
++
++  DBUG_ASSERT(user != 0);
++  DBUG_ASSERT(host != 0);
++
++  user_len= strlen(user);
++  temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1;
++  (void) pthread_mutex_lock(&LOCK_user_conn);
++  if (!(uc = (struct  user_conn *) hash_search(&hash_user_connections,
++					       (byte*) temp_user, temp_len)))
++  {
++    /* First connection for user; Create a user connection object */
++    if (!(uc= ((struct user_conn*)
++	       my_malloc(sizeof(struct user_conn) + temp_len+1,
++			 MYF(MY_WME)))))
++    {
++      net_send_error(thd, 0, NullS);		// Out of memory
++      return_val= 1;
++      goto end;
++    }
++    uc->user=(char*) (uc+1);
++    memcpy(uc->user,temp_user,temp_len+1);
++    uc->host= uc->user + user_len +  1;
++    uc->len= temp_len;
++    uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0;
++    uc->user_resources= *mqh;
++    uc->intime= thd->thr_create_time;
++    if (my_hash_insert(&hash_user_connections, (byte*) uc))
++    {
++      my_free((char*) uc,0);
++      net_send_error(thd, 0, NullS);		// Out of memory
++      return_val= 1;
++      goto end;
++    }
++  }
++  thd->user_connect=uc;
++  uc->connections++;
++end:
++  (void) pthread_mutex_unlock(&LOCK_user_conn);
++  return return_val;
++
++}
++#endif /* !NO_EMBEDDED_ACCESS_CHECKS */
++
++
++/*
++  Check if user exist and password supplied is correct. 
++
++  SYNOPSIS
++    check_user()
++    thd          thread handle, thd->security_ctx->{host,user,ip} are used
++    command      originator of the check: now check_user is called
++                 during connect and change user procedures; used for 
++                 logging.
++    passwd       scrambled password received from client
++    passwd_len   length of scrambled password
++    db           database name to connect to, may be NULL
++    check_count  dont know exactly
++
++    Note, that host, user and passwd may point to communication buffer.
++    Current implementation does not depend on that, but future changes
++    should be done with this in mind; 'thd' is INOUT, all other params
++    are 'IN'.
++
++  RETURN VALUE
++    0  OK; thd->security_ctx->user/master_access/priv_user/db_access and
++       thd->db are updated; OK is sent to client;
++   -1  access denied or handshake error; error is sent to client;
++   >0  error, not sent to client
++*/
++
++int check_user(THD *thd, enum enum_server_command command, 
++	       const char *passwd, uint passwd_len, const char *db,
++	       bool check_count)
++{
++  DBUG_ENTER("check_user");
++  LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 };
++
++#ifdef NO_EMBEDDED_ACCESS_CHECKS
++  thd->main_security_ctx.master_access= GLOBAL_ACLS;       // Full rights
++  /* Change database if necessary */
++  if (db && db[0])
++  {
++    /*
++      thd->db is saved in caller and needs to be freed by caller if this
++      function returns 0
++    */
++    thd->reset_db(NULL, 0);
++    if (mysql_change_db(thd, &db_str, FALSE))
++    {
++      /* Send the error to the client */
++      net_send_error(thd);
++      DBUG_RETURN(-1);
++    }
++  }
++  send_ok(thd);
++  DBUG_RETURN(0);
++#else
++
++  my_bool opt_secure_auth_local;
++  pthread_mutex_lock(&LOCK_global_system_variables);
++  opt_secure_auth_local= opt_secure_auth;
++  pthread_mutex_unlock(&LOCK_global_system_variables);
++  
++  /*
++    If the server is running in secure auth mode, short scrambles are 
++    forbidden.
++  */
++  if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
++  {
++    net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
++    mysql_log.write(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
++    DBUG_RETURN(-1);
++  }
++  if (passwd_len != 0 &&
++      passwd_len != SCRAMBLE_LENGTH &&
++      passwd_len != SCRAMBLE_LENGTH_323)
++    DBUG_RETURN(ER_HANDSHAKE_ERROR);
++
++  /*
++    Clear thd->db as it points to something, that will be freed when 
++    connection is closed. We don't want to accidentally free a wrong pointer
++    if connect failed. Also in case of 'CHANGE USER' failure, current
++    database will be switched to 'no database selected'.
++  */
++  thd->reset_db(NULL, 0);
++
++  USER_RESOURCES ur;
++  int res= acl_getroot(thd, &ur, passwd, passwd_len);
++#ifndef EMBEDDED_LIBRARY
++  if (res == -1)
++  {
++    /*
++      This happens when client (new) sends password scrambled with
++      scramble(), but database holds old value (scrambled with
++      scramble_323()). Here we please client to send scrambled_password
++      in old format.
++    */
++    NET *net= &thd->net;
++    if (opt_secure_auth_local)
++    {
++      net_printf_error(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
++                       thd->main_security_ctx.user,
++                       thd->main_security_ctx.host_or_ip);
++      mysql_log.write(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
++                      thd->main_security_ctx.user,
++                      thd->main_security_ctx.host_or_ip);
++      DBUG_RETURN(-1);
++    }
++    /* We have to read very specific packet size */
++    if (send_old_password_request(thd) ||
++        my_net_read(net) != SCRAMBLE_LENGTH_323 + 1)
++    {
++      inc_host_errors(&thd->remote.sin_addr);
++      DBUG_RETURN(ER_HANDSHAKE_ERROR);
++    }
++    /* Final attempt to check the user based on reply */
++    /* So as passwd is short, errcode is always >= 0 */
++    res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
++  }
++#endif /*EMBEDDED_LIBRARY*/
++  /* here res is always >= 0 */
++  if (res == 0)
++  {
++    if (!(thd->main_security_ctx.master_access &
++          NO_ACCESS)) // authentication is OK
++    {
++      DBUG_PRINT("info",
++                 ("Capabilities: %lu  packet_length: %ld  Host: '%s'  "
++                  "Login user: '%s' Priv_user: '%s'  Using password: %s "
++                  "Access: %lu  db: '%s'",
++                  thd->client_capabilities,
++                  thd->max_client_packet_length,
++                  thd->main_security_ctx.host_or_ip,
++                  thd->main_security_ctx.user,
++                  thd->main_security_ctx.priv_user,
++                  passwd_len ? "yes": "no",
++                  thd->main_security_ctx.master_access,
++                  (thd->db ? thd->db : "*none*")));
++
++      if (check_count)
++      {
++        VOID(pthread_mutex_lock(&LOCK_thread_count));
++        bool count_ok= thread_count <= max_connections + delayed_insert_threads
++                       || (thd->main_security_ctx.master_access & SUPER_ACL);
++        VOID(pthread_mutex_unlock(&LOCK_thread_count));
++        if (!count_ok)
++        {                                         // too many connections
++          net_send_error(thd, ER_CON_COUNT_ERROR);
++          DBUG_RETURN(-1);
++        }
++      }
++
++      /* Why logging is performed before all checks've passed? */
++      mysql_log.write(thd, command,
++                      (thd->main_security_ctx.priv_user ==
++                       thd->main_security_ctx.user ?
++                       (char*) "%s@%s on %s" :
++                       (char*) "%s@%s as anonymous on %s"),
++                      thd->main_security_ctx.user,
++                      thd->main_security_ctx.host_or_ip,
++                      db ? db : (char*) "");
++
++      /*
++        This is the default access rights for the current database.  It's
++        set to 0 here because we don't have an active database yet (and we
++        may not have an active database to set.
++      */
++      thd->main_security_ctx.db_access=0;
++
++      /* Don't allow user to connect if he has done too many queries */
++      if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn ||
++	   max_user_connections) &&
++	  get_or_create_user_conn(thd,
++            (opt_old_style_user_limits ? thd->main_security_ctx.user :
++             thd->main_security_ctx.priv_user),
++            (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip :
++             thd->main_security_ctx.priv_host),
++            &ur))
++	DBUG_RETURN(-1);
++      if (thd->user_connect &&
++	  (thd->user_connect->user_resources.conn_per_hour ||
++	   thd->user_connect->user_resources.user_conn ||
++	   max_user_connections) &&
++	  check_for_max_user_connections(thd, thd->user_connect))
++	DBUG_RETURN(-1);
++
++      /* Change database if necessary */
++      if (db && db[0])
++      {
++        if (mysql_change_db(thd, &db_str, FALSE))
++        {
++          /* Send error to the client */
++          net_send_error(thd);
++          if (thd->user_connect)
++            decrease_user_connections(thd->user_connect);
++          DBUG_RETURN(-1);
++        }
++      }
++      send_ok(thd);
++      thd->password= test(passwd_len);          // remember for error messages 
++      /* Ready to handle queries */
++      DBUG_RETURN(0);
++    }
++  }
++  else if (res == 2) // client gave short hash, server has long hash
++  {
++    net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
++    mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE));
++    DBUG_RETURN(-1);
++  }
++  net_printf_error(thd, ER_ACCESS_DENIED_ERROR,
++                   thd->main_security_ctx.user,
++                   thd->main_security_ctx.host_or_ip,
++                   passwd_len ? ER(ER_YES) : ER(ER_NO));
++  mysql_log.write(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
++                  thd->main_security_ctx.user,
++                  thd->main_security_ctx.host_or_ip,
++                  passwd_len ? ER(ER_YES) : ER(ER_NO));
++  DBUG_RETURN(-1);
++#endif /* NO_EMBEDDED_ACCESS_CHECKS */
++}
++
++/*
++  Check for maximum allowable user connections, if the mysqld server is
++  started with corresponding variable that is greater then 0.
++*/
++
++extern "C" byte *get_key_conn(user_conn *buff, uint *length,
++			      my_bool not_used __attribute__((unused)))
++{
++  *length=buff->len;
++  return (byte*) buff->user;
++}
++
++extern "C" void free_user(struct user_conn *uc)
++{
++  my_free((char*) uc,MYF(0));
++}
++
++void init_max_user_conn(void)
++{
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  (void) hash_init(&hash_user_connections,system_charset_info,max_connections,
++		   0,0,
++		   (hash_get_key) get_key_conn, (hash_free_key) free_user,
++		   0);
++#endif
++}
++
++
++/*
++  check if user has already too many connections
++  
++  SYNOPSIS
++  check_for_max_user_connections()
++  thd			Thread handle
++  uc			User connect object
++
++  NOTES
++    If check fails, we decrease user connection count, which means one
++    shouldn't call decrease_user_connections() after this function.
++
++  RETURN
++    0	ok
++    1	error
++*/
++
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++
++static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
++{
++  int error=0;
++  DBUG_ENTER("check_for_max_user_connections");
++
++  (void) pthread_mutex_lock(&LOCK_user_conn);
++  if (max_user_connections && !uc->user_resources.user_conn &&
++      max_user_connections < (uint) uc->connections)
++  {
++    net_printf_error(thd, ER_TOO_MANY_USER_CONNECTIONS, uc->user);
++    error=1;
++    goto end;
++  }
++  time_out_user_resource_limits(thd, uc);
++  if (uc->user_resources.user_conn &&
++      uc->user_resources.user_conn < uc->connections)
++  {
++    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
++                     "max_user_connections",
++                     (long) uc->user_resources.user_conn);
++    error= 1;
++    goto end;
++  }
++  if (uc->user_resources.conn_per_hour &&
++      uc->user_resources.conn_per_hour <= uc->conn_per_hour)
++  {
++    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
++                     "max_connections_per_hour",
++                     (long) uc->user_resources.conn_per_hour);
++    error=1;
++    goto end;
++  }
++  uc->conn_per_hour++;
++
++  end:
++  if (error)
++    uc->connections--; // no need for decrease_user_connections() here
++  (void) pthread_mutex_unlock(&LOCK_user_conn);
++  DBUG_RETURN(error);
++}
++
++/*
++  Decrease user connection count
++
++  SYNOPSIS
++    decrease_user_connections()
++    uc			User connection object
++
++  NOTES
++    If there is a n user connection object for a connection
++    (which only happens if 'max_user_connections' is defined or
++    if someone has created a resource grant for a user), then
++    the connection count is always incremented on connect.
++
++    The user connect object is not freed if some users has
++    'max connections per hour' defined as we need to be able to hold
++    count over the lifetime of the connection.
++*/
++
++static void decrease_user_connections(USER_CONN *uc)
++{
++  DBUG_ENTER("decrease_user_connections");
++  (void) pthread_mutex_lock(&LOCK_user_conn);
++  DBUG_ASSERT(uc->connections);
++  if (!--uc->connections && !mqh_used)
++  {
++    /* Last connection for user; Delete it */
++    (void) hash_delete(&hash_user_connections,(byte*) uc);
++  }
++  (void) pthread_mutex_unlock(&LOCK_user_conn);
++  DBUG_VOID_RETURN;
++}
++
++#endif /* NO_EMBEDDED_ACCESS_CHECKS */
++
++
++void free_max_user_conn(void)
++{
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  hash_free(&hash_user_connections);
++#endif /* NO_EMBEDDED_ACCESS_CHECKS */
++}
++
++
++
++/*
++  Mark all commands that somehow changes a table
++  This is used to check number of updates / hour
++
++  sql_command is actually set to SQLCOM_END sometimes
++  so we need the +1 to include it in the array.
++
++  numbers are:
++     0  - read-only query
++  != 0  - query that may change a table
++     2  - query that returns meaningful ROW_COUNT() -
++          a number of modified rows
++*/
++
++char  uc_update_queries[SQLCOM_END+1];
++
++void init_update_queries(void)
++{
++  bzero((gptr) &uc_update_queries, sizeof(uc_update_queries));
++
++  uc_update_queries[SQLCOM_CREATE_TABLE]=1;
++  uc_update_queries[SQLCOM_CREATE_INDEX]=1;
++  uc_update_queries[SQLCOM_ALTER_TABLE]=1;
++  uc_update_queries[SQLCOM_UPDATE]=2;
++  uc_update_queries[SQLCOM_UPDATE_MULTI]=2;
++  uc_update_queries[SQLCOM_INSERT]=2;
++  uc_update_queries[SQLCOM_INSERT_SELECT]=2;
++  uc_update_queries[SQLCOM_DELETE]=2;
++  uc_update_queries[SQLCOM_DELETE_MULTI]=2;
++  uc_update_queries[SQLCOM_TRUNCATE]=1;
++  uc_update_queries[SQLCOM_DROP_TABLE]=1;
++  uc_update_queries[SQLCOM_LOAD]=1;
++  uc_update_queries[SQLCOM_CREATE_DB]=1;
++  uc_update_queries[SQLCOM_DROP_DB]=1;
++  uc_update_queries[SQLCOM_REPLACE]=2;
++  uc_update_queries[SQLCOM_REPLACE_SELECT]=2;
++  uc_update_queries[SQLCOM_RENAME_TABLE]=1;
++  uc_update_queries[SQLCOM_BACKUP_TABLE]=1;
++  uc_update_queries[SQLCOM_RESTORE_TABLE]=1;
++  uc_update_queries[SQLCOM_DROP_INDEX]=1;
++  uc_update_queries[SQLCOM_CREATE_VIEW]=1;
++  uc_update_queries[SQLCOM_DROP_VIEW]=1;
++}
++
++bool is_update_query(enum enum_sql_command command)
++{
++  DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
++  return uc_update_queries[command] != 0;
++}
++
++/*
++  Reset per-hour user resource limits when it has been more than
++  an hour since they were last checked
++
++  SYNOPSIS:
++    time_out_user_resource_limits()
++    thd			Thread handler
++    uc			User connection details
++
++  NOTE:
++    This assumes that the LOCK_user_conn mutex has been acquired, so it is
++    safe to test and modify members of the USER_CONN structure.
++*/
++
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++
++static void time_out_user_resource_limits(THD *thd, USER_CONN *uc)
++{
++  time_t check_time = thd->start_time ?  thd->start_time : time(NULL);
++  DBUG_ENTER("time_out_user_resource_limits");
++
++  /* If more than a hour since last check, reset resource checking */
++  if (check_time  - uc->intime >= 3600)
++  {
++    uc->questions=1;
++    uc->updates=0;
++    uc->conn_per_hour=0;
++    uc->intime=check_time;
++  }
++
++  DBUG_VOID_RETURN;
++}
++
++/*
++  Check if maximum queries per hour limit has been reached
++  returns 0 if OK.
++*/
++
++static bool check_mqh(THD *thd, uint check_command)
++{
++  bool error= 0;
++  USER_CONN *uc=thd->user_connect;
++  DBUG_ENTER("check_mqh");
++  DBUG_ASSERT(uc != 0);
++
++  (void) pthread_mutex_lock(&LOCK_user_conn);
++
++  time_out_user_resource_limits(thd, uc);
++
++  /* Check that we have not done too many questions / hour */
++  if (uc->user_resources.questions &&
++      uc->questions++ >= uc->user_resources.questions)
++  {
++    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
++                     (long) uc->user_resources.questions);
++    error=1;
++    goto end;
++  }
++  if (check_command < (uint) SQLCOM_END)
++  {
++    /* Check that we have not done too many updates / hour */
++    if (uc->user_resources.updates && uc_update_queries[check_command] &&
++	uc->updates++ >= uc->user_resources.updates)
++    {
++      net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
++                       (long) uc->user_resources.updates);
++      error=1;
++      goto end;
++    }
++  }
++end:
++  (void) pthread_mutex_unlock(&LOCK_user_conn);
++  DBUG_RETURN(error);
++}
++
++#endif /* NO_EMBEDDED_ACCESS_CHECKS */
++
++
++static void reset_mqh(LEX_USER *lu, bool get_them= 0)
++{
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  (void) pthread_mutex_lock(&LOCK_user_conn);
++  if (lu)  // for GRANT
++  {
++    USER_CONN *uc;
++    uint temp_len=lu->user.length+lu->host.length+2;
++    char temp_user[USER_HOST_BUFF_SIZE];
++
++    memcpy(temp_user,lu->user.str,lu->user.length);
++    memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
++    temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0;
++    if ((uc = (struct  user_conn *) hash_search(&hash_user_connections,
++						(byte*) temp_user, temp_len)))
++    {
++      uc->questions=0;
++      get_mqh(temp_user,&temp_user[lu->user.length+1],uc);
++      uc->updates=0;
++      uc->conn_per_hour=0;
++    }
++  }
++  else
++  {
++    /* for FLUSH PRIVILEGES and FLUSH USER_RESOURCES */
++    for (uint idx=0;idx < hash_user_connections.records; idx++)
++    {
++      USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections,
++						      idx);
++      if (get_them)
++	get_mqh(uc->user,uc->host,uc);
++      uc->questions=0;
++      uc->updates=0;
++      uc->conn_per_hour=0;
++    }
++  }
++  (void) pthread_mutex_unlock(&LOCK_user_conn);
++#endif /* NO_EMBEDDED_ACCESS_CHECKS */
++}
++
++void thd_init_client_charset(THD *thd, uint cs_number)
++{
++  /*
++   Use server character set and collation if
++   - opt_character_set_client_handshake is not set
++   - client has not specified a character set
++   - client character set is the same as the servers
++   - client character set doesn't exists in server
++  */
++  if (!opt_character_set_client_handshake ||
++      !(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
++      !my_strcasecmp(&my_charset_latin1,
++                     global_system_variables.character_set_client->name,
++                     thd->variables.character_set_client->name))
++  {
++    thd->variables.character_set_client=
++      global_system_variables.character_set_client;
++    thd->variables.collation_connection=
++      global_system_variables.collation_connection;
++    thd->variables.character_set_results=
++      global_system_variables.character_set_results;
++  }
++  else
++  {
++    thd->variables.character_set_results=
++      thd->variables.collation_connection= 
++      thd->variables.character_set_client;
++  }
++}
++
++
++/*
++    Perform handshake, authorize client and update thd ACL variables.
++  SYNOPSIS
++    check_connection()
++    thd  thread handle
++
++  RETURN
++     0  success, OK is sent to user, thd is updated.
++    -1  error, which is sent to user
++   > 0  error code (not sent to user)
++*/
++
++#ifndef EMBEDDED_LIBRARY
++static int check_connection(THD *thd)
++{
++  uint connect_errors= 0;
++  NET *net= &thd->net;
++  ulong pkt_len= 0;
++  char *end;
++
++  DBUG_PRINT("info",
++             ("New connection received on %s", vio_description(net->vio)));
++#ifdef SIGNAL_WITH_VIO_CLOSE
++  thd->set_active_vio(net->vio);
++#endif
++
++  if (!thd->main_security_ctx.host)         // If TCP/IP connection
++  {
++    char ip[30];
++
++    if (vio_peer_addr(net->vio, ip, &thd->peer_port))
++      return (ER_BAD_HOST_ERROR);
++    if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(0))))
++      return (ER_OUT_OF_RESOURCES);
++    thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip;
++    vio_in_addr(net->vio,&thd->remote.sin_addr);
++    if (!(specialflag & SPECIAL_NO_RESOLVE))
++    {
++      vio_in_addr(net->vio,&thd->remote.sin_addr);
++      thd->main_security_ctx.host=
++        ip_to_hostname(&thd->remote.sin_addr, &connect_errors);
++      /* Cut very long hostnames to avoid possible overflows */
++      if (thd->main_security_ctx.host)
++      {
++        if (thd->main_security_ctx.host != my_localhost)
++          thd->main_security_ctx.host[min(strlen(thd->main_security_ctx.host),
++                                          HOSTNAME_LENGTH)]= 0;
++        thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
++      }
++      if (connect_errors > max_connect_errors)
++        return(ER_HOST_IS_BLOCKED);
++    }
++    DBUG_PRINT("info",("Host: %s  ip: %s",
++		       (thd->main_security_ctx.host ?
++                        thd->main_security_ctx.host : "unknown host"),
++		       (thd->main_security_ctx.ip ?
++                        thd->main_security_ctx.ip : "unknown ip")));
++    if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip))
++      return(ER_HOST_NOT_PRIVILEGED);
++  }
++  else /* Hostname given means that the connection was on a socket */
++  {
++    DBUG_PRINT("info",("Host: %s", thd->main_security_ctx.host));
++    thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
++    thd->main_security_ctx.ip= 0;
++    /* Reset sin_addr */
++    bzero((char*) &thd->remote, sizeof(thd->remote));
++  }
++  vio_keepalive(net->vio, TRUE);
++  {
++    /* buff[] needs to big enough to hold the server_version variable */
++    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
++    ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
++			  CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
++
++    if (opt_using_transactions)
++      client_flags|=CLIENT_TRANSACTIONS;
++#ifdef HAVE_COMPRESS
++    client_flags |= CLIENT_COMPRESS;
++#endif /* HAVE_COMPRESS */
++#ifdef HAVE_OPENSSL
++    if (ssl_acceptor_fd)
++      client_flags |= CLIENT_SSL;       /* Wow, SSL is available! */
++#endif /* HAVE_OPENSSL */
++
++    end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
++    int4store((uchar*) end, thd->thread_id);
++    end+= 4;
++    /*
++      So as check_connection is the only entry point to authorization
++      procedure, scramble is set here. This gives us new scramble for
++      each handshake.
++    */
++    create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
++    /*
++      Old clients does not understand long scrambles, but can ignore packet
++      tail: that's why first part of the scramble is placed here, and second
++      part at the end of packet.
++    */
++    end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
++   
++    int2store(end, client_flags);
++    /* write server characteristics: up to 16 bytes allowed */
++    end[2]=(char) default_charset_info->number;
++    int2store(end+3, thd->server_status);
++    bzero(end+5, 13);
++    end+= 18;
++    /* write scramble tail */
++    end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323, 
++                 SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
++
++    /* At this point we write connection message and read reply */
++    if (net_write_command(net, (uchar) protocol_version, "", 0, buff,
++			  (uint) (end-buff)) ||
++	(pkt_len= my_net_read(net)) == packet_error ||
++	pkt_len < MIN_HANDSHAKE_SIZE)
++    {
++      inc_host_errors(&thd->remote.sin_addr);
++      return(ER_HANDSHAKE_ERROR);
++    }
++  }
++#ifdef _CUSTOMCONFIG_
++#include "_cust_sql_parse.h"
++#endif
++  if (connect_errors)
++    reset_host_errors(&thd->remote.sin_addr);
++  if (thd->packet.alloc(thd->variables.net_buffer_length))
++    return(ER_OUT_OF_RESOURCES);
++
++  thd->client_capabilities=uint2korr(net->read_pos);
++  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
++  {
++    thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
++    thd->max_client_packet_length= uint4korr(net->read_pos+4);
++    DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
++    thd_init_client_charset(thd, (uint) net->read_pos[8]);
++    thd->update_charset();
++    end= (char*) net->read_pos+32;
++  }
++  else
++  {
++    thd->max_client_packet_length= uint3korr(net->read_pos+2);
++    end= (char*) net->read_pos+5;
++  }
++
++  if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
++    thd->variables.sql_mode|= MODE_IGNORE_SPACE;
++#ifdef HAVE_OPENSSL
++  DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
++  if (thd->client_capabilities & CLIENT_SSL)
++  {
++    /* Do the SSL layering. */
++    if (!ssl_acceptor_fd)
++    {
++      inc_host_errors(&thd->remote.sin_addr);
++      return(ER_HANDSHAKE_ERROR);
++    }
++    DBUG_PRINT("info", ("IO layer change in progress..."));
++    if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
++    {
++      DBUG_PRINT("error", ("Failed to accept new SSL connection"));
++      inc_host_errors(&thd->remote.sin_addr);
++      return(ER_HANDSHAKE_ERROR);
++    }
++    DBUG_PRINT("info", ("Reading user information over SSL layer"));
++    if ((pkt_len= my_net_read(net)) == packet_error ||
++	pkt_len < NORMAL_HANDSHAKE_SIZE)
++    {
++      DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
++			   pkt_len));
++      inc_host_errors(&thd->remote.sin_addr);
++      return(ER_HANDSHAKE_ERROR);
++    }
++  }
++#endif
++
++  if (end >= (char*) net->read_pos+ pkt_len +2)
++  {
++    inc_host_errors(&thd->remote.sin_addr);
++    return(ER_HANDSHAKE_ERROR);
++  }
++
++  if (thd->client_capabilities & CLIENT_INTERACTIVE)
++    thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
++  if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
++      opt_using_transactions)
++    net->return_status= &thd->server_status;
++
++  char *user= end;
++  char *passwd= strend(user)+1;
++  uint user_len= passwd - user - 1;
++  char *db= passwd;
++  char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
++  char user_buff[USERNAME_LENGTH + 1];	// buffer to store user in utf8
++  uint dummy_errors;
++
++  /*
++    Old clients send null-terminated string as password; new clients send
++    the size (1 byte) + string (not null-terminated). Hence in case of empty
++    password both send '\0'.
++
++    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
++    *passwd > 127 and become 2**32-127 after casting to uint.
++  */
++  uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
++    (uchar)(*passwd++) : strlen(passwd);
++  db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
++    db + passwd_len + 1 : 0;
++  uint db_len= db ? strlen(db) : 0;
++
++  if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
++  {
++    inc_host_errors(&thd->remote.sin_addr);
++    return ER_HANDSHAKE_ERROR;
++  }
++
++  /* Since 4.1 all database names are stored in utf8 */
++  if (db)
++  {
++    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
++                             system_charset_info,
++                             db, db_len,
++                             thd->charset(), &dummy_errors)]= 0;
++    db= db_buff;
++  }
++
++  user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
++                                       system_charset_info, user, user_len,
++                                       thd->charset(), &dummy_errors)]= '\0';
++  user= user_buff;
++
++  /* If username starts and ends in "'", chop them off */
++  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
++  {
++    user[user_len-1]= 0;
++    user++;
++    user_len-= 2;
++  }
++
++  if (thd->main_security_ctx.user)
++    x_free(thd->main_security_ctx.user);
++  if (!(thd->main_security_ctx.user= my_strdup(user, MYF(0))))
++    return (ER_OUT_OF_RESOURCES);
++  return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
++}
++
++
++void execute_init_command(THD *thd, sys_var_str *init_command_var,
++			  rw_lock_t *var_mutex)
++{
++  Vio* save_vio;
++  ulong save_client_capabilities;
++
++  thd_proc_info(thd, "Execution of init_command");
++  /*
++    We need to lock init_command_var because
++    during execution of init_command_var query
++    values of init_command_var can't be changed
++  */
++  rw_rdlock(var_mutex);
++  thd->query= init_command_var->value;
++  thd->query_length= init_command_var->value_length;
++  save_client_capabilities= thd->client_capabilities;
++  thd->client_capabilities|= CLIENT_MULTI_QUERIES;
++  /*
++    We don't need return result of execution to client side.
++    To forbid this we should set thd->net.vio to 0.
++  */
++  save_vio= thd->net.vio;
++  thd->net.vio= 0;
++  thd->net.no_send_error= 0;
++  dispatch_command(COM_QUERY, thd, thd->query, thd->query_length+1);
++  rw_unlock(var_mutex);
++  thd->client_capabilities= save_client_capabilities;
++  thd->net.vio= save_vio;
++}
++
++
++pthread_handler_t handle_one_connection(void *arg)
++{
++  THD *thd=(THD*) arg;
++  uint launch_time  =
++    (uint) ((thd->thr_create_time = time(NULL)) - thd->connect_time);
++  if (launch_time >= slow_launch_time)
++    statistic_increment(slow_launch_threads,&LOCK_status );
++
++  pthread_detach_this_thread();
++
++#if !defined( __WIN__) && !defined(OS2)	// Win32 calls this in pthread_create
++  /* The following calls needs to be done before we call DBUG_ macros */
++  if (!(test_flags & TEST_NO_THREADS) & my_thread_init())
++  {
++    close_connection(thd, ER_OUT_OF_RESOURCES, 1);
++    statistic_increment(aborted_connects,&LOCK_status);
++    end_thread(thd,0);
++    return 0;
++  }
++#endif
++
++  /*
++    handle_one_connection() is the only way a thread would start
++    and would always be on top of the stack, therefore, the thread
++    stack always starts at the address of the first local variable
++    of handle_one_connection, which is thd. We need to know the
++    start of the stack so that we could check for stack overruns.
++  */
++  DBUG_PRINT("info", ("handle_one_connection called by thread %lu\n",
++		      thd->thread_id));
++  /* now that we've called my_thread_init(), it is safe to call DBUG_* */
++
++#if defined(__WIN__)
++  init_signals();
++#elif !defined(OS2) && !defined(__NETWARE__)
++  sigset_t set;
++  VOID(sigemptyset(&set));			// Get mask in use
++  VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
++#endif
++  thd->thread_stack= (char*) &thd;
++  if (thd->store_globals())
++  {
++    close_connection(thd, ER_OUT_OF_RESOURCES, 1);
++    statistic_increment(aborted_connects,&LOCK_status);
++    end_thread(thd,0);
++    return 0;
++  }
++
++  do
++  {
++    int error;
++    NET *net= &thd->net;
++    Security_context *sctx= thd->security_ctx;
++    net->no_send_error= 0;
++
++    /* Use "connect_timeout" value during connection phase */
++    my_net_set_read_timeout(net, connect_timeout);
++    my_net_set_write_timeout(net, connect_timeout);
++
++    if ((error=check_connection(thd)))
++    {						// Wrong permissions
++      if (error > 0)
++	net_printf_error(thd, error, sctx->host_or_ip);
++#ifdef __NT__
++      if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
++	my_sleep(1000);				/* must wait after eof() */
++#endif
++      statistic_increment(aborted_connects,&LOCK_status);
++      goto end_thread;
++    }
++#ifdef __NETWARE__
++    netware_reg_user(sctx->ip, sctx->user, "MySQL");
++#endif
++    if (thd->variables.max_join_size == HA_POS_ERROR)
++      thd->options |= OPTION_BIG_SELECTS;
++    if (thd->client_capabilities & CLIENT_COMPRESS)
++      net->compress=1;				// Use compression
++
++    thd->version= refresh_version;
++    thd_proc_info(thd, 0);
++    thd->command= COM_SLEEP;
++    thd->init_for_queries();
++
++    if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL))
++    {
++      execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
++      if (thd->query_error)
++      {
++	thd->killed= THD::KILL_CONNECTION;
++        sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
++                          thd->thread_id,(thd->db ? thd->db : "unconnected"),
++                          sctx->user ? sctx->user : "unauthenticated",
++                          sctx->host_or_ip, "init_connect command failed");
++        sql_print_warning("%s", net->last_error);
++      }
++      thd_proc_info(thd, 0);
++      thd->init_for_queries();
++    }
++
++    /* Connect completed, set read/write timeouts back to tdefault */
++    my_net_set_read_timeout(net, thd->variables.net_read_timeout);
++    my_net_set_write_timeout(net, thd->variables.net_write_timeout);
++
++    while (!net->error && net->vio != 0 &&
++           !(thd->killed == THD::KILL_CONNECTION))
++    {
++      net->no_send_error= 0;
++      if (do_command(thd))
++	break;
++    }
++    if (thd->user_connect)
++      decrease_user_connections(thd->user_connect);
++    if (net->error && net->vio != 0 && net->report_error)
++    {
++      if (!thd->killed && thd->variables.log_warnings > 1)
++	sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
++                          thd->thread_id,(thd->db ? thd->db : "unconnected"),
++                          sctx->user ? sctx->user : "unauthenticated",
++                          sctx->host_or_ip,
++                          (net->last_errno ? ER(net->last_errno) :
++                           ER(ER_UNKNOWN_ERROR)));
++      net_send_error(thd, net->last_errno, NullS);
++      statistic_increment(aborted_threads,&LOCK_status);
++    }
++    else if (thd->killed)
++    {
++      statistic_increment(aborted_threads,&LOCK_status);
++    }
++    
++end_thread:
++    close_connection(thd, 0, 1);
++    end_thread(thd,1);
++    /*
++      If end_thread returns, we are either running with --one-thread
++      or this thread has been schedule to handle the next query
++    */
++    thd= current_thd;
++    thd->thread_stack= (char*) &thd;
++  } while (!(test_flags & TEST_NO_THREADS));
++  /* The following is only executed if we are not using --one-thread */
++  return(0);					/* purecov: deadcode */
++}
++
++#endif /* EMBEDDED_LIBRARY */
++
++/*
++  Execute commands from bootstrap_file.
++  Used when creating the initial grant tables
++*/
++
++pthread_handler_t handle_bootstrap(void *arg)
++{
++  THD *thd=(THD*) arg;
++  FILE *file=bootstrap_file;
++  char *buff;
++  const char* found_semicolon= NULL;
++
++  /* The following must be called before DBUG_ENTER */
++  thd->thread_stack= (char*) &thd;
++  if (my_thread_init() || thd->store_globals())
++  {
++#ifndef EMBEDDED_LIBRARY
++    close_connection(thd, ER_OUT_OF_RESOURCES, 1);
++#endif
++    thd->fatal_error();
++    goto end;
++  }
++  DBUG_ENTER("handle_bootstrap");
++
++#ifndef EMBEDDED_LIBRARY
++  pthread_detach_this_thread();
++  thd->thread_stack= (char*) &thd;
++#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
++  sigset_t set;
++  VOID(sigemptyset(&set));			// Get mask in use
++  VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
++#endif
++#endif /* EMBEDDED_LIBRARY */
++
++  if (thd->variables.max_join_size == HA_POS_ERROR)
++    thd->options |= OPTION_BIG_SELECTS;
++
++  thd_proc_info(thd, 0);
++  thd->version=refresh_version;
++  thd->security_ctx->priv_user=
++    thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
++  /*
++    Make the "client" handle multiple results. This is necessary
++    to enable stored procedures with SELECTs and Dynamic SQL
++    in init-file.
++  */
++  thd->client_capabilities|= CLIENT_MULTI_RESULTS;
++
++  buff= (char*) thd->net.buff;
++  thd->init_for_queries();
++  while (fgets(buff, thd->net.max_packet, file))
++  {
++   ulong length= (ulong) strlen(buff);
++   while (buff[length-1] != '\n' && !feof(file))
++   {
++     /*
++       We got only a part of the current string. Will try to increase
++       net buffer then read the rest of the current string.
++     */
++     if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
++     {
++       net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS);
++       thd->fatal_error();
++       break;
++     }
++     buff= (char*) thd->net.buff;
++     fgets(buff + length, thd->net.max_packet - length, file);
++     length+= (ulong) strlen(buff + length);
++   }
++   if (thd->is_fatal_error)
++     break;
++
++    while (length && (my_isspace(thd->charset(), buff[length-1]) ||
++           buff[length-1] == ';'))
++      length--;
++    buff[length]=0;
++    thd->query_length=length;
++    thd->query= thd->memdup_w_gap(buff, length+1, 
++				  thd->db_length+1+QUERY_CACHE_FLAGS_SIZE);
++    thd->query[length] = '\0';
++    DBUG_PRINT("query",("%-.4096s",thd->query));
++    /*
++      We don't need to obtain LOCK_thread_count here because in bootstrap
++      mode we have only one thread.
++    */
++    thd->query_id=next_query_id();
++    thd->set_time();
++    mysql_parse(thd, thd->query, length, & found_semicolon);
++    close_thread_tables(thd);			// Free tables
++
++    if (thd->is_fatal_error)
++      break;
++
++    if (thd->net.report_error)
++    {
++      /* The query failed, send error to log and abort bootstrap */
++      net_send_error(thd);
++      thd->fatal_error();
++      break;
++    }
++
++    free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
++#ifdef USING_TRANSACTIONS
++    free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC));
++#endif
++  }
++
++end:
++  /* Remember the exit code of bootstrap */
++  bootstrap_error= thd->is_fatal_error;
++
++  net_end(&thd->net);
++  thd->cleanup();
++  delete thd;
++
++#ifndef EMBEDDED_LIBRARY
++  (void) pthread_mutex_lock(&LOCK_thread_count);
++  thread_count--;
++  (void) pthread_mutex_unlock(&LOCK_thread_count);
++  (void) pthread_cond_broadcast(&COND_thread_count);
++  my_thread_end();
++  pthread_exit(0);
++#endif
++  DBUG_RETURN(0);
++}
++
++
++    /* This works because items are allocated with sql_alloc() */
++
++void cleanup_items(Item *item)
++{
++  DBUG_ENTER("cleanup_items");  
++  for (; item ; item=item->next)
++    item->cleanup();
++  DBUG_VOID_RETURN;
++}
++
++/*
++  Handle COM_TABLE_DUMP command
++
++  SYNOPSIS
++    mysql_table_dump
++      thd           thread handle
++      db            database name or an empty string. If empty,
++                    the current database of the connection is used
++      tbl_name      name of the table to dump
++
++  NOTES
++    This function is written to handle one specific command only.
++
++  RETURN VALUE
++    0               success
++    1               error, the error message is set in THD
++*/
++
++static
++int mysql_table_dump(THD* thd, char* db, char* tbl_name)
++{
++  TABLE* table;
++  TABLE_LIST* table_list;
++  int error = 0;
++  DBUG_ENTER("mysql_table_dump");
++  db = (db && db[0]) ? db : thd->db;
++  if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST))))
++    DBUG_RETURN(1); // out of memory
++  table_list->db= db;
++  table_list->table_name= table_list->alias= tbl_name;
++  table_list->lock_type= TL_READ_NO_INSERT;
++  table_list->prev_global= &table_list;	// can be removed after merge with 4.1
++
++  if (!db || check_db_name(db))
++  {
++    my_error(ER_WRONG_DB_NAME ,MYF(0), db ? db : "NULL");
++    goto err;
++  }
++  if (lower_case_table_names)
++    my_casedn_str(files_charset_info, tbl_name);
++  remove_escape(table_list->table_name);
++
++  if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT)))
++    DBUG_RETURN(1);
++
++  if (check_one_table_access(thd, SELECT_ACL, table_list))
++    goto err;
++  thd->free_list = 0;
++  thd->query_length=(uint) strlen(tbl_name);
++  thd->query = tbl_name;
++  if ((error = mysqld_dump_create_info(thd, table_list, -1)))
++  {
++    my_error(ER_GET_ERRNO, MYF(0), my_errno);
++    goto err;
++  }
++  net_flush(&thd->net);
++  if ((error= table->file->dump(thd,-1)))
++    my_error(ER_GET_ERRNO, MYF(0), error);
++
++err:
++  DBUG_RETURN(error);
++}
++
++/*
++  Ends the current transaction and (maybe) begin the next
++
++  SYNOPSIS
++    end_trans()
++      thd            Current thread
++      completion     Completion type
++
++  RETURN
++    0 - OK
++*/
++
++int end_trans(THD *thd, enum enum_mysql_completiontype completion)
++{
++  bool do_release= 0;
++  int res= 0;
++  DBUG_ENTER("end_trans");
++
++  if (unlikely(thd->in_sub_stmt))
++  {
++    my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
++    DBUG_RETURN(1);
++  }
++  if (thd->transaction.xid_state.xa_state != XA_NOTR)
++  {
++    my_error(ER_XAER_RMFAIL, MYF(0),
++             xa_state_names[thd->transaction.xid_state.xa_state]);
++    DBUG_RETURN(1);
++  }
++  switch (completion) {
++  case COMMIT:
++    /*
++     We don't use end_active_trans() here to ensure that this works
++     even if there is a problem with the OPTION_AUTO_COMMIT flag
++     (Which of course should never happen...)
++    */
++    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
++    res= ha_commit(thd);
++    thd->options&= ~OPTION_BEGIN;
++    thd->transaction.all.modified_non_trans_table= FALSE;
++    break;
++  case COMMIT_RELEASE:
++    do_release= 1; /* fall through */
++  case COMMIT_AND_CHAIN:
++    res= end_active_trans(thd);
++    if (!res && completion == COMMIT_AND_CHAIN)
++      res= begin_trans(thd);
++    break;
++  case ROLLBACK_RELEASE:
++    do_release= 1; /* fall through */
++  case ROLLBACK:
++  case ROLLBACK_AND_CHAIN:
++  {
++    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
++    if (ha_rollback(thd))
++      res= -1;
++    thd->options&= ~OPTION_BEGIN;
++    thd->transaction.all.modified_non_trans_table= FALSE;
++    if (!res && (completion == ROLLBACK_AND_CHAIN))
++      res= begin_trans(thd);
++    break;
++  }
++  default:
++    res= -1;
++    my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
++    DBUG_RETURN(-1);
++  }
++
++  if (res < 0)
++    my_error(thd->killed_errno(), MYF(0));
++  else if ((res == 0) && do_release)
++    thd->killed= THD::KILL_CONNECTION;
++
++  DBUG_RETURN(res);
++}
++
++#ifndef EMBEDDED_LIBRARY
++
++/*
++  Read one command from connection and execute it (query or simple command).
++  This function is called in loop from thread function.
++  SYNOPSIS
++    do_command()
++  RETURN VALUE
++    0  success
++    1  request of thread shutdown (see dispatch_command() description)
++*/
++
++bool do_command(THD *thd)
++{
++  char *packet= 0;
++  ulong packet_length;
++  NET *net= &thd->net;
++  enum enum_server_command command;
++  DBUG_ENTER("do_command");
++
++  /*
++    indicator of uninitialized lex => normal flow of errors handling
++    (see my_message_sql)
++  */
++  thd->lex->current_select= 0;
++
++  /*
++    This thread will do a blocking read from the client which
++    will be interrupted when the next command is received from
++    the client, the connection is closed or "net_wait_timeout"
++    number of seconds has passed
++  */
++  my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
++
++  thd->clear_error();				// Clear error message
++
++  net_new_transaction(net);
++  if ((packet_length=my_net_read(net)) == packet_error)
++  {
++    DBUG_PRINT("info",("Got error %d reading command from socket %s",
++		       net->error,
++		       vio_description(net->vio)));
++    /* Check if we can continue without closing the connection */
++    if (net->error != 3)
++    {
++      statistic_increment(aborted_threads,&LOCK_status);
++      DBUG_RETURN(TRUE);			// We have to close it.
++    }
++    net_send_error(thd, net->last_errno, NullS);
++    net->error= 0;
++    DBUG_RETURN(FALSE);
++  }
++  else
++  {
++    packet=(char*) net->read_pos;
++    command = (enum enum_server_command) (uchar) packet[0];
++    if (command >= COM_END)
++      command= COM_END;				// Wrong command
++    DBUG_PRINT("info",("Command on %s = %d (%s)",
++		       vio_description(net->vio), command,
++		       command_name[command]));
++  }
++
++  /* Restore read timeout value */
++  my_net_set_read_timeout(net, thd->variables.net_read_timeout);
++
++  /*
++    packet_length contains length of data, as it was stored in packet
++    header. In case of malformed header, packet_length can be zero.
++    If packet_length is not zero, my_net_read ensures that this number
++    of bytes was actually read from network. Additionally my_net_read
++    sets packet[packet_length]= 0 (thus if packet_length == 0,
++    command == packet[0] == COM_SLEEP).
++    In dispatch_command packet[packet_length] points beyond the end of packet.
++  */
++  DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length));
++}
++#endif  /* EMBEDDED_LIBRARY */
++
++
++/*
++   Perform one connection-level (COM_XXXX) command.
++
++  SYNOPSIS
++    dispatch_command()
++    thd             connection handle
++    command         type of command to perform 
++    packet          data for the command, packet is always null-terminated
++    packet_length   length of packet + 1 (to show that data is
++                    null-terminated) except for COM_SLEEP, where it
++                    can be zero.
++  RETURN VALUE
++    0   ok
++    1   request of thread shutdown, i. e. if command is
++        COM_QUIT/COM_SHUTDOWN
++*/
++
++bool dispatch_command(enum enum_server_command command, THD *thd,
++		      char* packet, uint packet_length)
++{
++  NET *net= &thd->net;
++  bool error= 0;
++  DBUG_ENTER("dispatch_command");
++
++  if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
++  {
++    thd->killed= THD::NOT_KILLED;
++    thd->mysys_var->abort= 0;
++  }
++
++  thd->command=command;
++  /*
++    Commands which always take a long time are logged into
++    the slow log only if opt_log_slow_admin_statements is set.
++  */
++  thd->enable_slow_log= TRUE;
++  thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
++  thd->set_time();
++  VOID(pthread_mutex_lock(&LOCK_thread_count));
++  thd->query_id= global_query_id;
++  if (command != COM_STATISTICS && command != COM_PING)
++    next_query_id();
++  thread_running++;
++  /* TODO: set thd->lex->sql_command to SQLCOM_END here */
++  VOID(pthread_mutex_unlock(&LOCK_thread_count));
++
++  thd->server_status&=
++           ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
++  switch (command) {
++  case COM_INIT_DB:
++  {
++    LEX_STRING tmp;
++    statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB],
++			&LOCK_status);
++    thd->convert_string(&tmp, system_charset_info,
++			packet, strlen(packet), thd->charset());
++    if (!mysql_change_db(thd, &tmp, FALSE))
++    {
++      mysql_log.write(thd,command,"%s",thd->db);
++      send_ok(thd);
++    }
++    break;
++  }
++#ifdef HAVE_REPLICATION
++  case COM_REGISTER_SLAVE:
++  {
++    if (!register_slave(thd, (uchar*)packet, packet_length))
++      send_ok(thd);
++    break;
++  }
++#endif
++  case COM_TABLE_DUMP:
++  {
++    char *db, *tbl_name;
++    uint db_len= *(uchar*) packet;
++    if (db_len >= packet_length || db_len > NAME_LEN)
++    {
++      my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
++      break;
++    }
++    uint tbl_len= *(uchar*) (packet + db_len + 1);
++    if (db_len+tbl_len+2 > packet_length || tbl_len > NAME_LEN)
++    {
++      my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
++      break;
++    }
++
++    statistic_increment(thd->status_var.com_other, &LOCK_status);
++    thd->enable_slow_log= opt_log_slow_admin_statements;
++    db= thd->alloc(db_len + tbl_len + 2);
++    if (!db)
++    {
++      my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
++      break;
++    }
++    tbl_name= strmake(db, packet + 1, db_len)+1;
++    strmake(tbl_name, packet + db_len + 2, tbl_len);
++    mysql_table_dump(thd, db, tbl_name);
++    break;
++  }
++  case COM_CHANGE_USER:
++  {
++    thd->change_user();
++    thd->clear_error();                         // if errors from rollback
++
++    statistic_increment(thd->status_var.com_other, &LOCK_status);
++    char *user= (char*) packet;
++    char *passwd= strend(user)+1;
++    /*
++      Old clients send null-terminated string ('\0' for empty string) for
++      password.  New clients send the size (1 byte) + string (not null
++      terminated, so also '\0' for empty string).
++
++      Cast *passwd to an unsigned char, so that it doesn't extend the sign
++      for *passwd > 127 and become 2**32-127 after casting to uint.
++    */
++    char db_buff[NAME_LEN+1];               // buffer to store db in utf8
++    char *db= passwd;
++    uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
++      (uchar)(*passwd++) : strlen(passwd);
++    db+= passwd_len + 1;
++#ifndef EMBEDDED_LIBRARY
++    /* Small check for incoming packet */
++    if ((uint) ((uchar*) db - net->read_pos) > packet_length)
++    {
++      my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
++      break;
++    }
++#endif
++    /* Convert database name to utf8 */
++    uint dummy_errors;
++    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
++                             system_charset_info, db, strlen(db),
++                             thd->charset(), &dummy_errors)]= 0;
++    db= db_buff;
++
++    /* Save user and privileges */
++    uint save_db_length= thd->db_length;
++    char *save_db= thd->db;
++    Security_context save_security_ctx= *thd->security_ctx;
++    USER_CONN *save_user_connect= thd->user_connect;
++
++    if (!(thd->security_ctx->user= my_strdup(user, MYF(0))))
++    {
++      thd->security_ctx->user= save_security_ctx.user;
++      my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
++      break;
++    }
++
++    /* Clear variables that are allocated */
++    thd->user_connect= 0;
++    int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE);
++
++    if (res)
++    {
++      /* authentication failure, we shall restore old user */
++      if (res > 0)
++        my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
++      x_free(thd->security_ctx->user);
++      *thd->security_ctx= save_security_ctx;
++      thd->user_connect= save_user_connect;
++      thd->db= save_db;
++      thd->db_length= save_db_length;
++    }
++    else
++    {
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++      /* we've authenticated new user */
++      if (save_user_connect)
++	decrease_user_connections(save_user_connect);
++#endif /* NO_EMBEDDED_ACCESS_CHECKS */
++      x_free((gptr) save_db);
++      x_free((gptr)  save_security_ctx.user);
++    }
++    break;
++  }
++  case COM_STMT_EXECUTE:
++  {
++    mysql_stmt_execute(thd, packet, packet_length);
++    break;
++  }
++  case COM_STMT_FETCH:
++  {
++    mysql_stmt_fetch(thd, packet, packet_length);
++    break;
++  }
++  case COM_STMT_SEND_LONG_DATA:
++  {
++    mysql_stmt_get_longdata(thd, packet, packet_length);
++    break;
++  }
++  case COM_STMT_PREPARE:
++  {
++    mysql_stmt_prepare(thd, packet, packet_length);
++    break;
++  }
++  case COM_STMT_CLOSE:
++  {
++    mysql_stmt_close(thd, packet);
++    break;
++  }
++  case COM_STMT_RESET:
++  {
++    mysql_stmt_reset(thd, packet);
++    break;
++  }
++  case COM_QUERY:
++  {
++    if (alloc_query(thd, packet, packet_length))
++      break;					// fatal error is set
++    char *packet_end= thd->query + thd->query_length;
++    /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
++    const char *format= "%.*b";
++    const char* found_semicolon= NULL;
++
++    mysql_log.write(thd,command, format, thd->query_length, thd->query);
++    DBUG_PRINT("query",("%-.4096s",thd->query));
++
++    if (!(specialflag & SPECIAL_NO_PRIOR))
++      my_pthread_setprio(pthread_self(),QUERY_PRIOR);
++
++    mysql_parse(thd, thd->query, thd->query_length, & found_semicolon);
++
++    while (!thd->killed && found_semicolon && !thd->net.report_error)
++    {
++      char *next_packet= (char*) found_semicolon;
++      net->no_send_error= 0;
++      /*
++        Multiple queries exits, execute them individually
++      */
++      if (thd->lock || thd->open_tables || thd->derived_tables ||
++          thd->prelocked_mode)
++        close_thread_tables(thd);
++      ulong length= (ulong)(packet_end - next_packet);
++
++      log_slow_statement(thd);
++
++      /* Remove garbage at start of query */
++      while (my_isspace(thd->charset(), *next_packet) && length > 0)
++      {
++        next_packet++;
++        length--;
++      }
++      VOID(pthread_mutex_lock(&LOCK_thread_count));
++      thd->query_length= length;
++      thd->query= next_packet;
++      thd->query_id= next_query_id();
++      thd->set_time(); /* Reset the query start time. */
++      /* TODO: set thd->lex->sql_command to SQLCOM_END here */
++      VOID(pthread_mutex_unlock(&LOCK_thread_count));
++      mysql_parse(thd, next_packet, length, & found_semicolon);
++    }
++
++    if (!(specialflag & SPECIAL_NO_PRIOR))
++      my_pthread_setprio(pthread_self(),WAIT_PRIOR);
++    DBUG_PRINT("info",("query ready"));
++    break;
++  }
++  case COM_FIELD_LIST:				// This isn't actually needed
++#ifdef DONT_ALLOW_SHOW_COMMANDS
++    my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
++               MYF(0));	/* purecov: inspected */
++    break;
++#else
++  {
++    char *fields, *pend;
++    /* Locked closure of all tables */
++    TABLE_LIST table_list;
++    LEX_STRING conv_name;
++
++    /* used as fields initializator */
++    lex_start(thd);
++
++    statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS],
++			&LOCK_status);
++    bzero((char*) &table_list,sizeof(table_list));
++    if (thd->copy_db_to(&table_list.db, &table_list.db_length))
++      break;
++    pend= strend(packet);
++    thd->convert_string(&conv_name, system_charset_info,
++			packet, (uint) (pend-packet), thd->charset());
++    table_list.alias= table_list.table_name= conv_name.str;
++    packet= pend+1;
++
++    if (!my_strcasecmp(system_charset_info, table_list.db,
++                       INFORMATION_SCHEMA_NAME.str))
++    {
++      ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, table_list.alias);
++      if (schema_table)
++        table_list.schema_table= schema_table;
++    }
++
++    thd->query_length= strlen(packet);       // for simplicity: don't optimize
++    if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1)))
++      break;
++    mysql_log.write(thd,command,"%s %s",table_list.table_name, fields);
++    if (lower_case_table_names)
++      my_casedn_str(files_charset_info, table_list.table_name);
++    remove_escape(table_list.table_name);	// This can't have wildcards
++
++    if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege,
++		     0, 0, test(table_list.schema_table)))
++      break;
++    if (grant_option &&
++	check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0))
++      break;
++    /* init structures for VIEW processing */
++    table_list.select_lex= &(thd->lex->select_lex);
++
++    lex_start(thd);
++    mysql_reset_thd_for_next_command(thd);
++
++    thd->lex->
++      select_lex.table_list.link_in_list((byte*) &table_list,
++                                         (byte**) &table_list.next_local);
++    thd->lex->add_to_query_tables(&table_list);
++
++    /* switch on VIEW optimisation: do not fill temporary tables */
++    thd->lex->sql_command= SQLCOM_SHOW_FIELDS;
++    mysqld_list_fields(thd,&table_list,fields);
++    thd->lex->unit.cleanup();
++    thd->cleanup_after_query();
++    break;
++  }
++#endif
++  case COM_QUIT:
++    /* We don't calculate statistics for this command */
++    mysql_log.write(thd,command,NullS);
++    net->error=0;				// Don't give 'abort' message
++    error=TRUE;					// End server
++    break;
++
++  case COM_CREATE_DB:				// QQ: To be removed
++    {
++      char *db=thd->strdup(packet), *alias;
++      HA_CREATE_INFO create_info;
++
++      statistic_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB],
++			  &LOCK_status);
++      // null test to handle EOM
++      if (!db || !(alias= thd->strdup(db)) || check_db_name(db))
++      {
++	my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL");
++	break;
++      }
++      if (check_access(thd,CREATE_ACL,db,0,1,0,is_schema_db(db)))
++	break;
++      mysql_log.write(thd,command,packet);
++      bzero(&create_info, sizeof(create_info));
++      mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db),
++                      &create_info, 0);
++      break;
++    }
++  case COM_DROP_DB:				// QQ: To be removed
++    {
++      statistic_increment(thd->status_var.com_stat[SQLCOM_DROP_DB],
++			  &LOCK_status);
++      char *db=thd->strdup(packet);
++      /*  null test to handle EOM */
++      if (!db || check_db_name(db))
++      {
++	my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL");
++	break;
++      }
++      if (check_access(thd,DROP_ACL,db,0,1,0,is_schema_db(db)))
++	break;
++      if (thd->locked_tables || thd->active_transaction())
++      {
++	my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
++                   ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
++	break;
++      }
++      mysql_log.write(thd,command,db);
++      mysql_rm_db(thd, db, 0, 0);
++      break;
++    }
++#ifndef EMBEDDED_LIBRARY
++  case COM_BINLOG_DUMP:
++    {
++      ulong pos;
++      ushort flags;
++      uint32 slave_server_id;
++
++      statistic_increment(thd->status_var.com_other,&LOCK_status);
++      thd->enable_slow_log= opt_log_slow_admin_statements;
++      if (check_global_access(thd, REPL_SLAVE_ACL))
++	break;
++
++      /* TODO: The following has to be changed to an 8 byte integer */
++      pos = uint4korr(packet);
++      flags = uint2korr(packet + 4);
++      thd->server_id=0; /* avoid suicide */
++      if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0
++	kill_zombie_dump_threads(slave_server_id);
++      thd->server_id = slave_server_id;
++
++      mysql_log.write(thd, command, "Log: '%s'  Pos: %ld", packet+10,
++                      (long) pos);
++      mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
++      unregister_slave(thd,1,1);
++      /*  fake COM_QUIT -- if we get here, the thread needs to terminate */
++      error = TRUE;
++      net->error = 0;
++      break;
++    }
++#endif
++  case COM_REFRESH:
++  {
++    bool not_used;
++    statistic_increment(thd->status_var.com_stat[SQLCOM_FLUSH],
++                        &LOCK_status);
++    ulong options= (ulong) (uchar) packet[0];
++    if (check_global_access(thd,RELOAD_ACL))
++      break;
++    mysql_log.write(thd,command,NullS);
++    if (!reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, &not_used))
++      send_ok(thd);
++    break;
++  }
++#ifndef EMBEDDED_LIBRARY
++  case COM_SHUTDOWN:
++  {
++    statistic_increment(thd->status_var.com_other, &LOCK_status);
++    if (check_global_access(thd,SHUTDOWN_ACL))
++      break; /* purecov: inspected */
++    /*
++      If the client is < 4.1.3, it is going to send us no argument; then
++      packet_length is 1, packet[0] is the end 0 of the packet. Note that
++      SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in
++      packet[0].
++    */
++    enum mysql_enum_shutdown_level level=
++      (enum mysql_enum_shutdown_level) (uchar) packet[0];
++    DBUG_PRINT("quit",("Got shutdown command for level %u", level));
++    if (level == SHUTDOWN_DEFAULT)
++      level= SHUTDOWN_WAIT_ALL_BUFFERS; // soon default will be configurable
++    else if (level != SHUTDOWN_WAIT_ALL_BUFFERS)
++    {
++      my_error(ER_NOT_SUPPORTED_YET, MYF(0), "this shutdown level");
++      break;
++    }
++    DBUG_PRINT("quit",("Got shutdown command for level %u", level));
++    mysql_log.write(thd,command,NullS);
++    send_eof(thd);
++#ifdef __WIN__
++    sleep(1);					// must wait after eof()
++#endif
++#ifndef OS2
++    send_eof(thd);				// This is for 'quit request'
++#endif
++    close_connection(thd, 0, 1);
++    close_thread_tables(thd);			// Free before kill
++    kill_mysql();
++    error=TRUE;
++    break;
++  }
++#endif
++  case COM_STATISTICS:
++  {
++    mysql_log.write(thd,command,NullS);
++    statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS],
++			&LOCK_status);
++#ifndef EMBEDDED_LIBRARY
++    char buff[200];
++#else
++    char *buff= thd->net.last_error;
++#endif
++
++    STATUS_VAR current_global_status_var;
++    calc_sum_of_all_status(&current_global_status_var);
++
++    ulong uptime = (ulong) (thd->start_time - server_start_time);
++    sprintf((char*) buff,
++	    "Uptime: %lu  Threads: %d  Questions: %lu  Slow queries: %lu  Opens: %lu  Flush tables: %lu  Open tables: %u  Queries per second avg: %.3f",
++	    uptime,
++	    (int) thread_count, (ulong) thd->query_id,
++	    current_global_status_var.long_query_count,
++	    current_global_status_var.opened_tables, refresh_version, cached_tables(),
++	    (uptime ? (ulonglong2double(thd->query_id) / (double) uptime) :
++	     (double) 0));
++#ifdef SAFEMALLOC
++    if (sf_malloc_cur_memory)				// Using SAFEMALLOC
++      sprintf(strend(buff), "  Memory in use: %ldK  Max memory used: %ldK",
++	      (sf_malloc_cur_memory+1023L)/1024L,
++	      (sf_malloc_max_memory+1023L)/1024L);
++#endif
++#ifndef EMBEDDED_LIBRARY
++    VOID(my_net_write(net, buff,(uint) strlen(buff)));
++    VOID(net_flush(net));
++#endif
++    break;
++  }
++  case COM_PING:
++    statistic_increment(thd->status_var.com_other, &LOCK_status);
++    send_ok(thd);				// Tell client we are alive
++    break;
++  case COM_PROCESS_INFO:
++    statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST],
++			&LOCK_status);
++    if (!thd->security_ctx->priv_user[0] &&
++        check_global_access(thd, PROCESS_ACL))
++      break;
++    mysql_log.write(thd,command,NullS);
++    mysqld_list_processes(thd,
++			  thd->security_ctx->master_access & PROCESS_ACL ? 
++			  NullS : thd->security_ctx->priv_user, 0);
++    break;
++  case COM_PROCESS_KILL:
++  {
++    statistic_increment(thd->status_var.com_stat[SQLCOM_KILL], &LOCK_status);
++    ulong id=(ulong) uint4korr(packet);
++    kill_one_thread(thd,id,false);
++    break;
++  }
++  case COM_SET_OPTION:
++  {
++    statistic_increment(thd->status_var.com_stat[SQLCOM_SET_OPTION],
++			&LOCK_status);
++    uint opt_command= uint2korr(packet);
++
++    switch (opt_command) {
++    case (int) MYSQL_OPTION_MULTI_STATEMENTS_ON:
++      thd->client_capabilities|= CLIENT_MULTI_STATEMENTS;
++      send_eof(thd);
++      break;
++    case (int) MYSQL_OPTION_MULTI_STATEMENTS_OFF:
++      thd->client_capabilities&= ~CLIENT_MULTI_STATEMENTS;
++      send_eof(thd);
++      break;
++    default:
++      my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
++      break;
++    }
++    break;
++  }
++  case COM_DEBUG:
++    statistic_increment(thd->status_var.com_other, &LOCK_status);
++    if (check_global_access(thd, SUPER_ACL))
++      break;					/* purecov: inspected */
++    mysql_print_status();
++    mysql_log.write(thd,command,NullS);
++    send_eof(thd);
++    break;
++  case COM_SLEEP:
++  case COM_CONNECT:				// Impossible here
++  case COM_TIME:				// Impossible from client
++  case COM_DELAYED_INSERT:
++  case COM_END:
++  default:
++    my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
++    break;
++  }
++  if (thd->lock || thd->open_tables || thd->derived_tables ||
++      thd->prelocked_mode)
++  {
++    thd_proc_info(thd, "closing tables");
++    close_thread_tables(thd);			/* Free tables */
++  }
++  /*
++    assume handlers auto-commit (if some doesn't - transaction handling
++    in MySQL should be redesigned to support it; it's a big change,
++    and it's not worth it - better to commit explicitly only writing
++    transactions, read-only ones should better take care of themselves.
++    saves some work in 2pc too)
++    see also sql_base.cc - close_thread_tables()
++  */
++  bzero(&thd->transaction.stmt, sizeof(thd->transaction.stmt));
++  if (!thd->active_transaction())
++    thd->transaction.xid_state.xid.null();
++
++  /* report error issued during command execution */
++  if (thd->killed_errno() && !thd->net.report_error)
++    thd->send_kill_message();
++  if (thd->net.report_error)
++    net_send_error(thd);
++
++  log_slow_statement(thd);
++
++  thd_proc_info(thd, "cleaning up");
++  VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list
++  thd_proc_info(thd, 0);
++  thd->command=COM_SLEEP;
++  thd->query=0;
++  thd->query_length=0;
++  thread_running--;
++  VOID(pthread_mutex_unlock(&LOCK_thread_count));
++  thd->packet.shrink(thd->variables.net_buffer_length);	// Reclaim some memory
++  free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
++  DBUG_RETURN(error);
++}
++
++
++void log_slow_statement(THD *thd)
++{
++  time_t start_of_query;
++
++  /*
++    The following should never be true with our current code base,
++    but better to keep this here so we don't accidently try to log a
++    statement in a trigger or stored function
++  */
++  if (unlikely(thd->in_sub_stmt))
++    return;                                     // Don't set time for sub stmt
++
++  start_of_query= thd->start_time;
++  thd->end_time();				// Set start time
++
++  /*
++    Do not log administrative statements unless the appropriate option is
++    set; do not log into slow log if reading from backup.
++  */
++  if (thd->enable_slow_log && !thd->user_time)
++  {
++    thd_proc_info(thd, "logging slow query");
++
++    if ((ulong) (thd->start_time - thd->time_after_lock) >
++	thd->variables.long_query_time ||
++        (thd->server_status &
++	  (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
++        opt_log_queries_not_using_indexes &&
++        /* == SQLCOM_END unless this is a SHOW command */
++        thd->lex->orig_sql_command == SQLCOM_END)
++    {
++      thd_proc_info(thd, "logging slow query");
++      thd->status_var.long_query_count++;
++      mysql_slow_log.write(thd, thd->query, thd->query_length, start_of_query);
++    }
++  }
++}
++
++
++/*
++  Create a TABLE_LIST object for an INFORMATION_SCHEMA table.
++
++  SYNOPSIS
++    prepare_schema_table()
++      thd              thread handle
++      lex              current lex
++      table_ident      table alias if it's used
++      schema_table_idx the type of the INFORMATION_SCHEMA table to be
++                       created
++
++  DESCRIPTION
++    This function is used in the parser to convert a SHOW or DESCRIBE
++    table_name command to a SELECT from INFORMATION_SCHEMA.
++    It prepares a SELECT_LEX and a TABLE_LIST object to represent the
++    given command as a SELECT parse tree.
++
++  NOTES
++    Due to the way this function works with memory and LEX it cannot
++    be used outside the parser (parse tree transformations outside
++    the parser break PS and SP).
++
++  RETURN VALUE
++    0                 success
++    1                 out of memory or SHOW commands are not allowed
++                      in this version of the server.
++*/
++
++int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
++                         enum enum_schema_tables schema_table_idx)
++{
++  DBUG_ENTER("prepare_schema_table");
++  SELECT_LEX *schema_select_lex= NULL;
++
++  switch (schema_table_idx) {
++  case SCH_SCHEMATA:
++#if defined(DONT_ALLOW_SHOW_COMMANDS)
++    my_message(ER_NOT_ALLOWED_COMMAND,
++               ER(ER_NOT_ALLOWED_COMMAND), MYF(0));   /* purecov: inspected */
++    DBUG_RETURN(1);
++#else
++    break;
++#endif
++
++  case SCH_TABLE_NAMES:
++  case SCH_TABLES:
++  case SCH_VIEWS:
++  case SCH_TRIGGERS:
++#ifdef DONT_ALLOW_SHOW_COMMANDS
++    my_message(ER_NOT_ALLOWED_COMMAND,
++               ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
++    DBUG_RETURN(1);
++#else
++    if (lex->select_lex.db == NULL &&
++        lex->copy_db_to(&lex->select_lex.db, NULL))
++    {
++      DBUG_RETURN(1);
++    }
++
++    schema_select_lex= new SELECT_LEX();
++    schema_select_lex->db= lex->select_lex.db;
++    schema_select_lex->table_list.first= NULL;
++    remove_escape(schema_select_lex->db); // Fix escaped '_'
++
++    if (check_db_name(schema_select_lex->db))
++    {
++      my_error(ER_WRONG_DB_NAME, MYF(0), schema_select_lex->db);
++      DBUG_RETURN(1);
++    }
++
++
++    break;
++#endif
++  case SCH_COLUMNS:
++  case SCH_STATISTICS:
++#ifdef DONT_ALLOW_SHOW_COMMANDS
++    my_message(ER_NOT_ALLOWED_COMMAND,
++               ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
++    DBUG_RETURN(1);
++#else
++    {
++      DBUG_ASSERT(table_ident);
++
++      TABLE_LIST **query_tables_last= lex->query_tables_last;
++      schema_select_lex= new SELECT_LEX();
++      /* 'parent_lex' is used in init_query() so it must be before it. */
++      schema_select_lex->parent_lex= lex;
++      schema_select_lex->init_query();
++      if (!schema_select_lex->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
++                                  (List<String> *) 0, (List<String> *) 0))
++        DBUG_RETURN(1);
++      lex->query_tables_last= query_tables_last;
++
++      TABLE_LIST *dst_table= (TABLE_LIST*) schema_select_lex->table_list.first;
++      remove_escape(dst_table->db);			// Fix escaped '_'
++      remove_escape(dst_table->table_name);
++
++      break;
++    }
++#endif
++  case SCH_PROFILES:
++    /* 
++      Mark this current profiling record to be discarded.  We don't
++      wish to have SHOW commands show up in profiling.
++    */
++#ifdef ENABLED_PROFILING
++    thd->profiling.discard();
++#endif
++    break;
++  case SCH_OPEN_TABLES:
++  case SCH_VARIABLES:
++  case SCH_STATUS:
++  case SCH_PROCEDURES:
++  case SCH_CHARSETS:
++  case SCH_COLLATIONS:
++  case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
++  case SCH_USER_PRIVILEGES:
++  case SCH_SCHEMA_PRIVILEGES:
++  case SCH_TABLE_PRIVILEGES:
++  case SCH_COLUMN_PRIVILEGES:
++  case SCH_TABLE_CONSTRAINTS:
++  case SCH_KEY_COLUMN_USAGE:
++  default:
++    break;
++  }
++  
++  SELECT_LEX *select_lex= lex->current_select;
++  if (make_schema_select(thd, select_lex, schema_table_idx))
++  {
++    DBUG_RETURN(1);
++  }
++  TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
++  table_list->schema_select_lex= schema_select_lex;
++  table_list->schema_table_reformed= 1;
++  statistic_increment(thd->status_var.com_stat[lex->orig_sql_command],
++                      &LOCK_status);
++  DBUG_RETURN(0);
++}
++
++
++/*
++  Read query from packet and store in thd->query
++  Used in COM_QUERY and COM_STMT_PREPARE
++
++  DESCRIPTION
++    Sets the following THD variables:
++      query
++      query_length
++
++  RETURN VALUES
++    FALSE ok
++    TRUE  error;  In this case thd->fatal_error is set
++*/
++
++bool alloc_query(THD *thd, const char *packet, uint packet_length)
++{
++  packet_length--;				// Remove end null
++  /* Remove garbage at start and end of query */
++  while (my_isspace(thd->charset(),packet[0]) && packet_length > 0)
++  {
++    packet++;
++    packet_length--;
++  }
++  const char *pos= packet + packet_length;     // Point at end null
++  while (packet_length > 0 &&
++	 (pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1])))
++  {
++    pos--;
++    packet_length--;
++  }
++  /* We must allocate some extra memory for query cache */
++  thd->query_length= 0;                        // Extra safety: Avoid races
++  if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet),
++					      packet_length,
++					      thd->db_length+ 1 +
++					      QUERY_CACHE_FLAGS_SIZE)))
++    return TRUE;
++  thd->query[packet_length]=0;
++  thd->query_length= packet_length;
++
++  /* Reclaim some memory */
++  thd->packet.shrink(thd->variables.net_buffer_length);
++  thd->convert_buffer.shrink(thd->variables.net_buffer_length);
++
++  return FALSE;
++}
++
++static void reset_one_shot_variables(THD *thd) 
++{
++  thd->variables.character_set_client=
++    global_system_variables.character_set_client;
++  thd->variables.collation_connection=
++    global_system_variables.collation_connection;
++  thd->variables.collation_database=
++    global_system_variables.collation_database;
++  thd->variables.collation_server=
++    global_system_variables.collation_server;
++  thd->update_charset();
++  thd->variables.time_zone=
++    global_system_variables.time_zone;
++  thd->variables.lc_time_names= &my_locale_en_US;
++  thd->one_shot_set= 0;
++}
++
++
++/*
++  Execute command saved in thd and lex->sql_command
++
++  SYNOPSIS
++    mysql_execute_command()
++      thd                       Thread handle
++
++  IMPLEMENTATION
++
++    Before every operation that can request a write lock for a table
++    wait if a global read lock exists. However do not wait if this
++    thread has locked tables already. No new locks can be requested
++    until the other locks are released. The thread that requests the
++    global read lock waits for write locked tables to become unlocked.
++
++    Note that wait_if_global_read_lock() sets a protection against a new
++    global read lock when it succeeds. This needs to be released by
++    start_waiting_global_read_lock() after the operation.
++
++  RETURN
++    FALSE       OK
++    TRUE        Error
++*/
++
++bool
++mysql_execute_command(THD *thd)
++{
++  bool res= FALSE;
++  bool need_start_waiting= FALSE; // have protection against global read lock
++  int  up_result= 0;
++  LEX  *lex= thd->lex;
++  /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
++  SELECT_LEX *select_lex= &lex->select_lex;
++  /* first table of first SELECT_LEX */
++  TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first;
++  /* list of all tables in query */
++  TABLE_LIST *all_tables;
++  /* most outer SELECT_LEX_UNIT of query */
++  SELECT_LEX_UNIT *unit= &lex->unit;
++  /* Saved variable value */
++  DBUG_ENTER("mysql_execute_command");
++  thd->net.no_send_error= 0;
++
++  /*
++    Remember first generated insert id value of the previous
++    statement.  We remember it here at the beginning of the statement,
++    and also in Item_func_last_insert_id::fix_fields() and
++    sys_var_last_insert_id::value_ptr().  Last two places are required
++    because LAST_INSERT_ID() and @@LAST_INSERT_ID may also be used in
++    expression that is not executed with mysql_execute_command().
++
++    And we remember it here because some statements read
++    @@LAST_INSERT_ID indirectly, like "SELECT * FROM t1 WHERE id IS
++    NULL", that may replace "id IS NULL" with "id = <LAST_INSERT_ID>".
++  */
++  thd->current_insert_id= thd->last_insert_id;
++
++  /*
++    In many cases first table of main SELECT_LEX have special meaning =>
++    check that it is first table in global list and relink it first in 
++    queries_tables list if it is necessary (we need such relinking only
++    for queries with subqueries in select list, in this case tables of
++    subqueries will go to global list first)
++
++    all_tables will differ from first_table only if most upper SELECT_LEX
++    do not contain tables.
++
++    Because of above in place where should be at least one table in most
++    outer SELECT_LEX we have following check:
++    DBUG_ASSERT(first_table == all_tables);
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++  */
++  lex->first_lists_tables_same();
++  /* should be assigned after making first tables same */
++  all_tables= lex->query_tables;
++  /* set context for commands which do not use setup_tables */
++  select_lex->
++    context.resolve_in_table_list_only((TABLE_LIST*)select_lex->
++                                       table_list.first);
++
++  /*
++    Reset warning count for each query that uses tables
++    A better approach would be to reset this for any commands
++    that is not a SHOW command or a select that only access local
++    variables, but for now this is probably good enough.
++    Don't reset warnings when executing a stored routine.
++  */
++  if ((all_tables || &lex->select_lex != lex->all_selects_list ||
++       lex->sroutines.records) && !thd->spcont ||
++      lex->time_zone_tables_used)
++    mysql_reset_errors(thd, 0);
++
++#ifdef HAVE_REPLICATION
++  if (unlikely(thd->slave_thread))
++  {
++    if (lex->sql_command == SQLCOM_DROP_TRIGGER)
++    {
++      /*
++        When dropping a trigger, we need to load its table name
++        before checking slave filter rules.
++      */
++      add_table_for_trigger(thd, thd->lex->spname, 1, &all_tables);
++      
++      if (!all_tables)
++      {
++        /*
++          If table name cannot be loaded,
++          it means the trigger does not exists possibly because
++          CREATE TRIGGER was previously skipped for this trigger
++          according to slave filtering rules.
++          Returning success without producing any errors in this case.
++        */
++        DBUG_RETURN(0);
++      }
++      
++      // force searching in slave.cc:tables_ok() 
++      all_tables->updating= 1;
++    }
++    
++    /*
++      Check if statment should be skipped because of slave filtering
++      rules
++
++      Exceptions are:
++      - UPDATE MULTI: For this statement, we want to check the filtering
++        rules later in the code
++      - SET: we always execute it (Not that many SET commands exists in
++        the binary log anyway -- only 4.1 masters write SET statements,
++	in 5.0 there are no SET statements in the binary log)
++      - DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we
++        have stale files on slave caused by exclusion of one tmp table).
++    */
++    if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) &&
++	!(lex->sql_command == SQLCOM_SET_OPTION) &&
++	!(lex->sql_command == SQLCOM_DROP_TABLE &&
++          lex->drop_temporary && lex->drop_if_exists) &&
++        all_tables_not_ok(thd, all_tables))
++    {
++      /* we warn the slave SQL thread */
++      my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
++      if (thd->one_shot_set)
++      {
++        /*
++          It's ok to check thd->one_shot_set here:
++
++          The charsets in a MySQL 5.0 slave can change by both a binlogged
++          SET ONE_SHOT statement and the event-internal charset setting, 
++          and these two ways to change charsets do not seems to work
++          together.
++
++          At least there seems to be problems in the rli cache for
++          charsets if we are using ONE_SHOT.  Note that this is normally no
++          problem because either the >= 5.0 slave reads a 4.1 binlog (with
++          ONE_SHOT) *or* or 5.0 binlog (without ONE_SHOT) but never both."
++        */
++        reset_one_shot_variables(thd);
++      }
++      DBUG_RETURN(0);
++    }
++  }
++  else
++  {
++#endif /* HAVE_REPLICATION */
++    /*
++      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->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_DROP_TABLE) && lex->drop_temporary) &&
++        ((lex->sql_command != SQLCOM_UPDATE_MULTI) &&
++          some_non_temp_table_to_be_updated(thd, all_tables)))
++    {
++      my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
++      DBUG_RETURN(-1);
++    }
++#ifdef HAVE_REPLICATION
++  } /* endif unlikely slave */
++#endif
++  if(lex->orig_sql_command == SQLCOM_END)
++    statistic_increment(thd->status_var.com_stat[lex->sql_command],
++                        &LOCK_status);
++
++  DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table == FALSE);
++  
++  switch (lex->sql_command) {
++  case SQLCOM_SELECT:
++  {
++    /* assign global limit variable if limit is not given */
++    {
++      SELECT_LEX *param= lex->unit.global_parameters;
++      if (!param->explicit_limit)
++	param->select_limit=
++          new Item_int((ulonglong)thd->variables.select_limit);
++    }
++
++    select_result *sel_result=lex->result;
++    if (all_tables)
++    {
++      if (lex->orig_sql_command != SQLCOM_SHOW_STATUS_PROC &&
++          lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC)
++        res= check_table_access(thd,
++                                lex->exchange ? SELECT_ACL | FILE_ACL :
++                                SELECT_ACL,
++                                all_tables, 0);
++    }
++    else
++      res= check_access(thd,
++			lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
++			any_db, 0, 0, 0, 0);
++    if (res)
++      goto error;
++
++    if (!(res= open_and_lock_tables(thd, all_tables)))
++    {
++      if (lex->describe)
++      {
++        /*
++          We always use select_send for EXPLAIN, even if it's an EXPLAIN
++          for SELECT ... INTO OUTFILE: a user application should be able
++          to prepend EXPLAIN to any query and receive output for it,
++          even if the query itself redirects the output.
++        */
++	if (!(sel_result= new select_send()))
++	  goto error;
++	else
++	  thd->send_explain_fields(sel_result);
++	res= mysql_explain_union(thd, &thd->lex->unit, sel_result);
++	if (lex->describe & DESCRIBE_EXTENDED)
++	{
++	  char buff[1024];
++	  String str(buff,(uint32) sizeof(buff), system_charset_info);
++	  str.length(0);
++	  thd->lex->unit.print(&str);
++	  str.append('\0');
++	  push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
++		       ER_YES, str.ptr());
++	}
++	sel_result->send_eof();
++        delete sel_result;
++      }
++      else
++      {
++	if (!sel_result && !(sel_result= new select_send()))
++          goto error;
++	query_cache_store_query(thd, all_tables);
++	res= handle_select(thd, lex, sel_result, 0);
++        if (sel_result != lex->result)
++          delete sel_result;
++      }
++    }
++    break;
++  }
++  case SQLCOM_PREPARE:
++  {
++    mysql_sql_stmt_prepare(thd);
++    break;
++  }
++  case SQLCOM_EXECUTE:
++  {
++    mysql_sql_stmt_execute(thd);
++    break;
++  }
++  case SQLCOM_DEALLOCATE_PREPARE:
++  {
++    mysql_sql_stmt_close(thd);
++    break;
++  }
++  case SQLCOM_DO:
++    if (check_table_access(thd, SELECT_ACL, all_tables, 0) ||
++        open_and_lock_tables(thd, all_tables))
++      goto error;
++
++    res= mysql_do(thd, *lex->insert_list);
++    break;
++
++  case SQLCOM_EMPTY_QUERY:
++    send_ok(thd);
++    break;
++
++  case SQLCOM_HELP:
++    res= mysqld_help(thd,lex->help_arg);
++    break;
++
++#ifndef EMBEDDED_LIBRARY
++  case SQLCOM_PURGE:
++  {
++    if (check_global_access(thd, SUPER_ACL))
++      goto error;
++    /* PURGE MASTER LOGS TO 'file' */
++    res = purge_master_logs(thd, lex->to_log);
++    break;
++  }
++  case SQLCOM_PURGE_BEFORE:
++  {
++    Item *it;
++
++    if (check_global_access(thd, SUPER_ACL))
++      goto error;
++    /* PURGE MASTER LOGS BEFORE 'data' */
++    it= (Item *)lex->value_list.head();
++    if ((!it->fixed && it->fix_fields(lex->thd, &it)) ||
++        it->check_cols(1))
++    {
++      my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
++      goto error;
++    }
++    it= new Item_func_unix_timestamp(it);
++    /*
++      it is OK only emulate fix_fieds, because we need only
++      value of constant
++    */
++    it->quick_fix_field();
++    res = purge_master_logs_before_date(thd, (ulong)it->val_int());
++    break;
++  }
++#endif
++  case SQLCOM_SHOW_WARNS:
++  {
++    res= mysqld_show_warnings(thd, (ulong)
++			      ((1L << (uint) MYSQL_ERROR::WARN_LEVEL_NOTE) |
++			       (1L << (uint) MYSQL_ERROR::WARN_LEVEL_WARN) |
++			       (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR)
++			       ));
++    break;
++  }
++  case SQLCOM_SHOW_ERRORS:
++  {
++    res= mysqld_show_warnings(thd, (ulong)
++			      (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR));
++    break;
++  }
++  case SQLCOM_SHOW_PROFILES:
++  {
++#ifdef ENABLED_PROFILING
++    thd->profiling.store();
++    thd->profiling.discard();
++    res= thd->profiling.show_profiles();
++    if (res)
++      goto error;
++#else
++    my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILES", "enable-profiling");
++    goto error;
++#endif
++    break;
++  }
++  case SQLCOM_SHOW_NEW_MASTER:
++  {
++    if (check_global_access(thd, REPL_SLAVE_ACL))
++      goto error;
++    /* This query don't work now. See comment in repl_failsafe.cc */
++#ifndef WORKING_NEW_MASTER
++    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "SHOW NEW MASTER");
++    goto error;
++#else
++    res = show_new_master(thd);
++    break;
++#endif
++  }
++
++#ifdef HAVE_REPLICATION
++  case SQLCOM_SHOW_SLAVE_HOSTS:
++  {
++    if (check_global_access(thd, REPL_SLAVE_ACL))
++      goto error;
++    res = show_slave_hosts(thd);
++    break;
++  }
++  case SQLCOM_SHOW_BINLOG_EVENTS:
++  {
++    if (check_global_access(thd, REPL_SLAVE_ACL))
++      goto error;
++    res = mysql_show_binlog_events(thd);
++    break;
++  }
++#endif
++
++  case SQLCOM_BACKUP_TABLE:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables) ||
++	check_table_access(thd, SELECT_ACL, all_tables, 0) ||
++	check_global_access(thd, FILE_ACL))
++      goto error; /* purecov: inspected */
++    thd->enable_slow_log= opt_log_slow_admin_statements;
++    res = mysql_backup_table(thd, first_table);
++    select_lex->table_list.first= (byte*) first_table;
++    lex->query_tables=all_tables;
++    break;
++  }
++  case SQLCOM_RESTORE_TABLE:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables) ||
++	check_table_access(thd, INSERT_ACL, all_tables, 0) ||
++	check_global_access(thd, FILE_ACL))
++      goto error; /* purecov: inspected */
++    thd->enable_slow_log= opt_log_slow_admin_statements;
++    res = mysql_restore_table(thd, first_table);
++    select_lex->table_list.first= (byte*) first_table;
++    lex->query_tables=all_tables;
++    break;
++  }
++  case SQLCOM_ASSIGN_TO_KEYCACHE:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables) ||
++        check_access(thd, INDEX_ACL, first_table->db,
++                     &first_table->grant.privilege, 0, 0,
++                     test(first_table->schema_table)))
++      goto error;
++    res= mysql_assign_to_keycache(thd, first_table, &lex->ident);
++    break;
++  }
++  case SQLCOM_PRELOAD_KEYS:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables) ||
++	check_access(thd, INDEX_ACL, first_table->db,
++                     &first_table->grant.privilege, 0, 0,
++                     test(first_table->schema_table)))
++      goto error;
++    res = mysql_preload_keys(thd, first_table);
++    break;
++  }
++#ifdef HAVE_REPLICATION
++  case SQLCOM_CHANGE_MASTER:
++  {
++    if (check_global_access(thd, SUPER_ACL))
++      goto error;
++    pthread_mutex_lock(&LOCK_active_mi);
++    res = change_master(thd,active_mi);
++    pthread_mutex_unlock(&LOCK_active_mi);
++    break;
++  }
++  case SQLCOM_SHOW_SLAVE_STAT:
++  {
++    /* Accept one of two privileges */
++    if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
++      goto error;
++    pthread_mutex_lock(&LOCK_active_mi);
++    res = show_master_info(thd,active_mi);
++    pthread_mutex_unlock(&LOCK_active_mi);
++    break;
++  }
++  case SQLCOM_SHOW_MASTER_STAT:
++  {
++    /* Accept one of two privileges */
++    if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
++      goto error;
++    res = show_binlog_info(thd);
++    break;
++  }
++
++  case SQLCOM_LOAD_MASTER_DATA: // sync with master
++    if (check_global_access(thd, SUPER_ACL))
++      goto error;
++    if (end_active_trans(thd))
++      goto error;
++    else
++      res = load_master_data(thd);
++    break;
++#endif /* HAVE_REPLICATION */
++#ifdef HAVE_NDBCLUSTER_DB
++  case SQLCOM_SHOW_NDBCLUSTER_STATUS:
++    {
++      res = ndbcluster_show_status(thd);
++      break;
++    }
++#endif
++#ifdef HAVE_INNOBASE_DB
++  case SQLCOM_SHOW_INNODB_STATUS:
++    {
++      if (check_global_access(thd, SUPER_ACL))
++	goto error;
++      res = innodb_show_status(thd);
++      break;
++    }
++  case SQLCOM_SHOW_MUTEX_STATUS:
++    {
++      if (check_global_access(thd, SUPER_ACL))
++        goto error;
++      res = innodb_mutex_show_status(thd);
++      break;
++    }
++#endif
++#ifdef HAVE_REPLICATION
++  case SQLCOM_LOAD_MASTER_TABLE:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    DBUG_ASSERT(first_table->db); /* Must be set in the parser */
++
++    if (check_access(thd, CREATE_ACL, first_table->db,
++		     &first_table->grant.privilege, 0, 0,
++                     test(first_table->schema_table)))
++      goto error;				/* purecov: inspected */
++    if (grant_option)
++    {
++      /* Check that the first table has CREATE privilege */
++      if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0))
++	goto error;
++    }
++    if (strlen(first_table->table_name) > NAME_LEN)
++    {
++      my_error(ER_WRONG_TABLE_NAME, MYF(0), first_table->table_name);
++      break;
++    }
++    pthread_mutex_lock(&LOCK_active_mi);
++    /*
++      fetch_master_table will send the error to the client on failure.
++      Give error if the table already exists.
++    */
++    if (!fetch_master_table(thd, first_table->db, first_table->table_name,
++			    active_mi, 0, 0))
++    {
++      send_ok(thd);
++    }
++    pthread_mutex_unlock(&LOCK_active_mi);
++    break;
++  }
++#endif /* HAVE_REPLICATION */
++
++  case SQLCOM_CREATE_TABLE:
++  {
++    /* If CREATE TABLE of non-temporary table, do implicit commit */
++    if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
++    {
++      if (end_active_trans(thd))
++      {
++	res= -1;
++	break;
++      }
++    }
++    else 
++    {
++      /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
++      thd->transaction.all.modified_non_trans_table= TRUE;
++    }
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    bool link_to_local;
++    // Skip first table, which is the table we are creating
++    TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local);
++    TABLE_LIST *select_tables= lex->query_tables;
++    /*
++      Code below (especially in mysql_create_table() and select_create
++      methods) may modify HA_CREATE_INFO structure in LEX, so we have to
++      use a copy of this structure to make execution prepared statement-
++      safe. A shallow copy is enough as this code won't modify any memory
++      referenced from this structure.
++    */
++    HA_CREATE_INFO create_info(lex->create_info);
++    Alter_info alter_info(lex->alter_info, thd->mem_root);
++
++    if (thd->is_fatal_error)
++    {
++      /* out of memory when creating a copy of alter_info */
++      res= 1;
++      goto end_with_restore_list;
++    }
++
++    if ((res= create_table_precheck(thd, select_tables, create_table)))
++      goto end_with_restore_list;
++
++    create_info.alias= create_table->alias;
++
++#ifndef HAVE_READLINK
++    if (create_info.data_file_name)
++      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
++                   "DATA DIRECTORY option ignored");
++    if (create_info.index_file_name)
++      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
++                   "INDEX DIRECTORY option ignored");
++    create_info.data_file_name= create_info.index_file_name= NULL;
++#else
++    /* Fix names if symlinked tables */
++    if (append_file_to_dir(thd, &create_info.data_file_name,
++			   create_table->table_name) ||
++	append_file_to_dir(thd, &create_info.index_file_name,
++			   create_table->table_name))
++      goto end_with_restore_list;
++#endif
++    /*
++      If we are using SET CHARSET without DEFAULT, add an implicit
++      DEFAULT to not confuse old users. (This may change).
++    */
++    if ((create_info.used_fields &
++	 (HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
++	HA_CREATE_USED_CHARSET)
++    {
++      create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
++      create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
++      create_info.default_table_charset= create_info.table_charset;
++      create_info.table_charset= 0;
++    }
++    /*
++      The create-select command will open and read-lock the select table
++      and then create, open and write-lock the new table. If a global
++      read lock steps in, we get a deadlock. The write lock waits for
++      the global read lock, while the global read lock waits for the
++      select table to be closed. So we wait until the global readlock is
++      gone before starting both steps. Note that
++      wait_if_global_read_lock() sets a protection against a new global
++      read lock when it succeeds. This needs to be released by
++      start_waiting_global_read_lock(). We protect the normal CREATE
++      TABLE in the same way. That way we avoid that a new table is
++      created during a gobal read lock.
++    */
++    if (!thd->locked_tables &&
++        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
++    {
++      res= 1;
++      goto end_with_restore_list;
++    }
++    if (select_lex->item_list.elements)		// With select
++    {
++      select_result *sel_result;
++
++      select_lex->options|= SELECT_NO_UNLOCK;
++      unit->set_limit(select_lex);
++
++      if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
++      {
++        lex->link_first_table_back(create_table, link_to_local);
++        create_table->create= TRUE;
++      }
++
++      if (!(res= open_and_lock_tables(thd, lex->query_tables)))
++      {
++        /*
++          Is table which we are changing used somewhere in other parts
++          of query
++        */
++        if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
++        {
++          TABLE_LIST *duplicate;
++          create_table= lex->unlink_first_table(&link_to_local);
++          if ((duplicate= unique_table(thd, create_table, select_tables, 0)))
++          {
++            update_non_unique_table_error(create_table, "CREATE", duplicate);
++            res= 1;
++            goto end_with_restore_list;
++          }
++        }
++        /* If we create merge table, we have to test tables in merge, too */
++        if (create_info.used_fields & HA_CREATE_USED_UNION)
++        {
++          TABLE_LIST *tab;
++          for (tab= (TABLE_LIST*) create_info.merge_list.first;
++               tab;
++               tab= tab->next_local)
++          {
++            TABLE_LIST *duplicate;
++            if ((duplicate= unique_table(thd, tab, select_tables, 0)))
++            {
++              update_non_unique_table_error(tab, "CREATE", duplicate);
++              res= 1;
++              goto end_with_restore_list;
++            }
++          }
++        }
++        /*
++          select_create is currently not re-execution friendly and
++          needs to be created for every execution of a PS/SP.
++        */
++        if ((sel_result= new select_create(create_table,
++                                           &create_info,
++                                           &alter_info,
++                                           select_lex->item_list,
++                                           lex->duplicates,
++                                           lex->ignore)))
++        {
++          /*
++            CREATE from SELECT give its SELECT_LEX for SELECT,
++            and item_list belong to SELECT
++          */
++          res= handle_select(thd, lex, sel_result, 0);
++          delete sel_result;
++        }
++      }
++      else if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
++        create_table= lex->unlink_first_table(&link_to_local);
++
++    }
++    else
++    {
++      /* regular create */
++      if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
++        res= mysql_create_like_table(thd, create_table, select_tables,
++                                     &create_info);
++      else
++      {
++        res= mysql_create_table(thd, create_table->db,
++                                create_table->table_name, &create_info,
++                                &alter_info, 0, 0);
++      }
++      if (!res)
++	send_ok(thd);
++    }
++
++    /* put tables back for PS rexecuting */
++end_with_restore_list:
++    lex->link_first_table_back(create_table, link_to_local);
++    break;
++  }
++  case SQLCOM_CREATE_INDEX:
++    /* Fall through */
++  case SQLCOM_DROP_INDEX:
++  /*
++    CREATE INDEX and DROP INDEX are implemented by calling ALTER
++    TABLE with proper arguments. This isn't very fast but it
++    should work for most cases.
++
++    In the future ALTER TABLE will notice that only added
++    indexes and create these one by one for the existing table
++    without having to do a full rebuild.
++
++    One should normally create all indexes with CREATE TABLE or
++    ALTER TABLE.
++  */
++  {
++    Alter_info alter_info(lex->alter_info, thd->mem_root);
++    HA_CREATE_INFO create_info;
++
++    if (thd->is_fatal_error) /* out of memory creating a copy of alter_info*/
++      goto error;
++
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_one_table_access(thd, INDEX_ACL, first_table))
++      goto error; /* purecov: inspected */
++    if (end_active_trans(thd))
++      goto error;
++    /*
++      Currently CREATE INDEX or DROP INDEX cause a full table rebuild
++      and thus classify as slow administrative statements just like
++      ALTER TABLE.
++    */
++    thd->enable_slow_log= opt_log_slow_admin_statements;
++
++    bzero((char*) &create_info, sizeof(create_info));
++    create_info.db_type= DB_TYPE_DEFAULT;
++    create_info.row_type= ROW_TYPE_NOT_USED;
++    create_info.default_table_charset= thd->variables.collation_database;
++
++    res= mysql_alter_table(thd, first_table->db, first_table->table_name,
++                           &create_info, first_table, &alter_info,
++                           0, (ORDER*) 0, 0);
++    break;
++  }
++#ifdef HAVE_REPLICATION
++  case SQLCOM_SLAVE_START:
++  {
++    pthread_mutex_lock(&LOCK_active_mi);
++    start_slave(thd,active_mi,1 /* net report*/);
++    pthread_mutex_unlock(&LOCK_active_mi);
++    break;
++  }
++  case SQLCOM_SLAVE_STOP:
++  /*
++    If the client thread has locked tables, a deadlock is possible.
++    Assume that
++    - the client thread does LOCK TABLE t READ.
++    - then the master updates t.
++    - then the SQL slave thread wants to update t,
++      so it waits for the client thread because t is locked by it.
++    - then the client thread does SLAVE STOP.
++      SLAVE STOP waits for the SQL slave thread to terminate its
++      update t, which waits for the client thread because t is locked by it.
++    To prevent that, refuse SLAVE STOP if the
++    client thread has locked tables
++  */
++  if (thd->locked_tables || thd->active_transaction() || thd->global_read_lock)
++  {
++    my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
++               ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
++    goto error;
++  }
++  {
++    pthread_mutex_lock(&LOCK_active_mi);
++    stop_slave(thd,active_mi,1/* net report*/);
++    pthread_mutex_unlock(&LOCK_active_mi);
++    break;
++  }
++#endif /* HAVE_REPLICATION */
++
++  case SQLCOM_ALTER_TABLE:
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    {
++      ulong priv=0;
++      /*
++        Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
++        so we have to use a copy of this structure to make execution
++        prepared statement- safe. A shallow copy is enough as no memory
++        referenced from this structure will be modified.
++      */
++      HA_CREATE_INFO create_info(lex->create_info);
++      Alter_info alter_info(lex->alter_info, thd->mem_root);
++
++      if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
++        goto error;
++      if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
++      {
++	my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name);
++        goto error;
++      }
++      /* Must be set in the parser */
++      DBUG_ASSERT(select_lex->db);
++      if (check_access(thd, ALTER_ACL, first_table->db,
++		       &first_table->grant.privilege, 0, 0,
++                       test(first_table->schema_table)) ||
++	  check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0,
++                       is_schema_db(select_lex->db))||
++	  check_merge_table_access(thd, first_table->db,
++				   (TABLE_LIST *)
++				   create_info.merge_list.first))
++	goto error;				/* purecov: inspected */
++      if (grant_option)
++      {
++	if (check_grant(thd, ALTER_ACL, all_tables, 0, UINT_MAX, 0))
++	  goto error;
++	if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL))
++	{					// Rename of table
++	  TABLE_LIST tmp_table;
++	  bzero((char*) &tmp_table,sizeof(tmp_table));
++	  tmp_table.table_name=lex->name;
++	  tmp_table.db=select_lex->db;
++	  tmp_table.grant.privilege=priv;
++	  if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0,
++			  UINT_MAX, 0))
++	    goto error;
++	}
++      }
++      /* Don't yet allow changing of symlinks with ALTER TABLE */
++      if (create_info.data_file_name)
++        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
++                     "DATA DIRECTORY option ignored");
++      if (create_info.index_file_name)
++        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
++                     "INDEX DIRECTORY option ignored");
++      create_info.data_file_name= create_info.index_file_name= NULL;
++      /* ALTER TABLE ends previous transaction */
++      if (end_active_trans(thd))
++	goto error;
++      else
++      {
++        if (!thd->locked_tables &&
++            !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
++        {
++          res= 1;
++          break;
++        }
++
++        thd->enable_slow_log= opt_log_slow_admin_statements;
++        res= mysql_alter_table(thd, select_lex->db, lex->name,
++                               &create_info,
++                               first_table,
++                               &alter_info,
++                               select_lex->order_list.elements,
++                               (ORDER *) select_lex->order_list.first,
++                               lex->ignore);
++      }
++      break;
++    }
++  case SQLCOM_RENAME_TABLE:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    TABLE_LIST *table;
++    if (check_db_used(thd, all_tables))
++      goto error;
++    for (table= first_table; table; table= table->next_local->next_local)
++    {
++      if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
++		       &table->grant.privilege,0,0, test(table->schema_table)) ||
++	  check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db,
++		       &table->next_local->grant.privilege, 0, 0,
++                       test(table->next_local->schema_table)))
++	goto error;
++      if (grant_option)
++      {
++	TABLE_LIST old_list, new_list;
++	/*
++	  we do not need initialize old_list and new_list because we will
++	  come table[0] and table->next[0] there
++	*/
++	old_list= table[0];
++	new_list= table->next_local[0];
++	if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, 0, 1, 0) ||
++	    (!test_all_bits(table->next_local->grant.privilege,
++			    INSERT_ACL | CREATE_ACL) &&
++	     check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0)))
++	  goto error;
++      }
++    }
++    query_cache_invalidate3(thd, first_table, 0);
++    if (end_active_trans(thd) || mysql_rename_tables(thd, first_table))
++      goto error;
++    break;
++  }
++#ifndef EMBEDDED_LIBRARY
++  case SQLCOM_SHOW_BINLOGS:
++#ifdef DONT_ALLOW_SHOW_COMMANDS
++    my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
++               MYF(0)); /* purecov: inspected */
++    goto error;
++#else
++    {
++      if (check_global_access(thd, SUPER_ACL))
++	goto error;
++      res = show_binlogs(thd);
++      break;
++    }
++#endif
++#endif /* EMBEDDED_LIBRARY */
++  case SQLCOM_SHOW_CREATE:
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++#ifdef DONT_ALLOW_SHOW_COMMANDS
++    my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
++               MYF(0)); /* purecov: inspected */
++    goto error;
++#else
++    {
++      /* Ignore temporary tables if this is "SHOW CREATE VIEW" */
++      if (lex->only_view)
++        first_table->skip_temporary= 1;
++
++      if (check_db_used(thd, all_tables) ||
++          check_show_create_table_access(thd, first_table))
++	goto error;
++      res= mysqld_show_create(thd, first_table);
++      break;
++    }
++#endif
++  case SQLCOM_CHECKSUM:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables) ||
++	check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables, 0))
++      goto error; /* purecov: inspected */
++    res = mysql_checksum_table(thd, first_table, &lex->check_opt);
++    break;
++  }
++  case SQLCOM_REPAIR:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables) ||
++	check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
++      goto error; /* purecov: inspected */
++    thd->enable_slow_log= opt_log_slow_admin_statements;
++    res= mysql_repair_table(thd, first_table, &lex->check_opt);
++    /* ! we write after unlocking the table */
++    if (!res && !lex->no_write_to_binlog)
++    {
++      /* Presumably, REPAIR and binlog writing doesn't require synchronization */
++      if (mysql_bin_log.is_open())
++      {
++	thd->clear_error(); // No binlog error generated
++        Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
++        mysql_bin_log.write(&qinfo);
++      }
++    }
++    select_lex->table_list.first= (byte*) first_table;
++    lex->query_tables=all_tables;
++    break;
++  }
++  case SQLCOM_CHECK:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables) ||
++	check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, 0))
++      goto error; /* purecov: inspected */
++    thd->enable_slow_log= opt_log_slow_admin_statements;
++    res = mysql_check_table(thd, first_table, &lex->check_opt);
++    select_lex->table_list.first= (byte*) first_table;
++    lex->query_tables=all_tables;
++    break;
++  }
++  case SQLCOM_ANALYZE:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables) ||
++	check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
++      goto error; /* purecov: inspected */
++    thd->enable_slow_log= opt_log_slow_admin_statements;
++    res = mysql_analyze_table(thd, first_table, &lex->check_opt);
++    /* ! we write after unlocking the table */
++    if (!res && !lex->no_write_to_binlog)
++    {
++      /* Presumably, ANALYZE and binlog writing doesn't require synchronization */
++      if (mysql_bin_log.is_open())
++      {
++	thd->clear_error(); // No binlog error generated
++        Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
++        mysql_bin_log.write(&qinfo);
++      }
++    }
++    select_lex->table_list.first= (byte*) first_table;
++    lex->query_tables=all_tables;
++    break;
++  }
++
++  case SQLCOM_OPTIMIZE:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables) ||
++	check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
++      goto error; /* purecov: inspected */
++    thd->enable_slow_log= opt_log_slow_admin_statements;
++    res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
++      mysql_recreate_table(thd, first_table) :
++      mysql_optimize_table(thd, first_table, &lex->check_opt);
++    /* ! we write after unlocking the table */
++    if (!res && !lex->no_write_to_binlog)
++    {
++      /* Presumably, OPTIMIZE and binlog writing doesn't require synchronization */
++      if (mysql_bin_log.is_open())
++      {
++	thd->clear_error(); // No binlog error generated
++        Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
++        mysql_bin_log.write(&qinfo);
++      }
++    }
++    select_lex->table_list.first= (byte*) first_table;
++    lex->query_tables=all_tables;
++    break;
++  }
++  case SQLCOM_UPDATE:
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (update_precheck(thd, all_tables))
++      break;
++    DBUG_ASSERT(select_lex->offset_limit == 0);
++    unit->set_limit(select_lex);
++    res= (up_result= mysql_update(thd, all_tables,
++                                  select_lex->item_list,
++                                  lex->value_list,
++                                  select_lex->where,
++                                  select_lex->order_list.elements,
++                                  (ORDER *) select_lex->order_list.first,
++                                  unit->select_limit_cnt,
++                                  lex->duplicates, lex->ignore));
++    /* mysql_update return 2 if we need to switch to multi-update */
++    if (up_result != 2)
++      break;
++    /* Fall through */
++  case SQLCOM_UPDATE_MULTI:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    /* if we switched from normal update, rights are checked */
++    if (up_result != 2)
++    {
++      if ((res= multi_update_precheck(thd, all_tables)))
++        break;
++    }
++    else
++      res= 0;
++
++    res= mysql_multi_update_prepare(thd);
++
++#ifdef HAVE_REPLICATION
++    /* Check slave filtering rules */
++    if (unlikely(thd->slave_thread))
++    {
++      if (all_tables_not_ok(thd, all_tables))
++      {
++        if (res!= 0)
++        {
++          res= 0;             /* don't care of prev failure  */
++          thd->clear_error(); /* filters are of highest prior */
++        }
++        /* we warn the slave SQL thread */
++        my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
++        break;
++      }
++      if (res)
++        break;
++    }
++    else
++    {
++#endif /* HAVE_REPLICATION */
++      if (res)
++        break;
++      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;
++      }
++#ifdef HAVE_REPLICATION
++    }  /* unlikely */
++#endif
++
++    res= mysql_multi_update(thd, all_tables,
++                            &select_lex->item_list,
++                            &lex->value_list,
++                            select_lex->where,
++                            select_lex->options,
++                            lex->duplicates, lex->ignore, unit, select_lex);
++    break;
++  }
++  case SQLCOM_REPLACE:
++  case SQLCOM_INSERT:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if ((res= insert_precheck(thd, all_tables)))
++      break;
++
++    if (!thd->locked_tables &&
++        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
++    {
++      res= 1;
++      break;
++    }
++
++    res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
++		      lex->update_list, lex->value_list,
++                      lex->duplicates, lex->ignore);
++
++    /*
++      If we have inserted into a VIEW, and the base table has
++      AUTO_INCREMENT column, but this column is not accessible through
++      a view, then we should restore LAST_INSERT_ID to the value it
++      had before the statement.
++    */
++    if (first_table->view && !first_table->contain_auto_increment)
++      thd->last_insert_id= thd->current_insert_id;
++
++    break;
++  }
++  case SQLCOM_REPLACE_SELECT:
++  case SQLCOM_INSERT_SELECT:
++  {
++    select_result *sel_result;
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if ((res= insert_precheck(thd, all_tables)))
++      break;
++
++    /* Fix lock for first table */
++    if (first_table->lock_type == TL_WRITE_DELAYED)
++      first_table->lock_type= TL_WRITE;
++
++    /* Don't unlock tables until command is written to binary log */
++    select_lex->options|= SELECT_NO_UNLOCK;
++
++    unit->set_limit(select_lex);
++
++    if (! thd->locked_tables &&
++        ! (need_start_waiting= ! wait_if_global_read_lock(thd, 0, 1)))
++    {
++      res= 1;
++      break;
++    }
++
++    if (!(res= open_and_lock_tables(thd, all_tables)))
++    {
++      /* Skip first table, which is the table we are inserting in */
++      TABLE_LIST *second_table= first_table->next_local;
++      select_lex->table_list.first= (byte*) second_table;
++      select_lex->context.table_list= 
++        select_lex->context.first_name_resolution_table= second_table;
++      res= mysql_insert_select_prepare(thd);
++      if (!res && (sel_result= new select_insert(first_table,
++                                                 first_table->table,
++                                                 &lex->field_list,
++                                                 &lex->update_list,
++                                                 &lex->value_list,
++                                                 lex->duplicates,
++                                                 lex->ignore)))
++      {
++	res= handle_select(thd, lex, sel_result, OPTION_SETUP_TABLES_DONE);
++        /*
++          Invalidate the table in the query cache if something changed
++          after unlocking when changes become visible.
++          TODO: this is workaround. right way will be move invalidating in
++          the unlock procedure.
++        */
++        if (first_table->lock_type ==  TL_WRITE_CONCURRENT_INSERT &&
++            thd->lock)
++        {
++          /* INSERT ... SELECT should invalidate only the very first table */
++          TABLE_LIST *save_table= first_table->next_local;
++          first_table->next_local= 0;
++          mysql_unlock_tables(thd, thd->lock);
++          query_cache_invalidate3(thd, first_table, 1);
++          first_table->next_local= save_table;
++          thd->lock=0;
++        }
++        delete sel_result;
++      }
++      /* revert changes for SP */
++      select_lex->table_list.first= (byte*) first_table;
++    }
++
++    /*
++      If we have inserted into a VIEW, and the base table has
++      AUTO_INCREMENT column, but this column is not accessible through
++      a view, then we should restore LAST_INSERT_ID to the value it
++      had before the statement.
++    */
++    if (first_table->view && !first_table->contain_auto_increment)
++      thd->last_insert_id= thd->current_insert_id;
++
++    break;
++  }
++  case SQLCOM_TRUNCATE:
++    if (end_active_trans(thd))
++    {
++      res= -1;
++      break;
++    }
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_one_table_access(thd, DELETE_ACL, all_tables))
++      goto error;
++    /*
++      Don't allow this within a transaction because we want to use
++      re-generate table
++    */
++    if (thd->locked_tables || thd->active_transaction())
++    {
++      my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
++                 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
++      goto error;
++    }
++
++    res= mysql_truncate(thd, first_table, 0);
++    break;
++  case SQLCOM_DELETE:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if ((res= delete_precheck(thd, all_tables)))
++      break;
++    DBUG_ASSERT(select_lex->offset_limit == 0);
++    unit->set_limit(select_lex);
++
++    if (!thd->locked_tables &&
++        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
++    {
++      res= 1;
++      break;
++    }
++
++    res = mysql_delete(thd, all_tables, select_lex->where,
++                       &select_lex->order_list,
++                       unit->select_limit_cnt, select_lex->options,
++                       FALSE);
++    break;
++  }
++  case SQLCOM_DELETE_MULTI:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    TABLE_LIST *aux_tables=
++      (TABLE_LIST *)thd->lex->auxiliary_table_list.first;
++    multi_delete *del_result;
++
++    if (!thd->locked_tables &&
++        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
++    {
++      res= 1;
++      break;
++    }
++
++    if ((res= multi_delete_precheck(thd, all_tables)))
++      break;
++
++    /* condition will be TRUE on SP re-excuting */
++    if (select_lex->item_list.elements != 0)
++      select_lex->item_list.empty();
++    if (add_item_to_list(thd, new Item_null()))
++      goto error;
++
++    thd_proc_info(thd, "init");
++    if ((res= open_and_lock_tables(thd, all_tables)))
++      break;
++
++    if ((res= mysql_multi_delete_prepare(thd)))
++      goto error;
++
++    if (!thd->is_fatal_error &&
++        (del_result= new multi_delete(aux_tables, lex->table_count)))
++    {
++      res= mysql_select(thd, &select_lex->ref_pointer_array,
++			select_lex->get_table_list(),
++			select_lex->with_wild,
++			select_lex->item_list,
++			select_lex->where,
++			0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
++			(ORDER *)NULL,
++			select_lex->options | thd->options |
++			SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
++                        OPTION_SETUP_TABLES_DONE,
++			del_result, unit, select_lex);
++      delete del_result;
++    }
++    else
++      res= TRUE;                                // Error
++    break;
++  }
++  case SQLCOM_DROP_TABLE:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (!lex->drop_temporary)
++    {
++      if (check_table_access(thd, DROP_ACL, all_tables, 0))
++	goto error;				/* purecov: inspected */
++      if (end_active_trans(thd))
++        goto error;
++    }
++    else
++    {
++      /*
++	If this is a slave thread, we may sometimes execute some 
++	DROP / * 40005 TEMPORARY * / TABLE
++	that come from parts of binlogs (likely if we use RESET SLAVE or CHANGE
++	MASTER TO), while the temporary table has already been dropped.
++	To not generate such irrelevant "table does not exist errors",
++	we silently add IF EXISTS if TEMPORARY was used.
++      */
++      if (thd->slave_thread)
++        lex->drop_if_exists= 1;
++
++      /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
++      thd->transaction.all.modified_non_trans_table= TRUE;
++    }
++    /* DDL and binlog write order protected by LOCK_open */
++    res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
++			lex->drop_temporary);
++  }
++  break;
++  case SQLCOM_SHOW_PROCESSLIST:
++    if (!thd->security_ctx->priv_user[0] &&
++        check_global_access(thd,PROCESS_ACL))
++      break;
++    mysqld_list_processes(thd,
++			  (thd->security_ctx->master_access & PROCESS_ACL ?
++                           NullS :
++                           thd->security_ctx->priv_user),
++                          lex->verbose);
++    break;
++  case SQLCOM_SHOW_STORAGE_ENGINES:
++    res= mysqld_show_storage_engines(thd);
++    break;
++  case SQLCOM_SHOW_PRIVILEGES:
++    res= mysqld_show_privileges(thd);
++    break;
++  case SQLCOM_SHOW_COLUMN_TYPES:
++    res= mysqld_show_column_types(thd);
++    break;
++  case SQLCOM_SHOW_LOGS:
++#ifdef DONT_ALLOW_SHOW_COMMANDS
++    my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
++               MYF(0));	/* purecov: inspected */
++    goto error;
++#else
++    {
++      if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0,0))
++	goto error;
++      res= mysqld_show_logs(thd);
++      break;
++    }
++#endif
++  case SQLCOM_CHANGE_DB:
++  {
++    LEX_STRING db_str= { (char *) select_lex->db, strlen(select_lex->db) };
++
++    if (!mysql_change_db(thd, &db_str, FALSE))
++      send_ok(thd);
++
++    break;
++  }
++
++  case SQLCOM_LOAD:
++  {
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    uint privilege= (lex->duplicates == DUP_REPLACE ?
++		     INSERT_ACL | DELETE_ACL : INSERT_ACL) |
++                    (lex->local_file ? 0 : FILE_ACL);
++
++    if (lex->local_file)
++    {
++      if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) ||
++          !opt_local_infile)
++      {
++	my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), MYF(0));
++	goto error;
++      }
++    }
++
++    if (check_one_table_access(thd, privilege, all_tables))
++      goto error;
++
++    res= mysql_load(thd, lex->exchange, first_table, lex->field_list,
++                    lex->update_list, lex->value_list, lex->duplicates,
++                    lex->ignore, (bool) lex->local_file);
++    break;
++  }
++
++  case SQLCOM_SET_OPTION:
++  {
++    List<set_var_base> *lex_var_list= &lex->var_list;
++    if ((check_table_access(thd, SELECT_ACL, all_tables, 0) ||
++	 open_and_lock_tables(thd, all_tables)))
++      goto error;
++    if (lex->one_shot_set && not_all_support_one_shot(lex_var_list))
++    {
++      my_error(ER_RESERVED_SYNTAX, MYF(0), "SET ONE_SHOT");
++      goto error;
++    }
++    if (!(res= sql_set_variables(thd, lex_var_list)))
++    {
++      /*
++        If the previous command was a SET ONE_SHOT, we don't want to forget
++        about the ONE_SHOT property of that SET. So we use a |= instead of = .
++      */
++      thd->one_shot_set|= lex->one_shot_set;
++      send_ok(thd);
++    }
++    break;
++  }
++
++  case SQLCOM_UNLOCK_TABLES:
++    /*
++      It is critical for mysqldump --single-transaction --master-data that
++      UNLOCK TABLES does not implicitely commit a connection which has only
++      done FLUSH TABLES WITH READ LOCK + BEGIN. If this assumption becomes
++      false, mysqldump will not work.
++    */
++    unlock_locked_tables(thd);
++    if (thd->options & OPTION_TABLE_LOCK)
++    {
++      end_active_trans(thd);
++      thd->options&= ~(OPTION_TABLE_LOCK);
++    }
++    if (thd->global_read_lock)
++      unlock_global_read_lock(thd);
++    send_ok(thd);
++    break;
++  case SQLCOM_LOCK_TABLES:
++    unlock_locked_tables(thd);
++    /* we must end the trasaction first, regardless of anything */
++    if (end_active_trans(thd))
++      goto error;
++    if (check_db_used(thd, all_tables))
++      goto error;
++    if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, 0))
++      goto error;
++    thd->in_lock_tables=1;
++    thd->options|= OPTION_TABLE_LOCK;
++
++    if (!(res= simple_open_n_lock_tables(thd, all_tables)))
++    {
++#ifdef HAVE_QUERY_CACHE
++      if (thd->variables.query_cache_wlock_invalidate)
++	query_cache.invalidate_locked_for_write(first_table);
++#endif /*HAVE_QUERY_CACHE*/
++      thd->locked_tables=thd->lock;
++      thd->lock=0;
++      send_ok(thd);
++    }
++    else
++    {
++      /* 
++        Need to end the current transaction, so the storage engine (InnoDB)
++        can free its locks if LOCK TABLES locked some tables before finding
++        that it can't lock a table in its list
++      */
++      end_active_trans(thd);
++      thd->options&= ~(OPTION_TABLE_LOCK);
++    }
++    thd->in_lock_tables=0;
++    break;
++  case SQLCOM_CREATE_DB:
++  {
++    /*
++      As mysql_create_db() may modify HA_CREATE_INFO structure passed to
++      it, we need to use a copy of LEX::create_info to make execution
++      prepared statement- safe.
++    */
++    HA_CREATE_INFO create_info(lex->create_info);
++    if (end_active_trans(thd))
++    {
++      res= -1;
++      break;
++    }
++    char *alias;
++    if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name))
++    {
++      my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
++      break;
++    }
++    /*
++      If in a slave thread :
++      CREATE DATABASE DB was certainly not preceded by USE DB.
++      For that reason, db_ok() in sql/slave.cc did not check the
++      do_db/ignore_db. And as this query involves no tables, tables_ok()
++      above was not called. So we have to check rules again here.
++    */
++#ifdef HAVE_REPLICATION
++    if (thd->slave_thread &&
++	(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
++	 !db_ok_with_wild_table(lex->name)))
++    {
++      my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
++      break;
++    }
++#endif
++
++    if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
++      break;
++    res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name),
++			 &create_info, 0);
++    break;
++  }
++  case SQLCOM_DROP_DB:
++  {
++    if (end_active_trans(thd))
++    {
++      res= -1;
++      break;
++    }
++    if (check_db_name(lex->name))
++    {
++      my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
++      break;
++    }
++    /*
++      If in a slave thread :
++      DROP DATABASE DB may not be preceded by USE DB.
++      For that reason, maybe db_ok() in sql/slave.cc did not check the 
++      do_db/ignore_db. And as this query involves no tables, tables_ok()
++      above was not called. So we have to check rules again here.
++    */
++#ifdef HAVE_REPLICATION
++    if (thd->slave_thread && 
++	(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
++	 !db_ok_with_wild_table(lex->name)))
++    {
++      my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
++      break;
++    }
++#endif
++    if (check_access(thd,DROP_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
++      break;
++    if (thd->locked_tables || thd->active_transaction())
++    {
++      my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
++                 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
++      goto error;
++    }
++    res= mysql_rm_db(thd, lex->name, lex->drop_if_exists, 0);
++    break;
++  }
++  case SQLCOM_ALTER_DB:
++  {
++    char *db= lex->name;
++    DBUG_ASSERT(db); /* Must be set in the parser */
++    if (!strip_sp(db) || check_db_name(db))
++    {
++      my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
++      break;
++    }
++    /*
++      If in a slave thread :
++      ALTER DATABASE DB may not be preceded by USE DB.
++      For that reason, maybe db_ok() in sql/slave.cc did not check the
++      do_db/ignore_db. And as this query involves no tables, tables_ok()
++      above was not called. So we have to check rules again here.
++    */
++#ifdef HAVE_REPLICATION
++    if (thd->slave_thread &&
++	(!db_ok(db, replicate_do_db, replicate_ignore_db) ||
++	 !db_ok_with_wild_table(db)))
++    {
++      my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
++      break;
++    }
++#endif
++    if (check_access(thd, ALTER_ACL, db, 0, 1, 0, is_schema_db(db)))
++      break;
++    if (thd->locked_tables || thd->active_transaction())
++    {
++      my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
++                 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
++      goto error;
++    }
++    res= mysql_alter_db(thd, db, &lex->create_info);
++    break;
++  }
++  case SQLCOM_SHOW_CREATE_DB:
++  {
++    DBUG_EXECUTE_IF("4x_server_emul",
++                    my_error(ER_UNKNOWN_ERROR, MYF(0)); goto error;);
++    if (!strip_sp(lex->name) || check_db_name(lex->name))
++    {
++      my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
++      break;
++    }
++    if (check_access(thd,SELECT_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
++      break;
++    res=mysqld_show_create_db(thd,lex->name,&lex->create_info);
++    break;
++  }
++  case SQLCOM_CREATE_FUNCTION:                  // UDF function
++  {
++    if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
++      break;
++#ifdef HAVE_DLOPEN
++    if (sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
++                        &thd->sp_func_cache, FALSE))
++    {
++      my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str);
++      goto error;
++    }
++    if (!(res = mysql_create_function(thd, &lex->udf)))
++      send_ok(thd);
++#else
++    my_error(ER_CANT_OPEN_LIBRARY, MYF(0), lex->udf.dl, 0, "feature disabled");
++    res= TRUE;
++#endif
++    break;
++  }
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  case SQLCOM_CREATE_USER:
++  {
++    if (check_access(thd, INSERT_ACL, "mysql", 0, 1, 1, 0) &&
++        check_global_access(thd,CREATE_USER_ACL))
++      break;
++    if (end_active_trans(thd))
++      goto error;
++    /* Conditionally writes to binlog */
++    if (!(res= mysql_create_user(thd, lex->users_list)))
++      send_ok(thd);
++    break;
++  }
++  case SQLCOM_DROP_USER:
++  {
++    if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 1, 0) &&
++        check_global_access(thd,CREATE_USER_ACL))
++      break;
++    if (end_active_trans(thd))
++      goto error;
++    /* Conditionally writes to binlog */
++    if (!(res= mysql_drop_user(thd, lex->users_list)))
++      send_ok(thd);
++    break;
++  }
++  case SQLCOM_RENAME_USER:
++  {
++    if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
++        check_global_access(thd,CREATE_USER_ACL))
++      break;
++    if (end_active_trans(thd))
++      goto error;
++    /* Conditionally writes to binlog */
++    if (!(res= mysql_rename_user(thd, lex->users_list)))
++      send_ok(thd);
++    break;
++  }
++  case SQLCOM_REVOKE_ALL:
++  {
++    if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
++        check_global_access(thd,CREATE_USER_ACL))
++      break;
++    /* Conditionally writes to binlog */
++    if (!(res = mysql_revoke_all(thd, lex->users_list)))
++      send_ok(thd);
++    break;
++  }
++  case SQLCOM_REVOKE:
++  case SQLCOM_GRANT:
++  {
++    if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
++		     first_table ?  first_table->db : select_lex->db,
++		     first_table ? &first_table->grant.privilege : 0,
++		     first_table ? 0 : 1, 0,
++                     first_table ? (bool) first_table->schema_table :
++                     select_lex->db ? is_schema_db(select_lex->db) : 0))
++      goto error;
++
++    if (thd->security_ctx->user)              // If not replication
++    {
++      LEX_USER *user, *tmp_user;
++
++      List_iterator <LEX_USER> user_list(lex->users_list);
++      while ((tmp_user= user_list++))
++      {
++        if (!(user= get_current_user(thd, tmp_user)))
++          goto error;
++        if (specialflag & SPECIAL_NO_RESOLVE &&
++            hostname_requires_resolving(user->host.str))
++          push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++                              ER_WARN_HOSTNAME_WONT_WORK,
++                              ER(ER_WARN_HOSTNAME_WONT_WORK),
++                              user->host.str);
++        // Are we trying to change a password of another user
++        DBUG_ASSERT(user->host.str != 0);
++        if (strcmp(thd->security_ctx->user, user->user.str) ||
++            my_strcasecmp(system_charset_info,
++                          user->host.str, thd->security_ctx->host_or_ip))
++        {
++          // TODO: use check_change_password()
++          if (is_acl_user(user->host.str, user->user.str) &&
++              user->password.str &&
++              check_access(thd, UPDATE_ACL,"mysql",0,1,1,0))
++          {
++            my_message(ER_PASSWORD_NOT_ALLOWED,
++                       ER(ER_PASSWORD_NOT_ALLOWED), MYF(0));
++            goto error;
++          }
++        }
++      }
++    }
++    if (first_table)
++    {
++      if (lex->type == TYPE_ENUM_PROCEDURE ||
++          lex->type == TYPE_ENUM_FUNCTION)
++      {
++        uint grants= lex->all_privileges 
++		   ? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
++		   : lex->grant;
++        if (grant_option && 
++	    check_grant_routine(thd, grants | GRANT_ACL, all_tables,
++                                lex->type == TYPE_ENUM_PROCEDURE, 0))
++	  goto error;
++        /* Conditionally writes to binlog */
++        res= mysql_routine_grant(thd, all_tables,
++                                 lex->type == TYPE_ENUM_PROCEDURE, 
++                                 lex->users_list, grants,
++                                 lex->sql_command == SQLCOM_REVOKE, 0);
++      }
++      else
++      {
++	if (grant_option && check_grant(thd,
++					(lex->grant | lex->grant_tot_col |
++					 GRANT_ACL),
++					all_tables, 0, UINT_MAX, 0))
++	  goto error;
++        /* Conditionally writes to binlog */
++        res= mysql_table_grant(thd, all_tables, lex->users_list,
++			       lex->columns, lex->grant,
++			       lex->sql_command == SQLCOM_REVOKE);
++      }
++    }
++    else
++    {
++      if (lex->columns.elements || lex->type)
++      {
++	my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE),
++                   MYF(0));
++        goto error;
++      }
++      else
++	/* Conditionally writes to binlog */
++	res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
++			  lex->sql_command == SQLCOM_REVOKE);
++      if (!res)
++      {
++	if (lex->sql_command == SQLCOM_GRANT)
++	{
++	  List_iterator <LEX_USER> str_list(lex->users_list);
++	  LEX_USER *user, *tmp_user;
++	  while ((tmp_user=str_list++))
++          {
++            if (!(user= get_current_user(thd, tmp_user)))
++              goto error;
++	    reset_mqh(user);
++          }
++	}
++      }
++    }
++    break;
++  }
++#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
++  case SQLCOM_RESET:
++    /*
++      RESET commands are never written to the binary log, so we have to
++      initialize this variable because RESET shares the same code as FLUSH
++    */
++    lex->no_write_to_binlog= 1;
++  case SQLCOM_FLUSH:
++  {
++    bool write_to_binlog;
++    if (check_global_access(thd,RELOAD_ACL))
++      goto error;
++
++    /*
++      reload_acl_and_cache() will tell us if we are allowed to write to the
++      binlog or not.
++    */
++    if (!reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog))
++    {
++      /*
++        We WANT to write and we CAN write.
++        ! we write after unlocking the table.
++      */
++      /* Presumably, RESET and binlog writing doesn't require synchronization */
++      if (!lex->no_write_to_binlog && write_to_binlog)
++      {
++        if (mysql_bin_log.is_open())
++        {
++          Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
++          mysql_bin_log.write(&qinfo);
++        }
++      }
++      send_ok(thd);
++    } 
++    
++    break;
++  }
++  case SQLCOM_KILL:
++  {
++    Item *it= (Item *)lex->value_list.head();
++
++    if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
++    {
++      my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
++		 MYF(0));
++      goto error;
++    }
++    kill_one_thread(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
++    break;
++  }
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  case SQLCOM_SHOW_GRANTS:
++  {
++    LEX_USER *grant_user= get_current_user(thd, lex->grant_user);
++    if (!grant_user)
++      goto error;
++    if ((thd->security_ctx->priv_user &&
++	 !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) ||
++	!check_access(thd, SELECT_ACL, "mysql",0,1,0,0))
++    {
++      res = mysql_show_grants(thd, grant_user);
++    }
++    break;
++  }
++#endif
++  case SQLCOM_HA_OPEN:
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables) ||
++	check_table_access(thd, SELECT_ACL, all_tables, 0))
++      goto error;
++    res= mysql_ha_open(thd, first_table, 0);
++    break;
++  case SQLCOM_HA_CLOSE:
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    if (check_db_used(thd, all_tables))
++      goto error;
++    res= mysql_ha_close(thd, first_table);
++    break;
++  case SQLCOM_HA_READ:
++    DBUG_ASSERT(first_table == all_tables && first_table != 0);
++    /*
++      There is no need to check for table permissions here, because
++      if a user has no permissions to read a table, he won't be
++      able to open it (with SQLCOM_HA_OPEN) in the first place.
++    */
++    if (check_db_used(thd, all_tables))
++      goto error;
++    unit->set_limit(select_lex);
++    res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str,
++                       lex->insert_list, lex->ha_rkey_mode, select_lex->where,
++                       unit->select_limit_cnt, unit->offset_limit_cnt);
++    break;
++
++  case SQLCOM_BEGIN:
++    if (thd->transaction.xid_state.xa_state != XA_NOTR)
++    {
++      my_error(ER_XAER_RMFAIL, MYF(0),
++               xa_state_names[thd->transaction.xid_state.xa_state]);
++      break;
++    }
++    if (begin_trans(thd))
++      goto error;
++    send_ok(thd);
++    break;
++  case SQLCOM_COMMIT:
++    if (end_trans(thd, lex->tx_release ? COMMIT_RELEASE :
++                              lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT))
++      goto error;
++    send_ok(thd);
++    break;
++  case SQLCOM_ROLLBACK:
++    if (end_trans(thd, lex->tx_release ? ROLLBACK_RELEASE :
++                              lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK))
++      goto error;
++    send_ok(thd);
++    break;
++  case SQLCOM_RELEASE_SAVEPOINT:
++  {
++    SAVEPOINT *sv;
++    for (sv=thd->transaction.savepoints; sv; sv=sv->prev)
++    {
++      if (my_strnncoll(system_charset_info,
++                       (uchar *)lex->ident.str, lex->ident.length,
++                       (uchar *)sv->name, sv->length) == 0)
++        break;
++    }
++    if (sv)
++    {
++      if (ha_release_savepoint(thd, sv))
++        res= TRUE; // cannot happen
++      else
++        send_ok(thd);
++      thd->transaction.savepoints=sv->prev;
++    }
++    else
++      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
++    break;
++  }
++  case SQLCOM_ROLLBACK_TO_SAVEPOINT:
++  {
++    SAVEPOINT *sv;
++    for (sv=thd->transaction.savepoints; sv; sv=sv->prev)
++    {
++      if (my_strnncoll(system_charset_info,
++                       (uchar *)lex->ident.str, lex->ident.length,
++                       (uchar *)sv->name, sv->length) == 0)
++        break;
++    }
++    if (sv)
++    {
++      if (ha_rollback_to_savepoint(thd, sv))
++        res= TRUE; // cannot happen
++      else
++      {
++        if (thd->transaction.all.modified_non_trans_table &&
++            !thd->slave_thread)
++          push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++                       ER_WARNING_NOT_COMPLETE_ROLLBACK,
++                       ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
++        send_ok(thd);
++      }
++      thd->transaction.savepoints=sv;
++    }
++    else
++      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
++    break;
++  }
++  case SQLCOM_SAVEPOINT:
++    if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
++          thd->in_sub_stmt) || !opt_using_transactions)
++      send_ok(thd);
++    else
++    {
++      SAVEPOINT **sv, *newsv;
++      for (sv=&thd->transaction.savepoints; *sv; sv=&(*sv)->prev)
++      {
++        if (my_strnncoll(system_charset_info,
++                         (uchar *)lex->ident.str, lex->ident.length,
++                         (uchar *)(*sv)->name, (*sv)->length) == 0)
++          break;
++      }
++      if (*sv) /* old savepoint of the same name exists */
++      {
++        newsv=*sv;
++        ha_release_savepoint(thd, *sv); // it cannot fail
++        *sv=(*sv)->prev;
++      }
++      else if ((newsv=(SAVEPOINT *) alloc_root(&thd->transaction.mem_root,
++                                               savepoint_alloc_size)) == 0)
++      {
++        my_error(ER_OUT_OF_RESOURCES, MYF(0));
++        break;
++      }
++      newsv->name=strmake_root(&thd->transaction.mem_root,
++                               lex->ident.str, lex->ident.length);
++      newsv->length=lex->ident.length;
++      /*
++        if we'll get an error here, don't add new savepoint to the list.
++        we'll lose a little bit of memory in transaction mem_root, but it'll
++        be free'd when transaction ends anyway
++      */
++      if (ha_savepoint(thd, newsv))
++        res= TRUE;
++      else
++      {
++        newsv->prev=thd->transaction.savepoints;
++        thd->transaction.savepoints=newsv;
++        send_ok(thd);
++      }
++    }
++    break;
++  case SQLCOM_CREATE_PROCEDURE:
++  case SQLCOM_CREATE_SPFUNCTION:
++  {
++    uint namelen;
++    char *name;
++    int sp_result= SP_INTERNAL_ERROR;
++
++    DBUG_ASSERT(lex->sphead != 0);
++    DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
++    /*
++      Verify that the database name is allowed, optionally
++      lowercase it.
++    */
++    if (check_db_name(lex->sphead->m_db.str))
++    {
++      my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str);
++      goto create_sp_error;
++    }
++
++    /*
++      Check that a database directory with this name
++      exists. Design note: This won't work on virtual databases
++      like information_schema.
++    */
++    if (check_db_dir_existence(lex->sphead->m_db.str))
++    {
++      my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
++      goto create_sp_error;
++    }
++
++    if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
++                     is_schema_db(lex->sphead->m_db.str)))
++      goto create_sp_error;
++
++    if (end_active_trans(thd))
++      goto create_sp_error;
++
++    name= lex->sphead->name(&namelen);
++#ifdef HAVE_DLOPEN
++    if (lex->sphead->m_type == TYPE_ENUM_FUNCTION)
++    {
++      udf_func *udf = find_udf(name, namelen);
++
++      if (udf)
++      {
++        my_error(ER_UDF_EXISTS, MYF(0), name);
++        goto create_sp_error;
++      }
++    }
++#endif
++
++    /*
++      If the definer is not specified, this means that CREATE-statement missed
++      DEFINER-clause. DEFINER-clause can be missed in two cases:
++
++        - The user submitted a statement w/o the clause. This is a normal
++          case, we should assign CURRENT_USER as definer.
++
++        - Our slave received an updated from the master, that does not
++          replicate definer for stored rountines. We should also assign
++          CURRENT_USER as definer here, but also we should mark this routine
++          as NON-SUID. This is essential for the sake of backward
++          compatibility.
++
++          The problem is the slave thread is running under "special" user (@),
++          that actually does not exist. In the older versions we do not fail
++          execution of a stored routine if its definer does not exist and
++          continue the execution under the authorization of the invoker
++          (BUG#13198). And now if we try to switch to slave-current-user (@),
++          we will fail.
++
++          Actually, this leads to the inconsistent state of master and
++          slave (different definers, different SUID behaviour), but it seems,
++          this is the best we can do.
++    */
++
++    if (!lex->definer)
++    {
++      bool local_res= FALSE;
++      Query_arena original_arena;
++      Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
++
++      if (!(lex->definer= create_default_definer(thd)))
++        local_res= TRUE;
++
++      if (ps_arena)
++        thd->restore_active_arena(ps_arena, &original_arena);
++
++      /* Error has been already reported. */
++      if (local_res)
++        goto create_sp_error;
++
++      if (thd->slave_thread)
++        lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
++    }
++
++    /*
++      If the specified definer differs from the current user, we should check
++      that the current user has SUPER privilege (in order to create a stored
++      routine under another user one must have SUPER privilege).
++    */
++
++    else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) ||
++        my_strcasecmp(system_charset_info,
++                      lex->definer->host.str,
++                      thd->security_ctx->priv_host))
++    {
++      if (check_global_access(thd, SUPER_ACL))
++      {
++        my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
++        goto create_sp_error;
++      }
++    }
++
++    /* Check that the specified definer exists. Emit a warning if not. */
++
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++    if (!is_acl_user(lex->definer->host.str,
++                     lex->definer->user.str))
++    {
++      push_warning_printf(thd,
++                          MYSQL_ERROR::WARN_LEVEL_NOTE,
++                          ER_NO_SUCH_USER,
++                          ER(ER_NO_SUCH_USER),
++                          lex->definer->user.str,
++                          lex->definer->host.str);
++    }
++#endif /* NO_EMBEDDED_ACCESS_CHECKS */
++
++    res= (sp_result= lex->sphead->create(thd));
++    switch (sp_result) {
++    case SP_OK:
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++      /* only add privileges if really neccessary */
++      if (sp_automatic_privileges && !opt_noacl &&
++          check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
++                               lex->sphead->m_db.str, name,
++                               lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
++      {
++        if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
++                                lex->sql_command == SQLCOM_CREATE_PROCEDURE))
++          push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++                       ER_PROC_AUTO_GRANT_FAIL,
++                       ER(ER_PROC_AUTO_GRANT_FAIL));
++        close_thread_tables(thd);
++      }
++#endif
++    break;
++    case SP_WRITE_ROW_FAILED:
++      my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name);
++    break;
++    case SP_BAD_IDENTIFIER:
++      my_error(ER_TOO_LONG_IDENT, MYF(0), name);
++    break;
++    case SP_BODY_TOO_LONG:
++      my_error(ER_TOO_LONG_BODY, MYF(0), name);
++    break;
++    default:
++      my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
++    break;
++    } /* end switch */
++
++    /*
++      Capture all errors within this CASE and
++      clean up the environment.
++    */
++create_sp_error:
++    if (sp_result != SP_OK )
++      goto error;
++    send_ok(thd);
++    break; /* break super switch */
++  } /* end case group bracket */
++  case SQLCOM_CALL:
++    {
++      sp_head *sp;
++
++      /*
++        This will cache all SP and SF and open and lock all tables
++        required for execution.
++      */
++      if (check_table_access(thd, SELECT_ACL, all_tables, 0) ||
++	  open_and_lock_tables(thd, all_tables))
++       goto error;
++
++      /*
++        By this moment all needed SPs should be in cache so no need to look 
++        into DB. 
++      */
++      if (!(sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
++                                &thd->sp_proc_cache, TRUE)))
++      {
++	my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
++                 lex->spname->m_qname.str);
++	goto error;
++      }
++      else
++      {
++	ha_rows select_limit;
++        /* bits that should be cleared in thd->server_status */
++	uint bits_to_be_cleared= 0;
++        /*
++          Check that the stored procedure doesn't contain Dynamic SQL
++          and doesn't return result sets: such stored procedures can't
++          be called from a function or trigger.
++        */
++        if (thd->in_sub_stmt)
++        {
++          const char *where= (thd->in_sub_stmt & SUB_STMT_TRIGGER ?
++                              "trigger" : "function");
++          if (sp->is_not_allowed_in_function(where))
++            goto error;
++        }
++
++	my_bool save_no_send_ok= thd->net.no_send_ok;
++	thd->net.no_send_ok= TRUE;
++	if (sp->m_flags & sp_head::MULTI_RESULTS)
++	{
++	  if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
++	  {
++            /*
++              The client does not support multiple result sets being sent
++              back
++            */
++	    my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
++	    thd->net.no_send_ok= save_no_send_ok;
++	    goto error;
++	  }
++          /*
++            If SERVER_MORE_RESULTS_EXISTS is not set,
++            then remember that it should be cleared
++          */
++	  bits_to_be_cleared= (~thd->server_status &
++                               SERVER_MORE_RESULTS_EXISTS);
++	  thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
++	}
++
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++	if (check_routine_access(thd, EXECUTE_ACL,
++				 sp->m_db.str, sp->m_name.str, TRUE, FALSE))
++	{
++	  thd->net.no_send_ok= save_no_send_ok;
++	  goto error;
++	}
++#endif
++	select_limit= thd->variables.select_limit;
++	thd->variables.select_limit= HA_POS_ERROR;
++
++        /* 
++          We never write CALL statements into binlog:
++           - If the mode is non-prelocked, each statement will be logged
++             separately.
++           - If the mode is prelocked, the invoking statement will care
++             about writing into binlog.
++          So just execute the statement.
++        */
++	res= sp->execute_procedure(thd, &lex->value_list);
++	/*
++          If warnings have been cleared, we have to clear total_warn_count
++          too, otherwise the clients get confused.
++	 */
++	if (thd->warn_list.is_empty())
++	  thd->total_warn_count= 0;
++
++	thd->variables.select_limit= select_limit;
++
++	thd->net.no_send_ok= save_no_send_ok;
++        thd->server_status&= ~bits_to_be_cleared;
++
++	if (!res)
++	  send_ok(thd, (ulong) (thd->row_count_func < 0 ? 0 :
++                                thd->row_count_func));
++	else
++	  goto error;		// Substatement should already have sent error
++      }
++      break;
++    }
++  case SQLCOM_ALTER_PROCEDURE:
++  case SQLCOM_ALTER_FUNCTION:
++    {
++      int sp_result;
++      sp_head *sp;
++      st_sp_chistics chistics;
++
++      memcpy(&chistics, &lex->sp_chistics, sizeof(chistics));
++      if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
++        sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
++                            &thd->sp_proc_cache, FALSE);
++      else
++        sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
++                            &thd->sp_func_cache, FALSE);
++      mysql_reset_errors(thd, 0);
++      if (! sp)
++      {
++	if (lex->spname->m_db.str)
++	  sp_result= SP_KEY_NOT_FOUND;
++	else
++	{
++	  my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
++	  goto error;
++	}
++      }
++      else
++      {
++        if (check_routine_access(thd, ALTER_PROC_ACL, sp->m_db.str, 
++				 sp->m_name.str,
++                                 lex->sql_command == SQLCOM_ALTER_PROCEDURE, 0))
++	  goto error;
++
++        if (end_active_trans(thd)) 
++          goto error;
++	memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics));
++        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))
++        {
++          my_message(ER_BINLOG_UNSAFE_ROUTINE,
++		     ER(ER_BINLOG_UNSAFE_ROUTINE), MYF(0));
++          sp_result= SP_INTERNAL_ERROR;
++        }
++        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.
++          */
++          /* Conditionally writes to binlog */
++          if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
++            sp_result= sp_update_procedure(thd, lex->spname,
++                                           &lex->sp_chistics);
++          else
++            sp_result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
++        }
++      }
++      switch (sp_result)
++      {
++      case SP_OK:
++	send_ok(thd);
++	break;
++      case SP_KEY_NOT_FOUND:
++	my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
++                 SP_COM_STRING(lex), lex->spname->m_qname.str);
++	goto error;
++      default:
++	my_error(ER_SP_CANT_ALTER, MYF(0),
++                 SP_COM_STRING(lex), lex->spname->m_qname.str);
++	goto error;
++      }
++      break;
++    }
++  case SQLCOM_DROP_PROCEDURE:
++  case SQLCOM_DROP_FUNCTION:
++    {
++      int sp_result;
++      int type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
++                 TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
++
++      sp_result= sp_routine_exists_in_table(thd, type, lex->spname);
++      mysql_reset_errors(thd, 0);
++      if (sp_result == SP_OK)
++      {
++        char *db= lex->spname->m_db.str;
++	char *name= lex->spname->m_name.str;
++
++	if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
++                                 lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
++          goto error;
++
++        if (end_active_trans(thd)) 
++          goto error;
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++	if (sp_automatic_privileges && !opt_noacl &&
++	    sp_revoke_privileges(thd, db, name, 
++                                 lex->sql_command == SQLCOM_DROP_PROCEDURE))
++	{
++	  push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 
++		       ER_PROC_AUTO_REVOKE_FAIL,
++		       ER(ER_PROC_AUTO_REVOKE_FAIL));
++	}
++#endif
++          /* Conditionally writes to binlog */
++	if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
++	  sp_result= sp_drop_procedure(thd, lex->spname);
++	else
++	  sp_result= sp_drop_function(thd, lex->spname);
++      }
++      else
++      {
++#ifdef HAVE_DLOPEN
++	if (lex->sql_command == SQLCOM_DROP_FUNCTION)
++	{
++          udf_func *udf = find_udf(lex->spname->m_name.str,
++                                   lex->spname->m_name.length);
++          if (udf)
++          {
++	    if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0))
++	      goto error;
++
++	    /* Does NOT write to binlog */
++	    if (!(res = mysql_drop_function(thd, &lex->spname->m_name)))
++	    {
++	      send_ok(thd);
++	      break;
++	    }
++	  }
++	}
++#endif
++	if (lex->spname->m_db.str)
++	  sp_result= SP_KEY_NOT_FOUND;
++	else
++	{
++	  my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
++	  goto error;
++	}
++      }
++      res= sp_result;
++      switch (sp_result) {
++      case SP_OK:
++	send_ok(thd);
++	break;
++      case SP_KEY_NOT_FOUND:
++	if (lex->drop_if_exists)
++	{
++	  push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
++			      ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
++			      SP_COM_STRING(lex), lex->spname->m_name.str);
++	  res= FALSE;
++	  send_ok(thd);
++	  break;
++	}
++	my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
++                 SP_COM_STRING(lex), lex->spname->m_qname.str);
++	goto error;
++      default:
++	my_error(ER_SP_DROP_FAILED, MYF(0),
++                 SP_COM_STRING(lex), lex->spname->m_qname.str);
++	goto error;
++      }
++      break;
++    }
++  case SQLCOM_SHOW_CREATE_PROC:
++    {
++      if (lex->spname->m_name.length > NAME_LEN)
++      {
++	my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
++	goto error;
++      }
++      if (sp_show_create_procedure(thd, lex->spname) != SP_OK)
++      {			/* We don't distinguish between errors for now */
++	my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
++                 SP_COM_STRING(lex), lex->spname->m_name.str);
++	goto error;
++      }
++      break;
++    }
++  case SQLCOM_SHOW_CREATE_FUNC:
++    {
++      if (lex->spname->m_name.length > NAME_LEN)
++      {
++	my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
++	goto error;
++      }
++      if (sp_show_create_function(thd, lex->spname) != SP_OK)
++      {			/* We don't distinguish between errors for now */
++	my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
++                 SP_COM_STRING(lex), lex->spname->m_name.str);
++	goto error;
++      }
++      break;
++    }
++  case SQLCOM_SHOW_STATUS_PROC:
++    {
++      res= sp_show_status_procedure(thd, (lex->wild ?
++					  lex->wild->ptr() : NullS));
++      break;
++    }
++  case SQLCOM_SHOW_STATUS_FUNC:
++    {
++      res= sp_show_status_function(thd, (lex->wild ? 
++					 lex->wild->ptr() : NullS));
++      break;
++    }
++#ifndef DBUG_OFF
++  case SQLCOM_SHOW_PROC_CODE:
++  case SQLCOM_SHOW_FUNC_CODE:
++    {
++      sp_head *sp;
++
++      if (lex->spname->m_name.length > NAME_LEN)
++      {
++	my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
++	goto error;
++      }
++      if (lex->sql_command == SQLCOM_SHOW_PROC_CODE)
++        sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
++                            &thd->sp_proc_cache, FALSE);
++      else
++        sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
++                            &thd->sp_func_cache, FALSE);
++      if (!sp || sp->show_routine_code(thd))
++      {
++        /* We don't distinguish between errors for now */
++        my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
++                 SP_COM_STRING(lex), lex->spname->m_name.str);
++        goto error;
++      }
++      break;
++    }
++#endif // ifndef DBUG_OFF
++  case SQLCOM_CREATE_VIEW:
++    {
++      /*
++        Note: SQLCOM_CREATE_VIEW also handles 'ALTER VIEW' commands
++        as specified through the thd->lex->create_view_mode flag.
++      */
++      if (end_active_trans(thd))
++        goto error;
++
++      res= mysql_create_view(thd, first_table, thd->lex->create_view_mode);
++      break;
++    }
++  case SQLCOM_DROP_VIEW:
++    {
++      if (check_table_access(thd, DROP_ACL, all_tables, 0) ||
++          end_active_trans(thd))
++        goto error;
++      /* Conditionally writes to binlog. */
++      res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
++      break;
++    }
++  case SQLCOM_CREATE_TRIGGER:
++  {
++    if (end_active_trans(thd))
++      goto error;
++
++    /* Conditionally writes to binlog. */
++    res= mysql_create_or_drop_trigger(thd, all_tables, 1);
++
++    break;
++  }
++  case SQLCOM_DROP_TRIGGER:
++  {
++    if (end_active_trans(thd))
++      goto error;
++
++    /* Conditionally writes to binlog. */
++    res= mysql_create_or_drop_trigger(thd, all_tables, 0);
++    break;
++  }
++  case SQLCOM_XA_START:
++    if (thd->transaction.xid_state.xa_state == XA_IDLE &&
++        thd->lex->xa_opt == XA_RESUME)
++    {
++      if (! thd->transaction.xid_state.xid.eq(thd->lex->xid))
++      {
++        my_error(ER_XAER_NOTA, MYF(0));
++        break;
++      }
++      thd->transaction.xid_state.xa_state=XA_ACTIVE;
++      send_ok(thd);
++      break;
++    }
++    if (thd->lex->xa_opt != XA_NONE)
++    { // JOIN is not supported yet. TODO
++      my_error(ER_XAER_INVAL, MYF(0));
++      break;
++    }
++    if (thd->transaction.xid_state.xa_state != XA_NOTR)
++    {
++      my_error(ER_XAER_RMFAIL, MYF(0),
++               xa_state_names[thd->transaction.xid_state.xa_state]);
++      break;
++    }
++    if (thd->active_transaction() || thd->locked_tables)
++    {
++      my_error(ER_XAER_OUTSIDE, MYF(0));
++      break;
++    }
++    if (xid_cache_search(thd->lex->xid))
++    {
++      my_error(ER_XAER_DUPID, MYF(0));
++      break;
++    }
++    DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
++    thd->transaction.xid_state.xa_state=XA_ACTIVE;
++    thd->transaction.xid_state.xid.set(thd->lex->xid);
++    xid_cache_insert(&thd->transaction.xid_state);
++    thd->transaction.all.modified_non_trans_table= FALSE;
++    thd->options|= OPTION_BEGIN;
++    thd->server_status|= SERVER_STATUS_IN_TRANS;
++    send_ok(thd);
++    break;
++  case SQLCOM_XA_END:
++    /* fake it */
++    if (thd->lex->xa_opt != XA_NONE)
++    { // SUSPEND and FOR MIGRATE are not supported yet. TODO
++      my_error(ER_XAER_INVAL, MYF(0));
++      break;
++    }
++    if (thd->transaction.xid_state.xa_state != XA_ACTIVE)
++    {
++      my_error(ER_XAER_RMFAIL, MYF(0),
++               xa_state_names[thd->transaction.xid_state.xa_state]);
++      break;
++    }
++    if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
++    {
++      my_error(ER_XAER_NOTA, MYF(0));
++      break;
++    }
++    thd->transaction.xid_state.xa_state=XA_IDLE;
++    send_ok(thd);
++    break;
++  case SQLCOM_XA_PREPARE:
++    if (thd->transaction.xid_state.xa_state != XA_IDLE)
++    {
++      my_error(ER_XAER_RMFAIL, MYF(0),
++               xa_state_names[thd->transaction.xid_state.xa_state]);
++      break;
++    }
++    if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
++    {
++      my_error(ER_XAER_NOTA, MYF(0));
++      break;
++    }
++    if (ha_prepare(thd))
++    {
++      my_error(ER_XA_RBROLLBACK, MYF(0));
++      xid_cache_delete(&thd->transaction.xid_state);
++      thd->transaction.xid_state.xa_state=XA_NOTR;
++      break;
++    }
++    thd->transaction.xid_state.xa_state=XA_PREPARED;
++    send_ok(thd);
++    break;
++  case SQLCOM_XA_COMMIT:
++    if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
++    {
++      XID_STATE *xs=xid_cache_search(thd->lex->xid);
++      if (!xs || xs->in_thd)
++        my_error(ER_XAER_NOTA, MYF(0));
++      else
++      {
++        ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
++        xid_cache_delete(xs);
++        send_ok(thd);
++      }
++      break;
++    }
++    if (thd->transaction.xid_state.xa_state == XA_IDLE &&
++        thd->lex->xa_opt == XA_ONE_PHASE)
++    {
++      int r;
++      if ((r= ha_commit(thd)))
++        my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
++      else
++        send_ok(thd);
++    }
++    else if (thd->transaction.xid_state.xa_state == XA_PREPARED &&
++             thd->lex->xa_opt == XA_NONE)
++    {
++      if (wait_if_global_read_lock(thd, 0, 0))
++      {
++        ha_rollback(thd);
++        my_error(ER_XAER_RMERR, MYF(0));
++      }
++      else
++      {
++        if (ha_commit_one_phase(thd, 1))
++          my_error(ER_XAER_RMERR, MYF(0));
++        else
++          send_ok(thd);
++        start_waiting_global_read_lock(thd);
++      }
++    }
++    else
++    {
++      my_error(ER_XAER_RMFAIL, MYF(0),
++               xa_state_names[thd->transaction.xid_state.xa_state]);
++      break;
++    }
++    thd->options&= ~OPTION_BEGIN;
++    thd->transaction.all.modified_non_trans_table= FALSE;
++    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
++    xid_cache_delete(&thd->transaction.xid_state);
++    thd->transaction.xid_state.xa_state=XA_NOTR;
++    break;
++  case SQLCOM_XA_ROLLBACK:
++    if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
++    {
++      XID_STATE *xs=xid_cache_search(thd->lex->xid);
++      if (!xs || xs->in_thd)
++        my_error(ER_XAER_NOTA, MYF(0));
++      else
++      {
++        ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
++        xid_cache_delete(xs);
++        send_ok(thd);
++      }
++      break;
++    }
++    if (thd->transaction.xid_state.xa_state != XA_IDLE &&
++        thd->transaction.xid_state.xa_state != XA_PREPARED)
++    {
++      my_error(ER_XAER_RMFAIL, MYF(0),
++               xa_state_names[thd->transaction.xid_state.xa_state]);
++      break;
++    }
++    if (ha_rollback(thd))
++      my_error(ER_XAER_RMERR, MYF(0));
++    else
++      send_ok(thd);
++    thd->options&= ~OPTION_BEGIN;
++    thd->transaction.all.modified_non_trans_table= FALSE;
++    thd->server_status&= ~SERVER_STATUS_IN_TRANS;
++    xid_cache_delete(&thd->transaction.xid_state);
++    thd->transaction.xid_state.xa_state=XA_NOTR;
++    break;
++  case SQLCOM_XA_RECOVER:
++    res= mysql_xa_recover(thd);
++    break;
++  default:
++#ifndef EMBEDDED_LIBRARY
++    DBUG_ASSERT(0);                             /* Impossible */
++#endif
++    send_ok(thd);
++    break;
++  }
++  thd_proc_info(thd, "query end");
++  /* Two binlog-related cleanups: */
++
++  /*
++    Reset system variables temporarily modified by SET ONE SHOT.
++
++    Exception: If this is a SET, do nothing. This is to allow
++    mysqlbinlog to print many SET commands (in this case we want the
++    charset temp setting to live until the real query). This is also
++    needed so that SET CHARACTER_SET_CLIENT... does not cancel itself
++    immediately.
++  */
++  if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION)
++    reset_one_shot_variables(thd);
++
++  /*
++    The return value for ROW_COUNT() is "implementation dependent" if the
++    statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC
++    wants.
++
++    We do not change the value for a CALL or EXECUTE statement, so the value
++    generated by the last called (or executed) statement is preserved.
++   */
++  if (lex->sql_command != SQLCOM_CALL && lex->sql_command != SQLCOM_EXECUTE &&
++      uc_update_queries[lex->sql_command]<2)
++    thd->row_count_func= -1;
++
++  goto end;
++
++error:
++  res= TRUE;
++
++end:
++  if (need_start_waiting)
++  {
++    /*
++      Release the protection against the global read lock and wake
++      everyone, who might want to set a global read lock.
++    */
++    start_waiting_global_read_lock(thd);
++  }
++  DBUG_RETURN(res || thd->net.report_error);
++}
++
++
++/*
++  Check grants for commands which work only with one table.
++
++  SYNOPSIS
++    check_single_table_access()
++    thd			Thread handler
++    privilege		requested privilege
++    all_tables		global table list of query
++
++  RETURN
++    0 - OK
++    1 - access denied, error is sent to client
++*/
++
++bool check_single_table_access(THD *thd, ulong privilege, 
++                               TABLE_LIST *all_tables)
++{
++  Security_context * backup_ctx= thd->security_ctx;
++
++  /* we need to switch to the saved context (if any) */
++  if (all_tables->security_ctx)
++    thd->security_ctx= all_tables->security_ctx;
++
++  const char *db_name;
++  if ((all_tables->view || all_tables->field_translation) &&
++      !all_tables->schema_table)
++    db_name= all_tables->view_db.str;
++  else
++    db_name= all_tables->db;
++
++  if (check_access(thd, privilege, db_name,
++		   &all_tables->grant.privilege, 0, 0,
++                   test(all_tables->schema_table)))
++    goto deny;
++
++  /* Show only 1 table for check_grant */
++  if (grant_option &&
++      !(all_tables->belong_to_view &&
++        (thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) &&
++      check_grant(thd, privilege, all_tables, 0, 1, 0))
++    goto deny;
++
++  thd->security_ctx= backup_ctx;
++  return 0;
++
++deny:
++  thd->security_ctx= backup_ctx;
++  return 1;
++}
++
++/*
++  Check grants for commands which work only with one table and all other
++  tables belonging to subselects or implicitly opened tables.
++
++  SYNOPSIS
++    check_one_table_access()
++    thd			Thread handler
++    privilege		requested privilege
++    all_tables		global table list of query
++
++  RETURN
++    0 - OK
++    1 - access denied, error is sent to client
++*/
++
++bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
++{
++  if (check_single_table_access (thd,privilege,all_tables))
++    return 1;
++
++  /* Check rights on tables of subselects and implictly opened tables */
++  TABLE_LIST *subselects_tables, *view= all_tables->view ? all_tables : 0;
++  if ((subselects_tables= all_tables->next_global))
++  {
++    /*
++      Access rights asked for the first table of a view should be the same
++      as for the view
++    */
++    if (view && subselects_tables->belong_to_view == view)
++    {
++      if (check_single_table_access (thd, privilege, subselects_tables))
++        return 1;
++      subselects_tables= subselects_tables->next_global;
++    }
++    if (subselects_tables &&
++        (check_table_access(thd, SELECT_ACL, subselects_tables, 0)))
++      return 1;
++  }
++  return 0;
++}
++
++
++/****************************************************************************
++  Get the user (global) and database privileges for all used tables
++
++  NOTES
++    The idea of EXTRA_ACL is that one will be granted access to the table if
++    one has the asked privilege on any column combination of the table; For
++    example to be able to check a table one needs to have SELECT privilege on
++    any column of the table.
++
++  RETURN
++    0  ok
++    1  If we can't get the privileges and we don't use table/column grants.
++
++    save_priv	In this we store global and db level grants for the table
++		Note that we don't store db level grants if the global grants
++                is enough to satisfy the request and the global grants contains
++                a SELECT grant.
++****************************************************************************/
++
++bool
++check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
++	     bool dont_check_global_grants, bool no_errors, bool schema_db)
++{
++  Security_context *sctx= thd->security_ctx;
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  ulong db_access;
++  /*
++    GRANT command:
++    In case of database level grant the database name may be a pattern,
++    in case of table|column level grant the database name can not be a pattern.
++    We use 'dont_check_global_grants' as a flag to determine
++    if it's database level grant command 
++    (see SQLCOM_GRANT case, mysql_execute_command() function) and
++    set db_is_pattern according to 'dont_check_global_grants' value.
++  */
++  bool  db_is_pattern= (test(want_access & GRANT_ACL) &&
++                        dont_check_global_grants);
++#endif
++  ulong dummy;
++  DBUG_ENTER("check_access");
++  DBUG_PRINT("enter",("db: %s  want_access: %lu  master_access: %lu",
++                      db ? db : "", want_access, sctx->master_access));
++  if (save_priv)
++    *save_priv=0;
++  else
++    save_priv= &dummy;
++
++  thd_proc_info(thd, "checking permissions");
++  if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
++  {
++    DBUG_PRINT("error",("No database"));
++    if (!no_errors)
++      my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
++                 MYF(0));                       /* purecov: tested */
++    DBUG_RETURN(TRUE);				/* purecov: tested */
++  }
++
++  if (schema_db)
++  {
++    if (!(sctx->master_access & FILE_ACL) && (want_access & FILE_ACL) ||
++        (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
++    {
++      if (!no_errors)
++      {
++        const char *db_name= db ? db : thd->db;
++        my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
++                 sctx->priv_user, sctx->priv_host, db_name);
++      }
++      DBUG_RETURN(TRUE);
++    }
++    else
++    {
++      *save_priv= SELECT_ACL;
++      DBUG_RETURN(FALSE);
++    }
++  }
++
++#ifdef NO_EMBEDDED_ACCESS_CHECKS
++  DBUG_RETURN(0);
++#else
++  if ((sctx->master_access & want_access) == want_access)
++  {
++    /*
++      If we don't have a global SELECT privilege, we have to get the database
++      specific access rights to be able to handle queries of type
++      UPDATE t1 SET a=1 WHERE b > 0
++    */
++    db_access= sctx->db_access;
++    if (!(sctx->master_access & SELECT_ACL) &&
++	(db && (!thd->db || db_is_pattern || strcmp(db,thd->db))))
++      db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
++                        db_is_pattern);
++    *save_priv=sctx->master_access | db_access;
++    DBUG_RETURN(FALSE);
++  }
++  if (((want_access & ~sctx->master_access) & ~(DB_ACLS | EXTRA_ACL)) ||
++      ! db && dont_check_global_grants)
++  {						// We can never grant this
++    DBUG_PRINT("error",("No possible access"));
++    if (!no_errors)
++      my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
++               sctx->priv_user,
++               sctx->priv_host,
++               (thd->password ?
++                ER(ER_YES) :
++                ER(ER_NO)));                    /* purecov: tested */
++    DBUG_RETURN(TRUE);				/* purecov: tested */
++  }
++
++  if (db == any_db)
++    DBUG_RETURN(FALSE);				// Allow select on anything
++
++  if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))
++    db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
++                       db_is_pattern);
++  else
++    db_access= sctx->db_access;
++  DBUG_PRINT("info",("db_access: %lu", db_access));
++  /* Remove SHOW attribute and access rights we already have */
++  want_access &= ~(sctx->master_access | EXTRA_ACL);
++  DBUG_PRINT("info",("db_access: %lu  want_access: %lu",
++                     db_access, want_access));
++  db_access= ((*save_priv=(db_access | sctx->master_access)) & want_access);
++
++  /* grant_option is set if there exists a single table or column grant */
++  if (db_access == want_access ||
++      (grant_option && !dont_check_global_grants &&
++       !(want_access & ~(db_access | TABLE_ACLS | PROC_ACLS))))
++    DBUG_RETURN(FALSE);				/* Ok */
++
++  DBUG_PRINT("error",("Access denied"));
++  if (!no_errors)
++    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
++             sctx->priv_user, sctx->priv_host,
++             (db ? db : (thd->db ?
++                         thd->db :
++                         "unknown")));          /* purecov: tested */
++  DBUG_RETURN(TRUE);				/* purecov: tested */
++#endif /* NO_EMBEDDED_ACCESS_CHECKS */
++}
++
++
++/*
++  check for global access and give descriptive error message if it fails
++
++  SYNOPSIS
++    check_global_access()
++    thd			Thread handler
++    want_access		Use should have any of these global rights
++
++  WARNING
++    One gets access right if one has ANY of the rights in want_access
++    This is useful as one in most cases only need one global right,
++    but in some case we want to check if the user has SUPER or
++    REPL_CLIENT_ACL rights.
++
++  RETURN
++    0	ok
++    1	Access denied.  In this case an error is sent to the client
++*/
++
++bool check_global_access(THD *thd, ulong want_access)
++{
++#ifdef NO_EMBEDDED_ACCESS_CHECKS
++  return 0;
++#else
++  char command[128];
++  if ((thd->security_ctx->master_access & want_access))
++    return 0;
++  get_privilege_desc(command, sizeof(command), want_access);
++  my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command);
++  return 1;
++#endif /* NO_EMBEDDED_ACCESS_CHECKS */
++}
++
++
++static bool check_show_access(THD *thd, TABLE_LIST *table)
++{
++  switch (get_schema_table_idx(table->schema_table))
++  {
++  case SCH_SCHEMATA:
++    return (specialflag & SPECIAL_SKIP_SHOW_DB) &&
++           check_global_access(thd, SHOW_DB_ACL);
++
++  case SCH_TABLE_NAMES:
++  case SCH_TABLES:
++  case SCH_VIEWS:
++  case SCH_TRIGGERS:
++    {
++      const char *dst_db_name= table->schema_select_lex->db;
++
++      DBUG_ASSERT(dst_db_name);
++
++      if (check_access(thd, SELECT_ACL, dst_db_name,
++                       &thd->col_access, FALSE, FALSE,
++                       is_schema_db(dst_db_name)))
++      {
++        return TRUE;
++      }
++
++      if (!thd->col_access && check_grant_db(thd, dst_db_name))
++      {
++        my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
++                 thd->security_ctx->priv_user,
++                 thd->security_ctx->priv_host,
++                 dst_db_name);
++        return TRUE;
++      }
++
++      return FALSE;
++    }
++
++  case SCH_COLUMNS:
++  case SCH_STATISTICS:
++    {
++      TABLE_LIST *dst_table=
++        (TABLE_LIST *) table->schema_select_lex->table_list.first;
++
++      DBUG_ASSERT(dst_table);
++
++      if (check_access(thd, SELECT_ACL | EXTRA_ACL,
++                       dst_table->db,
++                       &dst_table->grant.privilege,
++                       FALSE, FALSE,
++                       test(dst_table->schema_table)))
++      {
++        return FALSE;
++      }
++
++      return grant_option &&
++             check_grant(thd, SELECT_ACL, dst_table, 2, UINT_MAX, FALSE);
++    }
++
++  case SCH_OPEN_TABLES:
++  case SCH_VARIABLES:
++  case SCH_STATUS:
++  case SCH_PROCEDURES:
++  case SCH_CHARSETS:
++  case SCH_COLLATIONS:
++  case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
++  case SCH_USER_PRIVILEGES:
++  case SCH_SCHEMA_PRIVILEGES:
++  case SCH_TABLE_PRIVILEGES:
++  case SCH_COLUMN_PRIVILEGES:
++  case SCH_TABLE_CONSTRAINTS:
++  case SCH_KEY_COLUMN_USAGE:
++  case SCH_PROFILES:
++    break;
++  }
++
++  return FALSE;
++}
++
++
++/*
++  Check the privilege for all used tables.
++
++  SYNOPSYS
++    check_table_access()
++      thd          Thread context
++      want_access  Privileges requested
++      tables       List of tables to be checked
++      no_errors    FALSE/TRUE - report/don't report error to
++                   the client (using my_error() call).
++
++  NOTES
++    Table privileges are cached in the table list for GRANT checking.
++    This functions assumes that table list used and
++    thd->lex->query_tables_own_last value correspond to each other
++    (the latter should be either 0 or point to next_global member
++    of one of elements of this table list).
++
++  RETURN VALUE
++    FALSE - OK
++    TRUE  - Access denied
++*/
++
++bool
++check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
++		   bool no_errors)
++{
++  uint found=0;
++  ulong found_access=0;
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  TABLE_LIST *org_tables= tables;
++#endif
++  TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
++  Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx;
++  /*
++    The check that first_not_own_table is not reached is for the case when
++    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)
++  {
++    if (tables->security_ctx)
++      sctx= tables->security_ctx;
++    else
++      sctx= backup_ctx;
++
++    if (tables->schema_table && 
++        (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL)))
++    {
++      if (!no_errors)
++        my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
++                 sctx->priv_user, sctx->priv_host,
++                 INFORMATION_SCHEMA_NAME.str);
++      return TRUE;
++    }
++    /*
++       Register access for view underlying table.
++       Remove SHOW_VIEW_ACL, because it will be checked during making view
++     */
++    tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
++
++    if (tables->schema_table_reformed)
++    {
++      if (check_show_access(thd, tables))
++        goto deny;
++
++      continue;
++    }
++
++    if (tables->derived ||
++        (tables->table && (int)tables->table->s->tmp_table) ||
++        my_tz_check_n_skip_implicit_tables(&tables,
++                                           thd->lex->time_zone_tables_used))
++      continue;
++    thd->security_ctx= sctx;
++    if ((sctx->master_access & want_access) ==
++        (want_access & ~EXTRA_ACL) &&
++	thd->db)
++      tables->grant.privilege= want_access;
++    else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0)
++    {
++      if (found && !grant_option)		// db already checked
++	tables->grant.privilege=found_access;
++      else
++      {
++	if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
++			 0, no_errors, test(tables->schema_table)))
++	  goto deny;                            // Access denied
++	found_access=tables->grant.privilege;
++	found=1;
++      }
++    }
++    else if (check_access(thd,want_access,tables->db,&tables->grant.privilege,
++			  0, no_errors, test(tables->schema_table)))
++      goto deny;
++  }
++  thd->security_ctx= backup_ctx;
++  if (grant_option)
++    return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
++		       test(want_access & EXTRA_ACL), UINT_MAX, no_errors);
++  return FALSE;
++deny:
++  thd->security_ctx= backup_ctx;
++  return TRUE;
++}
++
++
++bool
++check_routine_access(THD *thd, ulong want_access,char *db, char *name,
++		     bool is_proc, bool no_errors)
++{
++  TABLE_LIST tables[1];
++  
++  bzero((char *)tables, sizeof(TABLE_LIST));
++  tables->db= db;
++  tables->table_name= tables->alias= name;
++  
++  /*
++    The following test is just a shortcut for check_access() (to avoid
++    calculating db_access) under the assumption that it's common to
++    give persons global right to execute all stored SP (but not
++    necessary to create them).
++  */
++  if ((thd->security_ctx->master_access & want_access) == want_access)
++    tables->grant.privilege= want_access;
++  else if (check_access(thd,want_access,db,&tables->grant.privilege,
++			0, no_errors, 0))
++    return TRUE;
++  
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  if (grant_option)
++    return check_grant_routine(thd, want_access, tables, is_proc, no_errors);
++#endif
++
++  return FALSE;
++}
++
++
++/*
++  Check if the routine has any of the routine privileges
++
++  SYNOPSIS
++    check_some_routine_access()
++    thd		 Thread handler
++    db           Database name
++    name         Routine name
++
++  RETURN
++    0            ok
++    1            error
++*/
++
++bool check_some_routine_access(THD *thd, const char *db, const char *name,
++                               bool is_proc)
++{
++  ulong save_priv;
++  if (thd->security_ctx->master_access & SHOW_PROC_ACLS)
++    return FALSE;
++  /*
++    There are no routines in information_schema db. So we can safely
++    pass zero to last paramter of check_access function
++  */
++  if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1, 0) ||
++      (save_priv & SHOW_PROC_ACLS))
++    return FALSE;
++  return check_routine_level_acl(thd, db, name, is_proc);
++}
++
++
++/*
++  Check if the given table has any of the asked privileges
++
++  SYNOPSIS
++    check_some_access()
++    thd		 Thread handler
++    want_access	 Bitmap of possible privileges to check for
++
++  RETURN
++    0  ok
++    1  error
++*/
++
++
++bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
++{
++  ulong access;
++  DBUG_ENTER("check_some_access");
++
++  /* This loop will work as long as we have less than 32 privileges */
++  for (access= 1; access < want_access ; access<<= 1)
++  {
++    if (access & want_access)
++    {
++      if (!check_access(thd, access, table->db,
++                        &table->grant.privilege, 0, 1,
++                        test(table->schema_table)) &&
++          !grant_option || !check_grant(thd, access, table, 0, 1, 1))
++        DBUG_RETURN(0);
++    }
++  }
++  DBUG_PRINT("exit",("no matching access rights"));
++  DBUG_RETURN(1);
++}
++
++
++bool check_merge_table_access(THD *thd, char *db,
++			      TABLE_LIST *table_list)
++{
++  int error=0;
++  if (table_list)
++  {
++    /* Check that all tables use the current database */
++    TABLE_LIST *tmp;
++    for (tmp= table_list; tmp; tmp= tmp->next_local)
++    {
++      if (!tmp->db || !tmp->db[0])
++	tmp->db=db;
++    }
++    error=check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
++			     table_list,0);
++  }
++  return error;
++}
++
++
++static bool check_db_used(THD *thd,TABLE_LIST *tables)
++{
++  char *current_db= NULL;
++  for (; tables; tables= tables->next_global)
++  {
++    if (tables->db == NULL)
++    {
++      /*
++        This code never works and should be removed in 5.1.  All tables
++        that are added to the list of tables should already have its
++        database field initialized properly (see st_lex::add_table_to_list).
++      */
++      DBUG_ASSERT(0);
++      if (thd->copy_db_to(&current_db, 0))
++        return TRUE;
++      tables->db= current_db;
++    }
++  }
++  return FALSE;
++}
++
++/****************************************************************************
++	Check stack size; Send error if there isn't enough stack to continue
++****************************************************************************/
++
++#if STACK_DIRECTION < 0
++#define used_stack(A,B) (long) (A - B)
++#else
++#define used_stack(A,B) (long) (B - A)
++#endif
++
++#ifndef DBUG_OFF
++long max_stack_used;
++#endif
++
++#ifndef EMBEDDED_LIBRARY
++/*
++  Note: The 'buf' parameter is necessary, even if it is unused here.
++  - fix_fields functions has a "dummy" buffer large enough for the
++    corresponding exec. (Thus we only have to check in fix_fields.)
++  - Passing to check_stack_overrun() prevents the compiler from removing it.
++ */
++bool check_stack_overrun(THD *thd, long margin,
++			 char *buf __attribute__((unused)))
++{
++  long stack_used;
++  DBUG_ASSERT(thd == current_thd);
++  if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >=
++      (long) (thread_stack - margin))
++  {
++    sprintf(errbuff[0],ER(ER_STACK_OVERRUN_NEED_MORE),
++            stack_used,thread_stack,margin);
++    my_message(ER_STACK_OVERRUN_NEED_MORE,errbuff[0],MYF(0));
++    thd->fatal_error();
++    return 1;
++  }
++#ifndef DBUG_OFF
++  max_stack_used= max(max_stack_used, stack_used);
++#endif
++  return 0;
++}
++#endif /* EMBEDDED_LIBRARY */
++
++#define MY_YACC_INIT 1000			// Start with big alloc
++#define MY_YACC_MAX  32000			// Because of 'short'
++
++bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
++{
++  LEX	*lex= current_thd->lex;
++  ulong old_info=0;
++  if ((uint) *yystacksize >= MY_YACC_MAX)
++    return 1;
++  if (!lex->yacc_yyvs)
++    old_info= *yystacksize;
++  *yystacksize= set_zone((*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX);
++  if (!(lex->yacc_yyvs= (char*)
++	my_realloc((gptr) lex->yacc_yyvs,
++		   *yystacksize*sizeof(**yyvs),
++		   MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) ||
++      !(lex->yacc_yyss= (char*)
++	my_realloc((gptr) lex->yacc_yyss,
++		   *yystacksize*sizeof(**yyss),
++		   MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))))
++    return 1;
++  if (old_info)
++  {						// Copy old info from stack
++    memcpy(lex->yacc_yyss, (gptr) *yyss, old_info*sizeof(**yyss));
++    memcpy(lex->yacc_yyvs, (gptr) *yyvs, old_info*sizeof(**yyvs));
++  }
++  *yyss=(short*) lex->yacc_yyss;
++  *yyvs=(YYSTYPE*) lex->yacc_yyvs;
++  return 0;
++}
++
++
++/*
++ Reset THD part responsible for command processing state.
++
++ DESCRIPTION
++   This needs to be called before execution of every statement
++   (prepared or conventional).
++
++ TODO
++   Make it a method of THD and align its name with the rest of
++   reset/end/start/init methods.
++   Call it after we use THD for queries, not before.
++*/
++
++void mysql_reset_thd_for_next_command(THD *thd)
++{
++  DBUG_ENTER("mysql_reset_thd_for_next_command");
++  thd->free_list= 0;
++  thd->select_number= 1;
++  thd->query_start_used= thd->insert_id_used=0;
++  thd->last_insert_id_used_bin_log= FALSE;
++  thd->is_fatal_error= thd->time_zone_used= 0;
++  thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | 
++                          SERVER_QUERY_NO_INDEX_USED |
++                          SERVER_QUERY_NO_GOOD_INDEX_USED);
++  DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx);
++  thd->tmp_table_used= 0;
++  thd->thread_specific_used= FALSE;
++  if (!thd->in_sub_stmt)
++  {
++    if (opt_bin_log)
++    {
++      reset_dynamic(&thd->user_var_events);
++      thd->user_var_events_alloc= thd->mem_root;
++    }
++    thd->clear_error();
++    thd->total_warn_count=0;			// Warnings for this query
++    thd->rand_used= 0;
++    thd->sent_row_count= thd->examined_row_count= 0;
++#ifdef ENABLED_PROFILING
++    thd->profiling.reset();
++#endif
++  }
++  DBUG_VOID_RETURN;
++}
++
++
++void
++mysql_init_select(LEX *lex)
++{
++  SELECT_LEX *select_lex= lex->current_select;
++  select_lex->init_select();
++  lex->wild= 0;
++  if (select_lex == &lex->select_lex)
++  {
++    DBUG_ASSERT(lex->result == 0);
++    lex->exchange= 0;
++  }
++}
++
++
++bool
++mysql_new_select(LEX *lex, bool move_down)
++{
++  SELECT_LEX *select_lex;
++  THD *thd= lex->thd;
++  DBUG_ENTER("mysql_new_select");
++
++  if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
++    DBUG_RETURN(1);
++  select_lex->select_number= ++thd->select_number;
++  select_lex->parent_lex= lex; /* Used in init_query. */
++  select_lex->init_query();
++  select_lex->init_select();
++  lex->nest_level++;
++  if (lex->nest_level > (int) MAX_SELECT_NESTING)
++  {
++    my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT,MYF(0),MAX_SELECT_NESTING);
++    DBUG_RETURN(1);
++  }
++  select_lex->nest_level= lex->nest_level;
++  /*
++    Don't evaluate this subquery during statement prepare even if
++    it's a constant one. The flag is switched off in the end of
++    mysql_stmt_prepare.
++  */
++  if (thd->stmt_arena->is_stmt_prepare())
++    select_lex->uncacheable|= UNCACHEABLE_PREPARE;
++  if (move_down)
++  {
++    SELECT_LEX_UNIT *unit;
++    lex->subqueries= TRUE;
++    /* first select_lex of subselect or derived table */
++    if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT()))
++      DBUG_RETURN(1);
++
++    unit->init_query();
++    unit->init_select();
++    unit->thd= thd;
++    unit->include_down(lex->current_select);
++    unit->link_next= 0;
++    unit->link_prev= 0;
++    unit->return_to= lex->current_select;
++    select_lex->include_down(unit);
++    /*
++      By default we assume that it is usual subselect and we have outer name
++      resolution context, if no we will assign it to 0 later
++    */
++    select_lex->context.outer_context= &select_lex->outer_select()->context;
++  }
++  else
++  {
++    if (lex->current_select->order_list.first && !lex->current_select->braces)
++    {
++      my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
++      DBUG_RETURN(1);
++    }
++    select_lex->include_neighbour(lex->current_select);
++    SELECT_LEX_UNIT *unit= select_lex->master_unit();                              
++    if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd))
++      DBUG_RETURN(1);
++    select_lex->context.outer_context= 
++                unit->first_select()->context.outer_context;
++  }
++
++  select_lex->master_unit()->global_parameters= select_lex;
++  select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
++  lex->current_select= select_lex;
++  /*
++    in subquery is SELECT query and we allow resolution of names in SELECT
++    list
++  */
++  select_lex->context.resolve_in_select_list= TRUE;
++  DBUG_RETURN(0);
++}
++
++/*
++  Create a select to return the same output as 'SELECT @@var_name'.
++
++  SYNOPSIS
++    create_select_for_variable()
++    var_name		Variable name
++
++  DESCRIPTION
++    Used for SHOW COUNT(*) [ WARNINGS | ERROR]
++
++    This will crash with a core dump if the variable doesn't exists
++*/
++
++void create_select_for_variable(const char *var_name)
++{
++  THD *thd;
++  LEX *lex;
++  LEX_STRING tmp, null_lex_string;
++  Item *var;
++  char buff[MAX_SYS_VAR_LENGTH*2+4+8], *end;
++  DBUG_ENTER("create_select_for_variable");
++
++  thd= current_thd;
++  lex= thd->lex;
++  mysql_init_select(lex);
++  lex->sql_command= SQLCOM_SELECT;
++  tmp.str= (char*) var_name;
++  tmp.length=strlen(var_name);
++  bzero((char*) &null_lex_string.str, sizeof(null_lex_string));
++  /*
++    We set the name of Item to @@session.var_name because that then is used
++    as the column name in the output.
++  */
++  if ((var= get_system_var(thd, OPT_SESSION, tmp, null_lex_string)))
++  {
++    end= strxmov(buff, "@@session.", var_name, NullS);
++    var->set_name(buff, end-buff, system_charset_info);
++    add_item_to_list(thd, var);
++  }
++  DBUG_VOID_RETURN;
++}
++
++
++void mysql_init_multi_delete(LEX *lex)
++{
++  lex->sql_command=  SQLCOM_DELETE_MULTI;
++  mysql_init_select(lex);
++  lex->select_lex.select_limit= 0;
++  lex->unit.select_limit_cnt= HA_POS_ERROR;
++  lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list);
++  lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ;
++  lex->query_tables= 0;
++  lex->query_tables_last= &lex->query_tables;
++}
++
++/*
++  When you modify mysql_parse(), you may need to mofify
++  mysql_test_parse_for_slave() in this same file.
++*/
++
++/**
++  Parse a query.
++  @param thd Current thread
++  @param inBuf Begining of the query text
++  @param length Length of the query text
++  @param [out] semicolon For multi queries, position of the character of
++  the next query in the query text.
++*/
++
++void mysql_parse(THD *thd, const char *inBuf, uint length,
++                 const char ** found_semicolon)
++{
++  DBUG_ENTER("mysql_parse");
++
++  DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););
++
++  /*
++    Warning.
++    The purpose of query_cache_send_result_to_client() is to lookup the
++    query in the query cache first, to avoid parsing and executing it.
++    So, the natural implementation would be to:
++    - first, call query_cache_send_result_to_client,
++    - second, if caching failed, initialise the lexical and syntactic parser.
++    The problem is that the query cache depends on a clean initialization
++    of (among others) lex->safe_to_cache_query and thd->server_status,
++    which are reset respectively in
++    - lex_start()
++    - mysql_reset_thd_for_next_command()
++    So, initializing the lexical analyser *before* using the query cache
++    is required for the cache to work properly.
++    FIXME: cleanup the dependencies in the code to simplify this.
++  */
++  lex_start(thd);
++  mysql_reset_thd_for_next_command(thd);
++
++  if (query_cache_send_result_to_client(thd, (char*) inBuf, length) <= 0)
++  {
++    LEX *lex= thd->lex;
++
++    sp_cache_flush_obsolete(&thd->sp_proc_cache);
++    sp_cache_flush_obsolete(&thd->sp_func_cache);
++
++    Lex_input_stream lip(thd, inBuf, length);
++    thd->m_lip= &lip;
++
++    int err= MYSQLparse(thd);
++    *found_semicolon= lip.found_semicolon;
++
++    if (!err && ! thd->is_fatal_error)
++    {
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++      if (mqh_used && thd->user_connect &&
++	  check_mqh(thd, lex->sql_command))
++      {
++	thd->net.error = 0;
++      }
++      else
++#endif
++      {
++	if (! thd->net.report_error)
++	{
++          /*
++            Binlog logs a string starting from thd->query and having length
++            thd->query_length; so we set thd->query_length correctly (to not
++            log several statements in one event, when we executed only first).
++            We set it to not see the ';' (otherwise it would get into binlog
++            and Query_log_event::print() would give ';;' output).
++            This also helps display only the current query in SHOW
++            PROCESSLIST.
++            Note that we don't need LOCK_thread_count to modify query_length.
++          */
++          if (lip.found_semicolon &&
++              (thd->query_length= (ulong)(lip.found_semicolon - thd->query)))
++            thd->query_length--;
++          /* Actually execute the query */
++          lex->set_trg_event_type_for_tables();
++          mysql_execute_command(thd);
++          query_cache_end_of_result(thd);
++	}
++      }
++    }
++    else
++    {
++      DBUG_ASSERT(thd->net.report_error);
++      DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
++			 thd->is_fatal_error));
++
++      query_cache_abort(&thd->net);
++    }
++    if (thd->lex->sphead)
++    {
++      delete thd->lex->sphead;
++      thd->lex->sphead= 0;
++    }
++    lex->unit.cleanup();
++    thd_proc_info(thd, "freeing items");
++    thd->end_statement();
++    thd->cleanup_after_query();
++    DBUG_ASSERT(thd->change_list.is_empty());
++  }
++  else
++  {
++    /* There are no multi queries in the cache. */
++    *found_semicolon= NULL;
++  }
++
++  DBUG_VOID_RETURN;
++}
++
++
++#ifdef HAVE_REPLICATION
++/*
++  Usable by the replication SQL thread only: just parse a query to know if it
++  can be ignored because of replicate-*-table rules.
++
++  RETURN VALUES
++    0	cannot be ignored
++    1	can be ignored
++*/
++
++bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
++{
++  LEX *lex= thd->lex;
++  bool error= 0;
++  DBUG_ENTER("mysql_test_parse_for_slave");
++
++  Lex_input_stream lip(thd, inBuf, length);
++  thd->m_lip= &lip;
++  lex_start(thd);
++  mysql_reset_thd_for_next_command(thd);
++  int err= MYSQLparse((void*) thd);
++
++  if (!err && ! thd->is_fatal_error &&
++      all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
++    error= 1;                  /* Ignore question */
++  thd->end_statement();
++  thd->cleanup_after_query();
++  DBUG_RETURN(error);
++}
++#endif
++
++
++
++/*****************************************************************************
++** Store field definition for create
++** Return 0 if ok
++******************************************************************************/
++
++bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
++		       char *length, char *decimals,
++		       uint type_modifier,
++		       Item *default_value, Item *on_update_value,
++                       LEX_STRING *comment,
++		       char *change,
++                       List<String> *interval_list, CHARSET_INFO *cs,
++		       uint uint_geom_type)
++{
++  register create_field *new_field;
++  LEX  *lex= thd->lex;
++  DBUG_ENTER("add_field_to_list");
++
++  if (strlen(field_name) > NAME_LEN)
++  {
++    my_error(ER_TOO_LONG_IDENT, MYF(0), field_name); /* purecov: inspected */
++    DBUG_RETURN(1);				/* purecov: inspected */
++  }
++  if (type_modifier & PRI_KEY_FLAG)
++  {
++    lex->col_list.push_back(new key_part_spec(field_name,0));
++    lex->alter_info.key_list.push_back(new Key(Key::PRIMARY, NullS,
++                                               HA_KEY_ALG_UNDEF, 0,
++                                               lex->col_list));
++    lex->col_list.empty();
++  }
++  if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
++  {
++    lex->col_list.push_back(new key_part_spec(field_name,0));
++    lex->alter_info.key_list.push_back(new Key(Key::UNIQUE, NullS,
++                                               HA_KEY_ALG_UNDEF, 0,
++                                               lex->col_list));
++    lex->col_list.empty();
++  }
++
++  if (default_value)
++  {
++    /* 
++      Default value should be literal => basic constants =>
++      no need fix_fields()
++      
++      We allow only one function as part of default value - 
++      NOW() as default for TIMESTAMP type.
++    */
++    if (default_value->type() == Item::FUNC_ITEM && 
++        !(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC &&
++         type == FIELD_TYPE_TIMESTAMP))
++    {
++      my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
++      DBUG_RETURN(1);
++    }
++    else if (default_value->type() == Item::NULL_ITEM)
++    {
++      default_value= 0;
++      if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
++	  NOT_NULL_FLAG)
++      {
++	my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
++	DBUG_RETURN(1);
++      }
++    }
++    else if (type_modifier & AUTO_INCREMENT_FLAG)
++    {
++      my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
++      DBUG_RETURN(1);
++    }
++  }
++
++  if (on_update_value && type != FIELD_TYPE_TIMESTAMP)
++  {
++    my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name);
++    DBUG_RETURN(1);
++  }
++
++  if (type == FIELD_TYPE_TIMESTAMP && length)
++  {
++    /* Display widths are no longer supported for TIMSTAMP as of MySQL 4.1.
++       In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4),
++       and so on, the display width is ignored.
++    */
++    char buf[32];
++    my_snprintf(buf, sizeof(buf), "TIMESTAMP(%s)", length);
++    push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
++                        ER_WARN_DEPRECATED_SYNTAX,
++                        ER(ER_WARN_DEPRECATED_SYNTAX),
++                        buf, "TIMESTAMP");
++  }
++
++  if (!(new_field= new create_field()) ||
++      new_field->init(thd, field_name, type, length, decimals, type_modifier,
++                      default_value, on_update_value, comment, change,
++                      interval_list, cs, uint_geom_type))
++    DBUG_RETURN(1);
++
++  lex->alter_info.create_list.push_back(new_field);
++  lex->last_field=new_field;
++  DBUG_RETURN(0);
++}
++
++
++/* Store position for column in ALTER TABLE .. ADD column */
++
++void store_position_for_column(const char *name)
++{
++  current_thd->lex->last_field->after=my_const_cast(char*) (name);
++}
++
++bool
++add_proc_to_list(THD* thd, Item *item)
++{
++  ORDER *order;
++  Item	**item_ptr;
++
++  if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)+sizeof(Item*))))
++    return 1;
++  item_ptr = (Item**) (order+1);
++  *item_ptr= item;
++  order->item=item_ptr;
++  order->free_me=0;
++  thd->lex->proc_list.link_in_list((byte*) order,(byte**) &order->next);
++  return 0;
++}
++
++
++/* Fix escaping of _, % and \ in database and table names (for ODBC) */
++
++static void remove_escape(char *name)
++{
++  if (!*name)					// For empty DB names
++    return;
++  char *to;
++#ifdef USE_MB
++  char *strend=name+(uint) strlen(name);
++#endif
++  for (to=name; *name ; name++)
++  {
++#ifdef USE_MB
++    int l;
++    if (use_mb(system_charset_info) &&
++        (l = my_ismbchar(system_charset_info, name, strend)))
++    {
++	while (l--)
++	    *to++ = *name++;
++	name--;
++	continue;
++    }
++#endif
++    if (*name == '\\' && name[1])
++      name++;					// Skip '\\'
++    *to++= *name;
++  }
++  *to=0;
++}
++
++/****************************************************************************
++** save order by and tables in own lists
++****************************************************************************/
++
++
++bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc)
++{
++  ORDER *order;
++  DBUG_ENTER("add_to_list");
++  if (!(order = (ORDER *) thd->alloc(sizeof(ORDER))))
++    DBUG_RETURN(1);
++  order->item_ptr= item;
++  order->item= &order->item_ptr;
++  order->asc = asc;
++  order->free_me=0;
++  order->used=0;
++  order->counter_used= 0;
++  list.link_in_list((byte*) order,(byte**) &order->next);
++  DBUG_RETURN(0);
++}
++
++
++/*
++  Add a table to list of used tables
++
++  SYNOPSIS
++    add_table_to_list()
++    table		Table to add
++    alias		alias for table (or null if no alias)
++    table_options	A set of the following bits:
++			TL_OPTION_UPDATING	Table will be updated
++			TL_OPTION_FORCE_INDEX	Force usage of index
++			TL_OPTION_ALIAS	        an alias in multi table DELETE
++    lock_type		How table should be locked
++    use_index		List of indexed used in USE INDEX
++    ignore_index	List of indexed used in IGNORE INDEX
++
++    RETURN
++      0		Error
++      #		Pointer to TABLE_LIST element added to the total table list
++*/
++
++TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
++					     Table_ident *table,
++					     LEX_STRING *alias,
++					     ulong table_options,
++					     thr_lock_type lock_type,
++					     List<String> *use_index_arg,
++					     List<String> *ignore_index_arg,
++                                             LEX_STRING *option)
++{
++  register TABLE_LIST *ptr;
++  TABLE_LIST *previous_table_ref; /* The table preceding the current one. */
++  char *alias_str;
++  LEX *lex= thd->lex;
++  DBUG_ENTER("add_table_to_list");
++  LINT_INIT(previous_table_ref);
++
++  if (!table)
++    DBUG_RETURN(0);				// End of memory
++  alias_str= alias ? alias->str : table->table.str;
++  if (!test(table_options & TL_OPTION_ALIAS) && 
++      check_table_name(table->table.str, table->table.length))
++  {
++    my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
++    DBUG_RETURN(0);
++  }
++
++  if (!alias)					/* Alias is case sensitive */
++  {
++    if (table->sel)
++    {
++      my_message(ER_DERIVED_MUST_HAVE_ALIAS,
++                 ER(ER_DERIVED_MUST_HAVE_ALIAS), MYF(0));
++      DBUG_RETURN(0);
++    }
++    if (!(alias_str=thd->memdup(alias_str,table->table.length+1)))
++      DBUG_RETURN(0);
++  }
++  if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
++    DBUG_RETURN(0);				/* purecov: inspected */
++  if (table->db.str)
++  {
++    if (table->is_derived_table() == FALSE && check_db_name(table->db.str))
++    {
++      my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
++      DBUG_RETURN(0);
++    }
++    ptr->db= table->db.str;
++    ptr->db_length= table->db.length;
++  }
++  else if (lex->copy_db_to(&ptr->db, &ptr->db_length))
++    DBUG_RETURN(0);
++
++  ptr->alias= alias_str;
++  if (lower_case_table_names && table->table.length)
++    table->table.length= my_casedn_str(files_charset_info, table->table.str);
++  ptr->table_name=table->table.str;
++  ptr->table_name_length=table->table.length;
++  ptr->lock_type=   lock_type;
++  ptr->updating=    test(table_options & TL_OPTION_UPDATING);
++  ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
++  ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
++  ptr->derived=	    table->sel;
++  if (!ptr->derived && !my_strcasecmp(system_charset_info, ptr->db,
++                                      INFORMATION_SCHEMA_NAME.str))
++  {
++    ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->table_name);
++    if (!schema_table ||
++        (schema_table->hidden && 
++         lex->orig_sql_command == SQLCOM_END))  // not a 'show' command
++    {
++      my_error(ER_UNKNOWN_TABLE, MYF(0),
++               ptr->table_name, INFORMATION_SCHEMA_NAME.str);
++      DBUG_RETURN(0);
++    }
++    ptr->schema_table_name= ptr->table_name;
++    ptr->schema_table= schema_table;
++  }
++  ptr->select_lex=  lex->current_select;
++  ptr->cacheable_table= 1;
++  if (use_index_arg)
++    ptr->use_index=(List<String> *) thd->memdup((gptr) use_index_arg,
++						sizeof(*use_index_arg));
++  if (ignore_index_arg)
++    ptr->ignore_index=(List<String> *) thd->memdup((gptr) ignore_index_arg,
++						   sizeof(*ignore_index_arg));
++  ptr->option= option ? option->str : 0;
++  /* check that used name is unique */
++  if (lock_type != TL_IGNORE)
++  {
++    TABLE_LIST *first_table= (TABLE_LIST*) table_list.first;
++    if (lex->sql_command == SQLCOM_CREATE_VIEW)
++      first_table= first_table ? first_table->next_local : NULL;
++    for (TABLE_LIST *tables= first_table ;
++	 tables ;
++	 tables=tables->next_local)
++    {
++      if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
++	  !strcmp(ptr->db, tables->db))
++      {
++	my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str); /* purecov: tested */
++	DBUG_RETURN(0);				/* purecov: tested */
++      }
++    }
++  }
++  /* Store the table reference preceding the current one. */
++  if (table_list.elements > 0)
++  {
++    /*
++      table_list.next points to the last inserted TABLE_LIST->next_local'
++      element
++      We don't use the offsetof() macro here to avoid warnings from gcc
++    */
++    previous_table_ref= (TABLE_LIST*) ((char*) table_list.next -
++                                       ((char*) &(ptr->next_local) -
++                                        (char*) ptr));
++    /*
++      Set next_name_resolution_table of the previous table reference to point
++      to the current table reference. In effect the list
++      TABLE_LIST::next_name_resolution_table coincides with
++      TABLE_LIST::next_local. Later this may be changed in
++      store_top_level_join_columns() for NATURAL/USING joins.
++    */
++    previous_table_ref->next_name_resolution_table= ptr;
++  }
++
++  /*
++    Link the current table reference in a local list (list for current select).
++    Notice that as a side effect here we set the next_local field of the
++    previous table reference to 'ptr'. Here we also add one element to the
++    list 'table_list'.
++  */
++  table_list.link_in_list((byte*) ptr, (byte**) &ptr->next_local);
++  ptr->next_name_resolution_table= NULL;
++  /* Link table in global list (all used tables) */
++  lex->add_to_query_tables(ptr);
++  DBUG_RETURN(ptr);
++}
++
++
++/*
++  Initialize a new table list for a nested join
++
++  SYNOPSIS
++    init_nested_join()
++    thd         current thread
++
++  DESCRIPTION
++    The function initializes a structure of the TABLE_LIST type
++    for a nested join. It sets up its nested join list as empty.
++    The created structure is added to the front of the current
++    join list in the st_select_lex object. Then the function
++    changes the current nest level for joins to refer to the newly
++    created empty list after having saved the info on the old level
++    in the initialized structure.
++
++  RETURN VALUE
++    0,  if success
++    1,  otherwise
++*/
++
++bool st_select_lex::init_nested_join(THD *thd)
++{
++  TABLE_LIST *ptr;
++  NESTED_JOIN *nested_join;
++  DBUG_ENTER("init_nested_join");
++
++  if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
++                                       sizeof(NESTED_JOIN))))
++    DBUG_RETURN(1);
++  nested_join= ptr->nested_join=
++    ((NESTED_JOIN*) ((byte*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
++
++  join_list->push_front(ptr);
++  ptr->embedding= embedding;
++  ptr->join_list= join_list;
++  embedding= ptr;
++  join_list= &nested_join->join_list;
++  join_list->empty();
++  DBUG_RETURN(0);
++}
++
++
++/*
++  End a nested join table list
++
++  SYNOPSIS
++    end_nested_join()
++    thd         current thread
++
++  DESCRIPTION
++    The function returns to the previous join nest level.
++    If the current level contains only one member, the function
++    moves it one level up, eliminating the nest.
++
++  RETURN VALUE
++    Pointer to TABLE_LIST element added to the total table list, if success
++    0, otherwise
++*/
++
++TABLE_LIST *st_select_lex::end_nested_join(THD *thd)
++{
++  TABLE_LIST *ptr;
++  NESTED_JOIN *nested_join;
++  DBUG_ENTER("end_nested_join");
++
++  DBUG_ASSERT(embedding);
++  ptr= embedding;
++  join_list= ptr->join_list;
++  embedding= ptr->embedding;
++  nested_join= ptr->nested_join;
++  if (nested_join->join_list.elements == 1)
++  {
++    TABLE_LIST *embedded= nested_join->join_list.head();
++    join_list->pop();
++    embedded->join_list= join_list;
++    embedded->embedding= embedding;
++    join_list->push_front(embedded);
++    ptr= embedded;
++  }
++  else if (nested_join->join_list.elements == 0)
++  {
++    join_list->pop();
++    ptr= 0;                                     // return value
++  }
++  DBUG_RETURN(ptr);
++}
++
++
++/*
++  Nest last join operation
++
++  SYNOPSIS
++    nest_last_join()
++    thd         current thread
++
++  DESCRIPTION
++    The function nest last join operation as if it was enclosed in braces.
++
++  RETURN VALUE
++    0  Error
++    #  Pointer to TABLE_LIST element created for the new nested join
++
++*/
++
++TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
++{
++  TABLE_LIST *ptr;
++  NESTED_JOIN *nested_join;
++  List<TABLE_LIST> *embedded_list;
++  DBUG_ENTER("nest_last_join");
++
++  if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
++                                       sizeof(NESTED_JOIN))))
++    DBUG_RETURN(0);
++  nested_join= ptr->nested_join=
++    ((NESTED_JOIN*) ((byte*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
++
++  ptr->embedding= embedding;
++  ptr->join_list= join_list;
++  embedded_list= &nested_join->join_list;
++  embedded_list->empty();
++
++  for (uint i=0; i < 2; i++)
++  {
++    TABLE_LIST *table= join_list->pop();
++    table->join_list= embedded_list;
++    table->embedding= ptr;
++    embedded_list->push_back(table);
++    if (table->natural_join)
++    {
++      ptr->is_natural_join= TRUE;
++      /*
++        If this is a JOIN ... USING, move the list of joined fields to the
++        table reference that describes the join.
++      */
++      if (prev_join_using)
++        ptr->join_using_fields= prev_join_using;
++    }
++  }
++  join_list->push_front(ptr);
++  nested_join->used_tables= nested_join->not_null_tables= (table_map) 0;
++  DBUG_RETURN(ptr);
++}
++
++
++/*
++  Add a table to the current join list
++
++  SYNOPSIS
++    add_joined_table()
++    table       the table to add
++
++  DESCRIPTION
++    The function puts a table in front of the current join list
++    of st_select_lex object.
++    Thus, joined tables are put into this list in the reverse order
++    (the most outer join operation follows first).
++
++  RETURN VALUE
++    None
++*/
++
++void st_select_lex::add_joined_table(TABLE_LIST *table)
++{
++  DBUG_ENTER("add_joined_table");
++  join_list->push_front(table);
++  table->join_list= join_list;
++  table->embedding= embedding;
++  DBUG_VOID_RETURN;
++}
++
++
++/*
++  Convert a right join into equivalent left join
++
++  SYNOPSIS
++    convert_right_join()
++    thd         current thread
++
++  DESCRIPTION
++    The function takes the current join list t[0],t[1] ... and
++    effectively converts it into the list t[1],t[0] ...
++    Although the outer_join flag for the new nested table contains
++    JOIN_TYPE_RIGHT, it will be handled as the inner table of a left join
++    operation.
++
++  EXAMPLES
++    SELECT * FROM t1 RIGHT JOIN t2 ON on_expr =>
++      SELECT * FROM t2 LEFT JOIN t1 ON on_expr
++
++    SELECT * FROM t1,t2 RIGHT JOIN t3 ON on_expr =>
++      SELECT * FROM t1,t3 LEFT JOIN t2 ON on_expr
++
++    SELECT * FROM t1,t2 RIGHT JOIN (t3,t4) ON on_expr =>
++      SELECT * FROM t1,(t3,t4) LEFT JOIN t2 ON on_expr
++
++    SELECT * FROM t1 LEFT JOIN t2 ON on_expr1 RIGHT JOIN t3  ON on_expr2 =>
++      SELECT * FROM t3 LEFT JOIN (t1 LEFT JOIN t2 ON on_expr2) ON on_expr1
++
++  RETURN
++    Pointer to the table representing the inner table, if success
++    0, otherwise
++*/
++
++TABLE_LIST *st_select_lex::convert_right_join()
++{
++  TABLE_LIST *tab2= join_list->pop();
++  TABLE_LIST *tab1= join_list->pop();
++  DBUG_ENTER("convert_right_join");
++
++  join_list->push_front(tab2);
++  join_list->push_front(tab1);
++  tab1->outer_join|= JOIN_TYPE_RIGHT;
++
++  DBUG_RETURN(tab1);
++}
++
++/*
++  Set lock for all tables in current select level
++
++  SYNOPSIS:
++    set_lock_for_tables()
++    lock_type			Lock to set for tables
++
++  NOTE:
++    If lock is a write lock, then tables->updating is set 1
++    This is to get tables_ok to know that the table is updated by the
++    query
++*/
++
++void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
++{
++  bool for_update= lock_type >= TL_READ_NO_INSERT;
++  DBUG_ENTER("set_lock_for_tables");
++  DBUG_PRINT("enter", ("lock_type: %d  for_update: %d", lock_type,
++		       for_update));
++
++  for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first;
++       tables;
++       tables= tables->next_local)
++  {
++    tables->lock_type= lock_type;
++    tables->updating=  for_update;
++  }
++  DBUG_VOID_RETURN;
++}
++
++
++/*
++  Create a fake SELECT_LEX for a unit
++
++  SYNOPSIS:
++    add_fake_select_lex()
++    thd			   thread handle
++
++  DESCRIPTION
++    The method create a fake SELECT_LEX object for a unit.
++    This object is created for any union construct containing a union
++    operation and also for any single select union construct of the form
++    (SELECT ... ORDER BY order_list [LIMIT n]) ORDER BY ... 
++    or of the form
++    (SELECT ... ORDER BY LIMIT n) ORDER BY ...
++  
++  NOTES
++    The object is used to retrieve rows from the temporary table
++    where the result on the union is obtained.
++
++  RETURN VALUES
++    1     on failure to create the object
++    0     on success
++*/
++
++bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
++{
++  SELECT_LEX *first_sl= first_select();
++  DBUG_ENTER("add_fake_select_lex");
++  DBUG_ASSERT(!fake_select_lex);
++
++  if (!(fake_select_lex= new (thd_arg->mem_root) SELECT_LEX()))
++      DBUG_RETURN(1);
++  fake_select_lex->include_standalone(this, 
++                                      (SELECT_LEX_NODE**)&fake_select_lex);
++  fake_select_lex->select_number= INT_MAX;
++  fake_select_lex->parent_lex= thd_arg->lex; /* Used in init_query. */
++  fake_select_lex->make_empty_select();
++  fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE;
++  fake_select_lex->select_limit= 0;
++
++  fake_select_lex->context.outer_context=first_sl->context.outer_context;
++  /* allow item list resolving in fake select for ORDER BY */
++  fake_select_lex->context.resolve_in_select_list= TRUE;
++  fake_select_lex->context.select_lex= fake_select_lex;
++
++  if (!first_sl->next_select())
++  {
++    /* 
++      This works only for 
++      (SELECT ... ORDER BY list [LIMIT n]) ORDER BY order_list [LIMIT m],
++      (SELECT ... LIMIT n) ORDER BY order_list [LIMIT m]
++      just before the parser starts processing order_list
++    */ 
++    global_parameters= fake_select_lex;
++    fake_select_lex->no_table_names_allowed= 1;
++    thd_arg->lex->current_select= fake_select_lex;
++  }
++  thd_arg->lex->pop_context();
++  DBUG_RETURN(0);
++}
++
++
++/*
++  Push a new name resolution context for a JOIN ... ON clause to the
++  context stack of a query block.
++
++  SYNOPSIS
++    push_new_name_resolution_context()
++    thd       pointer to current thread
++    left_op   left  operand of the JOIN
++    right_op  rigth operand of the JOIN
++
++  DESCRIPTION
++    Create a new name resolution context for a JOIN ... ON clause,
++    set the first and last leaves of the list of table references
++    to be used for name resolution, and push the newly created
++    context to the stack of contexts of the query.
++
++  RETURN
++    FALSE  if all is OK
++    TRUE   if a memory allocation error occured
++*/
++
++bool
++push_new_name_resolution_context(THD *thd,
++                                 TABLE_LIST *left_op, TABLE_LIST *right_op)
++{
++  Name_resolution_context *on_context;
++  if (!(on_context= new (thd->mem_root) Name_resolution_context))
++    return TRUE;
++  on_context->init();
++  on_context->first_name_resolution_table=
++    left_op->first_leaf_for_name_resolution();
++  on_context->last_name_resolution_table=
++    right_op->last_leaf_for_name_resolution();
++  return thd->lex->push_context(on_context);
++}
++
++
++/*
++  Add an ON condition to the second operand of a JOIN ... ON.
++
++  SYNOPSIS
++    add_join_on
++    b     the second operand of a JOIN ... ON
++    expr  the condition to be added to the ON clause
++
++  DESCRIPTION
++    Add an ON condition to the right operand of a JOIN ... ON clause.
++
++  RETURN
++    FALSE  if there was some error
++    TRUE   if all is OK
++*/
++
++void add_join_on(TABLE_LIST *b, Item *expr)
++{
++  if (expr)
++  {
++    if (!b->on_expr)
++      b->on_expr= expr;
++    else
++    {
++      /*
++        If called from the parser, this happens if you have both a
++        right and left join. If called later, it happens if we add more
++        than one condition to the ON clause.
++      */
++      b->on_expr= new Item_cond_and(b->on_expr,expr);
++    }
++    b->on_expr->top_level_item();
++  }
++}
++
++
++/*
++  Mark that there is a NATURAL JOIN or JOIN ... USING between two
++  tables.
++
++  SYNOPSIS
++    add_join_natural()
++    a			Left join argument
++    b			Right join argument
++    using_fields        Field names from USING clause
++    lex                 The current st_select_lex
++  
++  IMPLEMENTATION
++    This function marks that table b should be joined with a either via
++    a NATURAL JOIN or via JOIN ... USING. Both join types are special
++    cases of each other, so we treat them together. The function
++    setup_conds() creates a list of equal condition between all fields
++    of the same name for NATURAL JOIN or the fields in 'using_fields'
++    for JOIN ... USING. The list of equality conditions is stored
++    either in b->on_expr, or in JOIN::conds, depending on whether there
++    was an outer join.
++
++  EXAMPLE
++    SELECT * FROM t1 NATURAL LEFT JOIN t2
++     <=>
++    SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... )
++
++    SELECT * FROM t1 NATURAL JOIN t2 WHERE <some_cond>
++     <=>
++    SELECT * FROM t1, t2 WHERE (t1.i=t2.i and t1.j=t2.j and <some_cond>)
++
++    SELECT * FROM t1 JOIN t2 USING(j) WHERE <some_cond>
++     <=>
++    SELECT * FROM t1, t2 WHERE (t1.j=t2.j and <some_cond>)
++
++  RETURN
++    None
++*/
++
++void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
++                      SELECT_LEX *lex)
++{
++  b->natural_join= a;
++  lex->prev_join_using= using_fields;
++}
++
++
++/*
++  Reload/resets privileges and the different caches.
++
++  SYNOPSIS
++    reload_acl_and_cache()
++    thd			Thread handler (can be NULL!)
++    options             What should be reset/reloaded (tables, privileges,
++    slave...)
++    tables              Tables to flush (if any)
++    write_to_binlog     Depending on 'options', it may be very bad to write the
++                        query to the binlog (e.g. FLUSH SLAVE); this is a
++                        pointer where reload_acl_and_cache() will put 0 if
++                        it thinks we really should not write to the binlog.
++                        Otherwise it will put 1.
++
++  RETURN
++    0	 ok
++    !=0  error.  thd->killed or thd->net.report_error is set
++*/
++
++bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
++                          bool *write_to_binlog)
++{
++  bool result=0;
++  select_errors=0;				/* Write if more errors */
++  bool tmp_write_to_binlog= 1;
++
++  DBUG_ASSERT(!thd || !thd->in_sub_stmt);
++
++#ifndef NO_EMBEDDED_ACCESS_CHECKS
++  if (options & REFRESH_GRANT)
++  {
++    THD *tmp_thd= 0;
++    /*
++      If reload_acl_and_cache() is called from SIGHUP handler we have to
++      allocate temporary THD for execution of acl_reload()/grant_reload().
++    */
++    if (!thd && (thd= (tmp_thd= new THD)))
++    {
++      thd->thread_stack= (char*) &tmp_thd;
++      thd->store_globals();
++    }
++    if (thd)
++    {
++      (void)acl_reload(thd);
++      (void)grant_reload(thd);
++    }
++    if (tmp_thd)
++    {
++      delete tmp_thd;
++      /* Remember that we don't have a THD */
++      my_pthread_setspecific_ptr(THR_THD,  0);
++      thd= 0;
++    }
++    reset_mqh((LEX_USER *)NULL, TRUE);
++  }
++#endif
++  if (options & REFRESH_LOG)
++  {
++    /*
++      Flush the normal query log, the update log, the binary log,
++      the slow query log, and the relay log (if it exists).
++    */
++
++    /*
++      Writing this command to the binlog may result in infinite loops
++      when doing mysqlbinlog|mysql, and anyway it does not really make
++      sense to log it automatically (would cause more trouble to users
++      than it would help them)
++    */
++    tmp_write_to_binlog= 0;
++    mysql_log.new_file(1);
++    mysql_slow_log.new_file(1);
++    if( mysql_bin_log.is_open() )
++    {
++      mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
++    }
++#ifdef HAVE_REPLICATION
++    pthread_mutex_lock(&LOCK_active_mi);
++    rotate_relay_log(active_mi);
++    pthread_mutex_unlock(&LOCK_active_mi);
++#endif
++    if (ha_flush_logs())
++      result=1;
++    if (flush_error_log())
++      result=1;
++  }
++#ifdef HAVE_QUERY_CACHE
++  if (options & REFRESH_QUERY_CACHE_FREE)
++  {
++    query_cache.pack();				// FLUSH QUERY CACHE
++    options &= ~REFRESH_QUERY_CACHE;    // Don't flush cache, just free memory
++  }
++  if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE))
++  {
++    query_cache.flush();			// RESET QUERY CACHE
++  }
++#endif /*HAVE_QUERY_CACHE*/
++  /*
++    Note that if REFRESH_READ_LOCK bit is set then REFRESH_TABLES is set too
++    (see sql_yacc.yy)
++  */
++  if (options & (REFRESH_TABLES | REFRESH_READ_LOCK)) 
++  {
++    if ((options & REFRESH_READ_LOCK) && thd)
++    {
++      /*
++        We must not try to aspire a global read lock if we have a write
++        locked table. This would lead to a deadlock when trying to
++        reopen (and re-lock) the table after the flush.
++      */
++      if (thd->locked_tables)
++      {
++        THR_LOCK_DATA **lock_p= thd->locked_tables->locks;
++        THR_LOCK_DATA **end_p= lock_p + thd->locked_tables->lock_count;
++
++        for (; lock_p < end_p; lock_p++)
++        {
++          if ((*lock_p)->type == TL_WRITE)
++          {
++            my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
++            return 1;
++          }
++        }
++      }
++      /*
++	Writing to the binlog could cause deadlocks, as we don't log
++	UNLOCK TABLES
++      */
++      tmp_write_to_binlog= 0;
++      if (lock_global_read_lock(thd))
++	return 1;                               // Killed
++      result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1,
++                                 tables);
++      if (make_global_read_lock_block_commit(thd)) // Killed
++      {
++        /* Don't leave things in a half-locked state */
++        unlock_global_read_lock(thd);
++        return 1;
++      }
++    }
++    else
++      result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables);
++    my_dbopt_cleanup();
++  }
++  if (options & REFRESH_HOSTS)
++    hostname_cache_refresh();
++  if (thd && (options & REFRESH_STATUS))
++    refresh_status(thd);
++  if (options & REFRESH_THREADS)
++    flush_thread_cache();
++#ifdef HAVE_REPLICATION
++  if (options & REFRESH_MASTER)
++  {
++    DBUG_ASSERT(thd);
++    tmp_write_to_binlog= 0;
++    if (reset_master(thd))
++    {
++      result=1;
++      thd->fatal_error();                       // Ensure client get error
++    }
++  }
++#endif
++#ifdef OPENSSL
++   if (options & REFRESH_DES_KEY_FILE)
++   {
++     if (des_key_file)
++       result=load_des_key_file(des_key_file);
++   }
++#endif
++#ifdef HAVE_REPLICATION
++ if (options & REFRESH_SLAVE)
++ {
++   tmp_write_to_binlog= 0;
++   pthread_mutex_lock(&LOCK_active_mi);
++   if (reset_slave(thd, active_mi))
++     result=1;
++   pthread_mutex_unlock(&LOCK_active_mi);
++ }
++#endif
++ if (options & REFRESH_USER_RESOURCES)
++   reset_mqh((LEX_USER *) NULL);
++ *write_to_binlog= tmp_write_to_binlog;
++ return result;
++}
++
++/*
++  kill on thread
++
++  SYNOPSIS
++    kill_one_thread()
++    thd			Thread class
++    id			Thread id
++
++  NOTES
++    This is written such that we have a short lock on LOCK_thread_count
++*/
++
++void kill_one_thread(THD *thd, ulong id, bool only_kill_query)
++{
++  THD *tmp;
++  uint error=ER_NO_SUCH_THREAD;
++  VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
++  I_List_iterator<THD> it(threads);
++  while ((tmp=it++))
++  {
++    if (tmp->thread_id == id)
++    {
++      pthread_mutex_lock(&tmp->LOCK_delete);	// Lock from delete
++      break;
++    }
++  }
++  VOID(pthread_mutex_unlock(&LOCK_thread_count));
++  if (tmp)
++  {
++    if ((thd->security_ctx->master_access & SUPER_ACL) ||
++	!strcmp(thd->security_ctx->user, tmp->security_ctx->user))
++    {
++      tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION);
++      error=0;
++    }
++    else
++      error=ER_KILL_DENIED_ERROR;
++    pthread_mutex_unlock(&tmp->LOCK_delete);
++  }
++
++  if (!error)
++    send_ok(thd);
++  else
++    my_error(error, MYF(0), id);
++}
++
++
++	/* If pointer is not a null pointer, append filename to it */
++
++static bool append_file_to_dir(THD *thd, const char **filename_ptr,
++			       const char *table_name)
++{
++  char buff[FN_REFLEN],*ptr, *end;
++  if (!*filename_ptr)
++    return 0;					// nothing to do
++
++  /* Check that the filename is not too long and it's a hard path */
++  if (strlen(*filename_ptr)+strlen(table_name) >= FN_REFLEN-1 ||
++      !test_if_hard_path(*filename_ptr))
++  {
++    my_error(ER_WRONG_TABLE_NAME, MYF(0), *filename_ptr);
++    return 1;
++  }
++  /* Fix is using unix filename format on dos */
++  strmov(buff,*filename_ptr);
++  end=convert_dirname(buff, *filename_ptr, NullS);
++  if (!(ptr=thd->alloc((uint) (end-buff)+(uint) strlen(table_name)+1)))
++    return 1;					// End of memory
++  *filename_ptr=ptr;
++  strxmov(ptr,buff,table_name,NullS);
++  return 0;
++}
++
++
++/*
++  Check if the select is a simple select (not an union)
++
++  SYNOPSIS
++    check_simple_select()
++
++  RETURN VALUES
++    0	ok
++    1	error	; In this case the error messege is sent to the client
++*/
++
++bool check_simple_select()
++{
++  THD *thd= current_thd;
++  LEX *lex= thd->lex;
++  if (lex->current_select != &lex->select_lex)
++  {
++    char command[80];
++    Lex_input_stream *lip= thd->m_lip;
++    strmake(command, lip->yylval->symbol.str,
++	    min(lip->yylval->symbol.length, sizeof(command)-1));
++    my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
++    return 1;
++  }
++  return 0;
++}
++
++
++Comp_creator *comp_eq_creator(bool invert)
++{
++  return invert?(Comp_creator *)&ne_creator:(Comp_creator *)&eq_creator;
++}
++
++
++Comp_creator *comp_ge_creator(bool invert)
++{
++  return invert?(Comp_creator *)&lt_creator:(Comp_creator *)&ge_creator;
++}
++
++
++Comp_creator *comp_gt_creator(bool invert)
++{
++  return invert?(Comp_creator *)&le_creator:(Comp_creator *)&gt_creator;
++}
++
++
++Comp_creator *comp_le_creator(bool invert)
++{
++  return invert?(Comp_creator *)&gt_creator:(Comp_creator *)&le_creator;
++}
++
++
++Comp_creator *comp_lt_creator(bool invert)
++{
++  return invert?(Comp_creator *)&ge_creator:(Comp_creator *)&lt_creator;
++}
++
++
++Comp_creator *comp_ne_creator(bool invert)
++{
++  return invert?(Comp_creator *)&eq_creator:(Comp_creator *)&ne_creator;
++}
++
++
++/*
++  Construct ALL/ANY/SOME subquery Item
++
++  SYNOPSIS
++    all_any_subquery_creator()
++    left_expr - pointer to left expression
++    cmp - compare function creator
++    all - true if we create ALL subquery
++    select_lex - pointer on parsed subquery structure
++
++  RETURN VALUE
++    constructed Item (or 0 if out of memory)
++*/
++Item * all_any_subquery_creator(Item *left_expr,
++				chooser_compare_func_creator cmp,
++				bool all,
++				SELECT_LEX *select_lex)
++{
++  if ((cmp == &comp_eq_creator) && !all)       //  = ANY <=> IN
++    return new Item_in_subselect(left_expr, select_lex);
++
++  if ((cmp == &comp_ne_creator) && all)        // <> ALL <=> NOT IN
++    return new Item_func_not(new Item_in_subselect(left_expr, select_lex));
++
++  Item_allany_subselect *it=
++    new Item_allany_subselect(left_expr, cmp, select_lex, all);
++  if (all)
++    return it->upper_item= new Item_func_not_all(it);	/* ALL */
++
++  return it->upper_item= new Item_func_nop_all(it);      /* ANY/SOME */
++}
++
++
++/*
++  Multi update query pre-check
++
++  SYNOPSIS
++    multi_update_precheck()
++    thd		Thread handler
++    tables	Global/local table list (have to be the same)
++
++  RETURN VALUE
++    FALSE OK
++    TRUE  Error
++*/
++
++bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
++{
++  const char *msg= 0;
++  TABLE_LIST *table;
++  LEX *lex= thd->lex;
++  SELECT_LEX *select_lex= &lex->select_lex;
++  DBUG_ENTER("multi_update_precheck");
++
++  if (select_lex->item_list.elements != lex->value_list.elements)
++  {
++    my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
++    DBUG_RETURN(TRUE);
++  }
++  /*
++    Ensure that we have UPDATE or SELECT privilege for each table
++    The exact privilege is checked in mysql_multi_update()
++  */
++  for (table= tables; table; table= table->next_local)
++  {
++    if (table->derived)
++      table->grant.privilege= SELECT_ACL;
++    else if ((check_access(thd, UPDATE_ACL, table->db,
++                           &table->grant.privilege, 0, 1,
++                           test(table->schema_table)) ||
++              grant_option &&
++              check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) &&
++             (check_access(thd, SELECT_ACL, table->db,
++                           &table->grant.privilege, 0, 0,
++                           test(table->schema_table)) ||
++              grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
++      DBUG_RETURN(TRUE);
++
++    table->table_in_first_from_clause= 1;
++  }
++  /*
++    Is there tables of subqueries?
++  */
++  if (&lex->select_lex != lex->all_selects_list || lex->time_zone_tables_used)
++  {
++    DBUG_PRINT("info",("Checking sub query list"));
++    for (table= tables; table; table= table->next_global)
++    {
++      if (!my_tz_check_n_skip_implicit_tables(&table,
++                                              lex->time_zone_tables_used) &&
++          !table->table_in_first_from_clause)
++      {
++	if (check_access(thd, SELECT_ACL, table->db,
++			 &table->grant.privilege, 0, 0,
++                         test(table->schema_table)) ||
++	    grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))
++	  DBUG_RETURN(TRUE);
++      }
++    }
++  }
++
++  if (select_lex->order_list.elements)
++    msg= "ORDER BY";
++  else if (select_lex->select_limit)
++    msg= "LIMIT";
++  if (msg)
++  {
++    my_error(ER_WRONG_USAGE, MYF(0), "UPDATE", msg);
++    DBUG_RETURN(TRUE);
++  }
++  DBUG_RETURN(FALSE);
++}
++
++/*
++  Multi delete query pre-check
++
++  SYNOPSIS
++    multi_delete_precheck()
++    thd			Thread handler
++    tables		Global/local table list
++
++  RETURN VALUE
++    FALSE OK
++    TRUE  error
++*/
++
++bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
++{
++  SELECT_LEX *select_lex= &thd->lex->select_lex;
++  TABLE_LIST *aux_tables=
++    (TABLE_LIST *)thd->lex->auxiliary_table_list.first;
++  TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
++  DBUG_ENTER("multi_delete_precheck");
++
++  /* sql_yacc guarantees that tables and aux_tables are not zero */
++  DBUG_ASSERT(aux_tables != 0);
++  if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
++      check_table_access(thd, SELECT_ACL, tables, 0))
++    DBUG_RETURN(TRUE);
++
++  /*
++    Since aux_tables list is not part of LEX::query_tables list we
++    have to juggle with LEX::query_tables_own_last value to be able
++    call check_table_access() safely.
++  */
++  thd->lex->query_tables_own_last= 0;
++  if (check_table_access(thd, DELETE_ACL, aux_tables, 0))
++  {
++    thd->lex->query_tables_own_last= save_query_tables_own_last;
++    DBUG_RETURN(TRUE);
++  }
++  thd->lex->query_tables_own_last= save_query_tables_own_last;
++
++  if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
++  {
++    my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
++               ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
++    DBUG_RETURN(TRUE);
++  }
++  DBUG_RETURN(FALSE);
++}
++
++
++/*
++  Link tables in auxilary table list of multi-delete with corresponding
++  elements in main table list, and set proper locks for them.
++
++  SYNOPSIS
++    multi_delete_set_locks_and_link_aux_tables()
++      lex - pointer to LEX representing multi-delete
++
++  RETURN VALUE
++    FALSE - success
++    TRUE  - error
++*/
++
++bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
++{
++  TABLE_LIST *tables= (TABLE_LIST*)lex->select_lex.table_list.first;
++  TABLE_LIST *target_tbl;
++  DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables");
++
++  lex->table_count= 0;
++
++  for (target_tbl= (TABLE_LIST *)lex->auxiliary_table_list.first;
++       target_tbl; target_tbl= target_tbl->next_local)
++  {
++    lex->table_count++;
++    /* All tables in aux_tables must be found in FROM PART */
++    TABLE_LIST *walk;
++    for (walk= tables; walk; walk= walk->next_local)
++    {
++      if (!my_strcasecmp(table_alias_charset,
++			 target_tbl->alias, walk->alias) &&
++	  !strcmp(walk->db, target_tbl->db))
++	break;
++    }
++    if (!walk)
++    {
++      my_error(ER_UNKNOWN_TABLE, MYF(0),
++               target_tbl->table_name, "MULTI DELETE");
++      DBUG_RETURN(TRUE);
++    }
++    if (!walk->derived)
++    {
++      target_tbl->table_name= walk->table_name;
++      target_tbl->table_name_length= walk->table_name_length;
++    }
++    walk->updating= target_tbl->updating;
++    walk->lock_type= target_tbl->lock_type;
++    target_tbl->correspondent_table= walk;	// Remember corresponding table
++  }
++  DBUG_RETURN(FALSE);
++}
++
++
++/*
++  simple UPDATE query pre-check
++
++  SYNOPSIS
++    update_precheck()
++    thd		Thread handler
++    tables	Global table list
++
++  RETURN VALUE
++    FALSE OK
++    TRUE  Error
++*/
++
++bool update_precheck(THD *thd, TABLE_LIST *tables)
++{
++  DBUG_ENTER("update_precheck");
++  if (thd->lex->select_lex.item_list.elements != thd->lex->value_list.elements)
++  {
++    my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
++    DBUG_RETURN(TRUE);
++  }
++  DBUG_RETURN(check_db_used(thd, tables) ||
++	       check_one_table_access(thd, UPDATE_ACL, tables));
++}
++
++
++/*
++  simple DELETE query pre-check
++
++  SYNOPSIS
++    delete_precheck()
++    thd		Thread handler
++    tables	Global table list
++
++  RETURN VALUE
++    FALSE  OK
++    TRUE   error
++*/
++
++bool delete_precheck(THD *thd, TABLE_LIST *tables)
++{
++  DBUG_ENTER("delete_precheck");
++  if (check_one_table_access(thd, DELETE_ACL, tables))
++    DBUG_RETURN(TRUE);
++  /* Set privilege for the WHERE clause */
++  tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
++  DBUG_RETURN(FALSE);
++}
++
++
++/*
++  simple INSERT query pre-check
++
++  SYNOPSIS
++    insert_precheck()
++    thd		Thread handler
++    tables	Global table list
++
++  RETURN VALUE
++    FALSE  OK
++    TRUE   error
++*/
++
++bool insert_precheck(THD *thd, TABLE_LIST *tables)
++{
++  LEX *lex= thd->lex;
++  DBUG_ENTER("insert_precheck");
++
++  /*
++    Check that we have modify privileges for the first table and
++    select privileges for the rest
++  */
++  ulong privilege= (INSERT_ACL |
++                    (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) |
++                    (lex->value_list.elements ? UPDATE_ACL : 0));
++
++  if (check_one_table_access(thd, privilege, tables))
++    DBUG_RETURN(TRUE);
++
++  if (lex->update_list.elements != lex->value_list.elements)
++  {
++    my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
++    DBUG_RETURN(TRUE);
++  }
++  if (check_db_used(thd, tables))
++    DBUG_RETURN(TRUE);
++  DBUG_RETURN(FALSE);
++}
++
++
++/**
++   @brief  Check privileges for SHOW CREATE TABLE statement.
++
++   @param  thd    Thread context
++   @param  table  Target table
++
++   @retval TRUE  Failure
++   @retval FALSE Success
++*/
++
++static bool check_show_create_table_access(THD *thd, TABLE_LIST *table)
++{
++  return check_access(thd, SELECT_ACL | EXTRA_ACL, table->db,
++                      &table->grant.privilege, 0, 0,
++                      test(table->schema_table)) ||
++         grant_option && check_grant(thd, SELECT_ACL, table, 2, UINT_MAX, 0);
++}
++
++
++/*
++  CREATE TABLE query pre-check
++
++  SYNOPSIS
++    create_table_precheck()
++    thd			Thread handler
++    tables		Global table list
++    create_table	Table which will be created
++
++  RETURN VALUE
++    FALSE   OK
++    TRUE   Error
++*/
++
++bool create_table_precheck(THD *thd, TABLE_LIST *tables,
++                           TABLE_LIST *create_table)
++{
++  LEX *lex= thd->lex;
++  SELECT_LEX *select_lex= &lex->select_lex;
++  ulong want_priv;
++  bool error= TRUE;                                 // Error message is given
++  DBUG_ENTER("create_table_precheck");
++
++  want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
++              CREATE_TMP_ACL : CREATE_ACL);
++  if (check_access(thd, want_priv, create_table->db,
++		   &create_table->grant.privilege, 0, 0,
++                   test(create_table->schema_table)) ||
++      check_merge_table_access(thd, create_table->db,
++			       (TABLE_LIST *)
++			       lex->create_info.merge_list.first))
++    goto err;
++  if (grant_option && want_priv != CREATE_TMP_ACL &&
++      check_grant(thd, want_priv, create_table, 0, 1, 0))
++    goto err;
++
++  if (select_lex->item_list.elements)
++  {
++    /* Check permissions for used tables in CREATE TABLE ... SELECT */
++
++#ifdef NOT_NECESSARY_TO_CHECK_CREATE_TABLE_EXIST_WHEN_PREPARING_STATEMENT
++    /* This code throws an ill error for CREATE TABLE t1 SELECT * FROM t1 */
++    /*
++      Only do the check for PS, becasue we on execute we have to check that
++      against the opened tables to ensure we don't use a table that is part
++      of the view (which can only be done after the table has been opened).
++    */
++    if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
++    {
++      /*
++        For temporary tables we don't have to check if the created table exists
++      */
++      if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
++          find_table_in_global_list(tables, create_table->db,
++                                    create_table->table_name))
++      {
++	error= FALSE;
++        goto err;
++      }
++    }
++#endif
++    if (tables && check_table_access(thd, SELECT_ACL, tables,0))
++      goto err;
++  }
++  else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
++  {
++    if (check_show_create_table_access(thd, tables))
++      goto err;
++  }
++  error= FALSE;
++
++err:
++  DBUG_RETURN(error);
++}
++
++
++/*
++  negate given expression
++
++  SYNOPSIS
++    negate_expression()
++    thd  thread handler
++    expr expression for negation
++
++  RETURN
++    negated expression
++*/
++
++Item *negate_expression(THD *thd, Item *expr)
++{
++  Item *negated;
++  if (expr->type() == Item::FUNC_ITEM &&
++      ((Item_func *) expr)->functype() == Item_func::NOT_FUNC)
++  {
++    /* it is NOT(NOT( ... )) */
++    Item *arg= ((Item_func *) expr)->arguments()[0];
++    enum_parsing_place place= thd->lex->current_select->parsing_place;
++    if (arg->is_bool_func() || place == IN_WHERE || place == IN_HAVING)
++      return arg;
++    /*
++      if it is not boolean function then we have to emulate value of
++      not(not(a)), it will be a != 0
++    */
++    return new Item_func_ne(arg, new Item_int((char*) "0", 0, 1));
++  }
++
++  if ((negated= expr->neg_transformer(thd)) != 0)
++    return negated;
++  return new Item_func_not(expr);
++}
++
++/*
++  Set the specified definer to the default value, which is the current user in
++  the thread.
++ 
++  SYNOPSIS
++    get_default_definer()
++    thd       [in] thread handler
++    definer   [out] definer
++*/
++ 
++void get_default_definer(THD *thd, LEX_USER *definer)
++{
++  const Security_context *sctx= thd->security_ctx;
++
++  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);
++}
++
++
++/*
++  Create default definer for the specified THD.
++
++  SYNOPSIS
++    create_default_definer()
++    thd         [in] thread handler
++
++  RETURN
++    On success, return a valid pointer to the created and initialized
++    LEX_USER, which contains definer information.
++    On error, return 0.
++*/
++
++LEX_USER *create_default_definer(THD *thd)
++{
++  LEX_USER *definer;
++
++  if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
++    return 0;
++
++  get_default_definer(thd, definer);
++
++  return definer;
++}
++
++
++/*
++  Create definer with the given user and host names.
++
++  SYNOPSIS
++    create_definer()
++    thd         [in] thread handler
++    user_name   [in] user name
++    host_name   [in] host name
++
++  RETURN
++    On success, return a valid pointer to the created and initialized
++    LEX_USER, which contains definer information.
++    On error, return 0.
++*/
++
++LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name)
++{
++  LEX_USER *definer;
++
++  /* Create and initialize. */
++
++  if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
++    return 0;
++
++  definer->user= *user_name;
++  definer->host= *host_name;
++
++  return definer;
++}
++
++
++/*
++  Retuns information about user or current user.
++
++  SYNOPSIS
++    get_current_user()
++    thd         [in] thread handler
++    user        [in] user
++
++  RETURN
++    On success, return a valid pointer to initialized
++    LEX_USER, which contains user information.
++    On error, return 0.
++*/
++
++LEX_USER *get_current_user(THD *thd, LEX_USER *user)
++{
++  if (!user->user.str)  // current_user
++    return create_default_definer(thd);
++
++  return user;
++}
++
++
++/*
++  Check that length of a string does not exceed some limit.
++
++  SYNOPSIS
++    check_string_length()
++      str         string to be checked
++      err_msg     error message to be displayed if the string is too long
++      max_length  max length
++
++  RETURN
++    FALSE   the passed string is not longer than max_length
++    TRUE    the passed string is longer than max_length
++*/
++
++bool check_string_length(LEX_STRING *str, const char *err_msg,
++                         uint max_length)
++{
++  if (str->length <= max_length)
++    return FALSE;
++
++  my_error(ER_WRONG_STRING_LENGTH, MYF(0), str->str, err_msg, max_length);
++
++  return TRUE;
++}
+diff -urNad trunk~/sql/sql_yacc.yy trunk/sql/sql_yacc.yy
+--- trunk~/sql/sql_yacc.yy	2007-11-15 08:06:49.000000000 -0600
++++ trunk/sql/sql_yacc.yy	2007-12-27 15:54:49.574279959 -0600
+@@ -7273,6 +7273,9 @@
+ 	    case DB_TYPE_INNODB:
+ 	      Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS;
+ 	      break;
++	    case DB_TYPE_SPHINX_DB:
++	      Lex->sql_command = SQLCOM_SHOW_SPHINX_STATUS;
++	      break;
+ 	    default:
+ 	      my_error(ER_NOT_SUPPORTED_YET, MYF(0), "STATUS");
+ 	      MYSQL_YYABORT;
+diff -urNad trunk~/sql/sql_yacc.yy.orig trunk/sql/sql_yacc.yy.orig
+--- trunk~/sql/sql_yacc.yy.orig	1969-12-31 18:00:00.000000000 -0600
++++ trunk/sql/sql_yacc.yy.orig	2007-12-27 15:54:49.582280415 -0600
+@@ -0,0 +1,10061 @@
++/* Copyright (C) 2000-2003 MySQL AB
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; version 2 of the License.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
++
++/* sql_yacc.yy */
++
++%{
++/* thd is passed as an arg to yyparse(), and subsequently to yylex().
++** The type will be void*, so it must be  cast to (THD*) when used.
++** Use the YYTHD macro for this.
++*/
++#define YYPARSE_PARAM yythd
++#define YYLEX_PARAM yythd
++#define YYTHD ((THD *)yythd)
++
++#define MYSQL_YACC
++#define YYINITDEPTH 100
++#define YYMAXDEPTH 3200				/* Because of 64K stack */
++#define Lex (YYTHD->lex)
++#define Select Lex->current_select
++#include "mysql_priv.h"
++#include "slave.h"
++#include "lex_symbol.h"
++#include "item_create.h"
++#include "sp_head.h"
++#include "sp_pcontext.h"
++#include "sp_rcontext.h"
++#include "sp.h"
++#include <myisam.h>
++#include <myisammrg.h>
++
++int yylex(void *yylval, void *yythd);
++
++const LEX_STRING null_lex_str={0,0};
++
++#define yyoverflow(A,B,C,D,E,F) {ulong val= *(F); if (my_yyoverflow((B), (D), &val)) { yyerror((char*) (A)); return 2; } else { *(F)= (YYSIZE_T)val; }}
++
++#undef 	WARN_DEPRECATED			/* this macro is also defined in mysql_priv.h */
++#define WARN_DEPRECATED(A,B)                                        \
++  push_warning_printf(((THD *)yythd), MYSQL_ERROR::WARN_LEVEL_WARN, \
++		      ER_WARN_DEPRECATED_SYNTAX,                    \
++		      ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B));
++
++#define MYSQL_YYABORT                         \
++  do                                          \
++  {                                           \
++    LEX::cleanup_lex_after_parse_error(YYTHD);\
++    YYABORT;                                  \
++  } while (0)
++
++#define MYSQL_YYABORT_UNLESS(A)         \
++  if (!(A))                             \
++  {                                     \
++    my_parse_error(ER(ER_SYNTAX_ERROR));\
++    MYSQL_YYABORT;                      \
++  }
++
++#ifndef DBUG_OFF
++#define YYDEBUG 1
++#else
++#define YYDEBUG 0
++#endif
++
++/**
++  @brief Push an error message into MySQL error stack with line
++  and position information.
++
++  This function provides semantic action implementers with a way
++  to push the famous "You have a syntax error near..." error
++  message into the error stack, which is normally produced only if
++  a parse error is discovered internally by the Bison generated
++  parser.
++*/
++
++void my_parse_error(const char *s)
++{
++  THD *thd= current_thd;
++  Lex_input_stream *lip= thd->m_lip;
++
++  const char *yytext= lip->tok_start;
++  /* Push an error into the error stack */
++  my_printf_error(ER_PARSE_ERROR,  ER(ER_PARSE_ERROR), MYF(0), s,
++                  (yytext ? yytext : ""),
++                  lip->yylineno);
++}
++
++/**
++  @brief Bison callback to report a syntax/OOM error
++
++  This function is invoked by the bison-generated parser
++  when a syntax error, a parse error or an out-of-memory
++  condition occurs. This function is not invoked when the
++  parser is requested to abort by semantic action code
++  by means of YYABORT or YYACCEPT macros. This is why these
++  macros should not be used (use MYSQL_YYABORT/MYSQL_YYACCEPT
++  instead).
++
++  The parser will abort immediately after invoking this callback.
++
++  This function is not for use in semantic actions and is internal to
++  the parser, as it performs some pre-return cleanup. 
++  In semantic actions, please use my_parse_error or my_error to
++  push an error into the error stack and MYSQL_YYABORT
++  to abort from the parser.
++*/
++
++void MYSQLerror(const char *s)
++{
++  THD *thd= current_thd;
++
++  /*
++    Restore the original LEX if it was replaced when parsing
++    a stored procedure. We must ensure that a parsing error
++    does not leave any side effects in the THD.
++  */
++  LEX::cleanup_lex_after_parse_error(thd);
++
++  /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
++  if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
++    s= ER(ER_SYNTAX_ERROR);
++  my_parse_error(s);
++}
++
++
++#ifndef DBUG_OFF
++void turn_parser_debug_on()
++{
++  /*
++     MYSQLdebug is in sql/sql_yacc.cc, in bison generated code.
++     Turning this option on is **VERY** verbose, and should be
++     used when investigating a syntax error problem only.
++
++     The syntax to run with bison traces is as follows :
++     - Starting a server manually :
++       mysqld --debug="d,parser_debug" ...
++     - Running a test :
++       mysql-test-run.pl --mysqld="--debug=d,parser_debug" ...
++
++     The result will be in the process stderr (var/log/master.err)
++   */
++
++  extern int yydebug;
++  yydebug= 1;
++}
++#endif
++
++
++/**
++  Helper action for a case statement (entering the CASE).
++  This helper is used for both 'simple' and 'searched' cases.
++  This helper, with the other case_stmt_action_..., is executed when
++  the following SQL code is parsed:
++<pre>
++CREATE PROCEDURE proc_19194_simple(i int)
++BEGIN
++  DECLARE str CHAR(10);
++
++  CASE i
++    WHEN 1 THEN SET str="1";
++    WHEN 2 THEN SET str="2";
++    WHEN 3 THEN SET str="3";
++    ELSE SET str="unknown";
++  END CASE;
++
++  SELECT str;
++END
++</pre>
++  The actions are used to generate the following code:
++<pre>
++SHOW PROCEDURE CODE proc_19194_simple;
++Pos     Instruction
++0       set str at 1 NULL
++1       set_case_expr (12) 0 i at 0
++2       jump_if_not 5(12) (case_expr at 0 = 1)
++3       set str at 1 _latin1'1'
++4       jump 12
++5       jump_if_not 8(12) (case_expr at 0 = 2)
++6       set str at 1 _latin1'2'
++7       jump 12
++8       jump_if_not 11(12) (case_expr at 0 = 3)
++9       set str at 1 _latin1'3'
++10      jump 12
++11      set str at 1 _latin1'unknown'
++12      stmt 0 "SELECT str"
++</pre>
++
++  @param lex the parser lex context
++*/
++
++void case_stmt_action_case(LEX *lex)
++{
++  lex->sphead->new_cont_backpatch(NULL);
++
++  /*
++    BACKPATCH: Creating target label for the jump to
++    "case_stmt_action_end_case"
++    (Instruction 12 in the example)
++  */
++
++  lex->spcont->push_label((char *)"", lex->sphead->instructions());
++}
++
++/**
++  Helper action for a case expression statement (the expr in 'CASE expr').
++  This helper is used for 'searched' cases only.
++  @param lex the parser lex context
++  @param expr the parsed expression
++  @return 0 on success
++*/
++
++int case_stmt_action_expr(LEX *lex, Item* expr)
++{
++  sp_head *sp= lex->sphead;
++  sp_pcontext *parsing_ctx= lex->spcont;
++  int case_expr_id= parsing_ctx->register_case_expr();
++  sp_instr_set_case_expr *i;
++
++  if (parsing_ctx->push_case_expr_id(case_expr_id))
++    return 1;
++
++  i= new sp_instr_set_case_expr(sp->instructions(),
++                                parsing_ctx, case_expr_id, expr, lex);
++
++  sp->add_cont_backpatch(i);
++  sp->add_instr(i);
++
++  return 0;
++}
++
++/**
++  Helper action for a case when condition.
++  This helper is used for both 'simple' and 'searched' cases.
++  @param lex the parser lex context
++  @param when the parsed expression for the WHEN clause
++  @param simple true for simple cases, false for searched cases
++*/
++
++void case_stmt_action_when(LEX *lex, Item *when, bool simple)
++{
++  sp_head *sp= lex->sphead;
++  sp_pcontext *ctx= lex->spcont;
++  uint ip= sp->instructions();
++  sp_instr_jump_if_not *i;
++  Item_case_expr *var;
++  Item *expr;
++
++  if (simple)
++  {
++    var= new Item_case_expr(ctx->get_current_case_expr_id());
++
++#ifndef DBUG_OFF
++    if (var)
++    {
++      var->m_sp= sp;
++    }
++#endif
++
++    expr= new Item_func_eq(var, when);
++    i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
++  }
++  else
++    i= new sp_instr_jump_if_not(ip, ctx, when, lex);
++
++  /*
++    BACKPATCH: Registering forward jump from
++    "case_stmt_action_when" to "case_stmt_action_then"
++    (jump_if_not from instruction 2 to 5, 5 to 8 ... in the example)
++  */
++
++  sp->push_backpatch(i, ctx->push_label((char *)"", 0));
++  sp->add_cont_backpatch(i);
++  sp->add_instr(i);
++}
++
++/**
++  Helper action for a case then statements.
++  This helper is used for both 'simple' and 'searched' cases.
++  @param lex the parser lex context
++*/
++
++void case_stmt_action_then(LEX *lex)
++{
++  sp_head *sp= lex->sphead;
++  sp_pcontext *ctx= lex->spcont;
++  uint ip= sp->instructions();
++  sp_instr_jump *i = new sp_instr_jump(ip, ctx);
++  sp->add_instr(i);
++
++  /*
++    BACKPATCH: Resolving forward jump from
++    "case_stmt_action_when" to "case_stmt_action_then"
++    (jump_if_not from instruction 2 to 5, 5 to 8 ... in the example)
++  */
++
++  sp->backpatch(ctx->pop_label());
++
++  /*
++    BACKPATCH: Registering forward jump from
++    "case_stmt_action_then" to "case_stmt_action_end_case"
++    (jump from instruction 4 to 12, 7 to 12 ... in the example)
++  */
++
++  sp->push_backpatch(i, ctx->last_label());
++}
++
++/**
++  Helper action for an end case.
++  This helper is used for both 'simple' and 'searched' cases.
++  @param lex the parser lex context
++  @param simple true for simple cases, false for searched cases
++*/
++
++void case_stmt_action_end_case(LEX *lex, bool simple)
++{
++  /*
++    BACKPATCH: Resolving forward jump from
++    "case_stmt_action_then" to "case_stmt_action_end_case"
++    (jump from instruction 4 to 12, 7 to 12 ... in the example)
++  */
++  lex->sphead->backpatch(lex->spcont->pop_label());
++
++  if (simple)
++    lex->spcont->pop_case_expr_id();
++
++  lex->sphead->do_cont_backpatch();
++}
++
++/**
++  Helper to resolve the SQL:2003 Syntax exception 1) in <in predicate>.
++  See SQL:2003, Part 2, section 8.4 <in predicate>, Note 184, page 383.
++  This function returns the proper item for the SQL expression
++  <code>left [NOT] IN ( expr )</code>
++  @param thd the current thread
++  @param left the in predicand
++  @param equal true for IN predicates, false for NOT IN predicates
++  @param expr first and only expression of the in value list
++  @return an expression representing the IN predicate.
++*/
++Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
++                                       Item *expr)
++{
++  /*
++    Relevant references for this issue:
++    - SQL:2003, Part 2, section 8.4 <in predicate>, page 383,
++    - SQL:2003, Part 2, section 7.2 <row value expression>, page 296,
++    - SQL:2003, Part 2, section 6.3 <value expression primary>, page 174,
++    - SQL:2003, Part 2, section 7.15 <subquery>, page 370,
++    - SQL:2003 Feature F561, "Full value expressions".
++
++    The exception in SQL:2003 Note 184 means:
++    Item_singlerow_subselect, which corresponds to a <scalar subquery>,
++    should be re-interpreted as an Item_in_subselect, which corresponds
++    to a <table subquery> when used inside an <in predicate>.
++
++    Our reading of Note 184 is reccursive, so that all:
++    - IN (( <subquery> ))
++    - IN ((( <subquery> )))
++    - IN '('^N <subquery> ')'^N
++    - etc
++    should be interpreted as a <table subquery>, no matter how deep in the
++    expression the <subquery> is.
++  */
++
++  Item *result;
++
++  DBUG_ENTER("handle_sql2003_note184_exception");
++
++  if (expr->type() == Item::SUBSELECT_ITEM)
++  {
++    Item_subselect *expr2 = (Item_subselect*) expr;
++
++    if (expr2->substype() == Item_subselect::SINGLEROW_SUBS)
++    {
++      Item_singlerow_subselect *expr3 = (Item_singlerow_subselect*) expr2;
++      st_select_lex *subselect;
++
++      /*
++        Implement the mandated change, by altering the semantic tree:
++          left IN Item_singlerow_subselect(subselect)
++        is modified to
++          left IN (subselect)
++        which is represented as
++          Item_in_subselect(left, subselect)
++      */
++      subselect= expr3->invalidate_and_restore_select_lex();
++      result= new (thd->mem_root) Item_in_subselect(left, subselect);
++
++      if (! equal)
++        result = negate_expression(thd, result);
++
++      DBUG_RETURN(result);
++    }
++  }
++
++  if (equal)
++    result= new (thd->mem_root) Item_func_eq(left, expr);
++  else
++    result= new (thd->mem_root) Item_func_ne(left, expr);
++
++  DBUG_RETURN(result);
++}
++
++%}
++%union {
++  int  num;
++  ulong ulong_num;
++  ulonglong ulonglong_number;
++  LEX_STRING lex_str;
++  LEX_STRING *lex_str_ptr;
++  LEX_SYMBOL symbol;
++  Table_ident *table;
++  char *simple_string;
++  Item *item;
++  Item_num *item_num;
++  List<Item> *item_list;
++  List<String> *string_list;
++  String *string;
++  key_part_spec *key_part;
++  TABLE_LIST *table_list;
++  udf_func *udf;
++  LEX_USER *lex_user;
++  struct sys_var_with_base variable;
++  enum enum_var_type var_type;
++  Key::Keytype key_type;
++  enum ha_key_alg key_alg;
++  enum db_type db_type;
++  enum row_type row_type;
++  enum ha_rkey_function ha_rkey_mode;
++  enum enum_tx_isolation tx_isolation;
++  enum Cast_target cast_type;
++  enum Item_udftype udf_type;
++  CHARSET_INFO *charset;
++  thr_lock_type lock_type;
++  interval_type interval, interval_time_st;
++  timestamp_type date_time_type;
++  st_select_lex *select_lex;
++  chooser_compare_func_creator boolfunc2creator;
++  struct sp_cond_type *spcondtype;
++  struct { int vars, conds, hndlrs, curs; } spblock;
++  sp_name *spname;
++  struct st_lex *lex;
++}
++
++%{
++bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
++%}
++
++%pure_parser					/* We have threads */
++/*
++  Currently there are 245 shift/reduce conflicts.
++  We should not introduce new conflicts any more.
++*/
++%expect 245
++
++%token  END_OF_INPUT
++
++%token  ABORT_SYM
++%token  ACTION
++%token  ADD
++%token  ADDDATE_SYM
++%token  AFTER_SYM
++%token  AGAINST
++%token  AGGREGATE_SYM
++%token  ALGORITHM_SYM
++%token  ALL
++%token  ALTER
++%token  ANALYZE_SYM
++%token  AND_AND_SYM
++%token  AND_SYM
++%token  ANY_SYM
++%token  AS
++%token  ASC
++%token  ASCII_SYM
++%token  ASENSITIVE_SYM
++%token  ATAN
++%token  AUTO_INC
++%token  AVG_ROW_LENGTH
++%token  AVG_SYM
++%token  BACKUP_SYM
++%token  BEFORE_SYM
++%token  BEGIN_SYM
++%token  BENCHMARK_SYM
++%token  BERKELEY_DB_SYM
++%token  BIGINT
++%token  BINARY
++%token  BINLOG_SYM
++%token  BIN_NUM
++%token  BIT_AND
++%token  BIT_OR
++%token  BIT_SYM
++%token  BIT_XOR
++%token  BLOB_SYM
++%token  BLOCK_SYM
++%token  BOOLEAN_SYM
++%token  BOOL_SYM
++%token  BOTH
++%token  BTREE_SYM
++%token  BY
++%token  BYTE_SYM
++%token  CACHE_SYM
++%token  CALL_SYM
++%token  CASCADE
++%token  CASCADED
++%token  CAST_SYM
++%token  CHAIN_SYM
++%token  CHANGE
++%token  CHANGED
++%token  CHARSET
++%token  CHAR_SYM
++%token  CHECKSUM_SYM
++%token  CHECK_SYM
++%token  CIPHER_SYM
++%token  CLIENT_SYM
++%token  CLOSE_SYM
++%token  COALESCE
++%token  CODE_SYM
++%token  COLLATE_SYM
++%token  COLLATION_SYM
++%token  COLUMNS
++%token  COLUMN_SYM
++%token  COMMENT_SYM
++%token  COMMITTED_SYM
++%token  COMMIT_SYM
++%token  COMPACT_SYM
++%token  COMPRESSED_SYM
++%token  CONCAT
++%token  CONCAT_WS
++%token  CONCURRENT
++%token  CONDITION_SYM
++%token  CONNECTION_SYM
++%token  CONSISTENT_SYM
++%token  CONSTRAINT
++%token  CONTAINS_SYM
++%token  CONTEXT_SYM
++%token  CONTINUE_SYM
++%token  CONVERT_SYM
++%token  CONVERT_TZ_SYM
++%token  COUNT_SYM
++%token  CPU_SYM
++%token  CREATE
++%token  CROSS
++%token  CUBE_SYM
++%token  CURDATE
++%token  CURRENT_USER
++%token  CURSOR_SYM
++%token  CURTIME
++%token  DATABASE
++%token  DATABASES
++%token  DATA_SYM
++%token  DATETIME
++%token  DATE_ADD_INTERVAL
++%token  DATE_SUB_INTERVAL
++%token  DATE_SYM
++%token  DAY_HOUR_SYM
++%token  DAY_MICROSECOND_SYM
++%token  DAY_MINUTE_SYM
++%token  DAY_SECOND_SYM
++%token  DAY_SYM
++%token  DEALLOCATE_SYM
++%token  DECIMAL_NUM
++%token  DECIMAL_SYM
++%token  DECLARE_SYM
++%token  DECODE_SYM
++%token  DEFAULT
++%token  DEFINER_SYM
++%token  DELAYED_SYM
++%token  DELAY_KEY_WRITE_SYM
++%token  DELETE_SYM
++%token  DESC
++%token  DESCRIBE
++%token  DES_DECRYPT_SYM
++%token  DES_ENCRYPT_SYM
++%token  DES_KEY_FILE
++%token  DETERMINISTIC_SYM
++%token  DIRECTORY_SYM
++%token  DISABLE_SYM
++%token  DISCARD
++%token  DISTINCT
++%token  DIV_SYM
++%token  DOUBLE_SYM
++%token  DO_SYM
++%token  DROP
++%token  DUAL_SYM
++%token  DUMPFILE
++%token  DUPLICATE_SYM
++%token  DYNAMIC_SYM
++%token  EACH_SYM
++%token  ELSEIF_SYM
++%token  ELT_FUNC
++%token  ENABLE_SYM
++%token  ENCLOSED
++%token  ENCODE_SYM
++%token  ENCRYPT
++%token  END
++%token  ENGINES_SYM
++%token  ENGINE_SYM
++%token  ENUM
++%token  EQ
++%token  EQUAL_SYM
++%token  ERRORS
++%token  ESCAPED
++%token  ESCAPE_SYM
++%token  EVENTS_SYM
++%token  EXECUTE_SYM
++%token  EXISTS
++%token  EXIT_SYM
++%token  EXPANSION_SYM
++%token  EXPORT_SET
++%token  EXTENDED_SYM
++%token  EXTRACT_SYM
++%token  FALSE_SYM
++%token  FAST_SYM
++%token  FAULTS_SYM
++%token  FETCH_SYM
++%token  FIELD_FUNC
++%token  FILE_SYM
++%token  FIRST_SYM
++%token  FIXED_SYM
++%token  FLOAT_NUM
++%token  FLOAT_SYM
++%token  FLUSH_SYM
++%token  FORCE_SYM
++%token  FOREIGN
++%token  FORMAT_SYM
++%token  FOR_SYM
++%token  FOUND_SYM
++%token  FRAC_SECOND_SYM
++%token  FROM
++%token  FROM_UNIXTIME
++%token  FULL
++%token  FULLTEXT_SYM
++%token  FUNCTION_SYM
++%token  FUNC_ARG0
++%token  FUNC_ARG1
++%token  FUNC_ARG2
++%token  FUNC_ARG3
++%token  GE
++%token  GEOMCOLLFROMTEXT
++%token  GEOMETRYCOLLECTION
++%token  GEOMETRY_SYM
++%token  GEOMFROMTEXT
++%token  GEOMFROMWKB
++%token  GET_FORMAT
++%token  GLOBAL_SYM
++%token  GRANT
++%token  GRANTS
++%token  GREATEST_SYM
++%token  GROUP
++%token  GROUP_CONCAT_SYM
++%token  GROUP_UNIQUE_USERS
++%token  GT_SYM
++%token  HANDLER_SYM
++%token  HASH_SYM
++%token  HAVING
++%token  HELP_SYM
++%token  HEX_NUM
++%token  HIGH_PRIORITY
++%token  HOSTS_SYM
++%token  HOUR_MICROSECOND_SYM
++%token  HOUR_MINUTE_SYM
++%token  HOUR_SECOND_SYM
++%token  HOUR_SYM
++%token  IDENT
++%token  IDENTIFIED_SYM
++%token  IDENT_QUOTED
++%token  IF
++%token  IGNORE_SYM
++%token  IMPORT
++%token  INDEXES
++%token  INDEX_SYM
++%token  INFILE
++%token  INNER_SYM
++%token  INNOBASE_SYM
++%token  INOUT_SYM
++%token  INSENSITIVE_SYM
++%token  INSERT
++%token  INSERT_METHOD
++%token  INTERVAL_SYM
++%token  INTO
++%token  INT_SYM
++%token  INVOKER_SYM
++%token  IN_SYM
++%token  IO_SYM
++%token  IPC_SYM
++%token  IS
++%token  ISOLATION
++%token  ISSUER_SYM
++%token  ITERATE_SYM
++%token  JOIN_SYM
++%token  KEYS
++%token  KEY_SYM
++%token  KILL_SYM
++%token  LABEL_SYM
++%token  LANGUAGE_SYM
++%token  LAST_INSERT_ID
++%token  LAST_SYM
++%token  LE
++%token  LEADING
++%token  LEAST_SYM
++%token  LEAVES
++%token  LEAVE_SYM
++%token  LEFT
++%token  LEVEL_SYM
++%token  LEX_HOSTNAME
++%token  LIKE
++%token  LIMIT
++%token  LINEFROMTEXT
++%token  LINES
++%token  LINESTRING
++%token  LOAD
++%token  LOCAL_SYM
++%token  LOCATE
++%token  LOCATOR_SYM
++%token  LOCKS_SYM
++%token  LOCK_SYM
++%token  LOGS_SYM
++%token  LOG_SYM
++%token  LONGBLOB
++%token  LONGTEXT
++%token  LONG_NUM
++%token  LONG_SYM
++%token  LOOP_SYM
++%token  LOW_PRIORITY
++%token  LT
++%token  MAKE_SET_SYM
++%token  MASTER_CONNECT_RETRY_SYM
++%token  MASTER_HOST_SYM
++%token  MASTER_LOG_FILE_SYM
++%token  MASTER_LOG_POS_SYM
++%token  MASTER_PASSWORD_SYM
++%token  MASTER_PORT_SYM
++%token  MASTER_POS_WAIT
++%token  MASTER_SERVER_ID_SYM
++%token  MASTER_SSL_CAPATH_SYM
++%token  MASTER_SSL_CA_SYM
++%token  MASTER_SSL_CERT_SYM
++%token  MASTER_SSL_CIPHER_SYM
++%token  MASTER_SSL_KEY_SYM
++%token  MASTER_SSL_SYM
++%token  MASTER_SYM
++%token  MASTER_USER_SYM
++%token  MATCH
++%token  MAX_CONNECTIONS_PER_HOUR
++%token  MAX_QUERIES_PER_HOUR
++%token  MAX_ROWS
++%token  MAX_SYM
++%token  MAX_UPDATES_PER_HOUR
++%token  MAX_USER_CONNECTIONS_SYM
++%token  MEDIUMBLOB
++%token  MEDIUMINT
++%token  MEDIUMTEXT
++%token  MEDIUM_SYM
++%token  MEMORY_SYM
++%token  MERGE_SYM
++%token  MICROSECOND_SYM
++%token  MIGRATE_SYM
++%token  MINUTE_MICROSECOND_SYM
++%token  MINUTE_SECOND_SYM
++%token  MINUTE_SYM
++%token  MIN_ROWS
++%token  MIN_SYM
++%token  MLINEFROMTEXT
++%token  MODE_SYM
++%token  MODIFIES_SYM
++%token  MODIFY_SYM
++%token  MOD_SYM
++%token  MONTH_SYM
++%token  MPOINTFROMTEXT
++%token  MPOLYFROMTEXT
++%token  MULTILINESTRING
++%token  MULTIPOINT
++%token  MULTIPOLYGON
++%token  MUTEX_SYM
++%token  NAMES_SYM
++%token  NAME_SYM
++%token  NATIONAL_SYM
++%token  NATURAL
++%token  NCHAR_STRING
++%token  NCHAR_SYM
++%token  NDBCLUSTER_SYM
++%token  NE
++%token  NEW_SYM
++%token  NEXT_SYM
++%token  NONE_SYM
++%token  NOT2_SYM
++%token  NOT_SYM
++%token  NOW_SYM
++%token  NO_SYM
++%token  NO_WRITE_TO_BINLOG
++%token  NULL_SYM
++%token  NUM
++%token  NUMERIC_SYM
++%token  NVARCHAR_SYM
++%token  OFFSET_SYM
++%token  OJ_SYM
++%token  OLD_PASSWORD
++%token  ON
++%token  ONE_SHOT_SYM
++%token  ONE_SYM
++%token  OPEN_SYM
++%token  OPTIMIZE
++%token  OPTION
++%token  OPTIONALLY
++%token  OR2_SYM
++%token  ORDER_SYM
++%token  OR_OR_SYM
++%token  OR_SYM
++%token  OUTER
++%token  OUTFILE
++%token  OUT_SYM
++%token  PACK_KEYS_SYM
++%token  PAGE_SYM
++%token  PARTIAL
++%token  PASSWORD
++%token  PARAM_MARKER
++%token  PHASE_SYM
++%token  POINTFROMTEXT
++%token  POINT_SYM
++%token  POLYFROMTEXT
++%token  POLYGON
++%token  POSITION_SYM
++%token  PRECISION
++%token  PREPARE_SYM
++%token  PREV_SYM
++%token  PRIMARY_SYM
++%token  PRIVILEGES
++%token  PROCEDURE
++%token  PROCESS
++%token  PROCESSLIST_SYM
++%token  PROFILE_SYM
++%token  PROFILES_SYM
++%token  PURGE
++%token  QUARTER_SYM
++%token  QUERY_SYM
++%token  QUICK
++%token  RAID_0_SYM
++%token  RAID_CHUNKS
++%token  RAID_CHUNKSIZE
++%token  RAID_STRIPED_SYM
++%token  RAID_TYPE
++%token  RAND
++%token  READS_SYM
++%token  READ_SYM
++%token  REAL
++%token  RECOVER_SYM
++%token  REDUNDANT_SYM
++%token  REFERENCES
++%token  REGEXP
++%token  RELAY_LOG_FILE_SYM
++%token  RELAY_LOG_POS_SYM
++%token  RELAY_THREAD
++%token  RELEASE_SYM
++%token  RELOAD
++%token  RENAME
++%token  REPAIR
++%token  REPEATABLE_SYM
++%token  REPEAT_SYM
++%token  REPLACE
++%token  REPLICATION
++%token  REQUIRE_SYM
++%token  RESET_SYM
++%token  RESOURCES
++%token  RESTORE_SYM
++%token  RESTRICT
++%token  RESUME_SYM
++%token  RETURNS_SYM
++%token  RETURN_SYM
++%token  REVOKE
++%token  RIGHT
++%token  ROLLBACK_SYM
++%token  ROLLUP_SYM
++%token  ROUND
++%token  ROUTINE_SYM
++%token  ROWS_SYM
++%token  ROW_COUNT_SYM
++%token  ROW_FORMAT_SYM
++%token  ROW_SYM
++%token  RTREE_SYM
++%token  SAVEPOINT_SYM
++%token  SECOND_MICROSECOND_SYM
++%token  SECOND_SYM
++%token  SECURITY_SYM
++%token  SELECT_SYM
++%token  SENSITIVE_SYM
++%token  SEPARATOR_SYM
++%token  SERIALIZABLE_SYM
++%token  SERIAL_SYM
++%token  SESSION_SYM
++%token  SET
++%token  SET_VAR
++%token  SHARE_SYM
++%token  SHIFT_LEFT
++%token  SHIFT_RIGHT
++%token  SHOW
++%token  SHUTDOWN
++%token  SIGNED_SYM
++%token  SIMPLE_SYM
++%token  SLAVE
++%token  SMALLINT
++%token  SNAPSHOT_SYM
++%token  SOUNDS_SYM
++%token  SOURCE_SYM
++%token  SPATIAL_SYM
++%token  SPECIFIC_SYM
++%token  SQLEXCEPTION_SYM
++%token  SQLSTATE_SYM
++%token  SQLWARNING_SYM
++%token  SQL_BIG_RESULT
++%token  SQL_BUFFER_RESULT
++%token  SQL_CACHE_SYM
++%token  SQL_CALC_FOUND_ROWS
++%token  SQL_NO_CACHE_SYM
++%token  SQL_SMALL_RESULT
++%token  SQL_SYM
++%token  SQL_THREAD
++%token  SSL_SYM
++%token  STARTING
++%token  START_SYM
++%token  STATUS_SYM
++%token  STD_SYM
++%token  STDDEV_SAMP_SYM
++%token  STOP_SYM
++%token  STORAGE_SYM
++%token  STRAIGHT_JOIN
++%token  STRING_SYM
++%token  SUBDATE_SYM
++%token  SUBJECT_SYM
++%token  SUBSTRING
++%token  SUBSTRING_INDEX
++%token  SUM_SYM
++%token  SUPER_SYM
++%token  SUSPEND_SYM
++%token  SWAPS_SYM
++%token  SWITCHES_SYM
++%token  SYSDATE
++%token  TABLES
++%token  TABLESPACE
++%token  TABLE_SYM
++%token  TEMPORARY
++%token  TEMPTABLE_SYM
++%token  TERMINATED
++%token  TEXT_STRING
++%token  TEXT_SYM
++%token  TIMESTAMP
++%token  TIMESTAMP_ADD
++%token  TIMESTAMP_DIFF
++%token  TIME_SYM
++%token  TINYBLOB
++%token  TINYINT
++%token  TINYTEXT
++%token  TO_SYM
++%token  TRAILING
++%token  TRANSACTION_SYM
++%token  TRIGGER_SYM
++%token  TRIGGERS_SYM
++%token  TRIM
++%token  TRUE_SYM
++%token  TRUNCATE_SYM
++%token  TYPES_SYM
++%token  TYPE_SYM
++%token  UDF_RETURNS_SYM
++%token  UDF_SONAME_SYM
++%token  ULONGLONG_NUM
++%token  UNCOMMITTED_SYM
++%token  UNDEFINED_SYM
++%token  UNDERSCORE_CHARSET
++%token  UNDO_SYM
++%token  UNICODE_SYM
++%token  UNION_SYM
++%token  UNIQUE_SYM
++%token  UNIQUE_USERS
++%token  UNIX_TIMESTAMP
++%token  UNKNOWN_SYM
++%token  UNLOCK_SYM
++%token  UNSIGNED
++%token  UNTIL_SYM
++%token  UPDATE_SYM
++%token  UPGRADE_SYM
++%token  USAGE
++%token  USER
++%token  USE_FRM
++%token  USE_SYM
++%token  USING
++%token  UTC_DATE_SYM
++%token  UTC_TIMESTAMP_SYM
++%token  UTC_TIME_SYM
++%token  VAR_SAMP_SYM
++%token  VALUES
++%token  VALUE_SYM
++%token  VARBINARY
++%token  VARCHAR
++%token  VARIABLES
++%token  VARIANCE_SYM
++%token  VARYING
++%token  VIEW_SYM
++%token  WARNINGS
++%token  WEEK_SYM
++%token  WHEN_SYM
++%token  WHERE
++%token  WHILE_SYM
++%token  WITH
++%token  WORK_SYM
++%token  WRITE_SYM
++%token  X509_SYM
++%token  XA_SYM
++%token  XOR
++%token  YEARWEEK
++%token  YEAR_MONTH_SYM
++%token  YEAR_SYM
++%token  ZEROFILL
++
++%left   JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT
++/* A dummy token to force the priority of table_ref production in a join. */
++%left   TABLE_REF_PRIORITY
++%left   SET_VAR
++%left	OR_OR_SYM OR_SYM OR2_SYM
++%left	XOR
++%left	AND_SYM AND_AND_SYM
++%left	BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE
++%left	EQ EQUAL_SYM GE GT_SYM LE LT NE IS LIKE REGEXP IN_SYM
++%left	'|'
++%left	'&'
++%left	SHIFT_LEFT SHIFT_RIGHT
++%left	'-' '+'
++%left	'*' '/' '%' DIV_SYM MOD_SYM
++%left   '^'
++%left	NEG '~'
++%right	NOT_SYM NOT2_SYM
++%right	BINARY COLLATE_SYM
++%left   INTERVAL_SYM
++
++%type <lex_str>
++        IDENT IDENT_QUOTED TEXT_STRING DECIMAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM
++	LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
++        UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
++	NCHAR_STRING opt_component key_cache_name
++        sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem
++
++%type <lex_str_ptr>
++	opt_table_alias
++
++%type <table>
++	table_ident table_ident_nodb references xid
++
++%type <simple_string>
++	remember_name remember_end opt_ident opt_db text_or_password
++	opt_constraint constraint ident_or_empty
++
++%type <string>
++	text_string opt_gconcat_separator
++
++%type <num>
++	type int_type real_type order_dir lock_option
++	udf_type if_exists opt_local opt_table_options table_options
++        table_option opt_if_not_exists opt_no_write_to_binlog
++        delete_option opt_temporary all_or_any opt_distinct
++        opt_ignore_leaves fulltext_options spatial_type union_option
++        start_transaction_opts opt_chain opt_release
++        union_opt select_derived_init option_type2
++
++%type <ulong_num>
++	ulong_num raid_types merge_insert_types
++
++%type <ulonglong_number>
++	ulonglong_num
++
++%type <lock_type>
++	replace_lock_option opt_low_priority insert_lock_option load_data_lock
++
++%type <item>
++	literal text_literal insert_ident order_ident
++	simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
++	variable variable_aux
++        bool_pri
++	predicate bit_expr
++	table_wild simple_expr udf_expr
++	expr_or_default set_expr_or_default interval_expr
++	param_marker geometry_function
++	signed_literal now_or_signed_literal opt_escape
++	sp_opt_default
++	simple_ident_nospvar simple_ident_q
++        field_or_var limit_option
++
++%type <item_num>
++	NUM_literal
++
++%type <item_list>
++	expr_list udf_expr_list udf_expr_list2 when_list
++	ident_list ident_list_arg opt_expr_list
++
++%type <var_type>
++        option_type opt_var_type opt_var_ident_type
++
++%type <key_type>
++	key_type opt_unique_or_fulltext constraint_key_type
++
++%type <key_alg>
++	key_alg opt_btree_or_rtree
++
++%type <string_list>
++	key_usage_list using_list
++
++%type <key_part>
++	key_part
++
++%type <table_list>
++	join_table_list  join_table
++        table_factor table_ref
++        select_derived derived_table_list
++
++%type <date_time_type> date_time_type;
++%type <interval> interval
++
++%type <interval_time_st> interval_time_st
++
++%type <db_type> storage_engines
++
++%type <row_type> row_types
++
++%type <tx_isolation> isolation_types
++
++%type <ha_rkey_mode> handler_rkey_mode
++
++%type <cast_type> cast_type
++
++%type <udf_type> udf_func_type
++
++%type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp
++
++%type <lex_user> user grant_user
++
++%type <charset>
++	opt_collate
++	charset_name
++	charset_name_or_default
++	old_or_new_charset_name
++	old_or_new_charset_name_or_default
++	collation_name
++	collation_name_or_default
++	opt_load_data_charset
++
++%type <variable> internal_variable_name
++
++%type <select_lex> subselect subselect_init
++	get_select_lex
++
++%type <boolfunc2creator> comp_op
++
++%type <NONE>
++	query verb_clause create change select do drop insert replace insert2
++	insert_values update delete truncate rename
++	show describe load alter optimize keycache preload flush
++	reset purge begin commit rollback savepoint release
++	slave master_def master_defs master_file_def slave_until_opts
++	repair restore backup analyze check start checksum
++	field_list field_list_item field_spec kill column_def key_def
++	keycache_list assign_to_keycache preload_list preload_keys
++	select_item_list select_item values_list no_braces
++	opt_limit_clause delete_limit_clause fields opt_values values
++	procedure_list procedure_list2 procedure_item
++	expr_list2 udf_expr_list3 handler
++	opt_precision opt_ignore opt_column opt_restrict
++	grant revoke set lock unlock string_list field_options field_option
++	field_opt_list opt_binary table_lock_list table_lock
++	ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use
++	opt_delete_options opt_delete_option varchar nchar nvarchar
++	opt_outer table_list table_name table_alias_ref_list table_alias_ref
++	opt_option opt_place
++	opt_attribute opt_attribute_list attribute column_list column_list_id
++	opt_column_list grant_privileges grant_ident grant_list grant_option
++	object_privilege object_privilege_list user_list rename_list
++	clear_privileges flush_options flush_option
++	equal optional_braces opt_key_definition key_usage_list2
++	opt_mi_check_type opt_to mi_check_types normal_join
++	table_to_table_list table_to_table opt_table_list opt_as
++	handler_rkey_function handler_read_or_scan
++	single_multi table_wild_list table_wild_one opt_wild
++	union_clause union_list
++	precision subselect_start opt_and charset
++	subselect_end select_var_list select_var_list_init help opt_len
++	opt_extended_describe
++        prepare prepare_src execute deallocate
++	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
++        definer view_replace_or_algorithm view_replace view_algorithm_opt
++        view_algorithm view_or_trigger_or_sp view_or_trigger_or_sp_tail
++	view_suid view_tail view_list_opt view_list view_select
++	view_check_option trigger_tail sp_tail
++        case_stmt_specification simple_case_stmt searched_case_stmt
++END_OF_INPUT
++
++%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
++%type <num>  sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list
++%type <spcondtype> sp_cond sp_hcond
++%type <spblock> sp_decls sp_decl
++%type <lex> sp_cursor_stmt
++%type <spname> sp_name
++
++%type <NONE>
++	'-' '+' '*' '/' '%' '(' ')'
++	',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
++	THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM
++%%
++
++
++query:
++	END_OF_INPUT
++	{
++	   THD *thd= YYTHD;
++	   if (!thd->bootstrap &&
++	      (!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
++	   {
++	     my_message(ER_EMPTY_QUERY, ER(ER_EMPTY_QUERY), MYF(0));
++	     MYSQL_YYABORT;
++	   }
++	   else
++	   {
++	     thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
++	   }
++	}
++	| verb_clause END_OF_INPUT {};
++
++verb_clause:
++	  statement
++	| begin
++	;
++
++/* Verb clauses, except begin */
++statement:
++	  alter
++	| analyze
++	| backup
++	| call
++	| change
++	| check
++	| checksum
++	| commit
++	| create
++        | deallocate
++	| delete
++	| describe
++	| do
++	| drop
++        | execute
++	| flush
++	| grant
++	| handler
++	| help
++	| insert
++	| kill
++	| load
++	| lock
++	| optimize
++        | keycache
++	| preload
++        | prepare
++	| purge
++	| release
++	| rename
++	| repair
++	| replace
++	| reset
++	| restore
++	| revoke
++	| rollback
++	| savepoint
++	| select
++	| set
++	| show
++	| slave
++	| start
++	| truncate
++	| unlock
++	| update
++	| use
++	| xa
++        ;
++
++deallocate:
++        deallocate_or_drop PREPARE_SYM ident
++        {
++          THD *thd=YYTHD;
++          LEX *lex= thd->lex;
++          lex->sql_command= SQLCOM_DEALLOCATE_PREPARE;
++          lex->prepared_stmt_name= $3;
++        };
++
++deallocate_or_drop:
++	DEALLOCATE_SYM |
++	DROP
++	;
++
++
++prepare:
++        PREPARE_SYM ident FROM prepare_src
++        {
++          THD *thd=YYTHD;
++          LEX *lex= thd->lex;
++          lex->sql_command= SQLCOM_PREPARE;
++          lex->prepared_stmt_name= $2;
++        };
++
++prepare_src:
++        TEXT_STRING_sys
++        {
++          THD *thd=YYTHD;
++          LEX *lex= thd->lex;
++          lex->prepared_stmt_code= $1;
++          lex->prepared_stmt_code_is_varref= FALSE;
++        }
++        | '@' ident_or_text
++        {
++          THD *thd=YYTHD;
++          LEX *lex= thd->lex;
++          lex->prepared_stmt_code= $2;
++          lex->prepared_stmt_code_is_varref= TRUE;
++        };
++
++execute:
++        EXECUTE_SYM ident
++        {
++          THD *thd=YYTHD;
++          LEX *lex= thd->lex;
++          lex->sql_command= SQLCOM_EXECUTE;
++          lex->prepared_stmt_name= $2;
++        }
++        execute_using
++        {}
++        ;
++
++execute_using:
++        /* nothing */
++        | USING execute_var_list
++        ;
++
++execute_var_list:
++        execute_var_list ',' execute_var_ident
++        | execute_var_ident
++        ;
++
++execute_var_ident: '@' ident_or_text
++        {
++          LEX *lex=Lex;
++          LEX_STRING *lexstr= (LEX_STRING*)sql_memdup(&$2, sizeof(LEX_STRING));
++          if (!lexstr || lex->prepared_stmt_params.push_back(lexstr))
++              MYSQL_YYABORT;
++        }
++        ;
++
++/* help */
++
++help:
++       HELP_SYM
++       {
++         if (Lex->sphead)
++         {
++           my_error(ER_SP_BADSTATEMENT, MYF(0), "HELP");
++           MYSQL_YYABORT;
++         }
++       }
++       ident_or_text
++       {
++	  LEX *lex= Lex;
++	  lex->sql_command= SQLCOM_HELP;
++	  lex->help_arg= $3.str;
++       };
++
++/* change master */
++
++change:
++       CHANGE MASTER_SYM TO_SYM
++        {
++	  LEX *lex = Lex;
++	  lex->sql_command = SQLCOM_CHANGE_MASTER;
++	  bzero((char*) &lex->mi, sizeof(lex->mi));
++        }
++       master_defs
++	{}
++       ;
++
++master_defs:
++       master_def
++       | master_defs ',' master_def;
++
++master_def:
++       MASTER_HOST_SYM EQ TEXT_STRING_sys
++       {
++	 Lex->mi.host = $3.str;
++       }
++       |
++       MASTER_USER_SYM EQ TEXT_STRING_sys
++       {
++	 Lex->mi.user = $3.str;
++       }
++       |
++       MASTER_PASSWORD_SYM EQ TEXT_STRING_sys
++       {
++	 Lex->mi.password = $3.str;
++       }
++       |
++       MASTER_PORT_SYM EQ ulong_num
++       {
++	 Lex->mi.port = $3;
++       }
++       |
++       MASTER_CONNECT_RETRY_SYM EQ ulong_num
++       {
++	 Lex->mi.connect_retry = $3;
++       }
++       | MASTER_SSL_SYM EQ ulong_num
++         {
++           Lex->mi.ssl= $3 ? 
++               LEX_MASTER_INFO::SSL_ENABLE : LEX_MASTER_INFO::SSL_DISABLE;
++         }
++       | MASTER_SSL_CA_SYM EQ TEXT_STRING_sys
++         {
++           Lex->mi.ssl_ca= $3.str;
++         }
++       | MASTER_SSL_CAPATH_SYM EQ TEXT_STRING_sys
++         {
++           Lex->mi.ssl_capath= $3.str;
++         }
++       | MASTER_SSL_CERT_SYM EQ TEXT_STRING_sys
++         {
++           Lex->mi.ssl_cert= $3.str;
++         }
++       | MASTER_SSL_CIPHER_SYM EQ TEXT_STRING_sys
++         {
++           Lex->mi.ssl_cipher= $3.str;
++         }
++       | MASTER_SSL_KEY_SYM EQ TEXT_STRING_sys
++         {
++           Lex->mi.ssl_key= $3.str;
++	 }
++       |
++         master_file_def
++       ;
++
++master_file_def:
++       MASTER_LOG_FILE_SYM EQ TEXT_STRING_sys
++       {
++	 Lex->mi.log_file_name = $3.str;
++       }
++       | MASTER_LOG_POS_SYM EQ ulonglong_num
++         {
++           Lex->mi.pos = $3;
++           /* 
++              If the user specified a value < BIN_LOG_HEADER_SIZE, adjust it
++              instead of causing subsequent errors. 
++              We need to do it in this file, because only there we know that 
++              MASTER_LOG_POS has been explicitely specified. On the contrary
++              in change_master() (sql_repl.cc) we cannot distinguish between 0
++              (MASTER_LOG_POS explicitely specified as 0) and 0 (unspecified),
++              whereas we want to distinguish (specified 0 means "read the binlog
++              from 0" (4 in fact), unspecified means "don't change the position
++              (keep the preceding value)").
++           */
++           Lex->mi.pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.pos);
++         }
++       | RELAY_LOG_FILE_SYM EQ TEXT_STRING_sys
++         {
++           Lex->mi.relay_log_name = $3.str;
++         }
++       | RELAY_LOG_POS_SYM EQ ulong_num
++         {
++           Lex->mi.relay_log_pos = $3;
++           /* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
++           Lex->mi.relay_log_pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos);
++         }
++       ;
++
++/* create a table */
++
++create:
++	CREATE opt_table_options TABLE_SYM opt_if_not_exists table_ident
++	{
++	  THD *thd= YYTHD;
++	  LEX *lex=Lex;
++	  lex->sql_command= SQLCOM_CREATE_TABLE;
++	  if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
++						 TL_OPTION_UPDATING,
++						 TL_WRITE))
++	    MYSQL_YYABORT;
++          lex->alter_info.reset();
++	  lex->col_list.empty();
++	  lex->change=NullS;
++	  bzero((char*) &lex->create_info,sizeof(lex->create_info));
++	  lex->create_info.options=$2 | $4;
++	  lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type;
++	  lex->create_info.default_table_charset= NULL;
++	}
++	create2
++	  { Lex->current_select= &Lex->select_lex; }
++	| CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident
++	  {
++	    LEX *lex=Lex;
++	    lex->sql_command= SQLCOM_CREATE_INDEX;
++	    if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
++							TL_OPTION_UPDATING))
++	      MYSQL_YYABORT;
++            lex->alter_info.reset();
++            lex->alter_info.flags= ALTER_ADD_INDEX;
++	    lex->col_list.empty();
++	    lex->change=NullS;
++	  }
++	   '(' key_list ')'
++	  {
++	    LEX *lex=Lex;
++            Key *key= new Key($2, $4.str, $5, 0, lex->col_list);
++
++            lex->alter_info.key_list.push_back(key);
++	    lex->col_list.empty();
++	  }
++	| CREATE DATABASE opt_if_not_exists ident
++	  {
++             Lex->create_info.default_table_charset= NULL;
++             Lex->create_info.used_fields= 0;
++          }
++	  opt_create_database_options
++	  {
++	    LEX *lex=Lex;
++	    lex->sql_command=SQLCOM_CREATE_DB;
++	    lex->name=$4.str;
++            lex->create_info.options=$3;
++	  }
++	| CREATE
++	  {
++            Lex->create_view_mode= VIEW_CREATE_NEW;
++            Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
++            Lex->create_view_suid= TRUE;
++	  }
++	  view_or_trigger_or_sp
++	  {}
++	| CREATE USER clear_privileges grant_list
++	  {
++	    Lex->sql_command = SQLCOM_CREATE_USER;
++          }
++	;
++
++clear_privileges:
++        /* Nothing */
++        {
++          LEX *lex=Lex;
++          lex->users_list.empty();
++          lex->columns.empty();
++          lex->grant= lex->grant_tot_col= 0;
++	  lex->all_privileges= 0;
++          lex->select_lex.db= 0;
++          lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
++          lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
++          bzero((char *)&(lex->mqh),sizeof(lex->mqh));
++        }
++        ;
++
++sp_name:
++	  ident '.' ident
++	  {
++            if (!$1.str || check_db_name($1.str))
++            {
++	      my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
++	      MYSQL_YYABORT;
++	    }
++	    if (check_routine_name($3))
++            {
++	      my_error(ER_SP_WRONG_NAME, MYF(0), $3.str);
++	      MYSQL_YYABORT;
++	    }
++	    $$= new sp_name($1, $3, true);
++	    $$->init_qname(YYTHD);
++	  }
++	| ident
++	  {
++            LEX *lex= Lex;
++            LEX_STRING db;
++	    if (check_routine_name($1))
++            {
++	      my_error(ER_SP_WRONG_NAME, MYF(0), $1.str);
++	      MYSQL_YYABORT;
++	    }
++            if (lex->copy_db_to(&db.str, &db.length))
++              MYSQL_YYABORT;
++	    $$= new sp_name(db, $1, false);
++            if ($$)
++	      $$->init_qname(YYTHD);
++	  }
++	;
++
++create_function_tail:
++	  RETURNS_SYM udf_type UDF_SONAME_SYM TEXT_STRING_sys
++	  {
++	    LEX *lex=Lex;
++            if (lex->definer != NULL)
++            {
++              /*
++                 DEFINER is a concept meaningful when interpreting SQL code.
++                 UDF functions are compiled.
++                 Using DEFINER with UDF has therefore no semantic,
++                 and is considered a parsing error.
++              */
++	      my_error(ER_WRONG_USAGE, MYF(0), "SONAME", "DEFINER");
++              MYSQL_YYABORT;
++            }
++	    lex->sql_command = SQLCOM_CREATE_FUNCTION;
++	    lex->udf.name = lex->spname->m_name;
++	    lex->udf.returns=(Item_result) $2;
++	    lex->udf.dl=$4.str;
++	  }
++	| '('
++	  {
++            THD *thd= YYTHD;
++	    LEX *lex= thd->lex;
++            Lex_input_stream *lip= thd->m_lip;
++	    sp_head *sp;
++
++            /* 
++              First check if AGGREGATE was used, in that case it's a
++              syntax error.
++            */
++            if (lex->udf.type == UDFTYPE_AGGREGATE)
++            {
++              my_error(ER_SP_NO_AGGREGATE, MYF(0));
++              MYSQL_YYABORT;
++            }
++
++	    if (lex->sphead)
++	    {
++	      my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
++	      MYSQL_YYABORT;
++	    }
++	    /* Order is important here: new - reset - init */
++	    sp= new sp_head();
++	    sp->reset_thd_mem_root(thd);
++	    sp->init(lex);
++            sp->init_sp_name(thd, lex->spname);
++
++	    sp->m_type= TYPE_ENUM_FUNCTION;
++	    lex->sphead= sp;
++	    /*
++	     * 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= thd->client_capabilities & CLIENT_MULTI_QUERIES;
++	    thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
++	    lex->sphead->m_param_begin= lip->tok_start+1;
++	  }
++          sp_fdparam_list ')'
++	  {
++            THD *thd= YYTHD;
++	    LEX *lex= thd->lex;
++            Lex_input_stream *lip= thd->m_lip;
++
++	    lex->sphead->m_param_end= lip->tok_start;
++	  }
++	  RETURNS_SYM
++	  {
++	    LEX *lex= Lex;
++	    lex->charset= NULL;
++	    lex->length= lex->dec= NULL;
++	    lex->interval_list.empty();
++	    lex->type= 0;
++	  }
++	  type
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++
++            if (sp->fill_field_definition(YYTHD, lex,
++                                          (enum enum_field_types) $8,
++                                          &sp->m_return_field_def))
++              MYSQL_YYABORT;
++
++	    bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
++	  }
++	  sp_c_chistics
++	  {
++            THD *thd= YYTHD;
++	    LEX *lex= thd->lex;
++            Lex_input_stream *lip= thd->m_lip;
++
++	    lex->sphead->m_chistics= &lex->sp_chistics;
++	    lex->sphead->m_body_begin= lip->tok_start;
++	  }
++	  sp_proc_stmt
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++
++            if (sp->is_not_allowed_in_function("function"))
++              MYSQL_YYABORT;
++
++	    lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
++	    sp->init_strings(YYTHD, lex);
++            if (!(sp->m_flags & sp_head::HAS_RETURN))
++            {
++              my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
++              MYSQL_YYABORT;
++            }
++	    /* Restore flag if it was cleared above */
++	    if (sp->m_old_cmq)
++	      YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
++	    sp->restore_thd_mem_root(YYTHD);
++	  }
++	;
++
++sp_a_chistics:
++	  /* Empty */ {}
++	| sp_a_chistics sp_chistic {}
++	;
++
++sp_c_chistics:
++	  /* Empty */ {}
++	| sp_c_chistics sp_c_chistic {}
++	;
++
++/* Characteristics for both create and alter */
++sp_chistic:
++	  COMMENT_SYM TEXT_STRING_sys
++	  { Lex->sp_chistics.comment= $2; }
++	| LANGUAGE_SYM SQL_SYM
++	  { /* Just parse it, we only have one language for now. */ }
++	| NO_SYM SQL_SYM
++	  { Lex->sp_chistics.daccess= SP_NO_SQL; }
++	| CONTAINS_SYM SQL_SYM
++	  { Lex->sp_chistics.daccess= SP_CONTAINS_SQL; }
++	| READS_SYM SQL_SYM DATA_SYM
++	  { Lex->sp_chistics.daccess= SP_READS_SQL_DATA; }
++	| MODIFIES_SYM SQL_SYM DATA_SYM
++	  { Lex->sp_chistics.daccess= SP_MODIFIES_SQL_DATA; }
++	| sp_suid
++	  { }
++	;
++
++/* Create characteristics */
++sp_c_chistic:
++	  sp_chistic            { }
++	| DETERMINISTIC_SYM     { Lex->sp_chistics.detistic= TRUE; }
++	| not DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; }
++	;
++
++sp_suid:
++	  SQL_SYM SECURITY_SYM DEFINER_SYM
++	  {
++	    Lex->sp_chistics.suid= SP_IS_SUID;
++	  }
++	| SQL_SYM SECURITY_SYM INVOKER_SYM
++	  {
++	    Lex->sp_chistics.suid= SP_IS_NOT_SUID;
++	  }
++	;
++
++call:
++	  CALL_SYM sp_name
++	  {
++	    LEX *lex = Lex;
++
++	    lex->sql_command= SQLCOM_CALL;
++	    lex->spname= $2;
++	    lex->value_list.empty();
++	    sp_add_used_routine(lex, YYTHD, $2, TYPE_ENUM_PROCEDURE);
++	  }
++          opt_sp_cparam_list {}
++	;
++
++/* CALL parameters */
++opt_sp_cparam_list:
++	  /* Empty */
++	| '(' opt_sp_cparams ')'
++	;
++
++opt_sp_cparams:
++          /* Empty */
++        | sp_cparams
++        ;
++
++sp_cparams:
++	  sp_cparams ',' expr
++	  {
++	    Lex->value_list.push_back($3);
++	  }
++	| expr
++	  {
++	    Lex->value_list.push_back($1);
++	  }
++	;
++
++/* Stored FUNCTION parameter declaration list */
++sp_fdparam_list:
++	  /* Empty */
++	| sp_fdparams
++	;
++
++sp_fdparams:
++	  sp_fdparams ',' sp_fdparam
++	| sp_fdparam
++	;
++
++sp_init_param:
++	  /* Empty */
++	  {
++	    LEX *lex= Lex;
++
++	    lex->length= 0;
++	    lex->dec= 0;
++	    lex->type= 0;
++	  
++	    lex->default_value= 0;
++	    lex->on_update_value= 0;
++	  
++	    lex->comment= null_lex_str;
++	    lex->charset= NULL;
++	  
++	    lex->interval_list.empty();
++	    lex->uint_geom_type= 0;
++	  }
++	;
++
++sp_fdparam:
++	  ident sp_init_param type
++	  {
++	    LEX *lex= Lex;
++	    sp_pcontext *spc= lex->spcont;
++
++	    if (spc->find_variable(&$1, TRUE))
++	    {
++	      my_error(ER_SP_DUP_PARAM, MYF(0), $1.str);
++	      MYSQL_YYABORT;
++	    }
++            sp_variable_t *spvar= spc->push_variable(&$1,
++                                                     (enum enum_field_types)$3,
++                                                     sp_param_in);
++
++            if (lex->sphead->fill_field_definition(YYTHD, lex,
++                                                   (enum enum_field_types) $3,
++                                                   &spvar->field_def))
++            {
++              MYSQL_YYABORT;
++            }
++            spvar->field_def.field_name= spvar->name.str;
++            spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
++	  }
++	;
++
++/* Stored PROCEDURE parameter declaration list */
++sp_pdparam_list:
++	  /* Empty */
++	| sp_pdparams
++	;
++
++sp_pdparams:
++	  sp_pdparams ',' sp_pdparam
++	| sp_pdparam
++	;
++
++sp_pdparam:
++	  sp_opt_inout sp_init_param ident type
++	  {
++	    LEX *lex= Lex;
++	    sp_pcontext *spc= lex->spcont;
++
++	    if (spc->find_variable(&$3, TRUE))
++	    {
++	      my_error(ER_SP_DUP_PARAM, MYF(0), $3.str);
++	      MYSQL_YYABORT;
++	    }
++            sp_variable_t *spvar= spc->push_variable(&$3,
++                                                     (enum enum_field_types)$4,
++                                                     (sp_param_mode_t)$1);
++
++            if (lex->sphead->fill_field_definition(YYTHD, lex,
++                                                   (enum enum_field_types) $4,
++                                                   &spvar->field_def))
++            {
++              MYSQL_YYABORT;
++            }
++            spvar->field_def.field_name= spvar->name.str;
++            spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
++	  }
++	;
++
++sp_opt_inout:
++	  /* Empty */ { $$= sp_param_in; }
++	| IN_SYM      { $$= sp_param_in; }
++	| OUT_SYM     { $$= sp_param_out; }
++	| INOUT_SYM   { $$= sp_param_inout; }
++	;
++
++sp_proc_stmts:
++	  /* Empty */ {}
++	| sp_proc_stmts  sp_proc_stmt ';'
++	;
++
++sp_proc_stmts1:
++	  sp_proc_stmt ';' {}
++	| sp_proc_stmts1  sp_proc_stmt ';'
++	;
++
++sp_decls:
++	  /* Empty */
++	  {
++	    $$.vars= $$.conds= $$.hndlrs= $$.curs= 0;
++	  }
++	| sp_decls sp_decl ';'
++	  {
++	    /* We check for declarations out of (standard) order this way
++	       because letting the grammar rules reflect it caused tricky
++	       shift/reduce conflicts with the wrong result. (And we get
++	       better error handling this way.) */
++	    if (($2.vars || $2.conds) && ($1.curs || $1.hndlrs))
++	    { /* Variable or condition following cursor or handler */
++	      my_message(ER_SP_VARCOND_AFTER_CURSHNDLR,
++                         ER(ER_SP_VARCOND_AFTER_CURSHNDLR), MYF(0));
++	      MYSQL_YYABORT;
++	    }
++	    if ($2.curs && $1.hndlrs)
++	    { /* Cursor following handler */
++	      my_message(ER_SP_CURSOR_AFTER_HANDLER,
++                         ER(ER_SP_CURSOR_AFTER_HANDLER), MYF(0));
++	      MYSQL_YYABORT;
++	    }
++	    $$.vars= $1.vars + $2.vars;
++	    $$.conds= $1.conds + $2.conds;
++	    $$.hndlrs= $1.hndlrs + $2.hndlrs;
++	    $$.curs= $1.curs + $2.curs;
++	  }
++	;
++
++sp_decl:
++          DECLARE_SYM sp_decl_idents
++          {
++            LEX *lex= Lex;
++
++            lex->sphead->reset_lex(YYTHD);
++            lex->spcont->declare_var_boundary($2);
++          }
++          type
++          sp_opt_default
++          {
++            LEX *lex= Lex;
++            sp_pcontext *pctx= lex->spcont;
++            uint num_vars= pctx->context_var_count();
++            enum enum_field_types var_type= (enum enum_field_types) $4;
++            Item *dflt_value_item= $5;
++            
++            if (!dflt_value_item)
++            {
++              dflt_value_item= new Item_null();
++              /* QQ Set to the var_type with null_value? */
++            }
++            
++            for (uint i = num_vars-$2 ; i < num_vars ; i++)
++            {
++              uint var_idx= pctx->var_context2runtime(i);
++              sp_variable_t *spvar= pctx->find_variable(var_idx);
++            
++              if (!spvar)
++                MYSQL_YYABORT;
++            
++              spvar->type= var_type;
++              spvar->dflt= dflt_value_item;
++            
++              if (lex->sphead->fill_field_definition(YYTHD, lex, var_type,
++                                                     &spvar->field_def))
++              {
++                MYSQL_YYABORT;
++              }
++            
++              spvar->field_def.field_name= spvar->name.str;
++              spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
++            
++              /* The last instruction is responsible for freeing LEX. */
++
++              lex->sphead->add_instr(
++                new sp_instr_set(lex->sphead->instructions(), pctx, var_idx,
++                                 dflt_value_item, var_type, lex,
++                                 (i == num_vars - 1)));
++            }
++
++            pctx->declare_var_boundary(0);
++            lex->sphead->restore_lex(YYTHD);
++
++            $$.vars= $2;
++            $$.conds= $$.hndlrs= $$.curs= 0;
++          }
++	| DECLARE_SYM ident CONDITION_SYM FOR_SYM sp_cond
++	  {
++	    LEX *lex= Lex;
++	    sp_pcontext *spc= lex->spcont;
++
++	    if (spc->find_cond(&$2, TRUE))
++	    {
++	      my_error(ER_SP_DUP_COND, MYF(0), $2.str);
++	      MYSQL_YYABORT;
++	    }
++	    YYTHD->lex->spcont->push_cond(&$2, $5);
++	    $$.vars= $$.hndlrs= $$.curs= 0;
++	    $$.conds= 1;
++	  }
++	| DECLARE_SYM sp_handler_type HANDLER_SYM FOR_SYM
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++
++            lex->spcont= lex->spcont->push_context(LABEL_HANDLER_SCOPE);
++
++	    sp_pcontext *ctx= lex->spcont;
++	    sp_instr_hpush_jump *i=
++              new sp_instr_hpush_jump(sp->instructions(), ctx, $2,
++	                              ctx->current_var_count());
++
++	    sp->add_instr(i);
++	    sp->push_backpatch(i, ctx->push_label((char *)"", 0));
++	  }
++	  sp_hcond_list sp_proc_stmt
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    sp_pcontext *ctx= lex->spcont;
++	    sp_label_t *hlab= lex->spcont->pop_label(); /* After this hdlr */
++	    sp_instr_hreturn *i;
++
++	    if ($2 == SP_HANDLER_CONTINUE)
++	    {
++	      i= new sp_instr_hreturn(sp->instructions(), ctx,
++	                              ctx->current_var_count());
++	      sp->add_instr(i);
++	    }
++	    else
++	    {  /* EXIT or UNDO handler, just jump to the end of the block */
++	      i= new sp_instr_hreturn(sp->instructions(), ctx, 0);
++
++	      sp->add_instr(i);
++	      sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */
++	    }
++	    lex->sphead->backpatch(hlab);
++
++            lex->spcont= ctx->pop_context();
++
++	    $$.vars= $$.conds= $$.curs= 0;
++	    $$.hndlrs= $6;
++	    lex->spcont->add_handlers($6);
++	  }
++	| DECLARE_SYM ident CURSOR_SYM FOR_SYM sp_cursor_stmt
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    sp_pcontext *ctx= lex->spcont;
++	    uint offp;
++	    sp_instr_cpush *i;
++
++	    if (ctx->find_cursor(&$2, &offp, TRUE))
++	    {
++	      my_error(ER_SP_DUP_CURS, MYF(0), $2.str);
++	      delete $5;
++	      MYSQL_YYABORT;
++	    }
++            i= new sp_instr_cpush(sp->instructions(), ctx, $5,
++                                  ctx->current_cursor_count());
++	    sp->add_instr(i);
++	    ctx->push_cursor(&$2);
++	    $$.vars= $$.conds= $$.hndlrs= 0;
++	    $$.curs= 1;
++	  }
++	;
++
++sp_cursor_stmt:
++	  {
++	    Lex->sphead->reset_lex(YYTHD);
++
++	    /* We use statement here just be able to get a better
++	       error message. Using 'select' works too, but will then
++	       result in a generic "syntax error" if a non-select
++	       statement is given. */
++	  }
++	  statement
++	  {
++	    LEX *lex= Lex;
++
++	    if (lex->sql_command != SQLCOM_SELECT)
++	    {
++	      my_message(ER_SP_BAD_CURSOR_QUERY, ER(ER_SP_BAD_CURSOR_QUERY),
++                         MYF(0));
++	      MYSQL_YYABORT;
++	    }
++	    if (lex->result)
++	    {
++	      my_message(ER_SP_BAD_CURSOR_SELECT, ER(ER_SP_BAD_CURSOR_SELECT),
++                         MYF(0));
++	      MYSQL_YYABORT;
++	    }
++	    lex->sp_lex_in_use= TRUE;
++	    $$= lex;
++	    lex->sphead->restore_lex(YYTHD);
++	  }
++	;
++
++sp_handler_type:
++	  EXIT_SYM      { $$= SP_HANDLER_EXIT; }
++	| CONTINUE_SYM  { $$= SP_HANDLER_CONTINUE; }
++/*	| UNDO_SYM      { QQ No yet } */
++	;
++
++sp_hcond_list:
++          sp_hcond_element
++          { $$= 1; }
++        | sp_hcond_list ',' sp_hcond_element
++          { $$+= 1; }
++        ;
++
++sp_hcond_element:
++	  sp_hcond
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    sp_pcontext *ctx= lex->spcont->parent_context();
++
++	    if (ctx->find_handler($1))
++	    {
++	      my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0));
++	      MYSQL_YYABORT;
++	    }
++	    else
++	    {
++	      sp_instr_hpush_jump *i=
++                (sp_instr_hpush_jump *)sp->last_instruction();
++
++	      i->add_condition($1);
++	      ctx->push_handler($1);
++	    }
++	  }
++	;
++
++sp_cond:
++	  ulong_num
++	  {			/* mysql errno */
++	    $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
++	    $$->type= sp_cond_type_t::number;
++	    $$->mysqlerr= $1;
++	  }
++	| SQLSTATE_SYM opt_value TEXT_STRING_literal
++	  {		/* SQLSTATE */
++	    if (!sp_cond_check(&$3))
++	    {
++	      my_error(ER_SP_BAD_SQLSTATE, MYF(0), $3.str);
++	      MYSQL_YYABORT;
++	    }
++	    $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
++	    $$->type= sp_cond_type_t::state;
++	    memcpy($$->sqlstate, $3.str, 5);
++	    $$->sqlstate[5]= '\0';
++	  }
++	;
++
++opt_value:
++	  /* Empty */  {}
++	| VALUE_SYM    {}
++	;
++
++sp_hcond:
++	  sp_cond
++	  {
++	    $$= $1;
++	  }
++	| ident			/* CONDITION name */
++	  {
++	    $$= Lex->spcont->find_cond(&$1);
++	    if ($$ == NULL)
++	    {
++	      my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
++	      MYSQL_YYABORT;
++	    }
++	  }
++	| SQLWARNING_SYM	/* SQLSTATEs 01??? */
++	  {
++	    $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
++	    $$->type= sp_cond_type_t::warning;
++	  }
++	| not FOUND_SYM		/* SQLSTATEs 02??? */
++	  {
++	    $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
++	    $$->type= sp_cond_type_t::notfound;
++	  }
++	| SQLEXCEPTION_SYM	/* All other SQLSTATEs */
++	  {
++	    $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
++	    $$->type= sp_cond_type_t::exception;
++	  }
++	;
++
++sp_decl_idents:
++	  ident
++	  {
++            /* NOTE: field definition is filled in sp_decl section. */
++
++	    LEX *lex= Lex;
++	    sp_pcontext *spc= lex->spcont;
++
++	    if (spc->find_variable(&$1, TRUE))
++	    {
++	      my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
++	      MYSQL_YYABORT;
++	    }
++	    spc->push_variable(&$1, (enum_field_types)0, sp_param_in);
++	    $$= 1;
++	  }
++	| sp_decl_idents ',' ident
++	  {
++            /* NOTE: field definition is filled in sp_decl section. */
++
++	    LEX *lex= Lex;
++	    sp_pcontext *spc= lex->spcont;
++
++	    if (spc->find_variable(&$3, TRUE))
++	    {
++	      my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
++	      MYSQL_YYABORT;
++	    }
++	    spc->push_variable(&$3, (enum_field_types)0, sp_param_in);
++	    $$= $1 + 1;
++	  }
++	;
++
++sp_opt_default:
++	  /* Empty */ { $$ = NULL; }
++        | DEFAULT expr { $$ = $2; }
++	;
++
++sp_proc_stmt:
++	  {
++            THD *thd= YYTHD;
++	    LEX *lex= thd->lex;
++            Lex_input_stream *lip= thd->m_lip;
++
++	    lex->sphead->reset_lex(thd);
++	    lex->sphead->m_tmp_query= lip->tok_start;
++	  }
++	  statement
++	  {
++            THD *thd= YYTHD;
++	    LEX *lex= thd->lex;
++            Lex_input_stream *lip= thd->m_lip;
++	    sp_head *sp= lex->sphead;
++
++            sp->m_flags|= sp_get_flags_for_command(lex);
++	    if (lex->sql_command == SQLCOM_CHANGE_DB)
++	    { /* "USE db" doesn't work in a procedure */
++	      my_error(ER_SP_BADSTATEMENT, MYF(0), "USE");
++	      MYSQL_YYABORT;
++	    }
++	    /*
++              Don't add an instruction for SET statements, since all
++              instructions for them were already added during processing
++              of "set" rule.
++	    */
++            DBUG_ASSERT(lex->sql_command != SQLCOM_SET_OPTION ||
++                        lex->var_list.is_empty());
++            if (lex->sql_command != SQLCOM_SET_OPTION)
++	    {
++              sp_instr_stmt *i=new sp_instr_stmt(sp->instructions(),
++                                                 lex->spcont, lex);
++
++              /*
++                Extract the query statement from the tokenizer.  The
++                end is either lex->ptr, if there was no lookahead,
++                lex->tok_end otherwise.
++              */
++              if (yychar == YYEMPTY)
++                i->m_query.length= lip->ptr - sp->m_tmp_query;
++              else
++                i->m_query.length= lip->tok_end - sp->m_tmp_query;
++              i->m_query.str= strmake_root(thd->mem_root,
++                                           sp->m_tmp_query,
++                                           i->m_query.length);
++              sp->add_instr(i);
++            }
++	    sp->restore_lex(thd);
++          }
++          | RETURN_SYM 
++          { Lex->sphead->reset_lex(YYTHD); }
++          expr
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++
++	    if (sp->m_type != TYPE_ENUM_FUNCTION)
++	    {
++	      my_message(ER_SP_BADRETURN, ER(ER_SP_BADRETURN), MYF(0));
++	      MYSQL_YYABORT;
++	    }
++	    else
++	    {
++	      sp_instr_freturn *i;
++
++	      i= new sp_instr_freturn(sp->instructions(), lex->spcont, $3,
++                                      sp->m_return_field_def.sql_type, lex);
++	      sp->add_instr(i);
++	      sp->m_flags|= sp_head::HAS_RETURN;
++	    }
++	    sp->restore_lex(YYTHD);
++	  }
++        | IF
++          { Lex->sphead->new_cont_backpatch(NULL); }
++          sp_if END IF
++          { Lex->sphead->do_cont_backpatch(); }
++        | case_stmt_specification
++	| sp_labeled_control
++	  {}
++	| { /* Unlabeled controls get a secret label. */
++	    LEX *lex= Lex;
++
++	    lex->spcont->push_label((char *)"", lex->sphead->instructions());
++	  }
++	  sp_unlabeled_control
++	  {
++	    LEX *lex= Lex;
++
++	    lex->sphead->backpatch(lex->spcont->pop_label());
++	  }
++	| LEAVE_SYM label_ident
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp = lex->sphead;
++	    sp_pcontext *ctx= lex->spcont;
++	    sp_label_t *lab= ctx->find_label($2.str);
++
++	    if (! lab)
++	    {
++	      my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str);
++	      MYSQL_YYABORT;
++	    }
++	    else
++	    {
++	      sp_instr_jump *i;
++	      uint ip= sp->instructions();
++	      uint n;
++
++	      n= ctx->diff_handlers(lab->ctx, TRUE);  /* Exclusive the dest. */
++	      if (n)
++	        sp->add_instr(new sp_instr_hpop(ip++, ctx, n));
++	      n= ctx->diff_cursors(lab->ctx, TRUE);  /* Exclusive the dest. */
++	      if (n)
++	        sp->add_instr(new sp_instr_cpop(ip++, ctx, n));
++	      i= new sp_instr_jump(ip, ctx);
++	      sp->push_backpatch(i, lab);  /* Jumping forward */
++              sp->add_instr(i);
++	    }
++	  }
++	| ITERATE_SYM label_ident
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    sp_pcontext *ctx= lex->spcont;
++	    sp_label_t *lab= ctx->find_label($2.str);
++
++	    if (! lab || lab->type != SP_LAB_ITER)
++	    {
++	      my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str);
++	      MYSQL_YYABORT;
++	    }
++	    else
++	    {
++	      sp_instr_jump *i;
++	      uint ip= sp->instructions();
++	      uint n;
++
++	      n= ctx->diff_handlers(lab->ctx, FALSE);  /* Inclusive the dest. */
++	      if (n)
++	        sp->add_instr(new sp_instr_hpop(ip++, ctx, n));
++	      n= ctx->diff_cursors(lab->ctx, FALSE);  /* Inclusive the dest. */
++	      if (n)
++	        sp->add_instr(new sp_instr_cpop(ip++, ctx, n));
++	      i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
++              sp->add_instr(i);
++	    }
++	  }
++	| OPEN_SYM ident
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    uint offset;
++	    sp_instr_copen *i;
++
++	    if (! lex->spcont->find_cursor(&$2, &offset))
++	    {
++	      my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
++	      MYSQL_YYABORT;
++	    }
++	    i= new sp_instr_copen(sp->instructions(), lex->spcont, offset);
++	    sp->add_instr(i);
++	  }
++	| FETCH_SYM sp_opt_fetch_noise ident INTO
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    uint offset;
++	    sp_instr_cfetch *i;
++
++	    if (! lex->spcont->find_cursor(&$3, &offset))
++	    {
++	      my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $3.str);
++	      MYSQL_YYABORT;
++	    }
++	    i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
++	    sp->add_instr(i);
++	  }
++	  sp_fetch_list
++	  { }
++	| CLOSE_SYM ident
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    uint offset;
++	    sp_instr_cclose *i;
++
++	    if (! lex->spcont->find_cursor(&$2, &offset))
++	    {
++	      my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
++	      MYSQL_YYABORT;
++	    }
++	    i= new sp_instr_cclose(sp->instructions(), lex->spcont,  offset);
++	    sp->add_instr(i);
++	  }
++	;
++
++sp_opt_fetch_noise:
++	  /* Empty */
++	| NEXT_SYM FROM
++	| FROM
++	;
++
++sp_fetch_list:
++	  ident
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    sp_pcontext *spc= lex->spcont;
++	    sp_variable_t *spv;
++
++	    if (!spc || !(spv = spc->find_variable(&$1)))
++	    {
++	      my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
++	      MYSQL_YYABORT;
++	    }
++	    else
++	    {
++	      /* An SP local variable */
++	      sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
++
++	      i->add_to_varlist(spv);
++	    }
++	  }
++	|
++	  sp_fetch_list ',' ident
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    sp_pcontext *spc= lex->spcont;
++	    sp_variable_t *spv;
++
++	    if (!spc || !(spv = spc->find_variable(&$3)))
++	    {
++	      my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str);
++	      MYSQL_YYABORT;
++	    }
++	    else
++	    {
++	      /* An SP local variable */
++	      sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
++
++	      i->add_to_varlist(spv);
++	    }
++	  }
++	;
++
++sp_if:
++          { Lex->sphead->reset_lex(YYTHD); }
++          expr THEN_SYM
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    sp_pcontext *ctx= lex->spcont;
++	    uint ip= sp->instructions();
++	    sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx,
++                                                               $2, lex);
++
++	    sp->push_backpatch(i, ctx->push_label((char *)"", 0));
++            sp->add_cont_backpatch(i);
++            sp->add_instr(i);
++            sp->restore_lex(YYTHD);
++	  }
++	  sp_proc_stmts1
++	  {
++	    sp_head *sp= Lex->sphead;
++	    sp_pcontext *ctx= Lex->spcont;
++	    uint ip= sp->instructions();
++	    sp_instr_jump *i = new sp_instr_jump(ip, ctx);
++
++	    sp->add_instr(i);
++	    sp->backpatch(ctx->pop_label());
++	    sp->push_backpatch(i, ctx->push_label((char *)"", 0));
++	  }
++	  sp_elseifs
++	  {
++	    LEX *lex= Lex;
++
++	    lex->sphead->backpatch(lex->spcont->pop_label());
++	  }
++	;
++
++sp_elseifs:
++	  /* Empty */
++	| ELSEIF_SYM sp_if
++	| ELSE sp_proc_stmts1
++	;
++
++case_stmt_specification:
++          simple_case_stmt
++        | searched_case_stmt
++        ;
++
++simple_case_stmt:
++          CASE_SYM
++          {
++            LEX *lex= Lex;
++            case_stmt_action_case(lex);
++            lex->sphead->reset_lex(YYTHD); /* For expr $3 */
++          }
++          expr
++          {
++            LEX *lex= Lex;
++            if (case_stmt_action_expr(lex, $3))
++              MYSQL_YYABORT;
++
++            lex->sphead->restore_lex(YYTHD); /* For expr $3 */
++          }
++          simple_when_clause_list
++          else_clause_opt
++          END
++          CASE_SYM
++          {
++            LEX *lex= Lex;
++            case_stmt_action_end_case(lex, true);
++          }
++        ;
++
++searched_case_stmt:
++          CASE_SYM
++          {
++            LEX *lex= Lex;
++            case_stmt_action_case(lex);
++          }
++          searched_when_clause_list
++          else_clause_opt
++          END
++          CASE_SYM
++          {
++            LEX *lex= Lex;
++            case_stmt_action_end_case(lex, false);
++          }
++        ;
++
++simple_when_clause_list:
++          simple_when_clause
++        | simple_when_clause_list simple_when_clause
++        ;
++
++searched_when_clause_list:
++          searched_when_clause
++        | searched_when_clause_list searched_when_clause
++        ;
++
++simple_when_clause:
++          WHEN_SYM
++          {
++            Lex->sphead->reset_lex(YYTHD); /* For expr $3 */
++          }
++          expr
++          {
++            /* Simple case: <caseval> = <whenval> */
++
++            LEX *lex= Lex;
++            case_stmt_action_when(lex, $3, true);
++            lex->sphead->restore_lex(YYTHD); /* For expr $3 */
++          }
++          THEN_SYM
++          sp_proc_stmts1
++          {
++            LEX *lex= Lex;
++            case_stmt_action_then(lex);
++          }
++        ;
++
++searched_when_clause:
++          WHEN_SYM
++          {
++            Lex->sphead->reset_lex(YYTHD); /* For expr $3 */
++          }
++          expr
++          {
++            LEX *lex= Lex;
++            case_stmt_action_when(lex, $3, false);
++            lex->sphead->restore_lex(YYTHD); /* For expr $3 */
++          }
++          THEN_SYM
++          sp_proc_stmts1
++          {
++            LEX *lex= Lex;
++            case_stmt_action_then(lex);
++          }
++        ;
++
++else_clause_opt:
++          /* empty */
++          {
++            LEX *lex= Lex;
++            sp_head *sp= lex->sphead;
++            uint ip= sp->instructions();
++            sp_instr_error *i= new sp_instr_error(ip, lex->spcont,
++                                                  ER_SP_CASE_NOT_FOUND);
++            sp->add_instr(i);
++          }
++        | ELSE sp_proc_stmts1
++        ;
++
++sp_labeled_control:
++	  label_ident ':'
++	  {
++	    LEX *lex= Lex;
++	    sp_pcontext *ctx= lex->spcont;
++	    sp_label_t *lab= ctx->find_label($1.str);
++
++	    if (lab)
++	    {
++	      my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str);
++	      MYSQL_YYABORT;
++	    }
++	    else
++	    {
++	      lab= lex->spcont->push_label($1.str,
++	                                   lex->sphead->instructions());
++	      lab->type= SP_LAB_ITER;
++	    }
++	  }
++	  sp_unlabeled_control sp_opt_label
++	  {
++	    LEX *lex= Lex;
++
++	    if ($5.str)
++	    {
++	      sp_label_t *lab= lex->spcont->find_label($5.str);
++
++	      if (!lab ||
++	          my_strcasecmp(system_charset_info, $5.str, lab->name) != 0)
++	      {
++	        my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str);
++	        MYSQL_YYABORT;
++	      }
++	    }
++	    lex->sphead->backpatch(lex->spcont->pop_label());
++	  }
++	;
++
++sp_opt_label:
++        /* Empty  */    { $$= null_lex_str; }
++        | label_ident   { $$= $1; }
++	;
++
++sp_unlabeled_control:
++	  BEGIN_SYM
++	  { /* QQ This is just a dummy for grouping declarations and statements
++	       together. No [[NOT] ATOMIC] yet, and we need to figure out how
++	       make it coexist with the existing BEGIN COMMIT/ROLLBACK. */
++	    LEX *lex= Lex;
++	    sp_label_t *lab= lex->spcont->last_label();
++
++	    lab->type= SP_LAB_BEGIN;
++	    lex->spcont= lex->spcont->push_context(LABEL_DEFAULT_SCOPE);
++	  }
++	  sp_decls
++	  sp_proc_stmts
++	  END
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    sp_pcontext *ctx= lex->spcont;
++
++  	    sp->backpatch(ctx->last_label());	/* We always have a label */
++	    if ($3.hndlrs)
++	      sp->add_instr(new sp_instr_hpop(sp->instructions(), ctx,
++					      $3.hndlrs));
++	    if ($3.curs)
++	      sp->add_instr(new sp_instr_cpop(sp->instructions(), ctx,
++					      $3.curs));
++	    lex->spcont= ctx->pop_context();
++	  }
++	| LOOP_SYM
++	  sp_proc_stmts1 END LOOP_SYM
++	  {
++	    LEX *lex= Lex;
++	    uint ip= lex->sphead->instructions();
++	    sp_label_t *lab= lex->spcont->last_label();  /* Jumping back */
++	    sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
++
++	    lex->sphead->add_instr(i);
++	  }
++        | WHILE_SYM 
++          { Lex->sphead->reset_lex(YYTHD); }
++          expr DO_SYM
++	  {
++	    LEX *lex= Lex;
++	    sp_head *sp= lex->sphead;
++	    uint ip= sp->instructions();
++	    sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
++							       $3, lex);
++
++	    /* Jumping forward */
++	    sp->push_backpatch(i, lex->spcont->last_label());
++            sp->new_cont_backpatch(i);
++            sp->add_instr(i);
++            sp->restore_lex(YYTHD);
++	  }
++	  sp_proc_stmts1 END WHILE_SYM
++	  {
++	    LEX *lex= Lex;
++	    uint ip= lex->sphead->instructions();
++	    sp_label_t *lab= lex->spcont->last_label();  /* Jumping back */
++	    sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
++
++	    lex->sphead->add_instr(i);
++            lex->sphead->do_cont_backpatch();
++	  }
++        | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM 
++          { Lex->sphead->reset_lex(YYTHD); }
++          expr END REPEAT_SYM
++	  {
++	    LEX *lex= Lex;
++	    uint ip= lex->sphead->instructions();
++	    sp_label_t *lab= lex->spcont->last_label();  /* Jumping back */
++	    sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
++                                                               $5, lab->ip,
++                                                               lex);
++            lex->sphead->add_instr(i);
++            lex->sphead->restore_lex(YYTHD);
++            /* We can shortcut the cont_backpatch here */
++            i->m_cont_dest= ip+1;
++	  }
++	;
++
++trg_action_time:
++            BEFORE_SYM 
++            { Lex->trg_chistics.action_time= TRG_ACTION_BEFORE; }
++          | AFTER_SYM 
++            { Lex->trg_chistics.action_time= TRG_ACTION_AFTER; }
++          ;
++
++trg_event:
++            INSERT 
++            { Lex->trg_chistics.event= TRG_EVENT_INSERT; }
++          | UPDATE_SYM
++            { Lex->trg_chistics.event= TRG_EVENT_UPDATE; }
++          | DELETE_SYM
++            { Lex->trg_chistics.event= TRG_EVENT_DELETE; }
++          ;
++
++create2:
++        '(' create2a {}
++        | opt_create_table_options create3 {}
++        | LIKE table_ident
++          {
++            Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
++            if (!Lex->select_lex.add_table_to_list(YYTHD, $2, NULL, 0, TL_READ))
++              MYSQL_YYABORT;
++          }
++        | '(' LIKE table_ident ')'
++          {
++            Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
++            if (!Lex->select_lex.add_table_to_list(YYTHD, $3, NULL, 0, TL_READ))
++              MYSQL_YYABORT;
++          }
++        ;
++
++create2a:
++        field_list ')' opt_create_table_options create3 {}
++	|  create_select ')' { Select->set_braces(1);} union_opt {}
++        ;
++
++create3:
++	/* empty */ {}
++	| opt_duplicate opt_as     create_select
++          { Select->set_braces(0);} union_clause {}
++	| opt_duplicate opt_as '(' create_select ')'
++          { Select->set_braces(1);} union_opt {}
++        ;
++
++create_select:
++          SELECT_SYM
++          {
++	    LEX *lex=Lex;
++	    lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ;
++	    if (lex->sql_command == SQLCOM_INSERT)
++	      lex->sql_command= SQLCOM_INSERT_SELECT;
++	    else if (lex->sql_command == SQLCOM_REPLACE)
++	      lex->sql_command= SQLCOM_REPLACE_SELECT;
++	    /*
++              The following work only with the local list, the global list
++              is created correctly in this case
++	    */
++	    lex->current_select->table_list.save_and_clear(&lex->save_list);
++	    mysql_init_select(lex);
++	    lex->current_select->parsing_place= SELECT_LIST;
++          }
++          select_options select_item_list
++	  {
++	    Select->parsing_place= NO_MATTER;
++	  }
++	  opt_select_from
++	  {
++	    /*
++              The following work only with the local list, the global list
++              is created correctly in this case
++	    */
++	    Lex->current_select->table_list.push_front(&Lex->save_list);
++	  }
++        ;
++
++opt_as:
++	/* empty */ {}
++	| AS	    {};
++
++opt_create_database_options:
++	/* empty */			{}
++	| create_database_options	{};
++
++create_database_options:
++	create_database_option					{}
++	| create_database_options create_database_option	{};
++
++create_database_option:
++	default_collation   {}
++	| default_charset   {};
++
++opt_table_options:
++	/* empty */	 { $$= 0; }
++	| table_options  { $$= $1;};
++
++table_options:
++	table_option	{ $$=$1; }
++	| table_option table_options { $$= $1 | $2; };
++
++table_option:
++	TEMPORARY	{ $$=HA_LEX_CREATE_TMP_TABLE; };
++
++opt_if_not_exists:
++	/* empty */	 { $$= 0; }
++	| IF not EXISTS	 { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
++
++opt_create_table_options:
++	/* empty */
++	| create_table_options;
++
++create_table_options_space_separated:
++	create_table_option
++	| create_table_option create_table_options_space_separated;
++
++create_table_options:
++	create_table_option
++	| create_table_option     create_table_options
++	| create_table_option ',' create_table_options;
++
++create_table_option:
++	ENGINE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; }
++	| TYPE_SYM opt_equal storage_engines    { Lex->create_info.db_type= $3; WARN_DEPRECATED("TYPE=storage_engine","ENGINE=storage_engine");   Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; }
++	| MAX_ROWS opt_equal ulonglong_num	{ Lex->create_info.max_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MAX_ROWS;}
++	| MIN_ROWS opt_equal ulonglong_num	{ Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;}
++	| AVG_ROW_LENGTH opt_equal ulong_num	{ Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;}
++	| PASSWORD opt_equal TEXT_STRING_sys	{ Lex->create_info.password=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD; }
++	| COMMENT_SYM opt_equal TEXT_STRING_sys	{ Lex->create_info.comment=$3; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; }
++	| AUTO_INC opt_equal ulonglong_num	{ Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;}
++        | PACK_KEYS_SYM opt_equal ulong_num
++          {
++            switch($3) {
++            case 0:
++                Lex->create_info.table_options|= HA_OPTION_NO_PACK_KEYS;
++                break;
++            case 1:
++                Lex->create_info.table_options|= HA_OPTION_PACK_KEYS;
++                break;
++            default:
++                my_parse_error(ER(ER_SYNTAX_ERROR));
++                MYSQL_YYABORT;
++            }
++            Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
++          }
++        | PACK_KEYS_SYM opt_equal DEFAULT
++          {
++            Lex->create_info.table_options&=
++              ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
++            Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS;
++          }
++	| CHECKSUM_SYM opt_equal ulong_num	{ Lex->create_info.table_options|= $3 ? HA_OPTION_CHECKSUM : HA_OPTION_NO_CHECKSUM; Lex->create_info.used_fields|= HA_CREATE_USED_CHECKSUM; }
++	| DELAY_KEY_WRITE_SYM opt_equal ulong_num { Lex->create_info.table_options|= $3 ? HA_OPTION_DELAY_KEY_WRITE : HA_OPTION_NO_DELAY_KEY_WRITE;  Lex->create_info.used_fields|= HA_CREATE_USED_DELAY_KEY_WRITE; }
++	| ROW_FORMAT_SYM opt_equal row_types	{ Lex->create_info.row_type= $3;  Lex->create_info.used_fields|= HA_CREATE_USED_ROW_FORMAT; }
++	| RAID_TYPE opt_equal raid_types
++	  {
++	    my_error(ER_WARN_DEPRECATED_SYNTAX, MYF(0), "RAID_TYPE", "PARTITION");
++	    MYSQL_YYABORT;
++	  }
++	| RAID_CHUNKS opt_equal ulong_num
++	  {
++	    my_error(ER_WARN_DEPRECATED_SYNTAX, MYF(0), "RAID_CHUNKS", "PARTITION");
++	    MYSQL_YYABORT;
++	  }
++	| RAID_CHUNKSIZE opt_equal ulong_num
++	  {
++	    my_error(ER_WARN_DEPRECATED_SYNTAX, MYF(0), "RAID_CHUNKSIZE", "PARTITION");
++	    MYSQL_YYABORT;
++	  }
++	| UNION_SYM opt_equal '(' table_list ')'
++	  {
++	    /* Move the union list to the merge_list */
++	    LEX *lex=Lex;
++	    TABLE_LIST *table_list= lex->select_lex.get_table_list();
++	    lex->create_info.merge_list= lex->select_lex.table_list;
++	    lex->create_info.merge_list.elements--;
++	    lex->create_info.merge_list.first=
++	      (byte*) (table_list->next_local);
++	    lex->select_lex.table_list.elements=1;
++	    lex->select_lex.table_list.next=
++	      (byte**) &(table_list->next_local);
++	    table_list->next_local= 0;
++	    lex->create_info.used_fields|= HA_CREATE_USED_UNION;
++	  }
++	| default_charset
++	| default_collation
++	| INSERT_METHOD opt_equal merge_insert_types   { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;}
++	| DATA_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.data_file_name= $4.str; Lex->create_info.used_fields|= HA_CREATE_USED_DATADIR; }
++	| INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys { Lex->create_info.index_file_name= $4.str;  Lex->create_info.used_fields|= HA_CREATE_USED_INDEXDIR; }
++	| CONNECTION_SYM opt_equal TEXT_STRING_sys { Lex->create_info.connect_string.str= $3.str; Lex->create_info.connect_string.length= $3.length;  Lex->create_info.used_fields|= HA_CREATE_USED_CONNECTION; }
++        ;
++
++default_charset:
++        opt_default charset opt_equal charset_name_or_default
++        {
++          HA_CREATE_INFO *cinfo= &Lex->create_info;
++          if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
++               cinfo->default_table_charset && $4 &&
++               !my_charset_same(cinfo->default_table_charset,$4))
++          {
++            my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
++                     "CHARACTER SET ", cinfo->default_table_charset->csname,
++                     "CHARACTER SET ", $4->csname);
++            MYSQL_YYABORT;
++          }
++	  Lex->create_info.default_table_charset= $4;
++          Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
++        };
++
++default_collation:
++        opt_default COLLATE_SYM opt_equal collation_name_or_default
++        {
++          HA_CREATE_INFO *cinfo= &Lex->create_info;
++          if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) &&
++               cinfo->default_table_charset && $4 &&
++               !my_charset_same(cinfo->default_table_charset,$4))
++            {
++              my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
++                       $4->name, cinfo->default_table_charset->csname);
++              MYSQL_YYABORT;
++            }
++            Lex->create_info.default_table_charset= $4;
++            Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
++        };
++
++storage_engines:
++	ident_or_text
++	{
++	  $$ = ha_resolve_by_name($1.str,$1.length);
++	  if ($$ == DB_TYPE_UNKNOWN) {
++	    my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
++	    MYSQL_YYABORT;
++	  }
++	};
++
++row_types:
++	DEFAULT		{ $$= ROW_TYPE_DEFAULT; }
++	| FIXED_SYM	{ $$= ROW_TYPE_FIXED; }
++	| DYNAMIC_SYM	{ $$= ROW_TYPE_DYNAMIC; }
++	| COMPRESSED_SYM { $$= ROW_TYPE_COMPRESSED; }
++	| REDUNDANT_SYM	{ $$= ROW_TYPE_REDUNDANT; }
++	| COMPACT_SYM	{ $$= ROW_TYPE_COMPACT; };
++
++raid_types:
++	RAID_STRIPED_SYM { $$= RAID_TYPE_0; }
++	| RAID_0_SYM	 { $$= RAID_TYPE_0; }
++	| ulong_num	 { $$=$1;};
++
++merge_insert_types:
++       NO_SYM            { $$= MERGE_INSERT_DISABLED; }
++       | FIRST_SYM       { $$= MERGE_INSERT_TO_FIRST; }
++       | LAST_SYM        { $$= MERGE_INSERT_TO_LAST; };
++
++opt_select_from:
++	opt_limit_clause {}
++	| select_from select_lock_type;
++
++udf_func_type:
++	/* empty */	{ $$ = UDFTYPE_FUNCTION; }
++	| AGGREGATE_SYM { $$ = UDFTYPE_AGGREGATE; };
++
++udf_type:
++	STRING_SYM {$$ = (int) STRING_RESULT; }
++	| REAL {$$ = (int) REAL_RESULT; }
++        | DECIMAL_SYM {$$ = (int) DECIMAL_RESULT; }
++	| INT_SYM {$$ = (int) INT_RESULT; };
++
++field_list:
++	  field_list_item
++	| field_list ',' field_list_item;
++
++
++field_list_item:
++	   column_def
++         | key_def
++         ;
++
++column_def:
++	  field_spec opt_check_constraint
++	| field_spec references
++	  {
++	    Lex->col_list.empty();		/* Alloced by sql_alloc */
++	  }
++	;
++
++key_def:
++	key_type opt_ident key_alg '(' key_list ')'
++	  {
++	    LEX *lex=Lex;
++            Key *key= new Key($1, $2, $3, 0, lex->col_list);
++            lex->alter_info.key_list.push_back(key);
++
++	    lex->col_list.empty();		/* Alloced by sql_alloc */
++	  }
++	| opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')'
++	  {
++	    LEX *lex=Lex;
++	    const char *key_name= $3 ? $3:$1;
++            Key *key= new Key($2, key_name, $4, 0, lex->col_list);
++            lex->alter_info.key_list.push_back(key);
++	    lex->col_list.empty();		/* Alloced by sql_alloc */
++	  }
++	| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
++	  {
++	    LEX *lex=Lex;
++            const char *key_name= $4 ? $4 : $1;
++            Key *key= new foreign_key(key_name, lex->col_list,
++                                      $8,
++                                      lex->ref_list,
++                                      lex->fk_delete_opt,
++                                      lex->fk_update_opt,
++                                      lex->fk_match_option);
++            lex->alter_info.key_list.push_back(key);
++            key= new Key(Key::MULTIPLE, key_name,
++                         HA_KEY_ALG_UNDEF, 1,
++                         lex->col_list);
++            lex->alter_info.key_list.push_back(key);
++	    lex->col_list.empty();		/* Alloced by sql_alloc */
++	  }
++	| constraint opt_check_constraint
++	  {
++	    Lex->col_list.empty();		/* Alloced by sql_alloc */
++	  }
++	| opt_constraint check_constraint
++	  {
++	    Lex->col_list.empty();		/* Alloced by sql_alloc */
++	  }
++	;
++
++opt_check_constraint:
++	/* empty */
++	| check_constraint
++	;
++
++check_constraint:
++	CHECK_SYM expr
++	;
++
++opt_constraint:
++	/* empty */		{ $$=(char*) 0; }
++	| constraint		{ $$= $1; }
++	;
++
++constraint:
++	CONSTRAINT opt_ident	{ $$=$2; }
++	;
++
++field_spec:
++	field_ident
++	 {
++	   LEX *lex=Lex;
++	   lex->length=lex->dec=0; lex->type=0;
++	   lex->default_value= lex->on_update_value= 0;
++           lex->comment=null_lex_str;
++	   lex->charset=NULL;
++	 }
++	type opt_attribute
++	{
++	  LEX *lex=Lex;
++	  if (add_field_to_list(lex->thd, $1.str,
++				(enum enum_field_types) $3,
++				lex->length,lex->dec,lex->type,
++				lex->default_value, lex->on_update_value, 
++                                &lex->comment,
++				lex->change,&lex->interval_list,lex->charset,
++				lex->uint_geom_type))
++	    MYSQL_YYABORT;
++	};
++
++type:
++	int_type opt_len field_options	{ $$=$1; }
++	| real_type opt_precision field_options { $$=$1; }
++	| FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; }
++	| BIT_SYM			{ Lex->length= (char*) "1";
++					  $$=FIELD_TYPE_BIT; }
++	| BIT_SYM '(' NUM ')'		{ Lex->length= $3.str;
++					  $$=FIELD_TYPE_BIT; }
++	| BOOL_SYM			{ Lex->length=(char*) "1";
++					  $$=FIELD_TYPE_TINY; }
++	| BOOLEAN_SYM			{ Lex->length=(char*) "1";
++					  $$=FIELD_TYPE_TINY; }
++	| char '(' NUM ')' opt_binary	{ Lex->length=$3.str;
++					  $$=FIELD_TYPE_STRING; }
++	| char opt_binary		{ Lex->length=(char*) "1";
++					  $$=FIELD_TYPE_STRING; }
++	| nchar '(' NUM ')' opt_bin_mod	{ Lex->length=$3.str;
++					  $$=FIELD_TYPE_STRING;
++					  Lex->charset=national_charset_info; }
++	| nchar opt_bin_mod		{ Lex->length=(char*) "1";
++					  $$=FIELD_TYPE_STRING;
++					  Lex->charset=national_charset_info; }
++	| BINARY '(' NUM ')'		{ Lex->length=$3.str;
++					  Lex->charset=&my_charset_bin;
++					  $$=FIELD_TYPE_STRING; }
++	| BINARY			{ Lex->length= (char*) "1";
++					  Lex->charset=&my_charset_bin;
++					  $$=FIELD_TYPE_STRING; }
++	| varchar '(' NUM ')' opt_binary { Lex->length=$3.str;
++					  $$= MYSQL_TYPE_VARCHAR; }
++	| nvarchar '(' NUM ')' opt_bin_mod { Lex->length=$3.str;
++					  $$= MYSQL_TYPE_VARCHAR;
++					  Lex->charset=national_charset_info; }
++	| VARBINARY '(' NUM ')' 	{ Lex->length=$3.str;
++					  Lex->charset=&my_charset_bin;
++					  $$= MYSQL_TYPE_VARCHAR; }
++	| YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; }
++	| DATE_SYM			{ $$=FIELD_TYPE_DATE; }
++	| TIME_SYM			{ $$=FIELD_TYPE_TIME; }
++	| TIMESTAMP opt_len
++	  {
++	    if (YYTHD->variables.sql_mode & MODE_MAXDB)
++	      $$=FIELD_TYPE_DATETIME;
++	    else
++            {
++              /* 
++                Unlike other types TIMESTAMP fields are NOT NULL by default.
++              */
++              Lex->type|= NOT_NULL_FLAG;
++	      $$=FIELD_TYPE_TIMESTAMP;
++            }
++	   }
++	| DATETIME			{ $$=FIELD_TYPE_DATETIME; }
++	| TINYBLOB			{ Lex->charset=&my_charset_bin;
++					  $$=FIELD_TYPE_TINY_BLOB; }
++	| BLOB_SYM opt_len		{ Lex->charset=&my_charset_bin;
++					  $$=FIELD_TYPE_BLOB; }
++	| spatial_type
++          {
++#ifdef HAVE_SPATIAL
++            Lex->charset=&my_charset_bin;
++            Lex->uint_geom_type= (uint)$1;
++            $$=FIELD_TYPE_GEOMETRY;
++#else
++            my_error(ER_FEATURE_DISABLED, MYF(0),
++                     sym_group_geom.name, sym_group_geom.needed_define);
++            MYSQL_YYABORT;
++#endif
++          }
++	| MEDIUMBLOB			{ Lex->charset=&my_charset_bin;
++					  $$=FIELD_TYPE_MEDIUM_BLOB; }
++	| LONGBLOB			{ Lex->charset=&my_charset_bin;
++					  $$=FIELD_TYPE_LONG_BLOB; }
++	| LONG_SYM VARBINARY		{ Lex->charset=&my_charset_bin;
++					  $$=FIELD_TYPE_MEDIUM_BLOB; }
++	| LONG_SYM varchar opt_binary	{ $$=FIELD_TYPE_MEDIUM_BLOB; }
++	| TINYTEXT opt_binary		{ $$=FIELD_TYPE_TINY_BLOB; }
++	| TEXT_SYM opt_len opt_binary	{ $$=FIELD_TYPE_BLOB; }
++	| MEDIUMTEXT opt_binary		{ $$=FIELD_TYPE_MEDIUM_BLOB; }
++	| LONGTEXT opt_binary		{ $$=FIELD_TYPE_LONG_BLOB; }
++	| DECIMAL_SYM float_options field_options
++                                        { $$=FIELD_TYPE_NEWDECIMAL;}
++	| NUMERIC_SYM float_options field_options
++                                        { $$=FIELD_TYPE_NEWDECIMAL;}
++	| FIXED_SYM float_options field_options
++                                        { $$=FIELD_TYPE_NEWDECIMAL;}
++	| ENUM {Lex->interval_list.empty();} '(' string_list ')' opt_binary
++	  { $$=FIELD_TYPE_ENUM; }
++	| SET { Lex->interval_list.empty();} '(' string_list ')' opt_binary
++	  { $$=FIELD_TYPE_SET; }
++	| LONG_SYM opt_binary		{ $$=FIELD_TYPE_MEDIUM_BLOB; }
++	| SERIAL_SYM
++	  {
++	    $$=FIELD_TYPE_LONGLONG;
++	    Lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG |
++		         UNIQUE_FLAG);
++	  }
++	;
++
++spatial_type:
++	GEOMETRY_SYM	      { $$= Field::GEOM_GEOMETRY; }
++	| GEOMETRYCOLLECTION  { $$= Field::GEOM_GEOMETRYCOLLECTION; }
++	| POINT_SYM           { Lex->length= (char*)"21";
++                                $$= Field::GEOM_POINT;
++                              }
++	| MULTIPOINT          { $$= Field::GEOM_MULTIPOINT; }
++	| LINESTRING          { $$= Field::GEOM_LINESTRING; }
++	| MULTILINESTRING     { $$= Field::GEOM_MULTILINESTRING; }
++	| POLYGON             { $$= Field::GEOM_POLYGON; }
++	| MULTIPOLYGON        { $$= Field::GEOM_MULTIPOLYGON; }
++	;
++
++char:
++	CHAR_SYM {}
++	;
++
++nchar:
++	NCHAR_SYM {}
++	| NATIONAL_SYM CHAR_SYM {}
++	;
++
++varchar:
++	char VARYING {}
++	| VARCHAR {}
++	;
++
++nvarchar:
++	NATIONAL_SYM VARCHAR {}
++	| NVARCHAR_SYM {}
++	| NCHAR_SYM VARCHAR {}
++	| NATIONAL_SYM CHAR_SYM VARYING {}
++	| NCHAR_SYM VARYING {}
++	;
++
++int_type:
++	INT_SYM		{ $$=FIELD_TYPE_LONG; }
++	| TINYINT	{ $$=FIELD_TYPE_TINY; }
++	| SMALLINT	{ $$=FIELD_TYPE_SHORT; }
++	| MEDIUMINT	{ $$=FIELD_TYPE_INT24; }
++	| BIGINT	{ $$=FIELD_TYPE_LONGLONG; };
++
++real_type:
++	REAL		{ $$= YYTHD->variables.sql_mode & MODE_REAL_AS_FLOAT ?
++			      FIELD_TYPE_FLOAT : FIELD_TYPE_DOUBLE; }
++	| DOUBLE_SYM	{ $$=FIELD_TYPE_DOUBLE; }
++	| DOUBLE_SYM PRECISION { $$=FIELD_TYPE_DOUBLE; };
++
++
++float_options:
++        /* empty */		{ Lex->dec=Lex->length= (char*)0; }
++        | '(' NUM ')'		{ Lex->length=$2.str; Lex->dec= (char*)0; }
++	| precision		{};
++
++precision:
++	'(' NUM ',' NUM ')'
++	{
++	  LEX *lex=Lex;
++	  lex->length=$2.str; lex->dec=$4.str;
++	};
++
++field_options:
++	/* empty */		{}
++	| field_opt_list	{};
++
++field_opt_list:
++	field_opt_list field_option {}
++	| field_option {};
++
++field_option:
++	SIGNED_SYM	{}
++	| UNSIGNED	{ Lex->type|= UNSIGNED_FLAG;}
++	| ZEROFILL	{ Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; };
++
++opt_len:
++	/* empty */	{ Lex->length=(char*) 0; } /* use default length */
++	| '(' NUM ')'	{ Lex->length= $2.str; };
++
++opt_precision:
++	/* empty */	{}
++	| precision	{};
++
++opt_attribute:
++	/* empty */ {}
++	| opt_attribute_list {};
++
++opt_attribute_list:
++	opt_attribute_list attribute {}
++	| attribute;
++
++attribute:
++	NULL_SYM	  { Lex->type&= ~ NOT_NULL_FLAG; }
++	| not NULL_SYM	  { Lex->type|= NOT_NULL_FLAG; }
++	| DEFAULT now_or_signed_literal { Lex->default_value=$2; }
++	| ON UPDATE_SYM NOW_SYM optional_braces 
++          { Lex->on_update_value= new Item_func_now_local(); }
++	| AUTO_INC	  { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
++	| SERIAL_SYM DEFAULT VALUE_SYM
++	  { 
++	    LEX *lex=Lex;
++	    lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG; 
++	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
++	  }
++	| opt_primary KEY_SYM 
++	  {
++	    LEX *lex=Lex;
++	    lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; 
++	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
++	  }
++	| UNIQUE_SYM	  
++	  {
++	    LEX *lex=Lex;
++	    lex->type|= UNIQUE_FLAG; 
++	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
++	  }
++	| UNIQUE_SYM KEY_SYM 
++	  {
++	    LEX *lex=Lex;
++	    lex->type|= UNIQUE_KEY_FLAG; 
++	    lex->alter_info.flags|= ALTER_ADD_INDEX; 
++	  }
++	| COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
++	| COLLATE_SYM collation_name
++	  {
++	    if (Lex->charset && !my_charset_same(Lex->charset,$2))
++	    {
++	      my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
++                       $2->name,Lex->charset->csname);
++	      MYSQL_YYABORT;
++	    }
++	    else
++	    {
++	      Lex->charset=$2;
++	    }
++	  }
++	;
++
++now_or_signed_literal:
++        NOW_SYM optional_braces { $$= new Item_func_now_local(); }
++        | signed_literal { $$=$1; }
++        ;
++
++charset:
++	CHAR_SYM SET	{}
++	| CHARSET	{}
++	;
++
++charset_name:
++	ident_or_text
++	{
++	  if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))))
++	  {
++	    my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
++	    MYSQL_YYABORT;
++	  }
++	}
++	| BINARY { $$= &my_charset_bin; }
++	;
++
++charset_name_or_default:
++	charset_name { $$=$1;   }
++	| DEFAULT    { $$=NULL; } ;
++
++opt_load_data_charset:
++	/* Empty */ { $$= NULL; }
++	| charset charset_name_or_default { $$= $2; }
++	;
++
++old_or_new_charset_name:
++	ident_or_text
++	{
++	  if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))) &&
++	      !($$=get_old_charset_by_name($1.str)))
++	  {
++	    my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
++	    MYSQL_YYABORT;
++	  }
++	}
++	| BINARY { $$= &my_charset_bin; }
++	;
++
++old_or_new_charset_name_or_default:
++	old_or_new_charset_name { $$=$1;   }
++	| DEFAULT    { $$=NULL; } ;
++
++collation_name:
++	ident_or_text
++	{
++	  if (!($$=get_charset_by_name($1.str,MYF(0))))
++	  {
++	    my_error(ER_UNKNOWN_COLLATION, MYF(0), $1.str);
++	    MYSQL_YYABORT;
++	  }
++	};
++
++opt_collate:
++	/* empty */	{ $$=NULL; }
++	| COLLATE_SYM collation_name_or_default { $$=$2; }
++	;
++
++collation_name_or_default:
++	collation_name { $$=$1;   }
++	| DEFAULT    { $$=NULL; } ;
++
++opt_default:
++	/* empty */	{}
++	| DEFAULT	{};
++
++opt_binary:
++	/* empty */			{ Lex->charset=NULL; }
++	| ASCII_SYM opt_bin_mod		{ Lex->charset=&my_charset_latin1; }
++	| BYTE_SYM			{ Lex->charset=&my_charset_bin; }
++	| UNICODE_SYM opt_bin_mod
++	{
++	  if (!(Lex->charset=get_charset_by_csname("ucs2",
++                                                   MY_CS_PRIMARY,MYF(0))))
++	  {
++	    my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2");
++	    MYSQL_YYABORT;
++	  }
++	}
++	| charset charset_name opt_bin_mod	{ Lex->charset=$2; }
++        | BINARY opt_bin_charset { Lex->type|= BINCMP_FLAG; };
++
++opt_bin_mod:
++	/* empty */ { }
++	| BINARY { Lex->type|= BINCMP_FLAG; };
++
++opt_bin_charset:
++        /* empty */ { Lex->charset= NULL; }
++	| ASCII_SYM	{ Lex->charset=&my_charset_latin1; }
++	| UNICODE_SYM
++	{
++	  if (!(Lex->charset=get_charset_by_csname("ucs2",
++                                                   MY_CS_PRIMARY,MYF(0))))
++	  {
++	    my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2");
++	    MYSQL_YYABORT;
++	  }
++	}
++	| charset charset_name	{ Lex->charset=$2; } ;
++
++opt_primary:
++	/* empty */
++	| PRIMARY_SYM
++	;
++
++references:
++	REFERENCES table_ident
++	{
++	  LEX *lex=Lex;
++	  lex->fk_delete_opt= lex->fk_update_opt= lex->fk_match_option= 0;
++	  lex->ref_list.empty();
++	}
++	opt_ref_list
++	{
++	  $$=$2;
++	};
++
++opt_ref_list:
++	/* empty */ opt_on_delete {}
++	| '(' ref_list ')' opt_on_delete {};
++
++ref_list:
++	ref_list ',' ident	{ Lex->ref_list.push_back(new key_part_spec($3.str)); }
++	| ident			{ Lex->ref_list.push_back(new key_part_spec($1.str)); };
++
++
++opt_on_delete:
++	/* empty */ {}
++	| opt_on_delete_list {};
++
++opt_on_delete_list:
++	opt_on_delete_list opt_on_delete_item {}
++	| opt_on_delete_item {};
++
++opt_on_delete_item:
++	ON DELETE_SYM delete_option   { Lex->fk_delete_opt= $3; }
++	| ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; }
++	| MATCH FULL	{ Lex->fk_match_option= foreign_key::FK_MATCH_FULL; }
++	| MATCH PARTIAL { Lex->fk_match_option= foreign_key::FK_MATCH_PARTIAL; }
++	| MATCH SIMPLE_SYM { Lex->fk_match_option= foreign_key::FK_MATCH_SIMPLE; };
++
++delete_option:
++	RESTRICT	 { $$= (int) foreign_key::FK_OPTION_RESTRICT; }
++	| CASCADE	 { $$= (int) foreign_key::FK_OPTION_CASCADE; }
++	| SET NULL_SYM   { $$= (int) foreign_key::FK_OPTION_SET_NULL; }
++	| NO_SYM ACTION  { $$= (int) foreign_key::FK_OPTION_NO_ACTION; }
++	| SET DEFAULT    { $$= (int) foreign_key::FK_OPTION_DEFAULT;  };
++
++key_type:
++	key_or_index			    { $$= Key::MULTIPLE; }
++	| FULLTEXT_SYM opt_key_or_index	    { $$= Key::FULLTEXT; }
++	| SPATIAL_SYM opt_key_or_index
++	  {
++#ifdef HAVE_SPATIAL
++	    $$= Key::SPATIAL;
++#else
++	    my_error(ER_FEATURE_DISABLED, MYF(0),
++                     sym_group_geom.name, sym_group_geom.needed_define);
++	    MYSQL_YYABORT;
++#endif
++	  };
++
++constraint_key_type:
++	PRIMARY_SYM KEY_SYM  { $$= Key::PRIMARY; }
++	| UNIQUE_SYM opt_key_or_index { $$= Key::UNIQUE; };
++
++key_or_index:
++	KEY_SYM {}
++	| INDEX_SYM {};
++
++opt_key_or_index:
++	/* empty */ {}
++	| key_or_index
++	;
++
++keys_or_index:
++	KEYS {}
++	| INDEX_SYM {}
++	| INDEXES {};
++
++opt_unique_or_fulltext:
++	/* empty */	{ $$= Key::MULTIPLE; }
++	| UNIQUE_SYM	{ $$= Key::UNIQUE; }
++	| FULLTEXT_SYM	{ $$= Key::FULLTEXT;}
++	| SPATIAL_SYM
++	  {
++#ifdef HAVE_SPATIAL
++	    $$= Key::SPATIAL;
++#else
++            my_error(ER_FEATURE_DISABLED, MYF(0),
++                     sym_group_geom.name, sym_group_geom.needed_define);
++	    MYSQL_YYABORT;
++#endif
++	  }
++        ;
++
++key_alg:
++	/* empty */		   { $$= HA_KEY_ALG_UNDEF; }
++	| USING opt_btree_or_rtree { $$= $2; }
++	| TYPE_SYM opt_btree_or_rtree  { $$= $2; };
++
++opt_btree_or_rtree:
++	BTREE_SYM	{ $$= HA_KEY_ALG_BTREE; }
++	| RTREE_SYM
++	  {
++	    $$= HA_KEY_ALG_RTREE;
++	  }
++	| HASH_SYM	{ $$= HA_KEY_ALG_HASH; };
++
++key_list:
++	key_list ',' key_part order_dir { Lex->col_list.push_back($3); }
++	| key_part order_dir		{ Lex->col_list.push_back($1); };
++
++key_part:
++	ident			{ $$=new key_part_spec($1.str); }
++	| ident '(' NUM ')'	
++        {
++          int key_part_len= atoi($3.str);
++          if (!key_part_len)
++          {
++            my_error(ER_KEY_PART_0, MYF(0), $1.str);
++          }
++          $$=new key_part_spec($1.str,(uint) key_part_len);
++        };
++
++opt_ident:
++	/* empty */	{ $$=(char*) 0; }	/* Defaultlength */
++	| field_ident	{ $$=$1.str; };
++
++opt_component:
++        /* empty */      { $$= null_lex_str; }
++        | '.' ident      { $$= $2; };
++
++string_list:
++	text_string			{ Lex->interval_list.push_back($1); }
++	| string_list ',' text_string	{ Lex->interval_list.push_back($3); };
++
++/*
++** Alter table
++*/
++
++alter:
++	ALTER opt_ignore TABLE_SYM table_ident
++	{
++	  THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++	  lex->sql_command= SQLCOM_ALTER_TABLE;
++	  lex->name= 0;
++	  lex->duplicates= DUP_ERROR; 
++	  if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
++						 TL_OPTION_UPDATING))
++	    MYSQL_YYABORT;
++	  lex->col_list.empty();
++          lex->select_lex.init_order();
++	  lex->select_lex.db=
++            ((TABLE_LIST*) lex->select_lex.table_list.first)->db;
++          lex->name=0;
++	  bzero((char*) &lex->create_info,sizeof(lex->create_info));
++	  lex->create_info.db_type= DB_TYPE_DEFAULT;
++	  lex->create_info.default_table_charset= NULL;
++	  lex->create_info.row_type= ROW_TYPE_NOT_USED;
++          lex->alter_info.reset();
++	}
++	alter_list
++	{}
++	| ALTER DATABASE ident_or_empty
++          {
++            Lex->create_info.default_table_charset= NULL;
++            Lex->create_info.used_fields= 0;
++          }
++          create_database_options
++	  {
++	    LEX *lex=Lex;
++	    lex->sql_command=SQLCOM_ALTER_DB;
++	    lex->name= $3;
++            if (lex->name == NULL && lex->copy_db_to(&lex->name, NULL))
++              MYSQL_YYABORT;
++	  }
++	| ALTER PROCEDURE sp_name
++	  {
++	    LEX *lex= Lex;
++
++	    if (lex->sphead)
++	    {
++	      my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
++	      MYSQL_YYABORT;
++	    }
++	    bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
++          }
++	  sp_a_chistics
++	  {
++	    LEX *lex=Lex;
++
++	    lex->sql_command= SQLCOM_ALTER_PROCEDURE;
++	    lex->spname= $3;
++	  }
++	| ALTER FUNCTION_SYM sp_name
++	  {
++	    LEX *lex= Lex;
++
++	    if (lex->sphead)
++	    {
++	      my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
++	      MYSQL_YYABORT;
++	    }
++	    bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
++          }
++	  sp_a_chistics
++	  {
++	    LEX *lex=Lex;
++
++	    lex->sql_command= SQLCOM_ALTER_FUNCTION;
++	    lex->spname= $3;
++	  }
++        | ALTER view_algorithm_opt definer view_suid
++          VIEW_SYM table_ident
++	  {
++	    THD *thd= YYTHD;
++	    LEX *lex= thd->lex;
++	    if (lex->sphead)
++            {
++              my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW");
++              MYSQL_YYABORT;
++            }
++	    lex->sql_command= SQLCOM_CREATE_VIEW;
++	    lex->create_view_mode= VIEW_ALTER;
++	    /* first table in list is target VIEW name */
++	    lex->select_lex.add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING);
++	  }
++	  view_list_opt AS view_select view_check_option
++	  {}
++	;
++
++ident_or_empty:
++	/* empty */  { $$= 0; }
++	| ident      { $$= $1.str; };
++
++alter_list:
++	| DISCARD TABLESPACE { Lex->alter_info.tablespace_op= DISCARD_TABLESPACE; }
++	| IMPORT TABLESPACE { Lex->alter_info.tablespace_op= IMPORT_TABLESPACE; }
++        | alter_list_item
++	| alter_list ',' alter_list_item;
++
++add_column:
++	ADD opt_column
++	{
++	  LEX *lex=Lex;
++	  lex->change=0;
++	  lex->alter_info.flags|= ALTER_ADD_COLUMN;
++	};
++
++alter_list_item:
++	add_column column_def opt_place { }
++	| ADD key_def
++	  {
++	    Lex->alter_info.flags|= ALTER_ADD_INDEX;
++	  }
++	| add_column '(' field_list ')'
++          {
++	    Lex->alter_info.flags|= ALTER_ADD_COLUMN | ALTER_ADD_INDEX;
++          }
++	| CHANGE opt_column field_ident
++	  {
++	     LEX *lex=Lex;
++	     lex->change= $3.str;
++	     lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
++	  }
++          field_spec opt_place
++        | MODIFY_SYM opt_column field_ident
++          {
++            LEX *lex=Lex;
++            lex->length=lex->dec=0; lex->type=0;
++            lex->default_value= lex->on_update_value= 0;
++            lex->comment=null_lex_str;
++	    lex->charset= NULL;
++	    lex->alter_info.flags|= ALTER_CHANGE_COLUMN;
++          }
++          type opt_attribute
++          {
++            LEX *lex=Lex;
++            if (add_field_to_list(lex->thd,$3.str,
++                                  (enum enum_field_types) $5,
++                                  lex->length,lex->dec,lex->type,
++                                  lex->default_value, lex->on_update_value,
++                                  &lex->comment,
++				  $3.str, &lex->interval_list, lex->charset,
++				  lex->uint_geom_type))
++	       MYSQL_YYABORT;
++          }
++          opt_place
++	| DROP opt_column field_ident opt_restrict
++	  {
++	    LEX *lex=Lex;
++	    lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::COLUMN,
++                                                               $3.str));
++	    lex->alter_info.flags|= ALTER_DROP_COLUMN;
++	  }
++	| DROP FOREIGN KEY_SYM opt_ident
++          {
++	    Lex->alter_info.flags|= ALTER_DROP_INDEX;
++          }
++	| DROP PRIMARY_SYM KEY_SYM
++	  {
++	    LEX *lex=Lex;
++	    lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
++				               primary_key_name));
++	    lex->alter_info.flags|= ALTER_DROP_INDEX;
++	  }
++	| DROP key_or_index field_ident
++	  {
++	    LEX *lex=Lex;
++	    lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
++					                       $3.str));
++	    lex->alter_info.flags|= ALTER_DROP_INDEX;
++	  }
++	| DISABLE_SYM KEYS
++          {
++	    LEX *lex=Lex;
++            lex->alter_info.keys_onoff= DISABLE;
++	    lex->alter_info.flags|= ALTER_KEYS_ONOFF;
++          }
++	| ENABLE_SYM KEYS
++          {
++	    LEX *lex=Lex;
++            lex->alter_info.keys_onoff= ENABLE;
++	    lex->alter_info.flags|= ALTER_KEYS_ONOFF;
++          }
++	| ALTER opt_column field_ident SET DEFAULT signed_literal
++	  {
++	    LEX *lex=Lex;
++	    lex->alter_info.alter_list.push_back(new Alter_column($3.str,$6));
++	    lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT;
++	  }
++	| ALTER opt_column field_ident DROP DEFAULT
++	  {
++	    LEX *lex=Lex;
++	    lex->alter_info.alter_list.push_back(new Alter_column($3.str,
++                                                                  (Item*) 0));
++	    lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT;
++	  }
++	| RENAME opt_to table_ident
++	  {
++	    LEX *lex=Lex;
++	    lex->select_lex.db=$3->db.str;
++            if (lex->select_lex.db == NULL &&
++                lex->copy_db_to(&lex->select_lex.db, NULL))
++            {
++              MYSQL_YYABORT;
++            }
++            if (check_table_name($3->table.str,$3->table.length) ||
++                $3->db.str && check_db_name($3->db.str))
++            {
++              my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
++              MYSQL_YYABORT;
++            }
++	    lex->name= $3->table.str;
++	    lex->alter_info.flags|= ALTER_RENAME;
++	  }
++	| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
++	  {
++	    if (!$4)
++	    {
++	      THD *thd= YYTHD;
++	      $4= thd->variables.collation_database;
++	    }
++	    $5= $5 ? $5 : $4;
++	    if (!my_charset_same($4,$5))
++	    {
++	      my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
++                       $5->name, $4->csname);
++	      MYSQL_YYABORT;
++	    }
++	    LEX *lex= Lex;
++	    lex->create_info.table_charset=
++	      lex->create_info.default_table_charset= $5;
++	    lex->create_info.used_fields|= (HA_CREATE_USED_CHARSET |
++					    HA_CREATE_USED_DEFAULT_CHARSET);
++	    lex->alter_info.flags|= ALTER_CONVERT;
++	  }
++        | create_table_options_space_separated
++	  {
++	    LEX *lex=Lex;
++	    lex->alter_info.flags|= ALTER_OPTIONS;
++	  }
++	| FORCE_SYM
++	  {
++	    Lex->alter_info.flags|= ALTER_FORCE;
++	   }
++	| alter_order_clause
++	  {
++	    LEX *lex=Lex;
++	    lex->alter_info.flags|= ALTER_ORDER;
++	  };
++
++opt_column:
++	/* empty */	{}
++	| COLUMN_SYM	{};
++
++opt_ignore:
++	/* empty */	{ Lex->ignore= 0;}
++	| IGNORE_SYM	{ Lex->ignore= 1;}
++	;
++
++opt_restrict:
++	/* empty */	{ Lex->drop_mode= DROP_DEFAULT; }
++	| RESTRICT	{ Lex->drop_mode= DROP_RESTRICT; }
++	| CASCADE	{ Lex->drop_mode= DROP_CASCADE; }
++	;
++
++opt_place:
++	/* empty */	{}
++	| AFTER_SYM ident { store_position_for_column($2.str); }
++	| FIRST_SYM	  { store_position_for_column(first_keyword); };
++
++opt_to:
++	/* empty */	{}
++	| TO_SYM	{}
++	| EQ		{}
++	| AS		{};
++
++/*
++  SLAVE START and SLAVE STOP are deprecated. We keep them for compatibility.
++*/
++
++slave:
++	  START_SYM SLAVE slave_thread_opts
++          {
++	    LEX *lex=Lex;
++            lex->sql_command = SQLCOM_SLAVE_START;
++	    lex->type = 0;
++	    /* We'll use mi structure for UNTIL options */
++	    bzero((char*) &lex->mi, sizeof(lex->mi));
++            /* If you change this code don't forget to update SLAVE START too */
++          }
++          slave_until
++          {}
++        | STOP_SYM SLAVE slave_thread_opts
++          {
++	    LEX *lex=Lex;
++            lex->sql_command = SQLCOM_SLAVE_STOP;
++	    lex->type = 0;
++            /* If you change this code don't forget to update SLAVE STOP too */
++          }
++	| SLAVE START_SYM slave_thread_opts
++         {
++	   LEX *lex=Lex;
++           lex->sql_command = SQLCOM_SLAVE_START;
++	   lex->type = 0;
++	    /* We'll use mi structure for UNTIL options */
++	    bzero((char*) &lex->mi, sizeof(lex->mi));
++          }
++          slave_until
++          {}
++	| SLAVE STOP_SYM slave_thread_opts
++         {
++	   LEX *lex=Lex;
++           lex->sql_command = SQLCOM_SLAVE_STOP;
++	   lex->type = 0;
++         }
++        ;
++
++
++start:
++	START_SYM TRANSACTION_SYM start_transaction_opts
++        {
++          LEX *lex= Lex;
++          lex->sql_command= SQLCOM_BEGIN;
++          lex->start_transaction_opt= $3;
++        }
++	;
++
++start_transaction_opts:
++        /*empty*/ { $$ = 0; }
++        | WITH CONSISTENT_SYM SNAPSHOT_SYM
++        {
++           $$= MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT;
++        }
++        ;
++
++slave_thread_opts:
++	{ Lex->slave_thd_opt= 0; }
++	slave_thread_opt_list
++        {}
++	;
++
++slave_thread_opt_list:
++	slave_thread_opt
++	| slave_thread_opt_list ',' slave_thread_opt
++	;
++
++slave_thread_opt:
++	/*empty*/	{}
++	| SQL_THREAD	{ Lex->slave_thd_opt|=SLAVE_SQL; }
++	| RELAY_THREAD 	{ Lex->slave_thd_opt|=SLAVE_IO; }
++	;
++
++slave_until:
++	/*empty*/	{}
++	| UNTIL_SYM slave_until_opts
++          {
++            LEX *lex=Lex;
++            if ((lex->mi.log_file_name || lex->mi.pos) &&
++                (lex->mi.relay_log_name || lex->mi.relay_log_pos) ||
++                !((lex->mi.log_file_name && lex->mi.pos) ||
++                  (lex->mi.relay_log_name && lex->mi.relay_log_pos)))
++            {
++               my_message(ER_BAD_SLAVE_UNTIL_COND,
++                          ER(ER_BAD_SLAVE_UNTIL_COND), MYF(0));
++               MYSQL_YYABORT;
++            }
++
++          }
++	;
++
++slave_until_opts:
++       master_file_def
++       | slave_until_opts ',' master_file_def ;
++
++
++restore:
++	RESTORE_SYM table_or_tables
++	{
++	   Lex->sql_command = SQLCOM_RESTORE_TABLE;
++	}
++	table_list FROM TEXT_STRING_sys
++        {
++	  Lex->backup_dir = $6.str;
++        };
++
++backup:
++	BACKUP_SYM table_or_tables
++	{
++	   Lex->sql_command = SQLCOM_BACKUP_TABLE;
++	}
++	table_list TO_SYM TEXT_STRING_sys
++        {
++	  Lex->backup_dir = $6.str;
++        };
++
++checksum:
++        CHECKSUM_SYM table_or_tables
++	{
++	   LEX *lex=Lex;
++	   lex->sql_command = SQLCOM_CHECKSUM;
++	}
++	table_list opt_checksum_type
++        {}
++	;
++
++opt_checksum_type:
++        /* nothing */  { Lex->check_opt.flags= 0; }
++	| QUICK        { Lex->check_opt.flags= T_QUICK; }
++	| EXTENDED_SYM { Lex->check_opt.flags= T_EXTEND; }
++        ;
++
++repair:
++	REPAIR opt_no_write_to_binlog table_or_tables
++	{
++	   LEX *lex=Lex;
++	   lex->sql_command = SQLCOM_REPAIR;
++           lex->no_write_to_binlog= $2;
++	   lex->check_opt.init();
++	}
++	table_list opt_mi_repair_type
++	{}
++	;
++
++opt_mi_repair_type:
++	/* empty */ { Lex->check_opt.flags = T_MEDIUM; }
++	| mi_repair_types {};
++
++mi_repair_types:
++	mi_repair_type {}
++	| mi_repair_type mi_repair_types {};
++
++mi_repair_type:
++	QUICK          { Lex->check_opt.flags|= T_QUICK; }
++	| EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
++        | USE_FRM      { Lex->check_opt.sql_flags|= TT_USEFRM; };
++
++analyze:
++	ANALYZE_SYM opt_no_write_to_binlog table_or_tables
++	{
++	   LEX *lex=Lex;
++	   lex->sql_command = SQLCOM_ANALYZE;
++           lex->no_write_to_binlog= $2;
++	   lex->check_opt.init();
++	}
++	table_list opt_mi_check_type
++	{}
++	;
++
++check:
++	CHECK_SYM table_or_tables
++	{
++	  LEX *lex=Lex;
++
++	  if (lex->sphead)
++	  {
++	    my_error(ER_SP_BADSTATEMENT, MYF(0), "CHECK");
++	    MYSQL_YYABORT;
++	  }
++	  lex->sql_command = SQLCOM_CHECK;
++	  lex->check_opt.init();
++	}
++	table_list opt_mi_check_type
++	{}
++	;
++
++opt_mi_check_type:
++	/* empty */ { Lex->check_opt.flags = T_MEDIUM; }
++	| mi_check_types {};
++
++mi_check_types:
++	mi_check_type {}
++	| mi_check_type mi_check_types {};
++
++mi_check_type:
++	QUICK      { Lex->check_opt.flags|= T_QUICK; }
++	| FAST_SYM { Lex->check_opt.flags|= T_FAST; }
++	| MEDIUM_SYM { Lex->check_opt.flags|= T_MEDIUM; }
++	| EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
++	| CHANGED  { Lex->check_opt.flags|= T_CHECK_ONLY_CHANGED; }
++        | FOR_SYM UPGRADE_SYM { Lex->check_opt.sql_flags|= TT_FOR_UPGRADE; };
++
++optimize:
++	OPTIMIZE opt_no_write_to_binlog table_or_tables
++	{
++	   LEX *lex=Lex;
++	   lex->sql_command = SQLCOM_OPTIMIZE;
++           lex->no_write_to_binlog= $2;
++	   lex->check_opt.init();
++	}
++	table_list opt_mi_check_type
++	{}
++	;
++
++opt_no_write_to_binlog:
++	/* empty */        { $$= 0; }
++	| NO_WRITE_TO_BINLOG  { $$= 1; }
++	| LOCAL_SYM  { $$= 1; }
++	;
++
++rename:
++	RENAME table_or_tables
++	{
++          Lex->sql_command= SQLCOM_RENAME_TABLE;
++	}
++	table_to_table_list
++	{}
++	| RENAME USER clear_privileges rename_list
++          {
++	    Lex->sql_command = SQLCOM_RENAME_USER;
++          }
++	;
++
++rename_list:
++        user TO_SYM user
++        {
++          if (Lex->users_list.push_back($1) || Lex->users_list.push_back($3))
++            MYSQL_YYABORT;
++        }
++        | rename_list ',' user TO_SYM user
++          {
++            if (Lex->users_list.push_back($3) || Lex->users_list.push_back($5))
++              MYSQL_YYABORT;
++          }
++        ;
++
++table_to_table_list:
++	table_to_table
++	| table_to_table_list ',' table_to_table;
++
++table_to_table:
++	table_ident TO_SYM table_ident
++	{
++	  LEX *lex=Lex;
++	  SELECT_LEX *sl= lex->current_select;
++	  if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING,
++				     TL_IGNORE) ||
++	      !sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING,
++				     TL_IGNORE))
++	    MYSQL_YYABORT;
++	};
++
++keycache:
++        CACHE_SYM INDEX_SYM keycache_list IN_SYM key_cache_name
++        {
++          LEX *lex=Lex;
++          lex->sql_command= SQLCOM_ASSIGN_TO_KEYCACHE;
++	  lex->ident= $5;
++        }
++        ;
++
++keycache_list:
++        assign_to_keycache
++        | keycache_list ',' assign_to_keycache;
++
++assign_to_keycache:
++        table_ident cache_keys_spec
++        {
++          LEX *lex=Lex;
++          SELECT_LEX *sel= &lex->select_lex;
++          if (!sel->add_table_to_list(lex->thd, $1, NULL, 0,
++                                      TL_READ,
++                                      sel->get_use_index(),
++                                      (List<String> *)0))
++            MYSQL_YYABORT;
++        }
++        ;
++
++key_cache_name:
++	ident	   { $$= $1; }
++	| DEFAULT  { $$ = default_key_cache_base; }
++	;
++
++preload:
++	LOAD INDEX_SYM INTO CACHE_SYM
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command=SQLCOM_PRELOAD_KEYS;
++	}
++	preload_list
++	{}
++	;
++
++preload_list:
++	preload_keys
++	| preload_list ',' preload_keys;
++
++preload_keys:
++	table_ident cache_keys_spec opt_ignore_leaves
++	{
++	  LEX *lex=Lex;
++	  SELECT_LEX *sel= &lex->select_lex;
++	  if (!sel->add_table_to_list(lex->thd, $1, NULL, $3,
++                                      TL_READ,
++                                      sel->get_use_index(),
++                                      (List<String> *)0))
++            MYSQL_YYABORT;
++	}
++	;
++
++cache_keys_spec:
++        { Select->interval_list.empty(); }
++        cache_key_list_or_empty
++        {
++          LEX *lex=Lex;
++          SELECT_LEX *sel= &lex->select_lex;
++          sel->use_index= sel->interval_list;
++        }
++        ;
++
++cache_key_list_or_empty:
++	/* empty */	{ Lex->select_lex.use_index_ptr= 0; }
++	| opt_key_or_index '(' key_usage_list2 ')'
++	  {
++            SELECT_LEX *sel= &Lex->select_lex;
++	    sel->use_index_ptr= &sel->use_index;
++	  }
++	;
++
++opt_ignore_leaves:
++	/* empty */
++	{ $$= 0; }
++	| IGNORE_SYM LEAVES { $$= TL_OPTION_IGNORE_LEAVES; }
++	;
++
++/*
++  Select : retrieve data from table
++*/
++
++
++select:
++	select_init
++	{
++	  LEX *lex= Lex;
++	  lex->sql_command= SQLCOM_SELECT;
++	}
++	;
++
++/* Need select_init2 for subselects. */
++select_init:
++	SELECT_SYM select_init2
++	|
++	'(' select_paren ')' union_opt;
++
++select_paren:
++	SELECT_SYM select_part2
++	  {
++	    LEX *lex= Lex;
++            SELECT_LEX * sel= lex->current_select;
++	    if (sel->set_braces(1))
++	    {
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++	      MYSQL_YYABORT;
++	    }
++            if (sel->linkage == UNION_TYPE &&
++                !sel->master_unit()->first_select()->braces &&
++                sel->master_unit()->first_select()->linkage ==
++                UNION_TYPE)
++            {
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++              MYSQL_YYABORT;
++            }
++            /* select in braces, can't contain global parameters */
++	    if (sel->master_unit()->fake_select_lex)
++              sel->master_unit()->global_parameters=
++                 sel->master_unit()->fake_select_lex;
++          }
++	| '(' select_paren ')';
++
++select_init2:
++	select_part2
++        {
++	  LEX *lex= Lex;
++          SELECT_LEX * sel= lex->current_select;
++          if (lex->current_select->set_braces(0))
++	  {
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++	  }
++	  if (sel->linkage == UNION_TYPE &&
++	      sel->master_unit()->first_select()->braces)
++	  {
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++	  }
++	}
++	union_clause
++	;
++
++select_part2:
++	{
++	  LEX *lex= Lex;
++	  SELECT_LEX *sel= lex->current_select;
++	  if (sel->linkage != UNION_TYPE)
++	    mysql_init_select(lex);
++	  lex->current_select->parsing_place= SELECT_LIST;
++	}
++	select_options select_item_list
++	{
++	  Select->parsing_place= NO_MATTER;
++	}
++	select_into select_lock_type;
++
++select_into:
++	opt_order_clause opt_limit_clause {}
++        | into
++	| select_from
++	| into select_from
++	| select_from into;
++
++select_from:
++        FROM join_table_list where_clause group_clause having_clause
++	       opt_order_clause opt_limit_clause procedure_clause
++          {
++            Select->context.table_list=
++              Select->context.first_name_resolution_table= 
++                (TABLE_LIST *) Select->table_list.first;
++          }
++        | FROM DUAL_SYM where_clause opt_limit_clause
++          /* oracle compatibility: oracle always requires FROM clause,
++             and DUAL is system table without fields.
++             Is "SELECT 1 FROM DUAL" any better than "SELECT 1" ?
++          Hmmm :) */
++	;
++
++select_options:
++	/* empty*/
++	| select_option_list
++	  {
++	    if (test_all_bits(Select->options, SELECT_ALL | SELECT_DISTINCT))
++	    {
++	      my_error(ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT");
++              MYSQL_YYABORT;
++	    }
++          }
++	  ;
++
++select_option_list:
++	select_option_list select_option
++	| select_option;
++
++select_option:
++	STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; }
++	| HIGH_PRIORITY
++	  {
++	    if (check_simple_select())
++	      MYSQL_YYABORT;
++	    Lex->lock_option= TL_READ_HIGH_PRIORITY;
++	  }
++	| DISTINCT         { Select->options|= SELECT_DISTINCT; }
++	| SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
++	| SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; }
++	| SQL_BUFFER_RESULT
++	  {
++	    if (check_simple_select())
++	      MYSQL_YYABORT;
++	    Select->options|= OPTION_BUFFER_RESULT;
++	  }
++	| SQL_CALC_FOUND_ROWS
++	  {
++	    if (check_simple_select())
++	      MYSQL_YYABORT;
++	    Select->options|= OPTION_FOUND_ROWS;
++	  }
++	| SQL_NO_CACHE_SYM
++          {
++            Lex->safe_to_cache_query=0;
++	    Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
++            Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
++          }
++	| SQL_CACHE_SYM
++	  {
++            /*
++             Honor this flag only if SQL_NO_CACHE wasn't specified AND
++             we are parsing the outermost SELECT in the query.
++            */
++            if (Lex->select_lex.sql_cache != SELECT_LEX::SQL_NO_CACHE &&
++                Lex->current_select == &Lex->select_lex)
++            {
++              Lex->safe_to_cache_query=1;
++	      Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
++              Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
++            }
++	  }
++	| ALL		    { Select->options|= SELECT_ALL; }
++	;
++
++select_lock_type:
++	/* empty */
++	| FOR_SYM UPDATE_SYM
++	  {
++	    LEX *lex=Lex;
++	    lex->current_select->set_lock_for_tables(TL_WRITE);
++	    lex->safe_to_cache_query=0;
++	  }
++	| LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
++	  {
++	    LEX *lex=Lex;
++	    lex->current_select->
++	      set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
++	    lex->safe_to_cache_query=0;
++	  }
++	;
++
++select_item_list:
++	  select_item_list ',' select_item
++	| select_item
++	| '*'
++	  {
++	    THD *thd= YYTHD;
++	    if (add_item_to_list(thd,
++                                 new Item_field(&thd->lex->current_select->
++                                                context,
++                                                NULL, NULL, "*")))
++	      MYSQL_YYABORT;
++	    (thd->lex->current_select->with_wild)++;
++	  };
++
++
++select_item:
++	  remember_name select_item2 remember_end select_alias
++	  {
++            THD *thd= YYTHD;
++            DBUG_ASSERT($1 < $3);
++
++	    if (add_item_to_list(thd, $2))
++	      MYSQL_YYABORT;
++	    if ($4.str)
++            {
++              $2->is_autogenerated_name= FALSE;
++	      $2->set_name($4.str, $4.length, system_charset_info);
++            }
++	    else if (!$2->name)
++            {
++	      $2->set_name($1, (uint) ($3 - $1), thd->charset());
++	    }
++	  };
++
++
++remember_name:
++	{
++          THD *thd= YYTHD;
++          Lex_input_stream *lip= thd->m_lip;
++          $$= (char*) lip->tok_start;
++        };
++
++remember_end:
++	{
++          THD *thd= YYTHD;
++          Lex_input_stream *lip= thd->m_lip;
++          $$=(char*) lip->tok_end;
++        };
++
++select_item2:
++	table_wild	{ $$=$1; } /* table.* */
++	| expr		{ $$=$1; };
++
++select_alias:
++	/* empty */		{ $$=null_lex_str;}
++	| AS ident		{ $$=$2; }
++	| AS TEXT_STRING_sys	{ $$=$2; }
++	| ident			{ $$=$1; }
++	| TEXT_STRING_sys	{ $$=$1; }
++	;
++
++optional_braces:
++	/* empty */ {}
++	| '(' ')' {};
++
++/* all possible expressions */
++expr:
++          expr or expr %prec OR_SYM
++          {
++            /*
++              Design notes:
++              Do not use a manually maintained stack like thd->lex->xxx_list,
++              but use the internal bison stack ($$, $1 and $3) instead.
++              Using the bison stack is:
++              - more robust to changes in the grammar,
++              - guaranteed to be in sync with the parser state,
++              - better for performances (no memory allocation).
++            */
++            Item_cond_or *item1;
++            Item_cond_or *item3;
++            if (is_cond_or($1))
++            {
++              item1= (Item_cond_or*) $1;
++              if (is_cond_or($3))
++              {
++                item3= (Item_cond_or*) $3;
++                /*
++                  (X1 OR X2) OR (Y1 OR Y2) ==> OR (X1, X2, Y1, Y2)
++                */
++                item3->add_at_head(item1->argument_list());
++                $$ = $3;
++              }
++              else
++              {
++                /*
++                  (X1 OR X2) OR Y ==> OR (X1, X2, Y)
++                */
++                item1->add($3);
++                $$ = $1;
++              }
++            }
++            else if (is_cond_or($3))
++            {
++              item3= (Item_cond_or*) $3;
++              /*
++                X OR (Y1 OR Y2) ==> OR (X, Y1, Y2)
++              */
++              item3->add_at_head($1);
++              $$ = $3;
++            }
++            else
++            {
++              /* X OR Y */
++              $$ = new (YYTHD->mem_root) Item_cond_or($1, $3);
++            }
++          }
++        | expr XOR expr %prec XOR
++          {
++            /* XOR is a proprietary extension */
++            $$ = new (YYTHD->mem_root) Item_cond_xor($1, $3);
++          }
++        | expr and expr %prec AND_SYM
++          {
++            /* See comments in rule expr: expr or expr */
++            Item_cond_and *item1;
++            Item_cond_and *item3;
++            if (is_cond_and($1))
++            {
++              item1= (Item_cond_and*) $1;
++              if (is_cond_and($3))
++              {
++                item3= (Item_cond_and*) $3;
++                /*
++                  (X1 AND X2) AND (Y1 AND Y2) ==> AND (X1, X2, Y1, Y2)
++                */
++                item3->add_at_head(item1->argument_list());
++                $$ = $3;
++              }
++              else
++              {
++                /*
++                  (X1 AND X2) AND Y ==> AND (X1, X2, Y)
++                */
++                item1->add($3);
++                $$ = $1;
++              }
++            }
++            else if (is_cond_and($3))
++            {
++              item3= (Item_cond_and*) $3;
++              /*
++                X AND (Y1 AND Y2) ==> AND (X, Y1, Y2)
++              */
++              item3->add_at_head($1);
++              $$ = $3;
++            }
++            else
++            {
++              /* X AND Y */
++              $$ = new (YYTHD->mem_root) Item_cond_and($1, $3);
++            }
++          }
++	| NOT_SYM expr %prec NOT_SYM
++          { $$= negate_expression(YYTHD, $2); }
++        | bool_pri IS TRUE_SYM %prec IS
++          { $$= new (YYTHD->mem_root) Item_func_istrue($1); }
++        | bool_pri IS not TRUE_SYM %prec IS
++          { $$= new (YYTHD->mem_root) Item_func_isnottrue($1); }
++        | bool_pri IS FALSE_SYM %prec IS
++          { $$= new (YYTHD->mem_root) Item_func_isfalse($1); }
++        | bool_pri IS not FALSE_SYM %prec IS
++          { $$= new (YYTHD->mem_root) Item_func_isnotfalse($1); }
++        | bool_pri IS UNKNOWN_SYM %prec IS
++          { $$= new Item_func_isnull($1); }
++        | bool_pri IS not UNKNOWN_SYM %prec IS
++          { $$= new Item_func_isnotnull($1); }
++        | bool_pri
++        ;
++
++bool_pri:
++	bool_pri IS NULL_SYM %prec IS
++          { $$= new Item_func_isnull($1); }
++	| bool_pri IS not NULL_SYM %prec IS
++          { $$= new Item_func_isnotnull($1); }
++	| bool_pri EQUAL_SYM predicate %prec EQUAL_SYM
++          { $$= new Item_func_equal($1,$3); }
++	| bool_pri comp_op predicate %prec EQ
++	  { $$= (*$2)(0)->create($1,$3); }
++	| bool_pri comp_op all_or_any '(' subselect ')' %prec EQ
++	  { $$= all_any_subquery_creator($1, $2, $3, $5); }
++	| predicate ;
++
++predicate:
++          bit_expr IN_SYM '(' subselect ')'
++          {
++            $$= new (YYTHD->mem_root) Item_in_subselect($1, $4);
++          }
++        | bit_expr not IN_SYM '(' subselect ')'
++          {
++            THD *thd= YYTHD;
++            Item *item= new (thd->mem_root) Item_in_subselect($1, $5);
++            $$= negate_expression(thd, item);
++          }
++        | bit_expr IN_SYM '(' expr ')'
++          {
++            $$= handle_sql2003_note184_exception(YYTHD, $1, true, $4);
++          }
++        | bit_expr IN_SYM '(' expr ',' expr_list ')'
++          { 
++            $6->push_front($4);
++            $6->push_front($1);
++            $$= new (YYTHD->mem_root) Item_func_in(*$6);
++          }
++        | bit_expr not IN_SYM '(' expr ')'
++          {
++            $$= handle_sql2003_note184_exception(YYTHD, $1, false, $5);
++          }
++        | bit_expr not IN_SYM '(' expr ',' expr_list ')'
++          {
++            $7->push_front($5);
++            $7->push_front($1);
++            Item_func_in *item = new (YYTHD->mem_root) Item_func_in(*$7);
++            item->negate();
++            $$= item;
++          }
++	| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
++	  { $$= new Item_func_between($1,$3,$5); }
++	| bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
++          {
++            Item_func_between *item= new Item_func_between($1,$4,$6);
++            item->negate();
++            $$= item;
++          }
++	| bit_expr SOUNDS_SYM LIKE bit_expr
++	  { $$= new Item_func_eq(new Item_func_soundex($1),
++				 new Item_func_soundex($4)); }
++	| bit_expr LIKE simple_expr opt_escape
++          { $$= new Item_func_like($1,$3,$4,Lex->escape_used); }
++	| bit_expr not LIKE simple_expr opt_escape
++          { $$= new Item_func_not(new Item_func_like($1,$4,$5, Lex->escape_used)); }
++	| bit_expr REGEXP bit_expr	{ $$= new Item_func_regex($1,$3); }
++	| bit_expr not REGEXP bit_expr
++          { $$= negate_expression(YYTHD, new Item_func_regex($1,$4)); }
++	| bit_expr ;
++
++bit_expr:
++          bit_expr '|' bit_expr %prec '|'
++          { $$= new Item_func_bit_or($1,$3); }
++        | bit_expr '&' bit_expr %prec '&'
++          { $$= new Item_func_bit_and($1,$3); }
++        | bit_expr SHIFT_LEFT bit_expr %prec SHIFT_LEFT
++          { $$= new Item_func_shift_left($1,$3); }
++        | bit_expr SHIFT_RIGHT bit_expr %prec SHIFT_RIGHT
++          { $$= new Item_func_shift_right($1,$3); }
++        | bit_expr '+' bit_expr %prec '+'
++          { $$= new Item_func_plus($1,$3); }
++        | bit_expr '-' bit_expr %prec '-'
++          { $$= new Item_func_minus($1,$3); }
++        | bit_expr '+' interval_expr interval %prec '+'
++          { $$= new Item_date_add_interval($1,$3,$4,0); }
++        | bit_expr '-' interval_expr interval %prec '-'
++          { $$= new Item_date_add_interval($1,$3,$4,1); }
++        | bit_expr '*' bit_expr %prec '*'
++          { $$= new Item_func_mul($1,$3); }
++        | bit_expr '/' bit_expr %prec '/'
++          { $$= new Item_func_div($1,$3); }
++        | bit_expr '%' bit_expr %prec '%'
++          { $$= new Item_func_mod($1,$3); }
++        | bit_expr DIV_SYM bit_expr %prec DIV_SYM
++          { $$= new Item_func_int_div($1,$3); }
++        | bit_expr MOD_SYM bit_expr %prec MOD_SYM
++          { $$= new Item_func_mod($1,$3); }
++        | bit_expr '^' bit_expr
++          { $$= new Item_func_bit_xor($1,$3); }
++        | simple_expr
++        ;
++
++or:	OR_SYM | OR2_SYM;
++and:	AND_SYM | AND_AND_SYM;
++not:	NOT_SYM | NOT2_SYM;
++not2:	'!' | NOT2_SYM;
++
++comp_op:  EQ		{ $$ = &comp_eq_creator; }
++	| GE		{ $$ = &comp_ge_creator; }
++	| GT_SYM	{ $$ = &comp_gt_creator; }
++	| LE		{ $$ = &comp_le_creator; }
++	| LT		{ $$ = &comp_lt_creator; }
++	| NE		{ $$ = &comp_ne_creator; }
++	;
++
++all_or_any: ALL     { $$ = 1; }
++        |   ANY_SYM { $$ = 0; }
++        ;
++
++interval_expr:
++          INTERVAL_SYM expr %prec INTERVAL_SYM
++          { $$=$2; }
++        ;
++
++simple_expr:
++	simple_ident
++ 	| simple_expr COLLATE_SYM ident_or_text %prec NEG
++	  {
++	    $$= new Item_func_set_collation($1,
++					    new Item_string($3.str,
++							    $3.length,
++                                                            YYTHD->charset()));
++	  }
++	| literal
++	| param_marker
++	| variable
++	| sum_expr
++	| simple_expr OR_OR_SYM simple_expr
++	  { $$= new Item_func_concat($1, $3); }
++	| '+' simple_expr %prec NEG	{ $$= $2; }
++	| '-' simple_expr %prec NEG	{ $$= new Item_func_neg($2); }
++	| '~' simple_expr %prec NEG	{ $$= new Item_func_bit_neg($2); }
++	| not2 simple_expr %prec NEG	{ $$= negate_expression(YYTHD, $2); }
++	| '(' subselect ')'   
++          { 
++            $$= new Item_singlerow_subselect($2); 
++          }
++	| '(' expr ')'		{ $$= $2; }
++	| '(' expr ',' expr_list ')'
++	  {
++	    $4->push_front($2);
++	    $$= new Item_row(*$4);
++	  }
++	| ROW_SYM '(' expr ',' expr_list ')'
++	  {
++	    $5->push_front($3);
++	    $$= new Item_row(*$5);
++	  }
++	| EXISTS '(' subselect ')' 
++          {
++            $$= new Item_exists_subselect($3); 
++          }
++	| '{' ident expr '}'	{ $$= $3; }
++        | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
++          { $2->push_front($5);
++            Select->add_ftfunc_to_list((Item_func_match*)
++                                        ($$=new Item_func_match(*$2,$6))); }
++	| ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); }
++	| BINARY simple_expr %prec NEG
++	  {
++            $$= create_func_cast($2, ITEM_CAST_CHAR, NULL, NULL, &my_charset_bin);
++	  }
++	| CAST_SYM '(' expr AS cast_type ')'
++	  {
++            LEX *lex= Lex;
++	    $$= create_func_cast($3, $5, lex->length, lex->dec, lex->charset);
++            if (!$$)
++              MYSQL_YYABORT;
++	  }
++	| CASE_SYM opt_expr when_list opt_else END
++	  { $$= new Item_func_case(* $3, $2, $4 ); }
++	| CONVERT_SYM '(' expr ',' cast_type ')'
++	  {
++	    $$= create_func_cast($3, $5, Lex->length, Lex->dec, Lex->charset);
++            if (!$$)
++              MYSQL_YYABORT;
++	  }
++	| CONVERT_SYM '(' expr USING charset_name ')'
++	  { $$= new Item_func_conv_charset($3,$5); }
++	| DEFAULT '(' simple_ident ')'
++	  {
++	    if ($3->is_splocal())
++	    {
++	      Item_splocal *il= static_cast<Item_splocal *>($3);
++
++	      my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str);
++	      MYSQL_YYABORT;
++	    }
++	    $$= new Item_default_value(Lex->current_context(), $3);
++	  }
++	| VALUES '(' simple_ident_nospvar ')'
++	  { $$= new Item_insert_value(Lex->current_context(), $3); }
++	| FUNC_ARG0 '(' ')'
++	  {
++	    if (!$1.symbol->create_func)
++	    {
++              my_error(ER_FEATURE_DISABLED, MYF(0),
++                       $1.symbol->group->name,
++                       $1.symbol->group->needed_define);
++	      MYSQL_YYABORT;
++	    }
++	    $$= ((Item*(*)(void))($1.symbol->create_func))();
++	  }
++	| FUNC_ARG1 '(' expr ')'
++	  {
++	    if (!$1.symbol->create_func)
++	    {
++              my_error(ER_FEATURE_DISABLED, MYF(0),
++                       $1.symbol->group->name,
++                       $1.symbol->group->needed_define);
++	      MYSQL_YYABORT;
++	    }
++	    $$= ((Item*(*)(Item*))($1.symbol->create_func))($3);
++	  }
++	| FUNC_ARG2 '(' expr ',' expr ')'
++	  {
++	    if (!$1.symbol->create_func)
++	    {
++	      my_error(ER_FEATURE_DISABLED, MYF(0),
++                       $1.symbol->group->name,
++                       $1.symbol->group->needed_define);
++	      MYSQL_YYABORT;
++	    }
++	    $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5);
++	  }
++	| FUNC_ARG3 '(' expr ',' expr ',' expr ')'
++	  {
++	    if (!$1.symbol->create_func)
++	    {
++              my_error(ER_FEATURE_DISABLED, MYF(0),
++                       $1.symbol->group->name,
++                       $1.symbol->group->needed_define);
++	      MYSQL_YYABORT;
++	    }
++	    $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7);
++	  }
++	| ADDDATE_SYM '(' expr ',' expr ')'
++	  { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 0);}
++	| ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
++	  { $$= new Item_date_add_interval($3, $6, $7, 0); }
++	| REPEAT_SYM '(' expr ',' expr ')'
++	  { $$= new Item_func_repeat($3,$5); }
++	| ATAN	'(' expr ')'
++	  { $$= new Item_func_atan($3); }
++	| ATAN	'(' expr ',' expr ')'
++	  { $$= new Item_func_atan($3,$5); }
++	| CHAR_SYM '(' expr_list ')'
++	  { $$= new Item_func_char(*$3); }
++	| CHAR_SYM '(' expr_list USING charset_name ')'
++	  { $$= new Item_func_char(*$3, $5); }
++	| CHARSET '(' expr ')'
++	  { $$= new Item_func_charset($3); }
++	| COALESCE '(' expr_list ')'
++	  { $$= new Item_func_coalesce(* $3); }
++	| COLLATION_SYM '(' expr ')'
++	  { $$= new Item_func_collation($3); }
++	| CONCAT '(' expr_list ')'
++	  { $$= new Item_func_concat(* $3); }
++	| CONCAT_WS '(' expr ',' expr_list ')'
++	  { $5->push_front($3); $$= new Item_func_concat_ws(*$5); }
++	| CONVERT_TZ_SYM '(' expr ',' expr ',' expr ')'
++	  {
++            if (Lex->add_time_zone_tables_to_query_tables(YYTHD))
++              MYSQL_YYABORT;
++	    $$= new Item_func_convert_tz($3, $5, $7);
++	  }
++	| CURDATE optional_braces
++	  { $$= new Item_func_curdate_local(); Lex->safe_to_cache_query=0; }
++	| CURTIME optional_braces
++	  { $$= new Item_func_curtime_local(); Lex->safe_to_cache_query=0; }
++	| CURTIME '(' expr ')'
++	  {
++	    $$= new Item_func_curtime_local($3);
++	    Lex->safe_to_cache_query=0;
++	  }
++	| CURRENT_USER optional_braces
++          {
++            $$= new Item_func_current_user(Lex->current_context());
++            Lex->safe_to_cache_query= 0;
++          }
++	| DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')'
++	  { $$= new Item_date_add_interval($3,$5,$6,0); }
++	| DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')'
++	  { $$= new Item_date_add_interval($3,$5,$6,1); }
++	| DATABASE '(' ')'
++	  {
++	    $$= new Item_func_database();
++            Lex->safe_to_cache_query=0;
++	  }
++	| DATE_SYM '(' expr ')'
++	  { $$= new Item_date_typecast($3); }
++	| DAY_SYM '(' expr ')'
++	  { $$= new Item_func_dayofmonth($3); }
++	| ELT_FUNC '(' expr ',' expr_list ')'
++	  { $5->push_front($3); $$= new Item_func_elt(*$5); }
++	| MAKE_SET_SYM '(' expr ',' expr_list ')'
++	  { $$= new Item_func_make_set($3, *$5); }
++	| ENCRYPT '(' expr ')'
++	  {
++	    $$= new Item_func_encrypt($3);
++	    Lex->uncacheable(UNCACHEABLE_RAND);
++	  }
++	| ENCRYPT '(' expr ',' expr ')'   { $$= new Item_func_encrypt($3,$5); }
++	| DECODE_SYM '(' expr ',' TEXT_STRING_literal ')'
++	  { $$= new Item_func_decode($3,$5.str); }
++	| ENCODE_SYM '(' expr ',' TEXT_STRING_literal ')'
++	 { $$= new Item_func_encode($3,$5.str); }
++	| DES_DECRYPT_SYM '(' expr ')'
++        { $$= new Item_func_des_decrypt($3); }
++	| DES_DECRYPT_SYM '(' expr ',' expr ')'
++        { $$= new Item_func_des_decrypt($3,$5); }
++	| DES_ENCRYPT_SYM '(' expr ')'
++        { $$= new Item_func_des_encrypt($3); }
++	| DES_ENCRYPT_SYM '(' expr ',' expr ')'
++        { $$= new Item_func_des_encrypt($3,$5); }
++	| EXPORT_SET '(' expr ',' expr ',' expr ')'
++		{ $$= new Item_func_export_set($3, $5, $7); }
++	| EXPORT_SET '(' expr ',' expr ',' expr ',' expr ')'
++		{ $$= new Item_func_export_set($3, $5, $7, $9); }
++	| EXPORT_SET '(' expr ',' expr ',' expr ',' expr ',' expr ')'
++		{ $$= new Item_func_export_set($3, $5, $7, $9, $11); }
++	| FORMAT_SYM '(' expr ',' NUM ')'
++	  { $$= new Item_func_format($3,atoi($5.str)); }
++	| FROM_UNIXTIME '(' expr ')'
++	  { $$= new Item_func_from_unixtime($3); }
++	| FROM_UNIXTIME '(' expr ',' expr ')'
++	  {
++	    $$= new Item_func_date_format (new Item_func_from_unixtime($3),$5,0);
++	  }
++	| FIELD_FUNC '(' expr ',' expr_list ')'
++	  { $5->push_front($3); $$= new Item_func_field(*$5); }
++	| geometry_function
++	  {
++#ifdef HAVE_SPATIAL
++	    $$= $1;
++#else
++	    my_error(ER_FEATURE_DISABLED, MYF(0),
++                     sym_group_geom.name, sym_group_geom.needed_define);
++	    MYSQL_YYABORT;
++#endif
++	  }
++	| GET_FORMAT '(' date_time_type  ',' expr ')'
++	  { $$= new Item_func_get_format($3, $5); }
++	| HOUR_SYM '(' expr ')'
++	  { $$= new Item_func_hour($3); }
++	| IF '(' expr ',' expr ',' expr ')'
++	  { $$= new Item_func_if($3,$5,$7); }
++	| INSERT '(' expr ',' expr ',' expr ',' expr ')'
++	  { $$= new Item_func_insert($3,$5,$7,$9); }
++	| interval_expr interval '+' expr
++	  /* we cannot put interval before - */
++	  { $$= new Item_date_add_interval($4,$1,$2,0); }
++	| interval_expr
++	  {
++            if ($1->type() != Item::ROW_ITEM)
++            {
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++              MYSQL_YYABORT;
++            }
++            $$= new Item_func_interval((Item_row *)$1);
++          }
++	| LAST_INSERT_ID '(' ')'
++	  {
++	    $$= new Item_func_last_insert_id();
++	    Lex->safe_to_cache_query= 0;
++	  }
++	| LAST_INSERT_ID '(' expr ')'
++	  {
++	    $$= new Item_func_last_insert_id($3);
++	    Lex->safe_to_cache_query= 0;
++	  }
++	| LEFT '(' expr ',' expr ')'
++	  { $$= new Item_func_left($3,$5); }
++	| LOCATE '(' expr ',' expr ')'
++	  { $$= new Item_func_locate($5,$3); }
++	| LOCATE '(' expr ',' expr ',' expr ')'
++	  { $$= new Item_func_locate($5,$3,$7); }
++	| GREATEST_SYM '(' expr ',' expr_list ')'
++	  { $5->push_front($3); $$= new Item_func_max(*$5); }
++	| LEAST_SYM '(' expr ',' expr_list ')'
++	  { $5->push_front($3); $$= new Item_func_min(*$5); }
++	| LOG_SYM '(' expr ')'
++	  { $$= new Item_func_log($3); }
++	| LOG_SYM '(' expr ',' expr ')'
++	  { $$= new Item_func_log($3, $5); }
++	| MASTER_POS_WAIT '(' expr ',' expr ')'
++	  {
++	    $$= new Item_master_pos_wait($3, $5);
++	    Lex->safe_to_cache_query=0;
++		  }
++	| MASTER_POS_WAIT '(' expr ',' expr ',' expr ')'
++	  {
++	    $$= new Item_master_pos_wait($3, $5, $7);
++	    Lex->safe_to_cache_query=0;
++	  }
++	| MICROSECOND_SYM '(' expr ')'
++	  { $$= new Item_func_microsecond($3); }
++	| MINUTE_SYM '(' expr ')'
++	  { $$= new Item_func_minute($3); }
++	| MOD_SYM '(' expr ',' expr ')'
++	  { $$ = new Item_func_mod( $3, $5); }
++	| MONTH_SYM '(' expr ')'
++	  { $$= new Item_func_month($3); }
++	| NOW_SYM optional_braces
++	  { $$= new Item_func_now_local(); Lex->safe_to_cache_query=0;}
++	| NOW_SYM '(' expr ')'
++	  { $$= new Item_func_now_local($3); Lex->safe_to_cache_query=0;}
++	| PASSWORD '(' expr ')'
++	  {
++	    $$= YYTHD->variables.old_passwords ?
++              (Item *) new Item_func_old_password($3) :
++	      (Item *) new Item_func_password($3);
++	  }
++	| OLD_PASSWORD '(' expr ')'
++	  { $$=  new Item_func_old_password($3); }
++	| POSITION_SYM '(' bit_expr IN_SYM expr ')'
++	  { $$ = new Item_func_locate($5,$3); }
++	| QUARTER_SYM '(' expr ')'
++	  { $$ = new Item_func_quarter($3); }
++	| RAND '(' expr ')'
++	  { $$= new Item_func_rand($3); Lex->uncacheable(UNCACHEABLE_RAND);}
++	| RAND '(' ')'
++	  { $$= new Item_func_rand(); Lex->uncacheable(UNCACHEABLE_RAND);}
++	| REPLACE '(' expr ',' expr ',' expr ')'
++	  { $$= new Item_func_replace($3,$5,$7); }
++	| RIGHT '(' expr ',' expr ')'
++	  { $$= new Item_func_right($3,$5); }
++	| ROUND '(' expr ')'
++	  { $$= new Item_func_round($3, new Item_int((char*)"0",0,1),0); }
++	| ROUND '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,0); }
++	| ROW_COUNT_SYM '(' ')'
++	  {
++	    $$= new Item_func_row_count();
++	    Lex->safe_to_cache_query= 0;
++	  }
++	| SUBDATE_SYM '(' expr ',' expr ')'
++	  { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 1);}
++	| SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')'
++	  { $$= new Item_date_add_interval($3, $6, $7, 1); }
++	| SECOND_SYM '(' expr ')'
++	  { $$= new Item_func_second($3); }
++	| SUBSTRING '(' expr ',' expr ',' expr ')'
++	  { $$= new Item_func_substr($3,$5,$7); }
++	| SUBSTRING '(' expr ',' expr ')'
++	  { $$= new Item_func_substr($3,$5); }
++	| SUBSTRING '(' expr FROM expr FOR_SYM expr ')'
++	  { $$= new Item_func_substr($3,$5,$7); }
++	| SUBSTRING '(' expr FROM expr ')'
++	  { $$= new Item_func_substr($3,$5); }
++	| SUBSTRING_INDEX '(' expr ',' expr ',' expr ')'
++	  { $$= new Item_func_substr_index($3,$5,$7); }
++	| SYSDATE optional_braces
++          {
++            if (global_system_variables.sysdate_is_now == 0)
++              $$= new Item_func_sysdate_local();
++            else $$= new Item_func_now_local();
++            Lex->safe_to_cache_query=0;
++          }
++	| SYSDATE '(' expr ')'
++          {
++            if (global_system_variables.sysdate_is_now == 0)
++              $$= new Item_func_sysdate_local($3);
++            else $$= new Item_func_now_local($3);
++            Lex->safe_to_cache_query=0;
++          }
++	| TIME_SYM '(' expr ')'
++	  { $$= new Item_time_typecast($3); }
++	| TIMESTAMP '(' expr ')'
++	  { $$= new Item_datetime_typecast($3); }
++	| TIMESTAMP '(' expr ',' expr ')'
++	  { $$= new Item_func_add_time($3, $5, 1, 0); }
++	| TIMESTAMP_ADD '(' interval_time_st ',' expr ',' expr ')'
++	  { $$= new Item_date_add_interval($7,$5,$3,0); }
++	| TIMESTAMP_DIFF '(' interval_time_st ',' expr ',' expr ')'
++	  { $$= new Item_func_timestamp_diff($5,$7,$3); }
++	| TRIM '(' expr ')'
++	  { $$= new Item_func_trim($3); }
++	| TRIM '(' LEADING expr FROM expr ')'
++	  { $$= new Item_func_ltrim($6,$4); }
++	| TRIM '(' TRAILING expr FROM expr ')'
++	  { $$= new Item_func_rtrim($6,$4); }
++	| TRIM '(' BOTH expr FROM expr ')'
++	  { $$= new Item_func_trim($6,$4); }
++	| TRIM '(' LEADING FROM expr ')'
++	 { $$= new Item_func_ltrim($5); }
++	| TRIM '(' TRAILING FROM expr ')'
++	  { $$= new Item_func_rtrim($5); }
++	| TRIM '(' BOTH FROM expr ')'
++	  { $$= new Item_func_trim($5); }
++	| TRIM '(' expr FROM expr ')'
++	  { $$= new Item_func_trim($5,$3); }
++	| TRUNCATE_SYM '(' expr ',' expr ')'
++	  { $$= new Item_func_round($3,$5,1); }
++	| ident '.' ident '(' opt_expr_list ')'
++	  {
++	    LEX *lex= Lex;
++	    sp_name *name= new sp_name($1, $3, true);
++
++	    name->init_qname(YYTHD);
++	    sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
++	    if ($5)
++	      $$= new Item_func_sp(Lex->current_context(), name, *$5);
++	    else
++	      $$= new Item_func_sp(Lex->current_context(), name);
++	    lex->safe_to_cache_query=0;
++	  }
++	| IDENT_sys '(' 
++          {
++#ifdef HAVE_DLOPEN
++            udf_func *udf= 0;
++            LEX *lex= Lex;
++            if (using_udf_functions &&
++                (udf= find_udf($1.str, $1.length)) &&
++                udf->type == UDFTYPE_AGGREGATE)
++            {
++              if (lex->current_select->inc_in_sum_expr())
++              {
++                my_parse_error(ER(ER_SYNTAX_ERROR));
++                MYSQL_YYABORT;
++              }
++            }
++            lex->current_select->udf_list.push_front(udf);
++#endif
++          }
++          udf_expr_list ')'
++          {
++            LEX *lex= Lex;
++#ifdef HAVE_DLOPEN
++            udf_func *udf;
++
++            if (NULL != (udf= lex->current_select->udf_list.pop()))
++            {
++              if (udf->type == UDFTYPE_AGGREGATE)
++                Select->in_sum_expr--;
++
++              switch (udf->returns) {
++              case STRING_RESULT:
++                if (udf->type == UDFTYPE_FUNCTION)
++                {
++                  if ($4 != NULL)
++                    $$ = new Item_func_udf_str(udf, *$4);
++                  else
++                    $$ = new Item_func_udf_str(udf);
++                }
++                else
++                {
++                  if ($4 != NULL)
++                    $$ = new Item_sum_udf_str(udf, *$4);
++                  else
++                    $$ = new Item_sum_udf_str(udf);
++                }
++                break;
++              case REAL_RESULT:
++                if (udf->type == UDFTYPE_FUNCTION)
++                {
++                  if ($4 != NULL)
++                    $$ = new Item_func_udf_float(udf, *$4);
++                  else
++                    $$ = new Item_func_udf_float(udf);
++                }
++                else
++                {
++                  if ($4 != NULL)
++                    $$ = new Item_sum_udf_float(udf, *$4);
++                  else
++                    $$ = new Item_sum_udf_float(udf);
++                }
++                break;
++              case INT_RESULT:
++                if (udf->type == UDFTYPE_FUNCTION)
++                {
++                  if ($4 != NULL)
++                    $$ = new Item_func_udf_int(udf, *$4);
++                  else
++                    $$ = new Item_func_udf_int(udf);
++                }
++                else
++                {
++                  if ($4 != NULL)
++                    $$ = new Item_sum_udf_int(udf, *$4);
++                  else
++                    $$ = new Item_sum_udf_int(udf);
++                }
++                break;
++              case DECIMAL_RESULT:
++                if (udf->type == UDFTYPE_FUNCTION)
++                {
++                  if ($4 != NULL)
++                    $$ = new Item_func_udf_decimal(udf, *$4);
++                  else
++                    $$ = new Item_func_udf_decimal(udf);
++                }
++                else
++                {
++                  if ($4 != NULL)
++                    $$ = new Item_sum_udf_decimal(udf, *$4);
++                  else
++                    $$ = new Item_sum_udf_decimal(udf);
++                }
++                break;
++              default:
++                MYSQL_YYABORT;
++              }
++            }
++            else
++#endif /* HAVE_DLOPEN */
++            {
++              THD *thd= lex->thd;
++              LEX_STRING db;
++              if (lex->copy_db_to(&db.str, &db.length))
++                MYSQL_YYABORT;
++              sp_name *name= new sp_name(db, $1, false);
++              if (name)
++                name->init_qname(thd);
++
++              sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
++              if ($4)
++                $$= new Item_func_sp(Lex->current_context(), name, *$4);
++              else
++                $$= new Item_func_sp(Lex->current_context(), name);
++            }          
++          lex->safe_to_cache_query=0;
++          }
++	| UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')'
++	  {
++            $$= new Item_func_unique_users($3,atoi($5.str),atoi($7.str), * $9);
++	  }
++	| UNIX_TIMESTAMP '(' ')'
++	  {
++	    $$= new Item_func_unix_timestamp();
++	    Lex->safe_to_cache_query=0;
++	  }
++	| UNIX_TIMESTAMP '(' expr ')'
++	  { $$= new Item_func_unix_timestamp($3); }
++	| USER '(' ')'
++	  { $$= new Item_func_user(); Lex->safe_to_cache_query=0; }
++	| UTC_DATE_SYM optional_braces
++	  { $$= new Item_func_curdate_utc(); Lex->safe_to_cache_query=0;}
++	| UTC_TIME_SYM optional_braces
++	  { $$= new Item_func_curtime_utc(); Lex->safe_to_cache_query=0;}
++	| UTC_TIMESTAMP_SYM optional_braces
++	  { $$= new Item_func_now_utc(); Lex->safe_to_cache_query=0;}
++	| WEEK_SYM '(' expr ')'
++	  {
++            $$= new Item_func_week($3,new Item_int((char*) "0",
++				   YYTHD->variables.default_week_format,1));
++          }
++	| WEEK_SYM '(' expr ',' expr ')'
++	  { $$= new Item_func_week($3,$5); }
++	| YEAR_SYM '(' expr ')'
++	  { $$= new Item_func_year($3); }
++	| YEARWEEK '(' expr ')'
++	  { $$= new Item_func_yearweek($3,new Item_int((char*) "0",0,1)); }
++	| YEARWEEK '(' expr ',' expr ')'
++	  { $$= new Item_func_yearweek($3, $5); }
++	| BENCHMARK_SYM '(' ulong_num ',' expr ')'
++	  {
++	    $$=new Item_func_benchmark($3,$5);
++	    Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
++	  }
++	| EXTRACT_SYM '(' interval FROM expr ')'
++	{ $$=new Item_extract( $3, $5); };
++
++geometry_function:
++	  CONTAINS_SYM '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_spatial_rel($3, $5, Item_func::SP_CONTAINS_FUNC)); }
++	| GEOMFROMTEXT '(' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
++	| GEOMFROMTEXT '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
++	| GEOMFROMWKB '(' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_wkb($3)); }
++	| GEOMFROMWKB '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_wkb($3, $5)); }
++	| GEOMETRYCOLLECTION '(' expr_list ')'
++	  { $$= GEOM_NEW(Item_func_spatial_collection(* $3,
++                           Geometry::wkb_geometrycollection,
++                           Geometry::wkb_point)); }
++	| LINESTRING '(' expr_list ')'
++	  { $$= GEOM_NEW(Item_func_spatial_collection(* $3,
++                  Geometry::wkb_linestring, Geometry::wkb_point)); }
++ 	| MULTILINESTRING '(' expr_list ')'
++	  { $$= GEOM_NEW( Item_func_spatial_collection(* $3,
++                   Geometry::wkb_multilinestring, Geometry::wkb_linestring)); }
++ 	| MLINEFROMTEXT '(' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
++	| MLINEFROMTEXT '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
++	| MPOINTFROMTEXT '(' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
++	| MPOINTFROMTEXT '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
++	| MPOLYFROMTEXT '(' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
++	| MPOLYFROMTEXT '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
++	| MULTIPOINT '(' expr_list ')'
++	  { $$= GEOM_NEW(Item_func_spatial_collection(* $3,
++                  Geometry::wkb_multipoint, Geometry::wkb_point)); }
++ 	| MULTIPOLYGON '(' expr_list ')'
++	  { $$= GEOM_NEW(Item_func_spatial_collection(* $3,
++                  Geometry::wkb_multipolygon, Geometry::wkb_polygon)); }
++	| POINT_SYM '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_point($3,$5)); }
++ 	| POINTFROMTEXT '(' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
++	| POINTFROMTEXT '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
++	| POLYFROMTEXT '(' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
++	| POLYFROMTEXT '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
++	| POLYGON '(' expr_list ')'
++	  { $$= GEOM_NEW(Item_func_spatial_collection(* $3,
++	          Geometry::wkb_polygon, Geometry::wkb_linestring)); }
++ 	| GEOMCOLLFROMTEXT '(' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
++	| GEOMCOLLFROMTEXT '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
++ 	| LINEFROMTEXT '(' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3)); }
++	| LINEFROMTEXT '(' expr ',' expr ')'
++	  { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); }
++	;
++
++fulltext_options:
++        /* nothing */                   { $$= FT_NL;  }
++        | WITH QUERY_SYM EXPANSION_SYM  { $$= FT_NL | FT_EXPAND; }
++        | IN_SYM BOOLEAN_SYM MODE_SYM   { $$= FT_BOOL; }
++        ;
++
++udf_expr_list:
++	/* empty */	 { $$= NULL; }
++	| udf_expr_list2 { $$= $1;}
++	;
++
++udf_expr_list2:
++	{ Select->expr_list.push_front(new List<Item>); }
++	udf_expr_list3
++	{ $$= Select->expr_list.pop(); }
++	;
++
++udf_expr_list3:
++	udf_expr 
++	  {
++	    Select->expr_list.head()->push_back($1);
++	  }
++	| udf_expr_list3 ',' udf_expr 
++	  {
++	    Select->expr_list.head()->push_back($3);
++	  }
++	;
++
++udf_expr:
++	remember_name expr remember_end select_alias
++	{
++          udf_func *udf= Select->udf_list.head();
++          /*
++           Use Item::name as a storage for the attribute value of user
++           defined function argument. It is safe to use Item::name
++           because the syntax will not allow having an explicit name here.
++           See WL#1017 re. udf attributes.
++          */
++	  if ($4.str)
++          {
++            if (!udf)
++            {
++              /*
++                Disallow using AS to specify explicit names for the arguments
++                of stored routine calls
++              */
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++              MYSQL_YYABORT;
++            }
++
++            $2->is_autogenerated_name= FALSE;
++	    $2->set_name($4.str, $4.length, system_charset_info);
++          }
++	  else if (udf)
++	    $2->set_name($1, (uint) ($3 - $1), YYTHD->charset());
++	  $$= $2;
++	}
++	;
++
++sum_expr:
++	AVG_SYM '(' in_sum_expr ')'
++	  { $$=new Item_sum_avg($3); }
++	| AVG_SYM '(' DISTINCT in_sum_expr ')'
++	  { $$=new Item_sum_avg_distinct($4); }
++	| BIT_AND  '(' in_sum_expr ')'
++	  { $$=new Item_sum_and($3); }
++	| BIT_OR  '(' in_sum_expr ')'
++	  { $$=new Item_sum_or($3); }
++	| BIT_XOR  '(' in_sum_expr ')'
++	  { $$=new Item_sum_xor($3); }
++	| COUNT_SYM '(' opt_all '*' ')'
++	  { $$=new Item_sum_count(new Item_int((int32) 0L,1)); }
++	| COUNT_SYM '(' in_sum_expr ')'
++	  { $$=new Item_sum_count($3); }
++	| COUNT_SYM '(' DISTINCT
++	  { Select->in_sum_expr++; }
++	   expr_list
++	  { Select->in_sum_expr--; }
++	  ')'
++	  { $$=new Item_sum_count_distinct(* $5); }
++	| GROUP_UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' in_sum_expr ')'
++	  { $$= new Item_sum_unique_users($3,atoi($5.str),atoi($7.str),$9); }
++	| MIN_SYM '(' in_sum_expr ')'
++	  { $$=new Item_sum_min($3); }
++/*
++   According to ANSI SQL, DISTINCT is allowed and has
++   no sence inside MIN and MAX grouping functions; so MIN|MAX(DISTINCT ...)
++   is processed like an ordinary MIN | MAX()
++ */
++	| MIN_SYM '(' DISTINCT in_sum_expr ')'
++	  { $$=new Item_sum_min($4); }
++	| MAX_SYM '(' in_sum_expr ')'
++	  { $$=new Item_sum_max($3); }
++	| MAX_SYM '(' DISTINCT in_sum_expr ')'
++	  { $$=new Item_sum_max($4); }
++	| STD_SYM '(' in_sum_expr ')'
++	  { $$=new Item_sum_std($3, 0); }
++	| VARIANCE_SYM '(' in_sum_expr ')'
++	  { $$=new Item_sum_variance($3, 0); }
++	| STDDEV_SAMP_SYM '(' in_sum_expr ')'
++	  { $$=new Item_sum_std($3, 1); }
++	| VAR_SAMP_SYM '(' in_sum_expr ')'
++	  { $$=new Item_sum_variance($3, 1); }
++	| SUM_SYM '(' in_sum_expr ')'
++	  { $$=new Item_sum_sum($3); }
++	| SUM_SYM '(' DISTINCT in_sum_expr ')'
++	  { $$=new Item_sum_sum_distinct($4); }
++	| GROUP_CONCAT_SYM '(' opt_distinct
++	  { Select->in_sum_expr++; }
++	  expr_list opt_gorder_clause
++	  opt_gconcat_separator
++	 ')'
++	  {
++            SELECT_LEX *sel= Select;
++	    sel->in_sum_expr--;
++	    $$=new Item_func_group_concat(Lex->current_context(), $3, $5,
++                                          sel->gorder_list, $7);
++	    $5->empty();
++	  };
++
++variable:
++          '@'
++          {
++            if (! Lex->parsing_options.allows_variable)
++            {
++              my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
++              MYSQL_YYABORT;
++            }
++          }
++          variable_aux
++          {
++            $$= $3;
++          }
++          ;
++
++variable_aux:
++          ident_or_text SET_VAR expr
++          {
++            $$= new Item_func_set_user_var($1, $3);
++            LEX *lex= Lex;
++            lex->uncacheable(UNCACHEABLE_RAND);
++          }
++        | ident_or_text
++          {
++            $$= new Item_func_get_user_var($1);
++            LEX *lex= Lex;
++            lex->uncacheable(UNCACHEABLE_RAND);
++          }
++        | '@' opt_var_ident_type ident_or_text opt_component
++          {
++            if ($3.str && $4.str && check_reserved_words(&$3))
++            {
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++              MYSQL_YYABORT;
++            }
++            if (!($$= get_system_var(YYTHD, $2, $3, $4)))
++              MYSQL_YYABORT;
++          }
++        ;
++
++opt_distinct:
++    /* empty */ { $$ = 0; }
++    |DISTINCT   { $$ = 1; };
++
++opt_gconcat_separator:
++    /* empty */
++      {
++        $$= new (YYTHD->mem_root) String(",", 1, &my_charset_latin1);
++      }
++    | SEPARATOR_SYM text_string { $$ = $2; };
++
++
++opt_gorder_clause:
++	  /* empty */
++	  {
++            Select->gorder_list = NULL;
++	  }
++	| order_clause
++          {
++            SELECT_LEX *select= Select;
++            select->gorder_list=
++	      (SQL_LIST*) sql_memdup((char*) &select->order_list,
++				     sizeof(st_sql_list));
++	    select->order_list.empty();
++	  };
++
++
++in_sum_expr:
++	opt_all
++	{
++	  LEX *lex= Lex;
++	  if (lex->current_select->inc_in_sum_expr())
++	  {
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++	  }
++	}
++	expr
++	{
++	  Select->in_sum_expr--;
++	  $$= $3;
++	};
++
++cast_type:
++        BINARY opt_len		{ $$=ITEM_CAST_CHAR; Lex->charset= &my_charset_bin; Lex->dec= 0; }
++        | CHAR_SYM opt_len opt_binary	{ $$=ITEM_CAST_CHAR; Lex->dec= 0; }
++	| NCHAR_SYM opt_len	{ $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; Lex->dec=0; }
++        | SIGNED_SYM		{ $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
++        | SIGNED_SYM INT_SYM	{ $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
++        | UNSIGNED		{ $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
++        | UNSIGNED INT_SYM	{ $$=ITEM_CAST_UNSIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
++        | DATE_SYM		{ $$=ITEM_CAST_DATE; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
++        | TIME_SYM		{ $$=ITEM_CAST_TIME; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
++        | DATETIME		{ $$=ITEM_CAST_DATETIME; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
++        | DECIMAL_SYM float_options { $$=ITEM_CAST_DECIMAL; Lex->charset= NULL; }
++	;
++
++opt_expr_list:
++	/* empty */ { $$= NULL; }
++	| expr_list { $$= $1;}
++	;
++
++expr_list:
++	{ Select->expr_list.push_front(new List<Item>); }
++	expr_list2
++	{ $$= Select->expr_list.pop(); };
++
++expr_list2:
++	expr { Select->expr_list.head()->push_back($1); }
++	| expr_list2 ',' expr { Select->expr_list.head()->push_back($3); };
++
++ident_list_arg:
++          ident_list          { $$= $1; }
++        | '(' ident_list ')'  { $$= $2; };
++
++ident_list:
++        { Select->expr_list.push_front(new List<Item>); }
++        ident_list2
++        { $$= Select->expr_list.pop(); };
++
++ident_list2:
++        simple_ident { Select->expr_list.head()->push_back($1); }
++        | ident_list2 ',' simple_ident { Select->expr_list.head()->push_back($3); };
++
++opt_expr:
++	/* empty */      { $$= NULL; }
++	| expr           { $$= $1; };
++
++opt_else:
++	/* empty */    { $$= NULL; }
++	| ELSE expr    { $$= $2; };
++
++when_list:
++          WHEN_SYM expr THEN_SYM expr
++          {
++            $$= new List<Item>;
++            $$->push_back($2);
++            $$->push_back($4);
++          }
++        | when_list WHEN_SYM expr THEN_SYM expr
++          {
++            $1->push_back($3);
++            $1->push_back($5);
++            $$= $1;
++          }
++        ;
++
++/* Warning - may return NULL in case of incomplete SELECT */
++table_ref:
++        table_factor            { $$=$1; }
++        | join_table
++          {
++	    LEX *lex= Lex;
++            if (!($$= lex->current_select->nest_last_join(lex->thd)))
++              MYSQL_YYABORT;
++          }
++        ;
++
++join_table_list:
++	derived_table_list		{ MYSQL_YYABORT_UNLESS($$=$1); }
++	;
++
++/* Warning - may return NULL in case of incomplete SELECT */
++derived_table_list:
++        table_ref { $$=$1; }
++        | derived_table_list ',' table_ref
++          {
++            MYSQL_YYABORT_UNLESS($1 && ($$=$3));
++          }
++        ;
++
++/*
++  Notice that JOIN is a left-associative operation, and it must be parsed
++  as such, that is, the parser must process first the left join operand
++  then the right one. Such order of processing ensures that the parser
++  produces correct join trees which is essential for semantic analysis
++  and subsequent optimization phases.
++*/
++join_table:
++/* INNER JOIN variants */
++        /*
++          Use %prec to evaluate production 'table_ref' before 'normal_join'
++          so that [INNER | CROSS] JOIN is properly nested as other
++          left-associative joins.
++        */
++        table_ref normal_join table_ref %prec TABLE_REF_PRIORITY
++          { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); }
++	| table_ref STRAIGHT_JOIN table_factor
++	  { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=1; }
++	| table_ref normal_join table_ref
++          ON
++          {
++            MYSQL_YYABORT_UNLESS($1 && $3);
++            /* Change the current name resolution context to a local context. */
++            if (push_new_name_resolution_context(YYTHD, $1, $3))
++              MYSQL_YYABORT;
++            Select->parsing_place= IN_ON;
++          }
++          expr
++	  {
++            add_join_on($3,$6);
++            Lex->pop_context();
++            Select->parsing_place= NO_MATTER;
++          }
++        | table_ref STRAIGHT_JOIN table_factor
++          ON
++          {
++            MYSQL_YYABORT_UNLESS($1 && $3);
++            /* Change the current name resolution context to a local context. */
++            if (push_new_name_resolution_context(YYTHD, $1, $3))
++              MYSQL_YYABORT;
++            Select->parsing_place= IN_ON;
++          }
++          expr
++          {
++            $3->straight=1;
++            add_join_on($3,$6);
++            Lex->pop_context();
++            Select->parsing_place= NO_MATTER;
++          }
++	| table_ref normal_join table_ref
++	  USING
++	  {
++            MYSQL_YYABORT_UNLESS($1 && $3);
++	  }
++	  '(' using_list ')'
++          { add_join_natural($1,$3,$7,Select); $$=$3; }
++	| table_ref NATURAL JOIN_SYM table_factor
++	  {
++            MYSQL_YYABORT_UNLESS($1 && ($$=$4));
++            add_join_natural($1,$4,NULL,Select);
++          }
++
++/* LEFT JOIN variants */
++	| table_ref LEFT opt_outer JOIN_SYM table_ref
++          ON
++          {
++            MYSQL_YYABORT_UNLESS($1 && $5);
++            /* Change the current name resolution context to a local context. */
++            if (push_new_name_resolution_context(YYTHD, $1, $5))
++              MYSQL_YYABORT;
++            Select->parsing_place= IN_ON;
++          }
++          expr
++	  {
++            add_join_on($5,$8);
++            Lex->pop_context();
++            $5->outer_join|=JOIN_TYPE_LEFT;
++            $$=$5;
++            Select->parsing_place= NO_MATTER;
++          }
++	| table_ref LEFT opt_outer JOIN_SYM table_factor
++	  {
++            MYSQL_YYABORT_UNLESS($1 && $5);
++	  }
++	  USING '(' using_list ')'
++          { 
++            add_join_natural($1,$5,$9,Select); 
++            $5->outer_join|=JOIN_TYPE_LEFT; 
++            $$=$5; 
++          }
++	| table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
++	  {
++            MYSQL_YYABORT_UNLESS($1 && $6);
++ 	    add_join_natural($1,$6,NULL,Select);
++	    $6->outer_join|=JOIN_TYPE_LEFT;
++	    $$=$6;
++	  }
++
++/* RIGHT JOIN variants */
++	| table_ref RIGHT opt_outer JOIN_SYM table_ref
++          ON
++          {
++            MYSQL_YYABORT_UNLESS($1 && $5);
++            /* Change the current name resolution context to a local context. */
++            if (push_new_name_resolution_context(YYTHD, $1, $5))
++              MYSQL_YYABORT;
++            Select->parsing_place= IN_ON;
++          }
++          expr
++          {
++	    LEX *lex= Lex;
++            if (!($$= lex->current_select->convert_right_join()))
++              MYSQL_YYABORT;
++            add_join_on($$, $8);
++            Lex->pop_context();
++            Select->parsing_place= NO_MATTER;
++          }
++	| table_ref RIGHT opt_outer JOIN_SYM table_factor
++	  {
++            MYSQL_YYABORT_UNLESS($1 && $5);
++	  }
++	  USING '(' using_list ')'
++          {
++	    LEX *lex= Lex;
++            if (!($$= lex->current_select->convert_right_join()))
++              MYSQL_YYABORT;
++            add_join_natural($$,$5,$9,Select);
++          }
++	| table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
++	  {
++            MYSQL_YYABORT_UNLESS($1 && $6);
++	    add_join_natural($6,$1,NULL,Select);
++	    LEX *lex= Lex;
++            if (!($$= lex->current_select->convert_right_join()))
++              MYSQL_YYABORT;
++	  };
++
++normal_join:
++	JOIN_SYM		{}
++	| INNER_SYM JOIN_SYM	{}
++	| CROSS JOIN_SYM	{}
++	;
++
++/* Warning - may return NULL in case of incomplete SELECT */
++table_factor:
++	{
++	  SELECT_LEX *sel= Select;
++	  sel->use_index_ptr=sel->ignore_index_ptr=0;
++	  sel->table_join_options= 0;
++	}
++        table_ident opt_table_alias opt_key_definition
++	{
++	  LEX *lex= Lex;
++	  SELECT_LEX *sel= lex->current_select;
++	  if (!($$= sel->add_table_to_list(lex->thd, $2, $3,
++					   sel->get_table_join_options(),
++					   lex->lock_option,
++					   sel->get_use_index(),
++					   sel->get_ignore_index())))
++	    MYSQL_YYABORT;
++          sel->add_joined_table($$);
++	}
++	| '{' ident table_ref LEFT OUTER JOIN_SYM table_ref
++          ON
++          {
++            /* Change the current name resolution context to a local context. */
++            if (push_new_name_resolution_context(YYTHD, $3, $7))
++              MYSQL_YYABORT;
++
++          }
++          expr '}'
++	  {
++	    LEX *lex= Lex;
++            MYSQL_YYABORT_UNLESS($3 && $7);
++            add_join_on($7,$10);
++            Lex->pop_context();
++            $7->outer_join|=JOIN_TYPE_LEFT;
++            $$=$7;
++            if (!($$= lex->current_select->nest_last_join(lex->thd)))
++              MYSQL_YYABORT;
++          }
++	| select_derived_init get_select_lex select_derived2
++          {
++            LEX *lex= Lex;
++            SELECT_LEX *sel= lex->current_select;
++            if ($1)
++            {
++	      if (sel->set_braces(1))
++	      {
++                my_parse_error(ER(ER_SYNTAX_ERROR));
++	        MYSQL_YYABORT;
++	      }
++              /* select in braces, can't contain global parameters */
++	      if (sel->master_unit()->fake_select_lex)
++                sel->master_unit()->global_parameters=
++                   sel->master_unit()->fake_select_lex;
++            }
++            if ($2->init_nested_join(lex->thd))
++              MYSQL_YYABORT;
++            $$= 0;
++            /* incomplete derived tables return NULL, we must be
++               nested in select_derived rule to be here. */
++          }
++	| '(' get_select_lex select_derived union_opt ')' opt_table_alias
++	{
++          /* Use $2 instead of Lex->current_select as derived table will
++             alter value of Lex->current_select. */
++
++          if (!($3 || $6) && $2->embedding &&
++              !$2->embedding->nested_join->join_list.elements)
++          {
++            /* we have a derived table ($3 == NULL) but no alias,
++               Since we are nested in further parentheses so we
++               can pass NULL to the outer level parentheses
++               Permits parsing of "((((select ...))) as xyz)" */
++            $$= 0;
++          }
++          else
++          if (!$3)
++          {
++            /* Handle case of derived table, alias may be NULL if there
++               are no outer parentheses, add_table_to_list() will throw
++               error in this case */
++	    LEX *lex=Lex;
++            SELECT_LEX *sel= lex->current_select;
++	    SELECT_LEX_UNIT *unit= sel->master_unit();
++	    lex->current_select= sel= unit->outer_select();
++	    if (!($$= sel->
++                  add_table_to_list(lex->thd, new Table_ident(unit), $6, 0,
++				    TL_READ,(List<String> *)0,
++	                            (List<String> *)0)))
++
++	      MYSQL_YYABORT;
++            sel->add_joined_table($$);
++            lex->pop_context();
++          }
++	  else
++          if ($4 || $6)
++	  {
++            /* simple nested joins cannot have aliases or unions */
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++	  }
++          else
++            $$= $3;
++	}
++        ;
++
++/* handle contents of parentheses in join expression */
++select_derived:
++	  get_select_lex
++	  {
++            LEX *lex= Lex;
++            if ($1->init_nested_join(lex->thd))
++              MYSQL_YYABORT;
++          }
++          derived_table_list
++          {
++            LEX *lex= Lex;
++            /* for normal joins, $3 != NULL and end_nested_join() != NULL,
++               for derived tables, both must equal NULL */
++
++            if (!($$= $1->end_nested_join(lex->thd)) && $3)
++              MYSQL_YYABORT;
++            if (!$3 && $$)
++            {
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++	      MYSQL_YYABORT;
++            }
++          }
++ 	;
++
++select_derived2:
++        {
++	  LEX *lex= Lex;
++	  lex->derived_tables|= DERIVED_SUBQUERY;
++          if (lex->sql_command == (int)SQLCOM_HA_READ ||
++              lex->sql_command == (int)SQLCOM_KILL ||
++              lex->sql_command == (int)SQLCOM_PURGE)
++	  {
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++	  }
++	  if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
++              mysql_new_select(lex, 1))
++	    MYSQL_YYABORT;
++	  mysql_init_select(lex);
++	  lex->current_select->linkage= DERIVED_TABLE_TYPE;
++	  lex->current_select->parsing_place= SELECT_LIST;
++	}
++        select_options select_item_list
++	{
++	  Select->parsing_place= NO_MATTER;
++	}
++	opt_select_from
++        ;
++
++get_select_lex:
++	/* Empty */ { $$= Select; }
++        ;
++
++select_derived_init:
++          SELECT_SYM
++          {
++            LEX *lex= Lex;
++
++            if (! lex->parsing_options.allows_derived)
++            {
++              my_error(ER_VIEW_SELECT_DERIVED, MYF(0));
++              MYSQL_YYABORT;
++            }
++
++            SELECT_LEX *sel= lex->current_select;
++            TABLE_LIST *embedding;
++            if (!sel->embedding || sel->end_nested_join(lex->thd))
++	    {
++              /* we are not in parentheses */
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++	      MYSQL_YYABORT;
++	    }
++            embedding= Select->embedding;
++            $$= embedding &&
++                !embedding->nested_join->join_list.elements;
++            /* return true if we are deeply nested */
++          }
++        ;
++
++opt_outer:
++	/* empty */	{}
++	| OUTER		{};
++
++opt_for_join:
++        /* empty */
++        | FOR_SYM JOIN_SYM;
++
++opt_key_definition:
++	/* empty */	{}
++	| USE_SYM    key_usage_list
++          {
++	    SELECT_LEX *sel= Select;
++	    sel->use_index= *$2;
++	    sel->use_index_ptr= &sel->use_index;
++	  }
++	| FORCE_SYM key_usage_list
++          {
++	    SELECT_LEX *sel= Select;
++	    sel->use_index= *$2;
++	    sel->use_index_ptr= &sel->use_index;
++	    sel->table_join_options|= TL_OPTION_FORCE_INDEX;
++	  }
++	| IGNORE_SYM key_usage_list
++	  {
++	    SELECT_LEX *sel= Select;
++	    sel->ignore_index= *$2;
++	    sel->ignore_index_ptr= &sel->ignore_index;
++	  };
++
++key_usage_list:
++        key_or_index opt_for_join      
++	{ Select->interval_list.empty(); }
++        '(' key_list_or_empty ')'
++        { $$= &Select->interval_list; }
++	;
++
++key_list_or_empty:
++	/* empty */ 		{}
++	| key_usage_list2	{}
++	;
++
++key_usage_list2:
++	key_usage_list2 ',' ident
++        { Select->
++	    interval_list.push_back(new (YYTHD->mem_root) String((const char*) $3.str, $3.length,
++				    system_charset_info)); }
++	| ident
++        { Select->
++	    interval_list.push_back(new (YYTHD->mem_root) String((const char*) $1.str, $1.length,
++				    system_charset_info)); }
++	| PRIMARY_SYM
++        { Select->
++	    interval_list.push_back(new (YYTHD->mem_root) String("PRIMARY", 7,
++				    system_charset_info)); };
++
++using_list:
++	ident
++	  {
++            if (!($$= new List<String>))
++	      MYSQL_YYABORT;
++            $$->push_back(new (YYTHD->mem_root)
++                              String((const char *) $1.str, $1.length,
++                                      system_charset_info));
++	  }
++	| using_list ',' ident
++	  {
++            $1->push_back(new (YYTHD->mem_root)
++                              String((const char *) $3.str, $3.length,
++                                      system_charset_info));
++            $$= $1;
++	  };
++
++interval:
++	interval_time_st	{}
++	| DAY_HOUR_SYM		{ $$=INTERVAL_DAY_HOUR; }
++	| DAY_MICROSECOND_SYM	{ $$=INTERVAL_DAY_MICROSECOND; }
++	| DAY_MINUTE_SYM	{ $$=INTERVAL_DAY_MINUTE; }
++	| DAY_SECOND_SYM	{ $$=INTERVAL_DAY_SECOND; }
++	| HOUR_MICROSECOND_SYM	{ $$=INTERVAL_HOUR_MICROSECOND; }
++	| HOUR_MINUTE_SYM	{ $$=INTERVAL_HOUR_MINUTE; }
++	| HOUR_SECOND_SYM	{ $$=INTERVAL_HOUR_SECOND; }
++	| MICROSECOND_SYM	{ $$=INTERVAL_MICROSECOND; }
++	| MINUTE_MICROSECOND_SYM	{ $$=INTERVAL_MINUTE_MICROSECOND; }
++	| MINUTE_SECOND_SYM	{ $$=INTERVAL_MINUTE_SECOND; }
++	| SECOND_MICROSECOND_SYM	{ $$=INTERVAL_SECOND_MICROSECOND; }
++	| YEAR_MONTH_SYM	{ $$=INTERVAL_YEAR_MONTH; };
++
++interval_time_st:
++	DAY_SYM			{ $$=INTERVAL_DAY; }
++	| WEEK_SYM		{ $$=INTERVAL_WEEK; }
++	| HOUR_SYM		{ $$=INTERVAL_HOUR; }
++	| FRAC_SECOND_SYM	{ $$=INTERVAL_MICROSECOND; }
++	| MINUTE_SYM		{ $$=INTERVAL_MINUTE; }
++	| MONTH_SYM		{ $$=INTERVAL_MONTH; }
++	| QUARTER_SYM		{ $$=INTERVAL_QUARTER; }
++	| SECOND_SYM		{ $$=INTERVAL_SECOND; }
++	| YEAR_SYM		{ $$=INTERVAL_YEAR; }
++        ;
++
++date_time_type:
++          DATE_SYM              {$$=MYSQL_TIMESTAMP_DATE;}
++        | TIME_SYM              {$$=MYSQL_TIMESTAMP_TIME;}
++        | DATETIME              {$$=MYSQL_TIMESTAMP_DATETIME;}
++        | TIMESTAMP             {$$=MYSQL_TIMESTAMP_DATETIME;}
++        ;
++
++table_alias:
++	/* empty */
++	| AS
++	| EQ;
++
++opt_table_alias:
++	/* empty */		{ $$=0; }
++	| table_alias ident
++	  { $$= (LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING)); };
++
++opt_all:
++	/* empty */
++	| ALL
++	;
++
++where_clause:
++	/* empty */  { Select->where= 0; }
++	| WHERE
++          {
++            Select->parsing_place= IN_WHERE;
++          }
++          expr
++	  {
++            SELECT_LEX *select= Select;
++	    select->where= $3;
++            select->parsing_place= NO_MATTER;
++	    if ($3)
++	      $3->top_level_item();
++	  }
++ 	;
++
++having_clause:
++	/* empty */
++	| HAVING
++	  {
++	    Select->parsing_place= IN_HAVING;
++          }
++	  expr
++	  {
++	    SELECT_LEX *sel= Select;
++	    sel->having= $3;
++	    sel->parsing_place= NO_MATTER;
++	    if ($3)
++	      $3->top_level_item();
++	  }
++	;
++
++opt_escape:
++	ESCAPE_SYM simple_expr 
++          {
++            Lex->escape_used= TRUE;
++            $$= $2;
++          }
++	| /* empty */
++          {
++            Lex->escape_used= FALSE;
++            $$= ((YYTHD->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) ?
++		 new Item_string("", 0, &my_charset_latin1) :
++                 new Item_string("\\", 1, &my_charset_latin1));
++          }
++        ;
++
++
++/*
++   group by statement in select
++*/
++
++group_clause:
++	/* empty */
++	| GROUP BY group_list olap_opt;
++
++group_list:
++	group_list ',' order_ident order_dir
++	  { if (add_group_to_list(YYTHD, $3,(bool) $4)) MYSQL_YYABORT; }
++	| order_ident order_dir
++	  { if (add_group_to_list(YYTHD, $1,(bool) $2)) MYSQL_YYABORT; };
++
++olap_opt:
++	/* empty */ {}
++	| WITH CUBE_SYM
++          {
++	    LEX *lex=Lex;
++	    if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
++	    {
++	      my_error(ER_WRONG_USAGE, MYF(0), "WITH CUBE",
++		       "global union parameters");
++	      MYSQL_YYABORT;
++	    }
++	    lex->current_select->olap= CUBE_TYPE;
++	    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "CUBE");
++	    MYSQL_YYABORT;	/* To be deleted in 5.1 */
++	  }
++	| WITH ROLLUP_SYM
++          {
++	    LEX *lex= Lex;
++	    if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
++	    {
++	      my_error(ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
++		       "global union parameters");
++	      MYSQL_YYABORT;
++	    }
++	    lex->current_select->olap= ROLLUP_TYPE;
++	  }
++	;
++
++/*
++  Order by statement in ALTER TABLE
++*/
++
++alter_order_clause:
++          ORDER_SYM BY alter_order_list
++        ;
++
++alter_order_list:
++          alter_order_list ',' alter_order_item
++        | alter_order_item
++        ;
++
++alter_order_item:
++          simple_ident_nospvar order_dir
++          {
++            THD *thd= YYTHD;
++            bool ascending= ($2 == 1) ? true : false;
++            if (add_order_to_list(thd, $1, ascending))
++              MYSQL_YYABORT;
++          }
++        ;
++
++/*
++   Order by statement in select
++*/
++
++opt_order_clause:
++	/* empty */
++	| order_clause;
++
++order_clause:
++	ORDER_SYM BY
++        {
++	  LEX *lex=Lex;
++          SELECT_LEX *sel= lex->current_select;
++          SELECT_LEX_UNIT *unit= sel-> master_unit();
++	  if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
++	      sel->olap != UNSPECIFIED_OLAP_TYPE)
++	  {
++	    my_error(ER_WRONG_USAGE, MYF(0),
++                     "CUBE/ROLLUP", "ORDER BY");
++	    MYSQL_YYABORT;
++	  }
++          if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
++          {
++            /*
++              A query of the of the form (SELECT ...) ORDER BY order_list is
++              executed in the same way as the query
++              SELECT ... ORDER BY order_list
++              unless the SELECT construct contains ORDER BY or LIMIT clauses.
++              Otherwise we create a fake SELECT_LEX if it has not been created
++              yet.
++            */
++            SELECT_LEX *first_sl= unit->first_select();
++            if (!first_sl->next_select() &&
++                (first_sl->order_list.elements || 
++                 first_sl->select_limit) &&            
++                unit->add_fake_select_lex(lex->thd))
++              MYSQL_YYABORT;
++          }
++	} order_list;
++
++order_list:
++	order_list ',' order_ident order_dir
++	  { if (add_order_to_list(YYTHD, $3,(bool) $4)) MYSQL_YYABORT; }
++	| order_ident order_dir
++	  { if (add_order_to_list(YYTHD, $1,(bool) $2)) MYSQL_YYABORT; };
++
++order_dir:
++	/* empty */ { $$ =  1; }
++	| ASC  { $$ =1; }
++	| DESC { $$ =0; };
++
++
++opt_limit_clause_init:
++	/* empty */
++	{
++	  LEX *lex= Lex;
++	  SELECT_LEX *sel= lex->current_select;
++          sel->offset_limit= 0;
++          sel->select_limit= 0;
++	}
++	| limit_clause {}
++	;
++
++opt_limit_clause:
++	/* empty */	{}
++	| limit_clause	{}
++	;
++
++limit_clause:
++	LIMIT limit_options {}
++	;
++
++limit_options:
++	limit_option
++	  {
++            SELECT_LEX *sel= Select;
++            sel->select_limit= $1;
++            sel->offset_limit= 0;
++	    sel->explicit_limit= 1;
++	  }
++	| limit_option ',' limit_option
++	  {
++	    SELECT_LEX *sel= Select;
++	    sel->select_limit= $3;
++	    sel->offset_limit= $1;
++	    sel->explicit_limit= 1;
++	  }
++	| limit_option OFFSET_SYM limit_option
++	  {
++	    SELECT_LEX *sel= Select;
++	    sel->select_limit= $1;
++	    sel->offset_limit= $3;
++	    sel->explicit_limit= 1;
++	  }
++	;
++limit_option:
++        param_marker
++        {
++          ((Item_param *) $1)->set_strict_type(INT_RESULT);
++        }
++        | ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); }
++        | LONG_NUM     { $$= new Item_uint($1.str, $1.length); }
++        | NUM           { $$= new Item_uint($1.str, $1.length); }
++        ;
++
++delete_limit_clause:
++	/* empty */
++	{
++	  LEX *lex=Lex;
++	  lex->current_select->select_limit= 0;
++	}
++	| LIMIT limit_option
++	{
++	  SELECT_LEX *sel= Select;
++	  sel->select_limit= $2;
++	  sel->explicit_limit= 1;
++	};
++
++ulong_num:
++          NUM           { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
++	| HEX_NUM       { $$= (ulong) strtol($1.str, (char**) 0, 16); }
++	| LONG_NUM      { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
++	| ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
++        | DECIMAL_NUM   { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
++	| FLOAT_NUM	{ int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
++	;
++
++ulonglong_num:
++	NUM	    { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
++	| ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
++	| LONG_NUM  { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
++        | DECIMAL_NUM  { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
++	| FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
++	;
++
++procedure_clause:
++	/* empty */
++	| PROCEDURE ident			/* Procedure name */
++	  {
++	    LEX *lex=Lex;
++
++            if (! lex->parsing_options.allows_select_procedure)
++            {
++              my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "PROCEDURE");
++              MYSQL_YYABORT;
++            }
++
++	    if (&lex->select_lex != lex->current_select)
++	    {
++	      my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery");
++	      MYSQL_YYABORT;
++	    }
++	    lex->proc_list.elements=0;
++	    lex->proc_list.first=0;
++	    lex->proc_list.next= (byte**) &lex->proc_list.first;
++	    if (add_proc_to_list(lex->thd, new Item_field(&lex->
++                                                          current_select->
++                                                          context,
++                                                          NULL,NULL,$2.str)))
++	      MYSQL_YYABORT;
++	    Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
++	  }
++	  '(' procedure_list ')';
++
++
++procedure_list:
++	/* empty */ {}
++	| procedure_list2 {};
++
++procedure_list2:
++	procedure_list2 ',' procedure_item
++	| procedure_item;
++
++procedure_item:
++	  remember_name expr
++	  {
++            THD *thd= YYTHD;
++            Lex_input_stream *lip= thd->m_lip;
++
++	    if (add_proc_to_list(thd, $2))
++	      MYSQL_YYABORT;
++	    if (!$2->name)
++	      $2->set_name($1,(uint) ((char*) lip->tok_end - $1),
++                           thd->charset());
++	  }
++          ;
++
++
++select_var_list_init:
++	   {
++             LEX *lex=Lex;
++	     if (!lex->describe && (!(lex->result= new select_dumpvar())))
++	        MYSQL_YYABORT;
++	   }
++	   select_var_list
++	   {}
++           ;
++
++select_var_list:
++	   select_var_list ',' select_var_ident
++	   | select_var_ident {}
++           ;
++
++select_var_ident:  
++	   '@' ident_or_text
++           {
++             LEX *lex=Lex;
++	     if (lex->result) 
++	       ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($2,0,0,(enum_field_types)0));
++	     else
++               /*
++                 The parser won't create select_result instance only
++	         if it's an EXPLAIN.
++               */
++               DBUG_ASSERT(lex->describe);
++	   }
++           | ident_or_text
++           {
++             LEX *lex=Lex;
++	     sp_variable_t *t;
++
++	     if (!lex->spcont || !(t=lex->spcont->find_variable(&$1)))
++	     {
++	       my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
++	       MYSQL_YYABORT;
++	     }
++	     if (lex->result)
++             {
++               my_var *var;
++	       ((select_dumpvar *)lex->result)->
++                 var_list.push_back(var= new my_var($1,1,t->offset,t->type));
++#ifndef DBUG_OFF
++	       if (var)
++		 var->sp= lex->sphead;
++#endif
++             }
++	     else
++	     {
++               /*
++                 The parser won't create select_result instance only
++	         if it's an EXPLAIN.
++               */
++               DBUG_ASSERT(lex->describe);
++	     }
++	   }
++           ;
++
++into:
++        INTO
++	{
++          if (! Lex->parsing_options.allows_select_into)
++          {
++            my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "INTO");
++            MYSQL_YYABORT;
++          }
++	}
++        into_destination
++        ;
++
++into_destination:
++        OUTFILE TEXT_STRING_filesystem
++	{
++          LEX *lex= Lex;
++          lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
++          if (!(lex->exchange= new sql_exchange($2.str, 0)) ||
++              !(lex->result= new select_export(lex->exchange)))
++            MYSQL_YYABORT;
++	}
++	opt_field_term opt_line_term
++	| DUMPFILE TEXT_STRING_filesystem
++	{
++	  LEX *lex=Lex;
++	  if (!lex->describe)
++	  {
++	    lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
++	    if (!(lex->exchange= new sql_exchange($2.str,1)))
++	      MYSQL_YYABORT;
++	    if (!(lex->result= new select_dump(lex->exchange)))
++	      MYSQL_YYABORT;
++	  }
++	}
++        | select_var_list_init
++	{
++	  Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
++	}
++        ;
++
++/*
++  DO statement
++*/
++
++do:	DO_SYM
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command = SQLCOM_DO;
++	  mysql_init_select(lex);
++	}
++	expr_list
++	{
++	  Lex->insert_list= $3;
++	}
++	;
++
++/*
++  Drop : delete tables or index or user
++*/
++
++drop:
++	DROP opt_temporary table_or_tables if_exists table_list opt_restrict
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command = SQLCOM_DROP_TABLE;
++	  lex->drop_temporary= $2;
++	  lex->drop_if_exists= $4;
++	}
++	| DROP INDEX_SYM ident ON table_ident {}
++	  {
++	     LEX *lex=Lex;
++	     lex->sql_command= SQLCOM_DROP_INDEX;
++             lex->alter_info.reset();
++             lex->alter_info.flags= ALTER_DROP_INDEX;
++	     lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
++                                                                $3.str));
++	     if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
++							TL_OPTION_UPDATING))
++	      MYSQL_YYABORT;
++	  }
++	| DROP DATABASE if_exists ident
++	  {
++	    LEX *lex=Lex;
++	    lex->sql_command= SQLCOM_DROP_DB;
++	    lex->drop_if_exists=$3;
++	    lex->name=$4.str;
++	 }
++	| DROP FUNCTION_SYM if_exists sp_name
++	  {
++	    LEX *lex=Lex;
++	    if (lex->sphead)
++	    {
++	      my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
++	      MYSQL_YYABORT;
++	    }
++	    lex->sql_command = SQLCOM_DROP_FUNCTION;
++	    lex->drop_if_exists= $3;
++	    lex->spname= $4;
++	  }
++	| DROP PROCEDURE if_exists sp_name
++	  {
++	    LEX *lex=Lex;
++	    if (lex->sphead)
++	    {
++	      my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
++	      MYSQL_YYABORT;
++	    }
++	    lex->sql_command = SQLCOM_DROP_PROCEDURE;
++	    lex->drop_if_exists= $3;
++	    lex->spname= $4;
++	  }
++	| DROP USER clear_privileges user_list
++	  {
++	    Lex->sql_command = SQLCOM_DROP_USER;
++          }
++	| DROP VIEW_SYM if_exists table_list opt_restrict
++	  {
++	    LEX *lex= Lex;
++	    lex->sql_command= SQLCOM_DROP_VIEW;
++	    lex->drop_if_exists= $3;
++	  }
++        | DROP TRIGGER_SYM if_exists sp_name
++          {
++            LEX *lex= Lex;
++            lex->sql_command= SQLCOM_DROP_TRIGGER;
++            lex->drop_if_exists= $3;
++            lex->spname= $4;
++          }
++	;
++
++table_list:
++	table_name
++	| table_list ',' table_name;
++
++table_name:
++	table_ident
++	{
++	  if (!Select->add_table_to_list(YYTHD, $1, NULL, TL_OPTION_UPDATING))
++	    MYSQL_YYABORT;
++	}
++	;
++
++table_alias_ref_list:
++        table_alias_ref
++        | table_alias_ref_list ',' table_alias_ref;
++
++table_alias_ref:
++	table_ident
++	{
++	  if (!Select->add_table_to_list(YYTHD, $1, NULL,
++                                         TL_OPTION_UPDATING | TL_OPTION_ALIAS,
++                                         Lex->lock_option ))
++	    MYSQL_YYABORT;
++	}
++	;
++
++if_exists:
++	/* empty */ { $$= 0; }
++	| IF EXISTS { $$= 1; }
++	;
++
++opt_temporary:
++	/* empty */ { $$= 0; }
++	| TEMPORARY { $$= 1; }
++	;
++/*
++** Insert : add new data to table
++*/
++
++insert:
++	INSERT
++	{
++	  LEX *lex= Lex;
++	  lex->sql_command= SQLCOM_INSERT;
++	  lex->duplicates= DUP_ERROR; 
++	  mysql_init_select(lex);
++	  /* for subselects */
++          lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
++	} insert_lock_option
++	opt_ignore insert2
++	{
++	  Select->set_lock_for_tables($3);
++	  Lex->current_select= &Lex->select_lex;
++	}
++	insert_field_spec opt_insert_update
++	{}
++	;
++
++replace:
++	REPLACE
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command = SQLCOM_REPLACE;
++	  lex->duplicates= DUP_REPLACE;
++	  mysql_init_select(lex);
++	}
++	replace_lock_option insert2
++	{
++	  Select->set_lock_for_tables($3);
++	  Lex->current_select= &Lex->select_lex;
++	}
++	insert_field_spec
++	{}
++	;
++
++insert_lock_option:
++	/* empty */
++          {
++#ifdef HAVE_QUERY_CACHE
++            /*
++              If it is SP we do not allow insert optimisation whan result of
++              insert visible only after the table unlocking but everyone can
++              read table.
++            */
++            $$= (Lex->sphead ? TL_WRITE_DEFAULT : TL_WRITE_CONCURRENT_INSERT);
++#else
++            $$= TL_WRITE_CONCURRENT_INSERT;
++#endif
++          }
++	| LOW_PRIORITY	{ $$= TL_WRITE_LOW_PRIORITY; }
++	| DELAYED_SYM	{ $$= TL_WRITE_DELAYED; }
++	| HIGH_PRIORITY { $$= TL_WRITE; }
++	;
++
++replace_lock_option:
++	opt_low_priority { $$= $1; }
++	| DELAYED_SYM	 { $$= TL_WRITE_DELAYED; };
++
++insert2:
++	INTO insert_table {}
++	| insert_table {};
++
++insert_table:
++	table_name
++	{
++	  LEX *lex=Lex;
++	  lex->field_list.empty();
++	  lex->many_values.empty();
++	  lex->insert_list=0;
++	};
++
++insert_field_spec:
++	insert_values {}
++	| '(' ')' insert_values {}
++	| '(' fields ')' insert_values {}
++	| SET
++	  {
++	    LEX *lex=Lex;
++	    if (!(lex->insert_list = new List_item) ||
++		lex->many_values.push_back(lex->insert_list))
++	      MYSQL_YYABORT;
++	   }
++	   ident_eq_list;
++
++fields:
++	fields ',' insert_ident { Lex->field_list.push_back($3); }
++	| insert_ident		{ Lex->field_list.push_back($1); };
++
++insert_values:
++	VALUES	values_list  {}
++	| VALUE_SYM values_list  {}
++	|     create_select     { Select->set_braces(0);} union_clause {}
++	| '(' create_select ')' { Select->set_braces(1);} union_opt {}
++        ;
++
++values_list:
++	values_list ','  no_braces
++	| no_braces;
++
++ident_eq_list:
++	ident_eq_list ',' ident_eq_value
++	|
++	ident_eq_value;
++
++ident_eq_value:
++	simple_ident_nospvar equal expr_or_default
++	 {
++	  LEX *lex=Lex;
++	  if (lex->field_list.push_back($1) ||
++	      lex->insert_list->push_back($3))
++	    MYSQL_YYABORT;
++	 };
++
++equal:	EQ		{}
++	| SET_VAR	{}
++	;
++
++opt_equal:
++	/* empty */	{}
++	| equal		{}
++	;
++
++no_braces:
++	 '('
++	 {
++	    if (!(Lex->insert_list = new List_item))
++	      MYSQL_YYABORT;
++	 }
++	 opt_values ')'
++	 {
++	  LEX *lex=Lex;
++	  if (lex->many_values.push_back(lex->insert_list))
++	    MYSQL_YYABORT;
++	 };
++
++opt_values:
++	/* empty */ {}
++	| values;
++
++values:
++	values ','  expr_or_default
++	{
++	  if (Lex->insert_list->push_back($3))
++	    MYSQL_YYABORT;
++	}
++	| expr_or_default
++	  {
++	    if (Lex->insert_list->push_back($1))
++	      MYSQL_YYABORT;
++	  }
++	;
++
++expr_or_default:
++	expr	  { $$= $1;}
++	| DEFAULT {$$= new Item_default_value(Lex->current_context()); }
++	;
++
++opt_insert_update:
++        /* empty */
++        | ON DUPLICATE_SYM	{ Lex->duplicates= DUP_UPDATE; }
++          KEY_SYM UPDATE_SYM insert_update_list
++        ;
++
++/* Update rows in a table */
++
++update:
++	UPDATE_SYM
++	{
++	  LEX *lex= Lex;
++	  mysql_init_select(lex);
++          lex->sql_command= SQLCOM_UPDATE;
++	  lex->lock_option= TL_UNLOCK; 	/* Will be set later */
++	  lex->duplicates= DUP_ERROR; 
++        }
++        opt_low_priority opt_ignore join_table_list
++	SET update_list
++	{
++	  LEX *lex= Lex;
++          if (lex->select_lex.table_list.elements > 1)
++            lex->sql_command= SQLCOM_UPDATE_MULTI;
++	  else if (lex->select_lex.get_table_list()->derived)
++	  {
++	    /* it is single table update and it is update of derived table */
++	    my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
++                     lex->select_lex.get_table_list()->alias, "UPDATE");
++	    MYSQL_YYABORT;
++	  }
++          /*
++            In case of multi-update setting write lock for all tables may
++            be too pessimistic. We will decrease lock level if possible in
++            mysql_multi_update().
++          */
++          Select->set_lock_for_tables($3);
++	}
++	where_clause opt_order_clause delete_limit_clause {}
++	;
++
++update_list:
++	update_list ',' update_elem
++	| update_elem;
++
++update_elem:
++	simple_ident_nospvar equal expr_or_default
++	{
++	  if (add_item_to_list(YYTHD, $1) || add_value_to_list(YYTHD, $3))
++	    MYSQL_YYABORT;
++	};
++
++insert_update_list:
++	insert_update_list ',' insert_update_elem
++	| insert_update_elem;
++
++insert_update_elem:
++	simple_ident_nospvar equal expr_or_default
++	  {
++	  LEX *lex= Lex;
++	  if (lex->update_list.push_back($1) || 
++	      lex->value_list.push_back($3))
++	      MYSQL_YYABORT;
++	  };
++
++opt_low_priority:
++	/* empty */	{ $$= TL_WRITE_DEFAULT; }
++	| LOW_PRIORITY	{ $$= TL_WRITE_LOW_PRIORITY; };
++
++/* Delete rows from a table */
++
++delete:
++	DELETE_SYM
++	{
++	  LEX *lex= Lex;
++	  lex->sql_command= SQLCOM_DELETE;
++	  mysql_init_select(lex);
++	  lex->lock_option= TL_WRITE_DEFAULT;
++	  lex->ignore= 0;
++	  lex->select_lex.init_order();
++	}
++	opt_delete_options single_multi {}
++	;
++
++single_multi:
++ 	FROM table_ident
++	{
++	  if (!Select->add_table_to_list(YYTHD, $2, NULL, TL_OPTION_UPDATING,
++					 Lex->lock_option))
++	    MYSQL_YYABORT;
++	}
++	where_clause opt_order_clause
++	delete_limit_clause {}
++	| table_wild_list
++	  { mysql_init_multi_delete(Lex); }
++          FROM join_table_list where_clause
++          { 
++            if (multi_delete_set_locks_and_link_aux_tables(Lex))
++              MYSQL_YYABORT;
++          }
++	| FROM table_alias_ref_list
++	  { mysql_init_multi_delete(Lex); }
++	  USING join_table_list where_clause
++          { 
++            if (multi_delete_set_locks_and_link_aux_tables(Lex))
++              MYSQL_YYABORT;
++          }
++	;
++
++table_wild_list:
++	  table_wild_one {}
++	  | table_wild_list ',' table_wild_one {};
++
++table_wild_one:
++	ident opt_wild opt_table_alias
++	{
++	  if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3,
++					 TL_OPTION_UPDATING | 
++                                         TL_OPTION_ALIAS, Lex->lock_option))
++	    MYSQL_YYABORT;
++        }
++	| ident '.' ident opt_wild opt_table_alias
++	  {
++	    if (!Select->add_table_to_list(YYTHD,
++					   new Table_ident(YYTHD, $1, $3, 0),
++					   $5, 
++                                           TL_OPTION_UPDATING | 
++                                           TL_OPTION_ALIAS,
++					   Lex->lock_option))
++	      MYSQL_YYABORT;
++	  }
++	;
++
++opt_wild:
++	/* empty */	{}
++	| '.' '*'	{};
++
++
++opt_delete_options:
++	/* empty */	{}
++	| opt_delete_option opt_delete_options {};
++
++opt_delete_option:
++	QUICK		{ Select->options|= OPTION_QUICK; }
++	| LOW_PRIORITY	{ Lex->lock_option= TL_WRITE_LOW_PRIORITY; }
++	| IGNORE_SYM	{ Lex->ignore= 1; };
++
++truncate:
++	TRUNCATE_SYM opt_table_sym table_name
++	{
++	  LEX* lex= Lex;
++	  lex->sql_command= SQLCOM_TRUNCATE;
++	  lex->select_lex.options= 0;
++          lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
++	  lex->select_lex.init_order();
++	}
++	;
++
++opt_table_sym:
++	/* empty */
++	| TABLE_SYM;
++
++opt_profile_defs:
++  /* empty */
++  | profile_defs;
++
++profile_defs:
++  profile_def
++  | profile_defs ',' profile_def;
++
++profile_def:
++  CPU_SYM
++    {
++      Lex->profile_options|= PROFILE_CPU;
++    }
++  | MEMORY_SYM
++    {
++      Lex->profile_options|= PROFILE_MEMORY;
++    }
++  | BLOCK_SYM IO_SYM
++    {
++      Lex->profile_options|= PROFILE_BLOCK_IO;
++    }
++  | CONTEXT_SYM SWITCHES_SYM
++    {
++      Lex->profile_options|= PROFILE_CONTEXT;
++    }
++  | PAGE_SYM FAULTS_SYM
++    {
++      Lex->profile_options|= PROFILE_PAGE_FAULTS;
++    }
++  | IPC_SYM
++    {
++      Lex->profile_options|= PROFILE_IPC;
++    }
++  | SWAPS_SYM
++    {
++      Lex->profile_options|= PROFILE_SWAPS;
++    }
++  | SOURCE_SYM
++    {
++      Lex->profile_options|= PROFILE_SOURCE;
++    }
++  | ALL
++    {
++      Lex->profile_options|= PROFILE_ALL;
++    }
++  ;
++
++opt_profile_args:
++  /* empty */
++    {
++      Lex->profile_query_id= 0;
++    }
++  | FOR_SYM QUERY_SYM NUM
++    {
++      Lex->profile_query_id= atoi($3.str);
++    }
++  ;
++
++/* Show things */
++
++show:	SHOW
++	{
++	  LEX *lex=Lex;
++	  lex->wild=0;
++          lex->lock_option= TL_READ;
++          mysql_init_select(lex);
++          lex->current_select->parsing_place= SELECT_LIST;
++	  bzero((char*) &lex->create_info,sizeof(lex->create_info));
++	}
++	show_param
++	{}
++	;
++
++show_param:
++         DATABASES wild_and_where
++         {
++           LEX *lex= Lex;
++           lex->sql_command= SQLCOM_SELECT;
++           lex->orig_sql_command= SQLCOM_SHOW_DATABASES;
++           if (prepare_schema_table(YYTHD, lex, 0, SCH_SCHEMATA))
++             MYSQL_YYABORT;
++         }
++         | opt_full TABLES opt_db wild_and_where
++           {
++             LEX *lex= Lex;
++             lex->sql_command= SQLCOM_SELECT;
++             lex->orig_sql_command= SQLCOM_SHOW_TABLES;
++             lex->select_lex.db= $3;
++             if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_NAMES))
++               MYSQL_YYABORT;
++           }
++         | opt_full TRIGGERS_SYM opt_db wild_and_where
++           {
++             LEX *lex= Lex;
++             lex->sql_command= SQLCOM_SELECT;
++             lex->orig_sql_command= SQLCOM_SHOW_TRIGGERS;
++             lex->select_lex.db= $3;
++             if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS))
++               MYSQL_YYABORT;
++           }
++         | TABLE_SYM STATUS_SYM opt_db wild_and_where
++           {
++             LEX *lex= Lex;
++             lex->sql_command= SQLCOM_SELECT;
++             lex->orig_sql_command= SQLCOM_SHOW_TABLE_STATUS;
++             lex->select_lex.db= $3;
++             if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLES))
++               MYSQL_YYABORT;
++           }
++        | OPEN_SYM TABLES opt_db wild_and_where
++	  {
++	    LEX *lex= Lex;
++            lex->sql_command= SQLCOM_SELECT;
++            lex->orig_sql_command= SQLCOM_SHOW_OPEN_TABLES;
++	    lex->select_lex.db= $3;
++            if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES))
++              MYSQL_YYABORT;
++	  }
++	| ENGINE_SYM storage_engines 
++	  { Lex->create_info.db_type= $2; }
++	  show_engine_param
++	| opt_full COLUMNS from_or_in table_ident opt_db wild_and_where
++	  {
++ 	    LEX *lex= Lex;
++	    lex->sql_command= SQLCOM_SELECT;
++	    lex->orig_sql_command= SQLCOM_SHOW_FIELDS;
++	    if ($5)
++	      $4->change_db($5);
++	    if (prepare_schema_table(YYTHD, lex, $4, SCH_COLUMNS))
++	      MYSQL_YYABORT;
++	  }
++        | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ
++	  TEXT_STRING_sys AND_SYM MASTER_LOG_POS_SYM EQ ulonglong_num
++	  AND_SYM MASTER_SERVER_ID_SYM EQ
++	ulong_num
++          {
++	    Lex->sql_command = SQLCOM_SHOW_NEW_MASTER;
++	    Lex->mi.log_file_name = $8.str;
++	    Lex->mi.pos = $12;
++	    Lex->mi.server_id = $16;
++          }
++        | master_or_binary LOGS_SYM
++          {
++	    Lex->sql_command = SQLCOM_SHOW_BINLOGS;
++          }
++        | SLAVE HOSTS_SYM
++          {
++	    Lex->sql_command = SQLCOM_SHOW_SLAVE_HOSTS;
++          }
++        | BINLOG_SYM EVENTS_SYM binlog_in binlog_from
++          {
++	    LEX *lex= Lex;
++	    lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
++          } opt_limit_clause_init
++        | keys_or_index from_or_in table_ident opt_db where_clause
++          {
++            LEX *lex= Lex;
++            lex->sql_command= SQLCOM_SELECT;
++            lex->orig_sql_command= SQLCOM_SHOW_KEYS;
++	    if ($4)
++	      $3->change_db($4);
++            if (prepare_schema_table(YYTHD, lex, $3, SCH_STATISTICS))
++              MYSQL_YYABORT;
++	  }
++	| COLUMN_SYM TYPES_SYM
++	  {
++	    LEX *lex=Lex;
++	    lex->sql_command= SQLCOM_SHOW_COLUMN_TYPES;
++	  }
++	| TABLE_SYM TYPES_SYM
++	  {
++	    LEX *lex=Lex;
++	    lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES;
++	    WARN_DEPRECATED("SHOW TABLE TYPES", "SHOW [STORAGE] ENGINES");
++	  }
++	| opt_storage ENGINES_SYM
++	  {
++	    LEX *lex=Lex;
++	    lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES;
++	  }
++	| PRIVILEGES
++	  {
++	    LEX *lex=Lex;
++	    lex->sql_command= SQLCOM_SHOW_PRIVILEGES;
++	  }
++        | COUNT_SYM '(' '*' ')' WARNINGS
++          { (void) create_select_for_variable("warning_count"); }
++        | COUNT_SYM '(' '*' ')' ERRORS
++	  { (void) create_select_for_variable("error_count"); }
++        | WARNINGS opt_limit_clause_init
++          { Lex->sql_command = SQLCOM_SHOW_WARNS;}
++        | ERRORS opt_limit_clause_init
++          { Lex->sql_command = SQLCOM_SHOW_ERRORS;}
++        | PROFILES_SYM
++          { Lex->sql_command = SQLCOM_SHOW_PROFILES; }
++        | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause_init
++          { 
++            LEX *lex= Lex;
++            lex->sql_command= SQLCOM_SELECT;
++            lex->orig_sql_command= SQLCOM_SHOW_PROFILE;
++            if (prepare_schema_table(YYTHD, lex, NULL, SCH_PROFILES) != 0)
++              YYABORT;
++          }
++        | opt_var_type STATUS_SYM wild_and_where
++          {
++            LEX *lex= Lex;
++            lex->sql_command= SQLCOM_SELECT;
++            lex->orig_sql_command= SQLCOM_SHOW_STATUS;
++            lex->option_type= $1;
++            if (prepare_schema_table(YYTHD, lex, 0, SCH_STATUS))
++              MYSQL_YYABORT;
++	  }	
++        | INNOBASE_SYM STATUS_SYM
++          { Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS; WARN_DEPRECATED("SHOW INNODB STATUS", "SHOW ENGINE INNODB STATUS"); }
++        | MUTEX_SYM STATUS_SYM
++          { Lex->sql_command = SQLCOM_SHOW_MUTEX_STATUS; }
++	| opt_full PROCESSLIST_SYM
++	  { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;}
++        | opt_var_type  VARIABLES wild_and_where
++	  {
++            LEX *lex= Lex;
++            lex->sql_command= SQLCOM_SELECT;
++            lex->orig_sql_command= SQLCOM_SHOW_VARIABLES;
++            lex->option_type= $1;
++            if (prepare_schema_table(YYTHD, lex, 0, SCH_VARIABLES))
++              MYSQL_YYABORT;
++	  }
++        | charset wild_and_where
++          {
++            LEX *lex= Lex;
++            lex->sql_command= SQLCOM_SELECT;
++            lex->orig_sql_command= SQLCOM_SHOW_CHARSETS;
++            if (prepare_schema_table(YYTHD, lex, 0, SCH_CHARSETS))
++              MYSQL_YYABORT;
++          }
++        | COLLATION_SYM wild_and_where
++          {
++            LEX *lex= Lex;
++            lex->sql_command= SQLCOM_SELECT;
++            lex->orig_sql_command= SQLCOM_SHOW_COLLATIONS;
++            if (prepare_schema_table(YYTHD, lex, 0, SCH_COLLATIONS))
++              MYSQL_YYABORT;
++          }
++	| BERKELEY_DB_SYM LOGS_SYM
++	  { Lex->sql_command= SQLCOM_SHOW_LOGS; WARN_DEPRECATED("SHOW BDB LOGS", "SHOW ENGINE BDB LOGS"); }
++	| LOGS_SYM
++	  { Lex->sql_command= SQLCOM_SHOW_LOGS; WARN_DEPRECATED("SHOW LOGS", "SHOW ENGINE BDB LOGS"); }
++	| GRANTS
++	  {
++	    LEX *lex=Lex;
++	    lex->sql_command= SQLCOM_SHOW_GRANTS;
++	    LEX_USER *curr_user;
++            if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user))))
++              MYSQL_YYABORT;
++            bzero(curr_user, sizeof(st_lex_user));
++	    lex->grant_user= curr_user;
++	  }
++	| GRANTS FOR_SYM user
++	  {
++	    LEX *lex=Lex;
++	    lex->sql_command= SQLCOM_SHOW_GRANTS;
++	    lex->grant_user=$3;
++	    lex->grant_user->password=null_lex_str;
++	  }
++	| CREATE DATABASE opt_if_not_exists ident
++	  {
++	    Lex->sql_command=SQLCOM_SHOW_CREATE_DB;
++	    Lex->create_info.options=$3;
++	    Lex->name=$4.str;
++	  }
++        | CREATE TABLE_SYM table_ident
++          {
++            LEX *lex= Lex;
++	    lex->sql_command = SQLCOM_SHOW_CREATE;
++	    if (!lex->select_lex.add_table_to_list(YYTHD, $3, NULL,0))
++	      MYSQL_YYABORT;
++            lex->only_view= 0;
++	  }
++        | CREATE VIEW_SYM table_ident
++          {
++            LEX *lex= Lex;
++	    lex->sql_command = SQLCOM_SHOW_CREATE;
++	    if (!lex->select_lex.add_table_to_list(YYTHD, $3, NULL, 0))
++	      MYSQL_YYABORT;
++            lex->only_view= 1;
++	  }
++        | MASTER_SYM STATUS_SYM
++          {
++	    Lex->sql_command = SQLCOM_SHOW_MASTER_STAT;
++          }
++        | SLAVE STATUS_SYM
++          {
++	    Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
++          }
++	| CREATE PROCEDURE sp_name
++	  {
++	    LEX *lex= Lex;
++
++	    lex->sql_command = SQLCOM_SHOW_CREATE_PROC;
++	    lex->spname= $3;
++	  }
++	| CREATE FUNCTION_SYM sp_name
++	  {
++	    LEX *lex= Lex;
++
++	    lex->sql_command = SQLCOM_SHOW_CREATE_FUNC;
++	    lex->spname= $3;
++	  }
++	| PROCEDURE STATUS_SYM wild_and_where
++	  {
++            LEX *lex= Lex;
++            lex->sql_command= SQLCOM_SELECT;
++            lex->orig_sql_command= SQLCOM_SHOW_STATUS_PROC;
++	    if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
++	      MYSQL_YYABORT;
++            if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
++              MYSQL_YYABORT;
++	  }
++	| FUNCTION_SYM STATUS_SYM wild_and_where
++	  {
++            LEX *lex= Lex;
++            lex->sql_command= SQLCOM_SELECT;
++            lex->orig_sql_command= SQLCOM_SHOW_STATUS_FUNC;
++	    if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
++	      MYSQL_YYABORT;
++            if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
++              MYSQL_YYABORT;
++	  }
++        | PROCEDURE CODE_SYM sp_name
++          {
++#ifdef DBUG_OFF
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++            MYSQL_YYABORT;
++#else
++            Lex->sql_command= SQLCOM_SHOW_PROC_CODE;
++	    Lex->spname= $3;
++#endif
++          }
++        | FUNCTION_SYM CODE_SYM sp_name
++          {
++#ifdef DBUG_OFF
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++            MYSQL_YYABORT;
++#else
++            Lex->sql_command= SQLCOM_SHOW_FUNC_CODE;
++	    Lex->spname= $3;
++#endif
++          }
++        ;
++
++show_engine_param:
++	STATUS_SYM
++	  {
++	    switch (Lex->create_info.db_type) {
++	    case DB_TYPE_NDBCLUSTER:
++	      Lex->sql_command = SQLCOM_SHOW_NDBCLUSTER_STATUS;
++	      break;
++	    case DB_TYPE_INNODB:
++	      Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS;
++	      break;
++	    default:
++	      my_error(ER_NOT_SUPPORTED_YET, MYF(0), "STATUS");
++	      MYSQL_YYABORT;
++	    }
++	  }
++	| LOGS_SYM
++	  {
++	    switch (Lex->create_info.db_type) {
++	    case DB_TYPE_BERKELEY_DB:
++	      Lex->sql_command = SQLCOM_SHOW_LOGS;
++	      break;
++	    default:
++	      my_error(ER_NOT_SUPPORTED_YET, MYF(0), "LOGS");
++	      MYSQL_YYABORT;
++	    }
++	  };
++
++master_or_binary:
++	MASTER_SYM
++	| BINARY;
++
++opt_storage:
++	/* empty */
++	| STORAGE_SYM;
++
++opt_db:
++	/* empty */  { $$= 0; }
++	| from_or_in ident { $$= $2.str; };
++
++opt_full:
++	/* empty */ { Lex->verbose=0; }
++	| FULL	    { Lex->verbose=1; };
++
++from_or_in:
++	FROM
++	| IN_SYM;
++
++binlog_in:
++	/* empty */ { Lex->mi.log_file_name = 0; }
++        | IN_SYM TEXT_STRING_sys { Lex->mi.log_file_name = $2.str; };
++
++binlog_from:
++	/* empty */ { Lex->mi.pos = 4; /* skip magic number */ }
++        | FROM ulonglong_num { Lex->mi.pos = $2; };
++
++wild_and_where:
++      /* empty */
++      | LIKE TEXT_STRING_sys
++	{ Lex->wild=  new (YYTHD->mem_root) String($2.str, $2.length,
++                                                   system_charset_info); }
++      | WHERE expr
++        {
++          Select->where= $2;
++          if ($2)
++            $2->top_level_item();
++        }
++      ;
++
++
++/* A Oracle compatible synonym for show */
++describe:
++	describe_command table_ident
++	{
++          LEX *lex= Lex;
++          lex->lock_option= TL_READ;
++          mysql_init_select(lex);
++          lex->current_select->parsing_place= SELECT_LIST;
++          lex->sql_command= SQLCOM_SELECT;
++          lex->orig_sql_command= SQLCOM_SHOW_FIELDS;
++          lex->select_lex.db= 0;
++          lex->verbose= 0;
++          if (prepare_schema_table(YYTHD, lex, $2, SCH_COLUMNS))
++	    MYSQL_YYABORT;
++	}
++	opt_describe_column {}
++	| describe_command opt_extended_describe
++	  { Lex->describe|= DESCRIBE_NORMAL; }
++	  select
++          {
++	    LEX *lex=Lex;
++	    lex->select_lex.options|= SELECT_DESCRIBE;
++	  }
++	;
++
++describe_command:
++	DESC
++	| DESCRIBE;
++
++opt_extended_describe:
++	/* empty */ {}
++	| EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
++	;
++
++opt_describe_column:
++	/* empty */	{}
++	| text_string	{ Lex->wild= $1; }
++	| ident
++	  { Lex->wild= new (YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info); };
++
++
++/* flush things */
++
++flush:
++	FLUSH_SYM opt_no_write_to_binlog
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command= SQLCOM_FLUSH;
++          lex->type= 0;
++          lex->no_write_to_binlog= $2;
++	}
++	flush_options
++	{}
++	;
++
++flush_options:
++	flush_options ',' flush_option
++	| flush_option;
++
++flush_option:
++	table_or_tables	{ Lex->type|= REFRESH_TABLES; } opt_table_list {}
++	| TABLES WITH READ_SYM LOCK_SYM { Lex->type|= REFRESH_TABLES | REFRESH_READ_LOCK; }
++	| QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE_FREE; }
++	| HOSTS_SYM	{ Lex->type|= REFRESH_HOSTS; }
++	| PRIVILEGES	{ Lex->type|= REFRESH_GRANT; }
++	| LOGS_SYM	{ Lex->type|= REFRESH_LOG; }
++	| STATUS_SYM	{ Lex->type|= REFRESH_STATUS; }
++        | SLAVE         { Lex->type|= REFRESH_SLAVE; }
++        | MASTER_SYM    { Lex->type|= REFRESH_MASTER; }
++	| DES_KEY_FILE	{ Lex->type|= REFRESH_DES_KEY_FILE; }
++ 	| RESOURCES     { Lex->type|= REFRESH_USER_RESOURCES; };
++
++opt_table_list:
++	/* empty */  {;}
++	| table_list {;};
++
++reset:
++	RESET_SYM
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command= SQLCOM_RESET; lex->type=0;
++	} reset_options
++	{}
++	;
++
++reset_options:
++	reset_options ',' reset_option
++	| reset_option;
++
++reset_option:
++        SLAVE                 { Lex->type|= REFRESH_SLAVE; }
++        | MASTER_SYM          { Lex->type|= REFRESH_MASTER; }
++	| QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE;};
++
++purge:
++	PURGE
++	{
++	  LEX *lex=Lex;
++	  lex->type=0;
++          lex->sql_command = SQLCOM_PURGE;
++	} purge_options
++	{}
++	;
++
++purge_options:
++	master_or_binary LOGS_SYM purge_option
++	;
++
++purge_option:
++        TO_SYM TEXT_STRING_sys
++        {
++	   Lex->to_log = $2.str;
++        }
++	| BEFORE_SYM expr
++	{
++	  LEX *lex= Lex;
++	  lex->value_list.empty();
++	  lex->value_list.push_front($2);
++	  lex->sql_command= SQLCOM_PURGE_BEFORE;
++	}
++	;
++
++/* kill threads */
++
++kill:
++	KILL_SYM { Lex->sql_command= SQLCOM_KILL; } kill_option expr
++	{
++	  LEX *lex=Lex;
++	  lex->value_list.empty();
++	  lex->value_list.push_front($4);
++	};
++
++kill_option:
++	/* empty */	 { Lex->type= 0; }
++	| CONNECTION_SYM { Lex->type= 0; }
++	| QUERY_SYM      { Lex->type= ONLY_KILL_QUERY; }
++        ;
++
++/* change database */
++
++use:	USE_SYM ident
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command=SQLCOM_CHANGE_DB;
++	  lex->select_lex.db= $2.str;
++	};
++
++/* import, export of files */
++
++load:   LOAD DATA_SYM
++        {
++          THD *thd= YYTHD;
++          LEX *lex= thd->lex;
++          Lex_input_stream *lip= thd->m_lip;
++
++	  if (lex->sphead)
++	  {
++	    my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA");
++	    MYSQL_YYABORT;
++	  }
++          lex->fname_start= lip->ptr;
++        }
++        load_data
++        {}
++        |
++        LOAD TABLE_SYM table_ident FROM MASTER_SYM
++        {
++	  LEX *lex=Lex;
++	  if (lex->sphead)
++	  {
++	    my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD TABLE");
++	    MYSQL_YYABORT;
++	  }
++          lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
++          WARN_DEPRECATED("LOAD TABLE FROM MASTER",
++                          "mysqldump or future "
++                          "BACKUP/RESTORE DATABASE facility");
++          if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING))
++            MYSQL_YYABORT;
++        };
++
++load_data:
++	load_data_lock opt_local INFILE TEXT_STRING_filesystem
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command= SQLCOM_LOAD;
++	  lex->lock_option= $1;
++	  lex->local_file=  $2;
++	  lex->duplicates= DUP_ERROR;
++	  lex->ignore= 0;
++	  if (!(lex->exchange= new sql_exchange($4.str, 0)))
++	    MYSQL_YYABORT;
++        }
++        opt_duplicate INTO
++        {
++          THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++          Lex_input_stream *lip= thd->m_lip;
++	  lex->fname_end= lip->ptr;
++	}
++        TABLE_SYM table_ident
++        {
++          LEX *lex=Lex;
++          if (!Select->add_table_to_list(YYTHD, $10, NULL, TL_OPTION_UPDATING,
++                                         lex->lock_option))
++            MYSQL_YYABORT;
++          lex->field_list.empty();
++          lex->update_list.empty();
++          lex->value_list.empty();
++        }
++        opt_load_data_charset
++	{ Lex->exchange->cs= $12; }
++        opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
++        opt_load_data_set_spec
++        {}
++        |
++	FROM MASTER_SYM
++        {
++	  Lex->sql_command = SQLCOM_LOAD_MASTER_DATA;
++          WARN_DEPRECATED("LOAD DATA FROM MASTER",
++                          "mysqldump or future "
++                          "BACKUP/RESTORE DATABASE facility");
++        };
++
++opt_local:
++	/* empty */	{ $$=0;}
++	| LOCAL_SYM	{ $$=1;};
++
++load_data_lock:
++	/* empty */	{ $$= TL_WRITE_DEFAULT; }
++	| CONCURRENT
++          {
++#ifdef HAVE_QUERY_CACHE
++            /*
++              Ignore this option in SP to avoid problem with query cache
++            */
++            if (Lex->sphead != 0)
++              $$= TL_WRITE_DEFAULT;
++            else
++#endif
++              $$= TL_WRITE_CONCURRENT_INSERT;
++          }
++	| LOW_PRIORITY	{ $$= TL_WRITE_LOW_PRIORITY; };
++
++
++opt_duplicate:
++	/* empty */	{ Lex->duplicates=DUP_ERROR; }
++	| REPLACE	{ Lex->duplicates=DUP_REPLACE; }
++	| IGNORE_SYM	{ Lex->ignore= 1; };
++
++opt_field_term:
++	/* empty */
++	| COLUMNS field_term_list;
++
++field_term_list:
++	field_term_list field_term
++	| field_term;
++
++field_term:
++	TERMINATED BY text_string 
++          {
++            DBUG_ASSERT(Lex->exchange != 0);
++            Lex->exchange->field_term= $3;
++          }
++	| OPTIONALLY ENCLOSED BY text_string
++	  {
++            LEX *lex= Lex;
++            DBUG_ASSERT(lex->exchange != 0);
++            lex->exchange->enclosed= $4;
++            lex->exchange->opt_enclosed= 1;
++	  }
++        | ENCLOSED BY text_string
++          {
++            DBUG_ASSERT(Lex->exchange != 0);
++            Lex->exchange->enclosed= $3;
++          }
++        | ESCAPED BY text_string
++          {
++            DBUG_ASSERT(Lex->exchange != 0);
++            Lex->exchange->escaped= $3;
++          };
++
++opt_line_term:
++	/* empty */
++	| LINES line_term_list;
++
++line_term_list:
++	line_term_list line_term
++	| line_term;
++
++line_term:
++        TERMINATED BY text_string
++          {
++            DBUG_ASSERT(Lex->exchange != 0);
++            Lex->exchange->line_term= $3;
++          }
++        | STARTING BY text_string
++          {
++            DBUG_ASSERT(Lex->exchange != 0);
++            Lex->exchange->line_start= $3;
++          };
++
++opt_ignore_lines:
++	/* empty */
++        | IGNORE_SYM NUM LINES
++          {
++            DBUG_ASSERT(Lex->exchange != 0);
++            Lex->exchange->skip_lines= atol($2.str);
++          };
++
++opt_field_or_var_spec:
++	/* empty */	          { }
++	| '(' fields_or_vars ')'  { }
++	| '(' ')'	          { };
++
++fields_or_vars:
++        fields_or_vars ',' field_or_var
++          { Lex->field_list.push_back($3); }
++        | field_or_var
++          { Lex->field_list.push_back($1); }
++        ;
++
++field_or_var:
++        simple_ident_nospvar {$$= $1;}
++        | '@' ident_or_text
++          { $$= new Item_user_var_as_out_param($2); }
++        ;
++
++opt_load_data_set_spec:
++        /* empty */           { }
++        | SET insert_update_list  { };
++
++
++/* Common definitions */
++
++text_literal:
++        TEXT_STRING
++        {
++          LEX_STRING tmp;
++          THD *thd= YYTHD;
++          CHARSET_INFO *cs_con= thd->variables.collation_connection;
++          CHARSET_INFO *cs_cli= thd->variables.character_set_client;
++          uint repertoire= thd->lex->text_string_is_7bit &&
++                             my_charset_is_ascii_based(cs_cli) ?
++                           MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
++          if (thd->charset_is_collation_connection ||
++              (repertoire == MY_REPERTOIRE_ASCII &&
++               my_charset_is_ascii_based(cs_con)))
++            tmp= $1;
++          else
++            thd->convert_string(&tmp, cs_con, $1.str, $1.length, cs_cli);
++          $$= new Item_string(tmp.str, tmp.length, cs_con,
++                              DERIVATION_COERCIBLE, repertoire);
++        }
++        | NCHAR_STRING
++        {
++          uint repertoire= Lex->text_string_is_7bit ?
++                           MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30;
++          DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info));
++          $$= new Item_string($1.str, $1.length, national_charset_info,
++                              DERIVATION_COERCIBLE, repertoire);
++        }
++        | UNDERSCORE_CHARSET TEXT_STRING
++          {
++            $$= new Item_string($2.str, $2.length, Lex->underscore_charset);
++            ((Item_string*) $$)->set_repertoire_from_value();
++          }
++        | text_literal TEXT_STRING_literal
++          {
++            Item_string* item= (Item_string*) $1;
++            item->append($2.str, $2.length);
++            if (!(item->collation.repertoire & MY_REPERTOIRE_EXTENDED))
++            {
++              /*
++                 If the string has been pure ASCII so far,
++                 check the new part.
++              */
++              CHARSET_INFO *cs= YYTHD->variables.collation_connection;
++              item->collation.repertoire|= my_string_repertoire(cs,
++                                                                $2.str,
++                                                                $2.length);
++            }
++          }
++        ;
++
++text_string:
++	TEXT_STRING_literal
++	{ $$=  new (YYTHD->mem_root) String($1.str,$1.length,YYTHD->variables.collation_connection); }
++	| HEX_NUM
++	  {
++	    Item *tmp= new Item_hex_string($1.str, $1.length);
++	    /*
++	      it is OK only emulate fix_fields, because we need only
++              value of constant
++	    */
++	    $$= tmp ?
++	      tmp->quick_fix_field(), tmp->val_str((String*) 0) :
++	      (String*) 0;
++	  }
++        | BIN_NUM
++          {
++	    Item *tmp= new Item_bin_string($1.str, $1.length);
++	    /*
++	      it is OK only emulate fix_fields, because we need only
++              value of constant
++	    */
++	    $$= tmp ? tmp->quick_fix_field(), tmp->val_str((String*) 0) :
++		      (String*) 0;
++          }
++	;
++
++param_marker:
++        PARAM_MARKER
++        {
++          THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++          Lex_input_stream *lip= thd->m_lip;
++          Item_param *item;
++          if (! lex->parsing_options.allows_variable)
++          {
++            my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
++            MYSQL_YYABORT;
++          }
++          item= new Item_param((uint) (lip->tok_start - thd->query));
++          if (!($$= item) || lex->param_list.push_back(item))
++          {
++            my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
++            MYSQL_YYABORT;
++          }
++        }
++	;
++
++signed_literal:
++	literal		{ $$ = $1; }
++	| '+' NUM_literal { $$ = $2; }
++	| '-' NUM_literal
++	  {
++	    $2->max_length++;
++	    $$= $2->neg();
++	  }
++	;
++
++
++literal:
++	text_literal	{ $$ =	$1; }
++	| NUM_literal	{ $$ = $1; }
++	| NULL_SYM
++          {
++            $$ = new Item_null();
++            YYTHD->m_lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
++          }
++	| FALSE_SYM	{ $$= new Item_int((char*) "FALSE",0,1); }
++	| TRUE_SYM	{ $$= new Item_int((char*) "TRUE",1,1); }
++	| HEX_NUM	{ $$ =	new Item_hex_string($1.str, $1.length);}
++	| BIN_NUM	{ $$= new Item_bin_string($1.str, $1.length); }
++        | UNDERSCORE_CHARSET HEX_NUM
++          {
++            Item *tmp= new Item_hex_string($2.str, $2.length);
++            /*
++              it is OK only emulate fix_fieds, because we need only
++              value of constant
++            */
++            String *str= tmp ?
++              tmp->quick_fix_field(), tmp->val_str((String*) 0) :
++              (String*) 0;
++            $$= new Item_string(str ? str->ptr() : "",
++                                str ? str->length() : 0,
++                                Lex->underscore_charset);
++            if ($$)
++              ((Item_string *) $$)->set_repertoire_from_value();
++          }
++	| UNDERSCORE_CHARSET BIN_NUM
++          {
++	    Item *tmp= new Item_bin_string($2.str, $2.length);
++	    /*
++	      it is OK only emulate fix_fieds, because we need only
++              value of constant
++	    */
++	    String *str= tmp ?
++	      tmp->quick_fix_field(), tmp->val_str((String*) 0) :
++	      (String*) 0;
++	    $$= new Item_string(str ? str->ptr() : "",
++				str ? str->length() : 0,
++				Lex->charset);
++          }
++	| DATE_SYM text_literal { $$ = $2; }
++	| TIME_SYM text_literal { $$ = $2; }
++	| TIMESTAMP text_literal { $$ = $2; };
++
++NUM_literal:
++	NUM		{ int error; $$ = new Item_int($1.str, (longlong) my_strtoll10($1.str, NULL, &error), $1.length); }
++	| LONG_NUM	{ int error; $$ = new Item_int($1.str, (longlong) my_strtoll10($1.str, NULL, &error), $1.length); }
++	| ULONGLONG_NUM	{ $$ =	new Item_uint($1.str, $1.length); }
++        | DECIMAL_NUM
++	{
++           $$= new Item_decimal($1.str, $1.length, YYTHD->charset());
++	   if (YYTHD->net.report_error)
++	   {
++	     MYSQL_YYABORT;
++	   }
++	}
++	| FLOAT_NUM
++	{
++	   $$ =	new Item_float($1.str, $1.length);
++	   if (YYTHD->net.report_error)
++	   {
++	     MYSQL_YYABORT;
++	   }
++	}
++	;
++
++/**********************************************************************
++** Creating different items.
++**********************************************************************/
++
++insert_ident:
++	simple_ident_nospvar { $$=$1; }
++	| table_wild	 { $$=$1; };
++
++table_wild:
++	ident '.' '*'
++	{
++          SELECT_LEX *sel= Select;
++	  $$ = new Item_field(Lex->current_context(), NullS, $1.str, "*");
++	  sel->with_wild++;
++	}
++	| ident '.' ident '.' '*'
++	{
++          SELECT_LEX *sel= Select;
++	  $$ = new Item_field(Lex->current_context(), (YYTHD->client_capabilities &
++                             CLIENT_NO_SCHEMA ? NullS : $1.str),
++                             $3.str,"*");
++	  sel->with_wild++;
++	}
++	;
++
++order_ident:
++	expr { $$=$1; };
++
++simple_ident:
++	ident
++	{
++          THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++          Lex_input_stream *lip= thd->m_lip;
++	  sp_variable_t *spv;
++          sp_pcontext *spc = lex->spcont;
++	  if (spc && (spv = spc->find_variable(&$1)))
++	  {
++            /* We're compiling a stored procedure and found a variable */
++            if (! lex->parsing_options.allows_variable)
++            {
++              my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
++              MYSQL_YYABORT;
++            }
++
++            Item_splocal *splocal;
++            splocal= new Item_splocal($1, spv->offset, spv->type,
++                                      lip->tok_start_prev - 
++                                      lex->sphead->m_tmp_query,
++                                      lip->tok_end - lip->tok_start_prev);
++#ifndef DBUG_OFF
++            if (splocal)
++              splocal->m_sp= lex->sphead;
++#endif
++	    $$ = (Item*) splocal;
++	    lex->safe_to_cache_query=0;
++	  }
++	  else
++	  {
++	    SELECT_LEX *sel=Select;
++	    $$= (sel->parsing_place != IN_HAVING ||
++	         sel->get_in_sum_expr() > 0) ?
++                 (Item*) new Item_field(Lex->current_context(), NullS, NullS, $1.str) :
++	         (Item*) new Item_ref(Lex->current_context(), NullS, NullS, $1.str);
++	  }
++        }
++        | simple_ident_q { $$= $1; }
++	;
++
++simple_ident_nospvar:
++	ident
++	{
++	  SELECT_LEX *sel=Select;
++	  $$= (sel->parsing_place != IN_HAVING ||
++	       sel->get_in_sum_expr() > 0) ?
++              (Item*) new Item_field(Lex->current_context(), NullS, NullS, $1.str) :
++	      (Item*) new Item_ref(Lex->current_context(), NullS, NullS, $1.str);
++	}
++	| simple_ident_q { $$= $1; }
++	;
++
++simple_ident_q:
++	ident '.' ident
++	{
++	  THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++
++          /*
++            FIXME This will work ok in simple_ident_nospvar case because
++            we can't meet simple_ident_nospvar in trigger now. But it
++            should be changed in future.
++          */
++          if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER &&
++              (!my_strcasecmp(system_charset_info, $1.str, "NEW") ||
++               !my_strcasecmp(system_charset_info, $1.str, "OLD")))
++          {
++            Item_trigger_field *trg_fld;
++            bool new_row= ($1.str[0]=='N' || $1.str[0]=='n');
++
++            if (lex->trg_chistics.event == TRG_EVENT_INSERT &&
++                !new_row)
++            {
++              my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT");
++              MYSQL_YYABORT;
++            }
++
++            if (lex->trg_chistics.event == TRG_EVENT_DELETE &&
++                new_row)
++            {
++              my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
++              MYSQL_YYABORT;
++            }
++
++            DBUG_ASSERT(!new_row ||
++                        (lex->trg_chistics.event == TRG_EVENT_INSERT ||
++                         lex->trg_chistics.event == TRG_EVENT_UPDATE));
++            const bool read_only=
++              !(new_row && lex->trg_chistics.action_time == TRG_ACTION_BEFORE);
++            if (!(trg_fld= new Item_trigger_field(Lex->current_context(),
++                                                  new_row ?
++                                                  Item_trigger_field::NEW_ROW:
++                                                  Item_trigger_field::OLD_ROW,
++                                                  $3.str,
++                                                  SELECT_ACL,
++                                                  read_only)))
++              MYSQL_YYABORT;
++
++            /*
++              Let us add this item to list of all Item_trigger_field objects
++              in trigger.
++            */
++            lex->trg_table_fields.link_in_list((byte *)trg_fld,
++              (byte**)&trg_fld->next_trg_field);
++
++            $$= (Item *)trg_fld;
++          }
++          else
++          {
++	    SELECT_LEX *sel= lex->current_select;
++	    if (sel->no_table_names_allowed)
++	    {
++	      my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
++                       MYF(0), $1.str, thd->where);
++	    }
++	    $$= (sel->parsing_place != IN_HAVING ||
++	         sel->get_in_sum_expr() > 0) ?
++	        (Item*) new Item_field(Lex->current_context(), NullS, $1.str, $3.str) :
++	        (Item*) new Item_ref(Lex->current_context(), NullS, $1.str, $3.str);
++          }
++        }
++	| '.' ident '.' ident
++	{
++	  THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++	  SELECT_LEX *sel= lex->current_select;
++	  if (sel->no_table_names_allowed)
++	  {
++	    my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
++                     MYF(0), $2.str, thd->where);
++	  }
++	  $$= (sel->parsing_place != IN_HAVING ||
++	       sel->get_in_sum_expr() > 0) ?
++	      (Item*) new Item_field(Lex->current_context(), NullS, $2.str, $4.str) :
++              (Item*) new Item_ref(Lex->current_context(), NullS, $2.str, $4.str);
++	}
++	| ident '.' ident '.' ident
++	{
++	  THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++	  SELECT_LEX *sel= lex->current_select;
++	  if (sel->no_table_names_allowed)
++	  {
++	    my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
++                     MYF(0), $3.str, thd->where);
++	  }
++	  $$= (sel->parsing_place != IN_HAVING ||
++	       sel->get_in_sum_expr() > 0) ?
++	      (Item*) new Item_field(Lex->current_context(),
++                                     (YYTHD->client_capabilities &
++				      CLIENT_NO_SCHEMA ? NullS : $1.str),
++				     $3.str, $5.str) :
++	      (Item*) new Item_ref(Lex->current_context(),
++                                   (YYTHD->client_capabilities &
++				    CLIENT_NO_SCHEMA ? NullS : $1.str),
++                                   $3.str, $5.str);
++	};
++
++
++field_ident:
++	ident			{ $$=$1;}
++	| ident '.' ident '.' ident
++          {
++            TABLE_LIST *table= (TABLE_LIST*) Select->table_list.first;
++            if (my_strcasecmp(table_alias_charset, $1.str, table->db))
++            {
++              my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
++              MYSQL_YYABORT;
++            }
++            if (my_strcasecmp(table_alias_charset, $3.str,
++                              table->table_name))
++            {
++              my_error(ER_WRONG_TABLE_NAME, MYF(0), $3.str);
++              MYSQL_YYABORT;
++            }
++            $$=$5;
++          }
++	| ident '.' ident
++          {
++            TABLE_LIST *table= (TABLE_LIST*) Select->table_list.first;
++            if (my_strcasecmp(table_alias_charset, $1.str, table->alias))
++            {
++              my_error(ER_WRONG_TABLE_NAME, MYF(0), $1.str);
++              MYSQL_YYABORT;
++            }
++            $$=$3;
++          }
++	| '.' ident		{ $$=$2;}	/* For Delphi */;
++
++table_ident:
++	ident			{ $$=new Table_ident($1); }
++	| ident '.' ident	{ $$=new Table_ident(YYTHD, $1,$3,0);}
++	| '.' ident		{ $$=new Table_ident($2);} /* For Delphi */
++        ;
++
++table_ident_nodb:
++	ident			{ LEX_STRING db={(char*) any_db,3}; $$=new Table_ident(YYTHD, db,$1,0); }
++        ;
++
++IDENT_sys:
++	IDENT { $$= $1; }
++	| IDENT_QUOTED
++	  {
++	    THD *thd= YYTHD;
++	    if (thd->charset_is_system_charset)
++            {
++              CHARSET_INFO *cs= system_charset_info;
++              int dummy_error;
++              uint wlen= cs->cset->well_formed_len(cs, $1.str,
++                                                   $1.str+$1.length,
++                                                   $1.length, &dummy_error);
++              if (wlen < $1.length)
++              {
++                my_error(ER_INVALID_CHARACTER_STRING, MYF(0),
++                         cs->csname, $1.str + wlen);
++                MYSQL_YYABORT;
++              }
++	      $$= $1;
++            }
++	    else
++	      thd->convert_string(&$$, system_charset_info,
++				  $1.str, $1.length, thd->charset());
++	  }
++	;
++
++TEXT_STRING_sys:
++	TEXT_STRING
++	{
++	  THD *thd= YYTHD;
++	  if (thd->charset_is_system_charset)
++	    $$= $1;
++	  else
++	    thd->convert_string(&$$, system_charset_info,
++				$1.str, $1.length, thd->charset());
++	}
++	;
++
++TEXT_STRING_literal:
++	TEXT_STRING
++	{
++	  THD *thd= YYTHD;
++	  if (thd->charset_is_collation_connection)
++	    $$= $1;
++	  else
++	    thd->convert_string(&$$, thd->variables.collation_connection,
++				$1.str, $1.length, thd->charset());
++	}
++	;
++
++
++TEXT_STRING_filesystem:
++	TEXT_STRING
++	{
++	  THD *thd= YYTHD;
++	  if (thd->charset_is_character_set_filesystem)
++	    $$= $1;
++	  else
++	    thd->convert_string(&$$, thd->variables.character_set_filesystem,
++				$1.str, $1.length, thd->charset());
++	}
++	;
++
++ident:
++	IDENT_sys	    { $$=$1; }
++	| keyword
++	{
++	  THD *thd= YYTHD;
++	  $$.str=    thd->strmake($1.str, $1.length);
++	  $$.length= $1.length;
++	}
++	;
++
++label_ident:
++	IDENT_sys	    { $$=$1; }
++	| keyword_sp
++	{
++	  THD *thd= YYTHD;
++	  $$.str=    thd->strmake($1.str, $1.length);
++	  $$.length= $1.length;
++	}
++	;
++
++ident_or_text:
++        ident                   { $$=$1;}
++	| TEXT_STRING_sys	{ $$=$1;}
++	| LEX_HOSTNAME		{ $$=$1;};
++
++user:
++	ident_or_text
++	{
++	  THD *thd= YYTHD;
++	  if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
++	    MYSQL_YYABORT;
++	  $$->user = $1;
++	  $$->host.str= (char *) "%";
++	  $$->host.length= 1;
++
++	  if (check_string_length(&$$->user,
++                                  ER(ER_USERNAME), USERNAME_LENGTH))
++	    MYSQL_YYABORT;
++	}
++	| ident_or_text '@' ident_or_text
++	  {
++	    THD *thd= YYTHD;
++	    if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
++	      MYSQL_YYABORT;
++	    $$->user = $1; $$->host=$3;
++
++	    if (check_string_length(&$$->user,
++                                    ER(ER_USERNAME), USERNAME_LENGTH) ||
++	        check_string_length(&$$->host,
++                                    ER(ER_HOSTNAME), HOSTNAME_LENGTH))
++	      MYSQL_YYABORT;
++	  }
++	| CURRENT_USER optional_braces
++	{
++          if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user))))
++            MYSQL_YYABORT;
++          /* 
++            empty LEX_USER means current_user and 
++            will be handled in the  get_current_user() function
++            later
++          */
++          bzero($$, sizeof(LEX_USER));
++	};
++
++/* Keyword that we allow for identifiers (except SP labels) */
++keyword:
++	keyword_sp		{}
++	| ASCII_SYM		{}
++	| BACKUP_SYM		{}
++	| BEGIN_SYM		{}
++	| BYTE_SYM		{}
++	| CACHE_SYM		{}
++	| CHARSET		{}
++	| CHECKSUM_SYM		{}
++	| CLOSE_SYM		{}
++	| COMMENT_SYM		{}
++	| COMMIT_SYM		{}
++	| CONTAINS_SYM          {}
++        | DEALLOCATE_SYM        {}
++	| DO_SYM		{}
++	| END			{}
++	| EXECUTE_SYM		{}
++	| FLUSH_SYM		{}
++	| HANDLER_SYM		{}
++	| HELP_SYM		{}
++	| LANGUAGE_SYM          {}
++	| NO_SYM		{}
++	| OPEN_SYM		{}
++        | PREPARE_SYM           {}
++	| REPAIR		{}
++	| RESET_SYM		{}
++	| RESTORE_SYM		{}
++	| ROLLBACK_SYM		{}
++	| SAVEPOINT_SYM		{}
++	| SECURITY_SYM		{}
++	| SIGNED_SYM		{}
++	| SLAVE			{}
++	| START_SYM		{}
++	| STOP_SYM		{}
++	| TRUNCATE_SYM		{}
++	| UNICODE_SYM		{}
++        | XA_SYM                {}
++        | UPGRADE_SYM           {}
++	;
++
++/*
++ * Keywords that we allow for labels in SPs.
++ * Anything that's the beginning of a statement or characteristics
++ * must be in keyword above, otherwise we get (harmful) shift/reduce
++ * conflicts.
++ */
++keyword_sp:
++	ACTION			{}
++	| ADDDATE_SYM		{}
++	| AFTER_SYM		{}
++	| AGAINST		{}
++	| AGGREGATE_SYM		{}
++	| ALGORITHM_SYM		{}
++	| ANY_SYM		{}
++	| AUTO_INC		{}
++	| AVG_ROW_LENGTH	{}
++	| AVG_SYM		{}
++	| BERKELEY_DB_SYM	{}
++	| BINLOG_SYM		{}
++	| BIT_SYM		{}
++	| BLOCK_SYM             {}
++	| BOOL_SYM		{}
++	| BOOLEAN_SYM		{}
++	| BTREE_SYM		{}
++	| CASCADED              {}
++	| CHAIN_SYM		{}
++	| CHANGED		{}
++	| CIPHER_SYM		{}
++	| CLIENT_SYM		{}
++        | CODE_SYM              {}
++	| COLLATION_SYM		{}
++        | COLUMNS               {}
++	| COMMITTED_SYM		{}
++	| COMPACT_SYM		{}
++	| COMPRESSED_SYM	{}
++	| CONCURRENT		{}
++	| CONNECTION_SYM	{}
++	| CONSISTENT_SYM	{}
++	| CONTEXT_SYM           {}
++	| CPU_SYM               {}
++	| CUBE_SYM		{}
++	| DATA_SYM		{}
++	| DATETIME		{}
++	| DATE_SYM		{}
++	| DAY_SYM		{}
++	| DEFINER_SYM		{}
++	| DELAY_KEY_WRITE_SYM	{}
++	| DES_KEY_FILE		{}
++	| DIRECTORY_SYM		{}
++	| DISCARD		{}
++	| DUMPFILE		{}
++	| DUPLICATE_SYM		{}
++	| DYNAMIC_SYM		{}
++	| ENUM			{}
++	| ENGINE_SYM		{}
++	| ENGINES_SYM		{}
++	| ERRORS		{}
++	| ESCAPE_SYM		{}
++	| EVENTS_SYM		{}
++        | EXPANSION_SYM         {}
++	| EXTENDED_SYM		{}
++	| FAST_SYM		{}
++	| FAULTS_SYM            {}
++	| FOUND_SYM		{}
++	| DISABLE_SYM		{}
++	| ENABLE_SYM		{}
++	| FULL			{}
++	| FILE_SYM		{}
++	| FIRST_SYM		{}
++	| FIXED_SYM		{}
++	| FRAC_SECOND_SYM	{}
++	| GEOMETRY_SYM		{}
++	| GEOMETRYCOLLECTION	{}
++	| GET_FORMAT		{}
++	| GRANTS		{}
++	| GLOBAL_SYM		{}
++	| HASH_SYM		{}
++	| HOSTS_SYM		{}
++	| HOUR_SYM		{}
++	| IDENTIFIED_SYM	{}
++	| INVOKER_SYM		{}
++	| IMPORT		{}
++	| INDEXES		{}
++	| ISOLATION		{}
++	| ISSUER_SYM		{}
++	| INNOBASE_SYM		{}
++	| INSERT_METHOD		{}
++	| IO_SYM                {}
++	| IPC_SYM               {}
++	| RELAY_THREAD		{}
++	| LAST_SYM		{}
++	| LEAVES                {}
++	| LEVEL_SYM		{}
++	| LINESTRING		{}
++	| LOCAL_SYM		{}
++	| LOCKS_SYM		{}
++	| LOGS_SYM		{}
++	| MAX_ROWS		{}
++	| MASTER_SYM		{}
++	| MASTER_HOST_SYM	{}
++	| MASTER_PORT_SYM	{}
++	| MASTER_LOG_FILE_SYM	{}
++	| MASTER_LOG_POS_SYM	{}
++	| MASTER_USER_SYM	{}
++	| MASTER_PASSWORD_SYM	{}
++	| MASTER_SERVER_ID_SYM  {}
++	| MASTER_CONNECT_RETRY_SYM	{}
++	| MASTER_SSL_SYM	{}
++	| MASTER_SSL_CA_SYM	{}
++	| MASTER_SSL_CAPATH_SYM	{}
++	| MASTER_SSL_CERT_SYM	{}
++	| MASTER_SSL_CIPHER_SYM	{}
++	| MASTER_SSL_KEY_SYM	{}
++	| MAX_CONNECTIONS_PER_HOUR	 {}
++	| MAX_QUERIES_PER_HOUR	{}
++	| MAX_UPDATES_PER_HOUR	{}
++	| MAX_USER_CONNECTIONS_SYM {}
++	| MEDIUM_SYM		{}
++	| MEMORY_SYM            {}
++	| MERGE_SYM		{}
++	| MICROSECOND_SYM	{}
++        | MIGRATE_SYM           {}
++	| MINUTE_SYM		{}
++	| MIN_ROWS		{}
++	| MODIFY_SYM		{}
++	| MODE_SYM		{}
++	| MONTH_SYM		{}
++	| MULTILINESTRING	{}
++	| MULTIPOINT		{}
++	| MULTIPOLYGON		{}
++        | MUTEX_SYM             {}
++	| NAME_SYM              {}
++	| NAMES_SYM		{}
++	| NATIONAL_SYM		{}
++	| NCHAR_SYM		{}
++	| NDBCLUSTER_SYM	{}
++	| NEXT_SYM		{}
++	| NEW_SYM		{}
++	| NONE_SYM		{}
++	| NVARCHAR_SYM		{}
++	| OFFSET_SYM		{}
++	| OLD_PASSWORD		{}
++	| ONE_SHOT_SYM		{}
++        | ONE_SYM               {}
++	| PACK_KEYS_SYM		{}
++	| PAGE_SYM              {}
++	| PARTIAL		{}
++	| PASSWORD		{}
++        | PHASE_SYM             {}
++	| POINT_SYM		{}
++	| POLYGON		{}
++	| PREV_SYM		{}
++        | PRIVILEGES            {}
++	| PROCESS		{}
++	| PROCESSLIST_SYM	{}
++	| PROFILE_SYM           {}
++	| PROFILES_SYM          {}
++	| QUARTER_SYM		{}
++	| QUERY_SYM		{}
++	| QUICK			{}
++	| RAID_0_SYM		{}
++	| RAID_CHUNKS		{}
++	| RAID_CHUNKSIZE	{}
++	| RAID_STRIPED_SYM	{}
++	| RAID_TYPE		{}
++        | RECOVER_SYM           {}
++        | REDUNDANT_SYM         {}
++	| RELAY_LOG_FILE_SYM	{}
++	| RELAY_LOG_POS_SYM	{}
++	| RELOAD		{}
++	| REPEATABLE_SYM	{}
++	| REPLICATION		{}
++	| RESOURCES		{}
++        | RESUME_SYM            {}
++	| RETURNS_SYM           {}
++	| ROLLUP_SYM		{}
++	| ROUTINE_SYM		{}
++	| ROWS_SYM		{}
++	| ROW_FORMAT_SYM	{}
++	| ROW_SYM		{}
++	| RTREE_SYM		{}
++	| SECOND_SYM		{}
++	| SERIAL_SYM		{}
++	| SERIALIZABLE_SYM	{}
++	| SESSION_SYM		{}
++	| SIMPLE_SYM		{}
++	| SHARE_SYM		{}
++	| SHUTDOWN		{}
++	| SNAPSHOT_SYM		{}
++	| SOUNDS_SYM		{}
++	| SOURCE_SYM            {}
++	| SQL_CACHE_SYM		{}
++	| SQL_BUFFER_RESULT	{}
++	| SQL_NO_CACHE_SYM	{}
++	| SQL_THREAD		{}
++	| STATUS_SYM		{}
++	| STORAGE_SYM		{}
++	| STRING_SYM		{}
++	| SUBDATE_SYM		{}
++	| SUBJECT_SYM		{}
++	| SUPER_SYM		{}
++        | SUSPEND_SYM           {}
++        | SWAPS_SYM             {}
++	| SWITCHES_SYM          {}
++        | TABLES                {}
++	| TABLESPACE		{}
++	| TEMPORARY		{}
++	| TEMPTABLE_SYM		{}
++	| TEXT_SYM		{}
++	| TRANSACTION_SYM	{}
++	| TRIGGERS_SYM		{}
++	| TIMESTAMP		{}
++	| TIMESTAMP_ADD		{}
++	| TIMESTAMP_DIFF	{}
++	| TIME_SYM		{}
++	| TYPES_SYM		{}
++        | TYPE_SYM              {}
++        | UDF_RETURNS_SYM       {}
++	| FUNCTION_SYM		{}
++	| UNCOMMITTED_SYM	{}
++	| UNDEFINED_SYM		{}
++	| UNKNOWN_SYM		{}
++	| UNTIL_SYM		{}
++	| USER			{}
++	| USE_FRM		{}
++	| VARIABLES		{}
++	| VIEW_SYM		{}
++	| VALUE_SYM		{}
++	| WARNINGS		{}
++	| WEEK_SYM		{}
++	| WORK_SYM		{}
++	| X509_SYM		{}
++	| YEAR_SYM		{}
++	;
++
++/* Option functions */
++
++set:
++	SET opt_option
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command= SQLCOM_SET_OPTION;
++	  mysql_init_select(lex);
++	  lex->option_type=OPT_SESSION;
++	  lex->var_list.empty();
++          lex->one_shot_set= 0;
++	}
++	option_value_list
++	{}
++	;
++
++opt_option:
++	/* empty */ {}
++	| OPTION {};
++
++option_value_list:
++	option_type_value
++	| option_value_list ',' option_type_value;
++
++option_type_value:
++        {
++          THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++          Lex_input_stream *lip= thd->m_lip;
++
++          if (lex->sphead)
++          {
++            /*
++              If we are in SP we want have own LEX for each assignment.
++              This is mostly because it is hard for several sp_instr_set
++              and sp_instr_set_trigger instructions share one LEX.
++              (Well, it is theoretically possible but adds some extra
++               overhead on preparation for execution stage and IMO less
++               robust).
++
++              QQ: May be we should simply prohibit group assignments in SP?
++            */
++            Lex->sphead->reset_lex(thd);
++            lex= thd->lex;
++
++            /* Set new LEX as if we at start of set rule. */
++	    lex->sql_command= SQLCOM_SET_OPTION;
++	    mysql_init_select(lex);
++	    lex->option_type=OPT_SESSION;
++	    lex->var_list.empty();
++            lex->one_shot_set= 0;
++	    lex->sphead->m_tmp_query= lip->tok_start;
++          }
++        }
++	ext_option_value
++        {
++          THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++          Lex_input_stream *lip= thd->m_lip;
++
++          if (lex->sphead)
++          {
++            sp_head *sp= lex->sphead;
++
++	    if (!lex->var_list.is_empty())
++	    {
++              /*
++                We have assignment to user or system variable or
++                option setting, so we should construct sp_instr_stmt
++                for it.
++              */
++              LEX_STRING qbuff;
++	      sp_instr_stmt *i;
++
++              if (!(i= new sp_instr_stmt(sp->instructions(), lex->spcont,
++                                         lex)))
++                MYSQL_YYABORT;
++
++              /*
++                Extract the query statement from the tokenizer.  The
++                end is either lip->ptr, if there was no lookahead,
++                lip->tok_end otherwise.
++              */
++              if (yychar == YYEMPTY)
++                qbuff.length= lip->ptr - sp->m_tmp_query;
++              else
++                qbuff.length= lip->tok_end - sp->m_tmp_query;
++
++              if (!(qbuff.str= alloc_root(thd->mem_root, qbuff.length + 5)))
++                MYSQL_YYABORT;
++
++              strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query,
++                      qbuff.length);
++              qbuff.length+= 4;
++              i->m_query= qbuff;
++              sp->add_instr(i);
++            }
++            lex->sphead->restore_lex(thd);
++          }
++        };
++
++option_type:
++        option_type2    {}
++	| GLOBAL_SYM	{ $$=OPT_GLOBAL; }
++	| LOCAL_SYM	{ $$=OPT_SESSION; }
++	| SESSION_SYM	{ $$=OPT_SESSION; }
++	;
++
++option_type2:
++	/* empty */	{ $$= OPT_DEFAULT; }
++	| ONE_SHOT_SYM	{ Lex->one_shot_set= 1; $$= OPT_SESSION; }
++	;
++
++opt_var_type:
++	/* empty */	{ $$=OPT_SESSION; }
++	| GLOBAL_SYM	{ $$=OPT_GLOBAL; }
++	| LOCAL_SYM	{ $$=OPT_SESSION; }
++	| SESSION_SYM	{ $$=OPT_SESSION; }
++	;
++
++opt_var_ident_type:
++	/* empty */		{ $$=OPT_DEFAULT; }
++	| GLOBAL_SYM '.'	{ $$=OPT_GLOBAL; }
++	| LOCAL_SYM '.'		{ $$=OPT_SESSION; }
++	| SESSION_SYM '.'	{ $$=OPT_SESSION; }
++	;
++
++ext_option_value:
++        sys_option_value
++        | option_type2 option_value;
++
++sys_option_value:
++        option_type internal_variable_name equal set_expr_or_default
++        {
++          LEX *lex=Lex;
++
++          if ($2.var == &trg_new_row_fake_var)
++          {
++            /* We are in trigger and assigning value to field of new row */
++            Item *it;
++            Item_trigger_field *trg_fld;
++            sp_instr_set_trigger_field *sp_fld;
++	    LINT_INIT(sp_fld);
++            if ($1)
++            {
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++              MYSQL_YYABORT;
++            }
++            if ($4)
++              it= $4;
++            else
++            {
++              /* QQ: Shouldn't this be field's default value ? */
++              it= new Item_null();
++            }
++
++            DBUG_ASSERT(lex->trg_chistics.action_time == TRG_ACTION_BEFORE &&
++                        (lex->trg_chistics.event == TRG_EVENT_INSERT ||
++                         lex->trg_chistics.event == TRG_EVENT_UPDATE));
++            if (!(trg_fld= new Item_trigger_field(Lex->current_context(),
++                                                  Item_trigger_field::NEW_ROW,
++                                                  $2.base_name.str,
++                                                  UPDATE_ACL, FALSE)) ||
++                !(sp_fld= new sp_instr_set_trigger_field(lex->sphead->
++                          	                         instructions(),
++                                	                 lex->spcont,
++							 trg_fld,
++                                        	         it, lex)))
++              MYSQL_YYABORT;
++
++            /*
++              Let us add this item to list of all Item_trigger_field
++              objects in trigger.
++            */
++            lex->trg_table_fields.link_in_list((byte *)trg_fld,
++                                    (byte **)&trg_fld->next_trg_field);
++
++            lex->sphead->add_instr(sp_fld);
++          }
++          else if ($2.var)
++          { /* System variable */
++            if ($1)
++              lex->option_type= $1;
++            lex->var_list.push_back(new set_var(lex->option_type, $2.var,
++                                    &$2.base_name, $4));
++          }
++          else
++          {
++            /* An SP local variable */
++            sp_pcontext *ctx= lex->spcont;
++            sp_variable_t *spv;
++            sp_instr_set *sp_set;
++            Item *it;
++            if ($1)
++            {
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++              MYSQL_YYABORT;
++            }
++
++            spv= ctx->find_variable(&$2.base_name);
++
++            if ($4)
++              it= $4;
++            else if (spv->dflt)
++              it= spv->dflt;
++            else
++              it= new Item_null();
++            sp_set= new sp_instr_set(lex->sphead->instructions(), ctx,
++                                     spv->offset, it, spv->type, lex, TRUE);
++            lex->sphead->add_instr(sp_set);
++          }
++        }
++        | option_type TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types
++	{
++	  LEX *lex=Lex;
++          if ($1)
++            lex->option_type= $1;
++	  lex->var_list.push_back(new set_var(lex->option_type,
++                                              find_sys_var("tx_isolation"),
++                                              &null_lex_str,
++                                              new Item_int((int32) $5)));
++	}
++        ;
++
++option_value:
++	'@' ident_or_text equal expr
++	{
++          Lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4)));
++	}
++	| '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default
++	  {
++	    LEX *lex=Lex;
++	    lex->var_list.push_back(new set_var($3, $4.var, &$4.base_name, $6));
++	  }
++	| charset old_or_new_charset_name_or_default
++	{
++	  THD *thd= YYTHD;
++	  LEX *lex= Lex;
++	  $2= $2 ? $2: global_system_variables.character_set_client;
++	  lex->var_list.push_back(new set_var_collation_client($2,thd->variables.collation_database,$2));
++	}
++        | NAMES_SYM equal expr
++	  {
++	    LEX *lex= Lex;
++            sp_pcontext *spc= lex->spcont;
++	    LEX_STRING names;
++
++	    names.str= (char *)"names";
++	    names.length= 5;
++	    if (spc && spc->find_variable(&names))
++              my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
++            else
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++
++	    MYSQL_YYABORT;
++	  }
++	| NAMES_SYM charset_name_or_default opt_collate
++	{
++	  LEX *lex= Lex;
++	  $2= $2 ? $2 : global_system_variables.character_set_client;
++	  $3= $3 ? $3 : $2;
++	  if (!my_charset_same($2,$3))
++	  {
++	    my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
++                     $3->name, $2->csname);
++	    MYSQL_YYABORT;
++	  }
++	  lex->var_list.push_back(new set_var_collation_client($3,$3,$3));
++	}
++	| PASSWORD equal text_or_password
++	  {
++	    THD *thd=YYTHD;
++	    LEX_USER *user;
++	    LEX *lex= Lex;	    
++            sp_pcontext *spc= lex->spcont;
++	    LEX_STRING pw;
++
++	    pw.str= (char *)"password";
++	    pw.length= 8;
++	    if (spc && spc->find_variable(&pw))
++	    {
++              my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
++	      MYSQL_YYABORT;
++	    }
++	    if (!(user=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
++	      MYSQL_YYABORT;
++	    user->host=null_lex_str;
++	    user->user.str=thd->security_ctx->priv_user;
++	    thd->lex->var_list.push_back(new set_var_password(user, $3));
++	  }
++	| PASSWORD FOR_SYM user equal text_or_password
++	  {
++	    Lex->var_list.push_back(new set_var_password($3,$5));
++	  }
++	;
++
++internal_variable_name:
++	ident
++	{
++	  LEX *lex= Lex;
++          sp_pcontext *spc= lex->spcont;
++	  sp_variable_t *spv;
++
++	  /* We have to lookup here since local vars can shadow sysvars */
++	  if (!spc || !(spv = spc->find_variable(&$1)))
++	  {
++            /* Not an SP local variable */
++	    sys_var *tmp=find_sys_var($1.str, $1.length);
++	    if (!tmp)
++	      MYSQL_YYABORT;
++	    $$.var= tmp;
++	    $$.base_name= null_lex_str;
++            /*
++              If this is time_zone variable we should open time zone
++              describing tables 
++            */
++            if (tmp == &sys_time_zone &&
++                lex->add_time_zone_tables_to_query_tables(YYTHD))
++              MYSQL_YYABORT;
++            else if (spc && tmp == &sys_autocommit)
++            {
++              /*
++                We don't allow setting AUTOCOMMIT from a stored function
++		or trigger.
++              */
++              lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT;
++            }
++	  }
++	  else
++	  {
++            /* An SP local variable */
++	    $$.var= NULL;
++	    $$.base_name= $1;
++	  }
++	}
++	| ident '.' ident
++	  {
++            LEX *lex= Lex;
++            if (check_reserved_words(&$1))
++            {
++              my_parse_error(ER(ER_SYNTAX_ERROR));
++              MYSQL_YYABORT;
++            }
++            if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER &&
++                (!my_strcasecmp(system_charset_info, $1.str, "NEW") || 
++                 !my_strcasecmp(system_charset_info, $1.str, "OLD")))
++            {
++              if ($1.str[0]=='O' || $1.str[0]=='o')
++              {
++                my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", "");
++                MYSQL_YYABORT;
++              }
++              if (lex->trg_chistics.event == TRG_EVENT_DELETE)
++              {
++                my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0),
++                         "NEW", "on DELETE");
++                MYSQL_YYABORT;
++              }
++              if (lex->trg_chistics.action_time == TRG_ACTION_AFTER)
++              {
++                my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after ");
++                MYSQL_YYABORT;
++              }
++              /* This special combination will denote field of NEW row */
++              $$.var= &trg_new_row_fake_var;
++              $$.base_name= $3;
++            }
++            else
++            {
++              sys_var *tmp=find_sys_var($3.str, $3.length);
++              if (!tmp)
++                MYSQL_YYABORT;
++              if (!tmp->is_struct())
++                my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), $3.str);
++              $$.var= tmp;
++              $$.base_name= $1;
++            }
++	  }
++	| DEFAULT '.' ident
++	  {
++	    sys_var *tmp=find_sys_var($3.str, $3.length);
++	    if (!tmp)
++	      MYSQL_YYABORT;
++	    if (!tmp->is_struct())
++	      my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), $3.str);
++	    $$.var= tmp;
++	    $$.base_name.str=    (char*) "default";
++	    $$.base_name.length= 7;
++	  }
++        ;
++
++isolation_types:
++	READ_SYM UNCOMMITTED_SYM	{ $$= ISO_READ_UNCOMMITTED; }
++	| READ_SYM COMMITTED_SYM	{ $$= ISO_READ_COMMITTED; }
++	| REPEATABLE_SYM READ_SYM	{ $$= ISO_REPEATABLE_READ; }
++	| SERIALIZABLE_SYM		{ $$= ISO_SERIALIZABLE; }
++	;
++
++text_or_password:
++	TEXT_STRING { $$=$1.str;}
++	| PASSWORD '(' TEXT_STRING ')'
++	  {
++	    $$= $3.length ? YYTHD->variables.old_passwords ?
++	        Item_func_old_password::alloc(YYTHD, $3.str) :
++	        Item_func_password::alloc(YYTHD, $3.str) :
++	      $3.str;
++	  }
++	| OLD_PASSWORD '(' TEXT_STRING ')'
++	  {
++	    $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str) :
++	      $3.str;
++	  }
++          ;
++
++
++set_expr_or_default:
++	expr      { $$=$1; }
++	| DEFAULT { $$=0; }
++	| ON	  { $$=new Item_string("ON",  2, system_charset_info); }
++	| ALL	  { $$=new Item_string("ALL", 3, system_charset_info); }
++	| BINARY  { $$=new Item_string("binary", 6, system_charset_info); }
++	;
++
++
++/* Lock function */
++
++lock:
++	LOCK_SYM table_or_tables
++	{
++	  LEX *lex= Lex;
++
++	  if (lex->sphead)
++	  {
++	    my_error(ER_SP_BADSTATEMENT, MYF(0), "LOCK");
++	    MYSQL_YYABORT;
++	  }
++	  lex->sql_command= SQLCOM_LOCK_TABLES;
++	}
++	table_lock_list
++	{}
++	;
++
++table_or_tables:
++	TABLE_SYM
++	| TABLES;
++
++table_lock_list:
++	table_lock
++	| table_lock_list ',' table_lock;
++
++table_lock:
++	table_ident opt_table_alias lock_option
++	{
++	  if (!Select->add_table_to_list(YYTHD, $1, $2, 0, (thr_lock_type) $3))
++	   MYSQL_YYABORT;
++	}
++        ;
++
++lock_option:
++	READ_SYM	{ $$=TL_READ_NO_INSERT; }
++	| WRITE_SYM     { $$=TL_WRITE_DEFAULT; }
++	| LOW_PRIORITY WRITE_SYM { $$=TL_WRITE_LOW_PRIORITY; }
++	| READ_SYM LOCAL_SYM { $$= TL_READ; }
++        ;
++
++unlock:
++	UNLOCK_SYM
++	{
++	  LEX *lex= Lex;
++
++	  if (lex->sphead)
++	  {
++	    my_error(ER_SP_BADSTATEMENT, MYF(0), "UNLOCK");
++	    MYSQL_YYABORT;
++	  }
++	  lex->sql_command= SQLCOM_UNLOCK_TABLES;
++	}
++	table_or_tables
++	{}
++        ;
++
++
++/*
++** Handler: direct access to ISAM functions
++*/
++
++handler:
++	HANDLER_SYM table_ident OPEN_SYM opt_table_alias
++	{
++	  LEX *lex= Lex;
++	  if (lex->sphead)
++	  {
++	    my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
++	    MYSQL_YYABORT;
++	  }
++	  lex->sql_command = SQLCOM_HA_OPEN;
++	  if (!lex->current_select->add_table_to_list(lex->thd, $2, $4, 0))
++	    MYSQL_YYABORT;
++	}
++	| HANDLER_SYM table_ident_nodb CLOSE_SYM
++	{
++	  LEX *lex= Lex;
++	  if (lex->sphead)
++	  {
++	    my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
++	    MYSQL_YYABORT;
++	  }
++	  lex->sql_command = SQLCOM_HA_CLOSE;
++	  if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
++	    MYSQL_YYABORT;
++	}
++	| HANDLER_SYM table_ident_nodb READ_SYM
++	{
++	  LEX *lex=Lex;
++	  if (lex->sphead)
++	  {
++	    my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
++	    MYSQL_YYABORT;
++	  }
++	  lex->sql_command = SQLCOM_HA_READ;
++	  lex->ha_rkey_mode= HA_READ_KEY_EXACT;	/* Avoid purify warnings */
++	  lex->current_select->select_limit= new Item_int((int32) 1);
++	  lex->current_select->offset_limit= 0;
++	  if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
++	    MYSQL_YYABORT;
++        }
++        handler_read_or_scan where_clause opt_limit_clause {}
++        ;
++
++handler_read_or_scan:
++	handler_scan_function         { Lex->ident= null_lex_str; }
++        | ident handler_rkey_function { Lex->ident= $1; }
++        ;
++
++handler_scan_function:
++	FIRST_SYM  { Lex->ha_read_mode = RFIRST; }
++	| NEXT_SYM { Lex->ha_read_mode = RNEXT;  }
++        ;
++
++handler_rkey_function:
++	FIRST_SYM  { Lex->ha_read_mode = RFIRST; }
++	| NEXT_SYM { Lex->ha_read_mode = RNEXT;  }
++	| PREV_SYM { Lex->ha_read_mode = RPREV;  }
++	| LAST_SYM { Lex->ha_read_mode = RLAST;  }
++	| handler_rkey_mode
++	{
++	  LEX *lex=Lex;
++	  lex->ha_read_mode = RKEY;
++	  lex->ha_rkey_mode=$1;
++	  if (!(lex->insert_list = new List_item))
++	    MYSQL_YYABORT;
++	} '(' values ')' { }
++        ;
++
++handler_rkey_mode:
++	  EQ     { $$=HA_READ_KEY_EXACT;   }
++	| GE     { $$=HA_READ_KEY_OR_NEXT; }
++	| LE     { $$=HA_READ_KEY_OR_PREV; }
++	| GT_SYM { $$=HA_READ_AFTER_KEY;   }
++	| LT     { $$=HA_READ_BEFORE_KEY;  }
++        ;
++
++/* GRANT / REVOKE */
++
++revoke:
++	REVOKE clear_privileges revoke_command
++	{}
++        ;
++
++revoke_command:
++	grant_privileges ON opt_table grant_ident FROM grant_list
++	{
++          LEX *lex= Lex;
++	  lex->sql_command= SQLCOM_REVOKE;
++          lex->type= 0;
++        }
++        |
++        grant_privileges ON FUNCTION_SYM grant_ident FROM grant_list
++        {
++          LEX *lex= Lex;
++          if (lex->columns.elements)
++          {
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++          }
++	  lex->sql_command= SQLCOM_REVOKE;
++          lex->type= TYPE_ENUM_FUNCTION;
++          
++        }
++	|
++        grant_privileges ON PROCEDURE grant_ident FROM grant_list
++        {
++          LEX *lex= Lex;
++          if (lex->columns.elements)
++          {
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++          }
++	  lex->sql_command= SQLCOM_REVOKE;
++          lex->type= TYPE_ENUM_PROCEDURE;
++        }
++	|
++	ALL opt_privileges ',' GRANT OPTION FROM grant_list
++	{
++	  Lex->sql_command = SQLCOM_REVOKE_ALL;
++	}
++	;
++
++grant:
++	GRANT clear_privileges grant_command
++	{}
++        ;
++
++grant_command:
++	grant_privileges ON opt_table grant_ident TO_SYM grant_list
++	require_clause grant_options
++	{
++          LEX *lex= Lex;
++          lex->sql_command= SQLCOM_GRANT;
++          lex->type= 0;
++        }
++        |
++	grant_privileges ON FUNCTION_SYM grant_ident TO_SYM grant_list
++	require_clause grant_options
++	{
++          LEX *lex= Lex;
++          if (lex->columns.elements)
++          {
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++          }
++          lex->sql_command= SQLCOM_GRANT;
++          lex->type= TYPE_ENUM_FUNCTION;
++        }
++        |
++	grant_privileges ON PROCEDURE grant_ident TO_SYM grant_list
++	require_clause grant_options
++	{
++          LEX *lex= Lex;
++          if (lex->columns.elements)
++          {
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++          }
++          lex->sql_command= SQLCOM_GRANT;
++          lex->type= TYPE_ENUM_PROCEDURE;
++        }
++        ;
++
++opt_table:
++	/* Empty */
++	| TABLE_SYM ;
++        
++grant_privileges:
++	object_privilege_list { }
++	| ALL opt_privileges
++        { 
++          Lex->all_privileges= 1; 
++          Lex->grant= GLOBAL_ACLS;
++        }
++        ;
++
++opt_privileges:
++	/* empty */
++	| PRIVILEGES
++	;
++
++object_privilege_list:
++	object_privilege
++	| object_privilege_list ',' object_privilege;
++
++object_privilege:
++	SELECT_SYM	{ Lex->which_columns = SELECT_ACL;} opt_column_list {}
++	| INSERT	{ Lex->which_columns = INSERT_ACL;} opt_column_list {}
++	| UPDATE_SYM	{ Lex->which_columns = UPDATE_ACL; } opt_column_list {}
++	| REFERENCES	{ Lex->which_columns = REFERENCES_ACL;} opt_column_list {}
++	| DELETE_SYM	{ Lex->grant |= DELETE_ACL;}
++	| USAGE		{}
++	| INDEX_SYM	{ Lex->grant |= INDEX_ACL;}
++	| ALTER		{ Lex->grant |= ALTER_ACL;}
++	| CREATE	{ Lex->grant |= CREATE_ACL;}
++	| DROP		{ Lex->grant |= DROP_ACL;}
++	| EXECUTE_SYM	{ Lex->grant |= EXECUTE_ACL;}
++	| RELOAD	{ Lex->grant |= RELOAD_ACL;}
++	| SHUTDOWN	{ Lex->grant |= SHUTDOWN_ACL;}
++	| PROCESS	{ Lex->grant |= PROCESS_ACL;}
++	| FILE_SYM	{ Lex->grant |= FILE_ACL;}
++	| GRANT OPTION  { Lex->grant |= GRANT_ACL;}
++	| SHOW DATABASES { Lex->grant |= SHOW_DB_ACL;}
++	| SUPER_SYM	{ Lex->grant |= SUPER_ACL;}
++	| CREATE TEMPORARY TABLES { Lex->grant |= CREATE_TMP_ACL;}
++	| LOCK_SYM TABLES   { Lex->grant |= LOCK_TABLES_ACL; }
++	| REPLICATION SLAVE  { Lex->grant |= REPL_SLAVE_ACL; }
++	| REPLICATION CLIENT_SYM { Lex->grant |= REPL_CLIENT_ACL; }
++	| CREATE VIEW_SYM { Lex->grant |= CREATE_VIEW_ACL; }
++	| SHOW VIEW_SYM { Lex->grant |= SHOW_VIEW_ACL; }
++	| CREATE ROUTINE_SYM { Lex->grant |= CREATE_PROC_ACL; }
++	| ALTER ROUTINE_SYM { Lex->grant |= ALTER_PROC_ACL; }
++	| CREATE USER { Lex->grant |= CREATE_USER_ACL; }
++	;
++
++
++opt_and:
++	/* empty */	{}
++	| AND_SYM	{}
++	;
++
++require_list:
++	 require_list_element opt_and require_list
++	 | require_list_element
++	 ;
++
++require_list_element:
++	SUBJECT_SYM TEXT_STRING
++	{
++	  LEX *lex=Lex;
++	  if (lex->x509_subject)
++	  {
++	    my_error(ER_DUP_ARGUMENT, MYF(0), "SUBJECT");
++	    MYSQL_YYABORT;
++	  }
++	  lex->x509_subject=$2.str;
++	}
++	| ISSUER_SYM TEXT_STRING
++	{
++	  LEX *lex=Lex;
++	  if (lex->x509_issuer)
++	  {
++	    my_error(ER_DUP_ARGUMENT, MYF(0), "ISSUER");
++	    MYSQL_YYABORT;
++	  }
++	  lex->x509_issuer=$2.str;
++	}
++	| CIPHER_SYM TEXT_STRING
++	{
++	  LEX *lex=Lex;
++	  if (lex->ssl_cipher)
++	  {
++	    my_error(ER_DUP_ARGUMENT, MYF(0), "CIPHER");
++	    MYSQL_YYABORT;
++	  }
++	  lex->ssl_cipher=$2.str;
++	}
++	;
++
++grant_ident:
++	'*'
++	  {
++	    LEX *lex= Lex;
++            if (lex->copy_db_to(&lex->current_select->db, NULL))
++              MYSQL_YYABORT;
++	    if (lex->grant == GLOBAL_ACLS)
++	      lex->grant = DB_ACLS & ~GRANT_ACL;
++	    else if (lex->columns.elements)
++	    {
++	      my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
++                         ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
++	      MYSQL_YYABORT;
++	    }
++	  }
++	| ident '.' '*'
++	  {
++	    LEX *lex= Lex;
++	    lex->current_select->db = $1.str;
++	    if (lex->grant == GLOBAL_ACLS)
++	      lex->grant = DB_ACLS & ~GRANT_ACL;
++	    else if (lex->columns.elements)
++	    {
++	      my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
++                         ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
++	      MYSQL_YYABORT;
++	    }
++	  }
++	| '*' '.' '*'
++	  {
++	    LEX *lex= Lex;
++	    lex->current_select->db = NULL;
++	    if (lex->grant == GLOBAL_ACLS)
++	      lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
++	    else if (lex->columns.elements)
++	    {
++	      my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
++                         ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
++	      MYSQL_YYABORT;
++	    }
++	  }
++	| table_ident
++	  {
++	    LEX *lex=Lex;
++	    if (!lex->current_select->add_table_to_list(lex->thd, $1,NULL,
++                                                        TL_OPTION_UPDATING))
++	      MYSQL_YYABORT;
++	    if (lex->grant == GLOBAL_ACLS)
++	      lex->grant =  TABLE_ACLS & ~GRANT_ACL;
++	  }
++          ;
++
++
++user_list:
++	user  { if (Lex->users_list.push_back($1)) MYSQL_YYABORT;}
++	| user_list ',' user
++	  {
++	    if (Lex->users_list.push_back($3))
++	      MYSQL_YYABORT;
++	  }
++	;
++
++
++grant_list:
++	grant_user  { if (Lex->users_list.push_back($1)) MYSQL_YYABORT;}
++	| grant_list ',' grant_user
++	  {
++	    if (Lex->users_list.push_back($3))
++	      MYSQL_YYABORT;
++	  }
++	;
++
++
++grant_user:
++	user IDENTIFIED_SYM BY TEXT_STRING
++	{
++	   $$=$1; $1->password=$4;
++	   if ($4.length)
++	   {
++             if (YYTHD->variables.old_passwords)
++             {
++               char *buff= 
++                 (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
++               if (buff)
++                 make_scrambled_password_323(buff, $4.str);
++               $1->password.str= buff;
++               $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
++             }
++             else
++             {
++               char *buff= 
++                 (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
++               if (buff)
++                 make_scrambled_password(buff, $4.str);
++               $1->password.str= buff;
++               $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
++             }
++	  }
++	}
++	| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
++	  { $$= $1; $1->password= $5; }
++	| user
++	  { $$= $1; $1->password= null_lex_str; }
++        ;
++
++
++opt_column_list:
++	/* empty */
++	{
++	  LEX *lex=Lex;
++	  lex->grant |= lex->which_columns;
++	}
++	| '(' column_list ')';
++
++column_list:
++	column_list ',' column_list_id
++	| column_list_id;
++
++column_list_id:
++	ident
++	{
++	  String *new_str = new (YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
++	  List_iterator <LEX_COLUMN> iter(Lex->columns);
++	  class LEX_COLUMN *point;
++	  LEX *lex=Lex;
++	  while ((point=iter++))
++	  {
++	    if (!my_strcasecmp(system_charset_info,
++                               point->column.ptr(), new_str->ptr()))
++		break;
++	  }
++	  lex->grant_tot_col|= lex->which_columns;
++	  if (point)
++	    point->rights |= lex->which_columns;
++	  else
++	    lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns));
++	}
++        ;
++
++
++require_clause: /* empty */
++        | REQUIRE_SYM require_list
++          {
++            Lex->ssl_type=SSL_TYPE_SPECIFIED;
++          }
++        | REQUIRE_SYM SSL_SYM
++          {
++            Lex->ssl_type=SSL_TYPE_ANY;
++          }
++        | REQUIRE_SYM X509_SYM
++          {
++            Lex->ssl_type=SSL_TYPE_X509;
++          }
++	| REQUIRE_SYM NONE_SYM
++	  {
++	    Lex->ssl_type=SSL_TYPE_NONE;
++	  }
++          ;
++
++grant_options:
++	/* empty */ {}
++	| WITH grant_option_list;
++
++grant_option_list:
++	grant_option_list grant_option {}
++	| grant_option {}
++        ;
++
++grant_option:
++	GRANT OPTION { Lex->grant |= GRANT_ACL;}
++        | MAX_QUERIES_PER_HOUR ulong_num
++        {
++	  LEX *lex=Lex;
++	  lex->mqh.questions=$2;
++	  lex->mqh.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR;
++	}
++        | MAX_UPDATES_PER_HOUR ulong_num
++        {
++	  LEX *lex=Lex;
++	  lex->mqh.updates=$2;
++	  lex->mqh.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR;
++	}
++        | MAX_CONNECTIONS_PER_HOUR ulong_num
++        {
++	  LEX *lex=Lex;
++	  lex->mqh.conn_per_hour= $2;
++	  lex->mqh.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR;
++	}
++        | MAX_USER_CONNECTIONS_SYM ulong_num
++        {
++	  LEX *lex=Lex;
++          lex->mqh.user_conn= $2;
++          lex->mqh.specified_limits|= USER_RESOURCES::USER_CONNECTIONS;
++	}
++        ;
++
++begin:
++	BEGIN_SYM  
++        {
++	  LEX *lex=Lex;
++          lex->sql_command = SQLCOM_BEGIN;
++          lex->start_transaction_opt= 0;
++        }
++        opt_work {}
++	;
++
++opt_work:
++	/* empty */ {}
++	| WORK_SYM  {}
++        ;
++
++opt_chain:
++	/* empty */ { $$= (YYTHD->variables.completion_type == 1); }
++	| AND_SYM NO_SYM CHAIN_SYM	{ $$=0; }
++	| AND_SYM CHAIN_SYM		{ $$=1; }
++	;
++
++opt_release:
++	/* empty */ { $$= (YYTHD->variables.completion_type == 2); }
++	| RELEASE_SYM 			{ $$=1; }
++	| NO_SYM RELEASE_SYM 		{ $$=0; }
++	;
++	
++opt_savepoint:
++	/* empty */	{}
++	| SAVEPOINT_SYM {}
++	;
++
++commit:
++	COMMIT_SYM opt_work opt_chain opt_release
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command= SQLCOM_COMMIT;
++	  lex->tx_chain= $3; 
++	  lex->tx_release= $4;
++	}
++	;
++
++rollback:
++	ROLLBACK_SYM opt_work opt_chain opt_release
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command= SQLCOM_ROLLBACK;
++	  lex->tx_chain= $3; 
++	  lex->tx_release= $4;
++	}
++	| ROLLBACK_SYM opt_work
++	  TO_SYM opt_savepoint ident
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command= SQLCOM_ROLLBACK_TO_SAVEPOINT;
++	  lex->ident= $5;
++	}
++	;
++
++savepoint:
++	SAVEPOINT_SYM ident
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command= SQLCOM_SAVEPOINT;
++	  lex->ident= $2;
++	}
++	;
++
++release:
++	RELEASE_SYM SAVEPOINT_SYM ident
++	{
++	  LEX *lex=Lex;
++	  lex->sql_command= SQLCOM_RELEASE_SAVEPOINT;
++	  lex->ident= $3;
++	}
++	;
++  
++/*
++   UNIONS : glue selects together
++*/
++
++
++union_clause:
++	/* empty */ {}
++	| union_list
++	;
++
++union_list:
++	UNION_SYM union_option
++	{
++	  LEX *lex=Lex;
++	  if (lex->result)
++	  {
++	    /* Only the last SELECT can have  INTO...... */
++	    my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
++	    MYSQL_YYABORT;
++	  }
++	  if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
++	  {
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++	  }
++          /* This counter shouldn't be incremented for UNION parts */
++          Lex->nest_level--;
++	  if (mysql_new_select(lex, 0))
++	    MYSQL_YYABORT;
++          mysql_init_select(lex);
++	  lex->current_select->linkage=UNION_TYPE;
++          if ($2) /* UNION DISTINCT - remember position */
++            lex->current_select->master_unit()->union_distinct=
++                                                      lex->current_select;
++	}
++	select_init
++        {
++          /*
++	    Remove from the name resolution context stack the context of the
++            last select in the union.
++	  */
++          Lex->pop_context();
++        }
++	;
++
++union_opt:
++	/* Empty */ { $$= 0; }
++	| union_list { $$= 1; }
++	| union_order_or_limit { $$= 1; }
++	;
++
++union_order_or_limit:
++	  {
++	    THD *thd= YYTHD;
++	    LEX *lex= thd->lex;
++	    DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE);
++	    SELECT_LEX *sel= lex->current_select;
++	    SELECT_LEX_UNIT *unit= sel->master_unit();
++	    SELECT_LEX *fake= unit->fake_select_lex;
++	    if (fake)
++	    {
++	      unit->global_parameters= fake;
++	      fake->no_table_names_allowed= 1;
++	      lex->current_select= fake;
++	    }
++	    thd->where= "global ORDER clause";
++	  }
++	order_or_limit
++          {
++	    THD *thd= YYTHD;
++	    thd->lex->current_select->no_table_names_allowed= 0;
++	    thd->where= "";
++          }
++	;
++
++order_or_limit:
++	order_clause opt_limit_clause_init
++	| limit_clause
++	;
++
++union_option:
++	/* empty */ { $$=1; }
++	| DISTINCT  { $$=1; }
++	| ALL       { $$=0; }
++        ;
++
++subselect:
++        SELECT_SYM subselect_start subselect_init subselect_end
++        {
++          $$= $3;
++        }
++        | '(' subselect_start subselect ')'
++          {
++	    THD *thd= YYTHD;
++            /*
++              note that a local variable can't be used for
++              $3 as it's used in local variable construction
++              and some compilers can't guarnatee the order
++              in which the local variables are initialized.
++            */
++            List_iterator<Item> it($3->item_list);
++            Item *item;
++            /*
++              we must fill the items list for the "derived table".
++            */
++            while ((item= it++))
++              add_item_to_list(thd, item);
++          }
++          union_clause subselect_end { $$= $3; };
++
++subselect_init:
++  select_init2
++  {
++    $$= Lex->current_select->master_unit()->first_select();
++  };
++
++subselect_start:
++	{
++	  LEX *lex=Lex;
++          if (lex->sql_command == (int)SQLCOM_HA_READ ||
++              lex->sql_command == (int)SQLCOM_KILL ||
++              lex->sql_command == (int)SQLCOM_PURGE)
++	  {
++            my_parse_error(ER(ER_SYNTAX_ERROR));
++	    MYSQL_YYABORT;
++	  }
++          /* 
++            we are making a "derived table" for the parenthesis
++            as we need to have a lex level to fit the union 
++            after the parenthesis, e.g. 
++            (SELECT .. ) UNION ...  becomes 
++            SELECT * FROM ((SELECT ...) UNION ...)
++          */
++	  if (mysql_new_select(Lex, 1))
++	    MYSQL_YYABORT;
++	};
++
++subselect_end:
++	{
++	  LEX *lex=Lex;
++          lex->pop_context();
++          SELECT_LEX *child= lex->current_select;
++	  lex->current_select = lex->current_select->return_after_parsing();
++          lex->nest_level--;
++          lex->current_select->n_child_sum_items += child->n_sum_items;
++          /*
++            A subselect can add fields to an outer select. Reserve space for
++            them.
++          */
++          lex->current_select->select_n_where_fields+=
++            child->select_n_where_fields;
++	};
++
++/**************************************************************************
++
++ CREATE VIEW | TRIGGER | PROCEDURE statements.
++
++**************************************************************************/
++
++view_or_trigger_or_sp:
++	definer view_or_trigger_or_sp_tail
++	{}
++	| view_replace_or_algorithm definer view_tail
++	{}
++	;
++
++view_or_trigger_or_sp_tail:
++	view_tail
++	{}
++	| trigger_tail
++	{}
++	| sp_tail
++	{}
++	;
++
++/**************************************************************************
++
++ DEFINER clause support.
++
++**************************************************************************/
++
++definer:
++	/* empty */
++	{
++          /*
++            We have to distinguish missing DEFINER-clause from case when
++            CURRENT_USER specified as definer explicitly in order to properly
++            handle CREATE TRIGGER statements which come to replication thread
++            from older master servers (i.e. to create non-suid trigger in this
++            case).
++           */
++          YYTHD->lex->definer= 0;
++	}
++	| DEFINER_SYM EQ user
++	{
++	  YYTHD->lex->definer= get_current_user(YYTHD, $3);
++	}
++	;
++
++/**************************************************************************
++
++ CREATE VIEW statement parts.
++
++**************************************************************************/
++
++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_suid:
++	/* empty */
++	{ Lex->create_view_suid= VIEW_SUID_DEFAULT; }
++	| SQL_SYM SECURITY_SYM DEFINER_SYM
++	{ Lex->create_view_suid= VIEW_SUID_DEFINER; }
++	| SQL_SYM SECURITY_SYM INVOKER_SYM
++	{ Lex->create_view_suid= VIEW_SUID_INVOKER; }
++	;
++
++view_tail:
++	view_suid VIEW_SYM table_ident
++	{
++	  THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++	  lex->sql_command= SQLCOM_CREATE_VIEW;
++	  /* first table in list is target VIEW name */
++	  if (!lex->select_lex.add_table_to_list(thd, $3, NULL, TL_OPTION_UPDATING))
++	    MYSQL_YYABORT;
++	}
++	view_list_opt AS view_select view_check_option
++	{}
++	;
++
++view_list_opt:
++	/* empty */
++	{}
++	| '(' view_list ')'
++	;
++
++view_list:
++	ident 
++	  {
++	    Lex->view_list.push_back((LEX_STRING*)
++				     sql_memdup(&$1, sizeof(LEX_STRING)));
++	  }
++	| view_list ',' ident
++	  {
++	    Lex->view_list.push_back((LEX_STRING*)
++				     sql_memdup(&$3, sizeof(LEX_STRING)));
++	  }
++	;
++
++view_select:
++        {
++          LEX *lex= Lex;
++          lex->parsing_options.allows_variable= FALSE;
++          lex->parsing_options.allows_select_into= FALSE;
++          lex->parsing_options.allows_select_procedure= FALSE;
++          lex->parsing_options.allows_derived= FALSE;
++        }        
++        view_select_aux
++        {
++          LEX *lex= Lex;
++          lex->parsing_options.allows_variable= TRUE;
++          lex->parsing_options.allows_select_into= TRUE;
++          lex->parsing_options.allows_select_procedure= TRUE;
++          lex->parsing_options.allows_derived= TRUE;
++        }
++        ;
++
++view_select_aux:
++	SELECT_SYM remember_name select_init2
++	{
++          THD *thd=YYTHD;
++          LEX *lex= thd->lex;
++          char *stmt_beg= (lex->sphead ?
++                           (char *)lex->sphead->m_tmp_query :
++                           thd->query);
++	  lex->create_view_select_start= $2 - stmt_beg;
++	}
++	| '(' remember_name select_paren ')' union_opt
++	{
++          THD *thd=YYTHD;
++          LEX *lex= thd->lex;
++          char *stmt_beg= (lex->sphead ?
++                           (char *)lex->sphead->m_tmp_query :
++                           thd->query);
++	  lex->create_view_select_start= $2 - stmt_beg;
++	}
++	;
++
++view_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; }
++	;
++
++/**************************************************************************
++
++ CREATE TRIGGER statement parts.
++
++**************************************************************************/
++
++trigger_tail:
++	TRIGGER_SYM remember_name sp_name trg_action_time trg_event
++	ON remember_name table_ident FOR_SYM remember_name EACH_SYM ROW_SYM
++	{
++          THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++          Lex_input_stream *lip= thd->m_lip;
++	  sp_head *sp;
++	 
++	  if (lex->sphead)
++	  {
++	    my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
++	    MYSQL_YYABORT;
++	  }
++	
++	  if (!(sp= new sp_head()))
++	    MYSQL_YYABORT;
++	  sp->reset_thd_mem_root(thd);
++	  sp->init(lex);
++	  sp->m_type= TYPE_ENUM_TRIGGER;
++          sp->init_sp_name(thd, $3);
++	
++	  lex->stmt_definition_begin= $2;
++          lex->ident.str= $7;
++          lex->ident.length= $10 - $7;
++
++	  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= thd->client_capabilities & CLIENT_MULTI_QUERIES;
++	  thd->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= lip->ptr;
++          while (my_isspace(system_charset_info, lex->sphead->m_body_begin[0]))
++            ++lex->sphead->m_body_begin;
++	}
++	sp_proc_stmt
++	{
++	  LEX *lex= Lex;
++	  sp_head *sp= lex->sphead;
++	  
++	  lex->sql_command= SQLCOM_CREATE_TRIGGER;
++	  sp->init_strings(YYTHD, lex);
++	  /* 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"))
++	      MYSQL_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.
++	  */
++	  if (!lex->select_lex.add_table_to_list(YYTHD, $8,
++	                                         (LEX_STRING*) 0,
++	                                         TL_OPTION_UPDATING,
++                                                 TL_IGNORE))
++	    MYSQL_YYABORT;
++	}
++	;
++
++/**************************************************************************
++
++ CREATE FUNCTION | PROCEDURE statements parts.
++
++**************************************************************************/
++
++sp_tail:
++	udf_func_type remember_name FUNCTION_SYM sp_name
++	{
++	  LEX *lex=Lex;
++	  lex->udf.type= $1;
++	  lex->stmt_definition_begin= $2;
++	  lex->spname= $4;
++	}
++	create_function_tail
++	{}
++	| PROCEDURE remember_name sp_name
++	{
++	  LEX *lex= Lex;
++	  sp_head *sp;
++
++	  if (lex->sphead)
++	  {
++	    my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
++	    MYSQL_YYABORT;
++	  }
++
++	  lex->stmt_definition_begin= $2;
++
++	  /* Order is important here: new - reset - init */
++	  sp= new sp_head();
++	  sp->reset_thd_mem_root(YYTHD);
++	  sp->init(lex);
++	  sp->m_type= TYPE_ENUM_PROCEDURE;
++          sp->init_sp_name(YYTHD, $3);
++
++	  lex->sphead= sp;
++	  /*
++	   * 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);
++	}
++        '('
++	{
++          THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++          Lex_input_stream *lip= thd->m_lip;
++
++	  lex->sphead->m_param_begin= lip->tok_start+1;
++	}
++	sp_pdparam_list
++	')'
++	{
++          THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++          Lex_input_stream *lip= thd->m_lip;
++
++	  lex->sphead->m_param_end= lip->tok_start;
++	  bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
++	}
++	sp_c_chistics
++	{
++          THD *thd= YYTHD;
++	  LEX *lex= thd->lex;
++          Lex_input_stream *lip= thd->m_lip;
++
++	  lex->sphead->m_chistics= &lex->sp_chistics;
++	  lex->sphead->m_body_begin= lip->tok_start;
++	}
++	sp_proc_stmt
++	{
++	  LEX *lex= Lex;
++	  sp_head *sp= lex->sphead;
++
++	  sp->init_strings(YYTHD, lex);
++	  lex->sql_command= SQLCOM_CREATE_PROCEDURE;
++	  /* Restore flag if it was cleared above */
++	  if (sp->m_old_cmq)
++	    YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
++	  sp->restore_thd_mem_root(YYTHD);
++	}
++	;
++
++/*************************************************************************/
++
++xa: XA_SYM begin_or_start xid opt_join_or_resume
++      {
++        Lex->sql_command = SQLCOM_XA_START;
++      }
++    | XA_SYM END xid opt_suspend
++      {
++        Lex->sql_command = SQLCOM_XA_END;
++      }
++    | XA_SYM PREPARE_SYM xid
++      {
++        Lex->sql_command = SQLCOM_XA_PREPARE;
++      }
++    | XA_SYM COMMIT_SYM xid opt_one_phase
++      {
++        Lex->sql_command = SQLCOM_XA_COMMIT;
++      }
++    | XA_SYM ROLLBACK_SYM xid
++      {
++        Lex->sql_command = SQLCOM_XA_ROLLBACK;
++      }
++    | XA_SYM RECOVER_SYM
++      {
++        Lex->sql_command = SQLCOM_XA_RECOVER;
++      }
++    ;
++
++xid: text_string
++     {
++       MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE);
++       if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
++         MYSQL_YYABORT;
++       Lex->xid->set(1L, $1->ptr(), $1->length(), 0, 0);
++     }
++     | text_string ',' text_string
++     {
++       MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
++       if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
++         MYSQL_YYABORT;
++       Lex->xid->set(1L, $1->ptr(), $1->length(), $3->ptr(), $3->length());
++     }
++     | text_string ',' text_string ',' ulong_num
++     {
++       MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE);
++       if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID))))
++         MYSQL_YYABORT;
++       Lex->xid->set($5, $1->ptr(), $1->length(), $3->ptr(), $3->length());
++     }
++     ;
++
++begin_or_start:   BEGIN_SYM {}
++    |             START_SYM {}
++    ;
++
++opt_join_or_resume:
++    /* nothing */           { Lex->xa_opt=XA_NONE;        }
++    | JOIN_SYM              { Lex->xa_opt=XA_JOIN;        }
++    | RESUME_SYM            { Lex->xa_opt=XA_RESUME;      }
++    ;
++
++opt_one_phase:
++    /* nothing */           { Lex->xa_opt=XA_NONE;        }
++    | ONE_SYM PHASE_SYM     { Lex->xa_opt=XA_ONE_PHASE;   }
++    ;
++
++opt_suspend:
++    /* nothing */           { Lex->xa_opt=XA_NONE;        }
++    | SUSPEND_SYM           { Lex->xa_opt=XA_SUSPEND;     }
++      opt_migrate
++    ;
++
++opt_migrate:
++    /* nothing */           { }
++    | FOR_SYM MIGRATE_SYM   { Lex->xa_opt=XA_FOR_MIGRATE; }
++    ;
++
++
+diff -urNad trunk~/sql-bench/Makefile.in trunk/sql-bench/Makefile.in
+--- trunk~/sql-bench/Makefile.in	2007-11-15 08:08:47.000000000 -0600
++++ trunk/sql-bench/Makefile.in	2007-12-27 15:54:49.582280415 -0600
+@@ -66,6 +66,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/sql-common/Makefile.in trunk/sql-common/Makefile.in
+--- trunk~/sql-common/Makefile.in	2007-11-15 08:08:47.000000000 -0600
++++ trunk/sql-common/Makefile.in	2007-12-27 15:54:49.582280415 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/strings/Makefile.in trunk/strings/Makefile.in
+--- trunk~/strings/Makefile.in	2007-11-15 08:08:48.000000000 -0600
++++ trunk/strings/Makefile.in	2007-12-27 15:54:49.582280415 -0600
+@@ -68,6 +68,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/support-files/MacOSX/Makefile.in trunk/support-files/MacOSX/Makefile.in
+--- trunk~/support-files/MacOSX/Makefile.in	2007-11-15 08:08:49.000000000 -0600
++++ trunk/support-files/MacOSX/Makefile.in	2007-12-27 15:54:49.658284746 -0600
+@@ -65,6 +65,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/support-files/Makefile.in trunk/support-files/Makefile.in
+--- trunk~/support-files/Makefile.in	2007-11-15 08:08:49.000000000 -0600
++++ trunk/support-files/Makefile.in	2007-12-27 15:54:49.670285430 -0600
+@@ -66,6 +66,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/support-files/RHEL4-SElinux/Makefile.in trunk/support-files/RHEL4-SElinux/Makefile.in
+--- trunk~/support-files/RHEL4-SElinux/Makefile.in	2007-11-15 08:08:49.000000000 -0600
++++ trunk/support-files/RHEL4-SElinux/Makefile.in	2007-12-27 15:54:49.670285430 -0600
+@@ -64,6 +64,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/tests/Makefile.in trunk/tests/Makefile.in
+--- trunk~/tests/Makefile.in	2007-11-15 08:08:50.000000000 -0600
++++ trunk/tests/Makefile.in	2007-12-27 15:54:49.670285430 -0600
+@@ -68,6 +68,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/tools/Makefile.in trunk/tools/Makefile.in
+--- trunk~/tools/Makefile.in	2007-11-15 08:08:50.000000000 -0600
++++ trunk/tools/Makefile.in	2007-12-27 15:54:50.166313697 -0600
+@@ -65,6 +65,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/vio/Makefile.in trunk/vio/Makefile.in
+--- trunk~/vio/Makefile.in	2007-11-15 08:08:51.000000000 -0600
++++ trunk/vio/Makefile.in	2007-12-27 15:54:50.166313697 -0600
+@@ -65,6 +65,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/win/Makefile.in trunk/win/Makefile.in
+--- trunk~/win/Makefile.in	2007-11-15 08:08:51.000000000 -0600
++++ trunk/win/Makefile.in	2007-12-27 15:54:50.166313697 -0600
+@@ -62,6 +62,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
+diff -urNad trunk~/zlib/Makefile.in trunk/zlib/Makefile.in
+--- trunk~/zlib/Makefile.in	2007-11-15 08:08:51.000000000 -0600
++++ trunk/zlib/Makefile.in	2007-12-27 15:54:50.166313697 -0600
+@@ -67,6 +67,7 @@
+ 	$(top_srcdir)/config/ac-macros/ha_berkeley.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_blackhole.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_example.m4 \
++	$(top_srcdir)/config/ac-macros/ha_sphinx.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_federated.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_innodb.m4 \
+ 	$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \


Property changes on: trunk/debian/patches/88_sphinx_se.dpatch
___________________________________________________________________
Name: svn:executable
   + *

Modified: trunk/debian/rules
===================================================================
--- trunk/debian/rules	2007-12-27 23:28:35 UTC (rev 1112)
+++ trunk/debian/rules	2008-02-20 15:18:03 UTC (rev 1151)
@@ -93,6 +93,7 @@
 		--with-csv-storage-engine \
 		--with-federated-storage-engine \
 		--with-blackhole-storage-engine \
+		--with-sphinx-storage-engine \
 		--without-embedded-server \
 		--with-ndbcluster \
 		--with-ndb-ccflags="-fPIC" \




More information about the Pkg-mysql-commits mailing list