diff --git a/.bzrignore b/.bzrignore
index afd29afbae2..095c04b36ee 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -322,6 +322,7 @@ cmd-line-utils/libedit/makelist
comon.h
comp_err/*.ds?
comp_err/*.vcproj
+compile
config.cache
config.guess
config.h
@@ -553,6 +554,7 @@ libmysqld/spatial.cc
libmysqld/sql_acl.cc
libmysqld/sql_analyse.cc
libmysqld/sql_base.cc
+libmysqld/sql_builtin.cc
libmysqld/sql_cache.cc
libmysqld/sql_class.cc
libmysqld/sql_command
@@ -1179,6 +1181,7 @@ sql/share/gmon.out
sql/share/mysql
sql/share/norwegian-ny/errmsg.sys
sql/share/norwegian/errmsg.sys
+sql/sql_builtin.cc
sql/sql_select.cc.orig
sql/sql_yacc.cc
sql/sql_yacc.h
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index 6c83fffa8fb..589e609beeb 100755
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -147,18 +147,9 @@ static_link="$static_link --with-client-ldflags=-all-static"
local_infile_configs="--enable-local-infile"
-max_configs="--with-innodb --with-berkeley-db"
-max_configs="$max_configs --with-archive-storage-engine"
-max_configs="$max_configs --with-big-tables"
-max_configs="$max_configs --with-blackhole-storage-engine"
-max_configs="$max_configs --with-federated-storage-engine"
-max_configs="$max_configs --with-csv-storage-engine"
-max_configs="$max_configs --with-example-storage-engine"
-max_configs="$max_configs --with-partition $SSL_LIBRARY"
-
-max_no_embedded_configs="$max_configs --with-ndbcluster"
-max_no_ndb_configs="$max_configs --without-ndbcluster --with-embedded-server"
-max_configs="$max_configs --with-ndbcluster --with-embedded-server"
+max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max"
+max_no_ndb_configs="$SSL_LIBRARY --with-plugins=max-no-ndb --with-embedded-server"
+max_configs="$SSL_LIBRARY --with-plugins=max --with-embedded-server"
#
# CPU and platform specific compilation flags.
diff --git a/Makefile.am b/Makefile.am
index dbf43151d60..8709fca34c3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,12 +24,11 @@ EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \
SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
@readline_topdir@ sql-common \
@thread_dirs@ pstack \
- @sql_union_dirs@ storage \
+ @sql_union_dirs@ storage plugin \
@sql_server@ scripts @man_dirs@ tests \
- @mysql_se_plugins@ \
netware @libmysqld_dirs@ \
mysql-test support-files @tools_dirs@ \
- plugin unittest win
+ unittest win
DIST_SUBDIRS = $(SUBDIRS) BUILD
diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp
index 9c4485210a6..1c80147a8f5 100644
--- a/VC++Files/libmysqld/libmysqld.dsp
+++ b/VC++Files/libmysqld/libmysqld.dsp
@@ -363,6 +363,10 @@ SOURCE=..\mysys\my_getopt.c
SOURCE=..\sql-common\my_time.c
# End Source File
# Begin Source File
+
+SOURCE=..\sql-common\my_user.c
+# End Source File
+# Begin Source File
SOURCE=..\sql\net_serv.cpp
# End Source File
diff --git a/VC++Files/libmysqld/libmysqld_ia64.dsp b/VC++Files/libmysqld/libmysqld_ia64.dsp
index b5223e38f2d..9668193fc1d 100644
--- a/VC++Files/libmysqld/libmysqld_ia64.dsp
+++ b/VC++Files/libmysqld/libmysqld_ia64.dsp
@@ -338,6 +338,10 @@ SOURCE="..\sql-common\my_time.c"
# End Source File
# Begin Source File
+SOURCE="..\sql-common\my_user.c"
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\net_serv.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/mysql.sln b/VC++Files/mysql.sln
index f7c612ff390..c5bf8291888 100644
--- a/VC++Files/mysql.sln
+++ b/VC++Files/mysql.sln
@@ -257,6 +257,7 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql_client_test", "tests\mysql_client_test.vcproj", "{DA224DAB-5006-42BE-BB77-16E8BE5326D5}"
ProjectSection(ProjectDependencies) = postProject
{26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
+ {44D9C7DC-6636-4B82-BD01-6876C64017DF} = {44D9C7DC-6636-4B82-BD01-6876C64017DF}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqlmanager", "server-tools\instance-manager\mysqlmanager.vcproj", "{6D524B3E-210A-4FCD-8D41-FEC0D21E83AC}"
diff --git a/VC++Files/mysys/mysys.vcproj b/VC++Files/mysys/mysys.vcproj
index befb4ad58b0..cf367e5666b 100644
--- a/VC++Files/mysys/mysys.vcproj
+++ b/VC++Files/mysys/mysys.vcproj
@@ -3232,6 +3232,49 @@
PreprocessorDefinitions=""/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ptr(),buffer->length());
#ifdef HAVE_READLINE
@@ -1981,6 +2011,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
if (error)
{
+ executing_query= 0;
buffer->length(0); // Remove query on error
return error;
}
@@ -1992,13 +2023,19 @@ com_go(String *buffer,char *line __attribute__((unused)))
if (quick)
{
if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql))
- return put_error(&mysql);
+ {
+ executing_query= 0;
+ return put_error(&mysql);
+ }
}
else
{
error= mysql_store_result_for_lazy(&result);
if (error)
- return error;
+ {
+ executing_query= 0;
+ return error;
+ }
}
if (verbose >= 3 || !opt_silent)
@@ -2073,6 +2110,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
(mysql.server_status & SERVER_STATUS_DB_DROPPED))
get_current_db();
+ executing_query= 0;
return error; /* New command follows */
}
@@ -2286,6 +2324,8 @@ print_table_data(MYSQL_RES *result)
while ((cur= mysql_fetch_row(result)))
{
+ if (interrupted_query)
+ break;
ulong *lengths= mysql_fetch_lengths(result);
(void) tee_fputs("| ", PAGER);
mysql_field_seek(result, 0);
@@ -2393,6 +2433,8 @@ print_table_data_html(MYSQL_RES *result)
}
while ((cur = mysql_fetch_row(result)))
{
+ if (interrupted_query)
+ break;
ulong *lengths=mysql_fetch_lengths(result);
(void) tee_fputs("", PAGER);
for (uint i=0; i < mysql_num_fields(result); i++)
@@ -2422,6 +2464,8 @@ print_table_data_xml(MYSQL_RES *result)
fields = mysql_fetch_fields(result);
while ((cur = mysql_fetch_row(result)))
{
+ if (interrupted_query)
+ break;
ulong *lengths=mysql_fetch_lengths(result);
(void) tee_fputs("\n \n", PAGER);
for (uint i=0; i < mysql_num_fields(result); i++)
@@ -2456,6 +2500,8 @@ print_table_data_vertically(MYSQL_RES *result)
mysql_field_seek(result,0);
for (uint row_count=1; (cur= mysql_fetch_row(result)); row_count++)
{
+ if (interrupted_query)
+ break;
mysql_field_seek(result,0);
tee_fprintf(PAGER,
"*************************** %d. row ***************************\n", row_count);
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 551be79fc99..3288b627554 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -307,7 +307,7 @@ int main(int argc, char **argv)
b_read= my_read(check_file, chf_buffer, sizeof(chf_buffer)-1, MYF(0));
chf_buffer[b_read]= 0;
my_close(check_file, MYF(0));
- if (!strcmp(chf_buffer, VERSION))
+ if (!strcmp(chf_buffer, MYSQL_SERVER_VERSION))
{
if (opt_verbose)
puts("mysql_upgrade already done for this version");
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 21ca1d6e3a1..ce876708fbc 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -688,10 +688,11 @@ static void die(const char *fmt, ...)
/* Note that we will get some memory leaks when calling this! */
-static void abort_not_supported_test()
+static void abort_not_supported_test(const char *fname)
{
DBUG_ENTER("abort_not_supported_test");
- fprintf(stderr, "This test is not supported by this installation\n");
+ fprintf(stderr, "The test '%s' is not supported by this installation\n",
+ fname);
if (!silent)
printf("skipped\n");
free_used_memory();
@@ -814,7 +815,7 @@ static void check_result(DYNAMIC_STRING* ds, const char *fname,
DBUG_ENTER("check_result");
if (res && require_option)
- abort_not_supported_test();
+ abort_not_supported_test(fname);
switch (res) {
case RESULT_OK:
break; /* ok */
@@ -1036,7 +1037,7 @@ int do_wait_for_slave_to_stop(struct st_query *q __attribute__((unused)))
int do_require_manager(struct st_query *query __attribute__((unused)) )
{
if (!manager)
- abort_not_supported_test();
+ abort_not_supported_test("manager");
return 0;
}
@@ -1305,7 +1306,9 @@ int var_query_set(VAR* var, const char *query, const char** query_end)
uint i;
ulong *lengths;
char *end;
+#ifdef NOT_YET
MYSQL_FIELD *fields= mysql_fetch_fields(res);
+#endif
init_dynamic_string(&result, "", 16384, 65536);
lengths= mysql_fetch_lengths(res);
@@ -1920,7 +1923,7 @@ static void set_charset(struct st_query *q)
q->last_argument= p;
charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
if (!charset_info)
- abort_not_supported_test();
+ abort_not_supported_test(charset_name);
}
static uint get_errcodes(match_err *to,struct st_query *q)
@@ -1963,7 +1966,7 @@ static uint get_errcodes(match_err *to,struct st_query *q)
(as in ER_WRONG_VALUE vs. ER_WRONG_VALUE_COUNT).
*/
if (!strncmp(start, e->name, (int) (p - start)) &&
- strlen(e->name) == (p - start))
+ (uint) strlen(e->name) == (uint) (p - start))
{
to[count].code.errnum= (uint) e->code;
to[count].type= ERR_ERRNO;
@@ -4329,7 +4332,7 @@ static void handle_error(const char *query, struct st_query *q,
if (err_errno == CR_SERVER_LOST ||
err_errno == CR_SERVER_GONE_ERROR)
die("require query '%s' failed: %d: %s", query, err_errno, err_error);
- abort_not_supported_test();
+ abort_not_supported_test("failed_query");
}
if (q->abort_on_error)
@@ -5101,7 +5104,7 @@ static void init_var_hash(MYSQL *mysql)
DBUG_VOID_RETURN;
}
-static void mark_progress(int line)
+static void mark_progress(int line __attribute__((unused)))
{
#ifdef NOT_YET
static FILE* fp = NULL;
diff --git a/cmakelists.txt b/cmakelists.txt
index 0e91f49be90..5edc33b9f5a 100644
--- a/cmakelists.txt
+++ b/cmakelists.txt
@@ -9,56 +9,53 @@ SET(WITH_CSV_STORAGE_ENGINE TRUE)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/mysql_version.h.in
${CMAKE_SOURCE_DIR}/include/mysql_version.h @ONLY)
+SET(WITH_HEAP_STORAGE_ENGINE TRUE)
+ADD_DEFINITIONS(-D WITH_HEAP_STORAGE_ENGINE)
+SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_heap_plugin")
+
+SET(WITH_MYISAM_STORAGE_ENGINE TRUE)
+ADD_DEFINITIONS(-D WITH_MYISAM_STORAGE_ENGINE)
+SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_myisam_plugin")
+
+SET(WITH_MYISAMMRG_STORAGE_ENGINE TRUE)
+ADD_DEFINITIONS(-D WITH_MYISAMMRG_STORAGE_ENGINE)
+SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_myisammrg_plugin")
+
IF(WITH_ARCHIVE_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_ARCHIVE_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &archive_hton")
- SET (mysql_se_decls "${mysql_se_decls}, archive_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_archive.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_archive_plugin")
ENDIF(WITH_ARCHIVE_STORAGE_ENGINE)
IF(WITH_BLACKHOLE_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_BLACKHOLE_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &blackhole_hton")
- SET (mysql_se_decls "${mysql_se_decls}, blackhole_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_blackhole.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_blackhole_plugin")
ENDIF(WITH_BLACKHOLE_STORAGE_ENGINE)
IF(WITH_CSV_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_CSV_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &tina_hton")
- SET (mysql_se_decls "${mysql_se_decls}, tina_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../storage/csv/ha_tina.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_csv_plugin")
ENDIF(WITH_CSV_STORAGE_ENGINE)
IF(WITH_EXAMPLE_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_EXAMPLE_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &example_hton")
- SET (mysql_se_decls "${mysql_se_decls}, example_hton")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_example_plugin")
ENDIF(WITH_EXAMPLE_STORAGE_ENGINE)
IF(WITH_INNOBASE_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_INNOBASE_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &innobase_hton")
- SET (mysql_se_decls "${mysql_se_decls}, innobase_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_innodb.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_innobase_plugin")
ENDIF(WITH_INNOBASE_STORAGE_ENGINE)
IF(WITH_PARTITION_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_PARTITION_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &partition_hton")
- SET (mysql_se_decls "${mysql_se_decls}, partition_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_partition.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_partition_plugin")
ENDIF(WITH_PARTITION_STORAGE_ENGINE)
IF(WITH_FEDERATED_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_FEDERATED_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &federated_hton")
- SET (mysql_se_decls "${mysql_se_decls}, federated_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_federated.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_federated_plugin")
ENDIF(WITH_FEDERATED_STORAGE_ENGINE)
IF(WITH_BERKELEY_STORAGE_ENGINE)
ADD_DEFINITIONS(-D WITH_BERKELEY_STORAGE_ENGINE)
- SET (mysql_se_htons "${mysql_se_htons}, &berkeley_hton")
- SET (mysql_se_decls "${mysql_se_decls}, berkeley_hton")
- SET (mysql_se_ha_src ${mysql_se_ha_src} "../sql/ha_berkeley.cc")
+ SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_berkeley_plugin")
ENDIF(WITH_BERKELEY_STORAGE_ENGINE)
-CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/sql/handlerton.cc.in
- ${CMAKE_SOURCE_DIR}/sql/handlerton.cc @ONLY)
+CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc.in
+ ${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc @ONLY)
SET(localstatedir "C:\\mysql\\data")
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-huge.cnf.sh
@@ -137,6 +134,12 @@ ENDIF(WITH_ARCHIVE_STORAGE_ENGINE)
IF(WITH_BERKELEY_STORAGE_ENGINE)
ADD_SUBDIRECTORY(storage/bdb)
ENDIF(WITH_BERKELEY_STORAGE_ENGINE)
+IF(WITH_BLACKHOLE_STORAGE_ENGINE)
+ ADD_SUBDIRECTORY(storage/blackhole)
+ENDIF(WITH_BLACKHOLE_STORAGE_ENGINE)
+IF(WITH_CSV_STORAGE_ENGINE)
+ ADD_SUBDIRECTORY(storage/csv)
+ENDIF(WITH_CSV_STORAGE_ENGINE)
IF(WITH_EXAMPLE_STORAGE_ENGINE)
ADD_SUBDIRECTORY(storage/example)
ENDIF(WITH_EXAMPLE_STORAGE_ENGINE)
diff --git a/config/ac-macros/ha_archive.m4 b/config/ac-macros/ha_archive.m4
deleted file mode 100644
index 2d2558ea600..00000000000
--- a/config/ac-macros/ha_archive.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_ARCHIVEDB
-dnl Sets HAVE_ARCHIVE_DB if --with-archive-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_ARCHIVEDB], [
- AC_ARG_WITH([archive-storage-engine],
- [
- --with-archive-storage-engine
- Enable the Archive Storage Engine],
- [archivedb="$withval"],
- [archivedb=no])
- AC_MSG_CHECKING([for archive storage engine])
-
- case "$archivedb" in
- yes )
- AC_DEFINE([HAVE_ARCHIVE_DB], [1], [Builds Archive Storage Engine])
- AC_MSG_RESULT([yes])
- [archivedb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [archivedb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_ARCHIVE SECTION
-dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_berkeley.m4 b/config/ac-macros/ha_berkeley.m4
index 183a622dfc9..c7d99bd8e03 100644
--- a/config/ac-macros/ha_berkeley.m4
+++ b/config/ac-macros/ha_berkeley.m4
@@ -8,23 +8,20 @@ dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_SETUP_BERKELEY_DB], [
AC_ARG_WITH([berkeley-db],
- [
- --with-berkeley-db[=DIR]
- Use BerkeleyDB located in DIR],
+ AS_HELP_STRING([--with-berkeley-db[[[[[=DIR]]]]]],
+ [Use BerkeleyDB located in DIR]),
[bdb="$withval"],
[bdb=yes])
AC_ARG_WITH([berkeley-db-includes],
- [
- --with-berkeley-db-includes=DIR
- Find Berkeley DB headers in DIR],
+ AS_HELP_STRING([--with-berkeley-db-includes=DIR],
+ [Find Berkeley DB headers in DIR]),
[bdb_includes="$withval"],
[bdb_includes=default])
AC_ARG_WITH([berkeley-db-libs],
- [
- --with-berkeley-db-libs=DIR
- Find Berkeley DB libraries in DIR],
+ AS_HELP_STRING([--with-berkeley-db-libs=DIR],
+ [Find Berkeley DB libraries in DIR]),
[bdb_libs="$withval"],
[bdb_libs=default])
@@ -120,12 +117,9 @@ AC_DEFUN([MYSQL_SETUP_BERKELEY_DB], [
sh $rel_srcdir/$bdb/dist/configure $bdb_conf_flags) || \
AC_MSG_ERROR([could not configure Berkeley DB])
- mysql_se_libs="$mysql_se_libs $bdb_libs_with_path"
-
AC_SUBST(bdb_includes)
AC_SUBST(bdb_libs)
AC_SUBST(bdb_libs_with_path)
- AC_CONFIG_FILES(storage/bdb/Makefile)
])
AC_DEFUN([MYSQL_CHECK_INSTALLED_BDB], [
diff --git a/config/ac-macros/ha_blackhole.m4 b/config/ac-macros/ha_blackhole.m4
deleted file mode 100644
index cc4d360f5a8..00000000000
--- a/config/ac-macros/ha_blackhole.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_BLACKHOLEDB
-dnl Sets HAVE_BLACKHOLE_DB if --with-blackhole-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_BLACKHOLEDB], [
- AC_ARG_WITH([blackhole-storage-engine],
- [
- --with-blackhole-storage-engine
- Enable the Blackhole Storage Engine],
- [blackholedb="$withval"],
- [blackholedb=no])
- AC_MSG_CHECKING([for blackhole storage engine])
-
- case "$blackholedb" in
- yes )
- AC_DEFINE([HAVE_BLACKHOLE_DB], [1], [Builds Blackhole Storage Engine])
- AC_MSG_RESULT([yes])
- [blackholedb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [blackholedb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_BLACKHOLE SECTION
-dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_example.m4 b/config/ac-macros/ha_example.m4
deleted file mode 100644
index f8067931ce6..00000000000
--- a/config/ac-macros/ha_example.m4
+++ /dev/null
@@ -1,30 +0,0 @@
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_EXAMPLEDB
-dnl Sets HAVE_EXAMPLE_DB if --with-example-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_EXAMPLEDB], [
- AC_ARG_WITH([example-storage-engine],
- [
- --with-example-storage-engine
- Enable the Example Storage Engine],
- [exampledb="$withval"],
- [exampledb=no])
- AC_MSG_CHECKING([for example storage engine])
-
- case "$exampledb" in
- yes )
- AC_DEFINE([HAVE_EXAMPLE_DB], [1], [Builds Example DB])
- AC_MSG_RESULT([yes])
- [exampledb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [exampledb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_EXAMPLE SECTION
-dnl ---------------------------------------------------------------------------
-
diff --git a/config/ac-macros/ha_federated.m4 b/config/ac-macros/ha_federated.m4
deleted file mode 100644
index 5c991f31666..00000000000
--- a/config/ac-macros/ha_federated.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_FEDERATED
-dnl Sets HAVE_FEDERATED if --with-federated-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_FEDERATED], [
- AC_ARG_WITH([federated-storage-engine],
- [
- --with-federated-storage-engine
- Enable the MySQL Federated Storage Engine],
- [federateddb="$withval"],
- [federateddb=no])
- AC_MSG_CHECKING([for MySQL federated storage engine])
-
- case "$federateddb" in
- yes )
- AC_DEFINE([HAVE_FEDERATED_DB], [1], [Define to enable Federated Handler])
- AC_MSG_RESULT([yes])
- [federateddb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [federateddb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_FEDERATED SECTION
-dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_innodb.m4 b/config/ac-macros/ha_innodb.m4
deleted file mode 100644
index 287b77c8851..00000000000
--- a/config/ac-macros/ha_innodb.m4
+++ /dev/null
@@ -1,77 +0,0 @@
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_INNODB
-dnl Sets HAVE_INNOBASE_DB if --with-innodb is used
-dnl ---------------------------------------------------------------------------
-
-AC_DEFUN([MYSQL_CHECK_INNODB], [
- AC_ARG_WITH([innodb],
- [
- --without-innodb Do not include the InnoDB table handler],
- [innodb="$withval"],
- [innodb=yes])
-
- AC_MSG_CHECKING([for Innodb])
-
- have_innodb=no
- innodb_includes=
- innodb_libs=
- case "$innodb" in
- yes )
- AC_MSG_RESULT([Using Innodb])
- AC_DEFINE([HAVE_INNOBASE_DB], [1], [Using Innobase DB])
- have_innodb="yes"
- innodb_includes="-I\$(top_builddir)/innobase/include"
- innodb_system_libs=""
-dnl Some libs are listed several times, in order for gcc to sort out
-dnl circular references.
- innodb_libs="\
- \$(top_builddir)/storage/innobase/usr/libusr.a\
- \$(top_builddir)/storage/innobase/srv/libsrv.a\
- \$(top_builddir)/storage/innobase/dict/libdict.a\
- \$(top_builddir)/storage/innobase/que/libque.a\
- \$(top_builddir)/storage/innobase/srv/libsrv.a\
- \$(top_builddir)/storage/innobase/ibuf/libibuf.a\
- \$(top_builddir)/storage/innobase/row/librow.a\
- \$(top_builddir)/storage/innobase/pars/libpars.a\
- \$(top_builddir)/storage/innobase/btr/libbtr.a\
- \$(top_builddir)/storage/innobase/trx/libtrx.a\
- \$(top_builddir)/storage/innobase/read/libread.a\
- \$(top_builddir)/storage/innobase/usr/libusr.a\
- \$(top_builddir)/storage/innobase/buf/libbuf.a\
- \$(top_builddir)/storage/innobase/ibuf/libibuf.a\
- \$(top_builddir)/storage/innobase/eval/libeval.a\
- \$(top_builddir)/storage/innobase/log/liblog.a\
- \$(top_builddir)/storage/innobase/fsp/libfsp.a\
- \$(top_builddir)/storage/innobase/fut/libfut.a\
- \$(top_builddir)/storage/innobase/fil/libfil.a\
- \$(top_builddir)/storage/innobase/lock/liblock.a\
- \$(top_builddir)/storage/innobase/mtr/libmtr.a\
- \$(top_builddir)/storage/innobase/page/libpage.a\
- \$(top_builddir)/storage/innobase/rem/librem.a\
- \$(top_builddir)/storage/innobase/thr/libthr.a\
- \$(top_builddir)/storage/innobase/sync/libsync.a\
- \$(top_builddir)/storage/innobase/data/libdata.a\
- \$(top_builddir)/storage/innobase/mach/libmach.a\
- \$(top_builddir)/storage/innobase/ha/libha.a\
- \$(top_builddir)/storage/innobase/dyn/libdyn.a\
- \$(top_builddir)/storage/innobase/mem/libmem.a\
- \$(top_builddir)/storage/innobase/sync/libsync.a\
- \$(top_builddir)/storage/innobase/ut/libut.a\
- \$(top_builddir)/storage/innobase/os/libos.a\
- \$(top_builddir)/storage/innobase/ut/libut.a"
-
- AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"])
- ;;
- * )
- AC_MSG_RESULT([Not using Innodb])
- ;;
- esac
-
- AC_SUBST(innodb_includes)
- AC_SUBST(innodb_libs)
- AC_SUBST(innodb_system_libs)
-])
-
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_INNODB SECTION
-dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_ndbcluster.m4 b/config/ac-macros/ha_ndbcluster.m4
index ecb8808bfa0..505d000c196 100644
--- a/config/ac-macros/ha_ndbcluster.m4
+++ b/config/ac-macros/ha_ndbcluster.m4
@@ -191,7 +191,6 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
ndbcluster_libs="\$(top_builddir)/storage/ndb/src/.libs/libndbclient.a"
ndbcluster_system_libs=""
ndb_mgmclient_libs="\$(top_builddir)/storage/ndb/src/mgmclient/libndbmgmclient.la"
- mysql_se_objs="$mysql_se_objs ha_ndbcluster_binlog.o"
MYSQL_CHECK_NDB_OPTIONS
NDBCLUSTER_WORKAROUNDS
@@ -282,9 +281,6 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
ndb_bin_am_ldflags=""
fi
- mysql_se_libs="$mysql_se_libs $ndbcluster_libs $ndbcluster_system_libs"
- mysql_se_libs="$mysql_se_libs $NDB_SCI_LIBS"
-
AC_SUBST(NDB_VERSION_MAJOR)
AC_SUBST(NDB_VERSION_MINOR)
AC_SUBST(NDB_VERSION_BUILD)
@@ -302,6 +298,7 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
AC_SUBST(ndbcluster_libs)
AC_SUBST(ndbcluster_system_libs)
AC_SUBST(ndb_mgmclient_libs)
+ AC_SUBST(NDB_SCI_LIBS)
AC_SUBST(ndb_transporter_opt_objs)
AC_SUBST(ndb_port)
@@ -311,7 +308,7 @@ AC_DEFUN([MYSQL_SETUP_NDBCLUSTER], [
AC_SUBST(NDB_DEFS)
AC_SUBST(ndb_cxxflags_fix)
- AC_CONFIG_FILES(storage/ndb/Makefile storage/ndb/include/Makefile dnl
+ AC_CONFIG_FILES(storage/ndb/include/Makefile dnl
storage/ndb/src/Makefile storage/ndb/src/common/Makefile dnl
storage/ndb/docs/Makefile dnl
storage/ndb/tools/Makefile dnl
diff --git a/config/ac-macros/ha_partition.m4 b/config/ac-macros/ha_partition.m4
deleted file mode 100644
index 1ce7dedc5f3..00000000000
--- a/config/ac-macros/ha_partition.m4
+++ /dev/null
@@ -1,33 +0,0 @@
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_PARTITIONDB
-dnl Sets HAVE_PARTITION_DB if --with-partition is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_PARTITIONDB], [
- AC_ARG_WITH([partition],
- [
- --with-partition
- Enable the Partition Storage Engine],
- [partitiondb="$withval"],
- [partitiondb=no])
- AC_MSG_CHECKING([for partition])
-
-dnl case "$partitiondb" in
-dnl yes )
-dnl AC_DEFINE([HAVE_PARTITION_DB], [1], [Builds Partition DB])
-dnl AC_MSG_RESULT([yes])
-dnl [partitiondb=yes]
-dnl ;;
-dnl * )
-dnl AC_MSG_RESULT([no])
-dnl [partitiondb=no]
-dnl ;;
-dnl esac
- AC_DEFINE([HAVE_PARTITION_DB], [1], [Builds Partition DB])
- AC_MSG_RESULT([yes])
- [partitiondb=yes]
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_PARTITION SECTION
-dnl ---------------------------------------------------------------------------
-
diff --git a/config/ac-macros/ha_tina.m4 b/config/ac-macros/ha_tina.m4
deleted file mode 100644
index fe6e382ce20..00000000000
--- a/config/ac-macros/ha_tina.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_CSVDB
-dnl Sets HAVE_CSV_DB if --with-csv-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_CSVDB], [
- AC_ARG_WITH([csv-storage-engine],
- [
- --with-csv-storage-engine
- Enable the CSV Storage Engine],
- [csvdb="$withval"],
- [csvdb=no])
- AC_MSG_CHECKING([for csv storage engine])
-
- case "$csvdb" in
- yes )
- AC_DEFINE([HAVE_CSV_DB], [1], [Builds the CSV Storage Engine])
- AC_MSG_RESULT([yes])
- [csvdb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [csvdb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_CSV SECTION
-dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4
index d8199f5970e..a2f70071e2d 100644
--- a/config/ac-macros/misc.m4
+++ b/config/ac-macros/misc.m4
@@ -675,8 +675,8 @@ dnl Sets BIG_TABLES if --with-big-tables is used
dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_CHECK_BIG_TABLES], [
AC_ARG_WITH([big-tables],
- [
- --with-big-tables Support tables with more than 4 G rows even on 32 bit platforms],
+ AS_HELP_STRING([--with-big-tables],
+ [Support tables with more than 4 G rows even on 32 bit platforms]),
[bigtables="$withval"],
[bigtables=no])
AC_MSG_CHECKING([for big tables support])
@@ -703,8 +703,8 @@ dnl Sets MAX_INDEXES
dnl ---------------------------------------------------------------------------
AC_DEFUN([MYSQL_CHECK_MAX_INDEXES], [
AC_ARG_WITH([max-indexes],
- [
- --with-max-indexes=\# Sets the maximum number of indexes per table, default 64],
+ AS_HELP_STRING([--with-max-indexes=N],
+ [Sets the maximum number of indexes per table, default 64]),
[max_indexes="$withval"],
[max_indexes=64])
AC_MSG_CHECKING([max indexes per table])
diff --git a/config/ac-macros/plugins.m4 b/config/ac-macros/plugins.m4
new file mode 100644
index 00000000000..aa28a611e9e
--- /dev/null
+++ b/config/ac-macros/plugins.m4
@@ -0,0 +1,733 @@
+dnl ===========================================================================
+dnl Support for mysql server plugins
+dnl ===========================================================================
+dnl
+dnl WorkLog#3201
+dnl
+dnl Framework for pluggable static and dynamic plugins for mysql
+dnl
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN([name],[Plugin name],
+dnl [Plugin description],
+dnl [group,group...])
+dnl
+dnl DESCRIPTION
+dnl First declaration for a plugin (mandatory).
+dnl Adds plugin as member to configuration groups (if specified)
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN],[
+ _MYSQL_PLUGIN(
+ [$1],
+ [__MYSQL_PLUGIN_]AS_TR_CPP([$1])[__],
+ m4_default([$2], [$1 plugin]),
+ m4_default([$3], [plugin for $1]),
+ m4_default([$4], []),
+ )
+])
+
+AC_DEFUN([_MYSQL_PLUGIN],[
+ m4_ifdef([$2], [
+ AC_FATAL([Duplicate MYSQL_PLUGIN declaration for $3])
+ ],[
+ m4_define([$2], [$1])
+ _MYSQL_PLUGAPPEND([__mysql_plugin_list__],[$1])
+ m4_define([MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]), [$3])
+ m4_define([MYSQL_PLUGIN_DESC_]AS_TR_CPP([$1]), [$4])
+ _MYSQL_PLUGAPPEND_META([$1], $5)
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_STORAGE_ENGINE
+dnl
+dnl SYNOPSIS
+dnl MYSQL_STORAGE_ENGINE([name],[legacy-option],[Storage engine name],
+dnl [Storage engine description],[group,group...])
+dnl
+dnl DESCRIPTION
+dnl Short cut for storage engine declarations
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_STORAGE_ENGINE],[
+ MYSQL_PLUGIN([$1], [$3], [$4], [[$5]])
+ MYSQL_PLUGIN_DEFINE([$1], [WITH_]AS_TR_CPP([$1])[_STORAGE_ENGINE])
+ ifelse([$2],[no],[],[
+ _MYSQL_LEGACY_STORAGE_ENGINE(
+ m4_bpatsubst([$1], -, _),
+ m4_bpatsubst(m4_default([$2], [$1-storage-engine]), -, _))
+ ])
+])
+
+AC_DEFUN([_MYSQL_LEGACY_STORAGE_ENGINE],[
+if test "[${with_]$2[+set}]" = set; then
+ [with_plugin_]$1="[$with_]$2"
+fi
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_DEFINE
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DEFINE([name],[MYSQL_CPP_DEFINE])
+dnl
+dnl DESCRIPTION
+dnl When a plugin is to be statically linked, define the C macro
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_DEFINE],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ m4_define([MYSQL_PLUGIN_DEFINE_]AS_TR_CPP([$1]), [$2])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_DIRECTORY
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DIRECTORY([name],[plugin/dir])
+dnl
+dnl DESCRIPTION
+dnl Adds a directory to the build process
+dnl if it contains 'configure' it will be picked up automatically
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_DIRECTORY],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ m4_define([MYSQL_PLUGIN_DIRECTORY_]AS_TR_CPP([$1]), [$2])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_STATIC
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_STATIC([name],[libmyplugin.a])
+dnl
+dnl DESCRIPTION
+dnl Declare the name for the static library
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_STATIC],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ m4_define([MYSQL_PLUGIN_STATIC_]AS_TR_CPP([$1]), [$2])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_DYNAMIC
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DYNAMIC([name],[myplugin.la])
+dnl
+dnl DESCRIPTION
+dnl Declare the name for the shared library
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_DYNAMIC],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ m4_define([MYSQL_PLUGIN_DYNAMIC_]AS_TR_CPP([$1]), [$2])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_MANDATORY
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_MANDATORY([name])
+dnl
+dnl DESCRIPTION
+dnl Marks the specified plugin as a mandatory plugin
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_MANDATORY],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ _MYSQL_PLUGIN_MANDATORY([$1],
+ [MYSQL_PLUGIN_MANDATORY_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1])
+ )
+])
+
+AC_DEFUN([_MYSQL_PLUGIN_MANDATORY],[
+ m4_define([$2], [yes])
+ m4_ifdef([$3], [
+ AC_FATAL([mandatory plugin $1 has been disabled])
+ m4_undefine([$2])
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_DISABLED
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DISABLED([name])
+dnl
+dnl DESCRIPTION
+dnl Marks the specified plugin as a disabled plugin
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_DISABLED],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ _MYSQL_PLUGIN_DISABLED([$1],
+ [MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_MANDATORY_]AS_TR_CPP([$1])
+ )
+])
+
+AC_DEFUN([_MYSQL_PLUGIN_DISABLED],[
+ m4_define([$2], [yes])
+ m4_ifdef([$3], [
+ AC_FATAL([attempt to disable mandatory plugin $1])
+ m4_undefine([$2])
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_DEPENDS
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DEPENDS([name],[prereq,prereq...])
+dnl
+dnl DESCRIPTION
+dnl Enables other plugins neccessary for the named plugin
+dnl Dependency checking is not recursive so if any
+dnl required plugin requires further plugins, list them
+dnl here too!
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_DEPENDS],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ ifelse($#, 2, [
+ _MYSQL_PLUGIN_DEPEND([$1], $2)
+ ], [
+ AC_FATAL([bad number of arguments])
+ ])
+])
+
+AC_DEFUN([_MYSQL_PLUGIN_DEPEND],[
+ ifelse($#, 1, [], [$#:$2], [2:], [], [
+ MYSQL_REQUIRE_PLUGIN([$2])
+ _MYSQL_PLUGAPPEND([__mysql_plugdepends_$1__],[$2])
+ _MYSQL_PLUGIN_DEPEND([$1], m4_shift(m4_shift($@)))
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_PLUGIN_ACTIONS
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_ACTIONS([name],[PLUGIN_CONFIGURE_STUFF])
+dnl
+dnl DESCRIPTION
+dnl Declares additional autoconf actions required to configure the plugin
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_PLUGIN_ACTIONS],[
+ MYSQL_REQUIRE_PLUGIN([$1])
+ m4_ifdef([$2],[
+ m4_define([MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1]),m4_defn([$2]))
+ ],[
+ m4_define([MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1]), [$2])
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CONFIGURE_PLUGINS
+dnl
+dnl SYNOPSIS
+dnl MYSQL_PLUGIN_DEPENDS([name,name...])
+dnl
+dnl DESCRIPTION
+dnl Used last, emits all required shell code to configure the plugins
+dnl Argument is a list of default plugins or meta-plugin
+dnl
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_CONFIGURE_PLUGINS],[
+ m4_ifdef([__mysql_plugin_configured__],[
+ AC_FATAL([cannot use [MYSQL_CONFIGURE_PLUGINS] multiple times])
+ ],[
+ m4_define([__mysql_plugin_configured__],[done])
+ m4_ifdef([__mysql_plugin_list__],[
+ _MYSQL_CHECK_PLUGIN_ARGS([$1])
+ _MYSQL_CONFIGURE_PLUGINS(m4_bpatsubst(__mysql_plugin_list__, :, [,]))
+ _MYSQL_EMIT_PLUGIN_ACTIONS(m4_bpatsubst(__mysql_plugin_list__, :, [,]))
+ AC_SUBST([mysql_se_dirs])
+ AC_SUBST([mysql_pg_dirs])
+ ])
+ ])
+])
+
+AC_DEFUN([_MYSQL_CONFIGURE_PLUGINS],[
+ ifelse($#, 0, [], $#, 1, [
+ _MYSQL_EMIT_CHECK_PLUGIN([$1])
+ ],[
+ _MYSQL_EMIT_CHECK_PLUGIN([$1])
+ _MYSQL_CONFIGURE_PLUGINS(m4_shift($@))
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_CHECK_PLUGIN],[
+ __MYSQL_EMIT_CHECK_PLUGIN(
+ [$1],
+ m4_bpatsubst([$1], -, _),
+ [MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DESC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DEFINE_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DIRECTORY_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_STATIC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DYNAMIC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_MANDATORY_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1])
+ )
+])
+
+AC_DEFUN([__MYSQL_EMIT_CHECK_PLUGIN],[
+ m4_ifdef([$5],[
+ AH_TEMPLATE($5, [Include ]$4[ into mysqld])
+ ])
+ AC_MSG_CHECKING([whether to use ]$3)
+ mysql_use_plugin_dir=""
+ m4_ifdef([$10],[
+ if test "X[$mysql_plugin_]$2" = Xyes -a \
+ "X[$with_plugin_]$2" != Xno -o \
+ "X[$with_plugin_]$2" = Xyes; then
+ AC_MSG_RESULT([error])
+ AC_MSG_ERROR([disabled])
+ fi
+ AC_MSG_RESULT([no])
+ ],[
+ m4_ifdef([$9],[
+ if test "X[$with_plugin_]$2" = Xno; then
+ AC_MSG_RESULT([error])
+ AC_MSG_ERROR([cannot disable mandatory plugin])
+ fi
+ [mysql_plugin_]$2=yes
+ ])
+ if test "X[$with_plugin_]$2" = Xno; then
+ AC_MSG_RESULT([no])
+ else
+ m4_ifdef([$8],m4_ifdef([$7],[],[[with_plugin_]$2='']))
+ if test "X[$mysql_plugin_]$2" != Xyes -a \
+ "X[$with_plugin_]$2" != Xyes; then
+ m4_ifdef([$8],[
+ m4_ifdef([$6],[
+ if test -d "$srcdir/$6" ; then
+ mysql_use_plugin_dir="$6"
+ ])
+ AC_SUBST([plugin_]$2[_shared_target], "$8")
+ AC_SUBST([plugin_]$2[_static_target], [""])
+ [with_plugin_]$2=yes
+ AC_MSG_RESULT([plugin])
+ m4_ifdef([$6],[
+ else
+ [mysql_plugin_]$2=no
+ AC_MSG_RESULT([no])
+ fi
+ ])
+ ],[
+ [with_plugin_]$2=no
+ AC_MSG_RESULT([no])
+ ])
+ else
+ m4_ifdef([$7],[
+ ifelse(m4_bregexp($7, [^lib[^.]+\.a$]), -2, [
+dnl change above "-2" to "0" to enable this section
+dnl Although this is "pretty", it breaks libmysqld build
+ m4_ifdef([$6],[
+ mysql_use_plugin_dir="$6"
+ mysql_plugin_libs="$mysql_plugin_libs -L[\$(top_builddir)]/$6"
+ ])
+ mysql_plugin_libs="$mysql_plugin_libs dnl
+[-l]m4_bregexp($7, [^lib\([^.]+\)], [\1])"
+ ], m4_bregexp($7, [^\\\$]), 0, [
+ m4_ifdef([$6],[
+ mysql_use_plugin_dir="$6"
+ ])
+ mysql_plugin_libs="$mysql_plugin_libs $7"
+ ], [
+ m4_ifdef([$6],[
+ mysql_use_plugin_dir="$6"
+ mysql_plugin_libs="$mysql_plugin_libs \$(top_builddir)/$6/$7"
+ ],[
+ mysql_plugin_libs="$mysql_plugin_libs $7"
+ ])
+ ])
+ m4_ifdef([$5],[
+ AC_DEFINE($5)
+ ])
+ AC_SUBST([plugin_]$2[_static_target], "$7")
+ AC_SUBST([plugin_]$2[_shared_target], [""])
+ ],[
+ m4_ifdef([$6],[
+ AC_MSG_RESULT([error])
+ AC_MSG_ERROR([Plugin $1 does not support static linking])
+ ],[
+ m4_ifdef([$5],[
+ AC_DEFINE($5)
+ AC_SUBST([plugin_]$2[_static_target], ["yes"])
+ AC_SUBST([plugin_]$2[_shared_target], [""])
+ ])
+ ])
+ ])
+ mysql_plugin_defs="$mysql_plugin_defs, [builtin_]$2[_plugin]"
+ [with_plugin_]$2=yes
+ AC_MSG_RESULT([yes])
+ fi
+ m4_ifdef([$6],[
+ if test -n "$mysql_use_plugin_dir" ; then
+ mysql_plugin_dirs="$mysql_plugin_dirs $6"
+ if test -f "$srcdir/$6/configure" ; then
+ other_configures="$other_configures $6/configure"
+ else
+ AC_CONFIG_FILES($6/Makefile)
+ fi
+ ifelse(m4_substr($6, 0, 8), [storage/],
+ [mysql_se_dirs="$mysql_se_dirs ]m4_substr($6, 8)",
+ m4_substr($6, 0, 7), [plugin/],
+ [mysql_pg_dirs="$mysql_pg_dirs ]m4_substr($6, 7)",
+ [AC_FATAL([don't know how to handle plugin dir ]$6)])
+ fi
+ ])
+ fi
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_PLUGIN_ACTIONS],[
+ ifelse($#, 0, [], $#, 1, [
+ _MYSQL_EMIT_PLUGIN_ACTION([$1])
+ ],[
+ _MYSQL_EMIT_PLUGIN_ACTION([$1])
+ _MYSQL_EMIT_PLUGIN_ACTIONS(m4_shift($@))
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_PLUGIN_ACTION],[
+ __MYSQL_EMIT_PLUGIN_ACTION(
+ [$1],
+ m4_bpatsubst([$1], -, _),
+ [MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1])
+ )
+])
+
+
+AC_DEFUN([__MYSQL_EMIT_PLUGIN_ACTION],[
+ m4_ifdef([$3], [], [
+ if test "X[$with_plugin_]$2" = Xyes; then
+ if test "X[$plugin_]$2[_static_target]" = X -a \
+ "X[$plugin_]$2[_shared_target]" = X; then
+ AC_MSG_ERROR([that's strange, $1 failed sanity check])
+ fi
+ $4
+ fi
+ ])
+])
+
+
+
+dnl ===========================================================================
+dnl Private helper macros
+dnl ===========================================================================
+
+
+dnl SYNOPSIS
+dnl MYSQL_REQUIRE_PLUGIN([name])
+dnl
+dnl DESCRIPTION
+dnl Checks that the specified plugin does exist
+
+AC_DEFUN([MYSQL_REQUIRE_PLUGIN],[
+ _MYSQL_REQUIRE_PLUGIN([$1], [__MYSQL_PLUGIN_]AS_TR_CPP([$1])[__])
+])
+
+define([_MYSQL_REQUIRE_PLUGIN],[
+ ifdef([$2],[
+ ifelse($2, [$1], [], [
+ AC_FATAL([Misspelt MYSQL_PLUGIN declaration for $1])
+ ])
+ ],[
+ AC_FATAL([Missing MYSQL_PLUGIN declaration for $1])
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+
+
+dnl SYNOPSIS
+dnl _MYSQL_EMIT_METAPLUGINS([name,name...])
+dnl
+dnl DESCRIPTION
+dnl Emits shell code for metaplugins
+
+AC_DEFUN([_MYSQL_EMIT_METAPLUGINS], [ifelse($#, 0, [], $#, 1,
+[_MYSQL_EMIT_METAPLUGIN([$1], [__mysql_]m4_bpatsubst($1, -, _)[_plugins__])
+],
+[_MYSQL_EMIT_METAPLUGIN([$1], [__mysql_]m4_bpatsubst($1, -, _)[_plugins__])
+_MYSQL_EMIT_METAPLUGINS(m4_shift($@))])
+])
+
+AC_DEFUN([_MYSQL_EMIT_METAPLUGIN], [
+ [$1] )
+m4_ifdef([$2], [
+ mysql_plugins='m4_bpatsubst($2, :, [ ])'
+],[
+ mysql_plugins=''
+])
+ ;;
+])
+
+
+dnl ---------------------------------------------------------------------------
+
+
+dnl SYNOPSIS
+dnl _MYSQL_PLUGAPPEND([name],[to-append])
+dnl
+dnl DESCRIPTION
+dnl Helper macro for appending to colon-delimited lists
+dnl Optinal 3rd argument is for actions only required when defining
+dnl macro named for the first time.
+
+AC_DEFUN([_MYSQL_PLUGAPPEND],[
+ m4_ifdef([$1],[
+ m4_define([__plugin_append_tmp__], m4_defn([$1]))
+ m4_undefine([$1])
+ m4_define([$1], __plugin_append_tmp__[:$2])
+ m4_undefine([__plugin_append_tmp__])
+ ],[
+ m4_define([$1], [$2])
+ $3
+ ])
+])
+
+
+dnl SYNOPSIS
+dnl _MYSQL_PLUGAPPEND_META([name],[meta,meta...])
+dnl
+dnl DESCRIPTION
+dnl Helper macro for adding plugins to meta plugins
+
+AC_DEFUN([_MYSQL_PLUGAPPEND_META],[
+ ifelse($#, 1, [], [$#:$2], [2:], [], [$2], [all], [
+ AC_FATAL([protected plugin group: all])
+ ], [$2], [none], [
+ AC_FATAL([protected plugin group: none])
+ ],[
+ _MYSQL_PLUGAPPEND([__mysql_$1_configs__],[$2])
+ _MYSQL_PLUGAPPEND([__mysql_]m4_bpatsubst($2, -, _)[_plugins__],[$1], [
+ _MYSQL_PLUGAPPEND([__mysql_metaplugin_list__],[$2])
+ ])
+ _MYSQL_PLUGAPPEND_META([$1], m4_shift(m4_shift($@)))
+ ])
+])
+
+
+dnl ---------------------------------------------------------------------------
+
+
+dnl SYNOPSIS
+dnl MYSQL_LIST_PLUGINS
+dnl
+dnl DESCRIPTION
+dnl Emits formatted list of declared plugins
+
+AC_DEFUN([MYSQL_LIST_PLUGINS],[dnl
+ m4_ifdef([__mysql_plugin_list__],[dnl
+ _MYSQL_LIST_PLUGINS(m4_bpatsubst(__mysql_plugin_list__, :, [,]))dnl
+ ])dnl
+])
+
+AC_DEFUN([_MYSQL_LIST_PLUGINS],[dnl
+ ifelse($#, 0, [], $#, 1, [dnl
+ MYSQL_SHOW_PLUGIN([$1])dnl
+ ],[dnl
+ MYSQL_SHOW_PLUGIN([$1])dnl
+ _MYSQL_LIST_PLUGINS(m4_shift($@))dnl
+ ])dnl
+])
+
+AC_DEFUN([MYSQL_SHOW_PLUGIN],[
+ _MYSQL_SHOW_PLUGIN(
+ [$1],
+ [$1-plugin],
+ [MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DESC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DEFINE_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DIRECTORY_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_STATIC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DYNAMIC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_MANDATORY_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1]),
+ __mysql_[$1]_configs__,
+ )
+])
+
+AC_DEFUN([_MYSQL_SHOW_PLUGIN],[dnl
+ === $3 ===
+ Plugin Name: [$1]
+ Description: $4
+ Supports build: _PLUGIN_BUILD_TYPE([$7],[$8])[]dnl
+m4_ifdef([$12],[
+ Configurations: m4_bpatsubst($12, :, [, ])])[]dnl
+m4_ifdef([$10],[
+ Status: disabled])[]dnl
+m4_ifdef([$9],[
+ Status: mandatory])[]dnl
+])
+
+AC_DEFUN([_PLUGIN_BUILD_TYPE],
+[m4_ifdef([$1],[static ]m4_ifdef([$2],[and dnl
+]))[]m4_ifdef([$2],[dynamic],[m4_ifdef([$1],[],[static])])])
+
+
+dnl ---------------------------------------------------------------------------
+
+
+AC_DEFUN([_MYSQL_EMIT_PLUGINS],[
+ ifelse($#, 0, [], [$#:$1], [1:], [], [
+ m4_ifdef([MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1]), [], [
+ m4_define([MYSQL_PLUGIN_ACTIONS_]AS_TR_CPP([$1]),[ ])
+ ])
+ [$1] )
+ m4_ifdef([MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),[
+ AC_MSG_ERROR([plugin $1 is disabled])
+ ],[
+ _MYSQL_EMIT_PLUGIN_ENABLE([$1], m4_bpatsubst([$1], -, _),
+ [MYSQL_PLUGIN_NAME_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_STATIC_]AS_TR_CPP([$1]),
+ [MYSQL_PLUGIN_DYNAMIC_]AS_TR_CPP([$1]))
+ ])
+ ;;
+ _MYSQL_EMIT_PLUGINS(m4_shift($@))
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_PLUGIN_ENABLE],[
+ m4_ifdef([$5],m4_ifdef([$4],[
+ [mysql_plugin_]$2=yes
+ ],[
+ AC_MSG_WARN([$3 can only be built as a plugin])
+ ]),[
+ [mysql_plugin_]$2=yes
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_PLUGIN_DEPENDS], [
+ ifelse($#, 0, [], [$#:$1], [1:], [], [
+ _MYSQL_EMIT_CHECK_DEPENDS(m4_bpatsubst([$1], -, _),
+ [__mysql_plugdepends_$1__])
+ _MYSQL_EMIT_PLUGIN_DEPENDS(m4_shift($@))
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_CHECK_DEPENDS], [
+ m4_ifdef([$2], [
+ if test "X[$mysql_plugin_]$1" = Xyes -a \
+ "X[$with_plugin_]$1" != Xno -o \
+ "X[$with_plugin_]$1" = Xyes; then
+ _MYSQL_EMIT_PLUGIN_DEPENDENCIES(m4_bpatsubst($2, :, [,]))
+ fi
+ ])
+])
+
+AC_DEFUN([_MYSQL_EMIT_PLUGIN_DEPENDENCIES], [
+ ifelse([$1], [], [], [
+ m4_ifdef([MYSQL_PLUGIN_DISABLED_]AS_TR_CPP([$1]),[
+ AC_MSG_ERROR([depends upon disabled plugin $1])
+ ],[
+ [mysql_plugin_]m4_bpatsubst([$1], -, _)=yes
+ if test "X[$with_plugin_]m4_bpatsubst([$1], -, _)" = Xno; then
+ AC_MSG_ERROR([depends upon disabled plugin $1])
+ fi
+ ])
+ _MYSQL_EMIT_PLUGIN_DEPENDENCIES(m4_shift($@))
+ ])
+])
+
+dnl SYNOPSIS
+dnl _MYSQL_CHECK_PLUGIN_ARGS([plugin],[plugin]...)
+dnl
+dnl DESCRIPTION
+dnl Emits shell script for checking configure arguments
+dnl Arguments to this macro is default value for selected plugins
+
+AC_DEFUN([_MYSQL_CHECK_PLUGIN_ARGS],[
+ __MYSQL_CHECK_PLUGIN_ARGS(m4_default([$1], [none]))
+])
+
+AC_DEFUN([__MYSQL_CHECK_PLUGIN_ARGS],[
+ AC_ARG_WITH([plugins],
+AS_HELP_STRING([--with-plugins=PLUGIN[[[[[,PLUGIN..]]]]]],
+ [Plugins to include in mysqld. (default is: $1) Must be a
+ configuration name or a comma separated list of plugins.])
+AS_HELP_STRING([],
+ [Available configurations are:] dnl
+m4_bpatsubst([none:]m4_ifdef([__mysql_metaplugin_list__],
+ __mysql_metaplugin_list__:)[all], :, [ ])[.])
+AS_HELP_STRING([],
+ [Available plugins are:] dnl
+m4_bpatsubst(__mysql_plugin_list__, :, [ ])[.])
+AS_HELP_STRING([--without-plugin-PLUGIN],
+ [Disable the named plugin from being built. Otherwise, for
+ plugins which are not selected for inclusion in mysqld will be
+ built dynamically (if supported)])
+AS_HELP_STRING([--with-plugin-PLUGIN],
+ [Forces the named plugin to be linked into mysqld statically.]),
+ [mysql_plugins="`echo $withval | tr ',.:;*[]' ' '`"],
+ [mysql_plugins=['$1']])
+
+m4_divert_once([HELP_VAR_END],[
+Description of plugins:
+MYSQL_LIST_PLUGINS])
+
+ case "$mysql_plugins" in
+ all )
+ mysql_plugins='m4_bpatsubst(__mysql_plugin_list__, :, [ ])'
+ ;;
+ none )
+ mysql_plugins=''
+ ;;
+m4_ifdef([__mysql_metaplugin_list__],[
+_MYSQL_EMIT_METAPLUGINS(m4_bpatsubst(__mysql_metaplugin_list__, :, [,]))
+])
+ esac
+
+ for plugin in $mysql_plugins; do
+ case "$plugin" in
+ all | none )
+ AC_MSG_ERROR([bad plugin name: $plugin])
+ ;;
+_MYSQL_EMIT_PLUGINS(m4_bpatsubst(__mysql_plugin_list__, :, [,]))
+ * )
+ AC_MSG_ERROR([unknown plugin: $plugin])
+ ;;
+ esac
+ done
+
+ _MYSQL_EMIT_PLUGIN_DEPENDS(m4_bpatsubst(__mysql_plugin_list__, :, [,]))
+])
+
+dnl ===========================================================================
diff --git a/config/ac-macros/storage.m4 b/config/ac-macros/storage.m4
deleted file mode 100644
index 4148aed818d..00000000000
--- a/config/ac-macros/storage.m4
+++ /dev/null
@@ -1,55 +0,0 @@
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_STORAGE_ENGINE
-dnl
-dnl What it does:
-dnl creates --with-xxx configure option
-dnl adds HAVE_XXX to config.h
-dnl appends &xxx_hton, to the list of hanldertons
-dnl appends a dir to the list of source directories
-dnl appends ha_xxx.cc to the list of handler files
-dnl
-dnl all names above are configurable with reasonable defaults.
-dnl
-dnl ---------------------------------------------------------------------------
-
-AC_DEFUN([MYSQL_STORAGE_ENGINE],
-[_MYSQL_STORAGE_ENGINE(
-[$1], dnl name
-m4_default([$2], [$1 storage engine]), dnl verbose name
-m4_default([$3], [$1-storage-engine]), dnl with-name
-m4_default([$4], no), dnl default
-m4_default([$5], [WITH_]AS_TR_CPP([$1])[_STORAGE_ENGINE]),
-m4_default([$6], $1[_hton]), dnl hton
-m4_default([$7], []), dnl path to the code
-m4_default([$8], [ha_$1.o]), dnl path to the handler in
-m4_default([$9], []), dnl path to extra libraries
-[$10], dnl code-if-set
-)])
-
-AC_DEFUN([_MYSQL_STORAGE_ENGINE],
-[
-AC_ARG_WITH([$3], AS_HELP_STRING([--with-$3], [enable $2 (default is $4)]),
-[], [ [with_]m4_bpatsubst([$3], -, _)=['$4']])
-AC_CACHE_CHECK([whether to use $2], [mysql_cv_use_]m4_bpatsubst([$3], -, _),
-[mysql_cv_use_]m4_bpatsubst([$3], -, _)=[$with_]m4_bpatsubst([$3], -, _))
-AH_TEMPLATE([$5], [Build $2])
-if test "[$mysql_cv_use_]m4_bpatsubst([$3], -, _)" != no; then
-if test "$6" != "no"
-then
- AC_DEFINE([$5])
- mysql_se_decls="${mysql_se_decls},$6"
- mysql_se_htons="${mysql_se_htons},&$6"
- if test "$8" != "no"
- then
- mysql_se_objs="$mysql_se_objs $8"
- fi
- mysql_se_dirs="$mysql_se_dirs $7"
- mysql_se_libs="$mysql_se_libs $9"
-else
- mysql_se_plugins="$mysql_se_plugins $7"
-fi
-$10
-fi
-])
-
-dnl ---------------------------------------------------------------------------
diff --git a/configure.in b/configure.in
index eb3d8153d25..e159a5803f1 100644
--- a/configure.in
+++ b/configure.in
@@ -31,7 +31,7 @@ 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/storage.m4)
+sinclude(config/ac-macros/plugins.m4)
sinclude(config/ac-macros/ha_berkeley.m4)
sinclude(config/ac-macros/ha_ndbcluster.m4)
sinclude(config/ac-macros/large_file.m4)
@@ -51,7 +51,6 @@ romanian russian serbian slovak spanish swedish ukrainian"
#####
#####
-
AC_SUBST(MYSQL_NO_DASH_VERSION)
AC_SUBST(MYSQL_BASE_VERSION)
AC_SUBST(MYSQL_VERSION_ID)
@@ -1623,7 +1622,7 @@ fi
# If we should allow error injection tests
AC_ARG_WITH(error-inject,
- [ --with-error-inject Enable error injection in MySQL Server],
+ AC_HELP_STRING([--with-error-inject],[Enable error injection in MySQL Server]),
[ with_error_inject=$withval ],
[ with_error_inject=no ])
@@ -2196,6 +2195,102 @@ then
fi
AC_MSG_RESULT("$netinet_inc")
+#--------------------------------------------------------------------
+# Check for requested features
+#--------------------------------------------------------------------
+
+MYSQL_CHECK_BIG_TABLES
+MYSQL_CHECK_MAX_INDEXES
+MYSQL_CHECK_REPLICATION
+MYSQL_CHECK_VIO
+MYSQL_CHECK_OPENSSL
+MYSQL_CHECK_YASSL
+
+#--------------------------------------------------------------------
+# Declare our plugin modules
+# Has to be done late, as the plugin may need to check for existence of
+# functions tested above
+#--------------------------------------------------------------------
+
+MYSQL_STORAGE_ENGINE(archive,, [Archive Storage Engine],
+ [Archive Storage Engine], [max,max-no-ndb])
+MYSQL_PLUGIN_DIRECTORY(archive, [storage/archive])
+MYSQL_PLUGIN_STATIC(archive, [libarchive.a])
+MYSQL_PLUGIN_DYNAMIC(archive, [ha_archive.la])
+
+MYSQL_STORAGE_ENGINE(berkeley, berkeley-db, [BerkeleyDB Storage Engine],
+ [Transactional Tables using BerkeleyDB], [max,max-no-ndb])
+MYSQL_PLUGIN_DIRECTORY(berkeley,[storage/bdb])
+MYSQL_PLUGIN_STATIC(berkeley, [[\$(bdb_libs_with_path)]])
+MYSQL_PLUGIN_ACTIONS(berkeley, [MYSQL_SETUP_BERKELEY_DB])
+
+MYSQL_STORAGE_ENGINE(blackhole,,[Blackhole Storage Engine],
+ [Basic Write-only Read-never tables], [max,max-no-ndb])
+MYSQL_PLUGIN_DIRECTORY(blackhole, [storage/blackhole])
+MYSQL_PLUGIN_STATIC(blackhole, [libblackhole.a])
+MYSQL_PLUGIN_DYNAMIC(blackhole, [ha_blackhole.la])
+
+MYSQL_STORAGE_ENGINE(csv,, [CSV Storage Engine],
+ [Stores tables in text CSV format])
+MYSQL_PLUGIN_DIRECTORY(csv, [storage/csv])
+MYSQL_PLUGIN_STATIC(csv, [libcsv.a])
+MYSQL_PLUGIN_MANDATORY(csv) dnl Used for logging
+
+MYSQL_STORAGE_ENGINE(example,, [Example Storage Engine],
+ [Skeleton for Storage Engines for developers], [max,max-no-ndb])
+MYSQL_PLUGIN_DIRECTORY(example, [storage/example])
+MYSQL_PLUGIN_STATIC(example, [libexample.a])
+MYSQL_PLUGIN_DYNAMIC(example, [ha_example.la])
+
+MYSQL_STORAGE_ENGINE(federated,,[Federated Storage Engine],
+ [Connects to tables on remote MySQL servers], [max,max-no-ndb])
+
+MYSQL_PLUGIN(ftexample, [Simple Parser],
+ [Simple full-text parser plugin])
+MYSQL_PLUGIN_DIRECTORY(ftexample, [plugin/fulltext])
+MYSQL_PLUGIN_DYNAMIC(ftexample, [mypluglib.la])
+
+MYSQL_STORAGE_ENGINE(heap,no, [Memory Storage Engine],
+ [Volatile memory based tables])
+MYSQL_PLUGIN_DIRECTORY(heap, [storage/heap])
+MYSQL_PLUGIN_STATIC(heap, [libheap.a])
+MYSQL_PLUGIN_MANDATORY(heap) dnl Memory tables
+
+MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine],
+ [Transactional Tables using InnoDB], [max,max-no-ndb])
+MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase])
+MYSQL_PLUGIN_STATIC(innobase, [libinnobase.a])
+MYSQL_PLUGIN_ACTIONS(innobase, [
+ AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"])
+ AC_SUBST(innodb_system_libs)
+])
+
+MYSQL_STORAGE_ENGINE(myisam,no, [MyISAM Storage Engine],
+ [Traditional non-transactional MySQL tables])
+MYSQL_PLUGIN_DIRECTORY(myisam, [storage/myisam])
+MYSQL_PLUGIN_STATIC(myisam, [libmyisam.a])
+MYSQL_PLUGIN_MANDATORY(myisam) dnl Default
+
+MYSQL_STORAGE_ENGINE(myisammrg,no,[MyISAM MERGE Engine],
+ [Merge multiple MySQL tables into one])
+MYSQL_PLUGIN_DIRECTORY(myisammrg,[storage/myisammrg])
+MYSQL_PLUGIN_STATIC(myisammrg, [libmyisammrg.a])
+MYSQL_PLUGIN_MANDATORY(myisammrg)
+
+MYSQL_STORAGE_ENGINE(ndbcluster, ndbcluster, [Cluster Storage Engine],
+ [High Availability Clustered tables], [max])
+MYSQL_PLUGIN_DIRECTORY(ndbcluster,[storage/ndb])
+MYSQL_PLUGIN_STATIC(ndbcluster, [[\$(ndbcluster_libs) \$(ndbcluster_system_libs) \$(NDB_SCI_LIBS)]])
+MYSQL_PLUGIN_ACTIONS(ndbcluster,[MYSQL_SETUP_NDBCLUSTER])
+
+MYSQL_STORAGE_ENGINE(partition, partition, [Partition Support],
+ [MySQL Partitioning Support], [max,max-no-ndb])
+
+dnl -- ndbcluster requires partition to be enabled
+MYSQL_PLUGIN_DEPENDS(ndbcluster, [partition])
+
+MYSQL_CONFIGURE_PLUGINS([none])
+
# Only build client code?
AC_ARG_WITH(server,
[ --without-server Only build the client.],
@@ -2249,21 +2344,18 @@ fi
tools_dirs=""
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_HELP_STRING([--with-mysqlmanager], [Build the mysqlmanager binary: yes/no (default: build if server is built.)]),,)
+
+if test "$with_mysqlmanager" = "yes" -o \
+ '(' "$with_mysqlmanager:$with_server" = ":yes" -a \
+ -d "$srcdir/server-tools" ')' ; then
+ tools_dirs="$tools_dirs server-tools"
+ AC_CONFIG_FILES(server-tools/Makefile server-tools/instance-manager/Makefile)
+fi
AC_SUBST(tools_dirs)
#MYSQL_CHECK_CPU
-MYSQL_CHECK_VIO
-MYSQL_CHECK_OPENSSL
-MYSQL_CHECK_YASSL
libmysqld_dirs=
linked_libmysqld_targets=
@@ -2428,73 +2520,6 @@ AC_SUBST(readline_basedir)
AC_SUBST(readline_link)
AC_SUBST(readline_h_ln_cmd)
-MYSQL_CHECK_BIG_TABLES
-MYSQL_CHECK_MAX_INDEXES
-MYSQL_CHECK_REPLICATION
-
-MYSQL_STORAGE_ENGINE(innobase,,innodb,,,,innobase,ha_innodb.o,[ dnl
- \$(top_builddir)/storage/innobase/usr/libusr.a dnl
- \$(top_builddir)/storage/innobase/srv/libsrv.a dnl
- \$(top_builddir)/storage/innobase/dict/libdict.a dnl
- \$(top_builddir)/storage/innobase/que/libque.a dnl
- \$(top_builddir)/storage/innobase/srv/libsrv.a dnl
- \$(top_builddir)/storage/innobase/ibuf/libibuf.a dnl
- \$(top_builddir)/storage/innobase/row/librow.a dnl
- \$(top_builddir)/storage/innobase/pars/libpars.a dnl
- \$(top_builddir)/storage/innobase/btr/libbtr.a dnl
- \$(top_builddir)/storage/innobase/trx/libtrx.a dnl
- \$(top_builddir)/storage/innobase/read/libread.a dnl
- \$(top_builddir)/storage/innobase/usr/libusr.a dnl
- \$(top_builddir)/storage/innobase/buf/libbuf.a dnl
- \$(top_builddir)/storage/innobase/ibuf/libibuf.a dnl
- \$(top_builddir)/storage/innobase/eval/libeval.a dnl
- \$(top_builddir)/storage/innobase/log/liblog.a dnl
- \$(top_builddir)/storage/innobase/fsp/libfsp.a dnl
- \$(top_builddir)/storage/innobase/fut/libfut.a dnl
- \$(top_builddir)/storage/innobase/fil/libfil.a dnl
- \$(top_builddir)/storage/innobase/lock/liblock.a dnl
- \$(top_builddir)/storage/innobase/mtr/libmtr.a dnl
- \$(top_builddir)/storage/innobase/page/libpage.a dnl
- \$(top_builddir)/storage/innobase/rem/librem.a dnl
- \$(top_builddir)/storage/innobase/thr/libthr.a dnl
- \$(top_builddir)/storage/innobase/sync/libsync.a dnl
- \$(top_builddir)/storage/innobase/data/libdata.a dnl
- \$(top_builddir)/storage/innobase/mach/libmach.a dnl
- \$(top_builddir)/storage/innobase/ha/libha.a dnl
- \$(top_builddir)/storage/innobase/dyn/libdyn.a dnl
- \$(top_builddir)/storage/innobase/mem/libmem.a dnl
- \$(top_builddir)/storage/innobase/sync/libsync.a dnl
- \$(top_builddir)/storage/innobase/ut/libut.a dnl
- \$(top_builddir)/storage/innobase/os/libos.a dnl
- \$(top_builddir)/storage/innobase/ut/libut.a],[
- AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"])
- AC_SUBST(innodb_includes)
- AC_SUBST(innodb_libs)
- AC_SUBST(innodb_system_libs)
- other_configures="$other_configures storage/innobase/configure"
-])
-
-MYSQL_STORAGE_ENGINE(berkeley,,berkeley-db,,,,bdb,,,[
- MYSQL_SETUP_BERKELEY_DB
-])
-MYSQL_STORAGE_ENGINE(example,,,,,,example,no,
- \$(top_builddir)/storage/example/libexample.a,[
- AC_CONFIG_FILES(storage/example/Makefile)
-])
-MYSQL_STORAGE_ENGINE(archive,,,,,,archive,,
- \$(top_builddir)/storage/archive/libarchive.a, [
- AC_CONFIG_FILES(storage/archive/Makefile)
-])
-MYSQL_STORAGE_ENGINE(csv,,,"yes",,tina_hton,csv,no,
- \$(top_builddir)/storage/csv/libcsv.a,[
- AC_CONFIG_FILES(storage/csv/Makefile)
-])
-MYSQL_STORAGE_ENGINE(blackhole)
-MYSQL_STORAGE_ENGINE(federated)
-MYSQL_STORAGE_ENGINE(ndbcluster,,ndbcluster,,,,ndb,,,[
- MYSQL_SETUP_NDBCLUSTER
-])
-MYSQL_STORAGE_ENGINE(partition,,partition)
# If we have threads generate some library functions and test programs
sql_server_dirs=
@@ -2551,7 +2576,7 @@ then
AC_SUBST(THREAD_LOBJECTS)
server_scripts="mysqld_safe mysql_install_db"
sql_server_dirs="strings mysys dbug extra regex"
- mysql_se_dirs="myisam myisammrg heap $mysql_se_dirs"
+
sql_server="$sql_server vio sql"
fi
@@ -2567,12 +2592,9 @@ AC_SUBST(sql_server)
AC_SUBST(thread_dirs)
AC_SUBST(server_scripts)
-AC_SUBST(mysql_se_dirs)
-AC_SUBST(mysql_se_libs)
-AC_SUBST(mysql_se_objs)
-AC_SUBST(mysql_se_htons)
-AC_SUBST(mysql_se_decls)
-AC_SUBST(mysql_se_plugins)
+AC_SUBST(mysql_plugin_dirs)
+AC_SUBST(mysql_plugin_libs)
+AC_SUBST(mysql_plugin_defs)
# Now that sql_client_dirs and sql_server_dirs are stable, determine the union.
@@ -2614,25 +2636,18 @@ AC_SUBST(MAKE_BINARY_DISTRIBUTION_OPTIONS)
# Output results
AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
- unittest/Makefile dnl
- unittest/mytap/Makefile unittest/mytap/t/Makefile dnl
+ unittest/Makefile unittest/mytap/Makefile unittest/mytap/t/Makefile dnl
unittest/mysys/Makefile unittest/examples/Makefile dnl
- strings/Makefile regex/Makefile storage/Makefile storage/heap/Makefile dnl
- storage/myisam/Makefile storage/myisammrg/Makefile dnl
+ strings/Makefile regex/Makefile storage/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/handlerton.cc sql-common/Makefile dnl
- dbug/Makefile scripts/Makefile dnl
- include/Makefile dnl
- server-tools/Makefile server-tools/instance-manager/Makefile dnl
+ sql/sql_builtin.cc sql-common/Makefile dnl
+ dbug/Makefile scripts/Makefile include/Makefile dnl
tests/Makefile Docs/Makefile support-files/Makefile dnl
support-files/MacOSX/Makefile mysql-test/Makefile dnl
mysql-test/ndb/Makefile netware/Makefile dnl
- include/mysql_version.h dnl
- plugin/Makefile dnl
- plugin/fulltext/Makefile dnl
- win/Makefile)
+ include/mysql_version.h plugin/Makefile win/Makefile)
AC_CONFIG_COMMANDS([default], , test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h)
AC_OUTPUT
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 913272b2a11..40cadad0017 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -176,7 +176,7 @@ typedef struct my_charset_handler_st
uint (*lengthsp)(struct charset_info_st *, const char *ptr, uint length);
uint (*numcells)(struct charset_info_st *, const char *b, const char *e);
- /* Unicode convertion */
+ /* Unicode conversion */
int (*mb_wc)(struct charset_info_st *cs,my_wc_t *wc,
const unsigned char *s,const unsigned char *e);
int (*wc_mb)(struct charset_info_st *cs,my_wc_t wc,
@@ -186,7 +186,7 @@ typedef struct my_charset_handler_st
int (*ctype)(struct charset_info_st *cs, int *ctype,
const unsigned char *s, const unsigned char *e);
- /* Functions for case and sort convertion */
+ /* Functions for case and sort conversion */
void (*caseup_str)(struct charset_info_st *, char *);
void (*casedn_str)(struct charset_info_st *, char *);
uint (*caseup)(struct charset_info_st *, char *src, uint srclen,
@@ -204,7 +204,7 @@ typedef struct my_charset_handler_st
void (*fill)(struct charset_info_st *, char *to, uint len, int fill);
- /* String-to-number convertion routines */
+ /* String-to-number conversion routines */
long (*strntol)(struct charset_info_st *, const char *s, uint l,
int base, char **e, int *err);
ulong (*strntoul)(struct charset_info_st *, const char *s, uint l,
diff --git a/include/my_base.h b/include/my_base.h
index b9a806cc02f..e014f7c33b7 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -231,6 +231,7 @@ enum ha_base_keytype {
#define HA_VAR_LENGTH_KEY 8
#define HA_NULL_PART_KEY 64
#define HA_USES_PARSER 16384 /* Fulltext index uses [pre]parser */
+#define HA_USES_BLOCK_SIZE ((uint) 32768)
#define HA_SORT_ALLOWS_SAME 512 /* Intern bit when sorting records */
/*
Key has a part that can have end space. If this is an unique key
diff --git a/include/my_sys.h b/include/my_sys.h
index 41851b91cbd..1540d820777 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -558,6 +558,7 @@ extern File my_open(const char *FileName,int Flags,myf MyFlags);
extern File my_register_filename(File fd, const char *FileName,
enum file_type type_of_file,
uint error_message_number, myf MyFlags);
+extern void my_print_open_files(void);
extern File my_create(const char *FileName,int CreateFlags,
int AccessFlags, myf MyFlags);
extern int my_close(File Filedes,myf MyFlags);
@@ -601,6 +602,11 @@ extern char *_my_strndup(const byte *from, uint length,
const char *sFile, uint uLine,
myf MyFlag);
+/* implemented in my_memmem.c */
+extern void *my_memmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+
+
#ifdef __WIN__
extern int my_access(const char *path, int amode);
extern File my_sopen(const char *path, int oflag, int shflag, int pmode);
@@ -642,6 +648,12 @@ extern void allow_break(void);
#define allow_break()
#endif
+#ifdef EXTRA_DEBUG
+void my_print_open_files();
+#else
+#define my_print_open_files()
+#endif
+
extern my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist);
extern char *my_tmpdir(MY_TMPDIR *tmpdir);
extern void free_tmpdir(MY_TMPDIR *tmpdir);
@@ -812,6 +824,7 @@ extern int unpackfrm(const void **, uint *, const void *);
extern ha_checksum my_checksum(ha_checksum crc, const byte *mem, uint count);
extern uint my_bit_log2(ulong value);
+extern uint32 my_round_up_to_next_power(uint32 v);
extern uint my_count_bits(ulonglong v);
extern uint my_count_bits_ushort(ushort v);
extern void my_sleep(ulong m_seconds);
diff --git a/include/my_tree.h b/include/my_tree.h
index 14d8593b6dc..03dc9d5c829 100644
--- a/include/my_tree.h
+++ b/include/my_tree.h
@@ -84,7 +84,7 @@ TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size,
void *tree_search(TREE *tree, void *key, void *custom_arg);
int tree_walk(TREE *tree,tree_walk_action action,
void *argument, TREE_WALK visit);
-int tree_delete(TREE *tree, void *key, void *custom_arg);
+int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg);
void *tree_search_key(TREE *tree, const void *key,
TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
enum ha_rkey_function flag, void *custom_arg);
diff --git a/include/myisam.h b/include/myisam.h
index 5116f48eeb5..db1a7bd984d 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -192,7 +192,7 @@ typedef struct st_mi_keydef /* Key definition with open & info */
uint16 keylength; /* Tot length of keyparts (auto) */
uint16 minlength; /* min length of (packed) key (auto) */
uint16 maxlength; /* max length of (packed) key (auto) */
- uint16 block_size; /* block_size (auto) */
+ uint16 block_size_index; /* block_size (auto) */
uint32 version; /* For concurrent read/write */
uint32 ftparser_nr; /* distinct ftparser number */
diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h
index a7b3606061f..ab5ca6e7be4 100644
--- a/include/mysql/plugin.h
+++ b/include/mysql/plugin.h
@@ -37,10 +37,25 @@
be a st_mysql_plugin struct for each plugin to be declared.
*/
-#define mysql_declare_plugin \
-int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
-int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
+
+#ifndef MYSQL_DYNAMIC_PLUGIN
+#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
+int VERSION= MYSQL_PLUGIN_INTERFACE_VERSION; \
+int PSIZE= sizeof(struct st_mysql_plugin); \
+struct st_mysql_plugin DECLS[]= {
+#else
+#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
+int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
+int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
struct st_mysql_plugin _mysql_plugin_declarations_[]= {
+#endif
+
+#define mysql_declare_plugin(NAME) \
+__MYSQL_DECLARE_PLUGIN(NAME, \
+ builtin_ ## NAME ## _plugin_interface_version, \
+ builtin_ ## NAME ## _sizeof_struct_st_plugin, \
+ builtin_ ## NAME ## _plugin)
+
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0,0}}
/*
diff --git a/include/mysys_err.h b/include/mysys_err.h
index 341e6950792..9f104357f41 100644
--- a/include/mysys_err.h
+++ b/include/mysys_err.h
@@ -62,7 +62,8 @@ extern const char * NEAR globerrs[]; /* my_error_messages is here */
#define EE_SYNC 27
#define EE_UNKNOWN_COLLATION 28
#define EE_FILENOTFOUND 29
-#define EE_ERROR_LAST 29 /*Copy last error nr.*/
+#define EE_FILE_NOT_CLOSED 30
+#define EE_ERROR_LAST 30 /* Copy last error nr */
/* Add error numbers before EE_ERROR_LAST and change it accordingly. */
/* exit codes for all MySQL programs */
diff --git a/include/violite.h b/include/violite.h
index b48f3724f5b..de2ae5386c0 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -132,6 +132,7 @@ struct st_VioSSLAcceptorFd
const char *ca_file,const char *ca_path,
const char *cipher);
Vio *new_VioSSL(struct st_VioSSLAcceptorFd *fd, Vio *sd, int state);
+void free_vio_ssl_acceptor_fd(struct st_VioSSLAcceptorFd *fd);
#endif /* HAVE_OPENSSL */
#ifdef HAVE_SMEM
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index a869a3ccfe9..dab99d7509e 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -44,7 +44,10 @@ libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
noinst_HEADERS = embedded_priv.h emb_qcache.h
sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
- ha_heap.cc ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \
+ ha_heap.cc ha_myisam.cc ha_myisammrg.cc \
+ ha_innodb.cc ha_berkeley.cc ha_federated.cc ha_ndbcluster.cc \
+ ha_ndbcluster_binlog.cc ha_partition.cc \
+ handler.cc sql_handler.cc \
hostname.cc init.cc password.c \
item.cc item_buff.cc item_cmpfunc.cc item_create.cc \
item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \
@@ -65,17 +68,12 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
spatial.cc gstream.cc sql_help.cc tztime.cc sql_cursor.cc \
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
- event_executor.cc event.cc event_timed.cc \
- rpl_filter.cc sql_partition.cc handlerton.cc sql_plugin.cc \
- sql_tablespace.cc \
- rpl_injector.cc my_user.c partition_info.cc
+ event_executor.cc event.cc event_timed.cc \
+ rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
+ sql_tablespace.cc \
+ rpl_injector.cc my_user.c partition_info.cc
libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
-EXTRA_libmysqld_a_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \
- ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \
- ha_ndbcluster_binlog.cc \
- ha_partition.cc
-libmysqld_a_DEPENDENCIES= @mysql_se_objs@
libmysqld_a_SOURCES=
sqlstoragesources = $(EXTRA_libmysqld_a_SOURCES)
@@ -85,15 +83,11 @@ sql_yacc.cc sql_yacc.h: $(top_srcdir)/sql/sql_yacc.yy
# The following libraries should be included in libmysqld.a
INC_LIB= $(top_builddir)/regex/libregex.a \
- $(top_builddir)/storage/myisam/libmyisam.a \
- $(top_builddir)/storage/myisammrg/libmyisammrg.a \
- $(top_builddir)/storage/archive/libarchive.a \
- $(top_builddir)/storage/heap/libheap.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/strings/libmystrings.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/vio/libvio.a \
- @mysql_se_libs@ \
+ @mysql_plugin_libs@ \
$(yassl_las)
if HAVE_YASSL
@@ -173,10 +167,13 @@ link_sources:
rm -f $$f; \
@LN_CP_F@ $(top_srcdir)/libmysql/$$f $$f; \
done; \
- for f in $(sqlstoragesources); do \
- rm -f $$f; \
- @LN_CP_F@ `find $(srcdir)/../sql -name $$f` $$f; \
- done; \
+ if test -n "$(sqlstoragesources)" ; \
+ then \
+ for f in "$(sqlstoragesources)"; do \
+ rm -f "$$f"; \
+ @LN_CP_F@ `find $(srcdir)/../sql -name "$$f"` "$$f"; \
+ done; \
+ fi; \
rm -f client_settings.h; \
@LN_CP_F@ $(top_srcdir)/libmysql/client_settings.h client_settings.h
diff --git a/mysql-test/extra/rpl_tests/rpl_failed_optimize.test b/mysql-test/extra/rpl_tests/rpl_failed_optimize.test
index 598f9746fab..0c537ee188d 100644
--- a/mysql-test/extra/rpl_tests/rpl_failed_optimize.test
+++ b/mysql-test/extra/rpl_tests/rpl_failed_optimize.test
@@ -17,3 +17,8 @@ OPTIMIZE TABLE non_existing;
sync_slave_with_master;
# End of 4.1 tests
+
+connection master;
+select * from t1;
+commit;
+drop table t1;
diff --git a/mysql-test/include/have_ndb.inc b/mysql-test/include/have_ndb.inc
index 721d79392b7..8c277ea82a0 100644
--- a/mysql-test/include/have_ndb.inc
+++ b/mysql-test/include/have_ndb.inc
@@ -5,6 +5,8 @@ show variables like "have_ndbcluster";
enable_query_log;
# Check that NDB is installed and known to be working
+# This will disable ndb from the shell script 'mysql-test-run'
+
-- require r/have_ndb_status_ok.require
disable_query_log;
eval select "$NDB_STATUS_OK" as ndb_status_ok;
diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl
index 4587c8bc385..f2da89355f7 100644
--- a/mysql-test/lib/mtr_report.pl
+++ b/mysql-test/lib/mtr_report.pl
@@ -157,6 +157,7 @@ sub mtr_report_stats ($) {
my $tot_passed= 0;
my $tot_failed= 0;
my $tot_tests= 0;
+ my $found_problems= 0; # Some warnings are errors...
foreach my $tinfo (@$tests)
{
@@ -214,10 +215,11 @@ sub mtr_report_stats ($) {
}
else
{
- my $found_problems= 0; # Some warnings are errors...
-
# We report different types of problems in order
- foreach my $pattern ( "^Warning:", "^Error:", "^==.* at 0x" )
+ foreach my $pattern ( "^Warning:", "^Error:", "^==.* at 0x",
+ "InnoDB: Warning", "missing DBUG_RETURN",
+ "mysqld: Warning",
+ "Attempting backtrace", "Assertion .* failed" )
{
foreach my $errlog ( sort glob("$::opt_vardir/log/*.err") )
{
@@ -231,7 +233,8 @@ sub mtr_report_stats ($) {
# Skip some non fatal warnings from the log files
if ( /Warning:\s+Table:.* on (delete|rename)/ or
/Warning:\s+Setting lower_case_table_names=2/ or
- /Warning:\s+One can only use the --user.*root/ )
+ /Warning:\s+One can only use the --user.*root/ or
+ /InnoDB: Warning: we did not need to do crash recovery/)
{
next; # Skip these lines
}
@@ -242,11 +245,11 @@ sub mtr_report_stats ($) {
}
}
}
- if ( $found_problems )
- {
- mtr_warning("Got errors/warnings while running tests, please examine",
- "\"$warnlog\" for details.");
- }
+ }
+ if ( $found_problems )
+ {
+ mtr_warning("Got errors/warnings while running tests, please examine",
+ "\"$warnlog\" for details.");
}
}
}
@@ -266,6 +269,9 @@ sub mtr_report_stats ($) {
}
}
print "\n";
+ }
+ if ( $tot_failed != 0 || $found_problems)
+ {
mtr_error("there where failing test cases");
}
}
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 30ac61c80e8..0087459e1dd 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -1224,17 +1224,20 @@ sub environment_setup () {
$ENV{MTR_BUILD_THREAD}= 0 unless $ENV{MTR_BUILD_THREAD}; # Set if not set
# We are nice and report a bit about our settings
- print "Using MTR_BUILD_THREAD = $ENV{MTR_BUILD_THREAD}\n";
- print "Using MASTER_MYPORT = $ENV{MASTER_MYPORT}\n";
- print "Using MASTER_MYPORT1 = $ENV{MASTER_MYPORT1}\n";
- print "Using SLAVE_MYPORT = $ENV{SLAVE_MYPORT}\n";
- print "Using SLAVE_MYPORT1 = $ENV{SLAVE_MYPORT1}\n";
- print "Using SLAVE_MYPORT2 = $ENV{SLAVE_MYPORT2}\n";
- print "Using NDBCLUSTER_PORT = $ENV{NDBCLUSTER_PORT}\n";
- print "Using NDBCLUSTER_PORT_SLAVE = $ENV{NDBCLUSTER_PORT_SLAVE}\n";
- print "Using IM_PORT = $ENV{IM_PORT}\n";
- print "Using IM_MYSQLD1_PORT = $ENV{IM_MYSQLD1_PORT}\n";
- print "Using IM_MYSQLD2_PORT = $ENV{IM_MYSQLD2_PORT}\n";
+ if (!$opt_extern)
+ {
+ print "Using MTR_BUILD_THREAD = $ENV{MTR_BUILD_THREAD}\n";
+ print "Using MASTER_MYPORT = $ENV{MASTER_MYPORT}\n";
+ print "Using MASTER_MYPORT1 = $ENV{MASTER_MYPORT1}\n";
+ print "Using SLAVE_MYPORT = $ENV{SLAVE_MYPORT}\n";
+ print "Using SLAVE_MYPORT1 = $ENV{SLAVE_MYPORT1}\n";
+ print "Using SLAVE_MYPORT2 = $ENV{SLAVE_MYPORT2}\n";
+ print "Using NDBCLUSTER_PORT = $ENV{NDBCLUSTER_PORT}\n";
+ print "Using NDBCLUSTER_PORT_SLAVE = $ENV{NDBCLUSTER_PORT_SLAVE}\n";
+ print "Using IM_PORT = $ENV{IM_PORT}\n";
+ print "Using IM_MYSQLD1_PORT = $ENV{IM_MYSQLD1_PORT}\n";
+ print "Using IM_MYSQLD2_PORT = $ENV{IM_MYSQLD2_PORT}\n";
+ }
}
@@ -1399,7 +1402,7 @@ sub check_running_as_root () {
sub check_ssl_support () {
- if ($opt_skip_ssl)
+ if ($opt_skip_ssl || $opt_extern)
{
mtr_report("Skipping SSL");
$opt_ssl_supported= 0;
@@ -1857,7 +1860,7 @@ sub mysql_install_db () {
}
}
- if ( ndbcluster_install_slave() )
+ if ( $use_slaves and ndbcluster_install_slave() )
{
if ( $opt_force)
{
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 7e1ae58a406..f56099f3a49 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -205,6 +205,7 @@ TOT_SKIP=0
TOT_PASS=0
TOT_FAIL=0
TOT_TEST=0
+GOT_WARNINGS=0
USERT=0
SYST=0
REALT=0
@@ -1072,22 +1073,21 @@ report_stats () {
#
$RM -f $MY_LOG_DIR/warnings $MY_LOG_DIR/warnings.tmp
# Remove some non fatal warnings from the log files
- $SED -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' \
+ $SED -e 's!Warning: Table:.* on delete!!g' -e 's!Warning: Setting lower_case_table_names=2!!g' -e 's!Warning: One can only use the --user.*root!!g' -e 's|InnoDB: Warning: we did not need to do crash recovery||g' \
$MY_LOG_DIR/*.err \
| $SED -e 's!Warning: Table:.* on rename!!g' \
> $MY_LOG_DIR/warnings.tmp
- found_error=0
# Find errors
- for i in "^Warning:" "^Error:" "^==.* at 0x" "InnoDB: Warning" "missing DBUG_RETURN"
+ for i in "^Warning:" "^Error:" "^==.* at 0x" "InnoDB: Warning" "missing DBUG_RETURN" "mysqld: Warning" "Attempting backtrace" "Assertion .* failed"
do
if $GREP "$i" $MY_LOG_DIR/warnings.tmp >> $MY_LOG_DIR/warnings
then
- found_error=1
+ GOT_WARNINGS=1
fi
done
$RM -f $MY_LOG_DIR/warnings.tmp
- if [ $found_error = "1" ]
+ if [ $GOT_WARNINGS = "1" ]
then
echo "WARNING: Got errors/warnings while running tests. Please examine"
echo "$MY_LOG_DIR/warnings for details."
@@ -2300,6 +2300,8 @@ if [ $TOT_FAIL -ne 0 ]; then
$ECHO "mysql-test-run in $TEST_MODE mode: *** Failing the test(s):$FAILED_CASES"
$ECHO
exit 1
-else
- exit 0
fi
+if [ $GOT_WARNINGS -ne 0 ]; then
+ exit 1
+fi
+exit 0
diff --git a/mysql-test/r/analyze.result b/mysql-test/r/analyze.result
index 65c6955a959..fc267cb598d 100644
--- a/mysql-test/r/analyze.result
+++ b/mysql-test/r/analyze.result
@@ -46,4 +46,12 @@ Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_
execute stmt1;
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
deallocate prepare stmt1;
+create temporary table t1(a int, index(a));
+insert into t1 values('1'),('2'),('3'),('4'),('5');
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 1 a 1 a A 5 NULL NULL YES BTREE
drop table t1;
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index ddfeeac77b5..05f1c967e77 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -186,8 +186,8 @@ a b a b a b
explain select * from t1,t2,t3 where t1.a=t2.a AND t2.b=t3.a and t1.b=t3.b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3
-1 SIMPLE t2 index PRIMARY PRIMARY 8 NULL 3 Using where; Using index
-1 SIMPLE t3 index PRIMARY PRIMARY 8 NULL 3 Using where; Using index
+1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using index
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 8 test.t2.b,test.t1.b 1 Using index
delete t2.*,t3.* from t1,t2,t3 where t1.a=t2.a AND t2.b=t3.a and t1.b=t3.b;
select * from t3;
a b
diff --git a/mysql-test/r/exampledb.result b/mysql-test/r/exampledb.result
index 9bfb77c1c0b..6eea24e2e1f 100644
--- a/mysql-test/r/exampledb.result
+++ b/mysql-test/r/exampledb.result
@@ -1,3 +1,5 @@
+drop database if exists events_test;
+drop database if exists events_test2;
drop table if exists t1;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result
index a100266978b..7b944558a62 100644
--- a/mysql-test/r/heap_btree.result
+++ b/mysql-test/r/heap_btree.result
@@ -246,3 +246,13 @@ DELETE from t1 where a < 100;
SELECT * from t1;
a
DROP TABLE t1;
+CREATE TABLE t1(val INT, KEY USING BTREE(val)) ENGINE=memory;
+INSERT INTO t1 VALUES(0);
+SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
+INDEX_LENGTH
+21
+UPDATE t1 SET val=1;
+SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
+INDEX_LENGTH
+21
+DROP TABLE t1;
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index 5e915b5742c..898dd64b794 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -50,6 +50,7 @@ KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
PROCESSLIST
+REFERENTIAL_CONSTRAINTS
ROUTINES
SCHEMATA
SCHEMA_PRIVILEGES
@@ -745,7 +746,7 @@ CREATE TABLE t_crashme ( f1 BIGINT);
CREATE VIEW a1 (t_CRASHME) AS SELECT f1 FROM t_crashme GROUP BY f1;
CREATE VIEW a2 AS SELECT t_CRASHME FROM a1;
count(*)
-112
+113
drop view a2, a1;
drop table t_crashme;
select table_schema,table_name, column_name from
@@ -759,6 +760,7 @@ information_schema PARTITIONS PARTITION_EXPRESSION
information_schema PARTITIONS SUBPARTITION_EXPRESSION
information_schema PARTITIONS PARTITION_DESCRIPTION
information_schema PLUGINS PLUGIN_DESCRIPTION
+information_schema PROCESSLIST INFO
information_schema ROUTINES ROUTINE_DEFINITION
information_schema ROUTINES SQL_MODE
information_schema TRIGGERS ACTION_CONDITION
@@ -832,6 +834,7 @@ COLUMN_PRIVILEGES TABLE_NAME select
FILES TABLE_NAME select
KEY_COLUMN_USAGE TABLE_NAME select
PARTITIONS TABLE_NAME select
+REFERENTIAL_CONSTRAINTS TABLE_NAME select
STATISTICS TABLE_NAME select
TABLES TABLE_NAME select
TABLE_CONSTRAINTS TABLE_NAME select
@@ -843,7 +846,7 @@ flush privileges;
SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
table_schema count(*)
cluster 1
-information_schema 22
+information_schema 23
mysql 21
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row
diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result
index 584e1701a14..37537e257da 100644
--- a/mysql-test/r/information_schema_db.result
+++ b/mysql-test/r/information_schema_db.result
@@ -13,6 +13,7 @@ KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
PROCESSLIST
+REFERENTIAL_CONSTRAINTS
ROUTINES
SCHEMATA
SCHEMA_PRIVILEGES
diff --git a/mysql-test/r/information_schema_inno.result b/mysql-test/r/information_schema_inno.result
index fb6584673f6..9bb3185c6fb 100644
--- a/mysql-test/r/information_schema_inno.result
+++ b/mysql-test/r/information_schema_inno.result
@@ -25,3 +25,34 @@ NULL test PRIMARY NULL test t3 id 1 NULL NULL NULL NULL
NULL test t3_ibfk_1 NULL test t3 id 1 1 test t2 t1_id
NULL test t3_ibfk_1 NULL test t3 t2_id 2 2 test t2 id
drop table t3, t2, t1;
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT NOT NULL,
+PRIMARY KEY(a1, a2)) ENGINE=INNODB;
+CREATE TABLE t2(b1 INT, b2 INT, INDEX (b1, b2),
+CONSTRAINT A1
+FOREIGN KEY (b1, b2) REFERENCES t1(a1, a2)
+ON UPDATE CASCADE ON DELETE NO ACTION) ENGINE=INNODB;
+CREATE TABLE t3(b1 INT, b2 INT, INDEX (b1, b2),
+CONSTRAINT A2
+FOREIGN KEY (b1, b2) REFERENCES t2(b1, b2)
+ON UPDATE SET NULL ON DELETE RESTRICT) ENGINE=INNODB;
+CREATE TABLE t4(b1 INT, b2 INT, INDEX (b1, b2),
+CONSTRAINT A3
+FOREIGN KEY (b1, b2) REFERENCES t3(b1, b2)
+ON UPDATE NO ACTION ON DELETE SET NULL) ENGINE=INNODB;
+CREATE TABLE t5(b1 INT, b2 INT, INDEX (b1, b2),
+CONSTRAINT A4
+FOREIGN KEY (b1, b2) REFERENCES t4(b1, b2)
+ON UPDATE RESTRICT ON DELETE CASCADE) ENGINE=INNODB;
+select a.CONSTRAINT_SCHEMA, b.TABLE_NAME, CONSTRAINT_TYPE,
+b.CONSTRAINT_NAME, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME,
+MATCH_OPTION, UPDATE_RULE, DELETE_RULE
+from information_schema.TABLE_CONSTRAINTS a,
+information_schema.REFERENTIAL_CONSTRAINTS b
+where a.CONSTRAINT_SCHEMA = 'test' and a.CONSTRAINT_SCHEMA = b.CONSTRAINT_SCHEMA and
+a.CONSTRAINT_NAME = b.CONSTRAINT_NAME;
+CONSTRAINT_SCHEMA TABLE_NAME CONSTRAINT_TYPE CONSTRAINT_NAME UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE
+test t2 FOREIGN KEY A1 test t1 NONE CASCADE NO ACTION
+test t3 FOREIGN KEY A2 test t2 NONE SET NULL RESTRICT
+test t4 FOREIGN KEY A3 test t3 NONE NO ACTION SET NULL
+test t5 FOREIGN KEY A4 test t4 NONE RESTRICT CASCADE
+drop tables t5, t4, t3, t2, t1;
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index f32d7ee264a..7ae87e42b8c 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -3455,3 +3455,12 @@ SELECT p0.a FROM t2 p0 WHERE BINARY p0.b = 'customer_over';
a
1
drop table t2, t1;
+create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
+ERROR HY000: The used table type doesn't support SPATIAL indexes
+CREATE TABLE t1 ( a int ) ENGINE=innodb;
+BEGIN;
+INSERT INTO t1 VALUES (1);
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+DROP TABLE t1;
diff --git a/mysql-test/r/myisam-system.result b/mysql-test/r/myisam-system.result
new file mode 100644
index 00000000000..e0629d955ae
--- /dev/null
+++ b/mysql-test/r/myisam-system.result
@@ -0,0 +1,13 @@
+drop table if exists t1,t2;
+create table t1 (a int) engine=myisam;
+drop table if exists t1;
+Warnings:
+Error 2 Can't find file: 't1' (errno: 2)
+create table t1 (a int) engine=myisam;
+drop table t1;
+Got one of the listed errors
+create table t1 (a int) engine=myisam;
+drop table t1;
+Got one of the listed errors
+drop table t1;
+ERROR 42S02: Unknown table 't1'
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index 60836408698..8976c98136b 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -1344,18 +1344,6 @@ drop table t1;
create table t1 (v varchar(65535));
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
set storage_engine=MyISAM;
-create table t1 (a int) engine=myisam;
-drop table if exists t1;
-Warnings:
-Error 2 Can't find file: 't1' (errno: 2)
-create table t1 (a int) engine=myisam;
-drop table t1;
-Got one of the listed errors
-create table t1 (a int) engine=myisam;
-drop table t1;
-Got one of the listed errors
-drop table t1;
-ERROR 42S02: Unknown table 't1'
set @save_concurrent_insert=@@concurrent_insert;
set global concurrent_insert=1;
create table t1 (a int);
@@ -1433,3 +1421,157 @@ create table t3 (c1 int) engine=myisam pack_keys=default;
create table t4 (c1 int) engine=myisam pack_keys=2;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '2' at line 1
drop table t1, t2, t3;
+create table t1 (a int not null, key `a` key_block_size=1024 (a));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ KEY `a` KEY_BLOCK_SIZE=1024 (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set @@new=1;
+create table t1 (a int not null, key `a` (a) key_block_size=1024);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null, key `a` (a) key_block_size=2048);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=2048
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a varchar(2048), key `a` (a));
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`(1000))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a varchar(2048), key `a` (a) key_block_size=1024);
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=4096
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=1024;
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`),
+ KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=1024
+alter table t1 key_block_size=2048;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024,
+ KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2048
+alter table t1 add c int, add key (c);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024,
+ KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096,
+ KEY `c` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2048
+alter table t1 key_block_size=0;
+alter table t1 add d int, add key (d);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024,
+ KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096,
+ KEY `c` (`c`) KEY_BLOCK_SIZE=2048,
+ KEY `d` (`d`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=8192;
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`),
+ KEY `b` (`b`(1000))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8192
+drop table t1;
+create table t1 (a int not null, b varchar(2048), key (a) key_block_size=1024, key(b)) key_block_size=8192;
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024,
+ KEY `b` (`b`(1000))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8192
+drop table t1;
+create table t1 (a int not null, b int, key (a) key_block_size=1024, key(b) key_block_size=8192) key_block_size=16384;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024,
+ KEY `b` (`b`) KEY_BLOCK_SIZE=8192
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=16384
+drop table t1;
+create table t1 (a int not null, key `a` (a) key_block_size=512);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=1024
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a varchar(2048), key `a` (a) key_block_size=1000000000000000000);
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(2048) DEFAULT NULL,
+ KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=4096
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null, key `a` (a) key_block_size=1025);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ KEY `a` (`a`) KEY_BLOCK_SIZE=2048
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int not null, key key_block_size=1024 (a));
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '=1024 (a))' at line 1
+set @@new=0;
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index c35e1c09c5c..5da2be8da37 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -3,13 +3,14 @@ drop database if exists mysqldump_test_db;
drop database if exists db1;
drop database if exists db2;
drop view if exists v1, v2, v3;
-CREATE TABLE t1(a int);
+CREATE TABLE t1(a int, key (a)) key_block_size=1024;
INSERT INTO t1 VALUES (1), (2);
-
+
+
diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result
index a0220a0bad8..7c687ff33a1 100644
--- a/mysql-test/r/ndb_alter_table.result
+++ b/mysql-test/r/ndb_alter_table.result
@@ -286,3 +286,45 @@ unique key tx1 (c002, c003, c004, c005)) engine=ndb;
create index tx2
on t1 (c010, c011, c012, c013);
drop table t1;
+CREATE TABLE t1 (
+auto int(5) unsigned NOT NULL auto_increment,
+string char(10),
+vstring varchar(10),
+bin binary(2),
+vbin varbinary(7),
+tiny tinyint(4) DEFAULT '0' NOT NULL ,
+short smallint(6) DEFAULT '1' NOT NULL ,
+medium mediumint(8) DEFAULT '0' NOT NULL,
+long_int int(11) DEFAULT '0' NOT NULL,
+longlong bigint(13) DEFAULT '0' NOT NULL,
+real_float float(13,1) DEFAULT 0.0 NOT NULL,
+real_double double(16,4),
+real_decimal decimal(16,4),
+utiny tinyint(3) unsigned DEFAULT '0' NOT NULL,
+ushort smallint(5) unsigned zerofill DEFAULT '00000' NOT NULL,
+umedium mediumint(8) unsigned DEFAULT '0' NOT NULL,
+ulong int(11) unsigned DEFAULT '0' NOT NULL,
+ulonglong bigint(13) unsigned DEFAULT '0' NOT NULL,
+bits bit(3),
+options enum('zero','one','two','three','four') not null,
+flags set('zero','one','two','three','four') not null,
+date_field date,
+year_field year,
+time_field time,
+date_time datetime,
+time_stamp timestamp,
+PRIMARY KEY (auto)
+) engine=ndb;
+CREATE TEMPORARY TABLE ndb_show_tables (id INT, type VARCHAR(20), state VARCHAR(20), logging VARCHAR(20), _database VARCHAR(255), _schema VARCHAR(20), name VARCHAR(255));
+LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables;
+set @t1_id = (select id from ndb_show_tables where name like '%t1%');
+truncate ndb_show_tables;
+alter table t1 change tiny new_tiny tinyint(4) DEFAULT '0' NOT NULL;
+create index i1 on t1(medium);
+alter table t1 add index i2(long_int);
+drop index i1 on t1;
+LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables;
+select 'no_copy' from ndb_show_tables where id = @t1_id and name like '%t1%';
+no_copy
+no_copy
+DROP TABLE t1, ndb_show_tables;
diff --git a/mysql-test/r/ndb_alter_table_row.result b/mysql-test/r/ndb_alter_table3.result
similarity index 100%
rename from mysql-test/r/ndb_alter_table_row.result
rename to mysql-test/r/ndb_alter_table3.result
diff --git a/mysql-test/r/ndb_alter_table_stm.result b/mysql-test/r/ndb_alter_table_stm.result
deleted file mode 100644
index 7cb7b990e2c..00000000000
--- a/mysql-test/r/ndb_alter_table_stm.result
+++ /dev/null
@@ -1,29 +0,0 @@
-DROP TABLE IF EXISTS t1;
-create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
-engine=ndb;
-insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
-create index c on t1(c);
-select * from t1 where c = 'two';
-a b c
-2 two two
-alter table t1 drop index c;
-select * from t1 where c = 'two';
-select * from t1 where c = 'two';
-a b c
-2 two two
-drop table t1;
-create table t3 (a int primary key) engine=ndbcluster;
-begin;
-insert into t3 values (1);
-alter table t3 rename t4;
-delete from t3;
-insert into t3 values (1);
-commit;
-select * from t3;
-ERROR HY000: Can't lock file (errno: 155)
-select * from t4;
-a
-1
-drop table t4;
-show tables;
-Tables_in_test
diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result
index 4a1f5f587df..9477caf97ab 100644
--- a/mysql-test/r/ndb_basic.result
+++ b/mysql-test/r/ndb_basic.result
@@ -6,6 +6,13 @@ attr1 INT NOT NULL,
attr2 INT,
attr3 VARCHAR(10)
) ENGINE=ndbcluster;
+drop table t1;
+CREATE TABLE t1 (
+pk1 INT NOT NULL PRIMARY KEY,
+attr1 INT NOT NULL,
+attr2 INT,
+attr3 VARCHAR(10)
+) ENGINE=ndbcluster;
SHOW INDEX FROM t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 pk1 A 0 NULL NULL BTREE
diff --git a/mysql-test/r/ndb_blob.result b/mysql-test/r/ndb_blob.result
index 9c76d46f4f0..7a781ae3bde 100644
--- a/mysql-test/r/ndb_blob.result
+++ b/mysql-test/r/ndb_blob.result
@@ -481,14 +481,22 @@ msg text NOT NULL
insert into t1 (msg) values(
'Tries to validate (8 byte length + inline bytes) as UTF8 :(
Fast fix: removed validation for Text. It is not yet indexable
-so bad data will not crash kernel.
-Proper fix: Set inline bytes to multiple of mbmaxlen and
-validate it (after the 8 byte length).');
+so bad data will not crash kernel.');
select * from t1;
id msg
1 Tries to validate (8 byte length + inline bytes) as UTF8 :(
Fast fix: removed validation for Text. It is not yet indexable
so bad data will not crash kernel.
-Proper fix: Set inline bytes to multiple of mbmaxlen and
-validate it (after the 8 byte length).
+drop table t1;
+create table t1 (
+a int primary key not null auto_increment,
+b text
+) engine=ndbcluster;
+select count(*) from t1;
+count(*)
+500
+truncate t1;
+select count(*) from t1;
+count(*)
+0
drop table t1;
diff --git a/mysql-test/r/ndb_config.result b/mysql-test/r/ndb_config.result
index d2a8a91828c..c364b8f1b5d 100644
--- a/mysql-test/r/ndb_config.result
+++ b/mysql-test/r/ndb_config.result
@@ -8,4 +8,3 @@ ndbd,1,localhost,52428800,26214400 ndbd,2,localhost,52428800,36700160 ndbd,3,loc
ndbd,1,localhost ndbd,2,localhost ndbd,3,localhost ndbd,4,localhost ndb_mgmd,5,localhost mysqld,6, mysqld,7, mysqld,8, mysqld,9, mysqld,10,
ndbd,2,localhost ndbd,3,localhost ndbd,4,localhost ndbd,5,localhost ndb_mgmd,6,localhost mysqld,1, mysqld,7, mysqld,8, mysqld,9, mysqld,10,
ndbd,3,localhost ndbd,4,localhost ndbd,5,localhost ndbd,6,localhost ndb_mgmd,1,localhost ndb_mgmd,2,localhost mysqld,11, mysqld,12, mysqld,13, mysqld,14, mysqld,15,
-shm,3,4,35,3 shm,3,5,35,3 shm,3,6,35,3 shm,4,5,35,4 shm,4,6,35,4 shm,5,6,35,5 tcp,11,3,55,3 tcp,11,4,55,4 tcp,11,5,55,5 tcp,11,6,55,6 tcp,12,3,55,3 tcp,12,4,55,4 tcp,12,5,55,5 tcp,12,6,55,6 tcp,13,3,55,3 tcp,13,4,55,4 tcp,13,5,55,5 tcp,13,6,55,6 tcp,14,3,55,3 tcp,14,4,55,4 tcp,14,5,55,5 tcp,14,6,55,6 tcp,15,3,55,3 tcp,15,4,55,4 tcp,15,5,55,5 tcp,15,6,55,6 tcp,1,3,55,1 tcp,1,4,55,1 tcp,1,5,55,1 tcp,1,6,55,1 tcp,2,3,55,2 tcp,2,4,55,2 tcp,2,5,55,2 tcp,2,6,55,2
diff --git a/mysql-test/r/ndb_config2.result b/mysql-test/r/ndb_config2.result
new file mode 100644
index 00000000000..cfd012933c4
--- /dev/null
+++ b/mysql-test/r/ndb_config2.result
@@ -0,0 +1 @@
+shm,3,4,35,3 shm,3,5,35,3 shm,3,6,35,3 shm,4,5,35,4 shm,4,6,35,4 shm,5,6,35,5 tcp,11,3,55,3 tcp,11,4,55,4 tcp,11,5,55,5 tcp,11,6,55,6 tcp,12,3,55,3 tcp,12,4,55,4 tcp,12,5,55,5 tcp,12,6,55,6 tcp,13,3,55,3 tcp,13,4,55,4 tcp,13,5,55,5 tcp,13,6,55,6 tcp,14,3,55,3 tcp,14,4,55,4 tcp,14,5,55,5 tcp,14,6,55,6 tcp,15,3,55,3 tcp,15,4,55,4 tcp,15,5,55,5 tcp,15,6,55,6 tcp,1,3,55,1 tcp,1,4,55,1 tcp,1,5,55,1 tcp,1,6,55,1 tcp,2,3,55,2 tcp,2,4,55,2 tcp,2,5,55,2 tcp,2,6,55,2
diff --git a/mysql-test/r/ndb_dd_basic.result b/mysql-test/r/ndb_dd_basic.result
index d5ac5071a8e..ee1b717e6f1 100644
--- a/mysql-test/r/ndb_dd_basic.result
+++ b/mysql-test/r/ndb_dd_basic.result
@@ -5,20 +5,20 @@ INITIAL_SIZE 16M
UNDO_BUFFER_SIZE = 1M
ENGINE=MYISAM;
Warnings:
-Error 1539 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
+Error 1465 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
ALTER LOGFILE GROUP lg1
ADD UNDOFILE 'undofile02.dat'
INITIAL_SIZE = 4M
ENGINE=XYZ;
Warnings:
Error 1266 Using storage engine MyISAM for table 'lg1'
-Error 1539 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
+Error 1465 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
CREATE TABLESPACE ts1
ADD DATAFILE 'datafile.dat'
USE LOGFILE GROUP lg1
INITIAL_SIZE 12M;
Warnings:
-Error 1539 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
+Error 1465 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
set storage_engine=ndb;
CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
diff --git a/mysql-test/r/ndb_dd_ddl.result b/mysql-test/r/ndb_dd_ddl.result
index 39dceef1573..47b95214024 100644
--- a/mysql-test/r/ndb_dd_ddl.result
+++ b/mysql-test/r/ndb_dd_ddl.result
@@ -16,7 +16,7 @@ ERROR HY000: Failed to create LOGFILE GROUP
SHOW WARNINGS;
Level Code Message
Error 1296 Got error 1514 'Currently there is a limit of one logfile group' from NDB
-Error 1507 Failed to create LOGFILE GROUP
+Error 1515 Failed to create LOGFILE GROUP
CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
INITIAL_SIZE 16M
diff --git a/mysql-test/r/ndb_multi_row.result b/mysql-test/r/ndb_multi_row.result
index 64b151d42a9..cf5a76d6f01 100644
--- a/mysql-test/r/ndb_multi_row.result
+++ b/mysql-test/r/ndb_multi_row.result
@@ -62,4 +62,6 @@ t4
drop table t1, t2, t3, t4;
drop table if exists t1, t3, t4;
Warnings:
+Error 155 Table 'test.t1' doesn't exist
Error 155 Table 'test.t3' doesn't exist
+Error 155 Table 'test.t4' doesn't exist
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 3de7ab61e73..06443cde01d 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -1056,3 +1056,104 @@ a b
1 9
3 7
drop table t1;
+create table t1 (a int);
+create table t2 like t1;
+create table t3 like t2;
+prepare stmt from "repair table t1";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+prepare stmt from "optimize table t1";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status Table is already up to date
+prepare stmt from "analyze table t1";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+prepare stmt from "repair table t1, t2, t3";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+test.t2 repair status OK
+test.t3 repair status OK
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+test.t2 repair status OK
+test.t3 repair status OK
+prepare stmt from "optimize table t1, t2, t3";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+test.t2 optimize status OK
+test.t3 optimize status OK
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status Table is already up to date
+test.t2 optimize status Table is already up to date
+test.t3 optimize status Table is already up to date
+prepare stmt from "analyze table t1, t2, t3";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+test.t2 analyze status Table is already up to date
+test.t3 analyze status Table is already up to date
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+test.t2 analyze status Table is already up to date
+test.t3 analyze status Table is already up to date
+prepare stmt from "repair table t1, t4, t3";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+test.t4 repair error Table 'test.t4' doesn't exist
+test.t3 repair status OK
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+test.t4 repair error Table 'test.t4' doesn't exist
+test.t3 repair status OK
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+prepare stmt from "optimize table t1, t3, t4";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+test.t3 optimize status OK
+test.t4 optimize error Table 'test.t4' doesn't exist
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+execute stmt;
+Table Op Msg_type Msg_text
+test.t1 optimize status Table is already up to date
+test.t3 optimize status Table is already up to date
+test.t4 optimize error Table 'test.t4' doesn't exist
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+prepare stmt from "analyze table t4, t1";
+execute stmt;
+Table Op Msg_type Msg_text
+test.t4 analyze error Table 'test.t4' doesn't exist
+test.t1 analyze status Table is already up to date
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+execute stmt;
+Table Op Msg_type Msg_text
+test.t4 analyze error Table 'test.t4' doesn't exist
+test.t1 analyze status Table is already up to date
+Warnings:
+Error 1146 Table 'test.t4' doesn't exist
+deallocate prepare stmt;
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index 22d59c7bd8f..d0b773dfe34 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -410,13 +410,10 @@ ERROR HY000: This command is not supported in the prepared statement protocol ye
prepare stmt1 from ' select * into outfile ''data.txt'' from t1 ';
execute stmt1 ;
prepare stmt1 from ' optimize table t1 ' ;
-ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' analyze table t1 ' ;
-ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' checksum table t1 ' ;
ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' repair table t1 ' ;
-ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' restore table t1 from ''data.txt'' ' ;
ERROR HY000: This command is not supported in the prepared statement protocol yet
prepare stmt1 from ' handler t1 open ';
diff --git a/mysql-test/r/rpl_bit_npk.result b/mysql-test/r/rpl_bit_npk.result
index 2850e63aabd..9599660f18f 100644
--- a/mysql-test/r/rpl_bit_npk.result
+++ b/mysql-test/r/rpl_bit_npk.result
@@ -56,86 +56,90 @@ INSERT INTO test.t1 VALUES (8,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,4
UNLOCK TABLES;
UPDATE test.t1 set x034 = 50 where bit3 = b'000000';
UPDATE test.t1 set VNotSupp = 33 where bit1 = b'0';
-SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1;
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034
+FROM test.t1
+ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034;
oSupp sSuppD GSuppDf VNotSupp x034
5 5 3 NULL 1
5 5 3 2 1
-5 5 3 33 1
5 5 3 2 50
5 5 3 33 1
5 5 3 33 1
5 5 3 33 1
5 5 3 33 1
-SELECT hex(bit1) from test.t1;
+5 5 3 33 1
+SELECT hex(bit1) from test.t1 ORDER BY bit1;
hex(bit1)
+0
+0
+0
+0
+0
+2A
3F
3F
-0
-2A
-0
-0
-0
-0
-SELECT hex(bit2) from test.t1;
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
hex(bit2)
-3E
0
+1
+1
+1
+1
2A
+3E
3F
-1
-1
-1
-1
-SELECT hex(bit3) from test.t1;
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
hex(bit3)
-35
-24
-15
0
1
1
1
1
-SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1;
+15
+24
+35
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034
+FROM test.t1
+ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034;
oSupp sSuppD GSuppDf VNotSupp x034
5 5 3 NULL 1
5 5 3 2 1
-5 5 3 33 1
5 5 3 2 50
5 5 3 33 1
5 5 3 33 1
5 5 3 33 1
5 5 3 33 1
-SELECT hex(bit1) from test.t1;
+5 5 3 33 1
+SELECT hex(bit1) from test.t1 ORDER BY bit1;
hex(bit1)
+0
+0
+0
+0
+0
+2A
3F
3F
-0
-2A
-0
-0
-0
-0
-SELECT hex(bit2) from test.t1;
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
hex(bit2)
-3E
0
+1
+1
+1
+1
2A
+3E
3F
-1
-1
-1
-1
-SELECT hex(bit3) from test.t1;
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
hex(bit3)
-35
-24
-15
0
1
1
1
1
+15
+24
+35
CREATE TABLE test.t2 (a INT, b BIT(1));
INSERT INTO test.t2 VALUES (1, b'0');
INSERT INTO test.t2 VALUES (1, b'1');
@@ -144,19 +148,19 @@ CREATE TABLE test.t3 (a INT, b INT);
INSERT INTO test.t3 VALUES (1, NULL);
INSERT INTO test.t3 VALUES (1, 0);
UPDATE test.t3 SET a = 2 WHERE b = 0;
-SELECT a, hex(b) FROM test.t2;
+SELECT a, hex(b) FROM test.t2 ORDER BY a,b;
a hex(b)
1 0
2 1
-SELECT * FROM test.t3;
+SELECT * FROM test.t3 ORDER BY a,b;
a b
1 NULL
2 0
-SELECT a, hex(b) FROM test.t2;
+SELECT a, hex(b) FROM test.t2 ORDER BY a,b;
a hex(b)
1 0
2 1
-SELECT * FROM test.t3;
+SELECT * FROM test.t3 ORDER BY a,b;
a b
1 NULL
2 0
diff --git a/mysql-test/r/rpl_failed_optimize.result b/mysql-test/r/rpl_failed_optimize.result
index fd711f89222..ec0b3856ae7 100644
--- a/mysql-test/r/rpl_failed_optimize.result
+++ b/mysql-test/r/rpl_failed_optimize.result
@@ -18,3 +18,8 @@ Table Op Msg_type Msg_text
test.non_existing optimize error Table 'test.non_existing' doesn't exist
Warnings:
Error 1146 Table 'test.non_existing' doesn't exist
+select * from t1;
+a
+1
+commit;
+drop table t1;
diff --git a/mysql-test/r/rpl_loaddatalocal.result b/mysql-test/r/rpl_loaddatalocal.result
index 20e56a62133..bb1b0610aa8 100644
--- a/mysql-test/r/rpl_loaddatalocal.result
+++ b/mysql-test/r/rpl_loaddatalocal.result
@@ -18,12 +18,12 @@ select * into outfile 'MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_out
drop table t1;
create table t1(a int primary key);
load data local infile 'MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile' into table t1;
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
a
1
2
3
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
a
1
2
diff --git a/mysql-test/r/rpl_sp_effects.result b/mysql-test/r/rpl_sp_effects.result
index bf8128d9385..26455b65beb 100644
--- a/mysql-test/r/rpl_sp_effects.result
+++ b/mysql-test/r/rpl_sp_effects.result
@@ -19,24 +19,30 @@ set spv=spv+1;
end while;
end//
call p1();
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
+a
+1
+2
+3
+4
+5
+SELECT * FROM t1 ORDER BY a;
a
1
2
3
4
5
-delete from t1;
create procedure p2()
begin
declare a int default 4;
create table t2 as select a;
end//
call p2();
-select * from t2;
+SELECT * FROM t2 ORDER BY a;
a
4
-select * from t2;
+SELECT * FROM t2 ORDER BY a;
a
4
drop procedure p1;
@@ -61,43 +67,58 @@ end//
call p1(f1(1), f1(2));
yes
yes
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
a
1
+1
2
+2
+3
+4
+5
5
6
7
8
create table t2(a int);
insert into t2 values (10),(11);
-select a,f1(a) from t2;
+SELECT a,f1(a) FROM t2 ORDER BY a;
a f1(a)
10 11
11 12
insert into t2 select f1(3);
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
master: a
master: 1
+master: 1
master: 2
+master: 2
+master: 3
+master: 3
+master: 4
+master: 5
master: 5
master: 6
master: 7
master: 8
master: 10
master: 11
-master: 3
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
slave: a
slave: 1
+slave: 1
slave: 2
+slave: 2
+slave: 3
+slave: 3
+slave: 4
+slave: 5
slave: 5
slave: 6
slave: 7
slave: 8
slave: 10
slave: 11
-slave: 3
drop procedure p1;
delete from t1;
delete from t2;
@@ -108,11 +129,11 @@ select * from v1;
f1(a)
2
3
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
master: a
master: 1
master: 2
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
slave: a
slave: 1
slave: 2
@@ -123,10 +144,10 @@ set @xx=123;
execute s1 using @xx;
f1(?)
124
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
master: a
master: 123
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
slave: a
slave: 123
delete from t1;
@@ -141,18 +162,18 @@ set spv= spv - 10;
end while;
end//
call p1(15);
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
master: a
-master: 15
-master: 15
master: 6
master: 6
-select 'slave:',a from t1;
+master: 15
+master: 15
+SELECT 'slave:',a FROM t1 ORDER BY a;
slave: a
-slave: 15
-slave: 15
slave: 6
slave: 6
+slave: 15
+slave: 15
drop procedure p1;
drop function f1;
drop table t1,t2;
@@ -187,26 +208,26 @@ f1()
0
set @x=30;
call p1();
-select 'master', a from t1;
+SELECT 'master', a FROM t1 ORDER BY a;
master a
-master 20
master 10
master 11
-master 100
-master 101
+master 20
master 30
master 31
+master 100
+master 101
master 101
master 102
-select 'slave', a from t1;
+SELECT 'slave', a FROM t1 ORDER BY a;
slave a
-slave 20
slave 10
slave 11
-slave 100
-slave 101
+slave 20
slave 30
slave 31
+slave 100
+slave 101
slave 101
slave 102
drop table t1;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 9b9f67efeb5..e9092fc8a69 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -3390,3 +3390,24 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where
DROP TABLE t1,t2;
+CREATE TABLE t1 (i TINYINT UNSIGNED NOT NULL);
+INSERT t1 SET i = 0;
+UPDATE t1 SET i = -1;
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+0
+UPDATE t1 SET i = CAST(i - 1 AS SIGNED);
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+0
+UPDATE t1 SET i = i - 1;
+Warnings:
+Warning 1264 Out of range value for column 'i' at row 1
+SELECT * FROM t1;
+i
+255
+DROP TABLE t1;
diff --git a/mysql-test/r/sp-dynamic.result b/mysql-test/r/sp-dynamic.result
index c00b09f90e1..d9d5706cded 100644
--- a/mysql-test/r/sp-dynamic.result
+++ b/mysql-test/r/sp-dynamic.result
@@ -286,12 +286,12 @@ id stmt_text status
1 select 1 supported
2 flush tables not supported
3 handler t1 open as ha not supported
-4 analyze table t1 not supported
+4 analyze table t1 supported
5 check table t1 not supported
6 checksum table t1 not supported
7 check table t1 not supported
-8 optimize table t1 not supported
-9 repair table t1 not supported
+8 optimize table t1 supported
+9 repair table t1 supported
10 describe extended select * from t1 supported
11 help help not supported
12 show databases supported
diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result
index e39ddd1d79d..c8cafe5ace1 100644
--- a/mysql-test/r/sp_notembedded.result
+++ b/mysql-test/r/sp_notembedded.result
@@ -1,3 +1,4 @@
+drop table if exists t1,t3;
drop procedure if exists bug4902|
create procedure bug4902()
begin
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index e4850a19b4c..0a464d055c2 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1354,10 +1354,10 @@ a
explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
-2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 Using index
-2 DEPENDENT SUBQUERY t1 ref a a 10 func,test.t3.a 1167 Using where; Using index
+2 DEPENDENT SUBQUERY t1 ref a a 5 func 1001 Using where; Using index
+2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 Using where; Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a`,(select 1 AS `Not_used` from `test`.`t1` join `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`a`) and ((`test`.`t2`.`a`) = `test`.`t1`.`a`))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a`,(select 1 AS `Not_used` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t1`.`b`) and ((`test`.`t2`.`a`) = `test`.`t1`.`a`))))
insert into t1 values (3,31);
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result
index 5cc4150e374..fe9e971af2f 100644
--- a/mysql-test/r/timezone2.result
+++ b/mysql-test/r/timezone2.result
@@ -1,4 +1,5 @@
drop table if exists t1, t2;
+drop function if exists f1;
create table t1 (ts timestamp);
set time_zone='+00:00';
select unix_timestamp(utc_timestamp())-unix_timestamp(current_timestamp());
@@ -268,3 +269,17 @@ select * from t1;
convert_tz(NULL, NULL, NULL)
NULL
drop table t1;
+create table t1 (ldt datetime, udt datetime);
+create function f1(i datetime) returns datetime
+return convert_tz(i, 'UTC', 'Europe/Moscow');
+create trigger t1_bi before insert on t1 for each row
+set new.udt:= convert_tz(new.ldt, 'Europe/Moscow', 'UTC');
+insert into t1 (ldt) values ('2006-04-19 16:30:00');
+select * from t1;
+ldt udt
+2006-04-19 16:30:00 2006-04-19 12:30:00
+select ldt, f1(udt) as ldt2 from t1;
+ldt ldt2
+2006-04-19 16:30:00 2006-04-19 16:30:00
+drop table t1;
+drop function f1;
diff --git a/mysql-test/r/xml.result b/mysql-test/r/xml.result
index 61dd1390a6a..06dc2f3d78a 100644
--- a/mysql-test/r/xml.result
+++ b/mysql-test/r/xml.result
@@ -665,3 +665,12 @@ CALL p2();
EXTRACTVALUE(p,'/Ñ/r')
A
DROP PROCEDURE p2;
+select extractValue('','count(ns:element)');
+extractValue('','count(ns:element)')
+1
+select extractValue('a','/ns:element');
+extractValue('a','/ns:element')
+a
+select extractValue('a','/ns:element/@xmlns:ns');
+extractValue('a','/ns:element/@xmlns:ns')
+myns
diff --git a/mysql-test/t/analyze.test b/mysql-test/t/analyze.test
index a8fd0a4283e..1801a4a440f 100644
--- a/mysql-test/t/analyze.test
+++ b/mysql-test/t/analyze.test
@@ -61,6 +61,14 @@ prepare stmt1 from "SELECT * FROM t1 PROCEDURE ANALYSE()";
execute stmt1;
execute stmt1;
deallocate prepare stmt1;
+
+#
+# bug#15225 (ANALYZE temporary has no effect)
+#
+create temporary table t1(a int, index(a));
+insert into t1 values('1'),('2'),('3'),('4'),('5');
+analyze table t1;
+show index from t1;
drop table t1;
# End of 4.1 tests
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index 533da542855..b733a23f398 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -47,7 +47,7 @@ select cast('1a' as signed);
select cast('' as signed);
#
-# Character set convertion
+# Character set conversion
#
set names binary;
select cast(_latin1'test' as char character set latin2);
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index d92aed1d1a2..7cbe4419904 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -18,22 +18,23 @@ ndb_autodiscover2 : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t
ndb_binlog_discover : BUG#19395 2006-04-28 tomas/knielsen mysqld does not always detect cluster shutdown
#ndb_cache2 : BUG#18597 2006-03-28 brian simultaneous drop table and ndb statistics update triggers node failure
#ndb_cache_multi2 : BUG#18597 2006-04-10 kent simultaneous drop table and ndb statistics update triggers node failure
+ndb_load : BUG#17233 2006-05-04 tomas failed load data from infile causes mysqld dbug_assert, binlog not flushed
partition_03ndb : BUG#16385 2006-03-24 mikael Partitions: crash when updating a range partitioned NDB table
ps_7ndb : BUG#18950 2006-02-16 jmiller create table like does not obtain LOCK_open
rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated
rpl_ndb_2myisam : BUG#19227 2006-04-20 pekka pk delete apparently not replicated
rpl_ndb_auto_inc : BUG#17086 2006-02-16 jmiller CR: auto_increment_increment and auto_increment_offset produce duplicate key er
-rpl_ndb_dd_partitions : BUG#19259 2006-04-21 rpl_ndb_dd_partitions fails on solaris
+rpl_ndb_commit_afterflush : BUG#19328 2006-05-04 tomas Slave timeout with COM_REGISTER_SLAVE error causing stop
+rpl_ndb_dd_partitions : BUG#19259 2006-04-21 rpl_ndb_dd_partitions fails on s/AMD
rpl_ndb_ddl : BUG#18946 result file needs update + test needs to checked
-rpl_ndb_innodb2ndb : BUG#17400 2006-04-19 tomas Cluster Replication: delete & update of rows in table without pk fails on slave.
+rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ
-rpl_ndb_myisam2ndb : BUG#17400 2006-04-19 tomas Cluster Replication: delete & update of rows in table without pk fails on slave.
+rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
rpl_switch_stm_row_mixed : BUG#18590 2006-03-28 brian
rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly
-rpl_row_func003 : BUG#19074 2006-13-04 andrei test failed
+rpl_row_func003 : BUG#19074 2006-13-04 andrei test failed
rpl_row_inexist_tbl : BUG#18948 2006-03-09 mats Disabled since patch makes this test wait forever
rpl_sp : BUG#16456 2006-02-16 jmiller
-mysqldump : BUG#18078 2006-03-10 lars
udf : BUG#18564 2006-03-27 ian (Permission by Brian)
# the below testcase have been reworked to avoid the bug, test contains comment, keep bug open
diff --git a/mysql-test/t/exampledb.test b/mysql-test/t/exampledb.test
index 946d25325dc..fbb2a18f344 100644
--- a/mysql-test/t/exampledb.test
+++ b/mysql-test/t/exampledb.test
@@ -5,6 +5,10 @@
-- source include/have_exampledb.inc
--disable_warnings
+# Clean up if event's test fails
+drop database if exists events_test;
+drop database if exists events_test2;
+
drop table if exists t1;
--enable_warnings
diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test
index 5e493c2643b..f1b9d290885 100644
--- a/mysql-test/t/heap_btree.test
+++ b/mysql-test/t/heap_btree.test
@@ -164,4 +164,16 @@ DELETE from t1 where a < 100;
SELECT * from t1;
DROP TABLE t1;
+#
+# BUG#18160 - Memory-/HEAP Table endless growing indexes
+#
+CREATE TABLE t1(val INT, KEY USING BTREE(val)) ENGINE=memory;
+INSERT INTO t1 VALUES(0);
+--replace_result 37 21
+SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
+UPDATE t1 SET val=1;
+--replace_result 37 21
+SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
+DROP TABLE t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/information_schema_inno.test b/mysql-test/t/information_schema_inno.test
index 9cd64a54ad9..195bf57a880 100644
--- a/mysql-test/t/information_schema_inno.test
+++ b/mysql-test/t/information_schema_inno.test
@@ -21,3 +21,35 @@ select * from information_schema.KEY_COLUMN_USAGE where
TABLE_SCHEMA= "test";
drop table t3, t2, t1;
+
+#
+# Test for REFERENTIAL_CONSTRAINTS table
+#
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT NOT NULL,
+ PRIMARY KEY(a1, a2)) ENGINE=INNODB;
+CREATE TABLE t2(b1 INT, b2 INT, INDEX (b1, b2),
+ CONSTRAINT A1
+ FOREIGN KEY (b1, b2) REFERENCES t1(a1, a2)
+ ON UPDATE CASCADE ON DELETE NO ACTION) ENGINE=INNODB;
+CREATE TABLE t3(b1 INT, b2 INT, INDEX (b1, b2),
+ CONSTRAINT A2
+ FOREIGN KEY (b1, b2) REFERENCES t2(b1, b2)
+ ON UPDATE SET NULL ON DELETE RESTRICT) ENGINE=INNODB;
+CREATE TABLE t4(b1 INT, b2 INT, INDEX (b1, b2),
+ CONSTRAINT A3
+ FOREIGN KEY (b1, b2) REFERENCES t3(b1, b2)
+ ON UPDATE NO ACTION ON DELETE SET NULL) ENGINE=INNODB;
+CREATE TABLE t5(b1 INT, b2 INT, INDEX (b1, b2),
+ CONSTRAINT A4
+ FOREIGN KEY (b1, b2) REFERENCES t4(b1, b2)
+ ON UPDATE RESTRICT ON DELETE CASCADE) ENGINE=INNODB;
+
+
+select a.CONSTRAINT_SCHEMA, b.TABLE_NAME, CONSTRAINT_TYPE,
+ b.CONSTRAINT_NAME, UNIQUE_CONSTRAINT_SCHEMA, UNIQUE_CONSTRAINT_NAME,
+ MATCH_OPTION, UPDATE_RULE, DELETE_RULE
+from information_schema.TABLE_CONSTRAINTS a,
+ information_schema.REFERENTIAL_CONSTRAINTS b
+where a.CONSTRAINT_SCHEMA = 'test' and a.CONSTRAINT_SCHEMA = b.CONSTRAINT_SCHEMA and
+a.CONSTRAINT_NAME = b.CONSTRAINT_NAME;
+drop tables t5, t4, t3, t2, t1;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index cadb611714c..92e060eed92 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -2494,3 +2494,19 @@ SELECT DISTINCT p0.a FROM t2 p0 WHERE BINARY p0.b = 'customer_over';
SELECT p0.a FROM t2 p0 WHERE BINARY p0.b = 'customer_over';
drop table t2, t1;
+
+#
+# Bug #15680 (SPATIAL key in innodb)
+#
+--error ER_TABLE_CANT_HANDLE_SPKEYS
+create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
+
+#
+# Test optimize on table with open transaction
+#
+
+CREATE TABLE t1 ( a int ) ENGINE=innodb;
+BEGIN;
+INSERT INTO t1 VALUES (1);
+OPTIMIZE TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test
index 3b412d9e793..048da802d02 100644
--- a/mysql-test/t/log_tables.test
+++ b/mysql-test/t/log_tables.test
@@ -63,10 +63,10 @@ flush logs;
# check locking of the log tables
#
---error 1533
+--error ER_CANT_WRITE_LOCK_LOG_TABLE
lock tables mysql.general_log WRITE;
---error 1533
+--error ER_CANT_WRITE_LOCK_LOG_TABLE
lock tables mysql.slow_log WRITE;
#
@@ -75,10 +75,10 @@ lock tables mysql.slow_log WRITE;
# tables are always opened and locked by the logger.
#
---error 1534
+--error ER_CANT_READ_LOCK_LOG_TABLE
lock tables mysql.general_log READ;
---error 1534
+--error ER_CANT_READ_LOCK_LOG_TABLE
lock tables mysql.slow_log READ;
#
diff --git a/mysql-test/t/myisam-system.test b/mysql-test/t/myisam-system.test
new file mode 100644
index 00000000000..43fbaabf698
--- /dev/null
+++ b/mysql-test/t/myisam-system.test
@@ -0,0 +1,21 @@
+#
+# Test how DROP TABLE works if the index or data file doesn't exists
+
+# Initialise
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+
+create table t1 (a int) engine=myisam;
+system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYI ;
+drop table if exists t1;
+create table t1 (a int) engine=myisam;
+system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYI ;
+--error 1051,6
+drop table t1;
+create table t1 (a int) engine=myisam;
+system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYD ;
+--error 1105,6,29
+drop table t1;
+--error 1051
+drop table t1;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index 15533ca00e6..87a00399c23 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -726,23 +726,6 @@ create table t1 (v varchar(65535));
eval set storage_engine=$default;
-#
-# Test how DROP TABLE works if the index or data file doesn't exists
-
-create table t1 (a int) engine=myisam;
-system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYI ;
-drop table if exists t1;
-create table t1 (a int) engine=myisam;
-system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYI ;
---error 1051,6
-drop table t1;
-create table t1 (a int) engine=myisam;
-system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYD ;
---error 1105,6,29
-drop table t1;
---error 1051
-drop table t1;
-
#
# Test concurrent insert
# First with static record length
@@ -824,3 +807,72 @@ create table t3 (c1 int) engine=myisam pack_keys=default;
create table t4 (c1 int) engine=myisam pack_keys=2;
drop table t1, t2, t3;
+#
+# Test of key_block_size
+#
+
+# Old format, to be obsolete in 5.3
+create table t1 (a int not null, key `a` key_block_size=1024 (a));
+show create table t1;
+drop table t1;
+
+set @@new=1;
+
+create table t1 (a int not null, key `a` (a) key_block_size=1024);
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, key `a` (a) key_block_size=2048);
+show create table t1;
+drop table t1;
+
+create table t1 (a varchar(2048), key `a` (a));
+show create table t1;
+drop table t1;
+
+create table t1 (a varchar(2048), key `a` (a) key_block_size=1024);
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=1024;
+show create table t1;
+alter table t1 key_block_size=2048;
+show create table t1;
+alter table t1 add c int, add key (c);
+show create table t1;
+alter table t1 key_block_size=0;
+alter table t1 add d int, add key (d);
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=8192;
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, b varchar(2048), key (a) key_block_size=1024, key(b)) key_block_size=8192;
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, b int, key (a) key_block_size=1024, key(b) key_block_size=8192) key_block_size=16384;
+show create table t1;
+drop table t1;
+
+
+# Test limits and errors of key_block_size
+
+create table t1 (a int not null, key `a` (a) key_block_size=512);
+show create table t1;
+drop table t1;
+
+create table t1 (a varchar(2048), key `a` (a) key_block_size=1000000000000000000);
+show create table t1;
+drop table t1;
+
+create table t1 (a int not null, key `a` (a) key_block_size=1025);
+show create table t1;
+drop table t1;
+
+--error 1064
+create table t1 (a int not null, key key_block_size=1024 (a));
+
+set @@new=0;
diff --git a/mysql-test/t/mysql_client_test-master.opt b/mysql-test/t/mysql_client_test-master.opt
new file mode 100644
index 00000000000..3711946168d
--- /dev/null
+++ b/mysql-test/t/mysql_client_test-master.opt
@@ -0,0 +1 @@
+--log --log-output=FILE
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 5ba7838bb81..c5c3f88d8c8 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -11,7 +11,7 @@ drop view if exists v1, v2, v3;
# XML output
-CREATE TABLE t1(a int);
+CREATE TABLE t1(a int, key (a)) key_block_size=1024;
INSERT INTO t1 VALUES (1), (2);
--exec $MYSQL_DUMP --skip-create --skip-comments -X test t1
DROP TABLE t1;
@@ -1174,8 +1174,8 @@ create database first;
use first;
set time_zone = 'UTC';
-## prove one works
-create event ee1 on schedule at '2035-12-31 20:01:23' do set @a=5;
+## prove one works (with spaces and tabs on the end)
+create event ee1 on schedule at '2035-12-31 20:01:23' do set @a=5;
show events;
show create event ee1;
--exec $MYSQL_DUMP --events first > $MYSQLTEST_VARDIR/tmp/bug16853-1.sql
@@ -1187,10 +1187,10 @@ use second;
show events;
show create event ee1;
-## prove three works
+## prove three works (with spaces and tabs on the end)
# start with one from the previous restore
-create event ee2 on schedule at '2018-12-31 21:01:23' do set @a=5;
-create event ee3 on schedule at '2030-12-31 22:01:23' do set @a=5;
+create event ee2 on schedule at '2018-12-31 21:01:23' do set @a=5;
+create event ee3 on schedule at '2030-12-31 22:01:23' do set @a=5;
show events;
--exec $MYSQL_DUMP --events second > $MYSQLTEST_VARDIR/tmp/bug16853-2.sql
drop database second;
diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test
index a12ac20a259..29deea4aa0d 100644
--- a/mysql-test/t/ndb_alter_table.test
+++ b/mysql-test/t/ndb_alter_table.test
@@ -327,3 +327,59 @@ drop table t1;
# End of 4.1 tests
+# On-line alter table
+
+
+CREATE TABLE t1 (
+ auto int(5) unsigned NOT NULL auto_increment,
+ string char(10),
+ vstring varchar(10),
+ bin binary(2),
+ vbin varbinary(7),
+ tiny tinyint(4) DEFAULT '0' NOT NULL ,
+ short smallint(6) DEFAULT '1' NOT NULL ,
+ medium mediumint(8) DEFAULT '0' NOT NULL,
+ long_int int(11) DEFAULT '0' NOT NULL,
+ longlong bigint(13) DEFAULT '0' NOT NULL,
+ real_float float(13,1) DEFAULT 0.0 NOT NULL,
+ real_double double(16,4),
+ real_decimal decimal(16,4),
+ utiny tinyint(3) unsigned DEFAULT '0' NOT NULL,
+ ushort smallint(5) unsigned zerofill DEFAULT '00000' NOT NULL,
+ umedium mediumint(8) unsigned DEFAULT '0' NOT NULL,
+ ulong int(11) unsigned DEFAULT '0' NOT NULL,
+ ulonglong bigint(13) unsigned DEFAULT '0' NOT NULL,
+ bits bit(3),
+ options enum('zero','one','two','three','four') not null,
+ flags set('zero','one','two','three','four') not null,
+ date_field date,
+ year_field year,
+ time_field time,
+ date_time datetime,
+ time_stamp timestamp,
+ PRIMARY KEY (auto)
+) engine=ndb;
+
+CREATE TEMPORARY TABLE ndb_show_tables (id INT, type VARCHAR(20), state VARCHAR(20), logging VARCHAR(20), _database VARCHAR(255), _schema VARCHAR(20), name VARCHAR(255));
+
+--disable_warnings
+--exec $NDB_TOOLS_DIR/ndb_show_tables --p > $MYSQLTEST_VARDIR/master-data/test/tmp.dat
+LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables;
+--enable_warnings
+
+set @t1_id = (select id from ndb_show_tables where name like '%t1%');
+truncate ndb_show_tables;
+
+alter table t1 change tiny new_tiny tinyint(4) DEFAULT '0' NOT NULL;
+create index i1 on t1(medium);
+alter table t1 add index i2(long_int);
+drop index i1 on t1;
+
+--disable_warnings
+--exec $NDB_TOOLS_DIR/ndb_show_tables --p > $MYSQLTEST_VARDIR/master-data/test/tmp.dat
+LOAD DATA INFILE 'tmp.dat' INTO TABLE ndb_show_tables;
+--enable_warnings
+
+select 'no_copy' from ndb_show_tables where id = @t1_id and name like '%t1%';
+
+DROP TABLE t1, ndb_show_tables;
diff --git a/mysql-test/t/ndb_alter_table_row.test b/mysql-test/t/ndb_alter_table3.test
similarity index 96%
rename from mysql-test/t/ndb_alter_table_row.test
rename to mysql-test/t/ndb_alter_table3.test
index 9c834e0dd20..a5fe613adcf 100644
--- a/mysql-test/t/ndb_alter_table_row.test
+++ b/mysql-test/t/ndb_alter_table3.test
@@ -1,7 +1,6 @@
-- source include/have_ndb.inc
-- source include/have_multi_ndb.inc
-- source include/not_embedded.inc
--- source include/have_binlog_format_row.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
diff --git a/mysql-test/t/ndb_alter_table_stm.test b/mysql-test/t/ndb_alter_table_stm.test
deleted file mode 100644
index bf162dd0d50..00000000000
--- a/mysql-test/t/ndb_alter_table_stm.test
+++ /dev/null
@@ -1,55 +0,0 @@
--- source include/have_ndb.inc
--- source include/have_multi_ndb.inc
--- source include/not_embedded.inc
--- source include/have_binlog_format_statement.inc
-
---disable_warnings
-DROP TABLE IF EXISTS t1;
---enable_warnings
-
-connection server1;
-create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
-engine=ndb;
-insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
-create index c on t1(c);
-connection server2;
-select * from t1 where c = 'two';
-connection server1;
-alter table t1 drop index c;
-connection server2;
-
---disable_result_log
---error 0,1412
-select * from t1 where c = 'two';
---enable_result_log
-
-select * from t1 where c = 'two';
-connection server1;
-drop table t1;
-
-connection server1;
-create table t3 (a int primary key) engine=ndbcluster;
-
-connection server2;
-begin;
-insert into t3 values (1);
-
-connection server1;
-alter table t3 rename t4;
-
-connection server2;
-# with rbr the below will not work as the "alter" event
-# explicitly invalidates the dictionary cache.
-# This should work as transaction is ongoing...
-delete from t3;
-insert into t3 values (1);
-commit;
-
-# This should fail as its a new transaction
---error 1015
-select * from t3;
-select * from t4;
-drop table t4;
-show tables;
-connection server1;
-
diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test
index ab62e3dd13a..edf74ab1df9 100644
--- a/mysql-test/t/ndb_basic.test
+++ b/mysql-test/t/ndb_basic.test
@@ -6,6 +6,18 @@ DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7;
drop database if exists mysqltest;
--enable_warnings
+# workaround for bug#16445
+# remove to reproduce bug and run tests from ndb start
+# and with ndb_autodiscover disabled. Fails on Linux 50 % of the times
+
+CREATE TABLE t1 (
+ pk1 INT NOT NULL PRIMARY KEY,
+ attr1 INT NOT NULL,
+ attr2 INT,
+ attr3 VARCHAR(10)
+) ENGINE=ndbcluster;
+drop table t1;
+
#
# Basic test to show that the NDB
# table handler is working
diff --git a/mysql-test/t/ndb_blob.test b/mysql-test/t/ndb_blob.test
index f80b7f71281..bf82a793049 100644
--- a/mysql-test/t/ndb_blob.test
+++ b/mysql-test/t/ndb_blob.test
@@ -403,10 +403,29 @@ create table t1 (
insert into t1 (msg) values(
'Tries to validate (8 byte length + inline bytes) as UTF8 :(
Fast fix: removed validation for Text. It is not yet indexable
-so bad data will not crash kernel.
-Proper fix: Set inline bytes to multiple of mbmaxlen and
-validate it (after the 8 byte length).');
+so bad data will not crash kernel.');
select * from t1;
drop table t1;
+# -- bug #19201
+create table t1 (
+ a int primary key not null auto_increment,
+ b text
+) engine=ndbcluster;
+--disable_query_log
+set autocommit=1;
+# more rows than batch size (64)
+# for this bug no blob parts would be necessary
+let $1 = 500;
+while ($1)
+{
+ insert into t1 (b) values (repeat('x',4000));
+ dec $1;
+}
+--enable_query_log
+select count(*) from t1;
+truncate t1;
+select count(*) from t1;
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/ndb_config.test b/mysql-test/t/ndb_config.test
index 4787abe86e2..2fe54cac048 100644
--- a/mysql-test/t/ndb_config.test
+++ b/mysql-test/t/ndb_config.test
@@ -15,4 +15,3 @@
--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster0 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster1 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
---exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --ndb-shm --connections --query=type,nodeid1,nodeid2,group,nodeidserver --mycnf 2> /dev/null
diff --git a/mysql-test/t/ndb_config2.test b/mysql-test/t/ndb_config2.test
new file mode 100644
index 00000000000..170f1b2e5e7
--- /dev/null
+++ b/mysql-test/t/ndb_config2.test
@@ -0,0 +1,7 @@
+-- source include/have_ndb.inc
+-- source include/ndb_default_cluster.inc
+-- source include/not_embedded.inc
+
+# Following doesn't work in all configurations (if shm is not defined)
+
+--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --ndb-shm --connections --query=type,nodeid1,nodeid2,group,nodeidserver --mycnf 2> /dev/null
diff --git a/mysql-test/t/ndb_partition_error.test b/mysql-test/t/ndb_partition_error.test
index 286c2216f70..06581f1270f 100644
--- a/mysql-test/t/ndb_partition_error.test
+++ b/mysql-test/t/ndb_partition_error.test
@@ -66,6 +66,6 @@ partition by list(a)
partitions 2
(partition x123 values in (11, 12),
partition x234 values in (5, 1));
---error 1505
+--error ER_NO_PARTITION_FOR_GIVEN_VALUE
insert into t1 values (NULL,1,1);
drop table t1;
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 9ffdb72ca22..639a576fb35 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -1110,4 +1110,40 @@ select * from t1 order by 1+1;
drop table t1;
+#
+# Bug#19308 "REPAIR/OPTIMIZE/ANALYZE supported in SP but not in PS".
+# Add test coverage for the added commands.
+#
+create table t1 (a int);
+create table t2 like t1;
+create table t3 like t2;
+prepare stmt from "repair table t1";
+execute stmt;
+execute stmt;
+prepare stmt from "optimize table t1";
+execute stmt;
+execute stmt;
+prepare stmt from "analyze table t1";
+execute stmt;
+execute stmt;
+prepare stmt from "repair table t1, t2, t3";
+execute stmt;
+execute stmt;
+prepare stmt from "optimize table t1, t2, t3";
+execute stmt;
+execute stmt;
+prepare stmt from "analyze table t1, t2, t3";
+execute stmt;
+execute stmt;
+prepare stmt from "repair table t1, t4, t3";
+execute stmt;
+execute stmt;
+prepare stmt from "optimize table t1, t3, t4";
+execute stmt;
+execute stmt;
+prepare stmt from "analyze table t4, t1";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+
# End of 5.0 tests
diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test
index 6b168711de8..f61a7820afe 100644
--- a/mysql-test/t/ps_1general.test
+++ b/mysql-test/t/ps_1general.test
@@ -456,13 +456,10 @@ into table t1 fields terminated by ''\t'' ';
prepare stmt1 from ' select * into outfile ''data.txt'' from t1 ';
execute stmt1 ;
##
---error 1295
prepare stmt1 from ' optimize table t1 ' ;
---error 1295
prepare stmt1 from ' analyze table t1 ' ;
--error 1295
prepare stmt1 from ' checksum table t1 ' ;
---error 1295
prepare stmt1 from ' repair table t1 ' ;
--error 1295
prepare stmt1 from ' restore table t1 from ''data.txt'' ' ;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 7596a7ba708..e2ff20e6ecc 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -207,7 +207,7 @@ show status like "Qcache_queries_in_cache";
drop table t1;
#
-# Charset convertion (cp1251_koi8 always present)
+# Charset conversion (cp1251_koi8 always present)
#
create table t1 (a char(1) not null collate koi8r_general_ci);
insert into t1 values(_koi8r"á");
diff --git a/mysql-test/t/rpl_bit_npk.test b/mysql-test/t/rpl_bit_npk.test
index 07fc42b09ef..12b587919f9 100644
--- a/mysql-test/t/rpl_bit_npk.test
+++ b/mysql-test/t/rpl_bit_npk.test
@@ -70,18 +70,22 @@ UNLOCK TABLES;
UPDATE test.t1 set x034 = 50 where bit3 = b'000000';
UPDATE test.t1 set VNotSupp = 33 where bit1 = b'0';
-SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1;
-SELECT hex(bit1) from test.t1;
-SELECT hex(bit2) from test.t1;
-SELECT hex(bit3) from test.t1;
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034
+ FROM test.t1
+ ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034;
+SELECT hex(bit1) from test.t1 ORDER BY bit1;
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
save_master_pos;
connection slave;
sync_with_master;
-SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034 FROM test.t1;
-SELECT hex(bit1) from test.t1;
-SELECT hex(bit2) from test.t1;
-SELECT hex(bit3) from test.t1;
+SELECT oSupp, sSuppD, GSuppDf, VNotSupp, x034
+ FROM test.t1
+ ORDER BY oSupp, sSuppD, GSuppDf, VNotSupp, x034;
+SELECT hex(bit1) from test.t1 ORDER BY bit1;
+SELECT hex(bit2) from test.t1 ORDER BY bit2;
+SELECT hex(bit3) from test.t1 ORDER BY bit3;
connection master;
CREATE TABLE test.t2 (a INT, b BIT(1));
@@ -94,14 +98,14 @@ INSERT INTO test.t3 VALUES (1, NULL);
INSERT INTO test.t3 VALUES (1, 0);
UPDATE test.t3 SET a = 2 WHERE b = 0;
-SELECT a, hex(b) FROM test.t2;
-SELECT * FROM test.t3;
+SELECT a, hex(b) FROM test.t2 ORDER BY a,b;
+SELECT * FROM test.t3 ORDER BY a,b;
save_master_pos;
connection slave;
sync_with_master;
-SELECT a, hex(b) FROM test.t2;
-SELECT * FROM test.t3;
+SELECT a, hex(b) FROM test.t2 ORDER BY a,b;
+SELECT * FROM test.t3 ORDER BY a,b;
connection master;
DROP TABLE IF EXISTS test.t1;
diff --git a/mysql-test/t/rpl_loaddatalocal.test b/mysql-test/t/rpl_loaddatalocal.test
index af4fd0106bd..758ac94af24 100644
--- a/mysql-test/t/rpl_loaddatalocal.test
+++ b/mysql-test/t/rpl_loaddatalocal.test
@@ -53,11 +53,11 @@ create table t1(a int primary key);
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval load data local infile '$MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile' into table t1;
system rm $MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile ;
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
save_master_pos;
connection slave;
sync_with_master;
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
connection master;
drop table t1;
save_master_pos;
diff --git a/mysql-test/t/rpl_ndb_innodb2ndb-slave.opt b/mysql-test/t/rpl_ndb_innodb2ndb-slave.opt
index f47e5a7e98f..d6f11dcd7bc 100644
--- a/mysql-test/t/rpl_ndb_innodb2ndb-slave.opt
+++ b/mysql-test/t/rpl_ndb_innodb2ndb-slave.opt
@@ -1 +1 @@
---binlog-format=row --default-storage-engine=ndb
+--binlog-format=row --default-storage-engine=ndbcluster
diff --git a/mysql-test/t/rpl_ndb_myisam2ndb-slave.opt b/mysql-test/t/rpl_ndb_myisam2ndb-slave.opt
index f31d53c3cb1..b7990823676 100644
--- a/mysql-test/t/rpl_ndb_myisam2ndb-slave.opt
+++ b/mysql-test/t/rpl_ndb_myisam2ndb-slave.opt
@@ -1 +1 @@
---default-storage-engine=ndb --binlog-format=row
+--default-storage-engine=ndbcluster --binlog-format=row
diff --git a/mysql-test/t/rpl_sp_effects.test b/mysql-test/t/rpl_sp_effects.test
index c081f8e00c6..40c9a5d0b74 100644
--- a/mysql-test/t/rpl_sp_effects.test
+++ b/mysql-test/t/rpl_sp_effects.test
@@ -1,3 +1,9 @@
+##########################################
+# Change Author: JBM
+# Change Date: 2006-05-02
+# Change: Added Order By for NDB testing
+##########################################
+
# Test of replication of stored procedures (WL#2146 for MySQL 5.0)
-- source include/master-slave.inc
@@ -30,9 +36,9 @@ call p1();
sync_slave_with_master;
connection slave;
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
connection master;
-delete from t1;
+SELECT * FROM t1 ORDER BY a;
# 2. Test SP variable name
delimiter //;
@@ -44,10 +50,10 @@ end//
delimiter ;//
call p2();
-select * from t2;
+SELECT * FROM t2 ORDER BY a;
sync_slave_with_master;
connection slave;
-select * from t2;
+SELECT * FROM t2 ORDER BY a;
connection master;
drop procedure p1;
@@ -78,19 +84,19 @@ end//
delimiter ;//
call p1(f1(1), f1(2));
-select * from t1;
+SELECT * FROM t1 ORDER BY a;
create table t2(a int);
insert into t2 values (10),(11);
-select a,f1(a) from t2;
+SELECT a,f1(a) FROM t2 ORDER BY a;
# This shouldn't put separate 'call f1(3)' into binlog:
insert into t2 select f1(3);
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
connection master;
drop procedure p1;
@@ -102,11 +108,11 @@ delete from t1;
insert into t2 values(1),(2);
create view v1 as select f1(a) from t2;
select * from v1;
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
connection master;
drop view v1;
@@ -116,11 +122,11 @@ delete from t1;
prepare s1 from 'select f1(?)';
set @xx=123;
execute s1 using @xx;
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
connection master;
delete from t1;
@@ -140,10 +146,10 @@ begin
end//
delimiter ;//
call p1(15);
-select 'master:',a from t1;
+SELECT 'master:',a FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
-select 'slave:',a from t1;
+SELECT 'slave:',a FROM t1 ORDER BY a;
connection master;
drop procedure p1;
@@ -188,10 +194,10 @@ select f1();
set @x=30;
call p1();
-select 'master', a from t1;
+SELECT 'master', a FROM t1 ORDER BY a;
sync_slave_with_master;
connection slave;
-select 'slave', a from t1;
+SELECT 'slave', a FROM t1 ORDER BY a;
connection master;
drop table t1;
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index c4fe1906cbc..8e3c5847846 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -2871,3 +2871,18 @@ SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr
DROP TABLE t1,t2;
+
+#
+# Bug#18712: Truncation problem (needs just documenting and test
+# cases to prevent fixing this accidently. It is intended behaviour)
+#
+
+CREATE TABLE t1 (i TINYINT UNSIGNED NOT NULL);
+INSERT t1 SET i = 0;
+UPDATE t1 SET i = -1;
+SELECT * FROM t1;
+UPDATE t1 SET i = CAST(i - 1 AS SIGNED);
+SELECT * FROM t1;
+UPDATE t1 SET i = i - 1;
+SELECT * FROM t1;
+DROP TABLE t1;
diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test
index 4eb429156b2..0adbeb2d98b 100644
--- a/mysql-test/t/sp_notembedded.test
+++ b/mysql-test/t/sp_notembedded.test
@@ -1,6 +1,10 @@
# Can't test with embedded server
-- source include/not_embedded.inc
+--sleep 2
+--disable_warnings
+drop table if exists t1,t3;
+--enable_warnings
delimiter |;
#
diff --git a/mysql-test/t/timezone2.test b/mysql-test/t/timezone2.test
index 069c19341e4..bfc909d6995 100644
--- a/mysql-test/t/timezone2.test
+++ b/mysql-test/t/timezone2.test
@@ -3,6 +3,7 @@
# Preparing playground
--disable_warnings
drop table if exists t1, t2;
+drop function if exists f1;
--enable_warnings
@@ -222,3 +223,22 @@ select * from t1;
drop table t1;
# End of 4.1 tests
+
+#
+# Test for bug #11081 "Using a CONVERT_TZ function in a stored function
+# or trigger fails".
+#
+create table t1 (ldt datetime, udt datetime);
+create function f1(i datetime) returns datetime
+ return convert_tz(i, 'UTC', 'Europe/Moscow');
+create trigger t1_bi before insert on t1 for each row
+ set new.udt:= convert_tz(new.ldt, 'Europe/Moscow', 'UTC');
+# This should work without errors
+insert into t1 (ldt) values ('2006-04-19 16:30:00');
+select * from t1;
+# This should work without errors as well
+select ldt, f1(udt) as ldt2 from t1;
+drop table t1;
+drop function f1;
+
+# End of 5.0 tests
diff --git a/mysql-test/t/xml.test b/mysql-test/t/xml.test
index 8a12dbca51d..65d0a40291f 100644
--- a/mysql-test/t/xml.test
+++ b/mysql-test/t/xml.test
@@ -335,3 +335,11 @@ END//
DELIMITER ;//
CALL p2();
DROP PROCEDURE p2;
+
+#
+# Bug#18170: XML: ExtractValue():
+# XPath expression can't use QNames (colon in names)
+#
+select extractValue('','count(ns:element)');
+select extractValue('a','/ns:element');
+select extractValue('a','/ns:element/@xmlns:ns');
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 7a66164b775..abc5cc142f5 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -53,6 +53,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
charset.c charset-def.c my_bitmap.c my_bit.c md5.c \
my_gethostbyname.c rijndael.c my_aes.c sha1.c \
my_handler.c my_netware.c my_largepage.c \
+ my_memmem.c \
my_windac.c my_access.c base64.c
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
thr_mutex.c thr_rwlock.c \
diff --git a/mysys/cmakelists.txt b/mysys/cmakelists.txt
index 5a3b8f1657e..4aa99a70121 100644
--- a/mysys/cmakelists.txt
+++ b/mysys/cmakelists.txt
@@ -26,4 +26,4 @@ ADD_LIBRARY(mysys array.c charset-def.c charset.c checksum.c default.c default_m
my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c
my_windac.c my_winsem.c my_winthread.c my_write.c ptr_cmp.c queues.c
rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c
- thr_rwlock.c tree.c typelib.c my_vle.c base64.c)
+ thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c)
diff --git a/mysys/errors.c b/mysys/errors.c
index 4472b7173fa..5fe9eadb522 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -39,7 +39,7 @@ const char * NEAR globerrs[GLOBERRS]=
"Can't get working dirctory (Errcode: %d)",
"Can't change dir to '%s' (Errcode: %d)",
"Warning: '%s' had %d links",
- "%d files and %d streams is left open\n",
+ "Warning: %d files and %d streams is left open\n",
"Disk is full writing '%s' (Errcode: %d). Waiting for someone to free space... Retry in %d secs",
"Can't create directory '%s' (Errcode: %d)",
"Character set '%s' is not a compiled character set and is not specified in the '%s' file",
@@ -50,6 +50,7 @@ const char * NEAR globerrs[GLOBERRS]=
"Can't sync file '%s' to disk (Errcode: %d)",
"Collation '%s' is not a compiled collation and is not specified in the '%s' file",
"File '%s' not found (Errcode: %d)",
+ "File '%s' (fileno: %d) was not closed"
};
void init_glob_errs(void)
@@ -78,7 +79,7 @@ void init_glob_errs()
EE(EE_GETWD) = "Can't get working dirctory (Errcode: %d)";
EE(EE_SETWD) = "Can't change dir to '%s' (Errcode: %d)";
EE(EE_LINK_WARNING) = "Warning: '%s' had %d links";
- EE(EE_OPEN_WARNING) = "%d files and %d streams is left open\n";
+ EE(EE_OPEN_WARNING) = "Warning: %d files and %d streams is left open\n";
EE(EE_DISK_FULL) = "Disk is full writing '%s'. Waiting for someone to free space...";
EE(EE_CANT_MKDIR) ="Can't create directory '%s' (Errcode: %d)";
EE(EE_UNKNOWN_CHARSET)= "Character set '%s' is not a compiled character set and is not specified in the %s file";
@@ -89,5 +90,6 @@ void init_glob_errs()
EE(EE_SYNC)= "Can't sync file '%s' to disk (Errcode: %d)";
EE(EE_UNKNOWN_COLLATION)= "Collation '%s' is not a compiled collation and is not specified in the %s file";
EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)";
+ EE(EE_FILE_NOT_CLOSED) = "File '%s' (fileno: %d) was not closed";
}
#endif
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index e181ccfb88d..f1ea21c2a47 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -252,37 +252,89 @@ uint my_b_printf(IO_CACHE *info, const char* fmt, ...)
uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
{
uint out_length=0;
+ uint minimum_width; /* as yet unimplemented */
+ uint minimum_width_sign;
+ uint precision; /* as yet unimplemented for anything but %b */
- for (; *fmt ; fmt++)
+ /*
+ Store the location of the beginning of a format directive, for the
+ case where we learn we shouldn't have been parsing a format string
+ at all, and we don't want to lose the flag/precision/width/size
+ information.
+ */
+ const char* backtrack;
+
+ for (; *fmt != '\0'; fmt++)
{
- if (*fmt++ != '%')
+ /* Copy everything until '%' or end of string */
+ const char *start=fmt;
+ uint length;
+
+ for (; (*fmt != '\0') && (*fmt != '%'); fmt++) ;
+
+ length= (uint) (fmt - start);
+ out_length+=length;
+ if (my_b_write(info, start, length))
+ goto err;
+
+ if (*fmt == '\0') /* End of format */
{
- /* Copy everything until '%' or end of string */
- const char *start=fmt-1;
- uint length;
- for (; *fmt && *fmt != '%' ; fmt++ ) ;
- length= (uint) (fmt - start);
- out_length+=length;
- if (my_b_write(info, start, length))
- goto err;
- if (!*fmt) /* End of format */
- {
- return out_length;
- }
- fmt++;
- /* Found one '%' */
+ return out_length;
}
+
+ /*
+ By this point, *fmt must be a percent; Keep track of this location and
+ skip over the percent character.
+ */
+ DBUG_ASSERT(*fmt == '%');
+ backtrack= fmt;
+ fmt++;
+
+ minimum_width= 0;
+ precision= 0;
+ minimum_width_sign= 1;
/* Skip if max size is used (to be compatible with printf) */
- while (my_isdigit(&my_charset_latin1, *fmt) || *fmt == '.' || *fmt == '-')
+ while (*fmt == '-') { fmt++; minimum_width_sign= -1; }
+ if (*fmt == '*') {
+ precision= (int) va_arg(args, int);
fmt++;
+ } else {
+ while (my_isdigit(&my_charset_latin1, *fmt)) {
+ minimum_width=(minimum_width * 10) + (*fmt - '0');
+ fmt++;
+ }
+ }
+ minimum_width*= minimum_width_sign;
+
+ if (*fmt == '.') {
+ fmt++;
+ if (*fmt == '*') {
+ precision= (int) va_arg(args, int);
+ fmt++;
+ } else {
+ while (my_isdigit(&my_charset_latin1, *fmt)) {
+ precision=(precision * 10) + (*fmt - '0');
+ fmt++;
+ }
+ }
+ }
+
if (*fmt == 's') /* String parameter */
{
reg2 char *par = va_arg(args, char *);
uint length = (uint) strlen(par);
+ /* TODO: implement minimum width and precision */
out_length+=length;
if (my_b_write(info, par, length))
goto err;
}
+ else if (*fmt == 'b') /* Sized buffer parameter, only precision makes sense */
+ {
+ char *par = va_arg(args, char *);
+ out_length+= precision;
+ if (my_b_write(info, par, precision))
+ goto err;
+ }
else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
{
register int iarg;
@@ -317,9 +369,9 @@ uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
else
{
/* %% or unknown code */
- if (my_b_write(info, "%", 1))
- goto err;
- out_length++;
+ if (my_b_write(info, backtrack, fmt-backtrack))
+ goto err;
+ out_length+= fmt-backtrack;
}
}
return out_length;
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index bf8986fe05b..1dab9a47ed8 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -262,15 +262,9 @@ static int keycache_pthread_cond_signal(pthread_cond_t *cond);
#define keycache_pthread_cond_signal pthread_cond_signal
#endif /* defined(KEYCACHE_DEBUG) */
-static uint next_power(uint value)
+static inline uint next_power(uint value)
{
- uint old_value= 1;
- while (value)
- {
- old_value= value;
- value&= value-1;
- }
- return (old_value << 1);
+ return (uint) my_round_up_to_next_power((uint32) value) << 1;
}
diff --git a/mysys/my_bit.c b/mysys/my_bit.c
index 01c9b5ea68d..6ef0e171695 100644
--- a/mysys/my_bit.c
+++ b/mysys/my_bit.c
@@ -76,3 +76,33 @@ uint my_count_bits_ushort(ushort v)
return nbits[v];
}
+
+/*
+ Next highest power of two
+
+ SYNOPSIS
+ my_round_up_to_next_power()
+ v Value to check
+
+ RETURN
+ Next or equal power of 2
+ Note: 0 will return 0
+
+ NOTES
+ Algorithm by Sean Anderson, according to:
+ http://graphics.stanford.edu/~seander/bithacks.html
+ (Orignal code public domain)
+
+ Comments shows how this works with 01100000000000000000000000001011
+*/
+
+uint32 my_round_up_to_next_power(uint32 v)
+{
+ v--; /* 01100000000000000000000000001010 */
+ v|= v >> 1; /* 01110000000000000000000000001111 */
+ v|= v >> 2; /* 01111100000000000000000000001111 */
+ v|= v >> 4; /* 01111111110000000000000000001111 */
+ v|= v >> 8; /* 01111111111111111100000000001111 */
+ v|= v >> 16; /* 01111111111111111111111111111111 */
+ return v+1; /* 10000000000000000000000000000000 */
+}
diff --git a/mysys/my_file.c b/mysys/my_file.c
index 4c333c7d7db..0abc031a195 100644
--- a/mysys/my_file.c
+++ b/mysys/my_file.c
@@ -107,7 +107,10 @@ uint my_set_max_open_files(uint files)
DBUG_RETURN(MY_NFILE);
/* Copy any initialized files */
- memcpy((char*) tmp, (char*) my_file_info, sizeof(*tmp) * my_file_limit);
+ memcpy((char*) tmp, (char*) my_file_info,
+ sizeof(*tmp) * min(my_file_limit, files));
+ bzero((char*) (tmp + my_file_limit),
+ max((int) (files- my_file_limit), 0)*sizeof(*tmp));
my_free_open_file_info(); /* Free if already allocated */
my_file_info= tmp;
my_file_limit= files;
@@ -121,8 +124,12 @@ void my_free_open_file_info()
DBUG_ENTER("my_free_file_info");
if (my_file_info != my_file_info_default)
{
+ /* Copy data back for my_print_open_files */
+ memcpy((char*) my_file_info_default, my_file_info,
+ sizeof(*my_file_info_default)* MY_NFILE);
my_free((char*) my_file_info, MYF(0));
my_file_info= my_file_info_default;
+ my_file_limit= MY_NFILE;
}
DBUG_VOID_RETURN;
}
diff --git a/mysys/my_init.c b/mysys/my_init.c
index 88b8e457bd6..4d7299c7cb1 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -150,6 +150,7 @@ void my_end(int infoflag)
sprintf(errbuff[0],EE(EE_OPEN_WARNING),my_file_opened,my_stream_opened);
(void) my_message_no_curses(EE_OPEN_WARNING,errbuff[0],ME_BELL);
DBUG_PRINT("error",("%s",errbuff[0]));
+ my_print_open_files();
}
}
free_charsets();
diff --git a/mysys/my_memmem.c b/mysys/my_memmem.c
new file mode 100644
index 00000000000..682a1314f09
--- /dev/null
+++ b/mysys/my_memmem.c
@@ -0,0 +1,66 @@
+#include "my_base.h"
+
+/*
+ my_memmem, port of a GNU extension.
+
+ Returns a pointer to the beginning of the substring, needle, or NULL if the
+ substring is not found in haystack.
+*/
+void *my_memmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen)
+{
+ const unsigned char *cursor;
+ const unsigned char *last_possible_needle_location =
+ (unsigned char *)haystack + haystacklen - needlelen;
+
+ /* Easy answers */
+ if (needlelen > haystacklen) return(NULL);
+ if (needle == NULL) return(NULL);
+ if (haystack == NULL) return(NULL);
+ if (needlelen == 0) return(NULL);
+ if (haystacklen == 0) return(NULL);
+
+ for (cursor = haystack; cursor <= last_possible_needle_location; cursor++) {
+ if (memcmp(needle, cursor, needlelen) == 0) {
+ return((void *) cursor);
+ }
+ }
+ return(NULL);
+}
+
+
+
+#ifdef MAIN
+#include
+
+int main(int argc, char *argv[]) {
+ char haystack[10], needle[3];
+
+ memmove(haystack, "0123456789", 10);
+
+ memmove(needle, "no", 2);
+ assert(my_memmem(haystack, 10, needle, 2) == NULL);
+
+ memmove(needle, "345", 3);
+ assert(my_memmem(haystack, 10, needle, 3) != NULL);
+
+ memmove(needle, "789", 3);
+ assert(my_memmem(haystack, 10, needle, 3) != NULL);
+ assert(my_memmem(haystack, 9, needle, 3) == NULL);
+
+ memmove(needle, "012", 3);
+ assert(my_memmem(haystack, 10, needle, 3) != NULL);
+ assert(my_memmem(NULL, 10, needle, 3) == NULL);
+
+ assert(my_memmem(NULL, 10, needle, 3) == NULL);
+ assert(my_memmem(haystack, 0, needle, 3) == NULL);
+ assert(my_memmem(haystack, 10, NULL, 3) == NULL);
+ assert(my_memmem(haystack, 10, needle, 0) == NULL);
+
+ assert(my_memmem(haystack, 1, needle, 3) == NULL);
+
+ printf("success\n");
+ return(0);
+}
+
+#endif
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 098d410d8ce..ed323b3b1ad 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -351,3 +351,24 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode)
return fh; /* return handle */
}
#endif /* __WIN__ */
+
+
+#ifdef EXTRA_DEBUG
+
+void my_print_open_files(void)
+{
+ if (my_file_opened | my_stream_opened)
+ {
+ uint i;
+ for (i= 0 ; i < my_file_limit ; i++)
+ {
+ if (my_file_info[i].type != UNOPEN)
+ {
+ fprintf(stderr, EE(EE_FILE_NOT_CLOSED), my_file_info[i].name, i);
+ fputc('\n', stderr);
+ }
+ }
+ }
+}
+
+#endif
diff --git a/mysys/tree.c b/mysys/tree.c
index 1780913961e..0c9c04919b0 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -271,7 +271,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
return element;
}
-int tree_delete(TREE *tree, void *key, void *custom_arg)
+int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg)
{
int cmp,remove_colour;
TREE_ELEMENT *element,***parent, ***org_parent, *nod;
@@ -326,8 +326,7 @@ int tree_delete(TREE *tree, void *key, void *custom_arg)
rb_delete_fixup(tree,parent);
if (tree->free)
(*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
- /* This doesn't include key_size, but better than nothing */
- tree->allocated-= sizeof(TREE_ELEMENT)+tree->size_of_element;
+ tree->allocated-= sizeof(TREE_ELEMENT) + tree->size_of_element + key_size;
my_free((gptr) element,MYF(0));
tree->elements_in_tree--;
return 0;
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index d0f68a9c84b..6dee710103e 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -1,6 +1,28 @@
-SUBDIRS= fulltext
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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
+
+# Process this file with automake to create Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
# extra plugin example files are listed here, to
# keep its Makefile.am cleaner as a template
-EXTRA_DIST= fulltext/configure.in
+EXTRA_DIST = fulltext/configure.in
+SUBDIRS = @mysql_pg_dirs@
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/plugin/fulltext/plugin_example.c b/plugin/fulltext/plugin_example.c
index cdf1527b310..9b937453ce4 100644
--- a/plugin/fulltext/plugin_example.c
+++ b/plugin/fulltext/plugin_example.c
@@ -216,7 +216,7 @@ static struct st_mysql_show_var simple_status[]=
Plugin library descriptor
*/
-mysql_declare_plugin
+mysql_declare_plugin(ftexample)
{
MYSQL_FTPARSER_PLUGIN, /* type */
&simple_parser_descriptor, /* descriptor */
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 60e7891931f..ba9b58c0c5e 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -30,10 +30,7 @@ libexec_PROGRAMS = mysqld
noinst_PROGRAMS = gen_lex_hash
bin_PROGRAMS = mysql_tzinfo_to_sql
gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
-LDADD = $(top_builddir)/storage/myisam/libmyisam.a \
- $(top_builddir)/storage/myisammrg/libmyisammrg.a \
- $(top_builddir)/storage/heap/libheap.a \
- $(top_builddir)/vio/libvio.a \
+LDADD = $(top_builddir)/vio/libvio.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/regex/libregex.a \
@@ -41,7 +38,7 @@ LDADD = $(top_builddir)/storage/myisam/libmyisam.a \
mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \
@pstack_libs@ \
- @mysql_se_objs@ @mysql_se_libs@ \
+ @mysql_plugin_libs@ \
$(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ \
@yassl_libs@ @openssl_libs@
noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
@@ -53,20 +50,23 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_manager.h sql_map.h sql_string.h unireg.h \
sql_error.h field.h handler.h mysqld_suffix.h \
ha_heap.h ha_myisam.h ha_myisammrg.h ha_partition.h \
+ ha_innodb.h ha_berkeley.h ha_federated.h \
+ ha_ndbcluster.h ha_ndbcluster_binlog.h \
+ ha_ndbcluster_tables.h \
opt_range.h protocol.h rpl_tblmap.h \
log.h sql_show.h rpl_rli.h \
- sql_select.h structs.h table.h sql_udf.h hash_filo.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 rpl_filter.h \
rpl_injector.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\
+ 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 event.h event_priv.h \
sql_plugin.h authors.h sql_partition.h \
- partition_info.h partition_element.h
+ partition_info.h partition_element.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
@@ -79,7 +79,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.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_prepare.cc sql_error.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 \
@@ -87,6 +87,9 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.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_partition.cc ha_innodb.cc ha_berkeley.cc \
+ ha_federated.cc \
+ ha_ndbcluster.cc ha_ndbcluster_binlog.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 \
@@ -102,15 +105,9 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
sp_cache.cc parse_file.cc sql_trigger.cc \
event_executor.cc event.cc event_timed.cc \
sql_plugin.cc sql_binlog.cc \
- handlerton.cc sql_tablespace.cc partition_info.cc
-EXTRA_mysqld_SOURCES = ha_innodb.cc ha_berkeley.cc ha_archive.cc \
- ha_innodb.h ha_berkeley.h ha_archive.h \
- ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \
- ha_blackhole.h ha_federated.h ha_ndbcluster.h \
- ha_ndbcluster_binlog.cc ha_ndbcluster_binlog.h \
- ha_ndbcluster_tables.h \
- ha_partition.cc ha_partition.h
-mysqld_DEPENDENCIES = @mysql_se_objs@
+ sql_builtin.cc sql_tablespace.cc partition_info.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
@@ -162,6 +159,7 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS)
lex_hash.h: gen_lex_hash$(EXEEXT)
./gen_lex_hash$(EXEEXT) > $@
+# the following three should eventually be moved out of this directory
ha_berkeley.o: ha_berkeley.cc ha_berkeley.h
$(CXXCOMPILE) @bdb_includes@ $(LM_CFLAGS) -c $<
diff --git a/sql/cmakelists.txt b/sql/cmakelists.txt
index 381d22c605c..05b1efdbe51 100644
--- a/sql/cmakelists.txt
+++ b/sql/cmakelists.txt
@@ -16,7 +16,7 @@ SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/sql/message.rc
${CMAKE_SOURCE_DIR}/sql/sql_yacc.h
${CMAKE_SOURCE_DIR}/sql/sql_yacc.cc
${CMAKE_SOURCE_DIR}/include/mysql_version.h
- ${CMAKE_SOURCE_DIR}/sql/handlerton.cc
+ ${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc
${CMAKE_SOURCE_DIR}/sql/lex_hash.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h
${PROJECT_SOURCE_DIR}/include/mysqld_ername.h
@@ -29,7 +29,8 @@ ADD_DEFINITIONS(-DHAVE_ROW_BASED_REPLICATION -DMYSQL_SERVER
ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc
discover.cc ../libmysql/errmsg.c field.cc field_conv.cc
filesort.cc gstream.cc ha_heap.cc ha_myisam.cc ha_myisammrg.cc
- ${mysql_se_ha_src} handler.cc hash_filo.cc hash_filo.h
+ ha_innodb.cc ha_partition.cc ha_federated.cc ha_berkeley.cc
+ handler.cc hash_filo.cc hash_filo.h
hostname.cc init.cc item.cc item_buff.cc item_cmpfunc.cc
item_create.cc item_func.cc item_geofunc.cc item_row.cc
item_strfunc.cc item_subselect.cc item_sum.cc item_timefunc.cc
@@ -59,13 +60,19 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc
${PROJECT_SOURCE_DIR}/include/mysqld_ername.h
${PROJECT_SOURCE_DIR}/include/sql_state.h
${PROJECT_SOURCE_DIR}/include/mysql_version.h
- ${PROJECT_SOURCE_DIR}/sql/handlerton.cc
+ ${PROJECT_SOURCE_DIR}/sql/sql_builtin.cc
${PROJECT_SOURCE_DIR}/sql/lex_hash.h)
TARGET_LINK_LIBRARIES(mysqld heap myisam myisammrg mysys yassl zlib dbug yassl
taocrypt strings vio regex wsock32)
IF(WITH_ARCHIVE_STORAGE_ENGINE)
TARGET_LINK_LIBRARIES(mysqld archive)
ENDIF(WITH_ARCHIVE_STORAGE_ENGINE)
+IF(WITH_BLACKHOLE_STORAGE_ENGINE)
+ TARGET_LINK_LIBRARIES(mysqld blackhole)
+ENDIF(WITH_BLACKHOLE_STORAGE_ENGINE)
+IF(WITH_CSV_STORAGE_ENGINE)
+ TARGET_LINK_LIBRARIES(mysqld csv)
+ENDIF(WITH_CSV_STORAGE_ENGINE)
IF(WITH_EXAMPLE_STORAGE_ENGINE)
TARGET_LINK_LIBRARIES(mysqld example)
ENDIF(WITH_EXAMPLE_STORAGE_ENGINE)
diff --git a/sql/event_timed.cc b/sql/event_timed.cc
index adf28b8877c..879f4d6a3c9 100644
--- a/sql/event_timed.cc
+++ b/sql/event_timed.cc
@@ -19,10 +19,6 @@
#include "event.h"
#include "sp.h"
-
-
-extern int MYSQLparse(void *thd);
-
/*
Init all member variables
@@ -106,6 +102,9 @@ Event_timed::init_name(THD *thd, sp_name *spn)
NOTE
The body is extracted by copying all data between the
start of the body set by another method and the current pointer in Lex.
+
+ Some questionable removal of characters is done in here, and that part
+ should be refactored when the parser is smarter.
*/
void
@@ -116,9 +115,46 @@ Event_timed::init_body(THD *thd)
body_begin, thd->lex->ptr));
body.length= thd->lex->ptr - body_begin;
- /* Trim nuls at the end */
- while (body.length && body_begin[body.length-1] == '\0')
- body.length--;
+ const uchar *body_end= body_begin + body.length - 1;
+
+ /* Trim nuls or close-comments ('*'+'/') or spaces at the end */
+ while (body_begin < body_end)
+ {
+
+ if ((*body_end == '\0') ||
+ (my_isspace(thd->variables.character_set_client, *body_end)))
+ { /* consume NULs and meaningless whitespace */
+ --body.length;
+ --body_end;
+ continue;
+ }
+
+ /*
+ consume closing comments
+
+ This is arguably wrong, but it's the best we have until the parser is
+ changed to be smarter. FIXME PARSER
+
+ See also the sp_head code, where something like this is done also.
+
+ One idea is to keep in the lexer structure the count of the number of
+ open-comments we've entered, and scan left-to-right looking for a
+ closing comment IFF the count is greater than zero.
+
+ Another idea is to remove the closing comment-characters wholly in the
+ parser, since that's where it "removes" the opening characters.
+ */
+ if ((*(body_end - 1) == '*') && (*body_end == '/'))
+ {
+ DBUG_PRINT("info", ("consumend one '*" "/' comment in the query '%s'",
+ body_begin));
+ body.length-= 2;
+ body_end-= 2;
+ continue;
+ }
+
+ break; /* none were found, so we have excised all we can. */
+ }
/* the first is always whitespace which I cannot skip in the parser */
while (my_isspace(thd->variables.character_set_client, *body_begin))
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 6ea4cc9aeb5..473fb149871 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -56,10 +56,14 @@
#include
#include
#include
+
+#ifdef WITH_BERKELEY_STORAGE_ENGINE
#include "ha_berkeley.h"
#include "sql_manager.h"
#include
+#include
+
#define HA_BERKELEY_ROWS_IN_TABLE 10000 /* to get optimization right */
#define HA_BERKELEY_RANGE_COUNT 100
#define HA_BERKELEY_MAX_ROWS 10000000 /* Max rows in table */
@@ -121,11 +125,15 @@ static int berkeley_savepoint(THD* thd, void *savepoint);
static int berkeley_release_savepoint(THD* thd, void *savepoint);
static handler *berkeley_create_handler(TABLE_SHARE *table);
+static const char berkeley_hton_name[]= "BerkeleyDB";
+static const char berkeley_hton_comment[]=
+ "Supports transactions and page-level locking";
+
handlerton berkeley_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "BerkeleyDB",
+ berkeley_hton_name,
SHOW_OPTION_YES,
- "Supports transactions and page-level locking",
+ berkeley_hton_comment,
DB_TYPE_BERKELEY_DB,
berkeley_init,
0, /* slot */
@@ -2725,3 +2733,18 @@ bool ha_berkeley::check_if_incompatible_data(HA_CREATE_INFO *info,
}
+mysql_declare_plugin(berkeley)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &berkeley_hton,
+ berkeley_hton_name,
+ "Sleepycat Software",
+ berkeley_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ 0
+}
+mysql_declare_plugin_end;
+
+#endif
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index 129a44b5721..f4fc5f47193 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -351,9 +351,13 @@
#pragma implementation // gcc: Class implementation
#endif
+#ifdef WITH_FEDERATED_STORAGE_ENGINE
#include "ha_federated.h"
#include "m_string.h"
+
+#include
+
/* Variables for federated share methods */
static HASH federated_open_tables; // To track open tables
pthread_mutex_t federated_mutex; // To init the hash
@@ -366,11 +370,14 @@ static int federated_rollback(THD *thd, bool all);
/* Federated storage engine handlerton */
+static const char federated_hton_name[]= "FEDERATED";
+static const char federated_hton_comment[]= "Federated MySQL storage engine";
+
handlerton federated_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "FEDERATED",
+ federated_hton_name,
SHOW_OPTION_YES,
- "Federated MySQL storage engine",
+ federated_hton_comment,
DB_TYPE_FEDERATED_DB,
federated_db_init,
0, /* slot */
@@ -2804,3 +2811,18 @@ int ha_federated::execute_simple_query(const char *query, int len)
DBUG_RETURN(0);
}
+
+mysql_declare_plugin(federated)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &federated_hton,
+ federated_hton_name,
+ "Patrick Galbraith and Brian Aker, MySQL AB",
+ federated_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+}
+mysql_declare_plugin_end;
+
+#endif
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index f20dfe259fb..1a7efb42748 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -26,11 +26,15 @@
static handler *heap_create_handler(TABLE_SHARE *table);
+static const char heap_hton_name[]= "MEMORY";
+static const char heap_hton_comment[]=
+ "Hash based, stored in memory, useful for temporary tables";
+
handlerton heap_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "MEMORY",
+ heap_hton_name,
SHOW_OPTION_YES,
- "Hash based, stored in memory, useful for temporary tables",
+ heap_hton_comment,
DB_TYPE_HEAP,
NULL,
0, /* slot */
@@ -706,3 +710,17 @@ bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info,
return COMPATIBLE_DATA_NO;
return COMPATIBLE_DATA_YES;
}
+
+mysql_declare_plugin(heap)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &heap_hton,
+ heap_hton_name,
+ "MySQL AB",
+ heap_hton_comment,
+ NULL,
+ NULL,
+ 0x0100, /* 1.0 */
+ 0
+}
+mysql_declare_plugin_end;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 42def845174..0b2f561e8c9 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -42,6 +42,7 @@ have disables the InnoDB inlining in this file. */
#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
#include "ha_innodb.h"
pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */
@@ -204,11 +205,15 @@ static int innobase_savepoint(THD* thd, void *savepoint);
static int innobase_release_savepoint(THD* thd, void *savepoint);
static handler *innobase_create_handler(TABLE_SHARE *table);
+static const char innobase_hton_name[]= "InnoDB";
+static const char innobase_hton_comment[]=
+ "Supports transactions, row-level locking, and foreign keys";
+
handlerton innobase_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "InnoDB",
+ innobase_hton_name,
SHOW_OPTION_YES,
- "Supports transactions, row-level locking, and foreign keys",
+ innobase_hton_comment,
DB_TYPE_INNODB,
innobase_init,
0, /* slot */
@@ -5827,34 +5832,55 @@ ha_innobase::get_foreign_key_list(THD *thd, List *f_key_list)
break;
}
- ulong length= 0;
- if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) {
- length=17;
- tmp_buff= "ON DELETE CASCADE";
- }
- else if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
- length=18;
- tmp_buff= "ON DELETE SET NULL";
- }
- else if (foreign->type == DICT_FOREIGN_ON_DELETE_NO_ACTION) {
- length=19;
- tmp_buff= "ON DELETE NO ACTION";
- }
- else if (foreign->type == DICT_FOREIGN_ON_UPDATE_CASCADE) {
- length=17;
- tmp_buff= "ON UPDATE CASCADE";
- }
- else if (foreign->type == DICT_FOREIGN_ON_UPDATE_SET_NULL) {
- length=18;
- tmp_buff= "ON UPDATE SET NULL";
- }
- else if (foreign->type == DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
- length=19;
- tmp_buff= "ON UPDATE NO ACTION";
- }
- f_key_info.constraint_method= make_lex_string(thd,
- f_key_info.constraint_method,
- tmp_buff, length, 1);
+ ulong length;
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)
+ {
+ length=7;
+ tmp_buff= "CASCADE";
+ }
+ else if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
+ {
+ length=8;
+ tmp_buff= "SET NULL";
+ }
+ else if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION)
+ {
+ length=9;
+ tmp_buff= "NO ACTION";
+ }
+ else
+ {
+ length=8;
+ tmp_buff= "RESTRICT";
+ }
+ f_key_info.delete_method= make_lex_string(thd, f_key_info.delete_method,
+ tmp_buff, length, 1);
+
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)
+ {
+ length=7;
+ tmp_buff= "CASCADE";
+ }
+ else if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)
+ {
+ length=8;
+ tmp_buff= "SET NULL";
+ }
+ else if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION)
+ {
+ length=9;
+ tmp_buff= "NO ACTION";
+ }
+ else
+ {
+ length=8;
+ tmp_buff= "RESTRICT";
+ }
+ f_key_info.update_method= make_lex_string(thd, f_key_info.update_method,
+ tmp_buff, length, 1);
+
+
FOREIGN_KEY_INFO *pf_key_info= ((FOREIGN_KEY_INFO *)
thd->memdup((gptr) &f_key_info,
@@ -7432,3 +7458,20 @@ bool ha_innobase::check_if_incompatible_data(
return COMPATIBLE_DATA_YES;
}
+
+
+mysql_declare_plugin(innobase)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &innobase_hton,
+ innobase_hton_name,
+ "Innobase OY",
+ innobase_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ 0
+}
+mysql_declare_plugin_end;
+
+#endif
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index ec39ee00efc..786d45a4966 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -31,6 +31,8 @@
#include "../storage/myisam/rt_index.h"
#endif
+#include
+
ulong myisam_recover_options= HA_RECOVER_NONE;
/* bits in myisam_recover_options */
@@ -54,11 +56,15 @@ static handler *myisam_create_handler(TABLE_SHARE *table);
/* MyISAM handlerton */
+static const char myisam_hton_name[]= "MyISAM";
+static const char myisam_hton_comment[]=
+ "Default engine as of MySQL 3.23 with great performance";
+
handlerton myisam_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "MyISAM",
+ myisam_hton_name,
SHOW_OPTION_YES,
- "Default engine as of MySQL 3.23 with great performance",
+ myisam_hton_comment,
DB_TYPE_MYISAM,
NULL,
0, /* slot */
@@ -188,7 +194,7 @@ ha_myisam::ha_myisam(TABLE_SHARE *table_arg)
int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
HA_DUPP_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
HA_FILE_BASED | HA_CAN_GEOMETRY | HA_READ_RND_SAME |
- HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD),
+ HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS),
can_enable_indexes(1)
{}
@@ -350,6 +356,7 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
if (table->key_info[i].flags & HA_USES_PARSER)
file->s->keyinfo[i].parser=
(struct st_mysql_ftparser *)parser->plugin->info;
+ table->key_info[i].block_size= file->s->keyinfo[i].block_length;
}
return (0);
}
@@ -1368,7 +1375,7 @@ void ha_myisam::info(uint flag)
sortkey= info.sortkey;
ref_length= info.reflength;
share->db_options_in_use= info.options;
- block_size= myisam_block_size;
+ block_size= myisam_block_size; /* record block size */
/* Update share */
if (share->tmp_table == NO_TMP_TABLE)
@@ -1501,6 +1508,8 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
(pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
pos->algorithm;
+ keydef[i].block_length= pos->block_size;
+
keydef[i].seg=keyseg;
keydef[i].keysegs=pos->key_parts;
for (j=0 ; j < pos->key_parts ; j++)
@@ -1787,3 +1796,18 @@ bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info,
return COMPATIBLE_DATA_NO;
return COMPATIBLE_DATA_YES;
}
+
+
+mysql_declare_plugin(myisam)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisam_hton,
+ myisam_hton_name,
+ "MySQL AB",
+ myisam_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ 0
+}
+mysql_declare_plugin_end;
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 0ce4e1d8bcb..1cde37644bc 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -28,6 +28,8 @@
#include "../storage/myisammrg/myrg_def.h"
#endif
+#include
+
/*****************************************************************************
** MyISAM MERGE tables
*****************************************************************************/
@@ -36,11 +38,15 @@ static handler *myisammrg_create_handler(TABLE_SHARE *table);
/* MyISAM MERGE handlerton */
+static const char myisammrg_hton_name[]= "MRG_MYISAM";
+static const char myisammrg_hton_comment[]=
+ "Collection of identical MyISAM tables";
+
handlerton myisammrg_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "MRG_MYISAM",
+ myisammrg_hton_name,
SHOW_OPTION_YES,
- "Collection of identical MyISAM tables",
+ myisammrg_hton_comment,
DB_TYPE_MRG_MYISAM,
NULL,
0, /* slot */
@@ -573,3 +579,17 @@ bool ha_myisammrg::check_if_incompatible_data(HA_CREATE_INFO *info,
*/
return COMPATIBLE_DATA_NO;
}
+
+mysql_declare_plugin(myisammrg)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &myisammrg_hton,
+ myisammrg_hton_name,
+ "MySQL AB",
+ myisammrg_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ 0
+}
+mysql_declare_plugin_end;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index bc6a92368f6..5a1d4f48c9b 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -27,6 +27,7 @@
#include "mysql_priv.h"
#include
+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
#include "ha_ndbcluster.h"
#include
#include
@@ -36,6 +37,8 @@
#include "ha_ndbcluster_binlog.h"
#include "ha_ndbcluster_tables.h"
+#include
+
#ifdef ndb_dynamite
#undef assert
#define assert(x) do { if(x) break; ::printf("%s %d: assert failed: %s\n", __FILE__, __LINE__, #x); ::fflush(stdout); ::signal(SIGABRT,SIG_DFL); ::abort(); ::kill(::getpid(),6); ::kill(::getpid(),9); } while (0)
@@ -66,6 +69,9 @@ static bool ndbcluster_show_status(THD*,stat_print_fn *,enum ha_stat_type);
static int ndbcluster_alter_tablespace(THD* thd, st_alter_tablespace *info);
static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond);
+static const char ndbcluster_hton_name[]= "ndbcluster";
+static const char ndbcluster_hton_comment[]= "Clustered, fault-tolerant tables";
+
handlerton ndbcluster_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
"ndbcluster",
@@ -141,7 +147,7 @@ static int rename_share(NDB_SHARE *share, const char *new_key);
#endif
static void ndb_set_fragmentation(NDBTAB &tab, TABLE *table, uint pk_len);
-static int ndb_get_table_statistics(Ndb*, const char *,
+static int ndb_get_table_statistics(Ndb*, const NDBTAB *,
struct Ndb_statistics *);
@@ -431,7 +437,7 @@ void ha_ndbcluster::records_update()
Ndb *ndb= get_ndb();
ndb->setDatabaseName(m_dbname);
struct Ndb_statistics stat;
- if (ndb_get_table_statistics(ndb, m_tabname, &stat) == 0){
+ if (ndb_get_table_statistics(ndb, m_table, &stat) == 0){
mean_rec_length= stat.row_size;
data_file_length= stat.fragment_memory;
info->records= stat.row_count;
@@ -479,92 +485,6 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd)
DBUG_VOID_RETURN;
}
-/*
- Take care of the error that occured in NDB
-
- RETURN
- 0 No error
- # The mapped error code
-*/
-
-int ha_ndbcluster::invalidate_dictionary_cache(bool global, const NDBTAB *ndbtab)
-{
- NDBDICT *dict= get_ndb()->getDictionary();
- DBUG_ENTER("invalidate_dictionary_cache");
- DBUG_PRINT("info", ("m_tabname: %s global: %d", m_tabname, global));
-
- if (global)
- {
-#ifdef HAVE_NDB_BINLOG
- if (current_thd != injector_thd)
- {
- char key[FN_REFLEN];
- build_table_filename(key, sizeof(key), m_dbname, m_tabname, "");
- DBUG_PRINT("info", ("Getting ndbcluster mutex"));
- pthread_mutex_lock(&ndbcluster_mutex);
- NDB_SHARE *ndb_share= (NDB_SHARE*)hash_search(&ndbcluster_open_tables,
- (byte*) key, strlen(key));
- // Only binlog_thread is allowed to globally invalidate a table
- if (ndb_share && ndb_share->op)
- {
- pthread_mutex_unlock(&ndbcluster_mutex);
- DBUG_PRINT("info", ("Released ndbcluster mutex"));
- DBUG_RETURN(1);
- }
- pthread_mutex_unlock(&ndbcluster_mutex);
- DBUG_PRINT("info", ("Released ndbcluster mutex"));
- }
-#endif
- if (!ndbtab)
- {
- ndbtab= dict->getTable(m_tabname);
- if (!ndbtab)
- DBUG_RETURN(1);
- }
- dict->invalidateTable(ndbtab);
- table_share->version= 0L; /* Free when thread is ready */
- }
- else if (ndbtab)
- dict->removeCachedTable(ndbtab);
- else
- dict->removeCachedTable(m_tabname);
-
- /* Invalidate indexes */
- for (uint i= 0; i < table_share->keys; i++)
- {
- NDBINDEX *index = (NDBINDEX *) m_index[i].index;
- NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index;
- if (!index && !unique_index)
- continue;
- NDB_INDEX_TYPE idx_type= m_index[i].type;
-
- switch (idx_type) {
- case PRIMARY_KEY_ORDERED_INDEX:
- case ORDERED_INDEX:
- if (global)
- dict->invalidateIndex(index->getName(), m_tabname);
- else
- dict->removeCachedIndex(index->getName(), m_tabname);
- break;
- case UNIQUE_ORDERED_INDEX:
- if (global)
- dict->invalidateIndex(index->getName(), m_tabname);
- else
- dict->removeCachedIndex(index->getName(), m_tabname);
- case UNIQUE_INDEX:
- if (global)
- dict->invalidateIndex(unique_index->getName(), m_tabname);
- else
- dict->removeCachedIndex(unique_index->getName(), m_tabname);
- break;
- case PRIMARY_KEY_INDEX:
- case UNDEFINED_INDEX:
- break;
- }
- }
- DBUG_RETURN(0);
-}
-
int ha_ndbcluster::ndb_err(NdbTransaction *trans)
{
int res;
@@ -575,32 +495,14 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans)
switch (err.classification) {
case NdbError::SchemaError:
{
+ // TODO perhaps we need to do more here, invalidate also in the cache
+ m_table->setStatusInvalid();
/* Close other open handlers not used by any thread */
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
table_list.db= m_dbname;
table_list.alias= table_list.table_name= m_tabname;
close_cached_tables(current_thd, 0, &table_list);
-
- invalidate_dictionary_cache(TRUE, m_table);
-
- if (err.code==284)
- {
- /*
- Check if the table is _really_ gone or if the table has
- been alterend and thus changed table id
- */
- NDBDICT *dict= get_ndb()->getDictionary();
- DBUG_PRINT("info", ("Check if table %s is really gone", m_tabname));
- if (!(dict->getTable(m_tabname)))
- {
- err= dict->getNdbError();
- DBUG_PRINT("info", ("Table not found, error: %d", err.code));
- if (err.code != 709 && err.code != 723)
- DBUG_RETURN(1);
- }
- DBUG_PRINT("info", ("Table exists but must have changed"));
- }
break;
}
default:
@@ -1046,73 +948,59 @@ int ha_ndbcluster::get_metadata(const char *path)
NDBDICT *dict= ndb->getDictionary();
const NDBTAB *tab;
int error;
- bool invalidating_ndb_table= FALSE;
DBUG_ENTER("get_metadata");
DBUG_PRINT("enter", ("m_tabname: %s, path: %s", m_tabname, path));
- do {
- const void *data, *pack_data;
- uint length, pack_length;
+ DBUG_ASSERT(m_table == NULL);
+ DBUG_ASSERT(m_table_info == NULL);
- if (!(tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- // Check if thread has stale local cache
- if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- invalidate_dictionary_cache(FALSE, tab);
- if (!(tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
- }
- /*
- Compare FrmData in NDB with frm file from disk.
- */
- error= 0;
- if (readfrm(path, &data, &length) ||
- packfrm(data, length, &pack_data, &pack_length))
- {
- my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR));
- DBUG_RETURN(1);
- }
+ const void *data, *pack_data;
+ uint length, pack_length;
+
+ /*
+ Compare FrmData in NDB with frm file from disk.
+ */
+ error= 0;
+ if (readfrm(path, &data, &length) ||
+ packfrm(data, length, &pack_data, &pack_length))
+ {
+ my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR));
+ DBUG_RETURN(1);
+ }
- if (get_ndb_share_state(m_share) != NSS_ALTERED
- && cmp_frm(tab, pack_data, pack_length))
- {
- if (!invalidating_ndb_table)
- {
- DBUG_PRINT("info", ("Invalidating table"));
- invalidate_dictionary_cache(TRUE, tab);
- invalidating_ndb_table= TRUE;
- }
- else
- {
- DBUG_PRINT("error",
- ("metadata, pack_length: %d getFrmLength: %d memcmp: %d",
- pack_length, tab->getFrmLength(),
- memcmp(pack_data, tab->getFrmData(), pack_length)));
- DBUG_DUMP("pack_data", (char*)pack_data, pack_length);
- DBUG_DUMP("frm", (char*)tab->getFrmData(), tab->getFrmLength());
- error= HA_ERR_TABLE_DEF_CHANGED;
- invalidating_ndb_table= FALSE;
- }
- }
- else
- {
- invalidating_ndb_table= FALSE;
- }
- my_free((char*)data, MYF(0));
- my_free((char*)pack_data, MYF(0));
- } while (invalidating_ndb_table);
+ Ndb_table_guard ndbtab_g(dict, m_tabname);
+ if (!(tab= ndbtab_g.get_table()))
+ ERR_RETURN(dict->getNdbError());
+
+ if (get_ndb_share_state(m_share) != NSS_ALTERED
+ && cmp_frm(tab, pack_data, pack_length))
+ {
+ DBUG_PRINT("error",
+ ("metadata, pack_length: %d getFrmLength: %d memcmp: %d",
+ pack_length, tab->getFrmLength(),
+ memcmp(pack_data, tab->getFrmData(), pack_length)));
+ DBUG_DUMP("pack_data", (char*)pack_data, pack_length);
+ DBUG_DUMP("frm", (char*)tab->getFrmData(), tab->getFrmLength());
+ error= HA_ERR_TABLE_DEF_CHANGED;
+ }
+ my_free((char*)data, MYF(0));
+ my_free((char*)pack_data, MYF(0));
if (error)
- DBUG_RETURN(error);
-
- m_table_version= tab->getObjectVersion();
- m_table= tab;
- m_table_info= NULL; // Set in external lock
-
- DBUG_RETURN(open_indexes(ndb, table, FALSE));
+ goto err;
+
+ DBUG_PRINT("info", ("fetched table %s", tab->getName()));
+ m_table= tab;
+ if ((error= open_indexes(ndb, table, FALSE)) == 0)
+ {
+ ndbtab_g.release();
+ DBUG_RETURN(0);
+ }
+err:
+ ndbtab_g.invalidate();
+ m_table= NULL;
+ DBUG_RETURN(error);
}
static int fix_unique_index_attr_order(NDB_INDEX_DATA &data,
@@ -1149,36 +1037,6 @@ static int fix_unique_index_attr_order(NDB_INDEX_DATA &data,
DBUG_RETURN(0);
}
-int ha_ndbcluster::table_changed(const void *pack_frm_data, uint pack_frm_len)
-{
- Ndb *ndb;
- NDBDICT *dict;
- const NDBTAB *orig_tab;
- NdbDictionary::Table new_tab;
- int result;
- DBUG_ENTER("ha_ndbcluster::table_changed");
- DBUG_PRINT("info", ("Modifying frm for table %s", m_tabname));
- if (check_ndb_connection())
- DBUG_RETURN(my_errno= HA_ERR_NO_CONNECTION);
-
- ndb= get_ndb();
- dict= ndb->getDictionary();
- if (!(orig_tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- // Check if thread has stale local cache
- if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- dict->removeCachedTable(orig_tab);
- if (!(orig_tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- }
- new_tab= *orig_tab;
- new_tab.setFrm(pack_frm_data, pack_frm_len);
- if (dict->alterTable(new_tab) != 0)
- ERR_RETURN(dict->getNdbError());
- DBUG_RETURN(0);
-}
-
/*
Create all the indexes for a table.
If any index should fail to be created,
@@ -1209,22 +1067,30 @@ int ha_ndbcluster::create_indexes(Ndb *ndb, TABLE *tab)
DBUG_RETURN(error);
}
-void ha_ndbcluster::clear_index(int i)
+static void ndb_init_index(NDB_INDEX_DATA &data)
{
- m_index[i].type= UNDEFINED_INDEX;
- m_index[i].status= UNDEFINED;
- m_index[i].unique_index= NULL;
- m_index[i].index= NULL;
- m_index[i].unique_index_attrid_map= NULL;
- m_index[i].index_stat=NULL;
- m_index[i].index_stat_cache_entries=0;
- m_index[i].index_stat_update_freq=0;
- m_index[i].index_stat_query_count=0;
+ data.type= UNDEFINED_INDEX;
+ data.status= UNDEFINED;
+ data.unique_index= NULL;
+ data.index= NULL;
+ data.unique_index_attrid_map= NULL;
+ data.index_stat=NULL;
+ data.index_stat_cache_entries=0;
+ data.index_stat_update_freq=0;
+ data.index_stat_query_count=0;
}
-void ha_ndbcluster::clear_indexes()
+static void ndb_clear_index(NDB_INDEX_DATA &data)
{
- for (int i= 0; i < MAX_KEY; i++) clear_index(i);
+ if (data.unique_index_attrid_map)
+ {
+ my_free((char*)data.unique_index_attrid_map, MYF(0));
+ }
+ if (data.index_stat)
+ {
+ delete data.index_stat;
+ }
+ ndb_init_index(data);
}
/*
@@ -1246,7 +1112,7 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info,
const NDBINDEX *index;
do
{
- index= dict->getIndex(index_name, m_tabname);
+ index= dict->getIndexGlobal(index_name, *m_table);
if (!index)
ERR_RETURN(dict->getNdbError());
DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d",
@@ -1255,14 +1121,11 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info,
index->getObjectVersion() & 0xFFFFFF,
index->getObjectVersion() >> 24,
index->getObjectStatus()));
- if (index->getObjectStatus() != NdbDictionary::Object::Retrieved)
- {
- dict->removeCachedIndex(index);
- continue;
- }
+ DBUG_ASSERT(index->getObjectStatus() ==
+ NdbDictionary::Object::Retrieved);
break;
} while (1);
- m_index[index_no].index= (void *) index;
+ m_index[index_no].index= index;
// ordered index - add stats
NDB_INDEX_DATA& d=m_index[index_no];
delete d.index_stat;
@@ -1293,7 +1156,7 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info,
const NDBINDEX *index;
do
{
- index= dict->getIndex(unique_index_name, m_tabname);
+ index= dict->getIndexGlobal(unique_index_name, *m_table);
if (!index)
ERR_RETURN(dict->getNdbError());
DBUG_PRINT("info", ("index: 0x%x id: %d version: %d.%d status: %d",
@@ -1302,14 +1165,11 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info,
index->getObjectVersion() & 0xFFFFFF,
index->getObjectVersion() >> 24,
index->getObjectStatus()));
- if (index->getObjectStatus() != NdbDictionary::Object::Retrieved)
- {
- dict->removeCachedIndex(index);
- continue;
- }
+ DBUG_ASSERT(index->getObjectStatus() ==
+ NdbDictionary::Object::Retrieved);
break;
} while (1);
- m_index[index_no].unique_index= (void *) index;
+ m_index[index_no].unique_index= index;
error= fix_unique_index_attr_order(m_index[index_no], index, key_info);
}
if (!error)
@@ -1340,7 +1200,27 @@ int ha_ndbcluster::open_indexes(Ndb *ndb, TABLE *tab, bool ignore_error)
else
break;
}
-
+
+ if (error && !ignore_error)
+ {
+ while (i > 0)
+ {
+ i--;
+ if (m_index[i].index)
+ {
+ dict->removeIndexGlobal(*m_index[i].index, 1);
+ m_index[i].index= NULL;
+ }
+ if (m_index[i].unique_index)
+ {
+ dict->removeIndexGlobal(*m_index[i].unique_index, 1);
+ m_index[i].unique_index= NULL;
+ }
+ }
+ }
+
+ DBUG_ASSERT(error == 0 || error == 4243);
+
DBUG_RETURN(error);
}
@@ -1400,30 +1280,36 @@ int ha_ndbcluster::drop_indexes(Ndb *ndb, TABLE *tab)
m_index[i].type= idx_type;
if (m_index[i].status == TO_BE_DROPPED)
{
- NdbDictionary::Index *index=
- (NdbDictionary::Index *) m_index[i].index;
- NdbDictionary::Index *unique_index=
- (NdbDictionary::Index *) m_index[i].unique_index;
+ const NdbDictionary::Index *index= m_index[i].index;
+ const NdbDictionary::Index *unique_index= m_index[i].unique_index;
if (index)
{
index_name= index->getName();
DBUG_PRINT("info", ("Dropping index %u: %s", i, index_name));
// Drop ordered index from ndb
- error= drop_ndb_index(index_name);
+ error= dict->dropIndexGlobal(*index);
+ if (!error)
+ {
+ dict->removeIndexGlobal(*index, 1);
+ m_index[i].index= NULL;
+ }
}
- if (!error)
- m_index[i].index= NULL;
if (!error && unique_index)
{
index_name= unique_index->getName();
DBUG_PRINT("info", ("Dropping unique index %u: %s", i, index_name));
// Drop unique index from ndb
- error= drop_ndb_index(index_name);
+ error= dict->dropIndexGlobal(*unique_index);
+ if (!error)
+ {
+ dict->removeIndexGlobal(*unique_index, 1);
+ m_index[i].unique_index= NULL;
+ }
}
if (error)
DBUG_RETURN(error);
- clear_index(i);
+ ndb_clear_index(m_index[i]);
continue;
}
}
@@ -1476,30 +1362,46 @@ int ha_ndbcluster::check_index_fields_not_null(uint inx)
DBUG_RETURN(0);
}
-void ha_ndbcluster::release_metadata()
+void ha_ndbcluster::release_metadata(THD *thd, Ndb *ndb)
{
uint i;
DBUG_ENTER("release_metadata");
DBUG_PRINT("enter", ("m_tabname: %s", m_tabname));
- m_table= NULL;
+ NDBDICT *dict= ndb->getDictionary();
+ int invalidate_indexes= 0;
+ if (thd && thd->lex && thd->lex->sql_command == SQLCOM_FLUSH)
+ {
+ invalidate_indexes = 1;
+ }
+ if (m_table != NULL)
+ {
+ if (m_table->getObjectStatus() == NdbDictionary::Object::Invalid)
+ invalidate_indexes= 1;
+ dict->removeTableGlobal(*m_table, invalidate_indexes);
+ }
+ // TODO investigate
+ DBUG_ASSERT(m_table_info == NULL);
m_table_info= NULL;
// Release index list
for (i= 0; i < MAX_KEY; i++)
{
- m_index[i].unique_index= NULL;
- m_index[i].index= NULL;
- if (m_index[i].unique_index_attrid_map)
+ if (m_index[i].unique_index)
{
- my_free((char *)m_index[i].unique_index_attrid_map, MYF(0));
- m_index[i].unique_index_attrid_map= NULL;
+ DBUG_ASSERT(m_table != NULL);
+ dict->removeIndexGlobal(*m_index[i].unique_index, invalidate_indexes);
}
- delete m_index[i].index_stat;
- m_index[i].index_stat=NULL;
+ if (m_index[i].index)
+ {
+ DBUG_ASSERT(m_table != NULL);
+ dict->removeIndexGlobal(*m_index[i].index, invalidate_indexes);
+ }
+ ndb_clear_index(m_index[i]);
}
+ m_table= NULL;
DBUG_VOID_RETURN;
}
@@ -1971,11 +1873,10 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record)
{
// A unique index is defined on table
NdbIndexOperation *iop;
- NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index;
+ const NDBINDEX *unique_index = m_index[i].unique_index;
key_part= key_info->key_part;
end= key_part + key_info->key_parts;
- if (!(iop= trans->getNdbIndexOperation(unique_index,
- (const NDBTAB *) m_table)) ||
+ if (!(iop= trans->getNdbIndexOperation(unique_index, m_table)) ||
iop->readTuple(lm) != 0)
ERR_RETURN(trans->getNdbError());
@@ -2024,9 +1925,8 @@ int ha_ndbcluster::unique_index_read(const byte *key,
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
- if (!(op= trans->getNdbIndexOperation((NDBINDEX *)
- m_index[active_index].unique_index,
- (const NDBTAB *) m_table)) ||
+ if (!(op= trans->getNdbIndexOperation(m_index[active_index].unique_index,
+ m_table)) ||
op->readTuple(lm) != 0)
ERR_RETURN(trans->getNdbError());
@@ -2365,9 +2265,8 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
restart= FALSE;
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
- if (!(op= trans->getNdbIndexScanOperation((NDBINDEX *)
- m_index[active_index].index,
- (const NDBTAB *) m_table)) ||
+ if (!(op= trans->getNdbIndexScanOperation(m_index[active_index].index,
+ m_table)) ||
op->readTuples(lm, 0, parallelism, sorted, descending))
ERR_RETURN(trans->getNdbError());
if (m_use_partition_function && part_spec != NULL &&
@@ -2437,7 +2336,7 @@ int ha_ndbcluster::full_table_scan(byte *buf)
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
- if (!(op=trans->getNdbScanOperation((const NDBTAB *) m_table)) ||
+ if (!(op=trans->getNdbScanOperation(m_table)) ||
op->readTuples(lm, 0, parallelism))
ERR_RETURN(trans->getNdbError());
m_active_cursor= op;
@@ -2539,7 +2438,7 @@ int ha_ndbcluster::write_row(byte *record)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
- if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)))
+ if (!(op= trans->getNdbOperation(m_table)))
ERR_RETURN(trans->getNdbError());
res= (m_use_write) ? op->writeTuple() :op->insertTuple();
@@ -2565,7 +2464,7 @@ int ha_ndbcluster::write_row(byte *record)
Uint64 auto_value= NDB_FAILED_AUTO_INCREMENT;
uint retries= NDB_AUTO_INCREMENT_RETRIES;
do {
- auto_value= ndb->getAutoIncrementValue((const NDBTAB *) m_table);
+ auto_value= ndb->getAutoIncrementValue(m_table);
} while (auto_value == NDB_FAILED_AUTO_INCREMENT &&
--retries &&
ndb->getNdbError().status == NdbError::TemporaryError);
@@ -2666,7 +2565,7 @@ int ha_ndbcluster::write_row(byte *record)
DBUG_PRINT("info",
("Trying to set next auto increment value to %lu",
(ulong) next_val));
- if (ndb->setAutoIncrementValue((const NDBTAB *) m_table, next_val, TRUE))
+ if (ndb->setAutoIncrementValue(m_table, next_val, TRUE))
DBUG_PRINT("info",
("Setting next auto increment value to %u", next_val));
}
@@ -2816,7 +2715,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
}
else
{
- if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
+ if (!(op= trans->getNdbOperation(m_table)) ||
op->updateTuple() != 0)
ERR_RETURN(trans->getNdbError());
@@ -2925,7 +2824,7 @@ int ha_ndbcluster::delete_row(const byte *record)
else
{
- if (!(op=trans->getNdbOperation((const NDBTAB *) m_table)) ||
+ if (!(op=trans->getNdbOperation(m_table)) ||
op->deleteTuple() != 0)
ERR_RETURN(trans->getNdbError());
@@ -2976,7 +2875,7 @@ void ndb_unpack_record(TABLE *table, NdbValue *value,
MY_BITMAP *defined, byte *buf)
{
Field **p_field= table->field, *field= *p_field;
- uint row_offset= (uint) (buf - table->record[0]);
+ my_ptrdiff_t row_offset= buf - table->record[0];
DBUG_ENTER("ndb_unpack_record");
// Set null flag(s)
@@ -3007,24 +2906,34 @@ void ndb_unpack_record(TABLE *table, NdbValue *value,
}
else if (field->type() == MYSQL_TYPE_BIT)
{
- byte *save_field_ptr= field->ptr;
- field->ptr= save_field_ptr + row_offset;
+ Field_bit *field_bit= static_cast(field);
+
+ /*
+ Move internal field pointer to point to 'buf'. Calling
+ the correct member function directly since we know the
+ type of the object.
+ */
+ field_bit->Field_bit::move_field_offset(row_offset);
if (field->pack_length() < 5)
{
DBUG_PRINT("info", ("bit field H'%.8X",
(*value).rec->u_32_value()));
- ((Field_bit*) field)->store((longlong)
- (*value).rec->u_32_value(), FALSE);
+ field_bit->Field_bit::store((longlong) (*value).rec->u_32_value(),
+ FALSE);
}
else
{
DBUG_PRINT("info", ("bit field H'%.8X%.8X",
*(Uint32*) (*value).rec->aRef(),
*((Uint32*) (*value).rec->aRef()+1)));
- ((Field_bit*) field)->store((longlong)
- (*value).rec->u_64_value(),TRUE);
+ field_bit->Field_bit::store((longlong) (*value).rec->u_64_value(),
+ TRUE);
}
- field->ptr= save_field_ptr;
+ /*
+ Move back internal field pointer to point to original
+ value (usually record[0]).
+ */
+ field_bit->Field_bit::move_field_offset(-row_offset);
DBUG_PRINT("info",("[%u] SET",
(*value).rec->getColumn()->getColumnNo()));
DBUG_DUMP("info", (const char*) field->ptr, field->field_length);
@@ -3078,7 +2987,7 @@ void ha_ndbcluster::unpack_record(byte *buf)
{
// Table with hidden primary key
int hidden_no= table_share->fields;
- const NDBTAB *tab= (const NDBTAB *) m_table;
+ const NDBTAB *tab= m_table;
const NDBCOL *hidden_col= tab->getColumn(hidden_no);
const NdbRecAttr* rec= m_value[hidden_no].rec;
DBUG_ASSERT(rec);
@@ -3554,7 +3463,7 @@ void ha_ndbcluster::position(const byte *record)
key_length= ref_length;
#ifndef DBUG_OFF
int hidden_no= table->s->fields;
- const NDBTAB *tab= (const NDBTAB *) m_table;
+ const NDBTAB *tab= m_table;
const NDBCOL *hidden_col= tab->getColumn(hidden_no);
DBUG_ASSERT(hidden_col->getPrimaryKey() &&
hidden_col->getAutoIncrement() &&
@@ -3600,7 +3509,7 @@ void ha_ndbcluster::info(uint flag)
ndb->setDatabaseName(m_dbname);
struct Ndb_statistics stat;
if (current_thd->variables.ndb_use_exact_count &&
- ndb_get_table_statistics(ndb, m_tabname, &stat) == 0)
+ ndb_get_table_statistics(ndb, m_table, &stat) == 0)
{
mean_rec_length= stat.row_size;
data_file_length= stat.fragment_memory;
@@ -3631,7 +3540,7 @@ void ha_ndbcluster::info(uint flag)
Ndb *ndb= get_ndb();
auto_increment_value=
- ndb->readAutoIncrementValue((const NDBTAB *) m_table);
+ ndb->readAutoIncrementValue(m_table);
}
}
DBUG_VOID_RETURN;
@@ -3715,7 +3624,7 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
void ha_ndbcluster::start_bulk_insert(ha_rows rows)
{
int bytes, batch;
- const NDBTAB *tab= (const NDBTAB *) m_table;
+ const NDBTAB *tab= m_table;
DBUG_ENTER("start_bulk_insert");
DBUG_PRINT("enter", ("rows: %d", (int)rows));
@@ -3994,41 +3903,8 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
// Start of transaction
m_rows_changed= 0;
m_ops_pending= 0;
- {
- NDBDICT *dict= ndb->getDictionary();
- const NDBTAB *tab;
- if (!(tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("Table schema version: %d",
- tab->getObjectVersion()));
- // Check if thread has stale local cache
- // New transaction must not use old tables... (trans != 0)
- // Running might...
- if ((trans && tab->getObjectStatus() != NdbDictionary::Object::Retrieved)
- || tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- invalidate_dictionary_cache(FALSE, tab);
- if (!(tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("Table schema version: %d",
- tab->getObjectVersion()));
- }
- if (m_table_version < tab->getObjectVersion())
- {
- /*
- The table has been altered, caller has to retry
- */
- NdbError err= ndb->getNdbError(NDB_INVALID_SCHEMA_OBJECT);
- DBUG_RETURN(ndb_to_mysql_error(&err));
- }
- if (m_table != (void *)tab)
- {
- m_table= tab;
- m_table_version = tab->getObjectVersion();
- if (!(my_errno= open_indexes(ndb, table, FALSE)))
- DBUG_RETURN(my_errno);
- }
- }
+
+ // TODO remove double pointers...
m_thd_ndb_share= thd_ndb->get_open_table(thd, m_table);
m_table_info= &m_thd_ndb_share->stat;
}
@@ -4565,8 +4441,11 @@ int ha_ndbcluster::create(const char *name,
if (readfrm(name, &data, &length))
DBUG_RETURN(1);
if (packfrm(data, length, &pack_data, &pack_length))
+ {
+ my_free((char*)data, MYF(0));
DBUG_RETURN(2);
-
+ }
+
DBUG_PRINT("info", ("setFrm data=%lx len=%d", pack_data, pack_length));
tab.setFrm(pack_data, pack_length);
my_free((char*)data, MYF(0));
@@ -4673,6 +4552,14 @@ int ha_ndbcluster::create(const char *name,
my_errno= ndb_to_mysql_error(&err);
DBUG_RETURN(my_errno);
}
+
+ Ndb_table_guard ndbtab_g(dict, m_tabname);
+ // temporary set m_table during create
+ // reset at return
+ m_table= ndbtab_g.get_table();
+ // TODO check also that we have the same frm...
+ DBUG_ASSERT(m_table != 0);
+
DBUG_PRINT("info", ("Table %s/%s created successfully",
m_dbname, m_tabname));
@@ -4687,7 +4574,10 @@ int ha_ndbcluster::create(const char *name,
Failed to create an index,
drop the table (and all it's indexes)
*/
- drop_ndb_table();
+ if (dict->dropTableGlobal(*m_table) == 0)
+ {
+ m_table = 0;
+ }
}
#ifdef HAVE_NDB_BINLOG
@@ -4717,7 +4607,6 @@ int ha_ndbcluster::create(const char *name,
while (!IS_TMP_PREFIX(m_tabname))
{
- const NDBTAB *t= dict->getTable(m_tabname);
String event_name(INJECTOR_EVENT_LEN);
ndb_rep_event_name(&event_name,m_dbname,m_tabname);
int do_event_op= ndb_binlog_running;
@@ -4731,14 +4620,14 @@ int ha_ndbcluster::create(const char *name,
Always create an event for the table, as other mysql servers
expect it to be there.
*/
- if (!ndbcluster_create_event(ndb, t, event_name.c_ptr(), share,
+ if (!ndbcluster_create_event(ndb, m_table, event_name.c_ptr(), share,
share && do_event_op /* push warning */))
{
if (ndb_extra_logging)
sql_print_information("NDB Binlog: CREATE TABLE Event: %s",
event_name.c_ptr());
if (share && do_event_op &&
- ndbcluster_create_event_ops(share, t, event_name.c_ptr()))
+ ndbcluster_create_event_ops(share, m_table, event_name.c_ptr()))
{
sql_print_error("NDB Binlog: FAILED CREATE TABLE event operations."
" Event: %s", name);
@@ -4754,13 +4643,15 @@ int ha_ndbcluster::create(const char *name,
ndbcluster_log_schema_op(current_thd, share,
current_thd->query, current_thd->query_length,
share->db, share->table_name,
- 0, 0,
+ m_table->getObjectId(),
+ m_table->getObjectVersion(),
SOT_CREATE_TABLE);
break;
}
}
#endif /* HAVE_NDB_BINLOG */
+ m_table= 0;
DBUG_RETURN(my_errno);
}
@@ -4790,10 +4681,15 @@ int ha_ndbcluster::create_handler_files(const char *file,
NDBDICT *dict= ndb->getDictionary();
if (!info->frm_only)
DBUG_RETURN(0); // Must be a create, ignore since frm is saved in create
+
+ // TODO handle this
+ DBUG_ASSERT(m_table != 0);
+
set_dbname(file);
set_tabname(file);
+ Ndb_table_guard ndbtab_g(dict, m_tabname);
DBUG_PRINT("info", ("m_dbname: %s, m_tabname: %s", m_dbname, m_tabname));
- if (!(tab= dict->getTable(m_tabname)))
+ if (!(tab= ndbtab_g.get_table()))
DBUG_RETURN(0); // Unkown table, must be temporary table
DBUG_ASSERT(get_ndb_share_state(m_share) == NSS_ALTERED);
@@ -4809,7 +4705,12 @@ int ha_ndbcluster::create_handler_files(const char *file,
{
DBUG_PRINT("info", ("Table %s has changed, altering frm in ndb",
m_tabname));
- error= table_changed(pack_data, pack_length);
+ NdbDictionary::Table new_tab= *tab;
+ new_tab.setFrm(pack_data, pack_length);
+ if (dict->alterTableGlobal(*tab, new_tab))
+ {
+ error= ndb_to_mysql_error(&dict->getNdbError());
+ }
my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR));
}
@@ -4912,7 +4813,7 @@ int ha_ndbcluster::create_ndb_index(const char *name,
ndb_index.addColumnName(field->field_name);
}
- if (dict->createIndex(ndb_index))
+ if (dict->createIndex(ndb_index, *m_table))
ERR_RETURN(dict->getNdbError());
// Success
@@ -4965,18 +4866,6 @@ int ha_ndbcluster::add_index(TABLE *table_arg,
DBUG_RETURN(error);
}
-/*
- Drop an index in ndb
- */
-int ha_ndbcluster::drop_ndb_index(const char *name)
-{
- DBUG_ENTER("ha_ndbcluster::drop_index");
- DBUG_PRINT("enter", ("name: %s ", name));
- Ndb *ndb= get_ndb();
- NdbDictionary::Dictionary *dict= ndb->getDictionary();
- DBUG_RETURN(dict->dropIndex(name, m_tabname));
-}
-
/*
Mark one or several indexes for deletion. and
renumber the remaining indexes
@@ -5045,16 +4934,14 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
Ndb *ndb= get_ndb();
ndb->setDatabaseName(old_dbname);
dict= ndb->getDictionary();
- if (!(orig_tab= dict->getTable(m_tabname)))
+ Ndb_table_guard ndbtab_g(dict, m_tabname);
+ if (!(orig_tab= ndbtab_g.get_table()))
ERR_RETURN(dict->getNdbError());
- // Check if thread has stale local cache
- if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- dict->removeCachedTable(orig_tab);
- if (!(orig_tab= dict->getTable(m_tabname)))
- ERR_RETURN(dict->getNdbError());
- }
+
#ifdef HAVE_NDB_BINLOG
+ int ndb_table_id= orig_tab->getObjectId();
+ int ndb_table_version= orig_tab->getObjectVersion();
+
NDB_SHARE *share= get_share(from, 0, false);
if (share)
{
@@ -5062,13 +4949,15 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
DBUG_ASSERT(r == 0);
}
#endif
- m_table= orig_tab;
// Change current database to that of target table
set_dbname(to);
ndb->setDatabaseName(m_dbname);
- if ((result= alter_table_name(new_tabname)))
+ NdbDictionary::Table new_tab= *orig_tab;
+ new_tab.setName(new_tabname);
+ if (dict->alterTableGlobal(*orig_tab, new_tab) != 0)
{
+ NdbError ndb_error= dict->getNdbError();
#ifdef HAVE_NDB_BINLOG
if (share)
{
@@ -5077,7 +4966,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
free_share(&share);
}
#endif
- DBUG_RETURN(result);
+ ERR_RETURN(ndb_error);
}
// Rename .ndb file
@@ -5111,7 +5000,8 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
/* always create an event for the table */
String event_name(INJECTOR_EVENT_LEN);
ndb_rep_event_name(&event_name, to + sizeof(share_prefix) - 1, 0);
- const NDBTAB *ndbtab= dict->getTable(new_tabname);
+ Ndb_table_guard ndbtab_g2(dict, new_tabname);
+ const NDBTAB *ndbtab= ndbtab_g2.get_table();
if (!ndbcluster_create_event(ndb, ndbtab, event_name.c_ptr(), share,
share && ndb_binlog_running /* push warning */))
@@ -5134,10 +5024,10 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
if (!is_old_table_tmpfile)
ndbcluster_log_schema_op(current_thd, share,
current_thd->query, current_thd->query_length,
- m_dbname, new_tabname,
- 0, 0,
+ old_dbname, m_tabname,
+ ndb_table_id, ndb_table_version,
SOT_RENAME_TABLE,
- old_dbname, m_tabname);
+ m_dbname, new_tabname);
}
if (share)
free_share(&share);
@@ -5147,30 +5037,6 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
}
-/*
- Rename a table in NDB Cluster using alter table
- */
-
-int ha_ndbcluster::alter_table_name(const char *to)
-{
- Ndb *ndb= get_ndb();
- NDBDICT *dict= ndb->getDictionary();
- const NDBTAB *orig_tab= (const NDBTAB *) m_table;
- DBUG_ENTER("alter_table_name");
- DBUG_PRINT("info", ("from: %s to: %s", orig_tab->getName(), to));
-
- NdbDictionary::Table new_tab= *orig_tab;
- new_tab.setName(to);
- if (dict->alterTable(new_tab) != 0)
- ERR_RETURN(dict->getNdbError());
-
- m_table= NULL;
- m_table_info= NULL;
-
- DBUG_RETURN(0);
-}
-
-
/*
Delete table from NDB Cluster
@@ -5187,6 +5053,8 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb,
DBUG_ENTER("ha_ndbcluster::ndbcluster_delete_table");
NDBDICT *dict= ndb->getDictionary();
#ifdef HAVE_NDB_BINLOG
+ int ndb_table_id= 0;
+ int ndb_table_version= 0;
/*
Don't allow drop table unless
schema distribution table is setup
@@ -5202,14 +5070,45 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb,
/* Drop the table from NDB */
int res;
- if (h)
+ if (h && h->m_table)
{
- res= h->drop_ndb_table();
+ if (dict->dropTableGlobal(*h->m_table))
+ res= ndb_to_mysql_error(&dict->getNdbError());
+#ifdef HAVE_NDB_BINLOG
+ if (res == 0)
+ {
+ ndb_table_id= h->m_table->getObjectId();
+ ndb_table_version= h->m_table->getObjectVersion();
+ }
+#endif
+ h->release_metadata(current_thd, ndb);
}
else
{
ndb->setDatabaseName(db);
- res= dict->dropTable(table_name);
+ while (1)
+ {
+ Ndb_table_guard ndbtab_g(dict, table_name);
+ if (ndbtab_g.get_table())
+ {
+ if (dict->dropTableGlobal(*ndbtab_g.get_table()) == 0)
+ {
+#ifdef HAVE_NDB_BINLOG
+ ndb_table_id= ndbtab_g.get_table()->getObjectId();
+ ndb_table_version= ndbtab_g.get_table()->getObjectVersion();
+#endif
+ res= 0;
+ }
+ else if (dict->getNdbError().code == NDB_INVALID_SCHEMA_OBJECT)
+ {
+ ndbtab_g.invalidate();
+ continue;
+ }
+ }
+ else
+ res= ndb_to_mysql_error(&dict->getNdbError());
+ break;
+ }
}
if (res)
@@ -5251,7 +5150,7 @@ ha_ndbcluster::delete_table(ha_ndbcluster *h, Ndb *ndb,
ndbcluster_log_schema_op(current_thd, share,
current_thd->query, current_thd->query_length,
share->db, share->table_name,
- 0, 0,
+ ndb_table_id, ndb_table_version,
SOT_DROP_TABLE);
}
else if (table_dropped && share && share->op) /* ndbcluster_log_schema_op
@@ -5315,24 +5214,6 @@ int ha_ndbcluster::delete_table(const char *name)
}
-/*
- Drop table in NDB Cluster
- */
-
-int ha_ndbcluster::drop_ndb_table()
-{
- Ndb *ndb= get_ndb();
- NdbDictionary::Dictionary *dict= ndb->getDictionary();
-
- DBUG_ENTER("intern_drop_table");
- DBUG_PRINT("enter", ("Deleting %s", m_tabname));
- release_metadata();
- if (dict->dropTable(m_tabname))
- ERR_RETURN(dict->getNdbError());
- DBUG_RETURN(0);
-}
-
-
ulonglong ha_ndbcluster::get_auto_increment()
{
int cache_size;
@@ -5356,8 +5237,8 @@ ulonglong ha_ndbcluster::get_auto_increment()
do {
auto_value=
(m_skip_auto_increment) ?
- ndb->readAutoIncrementValue((const NDBTAB *) m_table)
- : ndb->getAutoIncrementValue((const NDBTAB *) m_table, cache_size);
+ ndb->readAutoIncrementValue(m_table)
+ : ndb->getAutoIncrementValue(m_table, cache_size);
} while (auto_value == NDB_FAILED_AUTO_INCREMENT &&
--retries &&
ndb->getNdbError().status == NdbError::TemporaryError);
@@ -5391,7 +5272,6 @@ ha_ndbcluster::ha_ndbcluster(TABLE_SHARE *table_arg):
m_active_trans(NULL),
m_active_cursor(NULL),
m_table(NULL),
- m_table_version(-1),
m_table_info(NULL),
m_table_flags(HA_NDBCLUSTER_TABLE_FLAGS),
m_share(0),
@@ -5431,25 +5311,38 @@ ha_ndbcluster::ha_ndbcluster(TABLE_SHARE *table_arg):
records= ~(ha_rows)0; // uninitialized
block_size= 1024;
- clear_indexes();
+ for (i= 0; i < MAX_KEY; i++)
+ ndb_init_index(m_index[i]);
DBUG_VOID_RETURN;
}
+int ha_ndbcluster::ha_initialise()
+{
+ DBUG_ENTER("ha_ndbcluster::ha_initialise");
+ if (check_ndb_in_thd(current_thd))
+ {
+ DBUG_RETURN(FALSE);
+ }
+ DBUG_RETURN(TRUE);
+}
+
/*
Destructor for NDB Cluster table handler
*/
ha_ndbcluster::~ha_ndbcluster()
{
+ THD *thd= current_thd;
+ Ndb *ndb= thd ? check_ndb_in_thd(thd) : g_ndb;
DBUG_ENTER("~ha_ndbcluster");
if (m_share)
{
free_share(&m_share);
}
- release_metadata();
+ release_metadata(thd, ndb);
my_free(m_blobs_buffer, MYF(MY_ALLOW_ZERO_PTR));
m_blobs_buffer= 0;
@@ -5564,10 +5457,12 @@ void ha_ndbcluster::set_part_info(partition_info *part_info)
int ha_ndbcluster::close(void)
{
- DBUG_ENTER("close");
+ DBUG_ENTER("close");
+ THD *thd= current_thd;
+ Ndb *ndb= thd ? check_ndb_in_thd(thd) : g_ndb;
free_share(&m_share);
m_share= 0;
- release_metadata();
+ release_metadata(thd, ndb);
DBUG_RETURN(0);
}
@@ -5655,9 +5550,10 @@ static int ndbcluster_close_connection(THD *thd)
int ndbcluster_discover(THD* thd, const char *db, const char *name,
const void** frmblob, uint* frmlen)
{
+ int error= 0;
+ NdbError ndb_error;
uint len;
const void* data;
- const NDBTAB* tab;
Ndb* ndb;
char key[FN_REFLEN];
DBUG_ENTER("ndbcluster_discover");
@@ -5667,7 +5563,6 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
DBUG_RETURN(HA_ERR_NO_CONNECTION);
ndb->setDatabaseName(db);
NDBDICT* dict= ndb->getDictionary();
- dict->invalidateTable(name);
build_table_filename(key, sizeof(key), db, name, "");
NDB_SHARE *share= get_share(key, 0, false);
if (share && get_ndb_share_state(share) == NSS_ALTERED)
@@ -5676,21 +5571,22 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
if (readfrm(key, &data, &len))
{
DBUG_PRINT("error", ("Could not read frm"));
- if (share)
- free_share(&share);
- DBUG_RETURN(1);
+ error= 1;
+ goto err;
}
}
else
{
- if (!(tab= dict->getTable(name)))
- {
+ Ndb_table_guard ndbtab_g(dict, name);
+ const NDBTAB *tab= ndbtab_g.get_table();
+ if (!tab)
+ {
const NdbError err= dict->getNdbError();
- if (share)
- free_share(&share);
if (err.code == 709 || err.code == 723)
- DBUG_RETURN(-1);
- ERR_RETURN(err);
+ error= -1;
+ else
+ ndb_error= err;
+ goto err;
}
DBUG_PRINT("info", ("Found table %s", tab->getName()));
@@ -5698,17 +5594,15 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
if (len == 0 || tab->getFrmData() == NULL)
{
DBUG_PRINT("error", ("No frm data found."));
- if (share)
- free_share(&share);
- DBUG_RETURN(1);
+ error= 1;
+ goto err;
}
if (unpackfrm(&data, &len, tab->getFrmData()))
{
DBUG_PRINT("error", ("Could not unpack table"));
- if (share)
- free_share(&share);
- DBUG_RETURN(1);
+ error= 1;
+ goto err;
}
}
@@ -5719,6 +5613,14 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
free_share(&share);
DBUG_RETURN(0);
+err:
+ if (share)
+ free_share(&share);
+ if (ndb_error.code)
+ {
+ ERR_RETURN(ndb_error);
+ }
+ DBUG_RETURN(error);
}
/*
@@ -5726,29 +5628,32 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
*/
-int ndbcluster_table_exists_in_engine(THD* thd, const char *db, const char *name)
+int ndbcluster_table_exists_in_engine(THD* thd, const char *db,
+ const char *name)
{
- const NDBTAB* tab;
Ndb* ndb;
DBUG_ENTER("ndbcluster_table_exists_in_engine");
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
if (!(ndb= check_ndb_in_thd(thd)))
DBUG_RETURN(HA_ERR_NO_CONNECTION);
- ndb->setDatabaseName(db);
NDBDICT* dict= ndb->getDictionary();
- dict->invalidateTable(name);
- if (!(tab= dict->getTable(name)))
+ NdbDictionary::Dictionary::List list;
+ if (dict->listObjects(list, NdbDictionary::Object::UserTable) != 0)
+ ERR_RETURN(dict->getNdbError());
+ for (int i= 0 ; i < list.count ; i++)
{
- const NdbError err= dict->getNdbError();
- if (err.code == 709 || err.code == 723)
- DBUG_RETURN(0);
- ERR_RETURN(err);
+ NdbDictionary::Dictionary::List::Element& elmt= list.elements[i];
+ if (my_strcasecmp(system_charset_info, elmt.database, db))
+ continue;
+ if (my_strcasecmp(system_charset_info, elmt.name, name))
+ continue;
+ // table found
+ DBUG_PRINT("info", ("Found table"));
+ DBUG_RETURN(1);
}
-
- DBUG_PRINT("info", ("Found table %s", tab->getName()));
- DBUG_RETURN(1);
+ DBUG_RETURN(0);
}
@@ -5902,9 +5807,9 @@ int ndbcluster_find_all_files(THD *thd)
}
ndb->setDatabaseName(elmt.database);
- const NDBTAB *ndbtab;
-
- if (!(ndbtab= dict->getTable(elmt.name)))
+ Ndb_table_guard ndbtab_g(dict, elmt.name);
+ const NDBTAB *ndbtab= ndbtab_g.get_table();
+ if (!ndbtab)
{
if (retries == 0)
sql_print_error("NDB: failed to setup table %s.%s, error: %d, %s",
@@ -6184,11 +6089,13 @@ static int connect_callback()
return 0;
}
+extern int ndb_dictionary_is_mysqld;
static bool ndbcluster_init()
{
int res;
DBUG_ENTER("ndbcluster_init");
+ ndb_dictionary_is_mysqld= 1;
if (have_ndbcluster != SHOW_OPTION_YES)
goto ndbcluster_init_error;
@@ -6320,6 +6227,24 @@ static int ndbcluster_end(ha_panic_function type)
if (!ndbcluster_inited)
DBUG_RETURN(0);
+#ifdef HAVE_NDB_BINLOG
+ {
+ pthread_mutex_lock(&ndbcluster_mutex);
+ while (ndbcluster_open_tables.records)
+ {
+ NDB_SHARE *share=
+ (NDB_SHARE*) hash_element(&ndbcluster_open_tables, 0);
+#ifndef DBUG_OFF
+ fprintf(stderr, "NDB: table share %s with use_count %d not freed\n",
+ share->key, share->use_count);
+#endif
+ real_free_share(&share);
+ }
+ pthread_mutex_unlock(&ndbcluster_mutex);
+ }
+#endif
+ hash_free(&ndbcluster_open_tables);
+
if (g_ndb)
{
#ifndef DBUG_OFF
@@ -6341,23 +6266,6 @@ static int ndbcluster_end(ha_panic_function type)
delete g_ndb_cluster_connection;
g_ndb_cluster_connection= NULL;
-#ifdef HAVE_NDB_BINLOG
- {
- pthread_mutex_lock(&ndbcluster_mutex);
- for (uint i= 0; i < ndbcluster_open_tables.records; i++)
- {
- NDB_SHARE *share=
- (NDB_SHARE*) hash_element(&ndbcluster_open_tables, i);
-#ifndef DBUG_OFF
- fprintf(stderr, "NDB: table share %s with use_count %d not freed\n",
- share->key, share->use_count);
-#endif
- real_free_share(&share);
- }
- pthread_mutex_unlock(&ndbcluster_mutex);
- }
-#endif
- hash_free(&ndbcluster_open_tables);
pthread_mutex_destroy(&ndbcluster_mutex);
pthread_mutex_destroy(&LOCK_ndb_util_thread);
pthread_cond_destroy(&COND_ndb_util_thread);
@@ -6518,7 +6426,7 @@ ha_ndbcluster::records_in_range(uint inx, key_range *min_key,
m_index[inx].index_stat != NULL)
{
NDB_INDEX_DATA& d=m_index[inx];
- NDBINDEX* index=(NDBINDEX*)d.index;
+ const NDBINDEX* index= d.index;
Ndb* ndb=get_ndb();
NdbTransaction* trans=NULL;
NdbIndexScanOperation* op=NULL;
@@ -6538,7 +6446,7 @@ ha_ndbcluster::records_in_range(uint inx, key_range *min_key,
else
{
Ndb_statistics stat;
- if ((res=ndb_get_table_statistics(ndb, m_tabname, &stat)) != 0)
+ if ((res=ndb_get_table_statistics(ndb, m_table, &stat)) != 0)
break;
table_rows=stat.row_count;
DBUG_PRINT("info", ("use db row_count: %llu", table_rows));
@@ -6552,7 +6460,8 @@ ha_ndbcluster::records_in_range(uint inx, key_range *min_key,
}
// Define scan op for the range
- if ((trans=m_active_trans) == NULL)
+ if ((trans=m_active_trans) == NULL ||
+ trans->commitStatus() != NdbTransaction::Started)
{
DBUG_PRINT("info", ("no active trans"));
if (! (trans=ndb->startTransaction()))
@@ -6699,10 +6608,14 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname,
pthread_mutex_unlock(&share->mutex);
struct Ndb_statistics stat;
- if (ndb_get_table_statistics(ndb, tabname, &stat))
{
- free_share(&share);
- DBUG_RETURN(1);
+ Ndb_table_guard ndbtab_g(ndb->getDictionary(), tabname);
+ if (ndbtab_g.get_table() == 0
+ || ndb_get_table_statistics(ndb, ndbtab_g.get_table(), &stat))
+ {
+ free_share(&share);
+ DBUG_RETURN(1);
+ }
}
pthread_mutex_lock(&share->mutex);
@@ -6916,7 +6829,11 @@ int handle_trailing_share(NDB_SHARE *share)
++share->use_count;
pthread_mutex_unlock(&ndbcluster_mutex);
- close_cached_tables((THD*) 0, 0, (TABLE_LIST*) 0, TRUE);
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+ table_list.db= share->db;
+ table_list.alias= table_list.table_name= share->table_name;
+ close_cached_tables(current_thd, 0, &table_list, TRUE);
pthread_mutex_lock(&ndbcluster_mutex);
if (!--share->use_count)
@@ -7262,15 +7179,17 @@ void ndbcluster_free_share(NDB_SHARE **share, bool have_lock)
static
int
-ndb_get_table_statistics(Ndb* ndb, const char * table,
+ndb_get_table_statistics(Ndb* ndb, const NDBTAB *ndbtab,
struct Ndb_statistics * ndbstat)
{
DBUG_ENTER("ndb_get_table_statistics");
- DBUG_PRINT("enter", ("table: %s", table));
+ DBUG_PRINT("enter", ("table: %s", ndbtab->getName()));
NdbTransaction* pTrans;
int retries= 10;
int retry_sleep= 30 * 1000; /* 30 milliseconds */
+ DBUG_ASSERT(ndbtab != 0);
+
do
{
pTrans= ndb->startTransaction();
@@ -7285,7 +7204,7 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
ERR_RETURN(ndb->getNdbError());
}
- NdbScanOperation* pOp= pTrans->getNdbScanOperation(table);
+ NdbScanOperation* pOp= pTrans->getNdbScanOperation(ndbtab);
if (pOp == NULL)
break;
@@ -7446,9 +7365,9 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
byte *end_of_buffer= (byte*)buffer->buffer_end;
NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
- const NDBTAB *tab= (const NDBTAB *) m_table;
- const NDBINDEX *unique_idx= (NDBINDEX *) m_index[active_index].unique_index;
- const NDBINDEX *idx= (NDBINDEX *) m_index[active_index].index;
+ const NDBTAB *tab= m_table;
+ const NDBINDEX *unique_idx= m_index[active_index].unique_index;
+ const NDBINDEX *idx= m_index[active_index].index;
const NdbOperation* lastOp= m_active_trans->getLastDefinedOperation();
NdbIndexScanOperation* scanOp= 0;
for (; multi_range_currsetDatabaseName(m_dbname);
NDBDICT* dict= ndb->getDictionary();
- const NDBTAB* tab;
- if (!(tab= dict->getTable(m_tabname)))
- {
- return((char*)comment);
- }
+ const NDBTAB* tab= m_table;
+ DBUG_ASSERT(tab != NULL);
char *str;
const char *fmt="%s%snumber_of_replicas: %d";
@@ -7987,18 +7903,22 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
lock= share->commit_count_lock;
pthread_mutex_unlock(&share->mutex);
- if (ndb_get_table_statistics(ndb, share->table_name, &stat) == 0)
{
- DBUG_PRINT("ndb_util_thread",
- ("Table: %s, commit_count: %llu, rows: %llu",
- share->key, stat.commit_count, stat.row_count));
- }
- else
- {
- DBUG_PRINT("ndb_util_thread",
- ("Error: Could not get commit count for table %s",
- share->key));
- stat.commit_count= 0;
+ Ndb_table_guard ndbtab_g(ndb->getDictionary(), share->table_name);
+ if (ndbtab_g.get_table() &&
+ ndb_get_table_statistics(ndb, ndbtab_g.get_table(), &stat) == 0)
+ {
+ DBUG_PRINT("ndb_util_thread",
+ ("Table: %s, commit_count: %llu, rows: %llu",
+ share->key, stat.commit_count, stat.row_count));
+ }
+ else
+ {
+ DBUG_PRINT("ndb_util_thread",
+ ("Error: Could not get commit count for table %s",
+ share->key));
+ stat.commit_count= 0;
+ }
}
pthread_mutex_lock(&share->mutex);
@@ -9390,12 +9310,8 @@ char* ha_ndbcluster::get_tablespace_name(THD *thd)
NdbError ndberr;
Uint32 id;
ndb->setDatabaseName(m_dbname);
- const NDBTAB *ndbtab= ndbdict->getTable(m_tabname);
- if (ndbtab == 0)
- {
- ndberr= ndbdict->getNdbError();
- goto err;
- }
+ const NDBTAB *ndbtab= m_table;
+ DBUG_ASSERT(ndbtab != NULL);
if (!ndbtab->getTablespace(&id))
{
return 0;
@@ -10060,17 +9976,10 @@ bool ha_ndbcluster::get_no_parts(const char *name, uint *no_parts)
}
ndb= get_ndb();
ndb->setDatabaseName(m_dbname);
- dict= ndb->getDictionary();
- if (!(tab= dict->getTable(m_tabname)))
+ Ndb_table_guard ndbtab_g(dict= ndb->getDictionary(), m_tabname);
+ if (!ndbtab_g.get_table())
ERR_BREAK(dict->getNdbError(), err);
- // Check if thread has stale local cache
- if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
- {
- invalidate_dictionary_cache(FALSE, tab);
- if (!(tab= dict->getTable(m_tabname)))
- ERR_BREAK(dict->getNdbError(), err);
- }
- *no_parts= tab->getFragmentCount();
+ *no_parts= ndbtab_g.get_table()->getFragmentCount();
DBUG_RETURN(FALSE);
} while (1);
@@ -10278,3 +10187,20 @@ static int ndbcluster_fill_files_table(THD *thd, TABLE_LIST *tables, COND *cond)
}
DBUG_RETURN(0);
}
+
+
+mysql_declare_plugin(ndbcluster)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &ndbcluster_hton,
+ ndbcluster_hton_name,
+ "MySQL AB",
+ ndbcluster_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+ 0
+}
+mysql_declare_plugin_end;
+
+#endif
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 0af65a373bd..f407cb0090f 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -70,8 +70,8 @@ typedef enum ndb_index_status {
typedef struct ndb_index_data {
NDB_INDEX_TYPE type;
NDB_INDEX_STATUS status;
- void *index;
- void *unique_index;
+ const NdbDictionary::Index *index;
+ const NdbDictionary::Index *unique_index;
unsigned char *unique_index_attrid_map;
// In this version stats are not shared between threads
NdbIndexStat* index_stat;
@@ -560,6 +560,7 @@ class ha_ndbcluster: public handler
ha_ndbcluster(TABLE_SHARE *table);
~ha_ndbcluster();
+ int ha_initialise();
int open(const char *name, int mode, uint test_if_locked);
int close(void);
@@ -708,23 +709,17 @@ private:
Ndb *ndb, NdbEventOperation *pOp,
NDB_SHARE *share);
- int alter_table_name(const char *to);
static int delete_table(ha_ndbcluster *h, Ndb *ndb,
const char *path,
const char *db,
const char *table_name);
- int drop_ndb_table();
int create_ndb_index(const char *name, KEY *key_info, bool unique);
int create_ordered_index(const char *name, KEY *key_info);
int create_unique_index(const char *name, KEY *key_info);
int create_index(const char *name, KEY *key_info,
NDB_INDEX_TYPE idx_type, uint idx_no);
- int drop_ndb_index(const char *name);
- int table_changed(const void *pack_frm_data, uint pack_frm_len);
// Index list management
int create_indexes(Ndb *ndb, TABLE *tab);
- void clear_index(int i);
- void clear_indexes();
int open_indexes(Ndb *ndb, TABLE *tab, bool ignore_error);
void renumber_indexes(Ndb *ndb, TABLE *tab);
int drop_indexes(Ndb *ndb, TABLE *tab);
@@ -732,7 +727,7 @@ private:
KEY *key_info, const char *index_name, uint index_no);
int initialize_autoincrement(const void *table);
int get_metadata(const char* path);
- void release_metadata();
+ void release_metadata(THD *thd, Ndb *ndb);
NDB_INDEX_TYPE get_index_type(uint idx_no) const;
NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const;
NDB_INDEX_TYPE get_index_type_from_key(uint index_no, KEY *key_info,
@@ -795,8 +790,6 @@ private:
void print_results();
ulonglong get_auto_increment();
- int invalidate_dictionary_cache(bool global,
- const NdbDictionary::Table *ndbtab);
int ndb_err(NdbTransaction*);
bool uses_blob_value();
@@ -834,7 +827,6 @@ private:
NdbTransaction *m_active_trans;
NdbScanOperation *m_active_cursor;
const NdbDictionary::Table *m_table;
- int m_table_version;
struct Ndb_local_table_statistics *m_table_info;
char m_dbname[FN_HEADLEN];
//char m_schemaname[FN_HEADLEN];
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index a39d92ae7a5..e358c87b378 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -16,6 +16,7 @@
*/
#include "mysql_priv.h"
+#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
#include "ha_ndbcluster.h"
#ifdef HAVE_NDB_BINLOG
@@ -254,7 +255,7 @@ ndbcluster_binlog_close_table(THD *thd, NDB_SHARE *share)
DBUG_ENTER("ndbcluster_binlog_close_table");
if (share->table_share)
{
- free_table_share(share->table_share);
+ closefrm(share->table, 1);
share->table_share= 0;
share->table= 0;
}
@@ -986,7 +987,7 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
uint32 ndb_table_id,
uint32 ndb_table_version,
enum SCHEMA_OP_TYPE type,
- const char *old_db, const char *old_table_name)
+ const char *new_db, const char *new_table_name)
{
DBUG_ENTER("ndbcluster_log_schema_op");
Thd_ndb *thd_ndb= get_thd_ndb(thd);
@@ -1026,8 +1027,8 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
/* redo the rename table query as is may contain several tables */
query= tmp_buf2;
query_length= (uint) (strxmov(tmp_buf2, "rename table `",
- old_db, ".", old_table_name, "` to `",
- db, ".", table_name, "`", NullS) - tmp_buf2);
+ db, ".", table_name, "` to `",
+ new_db, ".", new_table_name, "`", NullS) - tmp_buf2);
type_str= "rename table";
break;
case SOT_CREATE_TABLE:
@@ -1067,6 +1068,8 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
Uint64 epoch= 0;
MY_BITMAP schema_subscribers;
uint32 bitbuf[sizeof(ndb_schema_object->slock)/4];
+ uint32 bitbuf_e[sizeof(bitbuf)];
+ bzero((char *)bitbuf_e, sizeof(bitbuf_e));
{
int i, updated= 0;
int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes();
@@ -1110,7 +1113,8 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
char tmp_buf[FN_REFLEN];
NDBDICT *dict= ndb->getDictionary();
ndb->setDatabaseName(NDB_REP_DB);
- const NDBTAB *ndbtab= dict->getTable(NDB_SCHEMA_TABLE);
+ Ndb_table_guard ndbtab_g(dict, NDB_SCHEMA_TABLE);
+ const NDBTAB *ndbtab= ndbtab_g.get_table();
NdbTransaction *trans= 0;
int retries= 100;
const NDBCOL *col[SCHEMA_SIZE];
@@ -1141,8 +1145,13 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
while (1)
{
+ const char *log_db= db;
+ const char *log_tab= table_name;
+ const char *log_subscribers= (char*)schema_subscribers.bitmap;
+ uint32 log_type= (uint32)type;
if ((trans= ndb->startTransaction()) == 0)
goto err;
+ while (1)
{
NdbOperation *op= 0;
int r= 0;
@@ -1152,17 +1161,17 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
DBUG_ASSERT(r == 0);
/* db */
- ndb_pack_varchar(col[SCHEMA_DB_I], tmp_buf, db, strlen(db));
+ ndb_pack_varchar(col[SCHEMA_DB_I], tmp_buf, log_db, strlen(log_db));
r|= op->equal(SCHEMA_DB_I, tmp_buf);
DBUG_ASSERT(r == 0);
/* name */
- ndb_pack_varchar(col[SCHEMA_NAME_I], tmp_buf, table_name,
- strlen(table_name));
+ ndb_pack_varchar(col[SCHEMA_NAME_I], tmp_buf, log_tab,
+ strlen(log_tab));
r|= op->equal(SCHEMA_NAME_I, tmp_buf);
DBUG_ASSERT(r == 0);
/* slock */
DBUG_ASSERT(sz[SCHEMA_SLOCK_I] == sizeof(bitbuf));
- r|= op->setValue(SCHEMA_SLOCK_I, (char*)schema_subscribers.bitmap);
+ r|= op->setValue(SCHEMA_SLOCK_I, log_subscribers);
DBUG_ASSERT(r == 0);
/* query */
{
@@ -1186,8 +1195,17 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
r|= op->setValue(SCHEMA_VERSION_I, ndb_table_version);
DBUG_ASSERT(r == 0);
/* type */
- r|= op->setValue(SCHEMA_TYPE_I, (uint32)type);
+ r|= op->setValue(SCHEMA_TYPE_I, log_type);
DBUG_ASSERT(r == 0);
+ if (log_db != new_db && new_db && new_table_name)
+ {
+ log_db= new_db;
+ log_tab= new_table_name;
+ log_subscribers= (const char *)bitbuf_e; // no ack expected on this
+ log_type= (uint32)SOT_RENAME_TABLE_NEW;
+ continue;
+ }
+ break;
}
if (trans->execute(NdbTransaction::Commit) == 0)
{
@@ -1306,7 +1324,8 @@ ndbcluster_update_slock(THD *thd,
char tmp_buf[FN_REFLEN];
NDBDICT *dict= ndb->getDictionary();
ndb->setDatabaseName(NDB_REP_DB);
- const NDBTAB *ndbtab= dict->getTable(NDB_SCHEMA_TABLE);
+ Ndb_table_guard ndbtab_g(dict, NDB_SCHEMA_TABLE);
+ const NDBTAB *ndbtab= ndbtab_g.get_table();
NdbTransaction *trans= 0;
int retries= 100;
const NDBCOL *col[SCHEMA_SIZE];
@@ -1439,7 +1458,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
{
DBUG_ENTER("ndb_handle_schema_change");
TABLE* table= share->table;
- TABLE_SHARE *table_share= table->s;
+ TABLE_SHARE *table_share= share->table_share;
const char *dbname= table_share->db.str;
const char *tabname= table_share->table_name.str;
bool do_close_cached_tables= FALSE;
@@ -1452,31 +1471,28 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
{
if (pOp->tableFrmChanged())
{
+ DBUG_PRINT("info", ("NDBEVENT::TE_ALTER: table frm changed"));
is_online_alter_table= TRUE;
}
else
{
+ DBUG_PRINT("info", ("NDBEVENT::TE_ALTER: name changed"));
DBUG_ASSERT(pOp->tableNameChanged());
is_rename_table= TRUE;
}
}
- /*
- Refresh local dictionary cache by
- invalidating table and all it's indexes
- */
- ndb->setDatabaseName(dbname);
- Thd_ndb *thd_ndb= get_thd_ndb(thd);
- DBUG_ASSERT(thd_ndb != NULL);
- Ndb* old_ndb= thd_ndb->ndb;
- thd_ndb->ndb= ndb;
- ha_ndbcluster table_handler(table_share);
- (void)strxmov(table_handler.m_dbname, dbname, NullS);
- (void)strxmov(table_handler.m_tabname, tabname, NullS);
- table_handler.open_indexes(ndb, table, TRUE);
- table_handler.invalidate_dictionary_cache(TRUE, 0);
- thd_ndb->ndb= old_ndb;
-
+ {
+ ndb->setDatabaseName(dbname);
+ Ndb_table_guard ndbtab_g(ndb->getDictionary(), tabname);
+ const NDBTAB *ev_tab= pOp->getTable();
+ const NDBTAB *cache_tab= ndbtab_g.get_table();
+ if (cache_tab &&
+ cache_tab->getObjectId() == ev_tab->getObjectId() &&
+ cache_tab->getObjectVersion() <= ev_tab->getObjectVersion())
+ ndbtab_g.invalidate();
+ }
+
/*
Refresh local frm file and dictionary cache if
remote on-line alter table
@@ -1505,11 +1521,14 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
DBUG_DUMP("frm", (char*)altered_table->getFrmData(),
altered_table->getFrmLength());
pthread_mutex_lock(&LOCK_open);
- const NDBTAB *old= dict->getTable(tabname);
+ Ndb_table_guard ndbtab_g(dict, tabname);
+ const NDBTAB *old= ndbtab_g.get_table();
if (!old &&
old->getObjectVersion() != altered_table->getObjectVersion())
dict->putTable(altered_table);
+ my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
+ data= NULL;
if ((error= unpackfrm(&data, &length, altered_table->getFrmData())) ||
(error= writefrm(key, data, length)))
{
@@ -1517,13 +1536,21 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
dbname, tabname, error);
}
ndbcluster_binlog_close_table(thd, share);
- close_cached_tables((THD*) 0, 0, (TABLE_LIST*) 0, TRUE);
+
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+ table_list.db= (char *)dbname;
+ table_list.alias= table_list.table_name= (char *)tabname;
+ close_cached_tables(thd, 0, &table_list, TRUE);
+
if ((error= ndbcluster_binlog_open_table(thd, share,
table_share, table)))
sql_print_information("NDB: Failed to re-open table %s.%s",
dbname, tabname);
pthread_mutex_unlock(&LOCK_open);
}
+ my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR));
}
// If only frm was changed continue replicating
@@ -1545,26 +1572,22 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
share_prefix, share->table->s->db.str,
share->table->s->table_name.str,
share->key);
+ {
+ ndb->setDatabaseName(share->table->s->db.str);
+ Ndb_table_guard ndbtab_g(ndb->getDictionary(),
+ share->table->s->table_name.str);
+ const NDBTAB *ev_tab= pOp->getTable();
+ const NDBTAB *cache_tab= ndbtab_g.get_table();
+ if (cache_tab &&
+ cache_tab->getObjectId() == ev_tab->getObjectId() &&
+ cache_tab->getObjectVersion() <= ev_tab->getObjectVersion())
+ ndbtab_g.invalidate();
+ }
/* do the rename of the table in the share */
share->table->s->db.str= share->db;
share->table->s->db.length= strlen(share->db);
share->table->s->table_name.str= share->table_name;
share->table->s->table_name.length= strlen(share->table_name);
- /*
- Refresh local dictionary cache by invalidating any
- old table with same name and all it's indexes
- */
- ndb->setDatabaseName(dbname);
- Thd_ndb *thd_ndb= get_thd_ndb(thd);
- DBUG_ASSERT(thd_ndb != NULL);
- Ndb* old_ndb= thd_ndb->ndb;
- thd_ndb->ndb= ndb;
- ha_ndbcluster table_handler(table_share);
- table_handler.set_dbname(share->key);
- table_handler.set_tabname(share->key);
- table_handler.open_indexes(ndb, table, TRUE);
- table_handler.invalidate_dictionary_cache(TRUE, 0);
- thd_ndb->ndb= old_ndb;
}
DBUG_ASSERT(share->op == pOp || share->op_old == pOp);
if (share->op_old == pOp)
@@ -1582,14 +1605,19 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
if (is_remote_change && share && share->state != NSS_DROPPED)
{
DBUG_PRINT("info", ("remote change"));
+ share->state= NSS_DROPPED;
if (share->use_count != 1)
do_close_cached_tables= TRUE;
- share->state= NSS_DROPPED;
- free_share(&share, TRUE);
+ else
+ {
+ free_share(&share, TRUE);
+ share= 0;
+ }
}
+ else
+ share= 0;
pthread_mutex_unlock(&ndbcluster_mutex);
- share= 0;
pOp->setCustomData(0);
pthread_mutex_lock(&injector_mutex);
@@ -1598,7 +1626,14 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
pthread_mutex_unlock(&injector_mutex);
if (do_close_cached_tables)
- close_cached_tables((THD*) 0, 0, (TABLE_LIST*) 0);
+ {
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+ table_list.db= (char *)dbname;
+ table_list.alias= table_list.table_name= (char *)tabname;
+ close_cached_tables(thd, 0, &table_list);
+ free_share(&share);
+ }
DBUG_RETURN(0);
}
@@ -1630,60 +1665,39 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
if (schema->node_id != node_id)
{
int log_query= 0, post_epoch_unlock= 0;
- DBUG_PRINT("info", ("log query_length: %d query: '%s'",
- schema->query_length, schema->query));
+ DBUG_PRINT("info",
+ ("%s.%s: log query_length: %d query: '%s' type: %d",
+ schema->db, schema->name,
+ schema->query_length, schema->query,
+ schema->type));
char key[FN_REFLEN];
build_table_filename(key, sizeof(key), schema->db, schema->name, "");
- NDB_SHARE *share= get_share(key, 0, false, false);
switch ((enum SCHEMA_OP_TYPE)schema->type)
{
case SOT_DROP_TABLE:
- /* binlog dropping table after any table operations */
- if (share && share->op)
- {
- post_epoch_log_list->push_back(schema, mem_root);
- /* acknowledge this query _after_ epoch completion */
- post_epoch_unlock= 1;
- }
- /* table is either ignored or logging is postponed to later */
- log_query= 0;
- break;
+ // fall through
case SOT_RENAME_TABLE:
- if (share && share->op)
- {
- post_epoch_log_list->push_back(schema, mem_root);
- /* acknowledge this query _after_ epoch completion */
- post_epoch_unlock= 1;
- break; /* discovery will be handled by binlog */
- }
- goto sot_create_table;
+ // fall through
+ case SOT_RENAME_TABLE_NEW:
+ // fall through
case SOT_ALTER_TABLE:
- if (share && share->op)
- {
- post_epoch_log_list->push_back(schema, mem_root);
- /* acknowledge this query _after_ epoch completion */
- post_epoch_unlock= 1;
- break; /* discovery will be handled by binlog */
- }
- goto sot_create_table;
+ post_epoch_log_list->push_back(schema, mem_root);
+ /* acknowledge this query _after_ epoch completion */
+ post_epoch_unlock= 1;
+ break;
case SOT_CREATE_TABLE:
- sot_create_table:
- /*
- we need to free any share here as command below
- may need to call handle_trailing_share
- */
- if (share)
- {
- free_share(&share);
- share= 0;
- }
pthread_mutex_lock(&LOCK_open);
if (ndb_create_table_from_engine(thd, schema->db, schema->name))
{
- sql_print_error("Could not discover table '%s.%s' from "
- "binlog schema event '%s' from node %d",
+ sql_print_error("NDB binlog: Could not discover table '%s.%s' from "
+ "binlog schema event '%s' from node %d. "
+ "my_errno: %d",
schema->db, schema->name, schema->query,
- schema->node_id);
+ schema->node_id, my_errno);
+ List_iterator_fast it(thd->warn_list);
+ MYSQL_ERROR *err;
+ while ((err= it++))
+ sql_print_warning("NDB binlog: (%d)%s", err->code, err->msg);
}
pthread_mutex_unlock(&LOCK_open);
log_query= 1;
@@ -1694,12 +1708,9 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
TRUE, /* print error */
TRUE); /* don't binlog the query */
/* binlog dropping database after any table operations */
- if (ndb_binlog_running)
- {
- post_epoch_log_list->push_back(schema, mem_root);
- /* acknowledge this query _after_ epoch completion */
- post_epoch_unlock= 1;
- }
+ post_epoch_log_list->push_back(schema, mem_root);
+ /* acknowledge this query _after_ epoch completion */
+ post_epoch_unlock= 1;
break;
case SOT_CREATE_DB:
/* fall through */
@@ -1726,8 +1737,6 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
pthread_mutex_unlock(&ndb_schema_object->mutex);
pthread_cond_signal(&injector_cond);
}
- if (share)
- free_share(&share, TRUE);
pthread_mutex_unlock(&ndbcluster_mutex);
DBUG_RETURN(0);
}
@@ -1736,11 +1745,6 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
log_query= 1;
break;
}
- if (share)
- {
- free_share(&share);
- share= 0;
- }
if (log_query && ndb_binlog_running)
{
char *thd_db_save= thd->db;
@@ -1864,36 +1868,85 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
List
*post_epoch_unlock_list)
{
+ if (post_epoch_log_list->elements == 0)
+ return;
DBUG_ENTER("ndb_binlog_thread_handle_schema_event_post_epoch");
Cluster_schema *schema;
while ((schema= post_epoch_log_list->pop()))
{
- DBUG_PRINT("info", ("log query_length: %d query: '%s'",
- schema->query_length, schema->query));
+ DBUG_PRINT("info",
+ ("%s.%s: log query_length: %d query: '%s' type: %d",
+ schema->db, schema->name,
+ schema->query_length, schema->query,
+ schema->type));
+ int log_query= 0;
{
char key[FN_REFLEN];
build_table_filename(key, sizeof(key), schema->db, schema->name, "");
NDB_SHARE *share= get_share(key, 0, false, false);
- switch ((enum SCHEMA_OP_TYPE)schema->type)
+ enum SCHEMA_OP_TYPE schema_type= (enum SCHEMA_OP_TYPE)schema->type;
+ switch (schema_type)
{
case SOT_DROP_DB:
- case SOT_DROP_TABLE:
+ log_query= 1;
break;
- case SOT_RENAME_TABLE:
- case SOT_ALTER_TABLE:
+ case SOT_DROP_TABLE:
+ // invalidation already handled by binlog thread
if (share && share->op)
{
- break; /* discovery handled by binlog */
+ log_query= 1;
+ break;
}
- pthread_mutex_lock(&LOCK_open);
- if (ndb_create_table_from_engine(thd, schema->db, schema->name))
+ // fall through
+ case SOT_RENAME_TABLE:
+ // fall through
+ case SOT_ALTER_TABLE:
+ // invalidation already handled by binlog thread
+ if (!share || !share->op)
{
- sql_print_error("Could not discover table '%s.%s' from "
- "binlog schema event '%s' from node %d",
- schema->db, schema->name, schema->query,
- schema->node_id);
+ {
+ injector_ndb->setDatabaseName(schema->db);
+ Ndb_table_guard ndbtab_g(injector_ndb->getDictionary(),
+ schema->name);
+ ndbtab_g.invalidate();
+ }
+ TABLE_LIST table_list;
+ bzero((char*) &table_list,sizeof(table_list));
+ table_list.db= schema->db;
+ table_list.alias= table_list.table_name= schema->name;
+ close_cached_tables(thd, 0, &table_list, FALSE);
}
- pthread_mutex_unlock(&LOCK_open);
+ if (schema_type != SOT_ALTER_TABLE)
+ break;
+ // fall through
+ case SOT_RENAME_TABLE_NEW:
+ log_query= 1;
+ if (ndb_binlog_running && (!share || !share->op))
+ {
+ /*
+ we need to free any share here as command below
+ may need to call handle_trailing_share
+ */
+ if (share)
+ {
+ free_share(&share);
+ share= 0;
+ }
+ pthread_mutex_lock(&LOCK_open);
+ if (ndb_create_table_from_engine(thd, schema->db, schema->name))
+ {
+ sql_print_error("NDB binlog: Could not discover table '%s.%s' from "
+ "binlog schema event '%s' from node %d. my_errno: %d",
+ schema->db, schema->name, schema->query,
+ schema->node_id, my_errno);
+ List_iterator_fast it(thd->warn_list);
+ MYSQL_ERROR *err;
+ while ((err= it++))
+ sql_print_warning("NDB binlog: (%d)%s", err->code, err->msg);
+ }
+ pthread_mutex_unlock(&LOCK_open);
+ }
+ break;
default:
DBUG_ASSERT(false);
}
@@ -1903,6 +1956,7 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
share= 0;
}
}
+ if (ndb_binlog_running && log_query)
{
char *thd_db_save= thd->db;
thd->db= schema->db;
@@ -2186,7 +2240,8 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key,
ndb->setDatabaseName(db);
NDBDICT *dict= ndb->getDictionary();
- const NDBTAB *ndbtab= dict->getTable(table_name);
+ Ndb_table_guard ndbtab_g(dict, table_name);
+ const NDBTAB *ndbtab= ndbtab_g.get_table();
if (ndbtab == 0)
{
if (ndb_extra_logging)
@@ -2201,7 +2256,8 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key,
event should have been created by someone else,
but let's make sure, and create if it doesn't exist
*/
- if (!dict->getEvent(event_name.c_ptr()))
+ const NDBEVENT *ev= dict->getEvent(event_name.c_ptr());
+ if (!ev)
{
if (ndbcluster_create_event(ndb, ndbtab, event_name.c_ptr(), share))
{
@@ -2216,9 +2272,12 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key,
event_name.c_ptr());
}
else
+ {
+ delete ev;
if (ndb_extra_logging)
sql_print_information("NDB Binlog: DISCOVER TABLE Event: %s",
event_name.c_ptr());
+ }
/*
create the event operations for receiving logging events
@@ -2328,8 +2387,10 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
try retrieving the event, if table version/id matches, we will get
a valid event. Otherwise we have a trailing event from before
*/
- if (dict->getEvent(event_name))
+ const NDBEVENT *ev;
+ if ((ev= dict->getEvent(event_name)))
{
+ delete ev;
DBUG_RETURN(0);
}
@@ -2419,7 +2480,14 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
DBUG_RETURN(0);
}
- if (!binlog_filter->db_ok(share->db))
+ int do_schema_share= 0, do_apply_status_share= 0;
+ if (!schema_share && strcmp(share->db, NDB_REP_DB) == 0 &&
+ strcmp(share->table_name, NDB_SCHEMA_TABLE) == 0)
+ do_schema_share= 1;
+ else if (!apply_status_share && strcmp(share->db, NDB_REP_DB) == 0 &&
+ strcmp(share->table_name, NDB_APPLY_TABLE) == 0)
+ do_apply_status_share= 1;
+ else if (!binlog_filter->db_ok(share->db))
{
share->flags|= NSF_NO_BINLOG;
DBUG_RETURN(0);
@@ -2437,15 +2505,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
TABLE *table= share->table;
- int do_schema_share= 0, do_apply_status_share= 0;
int retries= 100;
- if (!schema_share && strcmp(share->db, NDB_REP_DB) == 0 &&
- strcmp(share->table_name, NDB_SCHEMA_TABLE) == 0)
- do_schema_share= 1;
- else if (!apply_status_share && strcmp(share->db, NDB_REP_DB) == 0 &&
- strcmp(share->table_name, NDB_APPLY_TABLE) == 0)
- do_apply_status_share= 1;
-
while (1)
{
pthread_mutex_lock(&injector_mutex);
@@ -3648,3 +3708,4 @@ ndbcluster_show_status_binlog(THD* thd, stat_print_fn *stat_print,
}
#endif /* HAVE_NDB_BINLOG */
+#endif
diff --git a/sql/ha_ndbcluster_binlog.h b/sql/ha_ndbcluster_binlog.h
index 9d15016568b..d82cdccb1b9 100644
--- a/sql/ha_ndbcluster_binlog.h
+++ b/sql/ha_ndbcluster_binlog.h
@@ -41,14 +41,15 @@ enum SCHEMA_OP_TYPE
{
SOT_DROP_TABLE= 0,
SOT_CREATE_TABLE= 1,
- SOT_RENAME_TABLE= 2,
+ SOT_RENAME_TABLE_NEW= 2,
SOT_ALTER_TABLE= 3,
SOT_DROP_DB= 4,
SOT_CREATE_DB= 5,
SOT_ALTER_DB= 6,
SOT_CLEAR_SLOCK= 7,
SOT_TABLESPACE= 8,
- SOT_LOGFILE_GROUP= 9
+ SOT_LOGFILE_GROUP= 9,
+ SOT_RENAME_TABLE= 10
};
const uint max_ndb_nodes= 64; /* multiple of 32 */
@@ -56,6 +57,45 @@ const uint max_ndb_nodes= 64; /* multiple of 32 */
static const char *ha_ndb_ext=".ndb";
static const char share_prefix[]= "./";
+class Ndb_table_guard
+{
+public:
+ Ndb_table_guard(NDBDICT *dict, const char *tabname)
+ : m_dict(dict)
+ {
+ DBUG_ENTER("Ndb_table_guard");
+ m_ndbtab= m_dict->getTableGlobal(tabname);
+ m_invalidate= 0;
+ DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab));
+ DBUG_VOID_RETURN;
+ }
+ ~Ndb_table_guard()
+ {
+ DBUG_ENTER("~Ndb_table_guard");
+ if (m_ndbtab)
+ {
+ DBUG_PRINT("info", ("m_ndbtab: %p m_invalidate: %d",
+ m_ndbtab, m_invalidate));
+ m_dict->removeTableGlobal(*m_ndbtab, m_invalidate);
+ }
+ DBUG_VOID_RETURN;
+ }
+ const NDBTAB *get_table() { return m_ndbtab; }
+ void invalidate() { m_invalidate= 1; }
+ const NDBTAB *release()
+ {
+ DBUG_ENTER("Ndb_table_guard::release");
+ const NDBTAB *tmp= m_ndbtab;
+ DBUG_PRINT("info", ("m_ndbtab: %p", m_ndbtab));
+ m_ndbtab = 0;
+ DBUG_RETURN(tmp);
+ }
+private:
+ const NDBTAB *m_ndbtab;
+ NDBDICT *m_dict;
+ int m_invalidate;
+};
+
#ifdef HAVE_NDB_BINLOG
extern pthread_t ndb_binlog_thread;
extern pthread_mutex_t injector_mutex;
@@ -98,8 +138,8 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
uint32 ndb_table_id,
uint32 ndb_table_version,
enum SCHEMA_OP_TYPE type,
- const char *old_db= 0,
- const char *old_table_name= 0);
+ const char *new_db= 0,
+ const char *new_table_name= 0);
int ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
NDB_SHARE *share,
const char *type_str);
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 1ab2c4270fd..b1a5a447b6f 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -54,8 +54,11 @@
#include "mysql_priv.h"
+#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
+#include
+
static const char *ha_par_ext= ".par";
#ifdef NOT_USED
static int free_share(PARTITION_SHARE * share);
@@ -70,11 +73,14 @@ static handler *partition_create_handler(TABLE_SHARE *share);
static uint partition_flags();
static uint alter_table_flags(uint flags);
+static const char partition_hton_name[]= "partition";
+static const char partition_hton_comment[]= "Partition Storage Engine Helper";
+
handlerton partition_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "partition",
+ partition_hton_name,
SHOW_OPTION_YES,
- "Partition Storage Engine Helper", /* A comment used by SHOW to describe an engine */
+ partition_hton_comment, /* A comment used by SHOW to describe an engine */
DB_TYPE_PARTITION_DB,
0, /* Method that initializes a storage engine */
0, /* slot */
@@ -5438,3 +5444,20 @@ static int free_share(PARTITION_SHARE *share)
return 0;
}
#endif /* NOT_USED */
+
+
+mysql_declare_plugin(partition)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &partition_hton,
+ partition_hton_name,
+ "Mikael Ronstrom, MySQL AB",
+ partition_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100, /* 1.0 */
+ 0
+}
+mysql_declare_plugin_end;
+
+#endif
diff --git a/sql/handler.cc b/sql/handler.cc
index 808dd0841c5..b9ef05a33c2 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -35,6 +35,7 @@
#define NDB_MAX_ATTRIBUTES_IN_TABLE 128
#include "ha_ndbcluster.h"
#endif
+
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
#endif
@@ -43,10 +44,15 @@
#include "ha_innodb.h"
#endif
-extern handlerton *sys_table_types[];
+/* While we have legacy_db_type, we have this array to
+ check for dups and to find handlerton from legacy_db_type.
+ Remove when legacy_db_type is finally gone */
+static handlerton *installed_htons[128];
#define BITMAP_STACKBUF_SIZE (128/8)
+KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0} };
+
/* static functions defined in this file */
static handler *create_default(TABLE_SHARE *table);
@@ -138,30 +144,8 @@ handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name)
}
-struct plugin_find_dbtype_st
-{
- enum legacy_db_type db_type;
- handlerton *hton;
-};
-
-
-static my_bool plugin_find_dbtype(THD *unused, st_plugin_int *plugin,
- void *arg)
-{
- handlerton *types= (handlerton *) plugin->plugin->info;
- if (types->db_type == ((struct plugin_find_dbtype_st *)arg)->db_type)
- {
- ((struct plugin_find_dbtype_st *)arg)->hton= types;
- return TRUE;
- }
- return FALSE;
-}
-
-
const char *ha_get_storage_engine(enum legacy_db_type db_type)
{
- struct plugin_find_dbtype_st info;
-
switch (db_type)
{
case DB_TYPE_DEFAULT:
@@ -169,13 +153,10 @@ const char *ha_get_storage_engine(enum legacy_db_type db_type)
case DB_TYPE_UNKNOWN:
return "UNKNOWN";
default:
- info.db_type= db_type;
-
- if (!plugin_foreach(NULL, plugin_find_dbtype,
- MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+ if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
+ installed_htons[db_type])
+ return installed_htons[db_type]->name;
return "*NONE*";
-
- return info.hton->name;
}
}
@@ -190,8 +171,6 @@ static handler *create_default(TABLE_SHARE *table)
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
{
- struct plugin_find_dbtype_st info;
-
switch (db_type)
{
case DB_TYPE_DEFAULT:
@@ -202,12 +181,9 @@ handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
case DB_TYPE_UNKNOWN:
return NULL;
default:
- info.db_type= db_type;
- if (!plugin_foreach(NULL, plugin_find_dbtype,
- MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+ if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT)
+ return installed_htons[db_type];
return NULL;
-
- return info.hton;
}
}
@@ -394,32 +370,77 @@ static int ha_finish_errors(void)
}
-static void ha_was_inited_ok(handlerton *ht)
+int ha_finalize_handlerton(st_plugin_int *plugin)
{
- 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++;
-}
+ handlerton *hton;
+ DBUG_ENTER("ha_finalize_handlerton");
-
-int ha_initialize_handlerton(handlerton *hton)
-{
- DBUG_ENTER("ha_initialize_handlerton");
-
- if (hton == NULL)
+ if (!(hton= (handlerton *) plugin->plugin->info))
DBUG_RETURN(1);
switch (hton->state)
{
+ case SHOW_OPTION_NO:
+ case SHOW_OPTION_DISABLED:
+ break;
+ case SHOW_OPTION_YES:
+ if (hton->panic && hton->panic(HA_PANIC_CLOSE))
+ DBUG_RETURN(1);
+ if (installed_htons[hton->db_type] == hton)
+ installed_htons[hton->db_type]= NULL;
+ break;
+ };
+ DBUG_RETURN(0);
+}
+
+
+int ha_initialize_handlerton(st_plugin_int *plugin)
+{
+ handlerton *hton;
+ DBUG_ENTER("ha_initialize_handlerton");
+
+ if (!(hton= (handlerton *) plugin->plugin->info))
+ DBUG_RETURN(1);
+
+ /* for the sake of sanity, we set the handlerton name to be the
+ same as the plugin name */
+ hton->name= plugin->name.str;
+
+
+ switch (hton->state) {
case SHOW_OPTION_NO:
break;
case SHOW_OPTION_YES:
if (!hton->init || !hton->init())
{
- ha_was_inited_ok(hton);
+ uint tmp= hton->savepoint_offset;
+ hton->savepoint_offset= savepoint_alloc_size;
+ savepoint_alloc_size+= tmp;
+ hton->slot= total_ha++;
+ if (hton->prepare)
+ total_ha_2pc++;
+
+ /* now check the db_type for conflict */
+ if (hton->db_type <= DB_TYPE_UNKNOWN ||
+ hton->db_type >= DB_TYPE_DEFAULT ||
+ installed_htons[hton->db_type])
+ {
+ int idx= (int) DB_TYPE_FIRST_DYNAMIC;
+
+ while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
+ idx++;
+
+ if (idx == (int) DB_TYPE_DEFAULT)
+ {
+ sql_print_warning("Too many storage engines!");
+ DBUG_RETURN(1);
+ }
+ if (hton->db_type != DB_TYPE_UNKNOWN)
+ sql_print_warning("Storage engine '%s' has conflicting typecode. "
+ "Assigning value %d.", hton->name, idx);
+ hton->db_type= (enum legacy_db_type) idx;
+ }
+ installed_htons[hton->db_type]= hton;
break;
}
/* fall through */
@@ -436,7 +457,7 @@ static my_bool init_handlerton(THD *unused1, st_plugin_int *plugin,
{
if (plugin->state == PLUGIN_IS_UNINITIALIZED)
{
- ha_initialize_handlerton((handlerton *) plugin->plugin->info);
+ ha_initialize_handlerton(plugin);
plugin->state= PLUGIN_IS_READY;
}
return FALSE;
@@ -447,12 +468,15 @@ int ha_init()
{
int error= 0;
total_ha= savepoint_alloc_size= 0;
+ DBUG_ENTER("ha_init");
+
+ bzero(installed_htons, sizeof(installed_htons));
if (ha_init_errors())
- return 1;
+ DBUG_RETURN(1);
if (plugin_foreach(NULL, init_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0))
- return 1;
+ DBUG_RETURN(1);
DBUG_ASSERT(total_ha < MAX_HA);
/*
@@ -462,37 +486,7 @@ int ha_init()
*/
opt_using_transactions= total_ha>(ulong)opt_bin_log;
savepoint_alloc_size+= sizeof(SAVEPOINT);
- return error;
-}
-
-
-int ha_register_builtin_plugins()
-{
- handlerton **hton;
- uint size= 0;
- struct st_mysql_plugin *plugin;
- DBUG_ENTER("ha_register_builtin_plugins");
-
- for (hton= sys_table_types; *hton; hton++)
- size+= sizeof(struct st_mysql_plugin);
-
- if (!(plugin= (struct st_mysql_plugin *)
- my_once_alloc(size, MYF(MY_WME | MY_ZEROFILL))))
- DBUG_RETURN(1);
-
- for (hton= sys_table_types; *hton; hton++, plugin++)
- {
- plugin->type= MYSQL_STORAGE_ENGINE_PLUGIN;
- plugin->info= *hton;
- plugin->version= 0;
- plugin->name= (*hton)->name;
- plugin->author= NULL;
- plugin->descr= (*hton)->comment;
-
- if (plugin_register_builtin(plugin))
- DBUG_RETURN(1);
- }
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
}
@@ -3270,10 +3264,11 @@ int handler::ha_external_lock(THD *thd, int lock_type)
locking combined with row-based replication needs to be looked
over. Ideally, no such special handling should be needed.
*/
- switch (thd->lex->sql_command)
- {
+ switch (thd->lex->sql_command) {
case SQLCOM_TRUNCATE:
case SQLCOM_ALTER_TABLE:
+ case SQLCOM_OPTIMIZE:
+ case SQLCOM_REPAIR:
DBUG_RETURN(0);
default:
break;
diff --git a/sql/handler.h b/sql/handler.h
index 090ef1f9f30..d988e46b236 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -84,6 +84,7 @@
access on the table based on a given record.
*/
#define HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS (1 << 16)
+#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)
@@ -233,6 +234,7 @@ enum legacy_db_type
DB_TYPE_BLACKHOLE_DB,
DB_TYPE_PARTITION_DB,
DB_TYPE_BINLOG,
+ DB_TYPE_FIRST_DYNAMIC=32,
DB_TYPE_DEFAULT=127 // Must be last
};
@@ -280,6 +282,7 @@ enum enum_binlog_command {
#define HA_CREATE_USED_COMMENT (1L << 16)
#define HA_CREATE_USED_PASSWORD (1L << 17)
#define HA_CREATE_USED_CONNECTION (1L << 18)
+#define HA_CREATE_USED_KEY_BLOCK_SIZE (1L << 19)
typedef ulonglong my_xid; // this line is the same as in log_event.h
#define MYSQL_XID_PREFIX "MySQLXid"
@@ -653,6 +656,7 @@ typedef struct st_ha_create_information
ulong table_options;
ulong avg_row_length;
ulong used_fields;
+ ulong key_block_size;
SQL_LIST merge_list;
handlerton *db_type;
enum row_type row_type;
@@ -666,6 +670,15 @@ typedef struct st_ha_create_information
bool store_on_disk; /* 1 if table stored on disk */
} HA_CREATE_INFO;
+
+typedef struct st_key_create_information
+{
+ enum ha_key_alg algorithm;
+ ulong block_size;
+ LEX_STRING parser_name;
+} KEY_CREATE_INFO;
+
+
/*
Class for maintaining hooks used inside operations on tables such
as: create table functions, delete table functions, and alter table
@@ -700,6 +713,7 @@ private:
typedef struct st_savepoint SAVEPOINT;
extern ulong savepoint_alloc_size;
+extern KEY_CREATE_INFO default_key_create_info;
/* Forward declaration for condition pushdown to storage engine */
typedef class Item COND;
@@ -1553,8 +1567,8 @@ static inline bool ha_storage_engine_is_enabled(const handlerton *db_type)
/* basic stuff */
int ha_init(void);
-int ha_register_builtin_plugins();
-int ha_initialize_handlerton(handlerton *hton);
+int ha_initialize_handlerton(st_plugin_int *plugin);
+int ha_finalize_handlerton(st_plugin_int *plugin);
TYPELIB *ha_known_exts(void);
int ha_panic(enum ha_panic_function flag);
diff --git a/sql/handlerton-win.cc b/sql/handlerton-win.cc
deleted file mode 100644
index 9ce4eab2444..00000000000
--- a/sql/handlerton-win.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "mysql_priv.h"
-
-extern handlerton heap_hton;
-extern handlerton myisam_hton;
-extern handlerton myisammrg_hton;
-extern handlerton binlog_hton;
-#ifdef WITH_INNOBASE_STORAGE_ENGINE
-extern handlerton innobase_hton;
-#endif
-#ifdef WITH_BERKELEY_STORAGE_ENGINE
-extern handlerton berkeley_hton;
-#endif
-#ifdef WITH_EXAMPLE_STORAGE_ENGINE
-extern handlerton example_hton;
-#endif
-#ifdef WITH_ARCHIVE_STORAGE_ENGINE
-extern handlerton archive_hton;
-#endif
-#ifdef WITH_CSV_STORAGE_ENGINE
-extern handlerton tina_hton;
-#endif
-#ifdef WITH_BLACKHOLE_STORAGE_ENGINE
-extern handlerton blackhole_hton;
-#endif
-#ifdef WITH_FEDERATED_STORAGE_ENGINE
-extern handlerton federated_hton;
-#endif
-#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
-extern handlerton ndbcluster_hton;
-#endif
-#ifdef WITH_PARTITION_STORAGE_ENGINE
-extern handlerton partition_hton;
-#endif
-
-/*
- This array is used for processing compiled in engines.
-*/
-handlerton *sys_table_types[]=
-{
- &heap_hton,
- &myisam_hton,
-#ifdef WITH_INNOBASE_STORAGE_ENGINE
- &innobase_hton,
-#endif
-#ifdef WITH_BERKELEY_STORAGE_ENGINE
- &berkeley_hton,
-#endif
-#ifdef WITH_EXAMPLE_STORAGE_ENGINE
- &example_hton,
-#endif
-#ifdef WITH_ARCHIVE_STORAGE_ENGINE
- &archive_hton,
-#endif
-#ifdef WITH_CSV_STORAGE_ENGINE
- &tina_hton,
-#endif
-#ifdef WITH_BLACKHOLE_STORAGE_ENGINE
- &blackhole_hton,
-#endif
-#ifdef WITH_FEDERATED_STORAGE_ENGINE
- &federated_hton,
-#endif
-#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
- &ndbcluster_hton,
-#endif
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- &partition_hton,
-#endif
- &myisammrg_hton,
- &binlog_hton,
- NULL
-};
diff --git a/sql/handlerton.cc.in b/sql/handlerton.cc.in
deleted file mode 100644
index 55af8cdd8cf..00000000000
--- a/sql/handlerton.cc.in
+++ /dev/null
@@ -1,14 +0,0 @@
-
-#include "mysql_priv.h"
-
-extern handlerton heap_hton,myisam_hton,myisammrg_hton,
- binlog_hton@mysql_se_decls@;
-
-/*
- This array is used for processing compiled in engines.
-*/
-handlerton *sys_table_types[]=
-{
- &heap_hton,&myisam_hton@mysql_se_htons@,&myisammrg_hton,&binlog_hton,NULL
-};
-
diff --git a/sql/item_func.h b/sql/item_func.h
index ed5924e8fe1..a91d93be8c6 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -284,6 +284,7 @@ class Item_func_connection_id :public Item_int_func
longlong value;
public:
+ Item_func_connection_id() {}
const char *func_name() const { return "connection_id"; }
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index a245e3b1b33..17e8db90dc7 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -2280,6 +2280,30 @@ static int my_xpath_parse_Number(MY_XPATH *xpath)
}
+/*
+ QName grammar can be found in a separate document
+ http://www.w3.org/TR/REC-xml-names/#NT-QName
+
+ [6] QName ::= (Prefix ':')? LocalPart
+ [7] Prefix ::= NCName
+ [8] LocalPart ::= NCName
+*/
+static int
+my_xpath_parse_QName(MY_XPATH *xpath)
+{
+ const char *beg;
+ if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
+ return 0;
+ beg= xpath->prevtok.beg;
+ if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_COLON))
+ return 1; /* Non qualified name */
+ if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
+ return 0;
+ xpath->prevtok.beg= beg;
+ return 1;
+}
+
+
/*
Scan Variable reference
@@ -2313,7 +2337,7 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath)
static int
my_xpath_parse_NodeTest_QName(MY_XPATH *xpath)
{
- if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
+ if (!my_xpath_parse_QName(xpath))
return 0;
DBUG_ASSERT(xpath->context);
uint len= xpath->prevtok.end - xpath->prevtok.beg;
diff --git a/sql/lex.h b/sql/lex.h
index 171f7a48980..555a68dc388 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -275,6 +275,7 @@ static SYMBOL symbols[] = {
{ "JOIN", SYM(JOIN_SYM)},
{ "KEY", SYM(KEY_SYM)},
{ "KEYS", SYM(KEYS)},
+ { "KEY_BLOCK_SIZE", SYM(KEY_BLOCK_SIZE)},
{ "KILL", SYM(KILL_SYM)},
{ "LANGUAGE", SYM(LANGUAGE_SYM)},
{ "LAST", SYM(LAST_SYM)},
diff --git a/sql/log.cc b/sql/log.cc
index 92cf8d2e73b..fa86064682d 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -30,6 +30,8 @@
#include "message.h"
#endif
+#include
+
/* max size of the log message */
#define MAX_LOG_BUFFER_SIZE 1024
#define MAX_USER_HOST_SIZE 512
@@ -68,11 +70,15 @@ struct binlog_trx_data {
Rows_log_event *pending; // The pending binrows event
};
+static const char binlog_hton_name[]= "binlog";
+static const char binlog_hton_comment[]=
+ "This is a meta storage engine to represent the binlog in a transaction";
+
handlerton binlog_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "binlog",
+ binlog_hton_name,
SHOW_OPTION_YES,
- "This is a meta storage engine to represent the binlog in a transaction",
+ binlog_hton_comment,
DB_TYPE_BINLOG, /* IGNORE for now */
binlog_init,
0,
@@ -1085,7 +1091,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, Log_event *end_ev)
inside a stored function.
*/
#ifdef HAVE_ROW_BASED_REPLICATION
- thd->binlog_flush_pending_rows_event(true);
+ thd->binlog_flush_pending_rows_event(TRUE);
#endif
error= mysql_bin_log.write(thd, trans_log, end_ev);
}
@@ -1484,6 +1490,7 @@ const char *MYSQL_LOG::generate_name(const char *log_name,
return log_name;
}
+
bool MYSQL_LOG::open_index_file(const char *index_file_name_arg,
const char *log_name)
{
@@ -2882,23 +2889,27 @@ bool MYSQL_LOG::write(Log_event *event_info)
binlog_trx_data *const trx_data=
(binlog_trx_data*) thd->ha_data[binlog_hton.slot];
IO_CACHE *trans_log= &trx_data->trans_log;
+ bool trans_log_in_use= my_b_tell(trans_log) != 0;
- if (event_info->get_cache_stmt() && !my_b_tell(trans_log))
+ if (event_info->get_cache_stmt() && !trans_log_in_use)
trans_register_ha(thd,
- thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN),
+ (thd->options &
+ (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)),
&binlog_hton);
-
- if (event_info->get_cache_stmt() || my_b_tell(trans_log))
+ if (event_info->get_cache_stmt() || trans_log_in_use)
+ {
+ DBUG_PRINT("info", ("Using trans_log"));
file= trans_log;
+ }
/*
- Note: as Mats suggested, for all the cases above where we write to
+ TODO as Mats suggested, for all the cases above where we write to
trans_log, it sounds unnecessary to lock LOCK_log. We should rather
test first if we want to write to trans_log, and if not, lock
- LOCK_log. TODO.
+ LOCK_log.
*/
}
#endif
- DBUG_PRINT("info",("event type=%d",event_info->get_type_code()));
+ DBUG_PRINT("info",("event type: %d",event_info->get_type_code()));
/*
No check for auto events flag here - this write method should
@@ -4353,3 +4364,16 @@ err1:
return 1;
}
+
+mysql_declare_plugin(binlog)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &binlog_hton,
+ binlog_hton_name,
+ "MySQL AB",
+ binlog_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+}
+mysql_declare_plugin_end;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d51a0ef4c9f..ab9fa2975a1 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -5350,6 +5350,7 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
slave_print_msg(ERROR_LEVEL, rli, error,
"Error in %s event: when locking tables",
get_type_str());
+ rli->clear_tables_to_lock();
DBUG_RETURN(error);
}
@@ -5385,6 +5386,7 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
"unexpected success or fatal error"));
thd->query_error= 1;
}
+ rli->clear_tables_to_lock();
DBUG_RETURN(error);
}
}
@@ -5393,19 +5395,17 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
the table map and remove them from tables to lock.
*/
- TABLE_LIST *ptr= rli->tables_to_lock;
- while (ptr)
+ TABLE_LIST *ptr;
+ for (ptr= rli->tables_to_lock ; ptr ; ptr= ptr->next_global)
{
rli->m_table_map.set_table(ptr->table_id, ptr->table);
rli->touching_table(ptr->db, ptr->table_name, ptr->table_id);
- char *to_free= reinterpret_cast(ptr);
- ptr= ptr->next_global;
- my_free(to_free, MYF(MY_WME));
}
- rli->tables_to_lock= 0;
- rli->tables_to_lock_count= 0;
+ rli->clear_tables_to_lock();
}
+ DBUG_ASSERT(rli->tables_to_lock == NULL && rli->tables_to_lock_count == 0);
+
TABLE* table= rli->m_table_map.get_table(m_table_id);
if (table)
@@ -5816,12 +5816,8 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli)
&tname_mem, NAME_LEN + 1,
NULL);
- /*
- If memory is allocated, it the pointer to it should be stored in
- table_list. If this is not true, the memory will not be correctly
- free:ed later.
- */
- DBUG_ASSERT(memory == NULL || memory == table_list);
+ if (memory == NULL)
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
uint32 dummy_len;
bzero(table_list, sizeof(*table_list));
@@ -5836,8 +5832,12 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli)
int error= 0;
- if (rpl_filter->db_ok(table_list->db) &&
- (!rpl_filter->is_on() || rpl_filter->tables_ok("", table_list)))
+ if (!rpl_filter->db_ok(table_list->db) ||
+ (rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list)))
+ {
+ my_free((gptr) memory, MYF(MY_WME));
+ }
+ else
{
/*
Check if the slave is set to use SBR. If so, it should switch
@@ -6416,12 +6416,17 @@ static int find_and_fetch_row(TABLE *table, byte *key)
if (table->s->keys > 0)
{
int error;
- /*
- We need to set the null bytes to ensure that the filler bit
- are all set when returning. There are storage engines that
- just set the necessary bits on the bytes and don't set the
- filler bits correctly.
- */
+ /* We have a key: search the table using the index */
+ if (!table->file->inited)
+ if ((error= table->file->ha_index_init(0, FALSE)))
+ return error;
+
+ /*
+ We need to set the null bytes to ensure that the filler bit are
+ all set when returning. There are storage engines that just set
+ the necessary bits on the bytes and don't set the filler bits
+ correctly.
+ */
my_ptrdiff_t const pos=
table->s->null_bytes > 0 ? table->s->null_bytes - 1 : 0;
table->record[1][pos]= 0xFF;
@@ -6430,6 +6435,7 @@ static int find_and_fetch_row(TABLE *table, byte *key)
HA_READ_KEY_EXACT)))
{
table->file->print_error(error, MYF(0));
+ table->file->ha_index_end();
DBUG_RETURN(error);
}
@@ -6448,7 +6454,10 @@ static int find_and_fetch_row(TABLE *table, byte *key)
chose the row to change only using a PK or an UNNI.
*/
if (table->key_info->flags & HA_NOSAME)
+ {
+ table->file->ha_index_end();
DBUG_RETURN(0);
+ }
while (record_compare(table))
{
@@ -6465,15 +6474,26 @@ static int find_and_fetch_row(TABLE *table, byte *key)
if ((error= table->file->index_next(table->record[1])))
{
table->file->print_error(error, MYF(0));
+ table->file->ha_index_end();
DBUG_RETURN(error);
}
}
+
+ /*
+ Have to restart the scan to be able to fetch the next row.
+ */
+ table->file->ha_index_end();
}
else
{
- /* Continue until we find the right record or have made a full loop */
int restart_count= 0; // Number of times scanning has restarted from top
- int error= 0;
+ int error;
+
+ /* We don't have a key: search the table using rnd_next() */
+ if ((error= table->file->ha_rnd_init(1)))
+ return error;
+
+ /* Continue until we find the right record or have made a full loop */
do
{
/*
@@ -6499,11 +6519,17 @@ static int find_and_fetch_row(TABLE *table, byte *key)
default:
table->file->print_error(error, MYF(0));
+ table->file->ha_rnd_end();
DBUG_RETURN(error);
}
}
while (restart_count < 2 && record_compare(table));
+ /*
+ Have to restart the scan to be able to fetch the next row.
+ */
+ table->file->ha_rnd_end();
+
DBUG_ASSERT(error == HA_ERR_END_OF_FILE || error == 0);
DBUG_RETURN(error);
}
@@ -6626,20 +6652,6 @@ int Delete_rows_log_event::do_exec_row(TABLE *table)
{
DBUG_ASSERT(table != NULL);
- if (table->s->keys > 0)
- {
- /* We have a key: search the table using the index */
- if (!table->file->inited)
- if (int error= table->file->ha_index_init(0, FALSE))
- return error;
- }
- else
- {
- /* We doesn't have a key: search the table using rnd_next() */
- if (int error= table->file->ha_rnd_init(1))
- return error;
- }
-
int error= find_and_fetch_row(table, m_key);
if (error)
return error;
@@ -6651,11 +6663,6 @@ int Delete_rows_log_event::do_exec_row(TABLE *table)
*/
error= table->file->ha_delete_row(table->record[0]);
- /*
- Have to restart the scan to be able to fetch the next row.
- */
- table->file->ha_index_or_rnd_end();
-
return error;
}
@@ -6736,17 +6743,6 @@ int Update_rows_log_event::do_before_row_operations(TABLE *table)
if (!m_memory)
return HA_ERR_OUT_OF_MEM;
- if (table->s->keys > 0)
- {
- /* We have a key: search the table using the index */
- if (!table->file->inited)
- error= table->file->ha_index_init(0, FALSE);
- }
- else
- {
- /* We doesn't have a key: search the table using rnd_next() */
- error= table->file->ha_rnd_init(1);
- }
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
return error;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index bc398b3d20a..93db68d1b50 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -92,7 +92,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
do { \
DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) >= 0); \
push_warning_printf(((THD *)Thd), MYSQL_ERROR::WARN_LEVEL_WARN, \
- ER_WARN_DEPRECATED, ER(ER_WARN_DEPRECATED), \
+ ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX), \
(Old), (Ver), (New)); \
} while(0)
@@ -177,6 +177,8 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
/* Characters shown for the command in 'show processlist' */
#define PROCESS_LIST_WIDTH 100
+/* Characters shown for the command in 'information_schema.processlist' */
+#define PROCESS_LIST_INFO_WIDTH 65535
/* Time handling defaults */
#define TIMESTAMP_MAX_YEAR 2038
@@ -556,6 +558,7 @@ enum enum_mysql_completiontype {
};
bool begin_trans(THD *thd);
+bool end_active_trans(THD *thd);
int end_trans(THD *thd, enum enum_mysql_completiontype completion);
Item *negate_expression(THD *thd, Item *expr);
@@ -1363,8 +1366,8 @@ bool mysql_manager_submit(void (*action)());
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, double read_time, double record_count,
- uint idx, const char *info);
+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 */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index e0cc9067e8d..f44c7d87ada 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -742,6 +742,7 @@ static void clean_up_mutexes(void);
static void wait_for_signal_thread_to_end(void);
static int test_if_case_insensitive(const char *dir_name);
static void create_pid_file();
+static void end_ssl();
#ifndef EMBEDDED_LIBRARY
/****************************************************************************
@@ -1184,8 +1185,8 @@ void clean_up(bool print_message)
#ifdef HAVE_DLOPEN
udf_free();
#endif
- plugin_free();
}
+ plugin_free();
if (tc_log)
tc_log->close();
xid_cache_free();
@@ -1217,10 +1218,7 @@ void clean_up(bool print_message)
#endif
delete binlog_filter;
delete rpl_filter;
-#ifdef HAVE_OPENSSL
- if (ssl_acceptor_fd)
- my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
-#endif /* HAVE_OPENSSL */
+ end_ssl();
#ifdef USE_REGEX
my_regex_end();
#endif
@@ -2637,12 +2635,6 @@ static int init_common_variables(const char *conf_file_name, int argc,
return 1;
}
- if (ha_register_builtin_plugins())
- {
- sql_print_error("Failed to register built-in storage engines.");
- return 1;
- }
-
load_defaults(conf_file_name, groups, &argc, &argv);
defaults_argv=argv;
get_options(argc,argv);
@@ -2968,6 +2960,18 @@ static void init_ssl()
}
+static void end_ssl()
+{
+#ifdef HAVE_OPENSSL
+ if (ssl_acceptor_fd)
+ {
+ free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
+ ssl_acceptor_fd= 0;
+ }
+#endif /* HAVE_OPENSSL */
+}
+
+
static int init_server_components()
{
DBUG_ENTER("init_server_components");
@@ -3012,42 +3016,13 @@ static int init_server_components()
}
}
-#ifdef WITH_CSV_STORAGE_ENGINE
- if (opt_bootstrap)
- log_output_options= LOG_FILE;
- else
- logger.init_log_tables();
-
- if (log_output_options & LOG_NONE)
+ if (xid_cache_init())
{
- /*
- Issue a warining if there were specified additional options to the
- log-output along with NONE. Probably this wasn't what user wanted.
- */
- if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
- sql_print_warning("There were other values specified to "
- "log-output besides NONE. Disabling slow "
- "and general logs anyway.");
- logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE);
+ sql_print_error("Out of memory");
+ unireg_abort(1);
}
- else
- {
- /* fall back to the log files if tables are not present */
- if (have_csv_db == SHOW_OPTION_NO)
- {
- sql_print_error("CSV engine is not present, falling back to the "
- "log files");
- log_output_options= log_output_options & ~LOG_TABLE | LOG_FILE;
- }
-
- logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
- opt_log ? log_output_options:LOG_NONE);
- }
-#else
- logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
- opt_log ? LOG_FILE:LOG_NONE);
-#endif
+ /* need to configure logging before initializing storage engines */
if (opt_update_log)
{
/*
@@ -3175,17 +3150,49 @@ server.");
using_update_log=1;
}
- if (xid_cache_init())
- {
- sql_print_error("Out of memory");
- unireg_abort(1);
- }
+ /* We have to initialize the storage engines before CSV logging */
if (ha_init())
{
sql_print_error("Can't init databases");
unireg_abort(1);
}
+#ifdef WITH_CSV_STORAGE_ENGINE
+ if (opt_bootstrap)
+ log_output_options= LOG_FILE;
+ else
+ logger.init_log_tables();
+
+ if (log_output_options & LOG_NONE)
+ {
+ /*
+ Issue a warining if there were specified additional options to the
+ log-output along with NONE. Probably this wasn't what user wanted.
+ */
+ if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
+ sql_print_warning("There were other values specified to "
+ "log-output besides NONE. Disabling slow "
+ "and general logs anyway.");
+ logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE);
+ }
+ else
+ {
+ /* fall back to the log files if tables are not present */
+ if (have_csv_db == SHOW_OPTION_NO)
+ {
+ sql_print_error("CSV engine is not present, falling back to the "
+ "log files");
+ log_output_options= log_output_options & ~LOG_TABLE | LOG_FILE;
+ }
+
+ logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
+ opt_log ? log_output_options:LOG_NONE);
+ }
+#else
+ logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
+ opt_log ? LOG_FILE:LOG_NONE);
+#endif
+
/*
Check that the default storage engine is actually available.
*/
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index dfc5dd2989b..6761b28331e 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -21,9 +21,10 @@
#endif
#include "mysql_priv.h"
-#include "ha_partition.h"
#ifdef WITH_PARTITION_STORAGE_ENGINE
+#include "ha_partition.h"
+
partition_info *partition_info::get_clone()
{
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index cacae1aa4c2..99606353080 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -309,15 +309,14 @@ typedef struct st_relay_log_info
void cleanup_context(THD *, bool);
void clear_tables_to_lock() {
- TABLE_LIST *ptr= tables_to_lock;
- while (ptr)
+ while (tables_to_lock)
{
- char *to_free= reinterpret_cast(ptr);
- ptr= ptr->next_global;
+ char *to_free= reinterpret_cast(tables_to_lock);
+ tables_to_lock= tables_to_lock->next_global;
+ tables_to_lock_count--;
my_free(to_free, MYF(MY_WME));
}
- tables_to_lock= 0;
- tables_to_lock_count= 0;
+ DBUG_ASSERT(tables_to_lock == NULL && tables_to_lock_count == 0);
}
time_t unsafe_to_stop_at;
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 01e66b35c0f..a2bc77714bb 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -2978,52 +2978,52 @@ ER_UDF_EXISTS
swe "Funktionen '%-.64s' finns redan"
ukr "æÕÎËÃ¦Ñ '%-.64s' ×ÖÅ ¦ÓÎÕ¤"
ER_CANT_OPEN_LIBRARY
- cze "Nemohu otev-Bøít sdílenou knihovnu '%-.64s' (errno: %d %s)"
- dan "Kan ikke åbne delt bibliotek '%-.64s' (errno: %d %s)"
- nla "Kan shared library '%-.64s' niet openen (Errcode: %d %s)"
- eng "Can't open shared library '%-.64s' (errno: %d %s)"
- jps "shared library '%-.64s' ‚ðŠJ‚Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d %s)",
- est "Ei suuda avada jagatud teeki '%-.64s' (veakood: %d %s)"
- fre "Impossible d'ouvrir la bibliothèque partagée '%-.64s' (errno: %d %s)"
- ger "Kann Shared Library '%-.64s' nicht öffnen (Fehler: %d %s)"
- greek "Äåí åßíáé äõíáôÞ ç áíÜãíùóç ôçò shared library '%-.64s' (êùäéêüò ëÜèïõò: %d %s)"
- hun "A(z) '%-.64s' megosztott konyvtar nem hasznalhato (hibakod: %d %s)"
- ita "Impossibile aprire la libreria condivisa '%-.64s' (errno: %d %s)"
- jpn "shared library '%-.64s' ¤ò³«¤¯»ö¤¬¤Ç¤¤Þ¤»¤ó (errno: %d %s)"
- kor "'%-.64s' °øÀ¯ ¶óÀ̹ö·¯¸®¸¦ ¿¼ö ¾ø½À´Ï´Ù.(¿¡·¯¹øÈ£: %d %s)"
- nor "Can't open shared library '%-.64s' (errno: %d %s)"
- norwegian-ny "Can't open shared library '%-.64s' (errno: %d %s)"
- pol "Can't open shared library '%-.64s' (errno: %d %s)"
- por "Não pode abrir biblioteca compartilhada '%-.64s' (erro no. '%d' - '%-.64s')"
- rum "Nu pot deschide libraria shared '%-.64s' (Eroare: %d %s)"
- rus "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÉÎÁÍÉÞÅÓËÕÀ ÂÉÂÌÉÏÔÅËÕ '%-.64s' (ÏÛÉÂËÁ: %d %s)"
- serbian "Ne mogu da otvorim share-ovanu biblioteku '%-.64s' (errno: %d %s)"
- slo "Nemô¾em otvori» zdieµanú kni¾nicu '%-.64s' (chybový kód: %d %s)"
- spa "No puedo abrir libraria conjugada '%-.64s' (errno: %d %s)"
- swe "Kan inte öppna det dynamiska biblioteket '%-.64s' (Felkod: %d %s)"
- ukr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÒÏÚĦÌÀ×ÁÎÕ Â¦Â̦ÏÔÅËÕ '%-.64s' (ÐÏÍÉÌËÁ: %d %s)"
-ER_CANT_FIND_DL_ENTRY
- cze "Nemohu naj-Bít funkci '%-.64s' v knihovnì"
- dan "Kan ikke finde funktionen '%-.64s' i bibliotek"
- nla "Kan functie '%-.64s' niet in library vinden"
- eng "Can't find symbol '%-.64s' in library"
- jps "function '%-.64s' ‚ðƒ‰ƒCƒuƒ‰ƒŠ[’†‚ÉŒ©•t‚¯‚鎖‚ª‚Å‚«‚Ü‚¹‚ñ",
- est "Ei leia funktsiooni '%-.64s' antud teegis"
- fre "Impossible de trouver la fonction '%-.64s' dans la bibliothèque"
- ger "Kann Funktion '%-.64s' in der Library nicht finden"
- greek "Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò óõíÜñôçóçò '%-.64s' óôçí âéâëéïèÞêç"
- hun "A(z) '%-.64s' fuggveny nem talalhato a konyvtarban"
- ita "Impossibile trovare la funzione '%-.64s' nella libreria"
- jpn "function '%-.64s' ¤ò¥é¥¤¥Ö¥é¥ê¡¼Ãæ¤Ë¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤¤Þ¤»¤ó"
- kor "¶óÀ̹ö·¯¸®¿¡¼ '%-.64s' ÇÔ¼ö¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù."
- por "Não pode encontrar a função '%-.64s' na biblioteca"
- rum "Nu pot gasi functia '%-.64s' in libraria"
- rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÓÉÍ×ÏÌ '%-.64s' × ÂÉÂÌÉÏÔÅËÅ"
- serbian "Ne mogu da pronadjem funkciju '%-.64s' u biblioteci"
- slo "Nemô¾em nájs» funkciu '%-.64s' v kni¾nici"
- spa "No puedo encontrar función '%-.64s' en libraria"
- swe "Hittar inte funktionen '%-.64s' in det dynamiska biblioteket"
- ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÕÎËæÀ '%-.64s' Õ Â¦Â̦ÏÔÅæ"
+ cze "Nemohu otev-Bøít sdílenou knihovnu '%-.64s' (errno: %d %-.128s)"
+ dan "Kan ikke åbne delt bibliotek '%-.64s' (errno: %d %-.128s)"
+ nla "Kan shared library '%-.64s' niet openen (Errcode: %d %-.128s)"
+ eng "Can't open shared library '%-.64s' (errno: %d %-.128s)"
+ jps "shared library '%-.64s' ‚ðŠJ‚Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d %-.128s)",
+ est "Ei suuda avada jagatud teeki '%-.64s' (veakood: %d %-.128s)"
+ fre "Impossible d'ouvrir la bibliothèque partagée '%-.64s' (errno: %d %-.128s)"
+ ger "Kann Shared Library '%-.64s' nicht öffnen (Fehler: %d %-.128s)"
+ greek "Äåí åßíáé äõíáôÞ ç áíÜãíùóç ôçò shared library '%-.64s' (êùäéêüò ëÜèïõò: %d %-.128s)"
+ hun "A(z) '%-.64s' megosztott konyvtar nem hasznalhato (hibakod: %d %-.128s)"
+ ita "Impossibile aprire la libreria condivisa '%-.64s' (errno: %d %-.128s)"
+ jpn "shared library '%-.64s' ¤ò³«¤¯»ö¤¬¤Ç¤¤Þ¤»¤ó (errno: %d %-.128s)"
+ kor "'%-.64s' °øÀ¯ ¶óÀ̹ö·¯¸®¸¦ ¿¼ö ¾ø½À´Ï´Ù.(¿¡·¯¹øÈ£: %d %-.128s)"
+ nor "Can't open shared library '%-.64s' (errno: %d %-.128s)"
+ norwegian-ny "Can't open shared library '%-.64s' (errno: %d %-.128s)"
+ pol "Can't open shared library '%-.64s' (errno: %d %-.128s)"
+ por "Não pode abrir biblioteca compartilhada '%-.64s' (erro no. %d '%-.128s')"
+ rum "Nu pot deschide libraria shared '%-.64s' (Eroare: %d %-.128s)"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÉÎÁÍÉÞÅÓËÕÀ ÂÉÂÌÉÏÔÅËÕ '%-.64s' (ÏÛÉÂËÁ: %d %-.128s)"
+ serbian "Ne mogu da otvorim share-ovanu biblioteku '%-.64s' (errno: %d %-.128s)"
+ slo "Nemô¾em otvori» zdieµanú kni¾nicu '%-.64s' (chybový kód: %d %-.128s)"
+ spa "No puedo abrir libraria conjugada '%-.64s' (errno: %d %-.128s)"
+ swe "Kan inte öppna det dynamiska biblioteket '%-.64s' (Felkod: %d %-.128s)"
+ ukr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÒÏÚĦÌÀ×ÁÎÕ Â¦Â̦ÏÔÅËÕ '%-.64s' (ÐÏÍÉÌËÁ: %d %-.128s)"
+ER_CANT_FIND_DL_ENTRY
+ cze "Nemohu naj-Bít funkci '%-.128s' v knihovnì"
+ dan "Kan ikke finde funktionen '%-.128s' i bibliotek"
+ nla "Kan functie '%-.128s' niet in library vinden"
+ eng "Can't find symbol '%-.128s' in library"
+ jps "function '%-.128s' ‚ðƒ‰ƒCƒuƒ‰ƒŠ[’†‚ÉŒ©•t‚¯‚鎖‚ª‚Å‚«‚Ü‚¹‚ñ",
+ est "Ei leia funktsiooni '%-.128s' antud teegis"
+ fre "Impossible de trouver la fonction '%-.128s' dans la bibliothèque"
+ ger "Kann Funktion '%-.128s' in der Library nicht finden"
+ greek "Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò óõíÜñôçóçò '%-.128s' óôçí âéâëéïèÞêç"
+ hun "A(z) '%-.128s' fuggveny nem talalhato a konyvtarban"
+ ita "Impossibile trovare la funzione '%-.128s' nella libreria"
+ jpn "function '%-.128s' ¤ò¥é¥¤¥Ö¥é¥ê¡¼Ãæ¤Ë¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤¤Þ¤»¤ó"
+ kor "¶óÀ̹ö·¯¸®¿¡¼ '%-.128s' ÇÔ¼ö¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù."
+ por "Não pode encontrar a função '%-.128s' na biblioteca"
+ rum "Nu pot gasi functia '%-.128s' in libraria"
+ rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÓÉÍ×ÏÌ '%-.128s' × ÂÉÂÌÉÏÔÅËÅ"
+ serbian "Ne mogu da pronadjem funkciju '%-.128s' u biblioteci"
+ slo "Nemô¾em nájs» funkciu '%-.128s' v kni¾nici"
+ spa "No puedo encontrar función '%-.128s' en libraria"
+ swe "Hittar inte funktionen '%-.128s' in det dynamiska biblioteket"
+ ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÕÎËæÀ '%-.128s' Õ Â¦Â̦ÏÔÅæ"
ER_FUNCTION_NOT_DEFINED
cze "Funkce '%-.64s' nen-Bí definována"
dan "Funktionen '%-.64s' er ikke defineret"
@@ -5602,6 +5602,22 @@ ER_SP_RECURSION_LIMIT
ger "Rekursionsgrenze %d (durch Variable max_sp_recursion_depth gegeben) wurde für Routine %.64s überschritten"
ER_SP_PROC_TABLE_CORRUPT
eng "Failed to load routine %-.64s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)"
+ER_SP_WRONG_NAME 42000
+ eng "Incorrect routine name '%-.64s'"
+ER_TABLE_NEEDS_UPGRADE
+ eng "Table upgrade required. Please do \"REPAIR TABLE `%-.32s`\" to fix it!"
+ER_SP_NO_AGGREGATE 42000
+ eng "AGGREGATE is not supported for stored functions"
+ER_MAX_PREPARED_STMT_COUNT_REACHED 42000
+ eng "Can't create more than max_prepared_stmt_count statements (current value: %lu)"
+ER_VIEW_RECURSIVE
+ eng "`%-.64s`.`%-.64s` contains view recursion"
+ER_NON_GROUPING_FIELD_USED 42000
+ eng "non-grouping field '%-.64s' is used in %-.64s clause"
+ER_TABLE_CANT_HANDLE_SPKEYS
+ eng "The used table type doesn't support SPATIAL indexes"
+ER_ILLEGAL_HA_CREATE_OPTION
+ eng "Table storage engine '%-.64s' does not support the create option '%.64s'"
ER_PARTITION_REQUIRES_VALUES_ERROR
eng "%-.64s PARTITIONING requires definition of VALUES %-.64s for each partition"
swe "%-.64s PARTITIONering kräver definition av VALUES %-.64s för varje partition"
@@ -5798,32 +5814,16 @@ ER_EVENT_DATA_TOO_LONG
ER_DROP_INDEX_FK
eng "Cannot drop index '%-.64s': needed in a foreign key constraint"
ger "Kann Index '%-.64s' nicht löschen: wird für einen Fremdschlüssel benötigt"
+ER_WARN_DEPRECATED_SYNTAX
+ eng "The syntax '%s' is deprecated and will be removed in MySQL %s. Please use %s instead."
ER_CANT_WRITE_LOCK_LOG_TABLE
eng "You can't write-lock a log table. Only read access is possible."
ER_CANT_READ_LOCK_LOG_TABLE
eng "You can't use usual read lock with log tables. Try READ LOCAL instead."
-ER_SP_WRONG_NAME 42000
- eng "Incorrect routine name '%-.64s'"
ER_FOREIGN_DUPLICATE_KEY 23000 S1009
eng "Upholding foreign key constraints for table '%.64s', entry '%-.64s', key %d would lead to a duplicate entry"
ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE
eng "Column count of mysql.%s is wrong. Expected %d, found %d. Created with MySQL %d, now running %d. Please use scripts/mysql_fix_privilege_tables"
-ER_TABLE_NEEDS_UPGRADE
- eng "Table upgrade required. Please do \"REPAIR TABLE `%-.32s`\" to fix it!"
-ER_ILLEGAL_HA_CREATE_OPTION
- eng "Table storage engine '%-.64s' does not support the create option '%.64s'"
-ER_CANT_CHANGE_TX_ISOLATION 25001
- eng "Transaction isolation level can't be changed while a transaction is in progress"
-ER_WARN_DEPRECATED
- eng "The syntax '%s' is deprecated and will be removed in MySQL %s. Please use %s instead."
-ER_SP_NO_AGGREGATE 42000
- eng "AGGREGATE is not supported for stored functions"
-ER_MAX_PREPARED_STMT_COUNT_REACHED 42000
- eng "Can't create more than max_prepared_stmt_count statements (current value: %lu)"
-ER_VIEW_RECURSIVE
- eng "`%-.64s`.`%-.64s` contains view recursion"
-ER_NON_GROUPING_FIELD_USED 42000
- eng "non-grouping field '%-.64s' is used in %-.64s clause"
ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
eng "Cannot switch out of the row-based binary log format when the session has open temporary tables"
ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT
@@ -5840,3 +5840,5 @@ ER_NULL_IN_VALUES_LESS_THAN
ER_WRONG_PARTITION_NAME
eng "Incorrect partition name"
swe "Felaktigt partitionsnamn"
+ER_CANT_CHANGE_TX_ISOLATION 25001
+ eng "Transaction isolation level can't be changed while a transaction is in progress"
diff --git a/sql/sp.cc b/sql/sp.cc
index f7a6772146d..6f074fd7dce 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -268,7 +268,6 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table)
static int
db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
{
- extern int MYSQLparse(void *thd);
TABLE *table;
const char *params, *returns, *body;
int ret;
@@ -477,6 +476,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
(*sphp)->optimize();
}
end:
+ lex_end(thd->lex);
thd->spcont= old_spcont;
thd->variables.sql_mode= old_sql_mode;
thd->variables.select_limit= old_select_limit;
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index fbdb9a72640..8a64799e5f9 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -680,6 +680,7 @@ sp_head::destroy()
DBUG_ASSERT(m_lex.is_empty() || m_thd);
while ((lex= (LEX *)m_lex.pop()))
{
+ lex_end(m_thd->lex);
delete m_thd->lex;
m_thd->lex= lex;
}
@@ -1682,7 +1683,10 @@ sp_head::restore_lex(THD *thd)
*/
merge_table_list(thd, sublex->query_tables, sublex);
if (! sublex->sp_lex_in_use)
+ {
+ lex_end(sublex);
delete sublex;
+ }
thd->lex= oldlex;
DBUG_VOID_RETURN;
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 6b32ea13e5d..fbc277b4de8 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -521,7 +521,10 @@ public:
virtual ~sp_lex_keeper()
{
if (m_lex_resp)
+ {
+ lex_end(m_lex);
delete m_lex;
+ }
}
/*
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index a2359d1b52b..8ea53747b40 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -288,13 +288,13 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (!(share= alloc_table_share(table_list, key, key_length)))
{
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
DBUG_RETURN(0);
}
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
// We need a write lock to be able to add a new entry
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&LOCK_open);
@@ -331,19 +331,19 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
if (my_hash_insert(&table_def_cache, (byte*) share))
{
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
(void) pthread_mutex_unlock(&share->mutex);
#endif
free_table_share(share);
DBUG_RETURN(0); // return error
}
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
if (open_table_def(thd, share, db_flags))
{
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
/*
No such table or wrong table definition file
Lock first the table cache and then the mutex.
@@ -372,7 +372,7 @@ found:
/* We must do a lock to ensure that the structure is initialized */
(void) pthread_mutex_lock(&share->mutex);
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
pthread_mutex_unlock(&LOCK_open);
#endif
if (share->error)
@@ -540,7 +540,7 @@ void release_table_share(TABLE_SHARE *share, enum release_type type)
DBUG_VOID_RETURN;
-#ifdef NOT_YET
+#ifdef WAITING_FOR_TABLE_DEF_CACHE_STAGE_3
if (to_be_deleted)
{
/*
@@ -1070,7 +1070,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
binlog_query()) or when preparing a pending event.
*/
#ifdef HAVE_ROW_BASED_REPLICATION
- thd->binlog_flush_pending_rows_event(true);
+ thd->binlog_flush_pending_rows_event(TRUE);
#endif /*HAVE_ROW_BASED_REPLICATION*/
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
diff --git a/sql/sql_builtin.cc.in b/sql/sql_builtin.cc.in
new file mode 100644
index 00000000000..18705aa3dfb
--- /dev/null
+++ b/sql/sql_builtin.cc.in
@@ -0,0 +1,13 @@
+
+#include
+
+typedef struct st_mysql_plugin builtin_plugin[];
+
+extern builtin_plugin
+ builtin_binlog_plugin@mysql_plugin_defs@;
+
+struct st_mysql_plugin *mysqld_builtins[]=
+{
+ builtin_binlog_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0
+};
+
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 76f08fe14de..ebf0d988e7e 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2693,8 +2693,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype,
DBUG_ENTER("THD::binlog_query");
DBUG_ASSERT(query && mysql_bin_log.is_open());
- switch (qtype)
- {
+ switch (qtype) {
case THD::MYSQL_QUERY_TYPE:
/*
Using this query type is a conveniece hack, since we have been
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7d30800aeb4..04095ff9acd 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -112,17 +112,16 @@ class Key :public Sql_alloc {
public:
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
enum Keytype type;
- enum ha_key_alg algorithm;
+ KEY_CREATE_INFO key_create_info;
List columns;
const char *name;
bool generated;
- LEX_STRING *parser_name;
- Key(enum Keytype type_par, const char *name_arg, enum ha_key_alg alg_par,
- bool generated_arg, List &cols,
- LEX_STRING *parser_arg= 0)
- :type(type_par), algorithm(alg_par), columns(cols), name(name_arg),
- generated(generated_arg), parser_name(parser_arg)
+ Key(enum Keytype type_par, const char *name_arg,
+ KEY_CREATE_INFO *key_info_arg,
+ bool generated_arg, List &cols)
+ :type(type_par), key_create_info(*key_info_arg), columns(cols),
+ name(name_arg), generated(generated_arg)
{}
~Key() {}
/* Equality comparison of keys (ignoring name) */
@@ -144,7 +143,7 @@ public:
foreign_key(const char *name_arg, List &cols,
Table_ident *table, List &ref_cols,
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
- :Key(FOREIGN_KEY, name_arg, HA_KEY_ALG_UNDEF, 0, cols),
+ :Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
ref_table(table), ref_columns(cols),
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
match_opt(match_opt_arg)
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 4365d5b04ce..44b0fe1a2f1 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -21,7 +21,9 @@
*/
#include "mysql_priv.h"
+#ifdef WITH_INNOBASE_STORAGE_ENGINE
#include "ha_innodb.h"
+#endif
#include "sql_select.h"
#include "sp_head.h"
#include "sql_trigger.h"
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5a76066af8c..562224201e7 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -168,8 +168,6 @@ void lex_start(THD *thd, const uchar *buf, uint length)
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
lex->select_lex.group_list.empty();
lex->select_lex.order_list.empty();
- lex->current_select= &lex->select_lex;
- lex->yacc_yyss=lex->yacc_yyvs=0;
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
lex->sql_command= lex->orig_sql_command= SQLCOM_END;
lex->duplicates= DUP_ERROR;
@@ -197,8 +195,16 @@ void lex_start(THD *thd, const uchar *buf, uint length)
void lex_end(LEX *lex)
{
- x_free(lex->yacc_yyss);
- x_free(lex->yacc_yyvs);
+ DBUG_ENTER("lex_end");
+ DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex));
+ if (lex->yacc_yyss)
+ {
+ my_free(lex->yacc_yyss, MYF(0));
+ my_free(lex->yacc_yyvs, MYF(0));
+ lex->yacc_yyss= 0;
+ lex->yacc_yyvs= 0;
+ }
+ DBUG_VOID_RETURN;
}
@@ -1633,7 +1639,8 @@ void st_select_lex::print_limit(THD *thd, String *str)
*/
st_lex::st_lex()
- :result(0), sql_command(SQLCOM_END), query_tables_own_last(0)
+ :result(0), yacc_yyss(0), yacc_yyvs(0),
+ sql_command(SQLCOM_END), query_tables_own_last(0)
{
hash_init(&sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0);
sroutines_list.empty();
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 47fbc685bab..f0bd85367d0 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -840,6 +840,7 @@ typedef struct st_lex
udf_func udf;
HA_CHECK_OPT check_opt; // check/repair options
HA_CREATE_INFO create_info;
+ KEY_CREATE_INFO key_create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER
USER_RESOURCES mqh;
ulong type;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 2a913cc66aa..ae2a173c936 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -137,7 +137,7 @@ static void unlock_locked_tables(THD *thd)
}
-static bool end_active_trans(THD *thd)
+bool end_active_trans(THD *thd)
{
int error=0;
DBUG_ENTER("end_active_trans");
@@ -1753,7 +1753,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (alloc_query(thd, packet, packet_length))
break; // fatal error is set
char *packet_end= thd->query + thd->query_length;
- general_log_print(thd, command, "%s", thd->query);
+ general_log_print(thd, command, "%.*b", thd->query_length, thd->query);
DBUG_PRINT("query",("%-.4096s",thd->query));
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -2963,8 +2963,7 @@ end_with_restore_list:
thd->enable_slow_log= opt_log_slow_admin_statements;
if (end_active_trans(thd))
goto error;
- else
- res = mysql_create_index(thd, first_table, lex->key_list);
+ res= mysql_create_index(thd, first_table, lex->key_list);
break;
#ifdef HAVE_REPLICATION
@@ -3071,18 +3070,16 @@ end_with_restore_list:
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))
goto error;
- else
- {
- thd->enable_slow_log= opt_log_slow_admin_statements;
- res= mysql_alter_table(thd, select_lex->db, lex->name,
- &lex->create_info,
- first_table, lex->create_list,
- lex->key_list,
- select_lex->order_list.elements,
- (ORDER *) select_lex->order_list.first,
- lex->duplicates, lex->ignore, &lex->alter_info,
- 1);
- }
+
+ thd->enable_slow_log= opt_log_slow_admin_statements;
+ res= mysql_alter_table(thd, select_lex->db, lex->name,
+ &lex->create_info,
+ first_table, lex->create_list,
+ lex->key_list,
+ select_lex->order_list.elements,
+ (ORDER *) select_lex->order_list.first,
+ lex->duplicates, lex->ignore, &lex->alter_info,
+ 1);
break;
}
#endif /*DONT_ALLOW_SHOW_COMMANDS*/
@@ -3209,7 +3206,7 @@ end_with_restore_list:
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);
+ res= mysql_analyze_table(thd, first_table, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
@@ -3514,8 +3511,7 @@ end_with_restore_list:
goto error; /* purecov: inspected */
if (end_active_trans(thd))
goto error;
- else
- res = mysql_drop_index(thd, first_table, &lex->alter_info);
+ res= mysql_drop_index(thd, first_table, &lex->alter_info);
break;
case SQLCOM_SHOW_PROCESSLIST:
if (!thd->security_ctx->priv_user[0] &&
@@ -5977,14 +5973,16 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
if (type_modifier & PRI_KEY_FLAG)
{
lex->col_list.push_back(new key_part_spec(field_name,0));
- lex->key_list.push_back(new Key(Key::PRIMARY, NullS, HA_KEY_ALG_UNDEF,
+ lex->key_list.push_back(new Key(Key::PRIMARY, NullS,
+ &default_key_create_info,
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->key_list.push_back(new Key(Key::UNIQUE, NullS, HA_KEY_ALG_UNDEF, 0,
+ lex->key_list.push_back(new Key(Key::UNIQUE, NullS,
+ &default_key_create_info, 0,
lex->col_list));
lex->col_list.empty();
}
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 0442ad724d2..71b8e9b1d95 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -3430,6 +3430,7 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
result= FALSE;
end:
+ lex_end(thd->lex);
thd->free_list= thd_free_list;
thd->lex= old_lex;
thd->variables.character_set_client= old_character_set_client;
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index b4e42dc4700..01faae22c57 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -19,6 +19,8 @@
#define REPORT_TO_LOG 1
#define REPORT_TO_USER 2
+extern struct st_mysql_plugin *mysqld_builtins[];
+
char *opt_plugin_dir_ptr;
char opt_plugin_dir[FN_REFLEN];
LEX_STRING plugin_type_names[]=
@@ -529,7 +531,7 @@ static int plugin_initialize(struct st_plugin_int *plugin)
switch (plugin->plugin->type)
{
case MYSQL_STORAGE_ENGINE_PLUGIN:
- if (ha_initialize_handlerton((handlerton*) plugin->plugin->info))
+ if (ha_initialize_handlerton(plugin))
{
sql_print_error("Plugin '%s' handlerton init returned error.",
plugin->name.str);
@@ -548,6 +550,53 @@ err:
DBUG_RETURN(1);
}
+static int plugin_finalize(THD *thd, struct st_plugin_int *plugin)
+{
+ int rc;
+ DBUG_ENTER("plugin_finalize");
+
+ if (plugin->ref_count)
+ {
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "Plugin is busy and will be uninstalled on shutdown");
+ goto err;
+ }
+
+ switch (plugin->plugin->type)
+ {
+ case MYSQL_STORAGE_ENGINE_PLUGIN:
+ if (ha_finalize_handlerton(plugin))
+ {
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "Storage engine shutdown failed. "
+ "It will be uninstalled on shutdown");
+ sql_print_warning("Storage engine '%s' shutdown failed. "
+ "It will be uninstalled on shutdown", plugin->name.str);
+ goto err;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (plugin->plugin->deinit)
+ {
+ if ((rc= plugin->plugin->deinit()))
+ {
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+ "Plugin deinit failed. "
+ "It will be uninstalled on shutdown");
+ sql_print_warning("Plugin '%s' deinit failed. "
+ "It will be uninstalled on shutdown", plugin->name.str);
+ goto err;
+ }
+ }
+
+ DBUG_RETURN(0);
+err:
+ DBUG_RETURN(1);
+}
+
static void plugin_call_initializer(void)
{
uint i;
@@ -606,6 +655,8 @@ static byte *get_hash_key(const byte *buff, uint *length,
int plugin_init(void)
{
int i;
+ struct st_mysql_plugin **builtins;
+ struct st_mysql_plugin *plugin;
DBUG_ENTER("plugin_init");
if (initialized)
@@ -625,6 +676,16 @@ int plugin_init(void)
get_hash_key, NULL, 0))
goto err;
}
+
+ /* Register all the built-in plugins */
+ for (builtins= mysqld_builtins; *builtins; builtins++)
+ {
+ for (plugin= *builtins; plugin->info; plugin++)
+ {
+ if (plugin_register_builtin(plugin))
+ goto err;
+ }
+ }
initialized= 1;
@@ -831,18 +892,10 @@ my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name)
goto err;
}
- if (plugin->ref_count)
- {
- plugin->state= PLUGIN_IS_DELETED;
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
- "Plugin is not deleted, waiting on tables.");
- }
- else
- {
- if (plugin->plugin->deinit)
- plugin->plugin->deinit();
+ if (!plugin_finalize(thd, plugin))
plugin_del(name);
- }
+ else
+ plugin->state= PLUGIN_IS_DELETED;
table->field[0]->store(name->str, name->length, system_charset_info);
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index e0cf9095a22..6d0a0f4799c 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1755,6 +1755,9 @@ static bool check_prepared_statement(Prepared_statement *stmt,
case SQLCOM_CALL:
case SQLCOM_CREATE_VIEW:
case SQLCOM_DROP_VIEW:
+ case SQLCOM_REPAIR:
+ case SQLCOM_ANALYZE:
+ case SQLCOM_OPTIMIZE:
break;
default:
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 79b1c3836dc..5f8c4dd2e1a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3360,33 +3360,46 @@ best_access_path(JOIN *join,
for (keyuse=s->keyuse ; keyuse->table == table ;)
{
key_part_map found_part= 0;
- table_map found_ref= 0;
- uint found_ref_or_null= 0;
- uint key= keyuse->key;
+ table_map found_ref= 0;
+ uint key= keyuse->key;
KEY *keyinfo= table->key_info+key;
bool ft_key= (keyuse->keypart == FT_KEYPART);
+ uint found_ref_or_null= 0;
/* Calculate how many key segments of the current key we can use */
start_key= keyuse;
do
{ /* for each keypart */
uint keypart= keyuse->keypart;
- uint found_part_ref_or_null= KEY_OPTIMIZE_REF_OR_NULL;
+ table_map best_part_found_ref= 0;
+ double best_prev_record_reads= DBL_MAX;
do
{
if (!(remaining_tables & keyuse->used_tables) &&
!(found_ref_or_null & keyuse->optimize))
{
found_part|= keyuse->keypart_map;
- found_ref|= keyuse->used_tables;
+ double tmp= prev_record_reads(join,
+ (found_ref |
+ keyuse->used_tables));
+ if (tmp < best_prev_record_reads)
+ {
+ best_part_found_ref= keyuse->used_tables;
+ best_prev_record_reads= tmp;
+ }
if (rec > keyuse->ref_table_rows)
rec= keyuse->ref_table_rows;
- found_part_ref_or_null&= keyuse->optimize;
+ /*
+ If there is one 'key_column IS NULL' expression, we can
+ use this ref_or_null optimisation of this field
+ */
+ found_ref_or_null|= (keyuse->optimize &
+ KEY_OPTIMIZE_REF_OR_NULL);
}
keyuse++;
- found_ref_or_null|= found_part_ref_or_null;
} while (keyuse->table == table && keyuse->key == key &&
keyuse->keypart == keypart);
+ found_ref|= best_part_found_ref;
} while (keyuse->table == table && keyuse->key == key);
/*
@@ -3451,17 +3464,17 @@ best_access_path(JOIN *join,
}
}
/* Limit the number of matched rows */
- tmp = records;
+ tmp= records;
set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
if (table->used_keys.is_set(key))
{
/* we can use only index tree */
uint keys_per_block= table->file->block_size/2/
(keyinfo->key_length+table->file->ref_length)+1;
- tmp = record_count*(tmp+keys_per_block-1)/keys_per_block;
+ tmp= record_count*(tmp+keys_per_block-1)/keys_per_block;
}
else
- tmp = record_count*min(tmp,s->worst_seeks);
+ tmp= record_count*min(tmp,s->worst_seeks);
}
}
else
@@ -3475,7 +3488,7 @@ best_access_path(JOIN *join,
(!(table->file->index_flags(key, 0, 0) & HA_ONLY_WHOLE_INDEX) ||
found_part == PREV_BITS(uint,keyinfo->key_parts)))
{
- max_key_part=max_part_bit(found_part);
+ max_key_part= max_part_bit(found_part);
/*
Check if quick_range could determinate how many rows we
will match
@@ -3486,8 +3499,8 @@ best_access_path(JOIN *join,
else
{
/* Check if we have statistic about the distribution */
- if ((records = keyinfo->rec_per_key[max_key_part-1]))
- tmp = records;
+ if ((records= keyinfo->rec_per_key[max_key_part-1]))
+ tmp= records;
else
{
/*
@@ -3548,13 +3561,13 @@ best_access_path(JOIN *join,
/* we can use only index tree */
uint keys_per_block= table->file->block_size/2/
(keyinfo->key_length+table->file->ref_length)+1;
- tmp = record_count*(tmp+keys_per_block-1)/keys_per_block;
+ tmp= record_count*(tmp+keys_per_block-1)/keys_per_block;
}
else
- tmp = record_count*min(tmp,s->worst_seeks);
+ tmp= record_count*min(tmp,s->worst_seeks);
}
else
- tmp = best_time; // Do nothing
+ tmp= best_time; // Do nothing
}
} /* not ft_key */
if (tmp < best_time - records/(double) TIME_FOR_COMPARE)
@@ -3906,7 +3919,8 @@ optimize_straight_join(JOIN *join, table_map join_tables)
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
{
/* Find the best access method from 's' to the current partial plan */
- best_access_path(join, s, join->thd, join_tables, idx, record_count, read_time);
+ best_access_path(join, s, join->thd, join_tables, idx,
+ record_count, read_time);
/* compute the cost of the new plan extended with 's' */
record_count*= join->positions[idx].records_read;
read_time+= join->positions[idx].read_time;
@@ -4029,8 +4043,9 @@ greedy_search(JOIN *join,
'join->best_positions' contains a complete optimal extension of the
current partial QEP.
*/
- DBUG_EXECUTE("opt", print_plan(join, read_time, record_count,
- join->tables, "optimal"););
+ DBUG_EXECUTE("opt", print_plan(join, join->tables,
+ record_count, read_time, read_time,
+ "optimal"););
DBUG_VOID_RETURN;
}
@@ -4061,8 +4076,9 @@ greedy_search(JOIN *join,
--rem_size;
++idx;
- DBUG_EXECUTE("opt",
- print_plan(join, read_time, record_count, idx, "extended"););
+ DBUG_EXECUTE("opt", print_plan(join, join->tables,
+ record_count, read_time, read_time,
+ "extended"););
} while (TRUE);
}
@@ -4085,13 +4101,14 @@ greedy_search(JOIN *join,
read_time the cost of the best partial plan
search_depth maximum depth of the recursion and thus size of the found
optimal plan (0 < search_depth <= join->tables+1).
- prune_level pruning heuristics that should be applied during optimization
+ prune_level pruning heuristics that should be applied during
+ optimization
(values: 0 = EXHAUSTIVE, 1 = PRUNE_BY_TIME_OR_ROWS)
DESCRIPTION
The procedure searches for the optimal ordering of the query tables in set
- 'remaining_tables' of size N, and the corresponding optimal access paths to each
- table. The choice of a table order and an access path for each table
+ 'remaining_tables' of size N, and the corresponding optimal access paths to
+ each table. The choice of a table order and an access path for each table
constitutes a query execution plan (QEP) that fully specifies how to
execute the query.
@@ -4201,8 +4218,8 @@ best_extension_by_limited_search(JOIN *join,
double best_record_count= DBL_MAX;
double best_read_time= DBL_MAX;
- DBUG_EXECUTE("opt",
- print_plan(join, read_time, record_count, idx, "part_plan"););
+ DBUG_EXECUTE("opt", print_plan(join, idx, record_count, read_time, read_time,
+ "part_plan"););
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
{
@@ -4214,7 +4231,8 @@ best_extension_by_limited_search(JOIN *join,
double current_record_count, current_read_time;
/* Find the best access method from 's' to the current partial plan */
- best_access_path(join, s, thd, remaining_tables, idx, record_count, read_time);
+ best_access_path(join, s, thd, remaining_tables, idx,
+ record_count, read_time);
/* Compute the cost of extending the plan with 's' */
current_record_count= record_count * join->positions[idx].records_read;
current_read_time= read_time + join->positions[idx].read_time;
@@ -4223,7 +4241,12 @@ best_extension_by_limited_search(JOIN *join,
if ((current_read_time +
current_record_count / (double) TIME_FOR_COMPARE) >= join->best_read)
{
- DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx,
+ DBUG_EXECUTE("opt", print_plan(join, idx+1,
+ current_record_count,
+ read_time,
+ (current_read_time +
+ current_record_count /
+ (double) TIME_FOR_COMPARE),
"prune_by_cost"););
restore_prev_nj_state(s);
continue;
@@ -4252,7 +4275,10 @@ best_extension_by_limited_search(JOIN *join,
}
else
{
- DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx,
+ DBUG_EXECUTE("opt", print_plan(join, idx+1,
+ current_record_count,
+ read_time,
+ current_read_time,
"pruned_by_heuristic"););
restore_prev_nj_state(s);
continue;
@@ -4280,7 +4306,8 @@ best_extension_by_limited_search(JOIN *join,
*/
current_read_time+= current_record_count / (double) TIME_FOR_COMPARE;
if (join->sort_by_table &&
- join->sort_by_table != join->positions[join->const_tables].table->table)
+ join->sort_by_table !=
+ join->positions[join->const_tables].table->table)
/* We have to make a temp table */
current_read_time+= current_record_count;
if ((search_depth == 1) || (current_read_time < join->best_read))
@@ -4289,8 +4316,10 @@ best_extension_by_limited_search(JOIN *join,
sizeof(POSITION) * (idx + 1));
join->best_read= current_read_time - 0.001;
}
- DBUG_EXECUTE("opt", print_plan(join, current_read_time,
- current_record_count, idx,
+ DBUG_EXECUTE("opt", print_plan(join, idx+1,
+ current_record_count,
+ read_time,
+ current_read_time,
"full_plan"););
}
restore_prev_nj_state(s);
@@ -4311,7 +4340,6 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
ha_rows rec;
double tmp;
THD *thd= join->thd;
-
if (!rest_tables)
{
DBUG_PRINT("best",("read_time: %g record_count: %g",read_time,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 95433828a1e..4071f86989f 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -42,6 +42,9 @@ static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
grant_names, NULL};
#endif
+static void store_key_options(THD *thd, String *packet, TABLE *table,
+ KEY *key_info);
+
/***************************************************************************
** List all table types supported
***************************************************************************/
@@ -119,7 +122,7 @@ static my_bool show_plugins(THD *thd, st_plugin_int *plugin,
make_version_string(version_buf, sizeof(version_buf), plug->version),
cs);
-
+
switch (plugin->state)
{
/* case PLUGIN_IS_FREED: does not happen */
@@ -929,15 +932,12 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
handler *file= table->file;
TABLE_SHARE *share= table->s;
HA_CREATE_INFO create_info;
- my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
- MODE_ORACLE |
- MODE_MSSQL |
- MODE_DB2 |
- MODE_MAXDB |
- MODE_ANSI)) != 0;
- my_bool limited_mysql_mode= (thd->variables.sql_mode &
- (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
- MODE_MYSQL40)) != 0;
+ bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
+ MODE_ORACLE |
+ MODE_MSSQL |
+ MODE_DB2 |
+ MODE_MAXDB |
+ MODE_ANSI)) != 0;
DBUG_ENTER("store_create_info");
DBUG_PRINT("enter",("table: %s", table->s->table_name.str));
@@ -1100,22 +1100,12 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
if (!found_primary)
append_identifier(thd, packet, key_info->name, strlen(key_info->name));
- if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
- !limited_mysql_mode && !foreign_db_mode)
- {
- if (key_info->algorithm == HA_KEY_ALG_BTREE)
- packet->append(STRING_WITH_LEN(" USING BTREE"));
+#if MYSQL_VERSION_ID < 50300
+ /* Key options moved to after key parts in 5.3.0 */
+ if (!thd->variables.new_mode)
+ store_key_options(thd, packet, table, key_info);
+#endif
- if (key_info->algorithm == HA_KEY_ALG_HASH)
- packet->append(STRING_WITH_LEN(" USING HASH"));
-
- // +BAR: send USING only in non-default case: non-spatial rtree
- if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
- !(key_info->flags & HA_SPATIAL))
- packet->append(STRING_WITH_LEN(" USING RTREE"));
-
- // No need to send USING FULLTEXT, it is sent as FULLTEXT KEY
- }
packet->append(STRING_WITH_LEN(" ("));
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
@@ -1140,6 +1130,10 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
}
}
packet->append(')');
+#if MYSQL_VERSION_ID < 50300
+ if (thd->variables.new_mode)
+#endif
+ store_key_options(thd, packet, table, key_info);
if (key_info->parser)
{
packet->append(" WITH PARSER ", 13);
@@ -1252,6 +1246,12 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
packet->append(ha_row_type[(uint) share->row_type]);
}
+ if (table->s->key_block_size)
+ {
+ packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
+ end= longlong10_to_str(table->s->key_block_size, buff, 10);
+ packet->append(buff, (uint) (end - buff));
+ }
table->file->append_create_info(packet);
if (share->comment && share->comment[0])
{
@@ -1286,6 +1286,47 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
DBUG_RETURN(0);
}
+
+static void store_key_options(THD *thd, String *packet, TABLE *table,
+ KEY *key_info)
+{
+ bool limited_mysql_mode= (thd->variables.sql_mode &
+ (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
+ MODE_MYSQL40)) != 0;
+ bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
+ MODE_ORACLE |
+ MODE_MSSQL |
+ MODE_DB2 |
+ MODE_MAXDB |
+ MODE_ANSI)) != 0;
+ char *end, buff[32];
+
+ if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
+ !limited_mysql_mode && !foreign_db_mode)
+ {
+
+ if (key_info->algorithm == HA_KEY_ALG_BTREE)
+ packet->append(STRING_WITH_LEN(" USING BTREE"));
+
+ if (key_info->algorithm == HA_KEY_ALG_HASH)
+ packet->append(STRING_WITH_LEN(" USING HASH"));
+
+ /* send USING only in non-default case: non-spatial rtree */
+ if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
+ !(key_info->flags & HA_SPATIAL))
+ packet->append(STRING_WITH_LEN(" USING RTREE"));
+
+ if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
+ table->s->key_block_size != key_info->block_size)
+ {
+ packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
+ end= longlong10_to_str(key_info->block_size, buff, 10);
+ packet->append(buff, (uint) (end - buff));
+ }
+ }
+}
+
+
void
view_store_options(THD *thd, TABLE_LIST *table, String *buff)
{
@@ -1553,15 +1594,11 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
TABLE *table= tables->table;
CHARSET_INFO *cs= system_charset_info;
char *user;
- bool verbose;
- ulong max_query_length;
time_t now= time(0);
DBUG_ENTER("fill_process_list");
user= thd->security_ctx->master_access & PROCESS_ACL ?
NullS : thd->security_ctx->priv_user;
- verbose= thd->lex->verbose;
- max_query_length= PROCESS_LIST_WIDTH;
VOID(pthread_mutex_lock(&LOCK_thread_count));
@@ -1645,7 +1682,8 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
if (tmp->query)
{
table->field[7]->store(tmp->query,
- min(max_query_length, tmp->query_length), cs);
+ min(PROCESS_LIST_INFO_WIDTH,
+ tmp->query_length), cs);
table->field[7]->set_notnull();
}
@@ -3000,46 +3038,49 @@ int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond)
}
-int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond)
+static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin,
+ void *ptable)
{
+ TABLE *table= (TABLE *) ptable;
+ handlerton *hton= (handlerton *) plugin->plugin->info;
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
- TABLE *table= tables->table;
CHARSET_INFO *scs= system_charset_info;
- handlerton **types;
+ DBUG_ENTER("iter_schema_engines");
- DBUG_ENTER("fill_schema_engines");
-
- for (types= sys_table_types; *types; types++)
+ if (!(hton->flags & HTON_HIDDEN))
{
- if ((*types)->flags & HTON_HIDDEN)
- continue;
-
if (!(wild && wild[0] &&
- wild_case_compare(scs, (*types)->name,wild)))
+ wild_case_compare(scs, hton->name,wild)))
{
const char *tmp;
restore_record(table, s->default_values);
- table->field[0]->store((*types)->name, strlen((*types)->name), scs);
- tmp= (*types)->state ? "DISABLED" : "ENABLED";
+ table->field[0]->store(hton->name, strlen(hton->name), scs);
+ tmp= hton->state ? "DISABLED" : "ENABLED";
table->field[1]->store( tmp, strlen(tmp), scs);
- table->field[2]->store((*types)->comment, strlen((*types)->comment), scs);
- tmp= (*types)->commit ? "YES" : "NO";
+ table->field[2]->store(hton->comment, strlen(hton->comment), scs);
+ tmp= hton->commit ? "YES" : "NO";
table->field[3]->store( tmp, strlen(tmp), scs);
- tmp= (*types)->prepare ? "YES" : "NO";
+ tmp= hton->prepare ? "YES" : "NO";
table->field[4]->store( tmp, strlen(tmp), scs);
- tmp= (*types)->savepoint_set ? "YES" : "NO";
+ tmp= hton->savepoint_set ? "YES" : "NO";
table->field[5]->store( tmp, strlen(tmp), scs);
if (schema_table_store_record(thd, table))
DBUG_RETURN(1);
}
}
-
DBUG_RETURN(0);
}
+int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ return plugin_foreach(thd, iter_schema_engines,
+ MYSQL_STORAGE_ENGINE_PLUGIN, tables->table);
+}
+
+
int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
{
CHARSET_INFO **cs;
@@ -4231,6 +4272,75 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
}
+/*
+ Fill and store records into I_S.referential_constraints table
+
+ SYNOPSIS
+ get_referential_constraints_record()
+ thd thread handle
+ tables table list struct(processed table)
+ table I_S table
+ res 1 means the error during opening of the processed table
+ 0 means processed table is opened without error
+ base_name db name
+ file_name table name
+
+ RETURN
+ 0 ok
+ # error
+*/
+
+static int
+get_referential_constraints_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name, const char *file_name)
+{
+ CHARSET_INFO *cs= system_charset_info;
+ DBUG_ENTER("get_referential_constraints_record");
+
+ if (res)
+ {
+ if (!tables->view)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ thd->net.last_errno, thd->net.last_error);
+ thd->clear_error();
+ DBUG_RETURN(0);
+ }
+ if (!tables->view)
+ {
+ List f_key_list;
+ TABLE *show_table= tables->table;
+ show_table->file->info(HA_STATUS_VARIABLE |
+ HA_STATUS_NO_LOCK |
+ HA_STATUS_TIME);
+
+ show_table->file->get_foreign_key_list(thd, &f_key_list);
+ FOREIGN_KEY_INFO *f_key_info;
+ List_iterator_fast it(f_key_list);
+ while ((f_key_info= it++))
+ {
+ restore_record(table, s->default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[9]->store(file_name, strlen(file_name), cs);
+ table->field[2]->store(f_key_info->forein_id->str,
+ f_key_info->forein_id->length, cs);
+ table->field[4]->store(f_key_info->referenced_db->str,
+ f_key_info->referenced_db->length, cs);
+ table->field[5]->store(f_key_info->referenced_table->str,
+ f_key_info->referenced_table->length, cs);
+ table->field[6]->store(STRING_WITH_LEN("NONE"), cs);
+ table->field[7]->store(f_key_info->update_method->str,
+ f_key_info->update_method->length, cs);
+ table->field[8]->store(f_key_info->delete_method->str,
+ f_key_info->delete_method->length, cs);
+ if (schema_table_store_record(thd, table))
+ DBUG_RETURN(1);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
/*
Find schema_tables elment by name
@@ -5096,9 +5206,9 @@ ST_FIELD_INFO processlist_fields_info[]=
{"HOST", LIST_PROCESS_HOST_LEN, MYSQL_TYPE_STRING, 0, 0, "Host"},
{"DB", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Db"},
{"COMMAND", 16, MYSQL_TYPE_STRING, 0, 0, "Command"},
- {"TIME", 4, MYSQL_TYPE_LONG, 0, 0, "Time"},
+ {"TIME", 7, MYSQL_TYPE_LONG, 0, 0, "Time"},
{"STATE", 30, MYSQL_TYPE_STRING, 0, 1, "State"},
- {"INFO", PROCESS_LIST_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info"},
+ {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info"},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
};
@@ -5160,6 +5270,22 @@ ST_FIELD_INFO files_fields_info[]=
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
};
+ST_FIELD_INFO referential_constraints_fields_info[]=
+{
+ {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"UNIQUE_CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"UNIQUE_CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"UNIQUE_CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"MATCH_OPTION", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"UPDATE_RULE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"DELETE_RULE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
/*
Description of ST_FIELD_INFO in table.h
@@ -5195,6 +5321,9 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_plugins, make_old_format, 0, -1, -1, 0},
{"PROCESSLIST", processlist_fields_info, create_schema_table,
fill_schema_processlist, make_old_format, 0, -1, -1, 0},
+ {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info,
+ create_schema_table, get_all_tables, 0, get_referential_constraints_record,
+ 1, 9, 0},
{"ROUTINES", proc_fields_info, create_schema_table,
fill_schema_proc, make_proc_old_format, 0, -1, -1, 0},
{"SCHEMATA", schema_fields_info, create_schema_table,
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 79228be8a76..19ee9f259dc 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -331,7 +331,7 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
return copy_aligned(str, arg_length, offset, cs);
}
- /* Copy with charset convertion */
+ /* Copy with charset conversion */
bool String::copy(const char *str, uint32 arg_length,
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors)
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 412682fc3b0..f890f504952 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -231,10 +231,9 @@ static int mysql_copy_key_list(List *orig_key,
}
}
if (!(temp_key= new Key(prep_key->type, prep_key->name,
- prep_key->algorithm,
+ &prep_key->key_create_info,
prep_key->generated,
- prep_columns,
- prep_key->parser_name)))
+ prep_columns)))
{
mem_alloc_error(sizeof(Key));
DBUG_RETURN(TRUE);
@@ -428,10 +427,6 @@ static uint read_ddl_log_header()
bool successful_open= FALSE;
DBUG_ENTER("read_ddl_log_header");
- bzero(file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
- global_ddl_log.inited= FALSE;
- global_ddl_log.recovery_phase= TRUE;
- global_ddl_log.io_size= IO_SIZE;
create_ddl_log_file_name(file_name);
if ((global_ddl_log.file_id= my_open(file_name,
O_RDWR | O_BINARY, MYF(MY_WME))) >= 0)
@@ -508,12 +503,14 @@ bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
Initialise ddl log
SYNOPSIS
init_ddl_log()
- RETURN VALUES
- TRUE Error
- FALSE Success
+
DESCRIPTION
Write the header of the ddl log file and length of names. Also set
number of entries to zero.
+
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
*/
static bool init_ddl_log()
@@ -523,9 +520,8 @@ static bool init_ddl_log()
DBUG_ENTER("init_ddl_log");
if (global_ddl_log.inited)
- {
- DBUG_RETURN(FALSE);
- }
+ goto end;
+
global_ddl_log.io_size= IO_SIZE;
create_ddl_log_file_name(file_name);
if ((global_ddl_log.file_id= my_create(file_name,
@@ -540,9 +536,12 @@ static bool init_ddl_log()
global_ddl_log.inited= TRUE;
if (write_ddl_log_header())
{
+ VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
global_ddl_log.inited= FALSE;
DBUG_RETURN(TRUE);
}
+
+end:
DBUG_RETURN(FALSE);
}
@@ -1067,6 +1066,15 @@ void execute_ddl_log_recovery()
char file_name[FN_REFLEN];
DBUG_ENTER("execute_ddl_log_recovery");
+ /*
+ Initialise global_ddl_log struct
+ */
+ bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
+ global_ddl_log.inited= FALSE;
+ global_ddl_log.recovery_phase= TRUE;
+ global_ddl_log.io_size= IO_SIZE;
+ global_ddl_log.file_id= (File) -1;
+
/*
To be able to run this from boot, we allocate a temporary THD
*/
@@ -1130,7 +1138,12 @@ void release_ddl_log()
my_free((char*)free_list, MYF(0));
free_list= tmp;
}
- VOID(my_close(global_ddl_log.file_id, MYF(0)));
+ if (global_ddl_log.file_id >= 0)
+ {
+ VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
+ global_ddl_log.file_id= (File) -1;
+ }
+ global_ddl_log.inited= 0;
pthread_mutex_unlock(&LOCK_gdl);
VOID(pthread_mutex_destroy(&LOCK_gdl));
DBUG_VOID_RETURN;
@@ -2495,14 +2508,16 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
break;
}
- switch(key->type){
+ switch (key->type) {
case Key::MULTIPLE:
key_info->flags= 0;
break;
case Key::FULLTEXT:
key_info->flags= HA_FULLTEXT;
- if ((key_info->parser_name= key->parser_name))
+ if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
key_info->flags|= HA_USES_PARSER;
+ else
+ key_info->parser_name= 0;
break;
case Key::SPATIAL:
#ifdef HAVE_SPATIAL
@@ -2526,7 +2541,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->key_parts=(uint8) key->columns.elements;
key_info->key_part=key_part_info;
key_info->usable_key_parts= key_number;
- key_info->algorithm=key->algorithm;
+ key_info->algorithm= key->key_create_info.algorithm;
if (key->type == Key::FULLTEXT)
{
@@ -2548,6 +2563,12 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
/* TODO: Add proper checks if handler supports key_type and algorithm */
if (key_info->flags & HA_SPATIAL)
{
+ if (!(file->table_flags() & HA_CAN_RTREEKEYS))
+ {
+ my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
+ MYF(0));
+ DBUG_RETURN(-1);
+ }
if (key_info->key_parts != 1)
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
@@ -2572,6 +2593,18 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
#endif
}
+ /* Take block size from key part or table part */
+ /*
+ TODO: Add warning if block size changes. We can't do it here, as
+ this may depend on the size of the key
+ */
+ key_info->block_size= (key->key_create_info.block_size ?
+ key->key_create_info.block_size :
+ create_info->key_block_size);
+
+ if (key_info->block_size)
+ key_info->flags|= HA_USES_BLOCK_SIZE;
+
List_iterator cols(key->columns), cols2(key->columns);
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
@@ -3545,7 +3578,9 @@ mysql_rename_table(handlerton *base,
}
}
delete file;
- if (error)
+ if (error == HA_ERR_WRONG_COMMAND)
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
+ else if (error)
my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
DBUG_RETURN(error != 0);
}
@@ -3863,6 +3898,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
int result_code;
DBUG_ENTER("mysql_admin_table");
+ if (end_active_trans(thd))
+ DBUG_RETURN(1);
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Op", 10));
@@ -3913,6 +3950,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
{
switch ((*prepare_func)(thd, table, check_opt)) {
case 1: // error, message written to net
+ ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
continue;
case -1: // error, message could be written to net
@@ -3954,6 +3992,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
View opening can be interrupted in the middle of process so some
tables can be left opening
*/
+ ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
if (protocol->write())
goto err;
@@ -3978,6 +4017,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
table_name);
protocol->store(buff, length, system_charset_info);
+ ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
table->table=0; // For query cache
if (protocol->write())
@@ -4023,6 +4063,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
(table->table->file->ha_check_for_upgrade(check_opt) ==
HA_ADMIN_NEEDS_ALTER))
{
+ ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
result_code= mysql_recreate_table(thd, table, 0);
@@ -4109,6 +4150,7 @@ send_result_message:
"try with alter", so here we close the table, do an ALTER TABLE,
reopen the table and do ha_innobase::analyze() on it.
*/
+ ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
TABLE_LIST *save_next_local= table->next_local,
*save_next_global= table->next_global;
@@ -4116,6 +4158,7 @@ send_result_message:
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
result_code= mysql_recreate_table(thd, table, 0);
reenable_binlog(thd);
+ ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
if (!result_code) // recreation went ok
{
@@ -4190,14 +4233,20 @@ send_result_message:
table->table->s->version=0; // Force close of table
else if (open_for_modify && !table->table->s->log_table)
{
- pthread_mutex_lock(&LOCK_open);
- remove_table_from_cache(thd, table->table->s->db.str,
- table->table->s->table_name.str, RTFC_NO_FLAG);
- pthread_mutex_unlock(&LOCK_open);
- /* Something may be modified, that's why we have to invalidate cache */
+ if (table->table->s->tmp_table)
+ table->table->file->info(HA_STATUS_CONST);
+ else
+ {
+ pthread_mutex_lock(&LOCK_open);
+ remove_table_from_cache(thd, table->table->s->db.str,
+ table->table->s->table_name.str, RTFC_NO_FLAG);
+ pthread_mutex_unlock(&LOCK_open);
+ }
+ /* May be something modified consequently we have to invalidate cache */
query_cache_invalidate3(thd, table->table, 0);
}
}
+ ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
table->table=0; // For query cache
if (protocol->write())
@@ -4206,7 +4255,9 @@ send_result_message:
send_eof(thd);
DBUG_RETURN(FALSE);
+
err:
+ ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
@@ -4661,7 +4712,9 @@ mysql_discard_or_import_tablespace(THD *thd,
if (error)
goto err;
write_bin_log(thd, FALSE, thd->query, thd->query_length);
+
err:
+ ha_autocommit_or_rollback(thd, error);
close_thread_tables(thd);
thd->tablespace_op=FALSE;
@@ -5142,6 +5195,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
create_info->avg_row_length= table->s->avg_row_length;
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
create_info->default_table_charset= table->s->table_charset;
+ if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
+ create_info->key_block_size= table->s->key_block_size;
restore_record(table, s->default_values); // Empty record for DEFAULT
List_iterator drop_it(alter_info->drop_list);
@@ -5344,6 +5399,16 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
key_part_length));
}
if (key_parts.elements)
+ {
+ KEY_CREATE_INFO key_create_info;
+ bzero((char*) &key_create_info, sizeof(key_create_info));
+
+ key_create_info.algorithm= key_info->algorithm;
+ if (key_info->flags & HA_USES_BLOCK_SIZE)
+ key_create_info.block_size= key_info->block_size;
+ if (key_info->flags & HA_USES_PARSER)
+ key_create_info.parser_name= *key_info->parser_name;
+
key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
(key_info->flags & HA_NOSAME ?
(!my_strcasecmp(system_charset_info,
@@ -5352,11 +5417,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
(key_info->flags & HA_FULLTEXT ?
Key::FULLTEXT : Key::MULTIPLE)),
key_name,
- key_info->algorithm,
+ &key_create_info,
test(key_info->flags & HA_GENERATED_KEY),
- key_parts,
- key_info->flags & HA_USES_PARSER ?
- &key_info->parser->name : 0));
+ key_parts));
+ }
}
{
Key *key;
@@ -5452,9 +5516,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
while ((prep_col= prep_col_it++))
prep_columns.push_back(new key_part_spec(*prep_col));
prepared_key_list.push_back(new Key(prep_key->type, prep_key->name,
- prep_key->algorithm,
- prep_key->generated, prep_columns,
- prep_key->parser_name));
+ &prep_key->key_create_info,
+ prep_key->generated, prep_columns));
}
/* Create the prepared information. */
@@ -6338,7 +6401,8 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
}
-bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
+bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
+ HA_CHECK_OPT *check_opt)
{
TABLE_LIST *table;
List- field_list;
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index bf86630d28c..b28aa4a1ce5 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -230,8 +230,8 @@ TEST_join(JOIN *join)
*/
void
-print_plan(JOIN* join, double read_time, double record_count,
- uint idx, const char *info)
+print_plan(JOIN* join, uint idx, double record_count, double read_time,
+ double current_read_time, const char *info)
{
uint i;
POSITION pos;
@@ -245,13 +245,15 @@ print_plan(JOIN* join, double read_time, double record_count,
DBUG_LOCK_FILE;
if (join->best_read == DBL_MAX)
{
- fprintf(DBUG_FILE,"%s; idx:%u, best: DBL_MAX, current:%g\n",
- info, idx, read_time);
+ fprintf(DBUG_FILE,
+ "%s; idx:%u, best: DBL_MAX, atime: %g, itime: %g, count: %g\n",
+ info, idx, current_read_time, read_time, record_count);
}
else
{
- fprintf(DBUG_FILE,"%s; idx: %u, best: %g, current: %g\n",
- info, idx, join->best_read, read_time);
+ fprintf(DBUG_FILE,
+ "%s; idx:%u, best: %g, accumulated: %g, increment: %g, count: %g\n",
+ info, idx, join->best_read, current_read_time, read_time, record_count);
}
/* Print the tables in JOIN->positions */
@@ -270,9 +272,9 @@ print_plan(JOIN* join, double read_time, double record_count,
Print the tables in JOIN->best_positions only if at least one complete plan
has been found. An indicator for this is the value of 'join->best_read'.
*/
- fputs("BEST_POSITIONS: ", DBUG_FILE);
if (join->best_read < DBL_MAX)
{
+ fputs("BEST_POSITIONS: ", DBUG_FILE);
for (i= 0; i < idx ; i++)
{
pos= join->best_positions[i];
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 3ef6a234f4e..8e5a776950d 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -943,7 +943,6 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
goto err;
}
-
if (!(table->view_tables=
(List*) new(thd->mem_root) List))
goto err;
@@ -1194,6 +1193,7 @@ ok2:
old_lex->time_zone_tables_used= thd->lex->time_zone_tables_used;
result= !table->prelocking_placeholder && table->prepare_security(thd);
+ lex_end(thd->lex);
end:
if (arena)
thd->restore_active_arena(arena, &backup);
@@ -1201,6 +1201,8 @@ end:
DBUG_RETURN(result);
err:
+ DBUG_ASSERT(thd->lex == table->view);
+ lex_end(thd->lex);
delete table->view;
table->view= 0; // now it is not VIEW placeholder
result= 1;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ab87c78d17c..32b5bc8adb9 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -364,6 +364,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token JOIN_SYM
%token KEYS
%token KEY_SYM
+%token KEY_BLOCK_SIZE
%token KILL_SYM
%token LANGUAGE_SYM
%token LAST_INSERT_ID
@@ -730,7 +731,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem
%type
- opt_table_alias opt_fulltext_parser
+ opt_table_alias
%type
table_ident table_ident_nodb references xid
@@ -795,7 +796,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
key_type opt_unique_or_fulltext constraint_key_type
%type
- key_alg opt_btree_or_rtree
+ opt_btree_or_rtree
%type
key_usage_list using_list
@@ -886,6 +887,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
view_suid view_tail view_list_opt view_list view_select
view_check_option trigger_tail sp_tail
install uninstall partition_entry binlog_base64_event
+ init_key_options key_options key_opts key_opt
END_OF_INPUT
%type call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -1220,11 +1222,13 @@ create:
}
create2
{ Lex->current_select= &Lex->select_lex; }
- | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident
+ | 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,
+ if (!lex->current_select->add_table_to_list(lex->thd, $7,
+ NULL,
TL_OPTION_UPDATING))
YYABORT;
lex->create_list.empty();
@@ -1232,15 +1236,16 @@ create:
lex->col_list.empty();
lex->change=NullS;
}
- '(' key_list ')' opt_fulltext_parser
+ '(' key_list ')' key_options
{
LEX *lex=Lex;
- if ($2 != Key::FULLTEXT && $12)
+ if ($2 != Key::FULLTEXT && lex->key_create_info.parser_name.str)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
- lex->key_list.push_back(new Key($2,$4.str,$5,0,lex->col_list,$12));
+ lex->key_list.push_back(new Key($2, $4.str, &lex->key_create_info, 0,
+ lex->col_list));
lex->col_list.empty();
}
| CREATE DATABASE opt_if_not_exists ident
@@ -3890,6 +3895,11 @@ create_table_option:
| STORAGE_SYM DISK_SYM {Lex->create_info.store_on_disk= TRUE;}
| STORAGE_SYM MEMORY_SYM {Lex->create_info.store_on_disk= FALSE;}
| 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; }
+ | KEY_BLOCK_SIZE opt_equal ulong_num
+ {
+ Lex->create_info.used_fields|= HA_CREATE_USED_KEY_BLOCK_SIZE;
+ Lex->create_info.key_block_size= $3;
+ }
;
default_charset:
@@ -3983,23 +3993,25 @@ column_def:
;
key_def:
- key_type opt_ident key_alg '(' key_list ')' opt_fulltext_parser
+ key_type opt_ident key_alg '(' key_list ')' key_options
{
LEX *lex=Lex;
- if ($1 != Key::FULLTEXT && $7)
+ if ($1 != Key::FULLTEXT && lex->key_create_info.parser_name.str)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
- lex->key_list.push_back(new Key($1,$2, $3, 0, lex->col_list, $7));
+ lex->key_list.push_back(new Key($1,$2, &lex->key_create_info, 0,
+ lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */
}
- | opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')'
+ | opt_constraint constraint_key_type opt_ident key_alg
+ '(' key_list ')' key_options
{
LEX *lex=Lex;
- const char *key_name= $3 ? $3:$1;
- lex->key_list.push_back(new Key($2, key_name, $4, 0,
- lex->col_list));
+ const char *key_name= $3 ? $3 : $1;
+ lex->key_list.push_back(new Key($2, key_name, &lex->key_create_info, 0,
+ lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */
}
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
@@ -4012,7 +4024,7 @@ key_def:
lex->fk_update_opt,
lex->fk_match_option));
lex->key_list.push_back(new Key(Key::MULTIPLE, $4 ? $4 : $1,
- HA_KEY_ALG_UNDEF, 1,
+ &default_key_create_info, 1,
lex->col_list));
lex->col_list.empty(); /* Alloced by sql_alloc */
@@ -4029,20 +4041,6 @@ key_def:
}
;
-opt_fulltext_parser:
- /* empty */ { $$= (LEX_STRING *)0; }
- | WITH PARSER_SYM IDENT_sys
- {
- if (plugin_is_ready(&$3, MYSQL_FTPARSER_PLUGIN))
- $$= (LEX_STRING *)sql_memdup(&$3, sizeof(LEX_STRING));
- else
- {
- my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str);
- YYABORT;
- }
- }
- ;
-
opt_check_constraint:
/* empty */
| check_constraint
@@ -4516,10 +4514,50 @@ opt_unique_or_fulltext:
}
;
+init_key_options:
+ {
+ Lex->key_create_info= default_key_create_info;
+ }
+ ;
+
+/*
+ For now, key_alg initializies lex->key_create_info.
+ In the future, when all key options are after key definition,
+ we can remove key_alg and move init_key_options to key_options
+*/
+
key_alg:
- /* empty */ { $$= HA_KEY_ALG_UNDEF; }
- | USING opt_btree_or_rtree { $$= $2; }
- | TYPE_SYM opt_btree_or_rtree { $$= $2; };
+ /* empty */ init_key_options
+ | init_key_options key_opts
+ ;
+
+key_options:
+ /* empty */ {}
+ | key_opts
+ ;
+
+key_opts:
+ key_opt
+ | key_opts key_opt
+ ;
+
+key_opt:
+ USING opt_btree_or_rtree { Lex->key_create_info.algorithm= $2; }
+ | TYPE_SYM opt_btree_or_rtree { Lex->key_create_info.algorithm= $2; }
+ | KEY_BLOCK_SIZE opt_equal ulong_num
+ { Lex->key_create_info.block_size= $3; }
+ | WITH PARSER_SYM IDENT_sys
+ {
+ if (plugin_is_ready(&$3, MYSQL_FTPARSER_PLUGIN))
+ Lex->key_create_info.parser_name= $3;
+ else
+ {
+ my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str);
+ YYABORT;
+ }
+ }
+ ;
+
opt_btree_or_rtree:
BTREE_SYM { $$= HA_KEY_ALG_BTREE; }
@@ -8038,7 +8076,7 @@ show_param:
if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES))
YYABORT;
}
- | PLUGIN_SYM
+ | opt_full PLUGIN_SYM
{
LEX *lex= Lex;
WARN_DEPRECATED(yythd, "5.2", "SHOW PLUGIN", "'SHOW PLUGINS'");
@@ -9348,7 +9386,7 @@ keyword_sp:
| ISSUER_SYM {}
| INNOBASE_SYM {}
| INSERT_METHOD {}
- | RELAY_THREAD {}
+ | KEY_BLOCK_SIZE {}
| LAST_SYM {}
| LEAVES {}
| LESS_SYM {}
@@ -9435,6 +9473,7 @@ keyword_sp:
| REDUNDANT_SYM {}
| RELAY_LOG_FILE_SYM {}
| RELAY_LOG_POS_SYM {}
+ | RELAY_THREAD {}
| RELOAD {}
| REORGANIZE_SYM {}
| REPEATABLE_SYM {}
diff --git a/sql/structs.h b/sql/structs.h
index e369d8ed7e8..72237887514 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -86,6 +86,7 @@ typedef struct st_key {
uint key_parts; /* How many key_parts */
uint extra_length;
uint usable_key_parts; /* Should normally be = key_parts */
+ uint block_size;
enum ha_key_alg algorithm;
/*
Note that parser is used when the table is opened for use, and
diff --git a/sql/table.cc b/sql/table.cc
index 6ba66569f5c..bacb703a28c 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -535,6 +535,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
keyinfo->key_length= (uint) uint2korr(strpos+2);
keyinfo->key_parts= (uint) strpos[4];
keyinfo->algorithm= (enum ha_key_alg) strpos[5];
+ keyinfo->block_size= uint2korr(strpos+6);
strpos+=8;
}
else
@@ -706,6 +707,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
}
my_free(buff, MYF(0));
}
+ share->key_block_size= uint2korr(head+62);
error=4;
extra_rec_buf_length= uint2korr(head+59);
@@ -2065,6 +2067,11 @@ File create_frm(THD *thd, const char *name, const char *db,
tmp= MYSQL_VERSION_ID; // Store to avoid warning from int4store
int4store(fileinfo+51, tmp);
int4store(fileinfo+55, create_info->extra_size);
+ /*
+ 59-60 is reserved for extra_rec_buf_length,
+ 61 for default_part_db_type
+ */
+ int2store(fileinfo+62, create_info->key_block_size);
bzero(fill,IO_SIZE);
for (; length > IO_SIZE ; length-= IO_SIZE)
{
diff --git a/sql/table.h b/sql/table.h
index aec9a7115e6..5fd9cd28585 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -160,6 +160,7 @@ typedef struct st_table_share
uint ref_count; /* How many TABLE objects uses this */
uint open_count; /* Number of tables in open list */
uint blob_ptr_size; /* 4 or 8 */
+ uint key_block_size; /* create key_block_size, if used */
uint null_bytes, last_null_bit_pos;
uint fields; /* Number of fields */
uint rec_buff_length; /* Size of table->record[] buffer */
@@ -335,7 +336,8 @@ typedef struct st_foreign_key_info
LEX_STRING *forein_id;
LEX_STRING *referenced_db;
LEX_STRING *referenced_table;
- LEX_STRING *constraint_method;
+ LEX_STRING *update_method;
+ LEX_STRING *delete_method;
List foreign_fields;
List referenced_fields;
} FOREIGN_KEY_INFO;
@@ -359,6 +361,7 @@ enum enum_schema_tables
SCH_PARTITIONS,
SCH_PLUGINS,
SCH_PROCESSLIST,
+ SCH_REFERENTIAL_CONSTRAINTS,
SCH_PROCEDURES,
SCH_SCHEMATA,
SCH_SCHEMA_PRIVILEGES,
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 1be2321200b..228a8cd9b92 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1382,11 +1382,30 @@ static LS_INFO *tz_lsis= 0;
static bool time_zone_tables_exist= 1;
-typedef struct st_tz_names_entry: public Sql_alloc
+/*
+ Names of tables (with their lengths) that are needed
+ for dynamical loading of time zone descriptions.
+*/
+
+static const LEX_STRING tz_tables_names[MY_TZ_TABLES_COUNT]=
{
+ {(char *) STRING_WITH_LEN("time_zone_name")},
+ {(char *) STRING_WITH_LEN("time_zone")},
+ {(char *) STRING_WITH_LEN("time_zone_transition_type")},
+ {(char *) STRING_WITH_LEN("time_zone_transition")}
+};
+
+/* Name of database to which those tables belong. */
+
+static const LEX_STRING tz_tables_db_name= {(char *) STRING_WITH_LEN("mysql")};
+
+
+class Tz_names_entry: public Sql_alloc
+{
+public:
String name;
Time_zone *tz;
-} TZ_NAMES_ENTRY;
+};
/*
@@ -1394,7 +1413,7 @@ typedef struct st_tz_names_entry: public Sql_alloc
they should obey C calling conventions.
*/
-extern "C" byte* my_tz_names_get_key(TZ_NAMES_ENTRY *entry, uint *length,
+extern "C" byte* my_tz_names_get_key(Tz_names_entry *entry, uint *length,
my_bool not_used __attribute__((unused)))
{
*length= entry->name.length();
@@ -1415,7 +1434,8 @@ extern "C" byte* my_offset_tzs_get_key(Time_zone_offset *entry, uint *length,
SYNOPSIS
tz_init_table_list()
- tz_tabs - pointer to preallocated array of 4 TABLE_LIST objects
+ tz_tabs - pointer to preallocated array of MY_TZ_TABLES_COUNT
+ TABLE_LIST objects
global_next_ptr - pointer to variable which points to global_next member
of last element of global table list (or list root
then list is empty) (in/out).
@@ -1430,27 +1450,27 @@ extern "C" byte* my_offset_tzs_get_key(Time_zone_offset *entry, uint *length,
static void
tz_init_table_list(TABLE_LIST *tz_tabs, TABLE_LIST ***global_next_ptr)
{
- bzero(tz_tabs, sizeof(TABLE_LIST) * 4);
- tz_tabs[0].alias= tz_tabs[0].table_name= (char*)"time_zone_name";
- tz_tabs[1].alias= tz_tabs[1].table_name= (char*)"time_zone";
- tz_tabs[2].alias= tz_tabs[2].table_name= (char*)"time_zone_transition_type";
- tz_tabs[3].alias= tz_tabs[3].table_name= (char*)"time_zone_transition";
- tz_tabs[0].next_global= tz_tabs[0].next_local= tz_tabs+1;
- tz_tabs[1].next_global= tz_tabs[1].next_local= tz_tabs+2;
- tz_tabs[2].next_global= tz_tabs[2].next_local= tz_tabs+3;
- tz_tabs[0].lock_type= tz_tabs[1].lock_type= tz_tabs[2].lock_type=
- tz_tabs[3].lock_type= TL_READ;
- tz_tabs[0].db= tz_tabs[1].db= tz_tabs[2].db= tz_tabs[3].db= (char *)"mysql";
+ bzero(tz_tabs, sizeof(TABLE_LIST) * MY_TZ_TABLES_COUNT);
+
+ for (int i= 0; i < MY_TZ_TABLES_COUNT; i++)
+ {
+ tz_tabs[i].alias= tz_tabs[i].table_name= tz_tables_names[i].str;
+ tz_tabs[i].table_name_length= tz_tables_names[i].length;
+ tz_tabs[i].db= tz_tables_db_name.str;
+ tz_tabs[i].db_length= tz_tables_db_name.length;
+ tz_tabs[i].lock_type= TL_READ;
+
+ if (i != MY_TZ_TABLES_COUNT - 1)
+ tz_tabs[i].next_global= tz_tabs[i].next_local= &tz_tabs[i+1];
+ if (i != 0)
+ tz_tabs[i].prev_global= &tz_tabs[i-1].next_global;
+ }
/* Link into global list */
tz_tabs[0].prev_global= *global_next_ptr;
- tz_tabs[1].prev_global= &tz_tabs[0].next_global;
- tz_tabs[2].prev_global= &tz_tabs[1].next_global;
- tz_tabs[3].prev_global= &tz_tabs[2].next_global;
-
**global_next_ptr= tz_tabs;
/* Update last-global-pointer to point to pointer in last table */
- *global_next_ptr= &tz_tabs[3].next_global;
+ *global_next_ptr= &tz_tabs[MY_TZ_TABLES_COUNT-1].next_global;
}
@@ -1479,7 +1499,8 @@ TABLE_LIST fake_time_zone_tables_list;
NOTE
my_tz_check_n_skip_implicit_tables() function depends on fact that
- elements of list created are allocated as TABLE_LIST[4] array.
+ elements of list created are allocated as TABLE_LIST[MY_TZ_TABLES_COUNT]
+ array.
RETURN VALUES
Returns pointer to first TABLE_LIST object, (could be 0 if time zone
@@ -1495,7 +1516,8 @@ my_tz_get_table_list(THD *thd, TABLE_LIST ***global_next_ptr)
if (!time_zone_tables_exist)
DBUG_RETURN(0);
- if (!(tz_tabs= (TABLE_LIST *)thd->alloc(sizeof(TABLE_LIST) * 4)))
+ if (!(tz_tabs= (TABLE_LIST *)thd->alloc(sizeof(TABLE_LIST) *
+ MY_TZ_TABLES_COUNT)))
DBUG_RETURN(&fake_time_zone_tables_list);
tz_init_table_list(tz_tabs, global_next_ptr);
@@ -1534,9 +1556,9 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
{
THD *thd;
TABLE_LIST *tables= 0;
- TABLE_LIST tables_buff[5], **last_global_next_ptr;
+ TABLE_LIST tables_buff[1+MY_TZ_TABLES_COUNT], **last_global_next_ptr;
TABLE *table;
- TZ_NAMES_ENTRY *tmp_tzname;
+ Tz_names_entry *tmp_tzname;
my_bool return_val= 1;
int res;
DBUG_ENTER("my_tz_init");
@@ -1568,7 +1590,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
tz_inited= 1;
/* Add 'SYSTEM' time zone to tz_names hash */
- if (!(tmp_tzname= new (&tz_storage) TZ_NAMES_ENTRY()))
+ if (!(tmp_tzname= new (&tz_storage) Tz_names_entry()))
{
sql_print_error("Fatal error: OOM while initializing time zones");
goto end_with_cleanup;
@@ -1764,7 +1786,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
{
TABLE *table= 0;
TIME_ZONE_INFO *tz_info;
- TZ_NAMES_ENTRY *tmp_tzname;
+ Tz_names_entry *tmp_tzname;
Time_zone *return_val= 0;
int res;
uint tzid, ttid;
@@ -2039,7 +2061,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
}
- if (!(tmp_tzname= new (&tz_storage) TZ_NAMES_ENTRY()) ||
+ if (!(tmp_tzname= new (&tz_storage) Tz_names_entry()) ||
!(tmp_tzname->tz= new (&tz_storage) Time_zone_db(tz_info,
&(tmp_tzname->name))) ||
(tmp_tzname->name.set(tz_name_buff, tz_name->length(),
@@ -2186,7 +2208,7 @@ str_to_offset(const char *str, uint length, long *offset)
Time_zone *
my_tz_find(const String * name, TABLE_LIST *tz_tables)
{
- TZ_NAMES_ENTRY *tmp_tzname;
+ Tz_names_entry *tmp_tzname;
Time_zone *result_tz= 0;
long offset;
DBUG_ENTER("my_tz_find");
@@ -2221,7 +2243,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
else
{
result_tz= 0;
- if ((tmp_tzname= (TZ_NAMES_ENTRY *)hash_search(&tz_names,
+ if ((tmp_tzname= (Tz_names_entry *)hash_search(&tz_names,
(const byte *)name->ptr(),
name->length())))
result_tz= tmp_tzname->tz;
@@ -2273,7 +2295,7 @@ Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name)
our time zone tables. Note that if we don't have tz tables on this
slave, we don't even try.
*/
- TABLE_LIST tables[4];
+ TABLE_LIST tables[MY_TZ_TABLES_COUNT];
TABLE_LIST *dummy;
TABLE_LIST **dummyp= &dummy;
tz_init_table_list(tables, &dummyp);
diff --git a/sql/tztime.h b/sql/tztime.h
index 42e50988e52..95184c9b3d1 100644
--- a/sql/tztime.h
+++ b/sql/tztime.h
@@ -69,6 +69,15 @@ extern my_time_t sec_since_epoch_TIME(TIME *t);
extern TABLE_LIST fake_time_zone_tables_list;
+/*
+ Number of elements in table list produced by my_tz_get_table_list()
+ (this table list contains tables which are needed for dynamical loading
+ of time zone descriptions). Actually it is imlementation detail that
+ should not be used anywhere outside of tztime.h and tztime.cc.
+*/
+
+static const int MY_TZ_TABLES_COUNT= 4;
+
/*
Check if we have pointer to the begining of list of implicitly used time
zone tables, set SELECT_ACL for them and fast-forward to its end.
@@ -91,9 +100,9 @@ inline bool my_tz_check_n_skip_implicit_tables(TABLE_LIST **table,
{
if (*table == tz_tables)
{
- for (int i= 0; i < 4; i++)
+ for (int i= 0; i < MY_TZ_TABLES_COUNT; i++)
(*table)[i].grant.privilege= SELECT_ACL;
- (*table)+= 3;
+ (*table)+= MY_TZ_TABLES_COUNT - 1;
return TRUE;
}
return FALSE;
diff --git a/sql/unireg.cc b/sql/unireg.cc
index bbb4d970d37..eb38e6c0592 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -338,9 +338,9 @@ err_handler:
/* Pack screens to a screen for save in a form-file */
-static uchar * pack_screens(List &create_fields,
- uint *info_length, uint *screens,
- bool small_file)
+static uchar *pack_screens(List &create_fields,
+ uint *info_length, uint *screens,
+ bool small_file)
{
reg1 uint i;
uint row,start_row,end_row,fields_on_screen;
@@ -431,7 +431,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
int2store(pos+2,key->key_length);
pos[4]= (uchar) key->key_parts;
pos[5]= (uchar) key->algorithm;
- pos[6]=pos[7]=0; // For the future
+ int2store(pos+6, key->block_size);
pos+=8;
key_parts+=key->key_parts;
DBUG_PRINT("loop",("flags: %d key_parts: %d at 0x%lx",
diff --git a/storage/archive/Makefile.am b/storage/archive/Makefile.am
index 415e0dc8f8f..85577f406da 100644
--- a/storage/archive/Makefile.am
+++ b/storage/archive/Makefile.am
@@ -14,20 +14,49 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
- @ZLIB_INCLUDES@
+#called from the top level Makefile
-LDADD = libarchive.a \
- $(top_builddir)/mysys/libmysys.a \
+MYSQLDATAdir = $(localstatedir)
+MYSQLSHAREdir = $(pkgdatadir)
+MYSQLBASEdir= $(prefix)
+MYSQLLIBdir= $(pkglibdir)
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
+ -I$(top_srcdir)/regex \
+ -I$(top_srcdir)/sql \
+ -I$(srcdir) @ZLIB_INCLUDES@
+WRAPLIBS=
+
+LDADD =
+
+DEFS = @DEFS@
+
+noinst_HEADERS = ha_archive.h azlib.h
+noinst_PROGRAMS = archive_test
+
+EXTRA_LTLIBRARIES = ha_archive.la
+pkglib_LTLIBRARIES = @plugin_archive_shared_target@
+ha_archive_la_LDFLAGS = -module -rpath $(MYSQLLIBdir)
+ha_archive_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_archive_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_archive_la_SOURCES = ha_archive.cc azio.c
+
+
+EXTRA_LIBRARIES = libarchive.a
+noinst_LIBRARIES = @plugin_archive_static_target@
+libarchive_a_CXXFLAGS = $(AM_CFLAGS)
+libarchive_a_CFLAGS = $(AM_CFLAGS)
+libarchive_a_SOURCES = ha_archive.cc azio.c
+
+
+archive_test_SOURCES = archive_test.c azio.c
+archive_test_CFLAGS = $(AM_CFLAGS)
+archive_test_LDADD = $(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a \
@ZLIB_LIBS@
-pkglib_LIBRARIES = libarchive.a
-noinst_PROGRAMS = archive_test
archive_test_LDFLAGS = @NOINST_LDFLAGS@
-noinst_HEADERS = azlib.h
-libarchive_a_SOURCES = azio.c
-EXTRA_DIST = cmakelists.txt
+
+EXTRA_DIST = cmakelists.txt
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/archive/cmakelists.txt b/storage/archive/cmakelists.txt
index 4189781e73a..a631f194b1a 100644
--- a/storage/archive/cmakelists.txt
+++ b/storage/archive/cmakelists.txt
@@ -1,6 +1,8 @@
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}/zlib)
-ADD_LIBRARY(archive azio.c)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib
+ ${CMAKE_SOURCE_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+ADD_LIBRARY(archive azio.c ha_archive.cc ha_archive.h)
TARGET_LINK_LIBRARIES(archive zlib mysys dbug strings)
diff --git a/sql/ha_archive.cc b/storage/archive/ha_archive.cc
similarity index 97%
rename from sql/ha_archive.cc
rename to storage/archive/ha_archive.cc
index 072359f896c..e39ee976eb1 100644
--- a/sql/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -19,10 +19,13 @@
#endif
#include "mysql_priv.h"
+#include
#include "ha_archive.h"
#include
+#include
+
/*
First, if you want to understand storage engines you should look at
ha_example.cc and ha_example.h.
@@ -143,12 +146,15 @@ static handler *archive_create_handler(TABLE_SHARE *table);
#define ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT 2
+static const char archive_hton_name[]= "ARCHIVE";
+static const char archive_hton_comment[]= "Archive storage engine";
+
/* dummy handlerton - only to have something to return from archive_db_init */
handlerton archive_hton = {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "ARCHIVE",
+ archive_hton_name,
SHOW_OPTION_YES,
- "Archive storage engine",
+ archive_hton_comment,
DB_TYPE_ARCHIVE_DB,
archive_db_init,
0, /* slot */
@@ -214,6 +220,8 @@ static byte* archive_get_key(ARCHIVE_SHARE *share,uint *length,
bool archive_db_init()
{
DBUG_ENTER("archive_db_init");
+ if (archive_inited)
+ DBUG_RETURN(FALSE);
if (pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST))
goto error;
if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
@@ -227,7 +235,6 @@ bool archive_db_init()
DBUG_RETURN(FALSE);
}
error:
- have_archive_db= SHOW_OPTION_DISABLED; // If we couldn't use handler
DBUG_RETURN(TRUE);
}
@@ -235,14 +242,14 @@ error:
Release the archive handler.
SYNOPSIS
- archive_db_end()
+ archive_db_done()
void
RETURN
FALSE OK
*/
-int archive_db_end(ha_panic_function type)
+int archive_db_done()
{
if (archive_inited)
{
@@ -253,6 +260,12 @@ int archive_db_end(ha_panic_function type)
return 0;
}
+
+int archive_db_end(ha_panic_function type)
+{
+ return archive_db_done();
+}
+
ha_archive::ha_archive(TABLE_SHARE *table_arg)
:handler(&archive_hton, table_arg), delayed_insert(0), bulk_insert(0)
{
@@ -838,7 +851,7 @@ int ha_archive::write_row(byte *buf)
if (share->crashed)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
- statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
+ ha_statistic_increment(&SSV::ha_write_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
pthread_mutex_lock(&share->mutex);
@@ -1158,8 +1171,7 @@ int ha_archive::rnd_next(byte *buf)
DBUG_RETURN(HA_ERR_END_OF_FILE);
scan_rows--;
- statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_rnd_next_count);
current_position= aztell(&archive);
rc= get_row(&archive, buf);
@@ -1195,8 +1207,7 @@ void ha_archive::position(const byte *record)
int ha_archive::rnd_pos(byte * buf, byte *pos)
{
DBUG_ENTER("ha_archive::rnd_pos");
- statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_rnd_next_count);
current_position= (my_off_t)my_get_ptr(pos, ref_length);
(void)azseek(&archive, current_position, SEEK_SET);
@@ -1384,8 +1395,8 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
*/
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
- lock_type <= TL_WRITE) && !thd->in_lock_tables
- && !thd->tablespace_op)
+ lock_type <= TL_WRITE) && !thd_in_lock_tables(thd)
+ && !thd_tablespace_op(thd))
lock_type = TL_WRITE_ALLOW_WRITE;
/*
@@ -1396,7 +1407,7 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
concurrent inserts to t2.
*/
- if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables)
+ if (lock_type == TL_READ_NO_INSERT && !thd_in_lock_tables(thd))
lock_type = TL_READ;
lock.type=lock_type;
@@ -1509,11 +1520,11 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
{
int rc= 0;
byte *buf;
- const char *old_proc_info=thd->proc_info;
+ const char *old_proc_info;
ha_rows count= share->rows_recorded;
DBUG_ENTER("ha_archive::check");
- thd->proc_info= "Checking table";
+ old_proc_info= thd_proc_info(thd, "Checking table");
/* Flush any waiting data */
azflush(&(share->archive_write), Z_SYNC_FLUSH);
share->forced_flushes++;
@@ -1538,7 +1549,7 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
my_free((char*)buf, MYF(0));
- thd->proc_info= old_proc_info;
+ thd_proc_info(thd, old_proc_info);
if ((rc && rc != HA_ERR_END_OF_FILE) || count)
{
@@ -1563,3 +1574,17 @@ bool ha_archive::check_and_repair(THD *thd)
DBUG_RETURN(repair(thd, &check_opt));
}
+
+
+mysql_declare_plugin(archive)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &archive_hton,
+ archive_hton_name,
+ "Brian Aker, MySQL AB",
+ archive_hton_comment,
+ NULL, /* Plugin Init */
+ archive_db_done, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+}
+mysql_declare_plugin_end;
diff --git a/sql/ha_archive.h b/storage/archive/ha_archive.h
similarity index 99%
rename from sql/ha_archive.h
rename to storage/archive/ha_archive.h
index 9f847a8825e..4663531b674 100644
--- a/sql/ha_archive.h
+++ b/storage/archive/ha_archive.h
@@ -19,7 +19,7 @@
#endif
#include
-#include "../storage/archive/azlib.h"
+#include "azlib.h"
/*
Please read ha_archive.cc first. If you are looking for more general
diff --git a/storage/blackhole/Makefile.am b/storage/blackhole/Makefile.am
new file mode 100644
index 00000000000..902d57c1668
--- /dev/null
+++ b/storage/blackhole/Makefile.am
@@ -0,0 +1,52 @@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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)
+MYSQLLIBdir= $(pkglibdir)
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
+ -I$(top_srcdir)/regex \
+ -I$(top_srcdir)/sql \
+ -I$(srcdir)
+WRAPLIBS=
+
+LDADD =
+
+DEFS = @DEFS@
+
+noinst_HEADERS = ha_blackhole.h
+
+EXTRA_LTLIBRARIES = ha_blackhole.la
+pkglib_LTLIBRARIES = @plugin_blackhole_shared_target@
+ha_blackhole_la_LDFLAGS=-module -rpath $(MYSQLLIBdir)
+ha_blackhole_la_CXXFLAGS=$(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_blackhole_la_CFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_blackhole_la_SOURCES=ha_blackhole.cc
+
+
+EXTRA_LIBRARIES = libblackhole.a
+noinst_LIBRARIES = @plugin_blackhole_static_target@
+libblackhole_a_CXXFLAGS=$(AM_CFLAGS)
+libblackhole_a_CFLAGS = $(AM_CFLAGS)
+libblackhole_a_SOURCES= ha_blackhole.cc
+
+
+EXTRA_DIST = cmakelists.txt
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/storage/blackhole/cmakelists.txt b/storage/blackhole/cmakelists.txt
new file mode 100644
index 00000000000..ea3a7eae38e
--- /dev/null
+++ b/storage/blackhole/cmakelists.txt
@@ -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(blackhole ha_blackhole.cc ha_blackhole.h)
diff --git a/sql/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
similarity index 93%
rename from sql/ha_blackhole.cc
rename to storage/blackhole/ha_blackhole.cc
index 2f5e8ee0abc..e9fd1c2319d 100644
--- a/sql/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -22,18 +22,24 @@
#include "mysql_priv.h"
#include "ha_blackhole.h"
+#include
+
/* Static declarations for handlerton */
static handler *blackhole_create_handler(TABLE_SHARE *table);
+static const char blackhole_hton_name[]= "BLACKHOLE";
+static const char blackhole_hton_comment[]=
+ "/dev/null storage engine (anything you write to it disappears)";
+
/* Blackhole storage engine handlerton */
handlerton blackhole_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "BLACKHOLE",
+ blackhole_hton_name,
SHOW_OPTION_YES,
- "/dev/null storage engine (anything you write to it disappears)",
+ blackhole_hton_comment,
DB_TYPE_BLACKHOLE_DB,
NULL,
0, /* slot */
@@ -250,3 +256,15 @@ int ha_blackhole::index_last(byte * buf)
DBUG_RETURN(HA_ERR_END_OF_FILE);
}
+mysql_declare_plugin(blackhole)
+{
+ MYSQL_STORAGE_ENGINE_PLUGIN,
+ &blackhole_hton,
+ blackhole_hton_name,
+ "MySQL AB",
+ blackhole_hton_comment,
+ NULL, /* Plugin Init */
+ NULL, /* Plugin Deinit */
+ 0x0100 /* 1.0 */,
+}
+mysql_declare_plugin_end;
diff --git a/sql/ha_blackhole.h b/storage/blackhole/ha_blackhole.h
similarity index 100%
rename from sql/ha_blackhole.h
rename to storage/blackhole/ha_blackhole.h
diff --git a/storage/csv/Makefile.am b/storage/csv/Makefile.am
index 5573df720a3..a2afeba137f 100644
--- a/storage/csv/Makefile.am
+++ b/storage/csv/Makefile.am
@@ -25,16 +25,22 @@ INCLUDES = -I$(top_builddir)/include \
-I$(top_srcdir)/regex \
-I$(top_srcdir)/sql \
-I$(srcdir)
-
-pkglib_LIBRARIES = libcsv.a
-
LDADD =
DEFS = @DEFS@
+noinst_HEADERS = ha_tina.h
+EXTRA_LTLIBRARIES = ha_csv.la
+pkglib_LTLIBRARIES = @plugin_csv_shared_target@
+ha_csv_la_LDFLAGS = -module -rpath $(MYSQLLIBdir)
+ha_csv_la_CXXFLAGS = $(AM_CFLAGS) -DMYSQL_PLUGIN
+ha_csv_la_SOURCES = ha_tina.cc
+
+EXTRA_LIBRARIES = libcsv.a
+noinst_LIBRARIES = @plugin_csv_static_target@
libcsv_a_CXXFLAGS = $(AM_CFLAGS)
-noinst_HEADERS = ha_tina.h
libcsv_a_SOURCES = ha_tina.cc
+EXTRA_DIST = cmakelists.txt
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/csv/cmakelists.txt b/storage/csv/cmakelists.txt
index 4e142646b2d..28748527cc3 100644
--- a/storage/csv/cmakelists.txt
+++ b/storage/csv/cmakelists.txt
@@ -1,5 +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)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include)
ADD_LIBRARY(csv ha_tina.cc ha_tina.h)
diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc
index aed861279d9..de69df90ed5 100644
--- a/storage/csv/ha_tina.cc
+++ b/storage/csv/ha_tina.cc
@@ -77,11 +77,14 @@ static int tina_init= 0;
static handler *tina_create_handler(TABLE_SHARE *table);
static int tina_init_func();
+static const char tina_hton_name[]= "CSV";
+static const char tina_hton_comment[]= "CSV storage engine";
+
handlerton tina_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "CSV",
+ tina_hton_name,
SHOW_OPTION_YES,
- "CSV storage engine",
+ tina_hton_comment,
DB_TYPE_CSV_DB,
(bool (*)()) tina_init_func,
0, /* slot */
@@ -1398,17 +1401,17 @@ bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info,
return COMPATIBLE_DATA_YES;
}
-#ifdef MYSQL_PLUGIN
-mysql_declare_plugin
+
+mysql_declare_plugin(csv)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&tina_hton,
- tina_hton.name,
+ tina_hton_name,
"Brian Aker, MySQL AB",
- "CSV Storage Engine",
+ tina_hton_comment,
tina_init_func, /* Plugin Init */
tina_done_func, /* Plugin Deinit */
0x0100 /* 1.0 */,
}
mysql_declare_plugin_end;
-#endif
+
diff --git a/storage/example/Makefile.am b/storage/example/Makefile.am
index 518d82abe2d..9c4bedb2160 100644
--- a/storage/example/Makefile.am
+++ b/storage/example/Makefile.am
@@ -1,15 +1,15 @@
# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
# (at your option) any later version.
-#
+#
# 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
@@ -20,20 +20,33 @@ MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
MYSQLLIBdir= $(pkglibdir)
-INCLUDES = -I$(top_srcdir)/include \
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
-I$(top_srcdir)/regex \
-I$(top_srcdir)/sql \
-I$(srcdir)
WRAPLIBS=
-pkglib_LIBRARIES = libexample.a
-
-noinst_HEADERS = ha_example.h
-libexample_a_SOURCES = ha_example.cc
-EXTRA_DIST = cmakelists.txt
LDADD =
-DEFS = -DMYSQL_SERVER @DEFS@
+DEFS = @DEFS@
+noinst_HEADERS = ha_example.h
+
+EXTRA_LTLIBRARIES = ha_example.la
+pkglib_LTLIBRARIES = @plugin_example_shared_target@
+ha_example_la_LDFLAGS = -module -rpath $(MYSQLLIBdir)
+ha_example_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_example_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
+ha_example_la_SOURCES = ha_example.cc
+
+
+EXTRA_LIBRARIES = libexample.a
+noinst_LIBRARIES = @plugin_example_static_target@
+libexample_a_CXXFLAGS = $(AM_CFLAGS)
+libexample_a_CFLAGS = $(AM_CFLAGS)
+libexample_a_SOURCES= ha_example.cc
+
+
+EXTRA_DIST = cmakelists.txt
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc
index caa64c10bbd..2ce543dfbb0 100644
--- a/storage/example/ha_example.cc
+++ b/storage/example/ha_example.cc
@@ -77,11 +77,14 @@ static int example_init_func();
static bool example_init_func_for_handlerton();
static int example_panic(enum ha_panic_function flag);
+static const char example_hton_name[]= "EXAMPLE";
+static const char example_hton_comment[]= "Example storage engine";
+
handlerton example_hton= {
MYSQL_HANDLERTON_INTERFACE_VERSION,
- "EXAMPLE",
+ example_hton_name,
SHOW_OPTION_YES,
- "Example storage engine",
+ example_hton_comment,
DB_TYPE_EXAMPLE_DB,
example_init_func_for_handlerton,
0, /* slot */
@@ -742,17 +745,17 @@ int ha_example::create(const char *name, TABLE *table_arg,
DBUG_RETURN(0);
}
-#ifdef MYSQL_PLUGIN
-mysql_declare_plugin
+
+mysql_declare_plugin(example)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&example_hton,
- example_hton.name,
+ example_hton_name,
"Brian Aker, MySQL AB",
- "Example Storage Engine",
+ example_hton_comment,
example_init_func, /* Plugin Init */
example_done_func, /* Plugin Deinit */
0x0001 /* 0.1 */,
}
mysql_declare_plugin_end;
-#endif
+
diff --git a/storage/heap/hp_delete.c b/storage/heap/hp_delete.c
index 2d94418a1bf..f37db2588f3 100644
--- a/storage/heap/hp_delete.c
+++ b/storage/heap/hp_delete.c
@@ -79,7 +79,8 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
custom_arg.search_flag= SEARCH_SAME;
old_allocated= keyinfo->rb_tree.allocated;
- res= tree_delete(&keyinfo->rb_tree, info->recbuf, &custom_arg);
+ res= tree_delete(&keyinfo->rb_tree, info->recbuf, custom_arg.key_length,
+ &custom_arg);
info->s->index_length-= (old_allocated - keyinfo->rb_tree.allocated);
return res;
}
diff --git a/storage/innobase/Makefile.am b/storage/innobase/Makefile.am
index 0cceac97688..908f5d669a2 100644
--- a/storage/innobase/Makefile.am
+++ b/storage/innobase/Makefile.am
@@ -79,5 +79,33 @@ EXTRA_DIST = include/btr0btr.h include/btr0btr.ic include/btr0cur.h include/btr
include/ut0sort.h include/ut0ut.h include/ut0ut.ic include/ut0vec.h include/ut0vec.ic \
cmakelists.txt
+noinst_LIBRARIES = libinnobase.a
+libinnobase_a_LIBADD = usr/libusr.a srv/libsrv.a dict/libdict.a \
+ que/libque.a srv/libsrv.a ibuf/libibuf.a \
+ row/librow.a pars/libpars.a btr/libbtr.a \
+ trx/libtrx.a read/libread.a usr/libusr.a \
+ buf/libbuf.a ibuf/libibuf.a eval/libeval.a \
+ log/liblog.a fsp/libfsp.a fut/libfut.a \
+ fil/libfil.a lock/liblock.a mtr/libmtr.a \
+ page/libpage.a rem/librem.a thr/libthr.a \
+ sync/libsync.a data/libdata.a mach/libmach.a \
+ ha/libha.a dyn/libdyn.a mem/libmem.a \
+ ut/libut.a os/libos.a ut/libut.a
+libinnobase_a_SOURCES =
+
+
+libinnobase.a: $(libinnobase_a_LIBADD)
+ -rm -f $@
+ if test "$(host_os)" = "netware" ; \
+ then \
+ $(libinnobase_a_AR) $@ $(libinnobase_a_LIBADD) ; \
+ else \
+ for arc in $(libinnobase_a_LIBADD); do \
+ arpath=`echo $$arc|sed 's|[^/]*$$||'`; \
+ $(AR) t $$arc|sed "s|^|$$arpath|"; \
+ done | sort -u | xargs $(AR) cq $@ ; \
+ $(RANLIB) $@ ; \
+ fi
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/storage/myisam/ft_eval.c b/storage/myisam/ft_eval.c
index eab9d37af0b..459742d2aff 100644
--- a/storage/myisam/ft_eval.c
+++ b/storage/myisam/ft_eval.c
@@ -54,6 +54,7 @@ int main(int argc, char *argv[])
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
keyinfo[0].keysegs=1;
+ keyinfo[0].block_length= 0; /* Default block length */
keyinfo[0].seg[0].type= HA_KEYTYPE_TEXT;
keyinfo[0].seg[0].flag= HA_BLOB_PART;
keyinfo[0].seg[0].start=recinfo[0].length;
diff --git a/storage/myisam/ft_test1.c b/storage/myisam/ft_test1.c
index d54b344e2cd..28dcfb2b758 100644
--- a/storage/myisam/ft_test1.c
+++ b/storage/myisam/ft_test1.c
@@ -89,6 +89,7 @@ static int run_test(const char *filename)
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
keyinfo[0].keysegs=1;
+ keyinfo[0].block_length= 0; /* Default block length */
keyinfo[0].seg[0].type= key_type;
keyinfo[0].seg[0].flag= (key_field == FIELD_BLOB) ? HA_BLOB_PART:
(key_field == FIELD_VARCHAR) ? HA_VAR_LENGTH_PART:0;
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index eb2f42697ce..0fa095a21db 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -358,7 +358,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
puts("- check key delete-chain");
param->key_file_blocks=info->s->base.keystart;
- for (key=0 ; key < info->s->state.header.max_block_size ; key++)
+ for (key=0 ; key < info->s->state.header.max_block_size_index ; key++)
if (check_k_link(param,info,key))
{
if (param->testflag & T_VERBOSE) puts("");
@@ -1411,7 +1411,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
share->state.key_root[i]= HA_OFFSET_ERROR;
/* Drop the delete chain. */
- for (i=0 ; i < share->state.header.max_block_size ; i++)
+ for (i=0 ; i < share->state.header.max_block_size_index ; i++)
share->state.key_del[i]= HA_OFFSET_ERROR;
/*
@@ -1795,7 +1795,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
for (key=0 ; key < info->s->base.keys ; key++)
info->s->state.key_root[key]=index_pos[key];
- for (key=0 ; key < info->s->state.header.max_block_size ; key++)
+ for (key=0 ; key < info->s->state.header.max_block_size_index ; key++)
info->s->state.key_del[key]= HA_OFFSET_ERROR;
info->s->state.changed&= ~STATE_NOT_SORTED_PAGES;
@@ -2095,7 +2095,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
- for (i=0 ; i < share->state.header.max_block_size ; i++)
+ for (i=0 ; i < share->state.header.max_block_size_index ; i++)
share->state.key_del[i]= HA_OFFSET_ERROR;
info->state->key_file_length=share->base.keystart;
}
@@ -2463,7 +2463,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
- for (i=0 ; i < share->state.header.max_block_size ; i++)
+ for (i=0 ; i < share->state.header.max_block_size_index ; i++)
share->state.key_del[i]= HA_OFFSET_ERROR;
info->state->key_file_length=share->base.keystart;
}
@@ -3800,6 +3800,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
ha_rows max_records;
ulonglong file_length,tmp_length;
MI_CREATE_INFO create_info;
+ DBUG_ENTER("recreate_table");
error=1; /* Default error */
info= **org_info;
@@ -3809,7 +3810,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
(param->testflag & T_UNPACK);
if (!(keyinfo=(MI_KEYDEF*) my_alloca(sizeof(MI_KEYDEF)*share.base.keys)))
- return 0;
+ DBUG_RETURN(0);
memcpy((byte*) keyinfo,(byte*) share.keyinfo,
(size_t) (sizeof(MI_KEYDEF)*share.base.keys));
@@ -3818,14 +3819,14 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
(key_parts+share.base.keys))))
{
my_afree((gptr) keyinfo);
- return 1;
+ DBUG_RETURN(1);
}
if (!(recdef=(MI_COLUMNDEF*)
my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
{
my_afree((gptr) keyinfo);
my_afree((gptr) keysegs);
- return 1;
+ DBUG_RETURN(1);
}
if (!(uniquedef=(MI_UNIQUEDEF*)
my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
@@ -3833,7 +3834,7 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
my_afree((gptr) recdef);
my_afree((gptr) keyinfo);
my_afree((gptr) keysegs);
- return 1;
+ DBUG_RETURN(1);
}
/* Copy the column definitions */
@@ -3903,6 +3904,11 @@ int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename)
create_info.language = (param->language ? param->language :
share.state.header.language);
create_info.key_file_length= status_info.key_file_length;
+ /*
+ Allow for creating an auto_increment key. This has an effect only if
+ an auto_increment key exists in the original table.
+ */
+ create_info.with_auto_increment= TRUE;
/* We don't have to handle symlinks here because we are using
HA_DONT_TOUCH_DATA */
if (mi_create(filename,
@@ -3947,7 +3953,7 @@ end:
my_afree((gptr) keyinfo);
my_afree((gptr) recdef);
my_afree((gptr) keysegs);
- return error;
+ DBUG_RETURN(error);
}
@@ -4050,6 +4056,8 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
my_bool repair_only)
{
byte *record;
+ DBUG_ENTER("update_auto_increment_key");
+
if (!info->s->base.auto_key ||
! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1))
{
@@ -4057,7 +4065,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
mi_check_print_info(param,
"Table: %s doesn't have an auto increment key\n",
param->isam_file_name);
- return;
+ DBUG_VOID_RETURN;
}
if (!(param->testflag & T_SILENT) &&
!(param->testflag & T_REP))
@@ -4070,7 +4078,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
MYF(0))))
{
mi_check_print_error(param,"Not enough memory for extra record");
- return;
+ DBUG_VOID_RETURN;
}
mi_extra(info,HA_EXTRA_KEYREAD,0);
@@ -4081,7 +4089,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
my_free((char*) record, MYF(0));
mi_check_print_error(param,"%d when reading last record",my_errno);
- return;
+ DBUG_VOID_RETURN;
}
if (!repair_only)
info->s->state.auto_increment=param->auto_increment_value;
@@ -4097,7 +4105,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
my_free((char*) record, MYF(0));
update_state_info(param, info, UPDATE_AUTO_INC);
- return;
+ DBUG_VOID_RETURN;
}
diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c
index 3be998b2c17..22cbde278be 100644
--- a/storage/myisam/mi_create.c
+++ b/storage/myisam/mi_create.c
@@ -28,9 +28,9 @@
#endif
#include
- /*
- ** Old options is used when recreating database, from isamchk
- */
+/*
+ Old options is used when recreating database, from myisamchk
+*/
int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
uint columns, MI_COLUMNDEF *recinfo,
@@ -45,6 +45,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_length,info_length,key_segs,options,min_key_length_skip,
base_pos,long_varchar_count,varchar_length,
max_key_block_length,unique_key_parts,fulltext_keys,offset;
+ uint aligned_key_start, block_length;
ulong reclength, real_reclength,min_pack_length;
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
ulong pack_reclength;
@@ -428,8 +429,16 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_segs)
share.state.rec_per_key_part[key_segs-1]=1L;
length+=key_length;
+ /* Get block length for key, if defined by user */
+ block_length= (keydef->block_length ?
+ my_round_up_to_next_power(keydef->block_length) :
+ myisam_block_size);
+ block_length= max(block_length, MI_MIN_KEY_BLOCK_LENGTH);
+ block_length= min(block_length, MI_MAX_KEY_BLOCK_LENGTH);
+
keydef->block_length= MI_BLOCK_SIZE(length-real_length_diff,
- pointer,MI_MAX_KEYPTR_SIZE);
+ pointer,MI_MAX_KEYPTR_SIZE,
+ block_length);
if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
length >= MI_MAX_KEY_BUFF)
{
@@ -485,7 +494,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
mi_int2store(share.state.header.base_pos,base_pos);
share.state.header.language= (ci->language ?
ci->language : default_charset_info->number);
- share.state.header.max_block_size=max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
+ share.state.header.max_block_size_index= max_key_block_length/MI_MIN_KEY_BLOCK_LENGTH;
share.state.dellink = HA_OFFSET_ERROR;
share.state.process= (ulong) getpid();
@@ -512,8 +521,12 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
mi_int2store(share.state.header.unique_key_parts,unique_key_parts);
mi_set_all_keys_active(share.state.key_map, keys);
- share.base.keystart = share.state.state.key_file_length=
- MY_ALIGN(info_length, myisam_block_size);
+ aligned_key_start= my_round_up_to_next_power(max_key_block_length ?
+ max_key_block_length :
+ myisam_block_size);
+
+ share.base.keystart= share.state.state.key_file_length=
+ MY_ALIGN(info_length, aligned_key_start);
share.base.max_key_block_length=max_key_block_length;
share.base.max_key_length=ALIGN_SIZE(max_key_length+4);
share.base.records=ci->max_rows;
diff --git a/storage/myisam/mi_key.c b/storage/myisam/mi_key.c
index f8463a0b6b0..526a733e724 100644
--- a/storage/myisam/mi_key.c
+++ b/storage/myisam/mi_key.c
@@ -127,7 +127,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
}
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
- uint pack_length= keyseg->bit_start;
+ uint pack_length= (keyseg->bit_start == 1 ? 1 : 2);
uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
uint2korr(pos));
pos+= pack_length; /* Skip VARCHAR length */
diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c
index 91bf438035f..b61c1af24da 100644
--- a/storage/myisam/mi_open.c
+++ b/storage/myisam/mi_open.c
@@ -295,7 +295,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
&share->data_file_name,strlen(data_name)+1,
&share->state.key_root,keys*sizeof(my_off_t),
&share->state.key_del,
- (share->state.header.max_block_size*sizeof(my_off_t)),
+ (share->state.header.max_block_size_index*sizeof(my_off_t)),
#ifdef THREAD
&share->key_root_lock,sizeof(rw_lock_t)*keys,
#endif
@@ -310,7 +310,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
(char*) key_root, sizeof(my_off_t)*keys);
memcpy((char*) share->state.key_del,
(char*) key_del, (sizeof(my_off_t) *
- share->state.header.max_block_size));
+ share->state.header.max_block_size_index));
strmov(share->unique_file_name, name_buff);
share->unique_name_length= strlen(name_buff);
strmov(share->index_file_name, index_name);
@@ -820,7 +820,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
uchar *ptr=buff;
uint i, keys= (uint) state->header.keys,
- key_blocks=state->header.max_block_size;
+ key_blocks=state->header.max_block_size_index;
DBUG_ENTER("mi_state_info_write");
memcpy_fixed(ptr,&state->header,sizeof(state->header));
@@ -886,7 +886,7 @@ uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state)
ptr +=sizeof(state->header);
keys=(uint) state->header.keys;
key_parts=mi_uint2korr(state->header.key_parts);
- key_blocks=state->header.max_block_size;
+ key_blocks=state->header.max_block_size_index;
state->open_count = mi_uint2korr(ptr); ptr +=2;
state->changed= (bool) *ptr++;
@@ -1059,7 +1059,7 @@ char *mi_keydef_read(char *ptr, MI_KEYDEF *keydef)
keydef->keylength = mi_uint2korr(ptr); ptr +=2;
keydef->minlength = mi_uint2korr(ptr); ptr +=2;
keydef->maxlength = mi_uint2korr(ptr); ptr +=2;
- keydef->block_size = keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
+ keydef->block_size_index= keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
keydef->underflow_block_length=keydef->block_length/3;
keydef->version = 0; /* Not saved */
keydef->parser = &ft_default_parser;
diff --git a/storage/myisam/mi_page.c b/storage/myisam/mi_page.c
index 5240c063fba..a5e2b01ed0f 100644
--- a/storage/myisam/mi_page.c
+++ b/storage/myisam/mi_page.c
@@ -112,8 +112,8 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos,
DBUG_ENTER("_mi_dispose");
DBUG_PRINT("enter",("pos: %ld", (long) pos));
- old_link=info->s->state.key_del[keyinfo->block_size];
- info->s->state.key_del[keyinfo->block_size]=pos;
+ old_link= info->s->state.key_del[keyinfo->block_size_index];
+ info->s->state.key_del[keyinfo->block_size_index]= pos;
mi_sizestore(buff,old_link);
info->s->state.changed|= STATE_NOT_SORTED_PAGES;
DBUG_RETURN(key_cache_write(info->s->key_cache,
@@ -132,7 +132,8 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo, int level)
char buff[8];
DBUG_ENTER("_mi_new");
- if ((pos=info->s->state.key_del[keyinfo->block_size]) == HA_OFFSET_ERROR)
+ if ((pos= info->s->state.key_del[keyinfo->block_size_index]) ==
+ HA_OFFSET_ERROR)
{
if (info->state->key_file_length >=
info->s->base.max_key_file_length - keyinfo->block_length)
@@ -152,7 +153,7 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo, int level)
(uint) keyinfo->block_length,0))
pos= HA_OFFSET_ERROR;
else
- info->s->state.key_del[keyinfo->block_size]=mi_sizekorr(buff);
+ info->s->state.key_del[keyinfo->block_size_index]= mi_sizekorr(buff);
}
info->s->state.changed|= STATE_NOT_SORTED_PAGES;
DBUG_PRINT("exit",("Pos: %ld",(long) pos));
diff --git a/storage/myisam/mi_test1.c b/storage/myisam/mi_test1.c
index 0e62b074376..0b78ac8a7ff 100644
--- a/storage/myisam/mi_test1.c
+++ b/storage/myisam/mi_test1.c
@@ -95,6 +95,7 @@ static int run_test(const char *filename)
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
keyinfo[0].keysegs=1;
+ keyinfo[0].block_length= 0; /* Default block length */
keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
keyinfo[0].seg[0].type= key_type;
keyinfo[0].seg[0].flag= pack_seg;
diff --git a/storage/myisam/mi_test2.c b/storage/myisam/mi_test2.c
index e77a37d853f..357ebb1b9bc 100644
--- a/storage/myisam/mi_test2.c
+++ b/storage/myisam/mi_test2.c
@@ -95,6 +95,7 @@ int main(int argc, char *argv[])
keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
keyinfo[0].keysegs=1;
keyinfo[0].flag = pack_type;
+ keyinfo[0].block_length= 0; /* Default block length */
keyinfo[1].seg= &glob_keyseg[1][0];
keyinfo[1].seg[0].start=7;
keyinfo[1].seg[0].length=6;
@@ -111,6 +112,7 @@ int main(int argc, char *argv[])
keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
keyinfo[1].keysegs=2;
keyinfo[1].flag =0;
+ keyinfo[1].block_length= MI_MIN_KEY_BLOCK_LENGTH; /* Diff blocklength */
keyinfo[2].seg= &glob_keyseg[2][0];
keyinfo[2].seg[0].start=12;
keyinfo[2].seg[0].length=8;
@@ -121,6 +123,7 @@ int main(int argc, char *argv[])
keyinfo[2].key_alg=HA_KEY_ALG_BTREE;
keyinfo[2].keysegs=1;
keyinfo[2].flag =HA_NOSAME;
+ keyinfo[2].block_length= 0; /* Default block length */
keyinfo[3].seg= &glob_keyseg[3][0];
keyinfo[3].seg[0].start=0;
keyinfo[3].seg[0].length=reclength-(use_blob ? 8 : 0);
@@ -132,6 +135,7 @@ int main(int argc, char *argv[])
keyinfo[3].key_alg=HA_KEY_ALG_BTREE;
keyinfo[3].keysegs=1;
keyinfo[3].flag = pack_type;
+ keyinfo[3].block_length= 0; /* Default block length */
keyinfo[4].seg= &glob_keyseg[4][0];
keyinfo[4].seg[0].start=0;
keyinfo[4].seg[0].length=5;
@@ -143,6 +147,7 @@ int main(int argc, char *argv[])
keyinfo[4].key_alg=HA_KEY_ALG_BTREE;
keyinfo[4].keysegs=1;
keyinfo[4].flag = pack_type;
+ keyinfo[4].block_length= 0; /* Default block length */
keyinfo[5].seg= &glob_keyseg[5][0];
keyinfo[5].seg[0].start=0;
keyinfo[5].seg[0].length=4;
@@ -154,6 +159,7 @@ int main(int argc, char *argv[])
keyinfo[5].key_alg=HA_KEY_ALG_BTREE;
keyinfo[5].keysegs=1;
keyinfo[5].flag = pack_type;
+ keyinfo[5].block_length= 0; /* Default block length */
recinfo[0].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
recinfo[0].length=7;
@@ -813,7 +819,7 @@ end:
printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
if (rec_pointer_size)
printf("Record pointer size: %d\n",rec_pointer_size);
- printf("myisam_block_size: %u\n", myisam_block_size);
+ printf("myisam_block_size: %lu\n", myisam_block_size);
if (key_cacheing)
{
puts("Key cache used");
@@ -914,13 +920,13 @@ static void get_options(int argc, char **argv)
}
break;
case 'e': /* myisam_block_length */
- if ((myisam_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
+ if ((myisam_block_size= atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
myisam_block_size > MI_MAX_KEY_BLOCK_LENGTH)
{
fprintf(stderr,"Wrong myisam_block_length\n");
exit(1);
}
- myisam_block_size=1 << my_bit_log2(myisam_block_size);
+ myisam_block_size= my_round_up_to_next_power(myisam_block_size);
break;
case 'E': /* myisam_block_length */
if ((key_cache_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
@@ -929,7 +935,7 @@ static void get_options(int argc, char **argv)
fprintf(stderr,"Wrong key_cache_block_size\n");
exit(1);
}
- key_cache_block_size=1 << my_bit_log2(key_cache_block_size);
+ key_cache_block_size= my_round_up_to_next_power(key_cache_block_size);
break;
case 'f':
if ((first_key=atoi(++pos)) < 0 || first_key >= MYISAM_KEYS)
diff --git a/storage/myisam/mi_test3.c b/storage/myisam/mi_test3.c
index 4e764c6f971..173fbe64cf5 100644
--- a/storage/myisam/mi_test3.c
+++ b/storage/myisam/mi_test3.c
@@ -76,6 +76,7 @@ int main(int argc,char **argv)
keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
keyinfo[0].keysegs=1;
keyinfo[0].flag = (uint8) HA_PACK_KEY;
+ keyinfo[0].block_length= 0; /* Default block length */
keyinfo[1].seg= &keyseg[1][0];
keyinfo[1].seg[0].start=8;
keyinfo[1].seg[0].length=4; /* Long is always 4 in myisam */
@@ -84,6 +85,7 @@ int main(int argc,char **argv)
keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
keyinfo[1].keysegs=1;
keyinfo[1].flag =HA_NOSAME;
+ keyinfo[1].block_length= 0; /* Default block length */
recinfo[0].type=0;
recinfo[0].length=sizeof(record.id);
diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h
index caf6254c321..0b450de9c03 100644
--- a/storage/myisam/myisamdef.h
+++ b/storage/myisam/myisamdef.h
@@ -55,7 +55,7 @@ typedef struct st_mi_state_info
uchar keys; /* number of keys in file */
uchar uniques; /* number of UNIQUE definitions */
uchar language; /* Language for indexes */
- uchar max_block_size; /* max keyblock size */
+ uchar max_block_size_index; /* max keyblock size */
uchar fulltext_keys;
uchar not_used; /* To align to 8 */
} header;
@@ -431,7 +431,7 @@ typedef struct st_mi_sort_param
#define MI_FOUND_WRONG_KEY 32738 /* Impossible value from ha_key_cmp */
#define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_MIN_KEY_BLOCK_LENGTH)
-#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer) (((((key_length)+(data_pointer)+(key_pointer))*4+(key_pointer)+2)/myisam_block_size+1)*myisam_block_size)
+#define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer,block_size) (((((key_length)+(data_pointer)+(key_pointer))*4+(key_pointer)+2)/(block_size)+1)*(block_size))
#define MI_MAX_KEYPTR_SIZE 5 /* For calculating block lengths */
#define MI_MIN_KEYBLOCK_LENGTH 50 /* When to split delete blocks */
@@ -742,6 +742,8 @@ my_bool check_table_is_closed(const char *name, const char *where);
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup);
int mi_open_keyfile(MYISAM_SHARE *share);
void mi_setup_functions(register MYISAM_SHARE *share);
+my_bool mi_dynmap_file(MI_INFO *info, my_off_t size);
+void mi_remap_file(MI_INFO *info, my_off_t size);
/* Functions needed by mi_check */
volatile int *killed_ptr(MI_CHECK *param);
diff --git a/storage/myisam/myisamlog.c b/storage/myisam/myisamlog.c
index de55b86252c..17af4ab34a2 100644
--- a/storage/myisam/myisamlog.c
+++ b/storage/myisam/myisamlog.c
@@ -475,7 +475,7 @@ static int examine_log(my_string file_name, char **table_names)
{
if (!curr_file_info->closed)
files_open--;
- VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
+ VOID(tree_delete(&tree, (gptr) curr_file_info, 0, tree.custom_arg));
}
break;
case MI_LOG_EXTRA:
diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c
index e80a3ffacd9..5b3067cb115 100644
--- a/storage/myisam/myisampack.c
+++ b/storage/myisam/myisampack.c
@@ -2726,6 +2726,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
break;
}
case FIELD_LAST:
+ case FIELD_enum_val_count:
abort(); /* Impossible */
}
start_pos+=count->max_zero_fill;
@@ -2965,7 +2966,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length,
mi_clear_all_keys_active(share->state.key_map);
for (key=0 ; key < share->base.keys ; key++)
share->state.key_root[key]= HA_OFFSET_ERROR;
- for (key=0 ; key < share->state.header.max_block_size ; key++)
+ for (key=0 ; key < share->state.header.max_block_size_index ; key++)
share->state.key_del[key]= HA_OFFSET_ERROR;
isam_file->state->checksum=crc; /* Save crc here */
share->changed=1; /* Force write of header */
diff --git a/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp b/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp
index a37f3811b25..0dbc4094e67 100644
--- a/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp
+++ b/storage/ndb/include/kernel/signaldata/TcKeyReq.hpp
@@ -39,6 +39,7 @@ class TcKeyReq {
friend class NdbOperation;
friend class NdbIndexOperation;
friend class NdbScanOperation;
+ friend class NdbBlob;
friend class DbUtil;
/**
diff --git a/storage/ndb/include/mgmapi/mgmapi_config_parameters.h b/storage/ndb/include/mgmapi/mgmapi_config_parameters.h
index 938706db331..78d34b31bbb 100644
--- a/storage/ndb/include/mgmapi/mgmapi_config_parameters.h
+++ b/storage/ndb/include/mgmapi/mgmapi_config_parameters.h
@@ -64,6 +64,7 @@
#define CFG_DB_BACKUP_DATA_BUFFER_MEM 134
#define CFG_DB_BACKUP_LOG_BUFFER_MEM 135
#define CFG_DB_BACKUP_WRITE_SIZE 136
+#define CFG_DB_BACKUP_MAX_WRITE_SIZE 139
#define CFG_LOG_DESTINATION 147
diff --git a/storage/ndb/include/ndbapi/Ndb.hpp b/storage/ndb/include/ndbapi/Ndb.hpp
index 90dca1c3fc6..010b85b03a9 100644
--- a/storage/ndb/include/ndbapi/Ndb.hpp
+++ b/storage/ndb/include/ndbapi/Ndb.hpp
@@ -1470,6 +1470,8 @@ public:
*
* @return tuple id or 0 on error
*/
+ int initAutoIncrement();
+
Uint64 getAutoIncrementValue(const char* aTableName,
Uint32 cacheSize = 1);
Uint64 getAutoIncrementValue(const NdbDictionary::Table * aTable,
@@ -1694,6 +1696,7 @@ private:
// The tupleId is retreived from DB the
// tupleId is unique for each tableid.
+ const NdbDictionary::Table *m_sys_tab_0;
Uint64 theFirstTupleId[2048];
Uint64 theLastTupleId[2048];
diff --git a/storage/ndb/include/ndbapi/NdbBlob.hpp b/storage/ndb/include/ndbapi/NdbBlob.hpp
index 13bbfa59e50..089b70339de 100644
--- a/storage/ndb/include/ndbapi/NdbBlob.hpp
+++ b/storage/ndb/include/ndbapi/NdbBlob.hpp
@@ -326,6 +326,7 @@ private:
bool isWriteOp();
bool isDeleteOp();
bool isScanOp();
+ bool isTakeOverOp();
// computations
Uint32 getPartNumber(Uint64 pos);
Uint32 getPartCount();
diff --git a/storage/ndb/include/ndbapi/NdbDictionary.hpp b/storage/ndb/include/ndbapi/NdbDictionary.hpp
index b31b35cba89..b31e2551e89 100644
--- a/storage/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/storage/ndb/include/ndbapi/NdbDictionary.hpp
@@ -798,6 +798,7 @@ public:
* Get object status
*/
virtual Object::Status getObjectStatus() const;
+ void setStatusInvalid() const;
/**
* Get object version
@@ -1734,6 +1735,7 @@ public:
* @return 0 if successful otherwise -1.
*/
int createIndex(const Index &index);
+ int createIndex(const Index &index, const Table &table);
/**
* Drop index with given name
@@ -1805,6 +1807,15 @@ public:
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
const Table * getTable(const char * name, void **data) const;
void set_local_table_data_size(unsigned sz);
+
+ const Index * getIndexGlobal(const char * indexName,
+ const Table &ndbtab) const;
+ const Table * getTableGlobal(const char * tableName) const;
+ int alterTableGlobal(const Table &f, const Table &t);
+ int dropTableGlobal(const Table &ndbtab);
+ int dropIndexGlobal(const Index &index);
+ int removeIndexGlobal(const Index &ndbidx, int invalidate) const;
+ int removeTableGlobal(const Table &ndbtab, int invalidate) const;
#endif
};
};
diff --git a/storage/ndb/include/ndbapi/NdbIndexStat.hpp b/storage/ndb/include/ndbapi/NdbIndexStat.hpp
index c718d175864..ddd27ed24d4 100644
--- a/storage/ndb/include/ndbapi/NdbIndexStat.hpp
+++ b/storage/ndb/include/ndbapi/NdbIndexStat.hpp
@@ -56,7 +56,7 @@ public:
* multiplied by a percentage obtained from the cache (result zero is
* returned as 1).
*/
- int records_in_range(NdbDictionary::Index* index,
+ int records_in_range(const NdbDictionary::Index* index,
NdbIndexScanOperation* op,
Uint64 table_rows,
Uint64* count,
diff --git a/storage/ndb/include/util/SocketServer.hpp b/storage/ndb/include/util/SocketServer.hpp
index e131b78baa1..e766a0b99c4 100644
--- a/storage/ndb/include/util/SocketServer.hpp
+++ b/storage/ndb/include/util/SocketServer.hpp
@@ -75,7 +75,7 @@ public:
/**
* Constructor / Destructor
*/
- SocketServer(int maxSessions = 32);
+ SocketServer(unsigned maxSessions = ~(unsigned)0);
~SocketServer();
/**
diff --git a/storage/ndb/src/common/util/SocketServer.cpp b/storage/ndb/src/common/util/SocketServer.cpp
index 481c656b78b..f0af925cf6d 100644
--- a/storage/ndb/src/common/util/SocketServer.cpp
+++ b/storage/ndb/src/common/util/SocketServer.cpp
@@ -27,7 +27,7 @@
#define DEBUG(x) ndbout << x << endl;
-SocketServer::SocketServer(int maxSessions) :
+SocketServer::SocketServer(unsigned maxSessions) :
m_sessions(10),
m_services(5)
{
@@ -136,7 +136,7 @@ SocketServer::setup(SocketServer::Service * service,
}
DBUG_PRINT("info",("bound to %u",ntohs(servaddr.sin_port)));
- if (listen(sock, m_maxSessions) == -1){
+ if (listen(sock, m_maxSessions > 32 ? 32 : m_maxSessions) == -1){
DBUG_PRINT("error",("listen() - %d - %s",
errno, strerror(errno)));
NDB_CLOSE_SOCKET(sock);
diff --git a/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp b/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp
index 45727d39937..5f49a1a8725 100644
--- a/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp
+++ b/storage/ndb/src/kernel/blocks/backup/BackupInit.cpp
@@ -163,15 +163,16 @@ Backup::execREAD_CONFIG_REQ(Signal* signal)
Uint32 szDataBuf = (2 * 1024 * 1024);
Uint32 szLogBuf = (2 * 1024 * 1024);
- Uint32 szWrite = 32768;
+ Uint32 szWrite = 32768, maxWriteSize = (256 * 1024);
ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_DATA_BUFFER_MEM, &szDataBuf);
ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_LOG_BUFFER_MEM, &szLogBuf);
ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_WRITE_SIZE, &szWrite);
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_MAX_WRITE_SIZE, &maxWriteSize);
c_defaults.m_logBufferSize = szLogBuf;
c_defaults.m_dataBufferSize = szDataBuf;
c_defaults.m_minWriteSize = szWrite;
- c_defaults.m_maxWriteSize = 256*1024;
+ c_defaults.m_maxWriteSize = maxWriteSize;
c_defaults.m_lcp_buffer_size = szDataBuf;
diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index 2b452e9529b..d031f9a00bf 100644
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -1394,6 +1394,7 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
if (! DictTabInfo::isOrderedIndex(addfragptr.p->tableType))
{
fragptr.p->m_copy_started_state = Fragrecord::AC_IGNORED;
+ //fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
fragptr.p->fragStatus = Fragrecord::ACTIVE_CREATION;
}
else
@@ -2470,6 +2471,8 @@ void Dblqh::execTUPKEYCONF(Signal* signal)
jamEntry();
tcConnectptr.i = tcIndex;
ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
+ TcConnectionrec * regTcPtr = tcConnectptr.p;
+ Uint32 activeCreat = regTcPtr->activeCreat;
FragrecordPtr regFragptr;
regFragptr.i = tcConnectptr.p->fragmentptr;
@@ -2497,6 +2500,32 @@ void Dblqh::execTUPKEYCONF(Signal* signal)
// Abort was not ready to start until this signal came back. Now we are ready
// to start the abort.
/* ------------------------------------------------------------------------- */
+ if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
+ {
+ jam();
+ ndbrequire(regTcPtr->m_nr_delete.m_cnt);
+ regTcPtr->m_nr_delete.m_cnt--;
+ if (regTcPtr->m_nr_delete.m_cnt)
+ {
+ jam();
+ /**
+ * Let operation wait for pending NR operations
+ * even for before writing log...(as it's simpler)
+ */
+
+#ifdef VM_TRACE
+ /**
+ * Only disk table can have pending ops...
+ */
+ TablerecPtr tablePtr;
+ tablePtr.i = regTcPtr->tableref;
+ ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
+ ndbrequire(tablePtr.p->m_disk_table);
+#endif
+ return;
+ }
+ }
+
abortCommonLab(signal);
break;
case TcConnectionrec::WAIT_ACC_ABORT:
@@ -2523,13 +2552,23 @@ void Dblqh::execTUPKEYREF(Signal* signal)
tcConnectptr.i = tupKeyRef->userRef;
terrorCode = tupKeyRef->errorCode;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
+ TcConnectionrec* regTcPtr = tcConnectptr.p;
+ Uint32 activeCreat = regTcPtr->activeCreat;
FragrecordPtr regFragptr;
- regFragptr.i = tcConnectptr.p->fragmentptr;
+ regFragptr.i = regTcPtr->fragmentptr;
c_fragment_pool.getPtr(regFragptr);
fragptr = regFragptr;
+
+ if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
+ {
+ jam();
+ ndbrequire(regTcPtr->m_nr_delete.m_cnt);
+ regTcPtr->m_nr_delete.m_cnt--;
+ ndbassert(regTcPtr->transactionState == TcConnectionrec::WAIT_TUP ||
+ regTcPtr->transactionState ==TcConnectionrec::WAIT_TUP_TO_ABORT);
+ }
- TcConnectionrec* regTcPtr = tcConnectptr.p;
switch (tcConnectptr.p->transactionState) {
case TcConnectionrec::WAIT_TUP:
jam();
@@ -3767,7 +3806,7 @@ void Dblqh::prepareContinueAfterBlockedLab(Signal* signal)
EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
jamEntry();
- execACC_ABORTCONF(signal);
+ packLqhkeyreqLab(signal);
}
}
@@ -3890,16 +3929,17 @@ Dblqh::handle_nr_copy(Signal* signal, Ptr regTcPtr)
if (TRACENR_FLAG)
TRACENR(" performing DELETE key: "
<< dst[0] << endl);
- regTcPtr.p->tupkeyData[0] = regTcPtr.p->m_row_id.ref();
- if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
+
+ nr_copy_delete_row(signal, regTcPtr, ®TcPtr.p->m_row_id, len);
+ ndbassert(regTcPtr.p->m_nr_delete.m_cnt);
+ regTcPtr.p->m_nr_delete.m_cnt--; // No real op is run
+ if (regTcPtr.p->m_nr_delete.m_cnt)
{
- regTcPtr.p->hashValue = calculateHash(tableId, dst);
+ jam();
+ return;
}
- else
- {
- regTcPtr.p->hashValue = md5_hash((Uint64*)dst, len);
- }
- goto run;
+ packLqhkeyreqLab(signal);
+ return;
}
else if (len == 0 && op == ZDELETE)
{
@@ -3993,9 +4033,7 @@ update_gci_ignore:
signal->theData[0] = regTcPtr.p->tupConnectrec;
EXECUTE_DIRECT(DBTUP, GSN_TUP_ABORTREQ, signal, 1);
- regTcPtr.p->transactionState = TcConnectionrec::WAIT_ACC_ABORT;
- signal->theData[0] = regTcPtr.i;
- execACC_ABORTCONF(signal);
+ packLqhkeyreqLab(signal);
}
int
@@ -4149,7 +4187,6 @@ Dblqh::get_nr_op_info(Nr_op_info* op, Uint32 page_id)
op->m_gci = tcPtr.p->gci;
op->m_tup_frag_ptr_i = fragPtr.p->tupFragptr;
- ndbrequire(tcPtr.p->transactionState == TcConnectionrec::WAIT_TUP_COMMIT);
ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
@@ -4194,16 +4231,36 @@ Dblqh::nr_delete_complete(Signal* signal, Nr_op_info* op)
tcPtr.i = op->m_ptr_i;
ptrCheckGuard(tcPtr, ctcConnectrecFileSize, tcConnectionrec);
- ndbrequire(tcPtr.p->transactionState == TcConnectionrec::WAIT_TUP_COMMIT);
ndbrequire(tcPtr.p->activeCreat == Fragrecord::AC_NR_COPY);
ndbrequire(tcPtr.p->m_nr_delete.m_cnt);
tcPtr.p->m_nr_delete.m_cnt--;
if (tcPtr.p->m_nr_delete.m_cnt == 0)
{
+ jam();
tcConnectptr = tcPtr;
c_fragment_pool.getPtr(fragptr, tcPtr.p->fragmentptr);
- packLqhkeyreqLab(signal);
+
+ if (tcPtr.p->abortState != TcConnectionrec::ABORT_IDLE)
+ {
+ jam();
+ tcPtr.p->activeCreat = Fragrecord::AC_NORMAL;
+ abortCommonLab(signal);
+ }
+ else if (tcPtr.p->operation == ZDELETE &&
+ LqhKeyReq::getNrCopyFlag(tcPtr.p->reqinfo))
+ {
+ /**
+ * This is run directly in handle_nr_copy
+ */
+ jam();
+ packLqhkeyreqLab(signal);
+ }
+ else
+ {
+ jam();
+ rwConcludedLab(signal);
+ }
return;
}
@@ -4319,7 +4376,6 @@ void Dblqh::execACCKEYCONF(Signal* signal)
return;
}//if
- // reset the activeCreat since that is only valid in cases where the record was not present.
/* ------------------------------------------------------------------------
* IT IS NOW TIME TO CONTACT THE TUPLE MANAGER. THE TUPLE MANAGER NEEDS THE
* INFORMATION ON WHICH TABLE AND FRAGMENT, THE LOCAL KEY AND IT NEEDS TO
@@ -4536,6 +4592,7 @@ Dblqh::acckeyconf_load_diskpage(Signal* signal, TcConnectionrecPtr regTcPtr,
}
else
{
+ regTcPtr.p->transactionState = TcConnectionrec::WAIT_TUP;
TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
ref->userRef= regTcPtr.i;
ref->errorCode= ~0;
@@ -4571,6 +4628,7 @@ Dblqh::acckeyconf_load_diskpage_callback(Signal* signal,
}
else
{
+ regTcPtr->transactionState = TcConnectionrec::WAIT_TUP;
TupKeyRef * ref = (TupKeyRef *)signal->getDataPtr();
ref->userRef= callbackData;
ref->errorCode= disk_page;
@@ -4592,9 +4650,11 @@ Dblqh::acckeyconf_load_diskpage_callback(Signal* signal,
* -------------------------------------------------------------------------- */
void Dblqh::tupkeyConfLab(Signal* signal)
{
-/* ---- GET OPERATION TYPE AND CHECK WHAT KIND OF OPERATION IS REQUESTED ---- */
+/* ---- GET OPERATION TYPE AND CHECK WHAT KIND OF OPERATION IS REQUESTED --- */
const TupKeyConf * const tupKeyConf = (TupKeyConf *)&signal->theData[0];
TcConnectionrec * const regTcPtr = tcConnectptr.p;
+ Uint32 activeCreat = regTcPtr->activeCreat;
+
if (regTcPtr->simpleRead) {
jam();
/* ----------------------------------------------------------------------
@@ -4616,6 +4676,34 @@ void Dblqh::tupkeyConfLab(Signal* signal)
}//if
regTcPtr->totSendlenAi = tupKeyConf->writeLength;
ndbrequire(regTcPtr->totSendlenAi == regTcPtr->currTupAiLen);
+
+ if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
+ {
+ jam();
+ ndbrequire(regTcPtr->m_nr_delete.m_cnt);
+ regTcPtr->m_nr_delete.m_cnt--;
+ if (regTcPtr->m_nr_delete.m_cnt)
+ {
+ jam();
+ /**
+ * Let operation wait for pending NR operations
+ * even for before writing log...(as it's simpler)
+ */
+
+#ifdef VM_TRACE
+ /**
+ * Only disk table can have pending ops...
+ */
+ TablerecPtr tablePtr;
+ tablePtr.i = regTcPtr->tableref;
+ ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
+ ndbrequire(tablePtr.p->m_disk_table);
+#endif
+
+ return;
+ }
+ }
+
rwConcludedLab(signal);
return;
}//Dblqh::tupkeyConfLab()
@@ -6325,27 +6413,19 @@ Dblqh::tupcommit_conf(Signal* signal,
/*SEND ANY COMMIT OR COMPLETE MESSAGES TO OTHER NODES. THEY WILL MERELY SEND */
/*THOSE SIGNALS INTERNALLY. */
/* ------------------------------------------------------------------------- */
- if (tcPtrP->abortState == TcConnectionrec::ABORT_IDLE) {
+ if (tcPtrP->abortState == TcConnectionrec::ABORT_IDLE)
+ {
jam();
- if (activeCreat == Fragrecord::AC_NR_COPY &&
- tcPtrP->m_nr_delete.m_cnt > 1)
+ if (activeCreat == Fragrecord::AC_NR_COPY)
{
jam();
- /**
- * Nr delete waiting for disk delete to complete...
- */
-#ifdef VM_TRACE
- TablerecPtr tablePtr;
- tablePtr.i = tcPtrP->tableref;
- ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
- ndbrequire(tablePtr.p->m_disk_table);
-#endif
- tcPtrP->m_nr_delete.m_cnt--;
- tcPtrP->transactionState = TcConnectionrec::WAIT_TUP_COMMIT;
- return;
+ ndbrequire(LqhKeyReq::getNrCopyFlag(tcPtrP->reqinfo));
+ ndbrequire(tcPtrP->m_nr_delete.m_cnt == 0);
}
packLqhkeyreqLab(signal);
- } else {
+ }
+ else
+ {
ndbrequire(tcPtrP->abortState != TcConnectionrec::NEW_FROM_TC);
jam();
sendLqhTransconf(signal, LqhTransConf::Committed);
@@ -6549,7 +6629,7 @@ void Dblqh::execABORT(Signal* signal)
}//if
TcConnectionrec * const regTcPtr = tcConnectptr.p;
-
+ Uint32 activeCreat = regTcPtr->activeCreat;
if (ERROR_INSERTED(5100))
{
SET_ERROR_INSERT_VALUE(5101);
@@ -6574,10 +6654,10 @@ void Dblqh::execABORT(Signal* signal)
sendSignal(TLqhRef, GSN_ABORT, signal, 4, JBB);
}//if
regTcPtr->abortState = TcConnectionrec::ABORT_FROM_TC;
- regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
- if(commitAckMarker != RNIL){
+ if(commitAckMarker != RNIL)
+ {
jam();
#ifdef MARKER_TRACE
{
@@ -6627,6 +6707,7 @@ void Dblqh::execABORTREQ(Signal* signal)
return;
}//if
TcConnectionrec * const regTcPtr = tcConnectptr.p;
+ Uint32 activeCreat = regTcPtr->activeCreat;
if (regTcPtr->transactionState != TcConnectionrec::PREPARED) {
warningReport(signal, 10);
return;
@@ -6634,7 +6715,7 @@ void Dblqh::execABORTREQ(Signal* signal)
regTcPtr->reqBlockref = reqBlockref;
regTcPtr->reqRef = reqPtr;
regTcPtr->abortState = TcConnectionrec::REQ_FROM_TC;
- regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
+
abortCommonLab(signal);
return;
}//Dblqh::execABORTREQ()
@@ -6704,42 +6785,26 @@ void Dblqh::execACCKEYREF(Signal* signal)
}
- if (tcPtr->activeCreat == Fragrecord::AC_NR_COPY)
- {
- jam();
- Uint32 op = tcPtr->operation;
- switch(errCode){
- case ZNO_TUPLE_FOUND:
- ndbrequire(op == ZDELETE);
- break;
- break;
- default:
- ndbrequire(false);
- }
- tcPtr->activeCreat = Fragrecord::AC_IGNORED;
- }
- else
- {
- ndbrequire(!LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo));
-
- /**
- * Only primary replica can get ZTUPLE_ALREADY_EXIST || ZNO_TUPLE_FOUND
- *
- * Unless it's a simple or dirty read
- *
- * NOT TRUE!
- * 1) op1 - primary insert ok
- * 2) op1 - backup insert fail (log full or what ever)
- * 3) op1 - delete ok @ primary
- * 4) op1 - delete fail @ backup
- *
- * -> ZNO_TUPLE_FOUND is possible
- */
- ndbrequire
- (tcPtr->seqNoReplica == 0 ||
- errCode != ZTUPLE_ALREADY_EXIST ||
- (tcPtr->operation == ZREAD && (tcPtr->dirtyOp || tcPtr->opSimple)));
- }
+ ndbrequire(tcPtr->activeCreat == Fragrecord::AC_NORMAL);
+ ndbrequire(!LqhKeyReq::getNrCopyFlag(tcPtr->reqinfo));
+
+ /**
+ * Only primary replica can get ZTUPLE_ALREADY_EXIST || ZNO_TUPLE_FOUND
+ *
+ * Unless it's a simple or dirty read
+ *
+ * NOT TRUE!
+ * 1) op1 - primary insert ok
+ * 2) op1 - backup insert fail (log full or what ever)
+ * 3) op1 - delete ok @ primary
+ * 4) op1 - delete fail @ backup
+ *
+ * -> ZNO_TUPLE_FOUND is possible
+ */
+ ndbrequire
+ (tcPtr->seqNoReplica == 0 ||
+ errCode != ZTUPLE_ALREADY_EXIST ||
+ (tcPtr->operation == ZREAD && (tcPtr->dirtyOp || tcPtr->opSimple)));
tcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
abortCommonLab(signal);
@@ -6753,7 +6818,6 @@ void Dblqh::localAbortStateHandlerLab(Signal* signal)
jam();
return;
}//if
- regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
regTcPtr->errorCode = terrorCode;
abortStateHandlerLab(signal);
@@ -6929,11 +6993,6 @@ void Dblqh::abortErrorLab(Signal* signal)
regTcPtr->abortState = TcConnectionrec::ABORT_FROM_LQH;
regTcPtr->errorCode = terrorCode;
}//if
- /* -----------------------------------------------------------------------
- * ACTIVE CREATION IS RESET FOR ALL ERRORS WHICH SHOULD BE HANDLED
- * WITH NORMAL ABORT HANDLING.
- * ----------------------------------------------------------------------- */
- regTcPtr->activeCreat = Fragrecord::AC_NORMAL;
abortCommonLab(signal);
return;
}//Dblqh::abortErrorLab()
@@ -6942,8 +7001,9 @@ void Dblqh::abortCommonLab(Signal* signal)
{
TcConnectionrec * const regTcPtr = tcConnectptr.p;
const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
- if(regTcPtr->activeCreat != Fragrecord::AC_IGNORED &&
- commitAckMarker != RNIL){
+ const Uint32 activeCreat = regTcPtr->activeCreat;
+ if (commitAckMarker != RNIL)
+ {
/**
* There is no NR ongoing and we have a marker
*/
@@ -6958,6 +7018,29 @@ void Dblqh::abortCommonLab(Signal* signal)
m_commitAckMarkerHash.release(commitAckMarker);
regTcPtr->commitAckMarker = RNIL;
}
+
+ if (unlikely(activeCreat == Fragrecord::AC_NR_COPY))
+ {
+ jam();
+ if (regTcPtr->m_nr_delete.m_cnt)
+ {
+ jam();
+ /**
+ * Let operation wait for pending NR operations
+ */
+
+#ifdef VM_TRACE
+ /**
+ * Only disk table can have pending ops...
+ */
+ TablerecPtr tablePtr;
+ tablePtr.i = regTcPtr->tableref;
+ ptrCheckGuard(tablePtr, ctabrecFileSize, tablerec);
+ ndbrequire(tablePtr.p->m_disk_table);
+#endif
+ return;
+ }
+ }
fragptr.i = regTcPtr->fragmentptr;
if (fragptr.i != RNIL) {
@@ -7034,25 +7117,6 @@ void Dblqh::execACC_ABORTCONF(Signal* signal)
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
TcConnectionrec * const regTcPtr = tcConnectptr.p;
ndbrequire(regTcPtr->transactionState == TcConnectionrec::WAIT_ACC_ABORT);
- if (regTcPtr->activeCreat == Fragrecord::AC_IGNORED) {
- /* ----------------------------------------------------------------------
- * A NORMAL EVENT DURING CREATION OF A FRAGMENT. WE NOW NEED TO CONTINUE
- * WITH NORMAL COMMIT PROCESSING.
- * --------------------------------------------------------------------- */
- if (regTcPtr->currTupAiLen == regTcPtr->totReclenAi) {
- jam();
- regTcPtr->abortState = TcConnectionrec::ABORT_IDLE;
- fragptr.i = regTcPtr->fragmentptr;
- c_fragment_pool.getPtr(fragptr);
- rwConcludedLab(signal);
- return;
- } else {
- ndbrequire(regTcPtr->currTupAiLen < regTcPtr->totReclenAi);
- jam();
- regTcPtr->transactionState = TcConnectionrec::WAIT_AI_AFTER_ABORT;
- return;
- }//if
- }//if
continueAbortLab(signal);
return;
}//Dblqh::execACC_ABORTCONF()
@@ -9450,7 +9514,7 @@ void Dblqh::initScanTc(const ScanFragReq* req,
tcConnectptr.p->m_offset_current_keybuf = 0;
tcConnectptr.p->m_scan_curr_range_no = 0;
tcConnectptr.p->m_dealloc = 0;
-
+ tcConnectptr.p->activeCreat = Fragrecord::AC_NORMAL;
TablerecPtr tTablePtr;
tTablePtr.i = tabptr.p->primaryTableId;
ptrCheckGuard(tTablePtr, ctabrecFileSize, tablerec);
@@ -9929,16 +9993,21 @@ void Dblqh::continueFirstCopyAfterBlockedLab(Signal* signal)
*/
fragptr.p->m_copy_started_state = Fragrecord::AC_NR_COPY;
- if (0)
+ scanptr.i = tcConnectptr.p->tcScanRec;
+ c_scanRecordPool.getPtr(scanptr);
+
+ if (false && fragptr.p->tabRef > 4)
{
- ndbout_c("STOPPING COPY (%d -> %d %d %d)",
- scanptr.p->scanBlockref,
+ ndbout_c("STOPPING COPY X = [ %d %d %d %d ]",
+ refToBlock(scanptr.p->scanBlockref),
scanptr.p->scanAccPtr, RNIL, NextScanReq::ZSCAN_NEXT);
+
+ /**
+ * RESTART: > DUMP 7020 332 X
+ */
return;
}
- scanptr.i = tcConnectptr.p->tcScanRec;
- c_scanRecordPool.getPtr(scanptr);
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = RNIL;
signal->theData[2] = NextScanReq::ZSCAN_NEXT;
@@ -18351,6 +18420,7 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
<< " tcBlockref = " << hex << tcRec.p->tcBlockref
<< " reqBlockref = " << hex << tcRec.p->reqBlockref
<< " primKeyLen = " << tcRec.p->primKeyLen
+ << " nrcopyflag = " << LqhKeyReq::getNrCopyFlag(tcRec.p->reqinfo)
<< endl;
ndbout << " nextReplica = " << tcRec.p->nextReplica
<< " tcBlockref = " << hex << tcRec.p->tcBlockref
@@ -18421,6 +18491,7 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
<< endl;
ndbout << " tupkeyData2 = " << tcRec.p->tupkeyData[2]
<< " tupkeyData3 = " << tcRec.p->tupkeyData[3]
+ << " m_nr_delete.m_cnt = " << tcRec.p->m_nr_delete.m_cnt
<< endl;
switch (tcRec.p->transactionState) {
diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 0000796d7b2..90abe2cb809 100644
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -483,6 +483,14 @@ Dbtup::load_diskpage(Signal* signal,
req.m_callback.m_callbackData= opRec;
req.m_callback.m_callbackFunction=
safe_cast(&Dbtup::disk_page_load_callback);
+
+#ifdef ERROR_INSERT
+ if (ERROR_INSERTED(4022))
+ {
+ flags |= Page_cache_client::DELAY_REQ;
+ req.m_delay_until_time = NdbTick_CurrentMillisecond()+(Uint64)3000;
+ }
+#endif
if((res= m_pgman.get_page(signal, req, flags)) > 0)
{
@@ -3119,6 +3127,35 @@ Dbtup::nr_delete(Signal* signal, Uint32 senderData,
preq.m_callback.m_callbackFunction =
safe_cast(&Dbtup::nr_delete_page_callback);
int flags = Page_cache_client::COMMIT_REQ;
+
+#ifdef ERROR_INSERT
+ if (ERROR_INSERTED(4023) || ERROR_INSERTED(4024))
+ {
+ int rnd = rand() % 100;
+ int slp = 0;
+ if (ERROR_INSERTED(4024))
+ {
+ slp = 3000;
+ }
+ else if (rnd > 90)
+ {
+ slp = 3000;
+ }
+ else if (rnd > 70)
+ {
+ slp = 100;
+ }
+
+ ndbout_c("rnd: %d slp: %d", rnd, slp);
+
+ if (slp)
+ {
+ flags |= Page_cache_client::DELAY_REQ;
+ preq.m_delay_until_time = NdbTick_CurrentMillisecond()+(Uint64)slp;
+ }
+ }
+#endif
+
res = m_pgman.get_page(signal, preq, flags);
if (res == 0)
{
@@ -3130,6 +3167,7 @@ Dbtup::nr_delete(Signal* signal, Uint32 senderData,
}
PagePtr disk_page = *(PagePtr*)&m_pgman.m_ptr;
+ disk_page_set_dirty(disk_page);
preq.m_callback.m_callbackFunction =
safe_cast(&Dbtup::nr_delete_logbuffer_callback);
@@ -3164,7 +3202,7 @@ Dbtup::nr_delete_page_callback(Signal* signal,
Ptr gpage;
m_global_page_pool.getPtr(gpage, page_id);
PagePtr pagePtr= *(PagePtr*)&gpage;
-
+ disk_page_set_dirty(pagePtr);
Dblqh::Nr_op_info op;
op.m_ptr_i = userpointer;
op.m_disk_ref.m_page_no = pagePtr.p->m_page_no;
diff --git a/storage/ndb/src/kernel/blocks/pgman.cpp b/storage/ndb/src/kernel/blocks/pgman.cpp
index be661433ef6..addbd5e4ba2 100644
--- a/storage/ndb/src/kernel/blocks/pgman.cpp
+++ b/storage/ndb/src/kernel/blocks/pgman.cpp
@@ -944,12 +944,16 @@ Pgman::process_callback(Signal* signal)
int max_count = 1;
Page_sublist& pl_callback = *m_page_sublist[Page_entry::SL_CALLBACK];
- while (! pl_callback.isEmpty() && --max_count >= 0)
+ Ptr ptr;
+ pl_callback.first(ptr);
+
+ while (! ptr.isNull() && --max_count >= 0)
{
jam();
- Ptr ptr;
- pl_callback.first(ptr);
- if (! process_callback(signal, ptr))
+ Ptr curr = ptr;
+ pl_callback.next(ptr);
+
+ if (! process_callback(signal, curr))
{
jam();
break;
@@ -987,6 +991,18 @@ Pgman::process_callback(Signal* signal, Ptr ptr)
#ifdef VM_TRACE
debugOut << "PGMAN: " << req_ptr << " : process_callback" << endl;
#endif
+
+#ifdef ERROR_INSERT
+ if (req_ptr.p->m_flags & Page_request::DELAY_REQ)
+ {
+ Uint64 now = NdbTick_CurrentMillisecond();
+ if (now < req_ptr.p->m_delay_until_time)
+ {
+ break;
+ }
+ }
+#endif
+
b = globalData.getBlock(req_ptr.p->m_block);
callback = req_ptr.p->m_callback;
@@ -1314,6 +1330,24 @@ Pgman::fsreadconf(Signal* signal, Ptr ptr)
state |= Page_entry::MAPPED;
set_page_state(ptr, state);
+ {
+ /**
+ * Update lsn record on page
+ * as it can be modified/flushed wo/ update_lsn has been called
+ * (e.g. prealloc) and it then would get lsn 0, which is bad
+ * when running undo and following SR
+ */
+ Ptr pagePtr;
+ m_global_page_pool.getPtr(pagePtr, ptr.p->m_real_page_i);
+ File_formats::Datafile::Data_page* page =
+ (File_formats::Datafile::Data_page*)pagePtr.p;
+
+ Uint64 lsn = 0;
+ lsn += page->m_page_header.m_page_lsn_hi; lsn <<= 32;
+ lsn += page->m_page_header.m_page_lsn_lo;
+ ptr.p->m_lsn = lsn;
+ }
+
ndbrequire(m_stats.m_current_io_waits > 0);
m_stats.m_current_io_waits--;
@@ -1575,7 +1609,13 @@ Pgman::get_page(Signal* signal, Ptr ptr, Page_request page_req)
}
bool only_request = ptr.p->m_requests.isEmpty();
-
+#ifdef ERROR_INSERT
+ if (req_flags & Page_request::DELAY_REQ)
+ {
+ jam();
+ only_request = false;
+ }
+#endif
if (only_request &&
state & Page_entry::MAPPED)
{
@@ -1623,7 +1663,10 @@ Pgman::get_page(Signal* signal, Ptr ptr, Page_request page_req)
req_ptr.p->m_block = page_req.m_block;
req_ptr.p->m_flags = page_req.m_flags;
req_ptr.p->m_callback = page_req.m_callback;
-
+#ifdef ERROR_INSERT
+ req_ptr.p->m_delay_until_time = page_req.m_delay_until_time;
+#endif
+
state |= Page_entry::REQUEST;
if (only_request && req_flags & Page_request::EMPTY_PAGE)
{
diff --git a/storage/ndb/src/kernel/blocks/pgman.hpp b/storage/ndb/src/kernel/blocks/pgman.hpp
index 5a6a5f319bd..ae7736025ab 100644
--- a/storage/ndb/src/kernel/blocks/pgman.hpp
+++ b/storage/ndb/src/kernel/blocks/pgman.hpp
@@ -256,12 +256,18 @@ private:
,DIRTY_REQ = 0x0200 // make page dirty wo/ update_lsn
,UNLOCK_PAGE = 0x0400
,CORR_REQ = 0x0800 // correlated request (no LIRS update)
+#ifdef ERROR_INSERT
+ ,DELAY_REQ = 0x1000 // Force request to be delayed
+#endif
};
-
+
Uint16 m_block;
Uint16 m_flags;
SimulatedBlock::Callback m_callback;
+#ifdef ERROR_INSERT
+ Uint64 m_delay_until_time;
+#endif
Uint32 nextList;
Uint32 m_magic;
};
@@ -508,6 +514,10 @@ public:
struct Request {
Local_key m_page;
SimulatedBlock::Callback m_callback;
+
+#ifdef ERROR_INSERT
+ Uint64 m_delay_until_time;
+#endif
};
Ptr m_ptr; // TODO remove
@@ -520,6 +530,9 @@ public:
,DIRTY_REQ = Pgman::Page_request::DIRTY_REQ
,UNLOCK_PAGE = Pgman::Page_request::UNLOCK_PAGE
,CORR_REQ = Pgman::Page_request::CORR_REQ
+#ifdef ERROR_INSERT
+ ,DELAY_REQ = Pgman::Page_request::DELAY_REQ
+#endif
};
/**
@@ -588,7 +601,10 @@ Page_cache_client::get_page(Signal* signal, Request& req, Uint32 flags)
page_req.m_block = m_block;
page_req.m_flags = flags;
page_req.m_callback = req.m_callback;
-
+#ifdef ERROR_INSERT
+ page_req.m_delay_until_time = req.m_delay_until_time;
+#endif
+
int i = m_pgman->get_page(signal, entry_ptr, page_req);
if (i > 0)
{
diff --git a/storage/ndb/src/mgmsrv/ConfigInfo.cpp b/storage/ndb/src/mgmsrv/ConfigInfo.cpp
index 5b3efa28d35..8705b640809 100644
--- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp
+++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp
@@ -1235,7 +1235,19 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
false,
ConfigInfo::CI_INT,
"32K",
- "0",
+ "2K",
+ STR_VALUE(MAX_INT_RNIL) },
+
+ {
+ CFG_DB_BACKUP_MAX_WRITE_SIZE,
+ "BackupMaxWriteSize",
+ DB_TOKEN,
+ "Max size of filesystem writes made by backup (in bytes)",
+ ConfigInfo::CI_USED,
+ false,
+ ConfigInfo::CI_INT,
+ "256K",
+ "2K",
STR_VALUE(MAX_INT_RNIL) },
{
diff --git a/storage/ndb/src/ndbapi/DictCache.cpp b/storage/ndb/src/ndbapi/DictCache.cpp
index fc276472c48..43913d6c5be 100644
--- a/storage/ndb/src/ndbapi/DictCache.cpp
+++ b/storage/ndb/src/ndbapi/DictCache.cpp
@@ -63,6 +63,7 @@ LocalDictCache::~LocalDictCache(){
Ndb_local_table_info *
LocalDictCache::get(const char * name){
+ ASSERT_NOT_MYSQLD;
assert(! is_ndb_blob_table(name));
const Uint32 len = strlen(name);
return m_tableHash.getData(name, len);
@@ -70,6 +71,7 @@ LocalDictCache::get(const char * name){
void
LocalDictCache::put(const char * name, Ndb_local_table_info * tab_info){
+ ASSERT_NOT_MYSQLD;
assert(! is_ndb_blob_table(name));
const Uint32 id = tab_info->m_table_impl->m_id;
m_tableHash.insertKey(name, strlen(name), id, tab_info);
@@ -77,6 +79,7 @@ LocalDictCache::put(const char * name, Ndb_local_table_info * tab_info){
void
LocalDictCache::drop(const char * name){
+ ASSERT_NOT_MYSQLD;
assert(! is_ndb_blob_table(name));
Ndb_local_table_info *info= m_tableHash.deleteKey(name, strlen(name));
DBUG_ASSERT(info != 0);
@@ -100,8 +103,15 @@ GlobalDictCache::~GlobalDictCache(){
Vector * vers = curr->theData;
const unsigned sz = vers->size();
for(unsigned i = 0; im_internalName.c_str()));
delete (* vers)[i].m_impl;
+ }
}
delete curr->theData;
curr->theData= NULL;
@@ -164,11 +174,18 @@ GlobalDictCache::get(const char * name)
TableVersion * ver = & versions->back();
switch(ver->m_status){
case OK:
+ if (ver->m_impl->m_status == NdbDictionary::Object::Invalid)
+ {
+ ver->m_status = DROPPED;
+ retreive = true; // Break loop
+ break;
+ }
ver->m_refCount++;
- DBUG_PRINT("info", ("Table OK version=%x.%x refCount=%u",
- ver->m_impl->m_version & 0xFFFFFF,
- ver->m_impl->m_version >> 24,
- ver->m_refCount));
+ DBUG_PRINT("info", ("Table OK tab: %p version=%x.%x refCount=%u",
+ ver->m_impl,
+ ver->m_impl->m_version & 0xFFFFFF,
+ ver->m_impl->m_version >> 24,
+ ver->m_refCount));
DBUG_RETURN(ver->m_impl);
case DROPPED:
retreive = true; // Break loop
@@ -197,8 +214,8 @@ NdbTableImpl *
GlobalDictCache::put(const char * name, NdbTableImpl * tab)
{
DBUG_ENTER("GlobalDictCache::put");
- DBUG_PRINT("enter", ("name: %s, internal_name: %s version: %x.%x",
- name,
+ DBUG_PRINT("enter", ("tab: %p name: %s, internal_name: %s version: %x.%x",
+ tab, name,
tab ? tab->m_internalName.c_str() : "tab NULL",
tab ? tab->m_version & 0xFFFFFF : 0,
tab ? tab->m_version >> 24 : 0));
@@ -264,66 +281,11 @@ GlobalDictCache::put(const char * name, NdbTableImpl * tab)
}
void
-GlobalDictCache::drop(NdbTableImpl * tab)
-{
- DBUG_ENTER("GlobalDictCache::drop");
- DBUG_PRINT("enter", ("internal_name: %s", tab->m_internalName.c_str()));
- assert(! is_ndb_blob_table(tab));
-
- unsigned i;
- const Uint32 len = strlen(tab->m_internalName.c_str());
- Vector * vers =
- m_tableHash.getData(tab->m_internalName.c_str(), len);
- if(vers == 0){
- // Should always tried to retreive it first
- // and thus there should be a record
- abort();
- }
-
- const Uint32 sz = vers->size();
- if(sz == 0){
- // Should always tried to retreive it first
- // and thus there should be a record
- abort();
- }
-
- for(i = 0; i < sz; i++){
- TableVersion & ver = (* vers)[i];
- if(ver.m_impl == tab){
- if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
- ver.m_version != tab->m_version){
- DBUG_PRINT("info", ("Dropping with refCount=%d status=%d impl=%p",
- ver.m_refCount, ver.m_status, ver.m_impl));
- break;
- }
- DBUG_PRINT("info", ("Found table to drop, i: %d, name: %s",
- i, ver.m_impl->m_internalName.c_str()));
- ver.m_refCount--;
- ver.m_status = DROPPED;
- if(ver.m_refCount == 0){
- DBUG_PRINT("info", ("refCount is zero, deleting m_impl"));
- delete ver.m_impl;
- vers->erase(i);
- }
- DBUG_VOID_RETURN;
- }
- }
-
- for(i = 0; im_internalName.c_str()));
+ DBUG_PRINT("enter", ("tab: %p internal_name: %s",
+ tab, tab->m_internalName.c_str()));
assert(! is_ndb_blob_table(tab));
unsigned i;
@@ -354,6 +316,17 @@ GlobalDictCache::release(NdbTableImpl * tab)
}
ver.m_refCount--;
+ if (ver.m_impl->m_status == NdbDictionary::Object::Invalid || invalidate)
+ {
+ ver.m_impl->m_status = NdbDictionary::Object::Invalid;
+ ver.m_status = DROPPED;
+ }
+ if (ver.m_refCount == 0 && ver.m_status == DROPPED)
+ {
+ DBUG_PRINT("info", ("refCount is zero, deleting m_impl"));
+ delete ver.m_impl;
+ vers->erase(i);
+ }
DBUG_VOID_RETURN;
}
}
@@ -374,6 +347,7 @@ GlobalDictCache::alter_table_rep(const char * name,
Uint32 tableVersion,
bool altered)
{
+ DBUG_ENTER("GlobalDictCache::alter_table_rep");
assert(! is_ndb_blob_table(name));
const Uint32 len = strlen(name);
Vector * vers =
@@ -381,13 +355,13 @@ GlobalDictCache::alter_table_rep(const char * name,
if(vers == 0)
{
- return;
+ DBUG_VOID_RETURN;
}
const Uint32 sz = vers->size();
if(sz == 0)
{
- return;
+ DBUG_VOID_RETURN;
}
for(Uint32 i = 0; i < sz; i++)
@@ -399,15 +373,16 @@ GlobalDictCache::alter_table_rep(const char * name,
ver.m_status = DROPPED;
ver.m_impl->m_status = altered ?
NdbDictionary::Object::Altered : NdbDictionary::Object::Invalid;
- return;
+ DBUG_VOID_RETURN;
}
if(i == sz - 1 && ver.m_status == RETREIVING)
{
ver.m_impl = altered ? &f_altered_table : &f_invalid_table;
- return;
+ DBUG_VOID_RETURN;
}
}
+ DBUG_VOID_RETURN;
}
template class Vector;
diff --git a/storage/ndb/src/ndbapi/DictCache.hpp b/storage/ndb/src/ndbapi/DictCache.hpp
index 2df6a139542..f134e6b348e 100644
--- a/storage/ndb/src/ndbapi/DictCache.hpp
+++ b/storage/ndb/src/ndbapi/DictCache.hpp
@@ -63,11 +63,11 @@ public:
GlobalDictCache();
~GlobalDictCache();
+ NdbTableImpl * get(NdbTableImpl *tab);
NdbTableImpl * get(const char * name);
NdbTableImpl* put(const char * name, NdbTableImpl *);
- void drop(NdbTableImpl *);
- void release(NdbTableImpl *);
+ void release(NdbTableImpl *, int invalidate = 0);
void alter_table_rep(const char * name,
Uint32 tableId, Uint32 tableVersion, bool altered);
diff --git a/storage/ndb/src/ndbapi/Ndb.cpp b/storage/ndb/src/ndbapi/Ndb.cpp
index ed54b894b64..b963aeeff84 100644
--- a/storage/ndb/src/ndbapi/Ndb.cpp
+++ b/storage/ndb/src/ndbapi/Ndb.cpp
@@ -901,6 +901,27 @@ Ndb::setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase )
DBUG_RETURN((opTupleIdOnNdb(aTableId, val, 1) == val));
}
+int Ndb::initAutoIncrement()
+{
+ if (m_sys_tab_0)
+ return 0;
+
+ BaseString currentDb(getDatabaseName());
+ BaseString currentSchema(getDatabaseSchemaName());
+
+ setDatabaseName("sys");
+ setDatabaseSchemaName("def");
+
+ m_sys_tab_0 = getDictionary()->getTableGlobal("SYSTAB_0");
+
+ // Restore current name space
+ setDatabaseName(currentDb.c_str());
+ setDatabaseSchemaName(currentSchema.c_str());
+
+
+ return (m_sys_tab_0 == NULL);
+}
+
Uint64
Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
{
@@ -916,19 +937,14 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
CHECK_STATUS_MACRO_ZERO;
- BaseString currentDb(getDatabaseName());
- BaseString currentSchema(getDatabaseSchemaName());
+ if (initAutoIncrement())
+ goto error_return;
- setDatabaseName("sys");
- setDatabaseSchemaName("def");
tConnection = this->startTransaction();
if (tConnection == NULL)
goto error_return;
- if (usingFullyQualifiedNames())
- tOperation = tConnection->getNdbOperation("SYSTAB_0");
- else
- tOperation = tConnection->getNdbOperation("sys/def/SYSTAB_0");
+ tOperation = tConnection->getNdbOperation(m_sys_tab_0);
if (tOperation == NULL)
goto error_handler;
@@ -997,20 +1013,12 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
this->closeTransaction(tConnection);
- // Restore current name space
- setDatabaseName(currentDb.c_str());
- setDatabaseSchemaName(currentSchema.c_str());
-
DBUG_RETURN(ret);
error_handler:
theError.code = tConnection->theError.code;
this->closeTransaction(tConnection);
error_return:
- // Restore current name space
- setDatabaseName(currentDb.c_str());
- setDatabaseSchemaName(currentSchema.c_str());
-
DBUG_PRINT("error", ("ndb=%d con=%d op=%d",
theError.code,
tConnection ? tConnection->theError.code : -1,
diff --git a/storage/ndb/src/ndbapi/NdbBlob.cpp b/storage/ndb/src/ndbapi/NdbBlob.cpp
index 00f71a2f85b..4e3e13b59bf 100644
--- a/storage/ndb/src/ndbapi/NdbBlob.cpp
+++ b/storage/ndb/src/ndbapi/NdbBlob.cpp
@@ -23,6 +23,7 @@
#include
#include "NdbBlobImpl.hpp"
#include
+#include
#include
/*
@@ -392,6 +393,13 @@ NdbBlob::isScanOp()
theNdbOp->theOperationType == NdbOperation::OpenRangeScanRequest;
}
+inline bool
+NdbBlob::isTakeOverOp()
+{
+ return
+ TcKeyReq::getTakeOverScanFlag(theNdbOp->theScanInfo);
+}
+
// computations (inline)
inline Uint32
@@ -1527,8 +1535,22 @@ NdbBlob::preExecute(NdbTransaction::ExecType anExecType, bool& batch)
if (isUpdateOp() || isWriteOp() || isDeleteOp()) {
// add operation before this one to read head+inline
NdbOperation* tOp = theNdbCon->getNdbOperation(theTable, theNdbOp);
+ /*
+ * If main op is from take over scan lock, the added read is done
+ * as committed read:
+ *
+ * In normal transactional case, the row is locked by us and
+ * committed read returns same as normal read.
+ *
+ * In current TRUNCATE TABLE, the deleting trans is committed in
+ * batches and then restarted with new trans id. A normal read
+ * would hang on the scan delete lock and then fail.
+ */
+ NdbOperation::LockMode lockMode =
+ ! isTakeOverOp() ?
+ NdbOperation::LM_Read : NdbOperation::LM_CommittedRead;
if (tOp == NULL ||
- tOp->readTuple() == -1 ||
+ tOp->readTuple(lockMode) == -1 ||
setTableKeyValue(tOp) == -1 ||
getHeadInlineValue(tOp) == -1) {
setErrorCode(tOp);
diff --git a/storage/ndb/src/ndbapi/NdbDictionary.cpp b/storage/ndb/src/ndbapi/NdbDictionary.cpp
index b0ebf90915f..e844dc3369e 100644
--- a/storage/ndb/src/ndbapi/NdbDictionary.cpp
+++ b/storage/ndb/src/ndbapi/NdbDictionary.cpp
@@ -559,6 +559,11 @@ NdbDictionary::Table::getObjectStatus() const {
return m_impl.m_status;
}
+void
+NdbDictionary::Table::setStatusInvalid() const {
+ m_impl.m_status = NdbDictionary::Object::Invalid;
+}
+
int
NdbDictionary::Table::getObjectVersion() const {
return m_impl.m_version;
@@ -1330,6 +1335,11 @@ NdbDictionary::Dictionary::dropTable(Table & t){
return m_impl.dropTable(NdbTableImpl::getImpl(t));
}
+int
+NdbDictionary::Dictionary::dropTableGlobal(const Table & t){
+ return m_impl.dropTableGlobal(NdbTableImpl::getImpl(t));
+}
+
int
NdbDictionary::Dictionary::dropTable(const char * name){
return m_impl.dropTable(name);
@@ -1340,6 +1350,14 @@ NdbDictionary::Dictionary::alterTable(const Table & t){
return m_impl.alterTable(NdbTableImpl::getImpl(t));
}
+int
+NdbDictionary::Dictionary::alterTableGlobal(const Table & f,
+ const Table & t)
+{
+ return m_impl.alterTableGlobal(NdbTableImpl::getImpl(f),
+ NdbTableImpl::getImpl(t));
+}
+
const NdbDictionary::Table *
NdbDictionary::Dictionary::getTable(const char * name, void **data) const
{
@@ -1349,6 +1367,40 @@ NdbDictionary::Dictionary::getTable(const char * name, void **data) const
return 0;
}
+const NdbDictionary::Index *
+NdbDictionary::Dictionary::getIndexGlobal(const char * indexName,
+ const Table &ndbtab) const
+{
+ NdbIndexImpl * i = m_impl.getIndexGlobal(indexName,
+ NdbTableImpl::getImpl(ndbtab));
+ if(i)
+ return i->m_facade;
+ return 0;
+}
+
+const NdbDictionary::Table *
+NdbDictionary::Dictionary::getTableGlobal(const char * name) const
+{
+ NdbTableImpl * t = m_impl.getTableGlobal(name);
+ if(t)
+ return t->m_facade;
+ return 0;
+}
+
+int
+NdbDictionary::Dictionary::removeIndexGlobal(const Index &ndbidx,
+ int invalidate) const
+{
+ return m_impl.releaseIndexGlobal(NdbIndexImpl::getImpl(ndbidx), invalidate);
+}
+
+int
+NdbDictionary::Dictionary::removeTableGlobal(const Table &ndbtab,
+ int invalidate) const
+{
+ return m_impl.releaseTableGlobal(NdbTableImpl::getImpl(ndbtab), invalidate);
+}
+
void NdbDictionary::Dictionary::putTable(const NdbDictionary::Table * table)
{
NdbDictionary::Table *copy_table = new NdbDictionary::Table;
@@ -1420,6 +1472,13 @@ NdbDictionary::Dictionary::createIndex(const Index & ind)
return m_impl.createIndex(NdbIndexImpl::getImpl(ind));
}
+int
+NdbDictionary::Dictionary::createIndex(const Index & ind, const Table & tab)
+{
+ return m_impl.createIndex(NdbIndexImpl::getImpl(ind),
+ NdbTableImpl::getImpl(tab));
+}
+
int
NdbDictionary::Dictionary::dropIndex(const char * indexName,
const char * tableName)
@@ -1427,6 +1486,12 @@ NdbDictionary::Dictionary::dropIndex(const char * indexName,
return m_impl.dropIndex(indexName, tableName);
}
+int
+NdbDictionary::Dictionary::dropIndexGlobal(const Index &ind)
+{
+ return m_impl.dropIndexGlobal(NdbIndexImpl::getImpl(ind));
+}
+
const NdbDictionary::Index *
NdbDictionary::Dictionary::getIndex(const char * indexName,
const char * tableName) const
diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index cae7488819e..104d2ffc8bb 100644
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -50,7 +50,14 @@
#define DICT_WAITFOR_TIMEOUT (7*24*60*60*1000)
+#define ERR_RETURN(a,b) \
+{\
+ DBUG_PRINT("exit", ("error %d", (a).code));\
+ DBUG_RETURN(b);\
+}
+
extern Uint64 g_latest_trans_gci;
+int ndb_dictionary_is_mysqld = 0;
bool
is_ndb_blob_table(const char* name, Uint32* ptab_id, Uint32* pcol_no)
@@ -72,18 +79,26 @@ is_ndb_blob_table(const NdbTableImpl* t)
NdbColumnImpl::NdbColumnImpl()
: NdbDictionary::Column(* this), m_attrId(-1), m_facade(this)
{
+ DBUG_ENTER("NdbColumnImpl::NdbColumnImpl");
+ DBUG_PRINT("info", ("this: %p", this));
init();
+ DBUG_VOID_RETURN;
}
NdbColumnImpl::NdbColumnImpl(NdbDictionary::Column & f)
: NdbDictionary::Column(* this), m_attrId(-1), m_facade(&f)
{
+ DBUG_ENTER("NdbColumnImpl::NdbColumnImpl");
+ DBUG_PRINT("info", ("this: %p", this));
init();
+ DBUG_VOID_RETURN;
}
NdbColumnImpl&
NdbColumnImpl::operator=(const NdbColumnImpl& col)
{
+ DBUG_ENTER("NdbColumnImpl::operator=");
+ DBUG_PRINT("info", ("this: %p &col: %p", this, &col));
m_attrId = col.m_attrId;
m_name = col.m_name;
m_type = col.m_type;
@@ -105,13 +120,14 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col)
if (col.m_blobTable == NULL)
m_blobTable = NULL;
else {
- m_blobTable = new NdbTableImpl();
+ if (m_blobTable == NULL)
+ m_blobTable = new NdbTableImpl();
m_blobTable->assign(*col.m_blobTable);
}
m_column_no = col.m_column_no;
// Do not copy m_facade !!
- return *this;
+ DBUG_RETURN(*this);
}
void
@@ -254,15 +270,19 @@ NdbColumnImpl::init(Type t)
NdbColumnImpl::~NdbColumnImpl()
{
+ DBUG_ENTER("NdbColumnImpl::~NdbColumnImpl");
+ DBUG_PRINT("info", ("this: %p", this));
if (m_blobTable != NULL)
delete m_blobTable;
m_blobTable = NULL;
+ DBUG_VOID_RETURN;
}
bool
NdbColumnImpl::equal(const NdbColumnImpl& col) const
{
DBUG_ENTER("NdbColumnImpl::equal");
+ DBUG_PRINT("info", ("this: %p &col: %p", this, &col));
if(strcmp(m_name.c_str(), col.m_name.c_str()) != 0){
DBUG_RETURN(false);
}
@@ -370,24 +390,33 @@ NdbTableImpl::NdbTableImpl()
: NdbDictionary::Table(* this),
NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(this)
{
+ DBUG_ENTER("NdbTableImpl::NdbTableImpl");
+ DBUG_PRINT("info", ("this: %p", this));
init();
+ DBUG_VOID_RETURN;
}
NdbTableImpl::NdbTableImpl(NdbDictionary::Table & f)
: NdbDictionary::Table(* this),
NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(&f)
{
+ DBUG_ENTER("NdbTableImpl::NdbTableImpl");
+ DBUG_PRINT("info", ("this: %p", this));
init();
+ DBUG_VOID_RETURN;
}
NdbTableImpl::~NdbTableImpl()
{
+ DBUG_ENTER("NdbTableImpl::~NdbTableImpl");
+ DBUG_PRINT("info", ("this: %p", this));
if (m_index != 0) {
delete m_index;
m_index = 0;
}
for (unsigned i = 0; i < m_columns.size(); i++)
- delete m_columns[i];
+ delete m_columns[i];
+ DBUG_VOID_RETURN;
}
void
@@ -629,6 +658,8 @@ NdbTableImpl::equal(const NdbTableImpl& obj) const
void
NdbTableImpl::assign(const NdbTableImpl& org)
{
+ DBUG_ENTER("NdbColumnImpl::assign");
+ DBUG_PRINT("info", ("this: %p &org: %p", this, &org));
/* m_changeMask intentionally not copied */
m_primaryTableId = org.m_primaryTableId;
m_internalName.assign(org.m_internalName);
@@ -655,7 +686,14 @@ NdbTableImpl::assign(const NdbTableImpl& org)
m_columnHashMask, m_columnHash, m_hashValueMask, m_hashpointerValue
is state calculated by computeAggregates and buildColumnHash
*/
- for(unsigned i = 0; im_status != NdbDictionary::Object::Invalid);
if (!m_tableImpl)
m_tableImpl = new NdbTableImpl();
// Copy table, since event might be accessed from different threads
m_tableImpl->assign(*tableImpl);
+ DBUG_VOID_RETURN;
}
const NdbDictionary::Table *
@@ -1288,44 +1339,30 @@ NdbDictionaryImpl::~NdbDictionaryImpl()
}
}
-Ndb_local_table_info *
-NdbDictionaryImpl::fetchGlobalTableImpl(const BaseString& internalTableName)
+NdbTableImpl *
+NdbDictionaryImpl::fetchGlobalTableImplRef(const GlobalCacheInitObject &obj)
{
+ DBUG_ENTER("fetchGlobalTableImplRef");
NdbTableImpl *impl;
m_globalHash->lock();
- impl = m_globalHash->get(internalTableName.c_str());
+ impl = m_globalHash->get(obj.m_name.c_str());
m_globalHash->unlock();
if (impl == 0){
- impl = m_receiver.getTable(internalTableName,
+ impl = m_receiver.getTable(obj.m_name.c_str(),
m_ndb.usingFullyQualifiedNames());
- if (impl != 0) {
- int ret = getBlobTables(*impl);
- if (ret != 0) {
- delete impl;
- impl = 0;
- }
+ if (impl != 0 && obj.init(*impl))
+ {
+ delete impl;
+ impl = 0;
}
-
m_globalHash->lock();
- m_globalHash->put(internalTableName.c_str(), impl);
+ m_globalHash->put(obj.m_name.c_str(), impl);
m_globalHash->unlock();
-
- if(impl == 0){
- return 0;
- }
}
- Ndb_local_table_info *info=
- Ndb_local_table_info::create(impl, m_local_table_data_size);
-
- m_localHash.put(internalTableName.c_str(), info);
-
- m_ndb.theFirstTupleId[impl->getTableId()] = ~0;
- m_ndb.theLastTupleId[impl->getTableId()] = ~0;
-
- return info;
+ DBUG_RETURN(impl);
}
void
@@ -2276,18 +2313,30 @@ int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
}
// Alter the table
- int ret = m_receiver.alterTable(m_ndb, impl);
- if(ret == 0){
- // Remove cached information and let it be refreshed at next access
+ int ret = alterTableGlobal(*local->m_table_impl, impl);
+ if(ret == 0)
+ {
m_globalHash->lock();
- local->m_table_impl->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(local->m_table_impl);
+ m_globalHash->release(local->m_table_impl, 1);
m_globalHash->unlock();
m_localHash.drop(originalInternalName);
}
DBUG_RETURN(ret);
}
+int NdbDictionaryImpl::alterTableGlobal(NdbTableImpl &old_impl,
+ NdbTableImpl &impl)
+{
+ DBUG_ENTER("NdbDictionaryImpl::alterTableGlobal");
+ // Alter the table
+ int ret = m_receiver.alterTable(m_ndb, impl);
+ old_impl.m_status = NdbDictionary::Object::Invalid;
+ if(ret == 0){
+ DBUG_RETURN(ret);
+ }
+ ERR_RETURN(getNdbError(), ret);
+}
+
int
NdbDictInterface::alterTable(Ndb & ndb,
NdbTableImpl & impl)
@@ -2731,6 +2780,7 @@ NdbDictionaryImpl::dropTable(const char * name)
{
DBUG_ENTER("NdbDictionaryImpl::dropTable");
DBUG_PRINT("enter",("name: %s", name));
+ ASSERT_NOT_MYSQLD;
NdbTableImpl * tab = getTable(name);
if(tab == 0){
DBUG_RETURN(-1);
@@ -2743,8 +2793,7 @@ NdbDictionaryImpl::dropTable(const char * name)
DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName.c_str()));
m_localHash.drop(internalTableName.c_str());
m_globalHash->lock();
- tab->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(tab);
+ m_globalHash->release(tab, 1);
m_globalHash->unlock();
DBUG_RETURN(dropTable(name));
}
@@ -2792,8 +2841,7 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
m_localHash.drop(internalTableName);
m_globalHash->lock();
- impl.m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(&impl);
+ m_globalHash->release(&impl, 1);
m_globalHash->unlock();
return 0;
@@ -2802,6 +2850,50 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
return ret;
}
+int
+NdbDictionaryImpl::dropTableGlobal(NdbTableImpl & impl)
+{
+ int res;
+ const char * name = impl.getName();
+ DBUG_ENTER("NdbDictionaryImpl::dropTableGlobal");
+ DBUG_ASSERT(impl.m_status != NdbDictionary::Object::New);
+ DBUG_ASSERT(impl.m_indexType == NdbDictionary::Object::TypeUndefined);
+
+ List list;
+ if ((res = listIndexes(list, impl.m_id)) == -1){
+ ERR_RETURN(getNdbError(), -1);
+ }
+ for (unsigned i = 0; i < list.count; i++) {
+ const List::Element& element = list.elements[i];
+ NdbIndexImpl *idx= getIndexGlobal(element.name, impl);
+ if (idx == NULL)
+ {
+ ERR_RETURN(getNdbError(), -1);
+ }
+ if ((res = dropIndexGlobal(*idx)) == -1)
+ {
+ releaseIndexGlobal(*idx, 1);
+ ERR_RETURN(getNdbError(), -1);
+ }
+ releaseIndexGlobal(*idx, 1);
+ }
+
+ if (impl.m_noOfBlobs != 0) {
+ if (dropBlobTables(impl) != 0){
+ ERR_RETURN(getNdbError(), -1);
+ }
+ }
+
+ int ret = m_receiver.dropTable(impl);
+ impl.m_status = NdbDictionary::Object::Invalid;
+ if(ret == 0 || m_error.code == 709 || m_error.code == 723)
+ {
+ DBUG_RETURN(0);
+ }
+
+ ERR_RETURN(getNdbError(), ret);
+}
+
int
NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
{
@@ -2822,7 +2914,7 @@ NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
DBUG_PRINT("info", ("col %s: blob table %s: error %d",
c.m_name.c_str(), bt->m_internalName.c_str(), m_error.code));
if (! (ret == 709 || ret == 723)) // "force" mode on
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
// leave c.m_blobTable defined
}
@@ -2891,8 +2983,7 @@ NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
m_localHash.drop(internalTableName);
m_globalHash->lock();
- impl.m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(&impl);
+ m_globalHash->release(&impl, 1);
m_globalHash->unlock();
DBUG_RETURN(0);
}
@@ -2918,6 +3009,7 @@ NdbIndexImpl*
NdbDictionaryImpl::getIndexImpl(const char * externalName,
const BaseString& internalName)
{
+ ASSERT_NOT_MYSQLD;
Ndb_local_table_info * info = get_local_table_info(internalName);
if(info == 0){
m_error.code = 4243;
@@ -2938,26 +3030,41 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
return 0;
}
+ return getIndexImpl(externalName, internalName, *tab, *prim);
+}
+
+NdbIndexImpl*
+NdbDictionaryImpl::getIndexImpl(const char * externalName,
+ const BaseString& internalName,
+ NdbTableImpl &tab,
+ NdbTableImpl &prim)
+{
+ DBUG_ENTER("NdbDictionaryImpl::getIndexImpl");
+ DBUG_ASSERT(tab.m_indexType != NdbDictionary::Object::TypeUndefined);
/**
* Create index impl
*/
NdbIndexImpl* idx;
- if(NdbDictInterface::create_index_obj_from_table(&idx, tab, prim) == 0){
- idx->m_table = tab;
+ if(NdbDictInterface::create_index_obj_from_table(&idx, &tab, &prim) == 0){
+ idx->m_table = &tab;
idx->m_externalName.assign(externalName);
idx->m_internalName.assign(internalName);
+ idx->m_table_id = prim.getObjectId();
+ idx->m_table_version = prim.getObjectVersion();
// TODO Assign idx to tab->m_index
// Don't do it right now since assign can't asign a table with index
// tab->m_index = idx;
- return idx;
+ DBUG_RETURN(idx);
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
NdbTableImpl* tab,
- const NdbTableImpl* prim){
+ const NdbTableImpl* prim)
+{
+ DBUG_ENTER("NdbDictInterface::create_index_obj_from_table");
NdbIndexImpl *idx = new NdbIndexImpl();
idx->m_version = tab->m_version;
idx->m_status = tab->m_status;
@@ -3010,8 +3117,8 @@ NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
}
* dst = idx;
-
- return 0;
+ DBUG_PRINT("exit", ("m_id: %d m_version: %d", idx->m_id, idx->m_version));
+ DBUG_RETURN(0);
}
/*****************************************************************
@@ -3020,6 +3127,7 @@ NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
int
NdbDictionaryImpl::createIndex(NdbIndexImpl &ix)
{
+ ASSERT_NOT_MYSQLD;
NdbTableImpl* tab = getTable(ix.getTable());
if(tab == 0){
m_error.code = 4249;
@@ -3029,6 +3137,12 @@ NdbDictionaryImpl::createIndex(NdbIndexImpl &ix)
return m_receiver.createIndex(m_ndb, ix, * tab);
}
+int
+NdbDictionaryImpl::createIndex(NdbIndexImpl &ix, NdbTableImpl &tab)
+{
+ return m_receiver.createIndex(m_ndb, ix, tab);
+}
+
int
NdbDictInterface::createIndex(Ndb & ndb,
const NdbIndexImpl & impl,
@@ -3135,6 +3249,7 @@ int
NdbDictionaryImpl::dropIndex(const char * indexName,
const char * tableName)
{
+ ASSERT_NOT_MYSQLD;
NdbIndexImpl * idx = getIndex(indexName, tableName);
if (idx == 0) {
m_error.code = 4243;
@@ -3152,8 +3267,7 @@ NdbDictionaryImpl::dropIndex(const char * indexName,
m_localHash.drop(internalIndexName.c_str());
m_globalHash->lock();
- idx->m_table->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(idx->m_table);
+ m_globalHash->release(idx->m_table, 1);
m_globalHash->unlock();
return dropIndex(indexName, tableName);
}
@@ -3183,13 +3297,13 @@ NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
return dropIndex(indexName, tableName);
}
- int ret = m_receiver.dropIndex(impl, *timpl);
- if(ret == 0){
- m_localHash.drop(internalIndexName.c_str());
+ int ret= dropIndexGlobal(impl);
+ if (ret == 0)
+ {
m_globalHash->lock();
- impl.m_table->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(impl.m_table);
+ m_globalHash->release(impl.m_table, 1);
m_globalHash->unlock();
+ m_localHash.drop(internalIndexName.c_str());
}
return ret;
}
@@ -3198,10 +3312,26 @@ NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
return -1;
}
+int
+NdbDictionaryImpl::dropIndexGlobal(NdbIndexImpl & impl)
+{
+ DBUG_ENTER("NdbDictionaryImpl::dropIndexGlobal");
+ int ret = m_receiver.dropIndex(impl, *impl.m_table);
+ impl.m_status = NdbDictionary::Object::Invalid;
+ if(ret == 0)
+ {
+ DBUG_RETURN(0);
+ }
+ ERR_RETURN(getNdbError(), ret);
+}
+
int
NdbDictInterface::dropIndex(const NdbIndexImpl & impl,
const NdbTableImpl & timpl)
{
+ DBUG_ENTER("NdbDictInterface::dropIndex");
+ DBUG_PRINT("enter", ("indexId: %d indexVersion: %d",
+ timpl.m_id, timpl.m_version));
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_DROP_INDX_REQ;
@@ -3223,9 +3353,9 @@ NdbDictInterface::dropIndex(const NdbIndexImpl & impl,
errCodes);
if(m_error.code == DropIndxRef::InvalidIndexVersion) {
// Clear caches and try again
- return INCOMPATIBLE_VERSION;
+ ERR_RETURN(m_error, INCOMPATIBLE_VERSION);
}
- return r;
+ ERR_RETURN(m_error, r);
}
void
@@ -3262,7 +3392,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
if(tab == 0){
DBUG_PRINT("info",("NdbDictionaryImpl::createEvent: table not found: %s",
evnt.getTableName()));
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
evnt.setTable(tab);
}
@@ -3281,7 +3411,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
ndbout_c("Attr id %u in table %s not found", evnt.m_attrIds[i],
evnt.getTableName());
m_error.code= 4713;
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
}
@@ -3302,7 +3432,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
table.getColumn(evnt.m_columns[i]->m_name.c_str());
if(col == 0){
m_error.code= 4247;
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
// Copy column definition
*evnt.m_columns[i] = *col;
@@ -3328,7 +3458,7 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
for(i = 1; im_attrId == evnt.m_columns[i]->m_attrId) {
m_error.code= 4258;
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
}
@@ -3340,14 +3470,14 @@ NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
// NdbDictInterface m_receiver;
if (m_receiver.createEvent(m_ndb, evnt, 0 /* getFlag unset */) != 0)
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
// Create blob events
if (evnt.m_mergeEvents && createBlobEvents(evnt) != 0) {
int save_code = m_error.code;
(void)dropEvent(evnt.m_name.c_str());
m_error.code = save_code;
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
DBUG_RETURN(0);
}
@@ -3367,7 +3497,7 @@ NdbDictionaryImpl::createBlobEvents(NdbEventImpl& evnt)
NdbEventImpl blob_evnt;
NdbBlob::getBlobEvent(blob_evnt, &evnt, &c);
if (createEvent(blob_evnt) != 0)
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
DBUG_RETURN(0);
}
@@ -3418,7 +3548,7 @@ NdbDictInterface::createEvent(class Ndb & ndb,
const size_t len = strlen(evnt.m_name.c_str()) + 1;
if(len > MAX_TAB_NAME_SIZE) {
m_error.code= 4241;
- DBUG_RETURN(-1);
+ ERR_RETURN(getNdbError(), -1);
}
w.add(SimpleProperties::StringValue, evnt.m_name.c_str());
@@ -3442,7 +3572,7 @@ NdbDictInterface::createEvent(class Ndb & ndb,
0, -1);
if (ret) {
- DBUG_RETURN(ret);
+ ERR_RETURN(getNdbError(), ret);
}
char *dataPtr = (char *)m_buffer.get_data();
@@ -3468,7 +3598,7 @@ NdbDictInterface::createEvent(class Ndb & ndb,
//evnt.m_attrListBitmask != evntConf->getAttrListBitmask() ||
evnt.mi_type != evntConf->getEventType()) {
ndbout_c("ERROR*************");
- DBUG_RETURN(1);
+ ERR_RETURN(getNdbError(), 1);
}
}
@@ -3555,7 +3685,7 @@ NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab)
DBUG_ENTER("NdbDictionaryImpl::getEvent");
DBUG_PRINT("enter",("eventName= %s", eventName));
- NdbEventImpl *ev = new NdbEventImpl();
+ NdbEventImpl *ev = new NdbEventImpl();
if (ev == NULL) {
DBUG_RETURN(NULL);
}
@@ -3569,35 +3699,36 @@ NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab)
DBUG_RETURN(NULL);
}
- if (tab == NULL) {
- // We only have the table name with internal name
- DBUG_PRINT("info",("table %s", ev->getTableName()));
- Ndb_local_table_info *info;
- info= get_local_table_info(ev->getTableName());
- if (info == 0)
+ // We only have the table name with internal name
+ DBUG_PRINT("info",("table %s", ev->getTableName()));
+ if (tab == NULL)
+ {
+ tab= fetchGlobalTableImplRef(InitTable(this, ev->getTableName()));
+ if (tab == 0)
{
DBUG_PRINT("error",("unable to find table %s", ev->getTableName()));
delete ev;
DBUG_RETURN(NULL);
}
- if ((info->m_table_impl->m_status != NdbDictionary::Object::Retrieved) ||
- (info->m_table_impl->m_id != ev->m_table_id) ||
- (table_version_major(info->m_table_impl->m_version) !=
+ if ((tab->m_status != NdbDictionary::Object::Retrieved) ||
+ (tab->m_id != ev->m_table_id) ||
+ (table_version_major(tab->m_version) !=
table_version_major(ev->m_table_version)))
{
- removeCachedObject(*info->m_table_impl);
- info= get_local_table_info(ev->getTableName());
- if (info == 0)
+ DBUG_PRINT("info", ("mismatch on verison in cache"));
+ releaseTableGlobal(*tab, 1);
+ tab= fetchGlobalTableImplRef(InitTable(this, ev->getTableName()));
+ if (tab == 0)
{
DBUG_PRINT("error",("unable to find table %s", ev->getTableName()));
delete ev;
DBUG_RETURN(NULL);
}
}
- tab = info->m_table_impl;
}
ev->setTable(tab);
+
ev->setTable(m_ndb.externalizeTableName(ev->getTableName()));
// get the columns from the attrListBitmask
NdbTableImpl &table = *ev->m_tableImpl;
@@ -3857,6 +3988,7 @@ NdbDictionaryImpl::dropBlobEvents(const NdbEventImpl& evnt)
if (blob_evnt == NULL)
continue;
(void)dropEvent(*blob_evnt);
+ delete blob_evnt;
}
} else {
// loop over MAX_ATTRIBUTES_IN_TABLE ...
diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index 38033e7237b..5a7a1ebb0ab 100644
--- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -35,6 +35,9 @@ is_ndb_blob_table(const char* name, Uint32* ptab_id = 0, Uint32* pcol_no = 0);
bool
is_ndb_blob_table(const class NdbTableImpl* t);
+extern int ndb_dictionary_is_mysqld;
+#define ASSERT_NOT_MYSQLD assert(ndb_dictionary_is_mysqld == 0)
+
class NdbDictObjectImpl {
public:
int m_id;
@@ -253,6 +256,8 @@ public:
BaseString m_internalName;
BaseString m_externalName;
BaseString m_tableName;
+ Uint32 m_table_id;
+ Uint32 m_table_version;
Vector m_columns;
Vector m_key_ids;
@@ -539,6 +544,21 @@ private:
UtilBuffer m_buffer;
};
+class NdbDictionaryImpl;
+class GlobalCacheInitObject
+{
+public:
+ NdbDictionaryImpl *m_dict;
+ const BaseString &m_name;
+ GlobalCacheInitObject(NdbDictionaryImpl *dict,
+ const BaseString &name) :
+ m_dict(dict),
+ m_name(name)
+ {}
+ virtual ~GlobalCacheInitObject() {}
+ virtual int init(NdbTableImpl &tab) const = 0;
+};
+
class NdbDictionaryImpl : public NdbDictionary::Dictionary {
public:
NdbDictionaryImpl(Ndb &ndb);
@@ -558,6 +578,7 @@ public:
int removeCachedObject(NdbTableImpl &);
int createIndex(NdbIndexImpl &ix);
+ int createIndex(NdbIndexImpl &ix, NdbTableImpl & tab);
int dropIndex(const char * indexName,
const char * tableName);
int dropIndex(NdbIndexImpl &, const char * tableName);
@@ -578,6 +599,15 @@ public:
int listObjects(List& list, NdbDictionary::Object::Type type);
int listIndexes(List& list, Uint32 indexId);
+ NdbTableImpl * getTableGlobal(const char * tableName);
+ NdbIndexImpl * getIndexGlobal(const char * indexName,
+ NdbTableImpl &ndbtab);
+ int alterTableGlobal(NdbTableImpl &orig_impl, NdbTableImpl &impl);
+ int dropTableGlobal(NdbTableImpl &);
+ int dropIndexGlobal(NdbIndexImpl & impl);
+ int releaseTableGlobal(NdbTableImpl & impl, int invalidate);
+ int releaseIndexGlobal(NdbIndexImpl & impl, int invalidate);
+
NdbTableImpl * getTable(const char * tableName, void **data= 0);
NdbTableImpl * getBlobTable(const NdbTableImpl&, uint col_no);
NdbTableImpl * getBlobTable(uint tab_id, uint col_no);
@@ -616,10 +646,14 @@ public:
NdbDictInterface m_receiver;
Ndb & m_ndb;
-private:
+ NdbIndexImpl* getIndexImpl(const char * externalName,
+ const BaseString& internalName,
+ NdbTableImpl &tab,
+ NdbTableImpl &prim);
NdbIndexImpl * getIndexImpl(const char * name,
const BaseString& internalName);
- Ndb_local_table_info * fetchGlobalTableImpl(const BaseString& internalName);
+private:
+ NdbTableImpl * fetchGlobalTableImplRef(const GlobalCacheInitObject &obj);
};
inline
@@ -852,6 +886,27 @@ NdbDictionaryImpl::getImpl(const NdbDictionary::Dictionary & t){
* Inline:d getters
*/
+class InitTable : public GlobalCacheInitObject
+{
+public:
+ InitTable(NdbDictionaryImpl *dict,
+ const BaseString &name) :
+ GlobalCacheInitObject(dict, name)
+ {}
+ int init(NdbTableImpl &tab) const
+ {
+ return m_dict->getBlobTables(tab);
+ }
+};
+
+inline
+NdbTableImpl *
+NdbDictionaryImpl::getTableGlobal(const char * table_name)
+{
+ const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
+ return fetchGlobalTableImplRef(InitTable(this, internal_tabname));
+}
+
inline
NdbTableImpl *
NdbDictionaryImpl::getTable(const char * table_name, void **data)
@@ -885,21 +940,134 @@ NdbDictionaryImpl::get_local_table_info(const BaseString& internalTableName)
DBUG_PRINT("enter", ("table: %s", internalTableName.c_str()));
Ndb_local_table_info *info= m_localHash.get(internalTableName.c_str());
- if (info == 0) {
- info= fetchGlobalTableImpl(internalTableName);
- if (info == 0) {
- DBUG_RETURN(0);
+ if (info == 0)
+ {
+ NdbTableImpl *tab=
+ fetchGlobalTableImplRef(InitTable(this, internalTableName));
+ if (tab)
+ {
+ info= Ndb_local_table_info::create(tab, m_local_table_data_size);
+ if (info)
+ {
+ m_localHash.put(internalTableName.c_str(), info);
+ m_ndb.theFirstTupleId[tab->getTableId()] = ~0;
+ m_ndb.theLastTupleId[tab->getTableId()] = ~0;
+ }
}
}
DBUG_RETURN(info); // autoincrement already initialized
}
+class InitIndexGlobal : public GlobalCacheInitObject
+{
+public:
+ const char *m_index_name;
+ NdbTableImpl &m_prim;
+
+ InitIndexGlobal(NdbDictionaryImpl *dict,
+ const BaseString &internal_indexname,
+ const char *index_name,
+ NdbTableImpl &prim) :
+ GlobalCacheInitObject(dict, internal_indexname),
+ m_index_name(index_name),
+ m_prim(prim)
+ {}
+ int init(NdbTableImpl &tab) const
+ {
+ tab.m_index= m_dict->getIndexImpl(m_index_name, m_name, tab, m_prim);
+ if (tab.m_index == 0)
+ return 1;
+ tab.m_index->m_table= &tab;
+ return 0;
+ }
+};
+
+class InitIndex : public GlobalCacheInitObject
+{
+public:
+ const char *m_index_name;
+
+ InitIndex(NdbDictionaryImpl *dict,
+ const BaseString &internal_indexname,
+ const char *index_name) :
+ GlobalCacheInitObject(dict, internal_indexname),
+ m_index_name(index_name)
+ {}
+ int init(NdbTableImpl &tab) const
+ {
+ DBUG_ASSERT(tab.m_index == 0);
+ tab.m_index= m_dict->getIndexImpl(m_index_name, m_name);
+ if (tab.m_index)
+ {
+ tab.m_index->m_table= &tab;
+ return 0;
+ }
+ return 1;
+ }
+};
+
+inline
+NdbIndexImpl *
+NdbDictionaryImpl::getIndexGlobal(const char * index_name,
+ NdbTableImpl &ndbtab)
+{
+ DBUG_ENTER("NdbDictionaryImpl::getIndexGlobal");
+ const BaseString
+ internal_indexname(m_ndb.internalize_index_name(&ndbtab, index_name));
+ int retry= 2;
+
+ while (retry)
+ {
+ NdbTableImpl *tab=
+ fetchGlobalTableImplRef(InitIndexGlobal(this, internal_indexname,
+ index_name, ndbtab));
+ if (tab)
+ {
+ // tab->m_index sould be set. otherwise tab == 0
+ NdbIndexImpl *idx= tab->m_index;
+ if (idx->m_table_id != ndbtab.getObjectId() ||
+ idx->m_table_version != ndbtab.getObjectVersion())
+ {
+ releaseIndexGlobal(*idx, 1);
+ retry--;
+ continue;
+ }
+ DBUG_RETURN(idx);
+ }
+ break;
+ }
+ m_error.code= 4243;
+ DBUG_RETURN(0);
+}
+
+inline int
+NdbDictionaryImpl::releaseTableGlobal(NdbTableImpl & impl, int invalidate)
+{
+ DBUG_ENTER("NdbDictionaryImpl::releaseTableGlobal");
+ DBUG_PRINT("enter", ("internal_name: %s", impl.m_internalName.c_str()));
+ m_globalHash->lock();
+ m_globalHash->release(&impl, invalidate);
+ m_globalHash->unlock();
+ DBUG_RETURN(0);
+}
+
+inline int
+NdbDictionaryImpl::releaseIndexGlobal(NdbIndexImpl & impl, int invalidate)
+{
+ DBUG_ENTER("NdbDictionaryImpl::releaseIndexGlobal");
+ DBUG_PRINT("enter", ("internal_name: %s", impl.m_internalName.c_str()));
+ m_globalHash->lock();
+ m_globalHash->release(impl.m_table, invalidate);
+ m_globalHash->unlock();
+ DBUG_RETURN(0);
+}
+
inline
NdbIndexImpl *
NdbDictionaryImpl::getIndex(const char * index_name,
const char * table_name)
{
- if (table_name || m_ndb.usingFullyQualifiedNames())
+ while (table_name || m_ndb.usingFullyQualifiedNames())
{
const BaseString internal_indexname(
(table_name)
@@ -910,18 +1078,28 @@ NdbDictionaryImpl::getIndex(const char * index_name,
if (internal_indexname.length())
{
- Ndb_local_table_info * info=
- get_local_table_info(internal_indexname);
- if (info)
+ Ndb_local_table_info *info= m_localHash.get(internal_indexname.c_str());
+ NdbTableImpl *tab;
+ if (info == 0)
{
- NdbTableImpl * tab= info->m_table_impl;
- if (tab->m_index == 0)
- tab->m_index= getIndexImpl(index_name, internal_indexname);
- if (tab->m_index != 0)
- tab->m_index->m_table= tab;
- return tab->m_index;
+ tab= fetchGlobalTableImplRef(InitIndex(this, internal_indexname,
+ index_name));
+ if (tab)
+ {
+ info= Ndb_local_table_info::create(tab, 0);
+ if (info)
+ m_localHash.put(internal_indexname.c_str(), info);
+ else
+ break;
+ }
+ else
+ break;
}
+ else
+ tab= info->m_table_impl;
+ return tab->m_index;
}
+ break;
}
m_error.code= 4243;
diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
index 070a3baa686..628ad5d925f 100644
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.cpp
@@ -70,21 +70,6 @@ print_std(const SubTableData * sdata, LinearSectionPtr ptr[3])
*
*/
-//#define EVENT_DEBUG
-#ifdef EVENT_DEBUG
-#define DBUG_ENTER_EVENT(A) DBUG_ENTER(A)
-#define DBUG_RETURN_EVENT(A) DBUG_RETURN(A)
-#define DBUG_VOID_RETURN_EVENT DBUG_VOID_RETURN
-#define DBUG_PRINT_EVENT(A,B) DBUG_PRINT(A,B)
-#define DBUG_DUMP_EVENT(A,B,C) DBUG_DUMP(A,B,C)
-#else
-#define DBUG_ENTER_EVENT(A)
-#define DBUG_RETURN_EVENT(A) return(A)
-#define DBUG_VOID_RETURN_EVENT return
-#define DBUG_PRINT_EVENT(A,B)
-#define DBUG_DUMP_EVENT(A,B,C)
-#endif
-
// todo handle several ndb objects
// todo free allocated data when closing NdbEventBuffer
@@ -189,6 +174,17 @@ NdbEventOperationImpl::~NdbEventOperationImpl()
// m_bufferHandle->dropSubscribeEvent(m_bufferId);
; // ToDo? We should send stop signal here
+ if (theMainOp == NULL)
+ {
+ NdbEventOperationImpl* tBlobOp = theBlobOpList;
+ while (tBlobOp != NULL)
+ {
+ NdbEventOperationImpl *op = tBlobOp;
+ tBlobOp = tBlobOp->m_next;
+ delete op;
+ }
+ }
+
m_ndb->theImpl->theNdbObjectIdMap.unmap(m_oid, this);
DBUG_PRINT("exit",("this: %p/%p oid: %u main: %p",
this, m_facade, m_oid, theMainOp));
@@ -966,7 +962,22 @@ NdbEventBuffer::NdbEventBuffer(Ndb *ndb) :
NdbEventBuffer::~NdbEventBuffer()
{
// todo lock? what if receive thread writes here?
- for (unsigned j= 0; j < m_allocated_data.size(); j++)
+ NdbEventOperationImpl* op= m_dropped_ev_op;
+ while ((op = m_dropped_ev_op))
+ {
+ m_dropped_ev_op = m_dropped_ev_op->m_next;
+ delete op->m_facade;
+ }
+
+ unsigned j;
+ Uint32 sz= m_active_gci.size();
+ Gci_container* array = (Gci_container*)m_active_gci.getBase();
+ for(j = 0; j < sz; j++)
+ {
+ array[j].~Gci_container();
+ }
+
+ for (j= 0; j < m_allocated_data.size(); j++)
{
unsigned sz= m_allocated_data[j]->sz;
EventBufData *data= m_allocated_data[j]->data;
@@ -1469,6 +1480,7 @@ NdbEventBuffer::report_node_failure(Uint32 node_id)
data.req_nodeid = (Uint8)node_id;
data.ndbd_nodeid = (Uint8)node_id;
data.logType = SubTableData::LOG;
+ data.gci = m_latestGCI + 1;
/**
* Insert this event for each operation
*/
@@ -1485,8 +1497,11 @@ NdbEventBuffer::report_node_failure(Uint32 node_id)
void
NdbEventBuffer::completeClusterFailed()
{
- DBUG_ENTER("NdbEventBuffer::completeClusterFailed");
+ NdbEventOperation* op= m_ndb->getEventOperation(0);
+ if (op == 0)
+ return;
+ DBUG_ENTER("NdbEventBuffer::completeClusterFailed");
SubTableData data;
LinearSectionPtr ptr[3];
bzero(&data, sizeof(data));
@@ -1495,73 +1510,66 @@ NdbEventBuffer::completeClusterFailed()
data.tableId = ~0;
data.operation = NdbDictionary::Event::_TE_CLUSTER_FAILURE;
data.logType = SubTableData::LOG;
-
- /**
- * Find min not completed GCI
- */
- Uint32 sz= m_active_gci.size();
- Uint64 gci= ~0;
- Gci_container* bucket = 0;
- Gci_container* array = (Gci_container*)m_active_gci.getBase();
- for(Uint32 i = 0; im_gci;
- }
- }
-
- if(bucket == 0)
- {
- /**
- * Did not find any not completed GCI's
- * lets fake one...
- */
- gci = m_latestGCI + 1;
- bucket = array + ( gci & ACTIVE_GCI_MASK );
- bucket->m_gcp_complete_rep_count = 1;
- }
-
- const Uint32 cnt= bucket->m_gcp_complete_rep_count = 1;
-
- /**
- * Release all GCI's
- */
- for(Uint32 i = 0; im_data.is_empty())
- {
- free_list(tmp->m_data);
-#if 0
- m_free_data_count++;
- EventBufData* loop= tmp->m_head;
- while(loop != tmp->m_tail)
- {
- m_free_data_count++;
- loop = loop->m_next;
- }
-#endif
- }
- bzero(tmp, sizeof(Gci_container));
- }
-
- bucket->m_gci = gci;
- bucket->m_gcp_complete_rep_count = cnt;
-
- data.gci = gci;
+ data.gci = m_latestGCI + 1;
/**
* Insert this event for each operation
*/
- NdbEventOperation* op= 0;
- while((op = m_ndb->getEventOperation(op)))
+ do
{
NdbEventOperationImpl* impl= &op->m_impl;
data.senderData = impl->m_oid;
- insertDataL(impl, &data, ptr);
+ insertDataL(impl, &data, ptr);
+ } while((op = m_ndb->getEventOperation(op)));
+
+ /**
+ * Release all GCI's with m_gci > gci
+ */
+ Uint32 i;
+ Uint32 sz= m_active_gci.size();
+ Uint64 gci= data.gci;
+ Gci_container* bucket = 0;
+ Gci_container* array = (Gci_container*)m_active_gci.getBase();
+ for(i = 0; i < sz; i++)
+ {
+ Gci_container* tmp = array + i;
+ if (tmp->m_gci > gci)
+ {
+ if(!tmp->m_data.is_empty())
+ {
+ free_list(tmp->m_data);
+ }
+ tmp->~Gci_container();
+ bzero(tmp, sizeof(Gci_container));
+ }
+ else if (tmp->m_gcp_complete_rep_count)
+ {
+ if (tmp->m_gci == gci)
+ {
+ bucket= tmp;
+ continue;
+ }
+ // we have found an old not-completed gci
+ // something is wrong, assert in debug, but try so salvage
+ // in release
+ ndbout_c("out of order bucket detected at cluster disconnect, "
+ "data.gci: %u. tmp->m_gci: %u",
+ (unsigned)data.gci, (unsigned)tmp->m_gci);
+ assert(false);
+ if(!tmp->m_data.is_empty())
+ {
+ free_list(tmp->m_data);
+ }
+ tmp->~Gci_container();
+ bzero(tmp, sizeof(Gci_container));
+ }
}
+
+ assert(bucket != 0);
+
+ const Uint32 cnt= bucket->m_gcp_complete_rep_count = 1;
+ bucket->m_gci = gci;
+ bucket->m_gcp_complete_rep_count = cnt;
/**
* And finally complete this GCI
@@ -2255,8 +2263,12 @@ EventBufData_list::add_gci_op(Gci_op g, bool del)
if (m_gci_op_alloc != 0) {
Uint32 bytes = m_gci_op_alloc * sizeof(Gci_op);
memcpy(m_gci_op_list, old_list, bytes);
+ DBUG_PRINT_EVENT("info", ("this: %p delete m_gci_op_list: %p",
+ this, old_list));
delete [] old_list;
}
+ DBUG_PRINT_EVENT("info", ("this: %p new m_gci_op_list: %p",
+ this, m_gci_op_list));
m_gci_op_alloc = n;
}
assert(m_gci_op_count < m_gci_op_alloc);
@@ -2268,6 +2280,9 @@ EventBufData_list::add_gci_op(Gci_op g, bool del)
void
EventBufData_list::move_gci_ops(EventBufData_list *list, Uint64 gci)
{
+ DBUG_ENTER_EVENT("EventBufData_list::move_gci_ops");
+ DBUG_PRINT_EVENT("info", ("this: %p list: %p gci: %llu",
+ this, list, gci));
assert(!m_is_not_multi_list);
if (!list->m_is_not_multi_list)
{
@@ -2283,6 +2298,8 @@ EventBufData_list::move_gci_ops(EventBufData_list *list, Uint64 gci)
}
{
Gci_ops *new_gci_ops = new Gci_ops;
+ DBUG_PRINT_EVENT("info", ("this: %p m_gci_op_list: %p",
+ new_gci_ops, list->m_gci_op_list));
if (m_gci_ops_list_tail)
m_gci_ops_list_tail->m_next = new_gci_ops;
else
@@ -2301,6 +2318,7 @@ end:
list->m_gci_op_list = 0;
list->m_gci_ops_list_tail = 0;
list->m_gci_op_alloc = 0;
+ DBUG_VOID_RETURN_EVENT;
}
NdbEventOperation*
diff --git a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
index 8d413cc8d14..70b3ce6b8de 100644
--- a/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
+++ b/storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp
@@ -25,6 +25,20 @@
#include
#define NDB_EVENT_OP_MAGIC_NUMBER 0xA9F301B4
+//#define EVENT_DEBUG
+#ifdef EVENT_DEBUG
+#define DBUG_ENTER_EVENT(A) DBUG_ENTER(A)
+#define DBUG_RETURN_EVENT(A) DBUG_RETURN(A)
+#define DBUG_VOID_RETURN_EVENT DBUG_VOID_RETURN
+#define DBUG_PRINT_EVENT(A,B) DBUG_PRINT(A,B)
+#define DBUG_DUMP_EVENT(A,B,C) DBUG_DUMP(A,B,C)
+#else
+#define DBUG_ENTER_EVENT(A)
+#define DBUG_RETURN_EVENT(A) return(A)
+#define DBUG_VOID_RETURN_EVENT return
+#define DBUG_PRINT_EVENT(A,B)
+#define DBUG_DUMP_EVENT(A,B,C)
+#endif
class NdbEventOperationImpl;
@@ -149,19 +163,29 @@ EventBufData_list::EventBufData_list()
m_gci_ops_list_tail(0),
m_gci_op_alloc(0)
{
+ DBUG_ENTER_EVENT("EventBufData_list::EventBufData_list");
+ DBUG_PRINT_EVENT("info", ("this: %p", this));
+ DBUG_VOID_RETURN_EVENT;
}
inline
EventBufData_list::~EventBufData_list()
{
+ DBUG_ENTER_EVENT("EventBufData_list::~EventBufData_list");
+ DBUG_PRINT_EVENT("info", ("this: %p m_is_not_multi_list: %u",
+ this, m_is_not_multi_list));
if (m_is_not_multi_list)
+ {
+ DBUG_PRINT_EVENT("info", ("delete m_gci_op_list: %p", m_gci_op_list));
delete [] m_gci_op_list;
+ }
else
{
Gci_ops *op = first_gci_ops();
while (op)
op = next_gci_ops();
}
+ DBUG_VOID_RETURN_EVENT;
}
inline
@@ -223,7 +247,11 @@ EventBufData_list::next_gci_ops()
Gci_ops *first = m_gci_ops_list;
m_gci_ops_list = first->m_next;
if (first->m_gci_op_list)
+ {
+ DBUG_PRINT_EVENT("info", ("this: %p delete m_gci_op_list: %p",
+ this, first->m_gci_op_list));
delete [] first->m_gci_op_list;
+ }
delete first;
if (m_gci_ops_list == 0)
m_gci_ops_list_tail = 0;
diff --git a/storage/ndb/src/ndbapi/NdbIndexStat.cpp b/storage/ndb/src/ndbapi/NdbIndexStat.cpp
index 8740b80a81d..e490290b6a2 100644
--- a/storage/ndb/src/ndbapi/NdbIndexStat.cpp
+++ b/storage/ndb/src/ndbapi/NdbIndexStat.cpp
@@ -377,7 +377,7 @@ NdbIndexStat::stat_select(const Uint32* key1, Uint32 keylen1, const Uint32* key2
}
int
-NdbIndexStat::records_in_range(NdbDictionary::Index* index, NdbIndexScanOperation* op, Uint64 table_rows, Uint64* count, int flags)
+NdbIndexStat::records_in_range(const NdbDictionary::Index* index, NdbIndexScanOperation* op, Uint64 table_rows, Uint64* count, int flags)
{
DBUG_ENTER("NdbIndexStat::records_in_range");
Uint64 rows;
diff --git a/storage/ndb/src/ndbapi/Ndbinit.cpp b/storage/ndb/src/ndbapi/Ndbinit.cpp
index b502ec27b9d..e41380e6484 100644
--- a/storage/ndb/src/ndbapi/Ndbinit.cpp
+++ b/storage/ndb/src/ndbapi/Ndbinit.cpp
@@ -99,6 +99,7 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
for (i = 0; i < MAX_NDB_NODES ; i++) {
theConnectionArray[i] = NULL;
}//forg
+ m_sys_tab_0 = NULL;
for (i = 0; i < 2048 ; i++) {
theFirstTupleId[i] = 0;
theLastTupleId[i] = 0;
@@ -137,6 +138,9 @@ Ndb::~Ndb()
DBUG_ENTER("Ndb::~Ndb()");
DBUG_PRINT("enter",("this=0x%x",this));
+ if (m_sys_tab_0)
+ getDictionary()->removeTableGlobal(*m_sys_tab_0, 0);
+
assert(theImpl->m_ev_op == 0); // user should return NdbEventOperation's
for (NdbEventOperationImpl *op= theImpl->m_ev_op; op; op=op->m_next)
{
diff --git a/storage/ndb/test/ndbapi/testBlobs.cpp b/storage/ndb/test/ndbapi/testBlobs.cpp
index a1b0c89652e..bf9a8b1bce9 100644
--- a/storage/ndb/test/ndbapi/testBlobs.cpp
+++ b/storage/ndb/test/ndbapi/testBlobs.cpp
@@ -44,6 +44,7 @@ struct Opt {
bool m_dbg;
bool m_dbgall;
const char* m_dbug;
+ bool m_fac;
bool m_full;
unsigned m_loop;
unsigned m_parts;
@@ -72,6 +73,7 @@ struct Opt {
m_dbg(false),
m_dbgall(false),
m_dbug(0),
+ m_fac(false),
m_full(false),
m_loop(1),
m_parts(10),
@@ -110,6 +112,7 @@ printusage()
<< " -dbg print debug" << endl
<< " -dbgall print also NDB API debug (if compiled in)" << endl
<< " -dbug opt dbug options" << endl
+ << " -fac fetch across commit in scan delete [" << d.m_fac << "]" << endl
<< " -full read/write only full blob values" << endl
<< " -loop N loop N times 0=forever [" << d.m_loop << "]" << endl
<< " -parts N max parts in blob value [" << d.m_parts << "]" << endl
@@ -1255,23 +1258,11 @@ deleteScan(bool idx)
CHK((ret = g_ops->nextResult(false)) == 0 || ret == 1 || ret == 2);
if (++n == g_opt.m_batch || ret == 2) {
DBG("execute batch: n=" << n << " ret=" << ret);
- switch (0) {
- case 0: // works normally
+ if (! g_opt.m_fac) {
CHK(g_con->execute(NoCommit) == 0);
- CHK(true || g_con->restart() == 0);
- break;
- case 1: // nonsense - g_con is invalid for 2nd batch
- CHK(g_con->execute(Commit) == 0);
- CHK(true || g_con->restart() == 0);
- break;
- case 2: // DBTC sendSignalErrorRefuseLab
- CHK(g_con->execute(NoCommit) == 0);
- CHK(g_con->restart() == 0);
- break;
- case 3: // 266 time-out
+ } else {
CHK(g_con->execute(Commit) == 0);
CHK(g_con->restart() == 0);
- break;
}
n = 0;
}
@@ -1817,6 +1808,10 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
continue;
}
}
+ if (strcmp(arg, "-fac") == 0) {
+ g_opt.m_fac = true;
+ continue;
+ }
if (strcmp(arg, "-full") == 0) {
g_opt.m_full = true;
continue;
diff --git a/storage/ndb/test/ndbapi/testDict.cpp b/storage/ndb/test/ndbapi/testDict.cpp
index 0176db8d4fd..7ade359342d 100644
--- a/storage/ndb/test/ndbapi/testDict.cpp
+++ b/storage/ndb/test/ndbapi/testDict.cpp
@@ -109,7 +109,7 @@ int runCreateTheTable(NDBT_Context* ctx, NDBT_Step* step){
const NdbDictionary::Table* pTab = ctx->getTab();
// Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
+ if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
return NDBT_FAILED;
}
@@ -151,7 +151,7 @@ int runCreateTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
}
// Try to create table in db
- if (pTab->createTableInDb(pNdb) == 0){
+ if (NDBT_Tables::createTable(pNdb, pTab->getName()) == 0){
result = NDBT_FAILED;
}
@@ -203,7 +203,7 @@ int runCreateAndDrop(NDBT_Context* ctx, NDBT_Step* step){
ndbout << i << ": ";
// Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
+ if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
return NDBT_FAILED;
}
@@ -254,7 +254,8 @@ int runCreateAndDropWithData(NDBT_Context* ctx, NDBT_Step* step){
while (i < loops){
ndbout << i << ": ";
// Try to create table in db
- if (pTab->createTableInDb(pNdb) != 0){
+
+ if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
return NDBT_FAILED;
}
@@ -336,7 +337,7 @@ int runCreateAndDropDuring(NDBT_Context* ctx, NDBT_Step* step){
Ndb* pNdb = GETNDB(step);
g_debug << "Creating table" << endl;
- if (pTab->createTableInDb(pNdb) != 0){
+ if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
g_err << "createTableInDb failed" << endl;
result = NDBT_FAILED;
continue;
@@ -357,7 +358,6 @@ int runCreateAndDropDuring(NDBT_Context* ctx, NDBT_Step* step){
g_debug << "Dropping table" << endl;
-
if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
g_err << "Failed to drop "<getName()<<" in db" << endl;
result = NDBT_FAILED;
diff --git a/storage/ndb/tools/delete_all.cpp b/storage/ndb/tools/delete_all.cpp
index feedded06ad..fcf9b425bd0 100644
--- a/storage/ndb/tools/delete_all.cpp
+++ b/storage/ndb/tools/delete_all.cpp
@@ -23,17 +23,21 @@
#include
static int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
- bool commit_across_open_cursor, int parallelism=240);
+ bool fetch_across_commit, int parallelism=240);
NDB_STD_OPTS_VARS;
static const char* _dbname = "TEST_DB";
+static my_bool _transactional = false;
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_desc"),
{ "database", 'd', "Name of database table is in",
(gptr*) &_dbname, (gptr*) &_dbname, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "transactional", 't', "Single transaction (may run out of operations)",
+ (gptr*) &_transactional, (gptr*) &_transactional, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
static void usage()
@@ -84,18 +88,11 @@ int main(int argc, char** argv){
ndbout << " Table " << argv[i] << " does not exist!" << endl;
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- // Check if we have any blobs
- bool commit_across_open_cursor = true;
- for (int j = 0; j < pTab->getNoOfColumns(); j++) {
- NdbDictionary::Column::Type t = pTab->getColumn(j)->getType();
- if (t == NdbDictionary::Column::Blob ||
- t == NdbDictionary::Column::Text) {
- commit_across_open_cursor = false;
- break;
- }
- }
- ndbout << "Deleting all from " << argv[i] << "...";
- if(clear_table(&MyNdb, pTab, commit_across_open_cursor) == NDBT_FAILED){
+ ndbout << "Deleting all from " << argv[i];
+ if (! _transactional)
+ ndbout << " (non-transactional)";
+ ndbout << " ...";
+ if(clear_table(&MyNdb, pTab, ! _transactional) == NDBT_FAILED){
res = NDBT_FAILED;
ndbout << "FAILED" << endl;
}
@@ -105,7 +102,7 @@ int main(int argc, char** argv){
int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
- bool commit_across_open_cursor, int parallelism)
+ bool fetch_across_commit, int parallelism)
{
// Scan all records exclusive and delete
// them one by one
@@ -136,7 +133,7 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
}
goto failed;
}
-
+
pOp = pTrans->getNdbScanOperation(pTab->getName());
if (pOp == NULL) {
goto failed;
@@ -167,7 +164,7 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
} while((check = pOp->nextResult(false)) == 0);
if(check != -1){
- if (commit_across_open_cursor) {
+ if (fetch_across_commit) {
check = pTrans->execute(NdbTransaction::Commit);
pTrans->restart(); // new tx id
} else {
@@ -198,7 +195,7 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
}
goto failed;
}
- if (! commit_across_open_cursor &&
+ if (! fetch_across_commit &&
pTrans->execute(NdbTransaction::Commit) != 0) {
err = pTrans->getNdbError();
goto failed;
diff --git a/storage/ndb/tools/listTables.cpp b/storage/ndb/tools/listTables.cpp
index ef51b66bb10..a221156280d 100644
--- a/storage/ndb/tools/listTables.cpp
+++ b/storage/ndb/tools/listTables.cpp
@@ -188,6 +188,8 @@ list(const char * tabname,
ndbout_c("%-5d %-20s %-8s %-7s %s", elt.id, type, state, store, elt.name);
}
}
+ if (_parsable)
+ exit(0);
}
NDB_STD_OPTS_VARS;
diff --git a/strings/CHARSET_INFO.txt b/strings/CHARSET_INFO.txt
index f7a10f95880..40f171440a4 100644
--- a/strings/CHARSET_INFO.txt
+++ b/strings/CHARSET_INFO.txt
@@ -172,7 +172,7 @@ mb_wc - converts the left multibyte sequence into it Unicode code.
mc_mb - converts the given Unicode code into multibyte sequence.
-Case and sort convertion
+Case and sort conversion
------------------------
caseup_str - converts the given 0-terminated string into the upper case
casedn_str - converts the given 0-terminated string into the lower case
@@ -227,4 +227,4 @@ hash_sort() - calculates hash value taking in account
the collation rules, e.g. case-insensitivity,
accent sensitivity, etc.
-
\ No newline at end of file
+
diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c
index 0e036c2bbcd..e4302f50c58 100644
--- a/strings/my_vsnprintf.c
+++ b/strings/my_vsnprintf.c
@@ -27,6 +27,7 @@
%#[l]d
%#[l]u
%#[l]x
+ %#.#b Local format; note first # is ignored and second is REQUIRED
%#.#s Note first # is ignored
RETURN
@@ -40,7 +41,7 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
for (; *fmt ; fmt++)
{
- if (fmt[0] != '%')
+ if (*fmt != '%')
{
if (to == end) /* End of buffer */
break;
@@ -95,6 +96,16 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
to=strnmov(to,par,plen);
continue;
}
+ else if (*fmt == 'b') /* Buffer parameter */
+ {
+ char *par = va_arg(ap, char *);
+ DBUG_ASSERT(to <= end);
+ if (to + abs(width) + 1 > end)
+ width= end - to - 1; /* sign doesn't matter */
+ memmove(to, par, abs(width));
+ to+= width;
+ continue;
+ }
else if (*fmt == 'd' || *fmt == 'u'|| *fmt== 'x') /* Integer parameter */
{
register long larg;
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 2c55cfcf319..c57496e6c55 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -636,6 +636,7 @@ fi
%attr(755, root, root) %{_bindir}/ndb_desc
%attr(755, root, root) %{_bindir}/ndb_show_tables
%attr(755, root, root) %{_bindir}/ndb_test_platform
+%attr(755, root, root) %{_bindir}/ndb_config
%files ndb-extra
%defattr(-,root,root,0755)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ba0a7ad73d0..4cad3c30bdd 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -43,7 +43,7 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
LIBS = @CLIENT_LIBS@
LDADD = @CLIENT_EXTRA_LDFLAGS@ \
$(top_builddir)/libmysql/libmysqlclient.la
-mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS)
+mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) -L../mysys -lmysys
mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix)
insert_test_SOURCES= insert_test.c $(yassl_dummy_link_fix)
select_test_SOURCES= select_test.c $(yassl_dummy_link_fix)
diff --git a/tests/cmakelists.txt b/tests/cmakelists.txt
index c9b0b8735a2..46c42d461f3 100644
--- a/tests/cmakelists.txt
+++ b/tests/cmakelists.txt
@@ -6,4 +6,4 @@ ADD_DEFINITIONS("-DMYSQL_CLIENT")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
ADD_EXECUTABLE(mysql_client_test mysql_client_test.c)
-TARGET_LINK_LIBRARIES(mysql_client_test dbug mysqlclient yassl taocrypt zlib wsock32)
+TARGET_LINK_LIBRARIES(mysql_client_test dbug mysys mysqlclient yassl taocrypt zlib wsock32)
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 5730efced35..d927b27ab37 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -14839,6 +14839,73 @@ static void test_bug15613()
myquery(rc);
mysql_stmt_close(stmt);
}
+
+/*
+ Bug#17667: An attacker has the opportunity to bypass query logging.
+*/
+static void test_bug17667()
+{
+ int rc;
+ struct buffer_and_length {
+ const char *buffer;
+ const uint length;
+ } statements[]= {
+ { "drop table if exists bug17667", 29 },
+ { "create table bug17667 (c varchar(20))", 37 },
+ { "insert into bug17667 (c) values ('regular') /* NUL=\0 with comment */", 68 },
+ { "insert into bug17667 (c) values ('NUL=\0 in value')", 50 },
+ { "insert into bug17667 (c) values ('5 NULs=\0\0\0\0\0')", 48 },
+ { "/* NUL=\0 with comment */ insert into bug17667 (c) values ('encore')", 67 },
+ { "drop table bug17667", 19 },
+ { NULL, 0 } };
+
+ struct buffer_and_length *statement_cursor;
+ FILE *log_file;
+
+ myheader("test_bug17667");
+
+ for (statement_cursor= statements; statement_cursor->buffer != NULL;
+ statement_cursor++) {
+ rc= mysql_real_query(mysql, statement_cursor->buffer,
+ statement_cursor->length);
+ myquery(rc);
+ }
+
+ sleep(1); /* The server may need time to flush the data to the log. */
+ log_file= fopen("var/log/master.log", "r");
+ if (log_file != NULL) {
+
+ for (statement_cursor= statements; statement_cursor->buffer != NULL;
+ statement_cursor++) {
+ char line_buffer[MAX_TEST_QUERY_LENGTH*2];
+ /* more than enough room for the query and some marginalia. */
+
+ do {
+ memset(line_buffer, '/', MAX_TEST_QUERY_LENGTH*2);
+
+ DIE_UNLESS(fgets(line_buffer, MAX_TEST_QUERY_LENGTH*2, log_file) !=
+ NULL);
+ /* If we reach EOF before finishing the statement list, then we failed. */
+
+ } while (my_memmem(line_buffer, MAX_TEST_QUERY_LENGTH*2,
+ statement_cursor->buffer, statement_cursor->length) == NULL);
+ }
+
+ printf("success. All queries found intact in the log.\n");
+
+ } else {
+ fprintf(stderr, "Could not find the log file, var/log/master.log, so "
+ "test_bug17667 is \ninconclusive. Run test from the "
+ "mysql-test/mysql-test-run* program \nto set up the correct "
+ "environment for this test.\n\n");
+ }
+
+ if (log_file != NULL)
+ fclose(log_file);
+
+}
+
+
/*
Bug#14169: type of group_concat() result changed to blob if tmp_table was used
*/
@@ -15139,6 +15206,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug16144", test_bug16144 },
{ "test_bug15613", test_bug15613 },
{ "test_bug14169", test_bug14169 },
+ { "test_bug17667", test_bug17667 },
{ 0, 0 }
};
diff --git a/unittest/examples/no_plan.t.c b/unittest/examples/no_plan.t.c
index 67029c7962f..98e4d06def6 100644
--- a/unittest/examples/no_plan.t.c
+++ b/unittest/examples/no_plan.t.c
@@ -1,4 +1,6 @@
+#include "my_config.h"
+
#include
#include
diff --git a/unittest/examples/skip_all.t.c b/unittest/examples/skip_all.t.c
index bbde6b63f1c..19b8c1fddaf 100644
--- a/unittest/examples/skip_all.t.c
+++ b/unittest/examples/skip_all.t.c
@@ -1,4 +1,6 @@
+#include "my_config.h"
+
#include
#include
diff --git a/unittest/examples/todo.t.c b/unittest/examples/todo.t.c
index 13a0c950b54..82601bee41c 100644
--- a/unittest/examples/todo.t.c
+++ b/unittest/examples/todo.t.c
@@ -1,4 +1,6 @@
+#include "my_config.h"
+
#include
#include
diff --git a/unittest/mytap/t/basic.t.c b/unittest/mytap/t/basic.t.c
index eb820d6c651..95a77755347 100644
--- a/unittest/mytap/t/basic.t.c
+++ b/unittest/mytap/t/basic.t.c
@@ -1,4 +1,6 @@
+#include "my_config.h"
+
#include
#include
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 4ee27f1e491..002874caf58 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -296,7 +296,7 @@ ctor_failure:
TODO:
Add option --verify to mysqld to be able to change verification mode
*/
-struct st_VioSSLAcceptorFd*
+struct st_VioSSLAcceptorFd *
new_VioSSLAcceptorFd(const char *key_file,
const char *cert_file,
const char *ca_file,
@@ -387,4 +387,12 @@ ctor_failure:
my_free((gptr) ptr,MYF(0));
DBUG_RETURN(0);
}
+
+
+void free_vio_ssl_acceptor_fd(struct st_VioSSLAcceptorFd *fd)
+{
+ SSL_CTX_free(fd->ssl_context);
+ my_free((gptr) fd, MYF(0));
+}
+
#endif /* HAVE_OPENSSL */