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 */