summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/.cvsignore14
-rw-r--r--[-rwxr-xr-x]client/CMakeLists.txt103
-rw-r--r--client/Makefile.am125
-rw-r--r--client/async_example.c216
-rw-r--r--client/client_priv.h51
-rw-r--r--client/completion_hash.cc7
-rw-r--r--client/get_password.c4
-rw-r--r--client/my_readline.h5
-rw-r--r--client/mysql.cc346
-rw-r--r--client/mysql_plugin.c1206
-rw-r--r--client/mysql_upgrade.c63
-rw-r--r--client/mysqladmin.cc131
-rw-r--r--client/mysqlbinlog.cc185
-rw-r--r--client/mysqlcheck.c302
-rw-r--r--client/mysqldump.c711
-rw-r--r--client/mysqlimport.c70
-rw-r--r--client/mysqlshow.c43
-rw-r--r--client/mysqlslap.c89
-rw-r--r--client/mysqltest.cc1735
-rw-r--r--client/readline.cc8
-rw-r--r--client/sql_string.cc.dontuse (renamed from client/sql_string.cc)92
-rw-r--r--client/sql_string.h.dontuse (renamed from client/sql_string.h)33
22 files changed, 3927 insertions, 1612 deletions
diff --git a/client/.cvsignore b/client/.cvsignore
deleted file mode 100644
index 54bbaed97f5..00000000000
--- a/client/.cvsignore
+++ /dev/null
@@ -1,14 +0,0 @@
-.deps
-.libs
-Makefile
-Makefile.in
-insert_test
-mysql
-mysql-test
-mysql_test
-mysqladmin
-mysqldump
-mysqlimport
-mysqlshow
-select_test
-thread_test
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 2d51bc3fd0f..e4507f9c8ba 100755..100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -1,5 +1,4 @@
-# Copyright (c) 2006-2008 MySQL AB, 2009 Sun Microsystems, Inc.
-# Use is subject to license terms.
+# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
#
# 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
@@ -12,63 +11,75 @@
#
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-# We use the "mysqlclient" library here just as safety, in case
-# any of the clients here would go beyond the client API and access the
-# Thread Local Storage directly.
+INCLUDE_DIRECTORIES(
+ ${CMAKE_SOURCE_DIR}/include
+ ${ZLIB_INCLUDE_DIR}
+ ${SSL_INCLUDE_DIRS}
+ ${CMAKE_SOURCE_DIR}/libmysql
+ ${CMAKE_SOURCE_DIR}/regex
+ ${CMAKE_SOURCE_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/strings
+ ${MY_READLINE_INCLUDE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+ADD_DEFINITIONS(${SSL_DEFINES})
+MYSQL_ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc
+ ${CMAKE_SOURCE_DIR}/sql/sql_string.cc)
+TARGET_LINK_LIBRARIES(mysql mysqlclient)
+IF(UNIX)
+ TARGET_LINK_LIBRARIES(mysql ${MY_READLINE_LIBRARY})
+ SET_TARGET_PROPERTIES(mysql PROPERTIES ENABLE_EXPORTS TRUE)
+ENDIF(UNIX)
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
- ${CMAKE_SOURCE_DIR}/zlib
- ${CMAKE_SOURCE_DIR}/extra/yassl/include
- ${CMAKE_SOURCE_DIR}/libmysql
- ${CMAKE_SOURCE_DIR}/regex
- ${CMAKE_SOURCE_DIR}/sql
- ${CMAKE_SOURCE_DIR}/strings
- ${CMAKE_CURRENT_BINARY_DIR})
-
-MYSQL_ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc ../mysys/my_conio.c DESTINATION bin)
-TARGET_LINK_LIBRARIES(mysql mysqlclient wsock32)
-
-MYSQL_ADD_EXECUTABLE(mysqltest mysqltest.cc DESTINATION bin)
+MYSQL_ADD_EXECUTABLE(mysqltest mysqltest.cc COMPONENT Test)
SET_SOURCE_FILES_PROPERTIES(mysqltest.cc PROPERTIES COMPILE_FLAGS "-DTHREADS")
-TARGET_LINK_LIBRARIES(mysqltest mysqlclient mysys regex wsock32 dbug)
+TARGET_LINK_LIBRARIES(mysqltest mysqlclient regex)
+SET_TARGET_PROPERTIES(mysqltest PROPERTIES ENABLE_EXPORTS TRUE)
-MYSQL_ADD_EXECUTABLE(mysqlcheck mysqlcheck.c DESTINATION bin)
-TARGET_LINK_LIBRARIES(mysqlcheck mysqlclient wsock32)
-MYSQL_ADD_EXECUTABLE(mysqldump mysqldump.c ../sql-common/my_user.c ../mysys/mf_getdate.c DESTINATION bin)
-TARGET_LINK_LIBRARIES(mysqldump mysqlclient wsock32)
+MYSQL_ADD_EXECUTABLE(mysqlcheck mysqlcheck.c)
+TARGET_LINK_LIBRARIES(mysqlcheck mysqlclient)
-MYSQL_ADD_EXECUTABLE(mysqlimport mysqlimport.c DESTINATION bin)
-TARGET_LINK_LIBRARIES(mysqlimport mysqlclient wsock32)
+MYSQL_ADD_EXECUTABLE(mysqldump mysqldump.c ../sql-common/my_user.c)
+TARGET_LINK_LIBRARIES(mysqldump mysqlclient)
-MYSQL_ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c DESTINATION bin)
-TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient wsock32)
+MYSQL_ADD_EXECUTABLE(mysqlimport mysqlimport.c)
+TARGET_LINK_LIBRARIES(mysqlimport mysqlclient)
+
+MYSQL_ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c COMPONENT Server)
+TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient)
ADD_DEPENDENCIES(mysql_upgrade GenFixPrivs)
-MYSQL_ADD_EXECUTABLE(mysqlshow mysqlshow.c DESTINATION bin)
-TARGET_LINK_LIBRARIES(mysqlshow mysqlclient wsock32)
+MYSQL_ADD_EXECUTABLE(mysqlshow mysqlshow.c)
+TARGET_LINK_LIBRARIES(mysqlshow mysqlclient)
+
+MYSQL_ADD_EXECUTABLE(mysql_plugin mysql_plugin.c)
+TARGET_LINK_LIBRARIES(mysql_plugin mysqlclient)
-MYSQL_ADD_EXECUTABLE(mysqlbinlog mysqlbinlog.cc
- ../mysys/mf_tempdir.c
- ../mysys/my_new.cc
- ../mysys/my_bit.c
- ../mysys/my_bitmap.c
- ../mysys/my_vle.c
- ../mysys/base64.c
- ../mysys/checksum.c
- DESTINATION bin)
-TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient wsock32)
+MYSQL_ADD_EXECUTABLE(mysqlbinlog mysqlbinlog.cc)
+TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient)
-MYSQL_ADD_EXECUTABLE(mysqladmin mysqladmin.cc DESTINATION bin)
-TARGET_LINK_LIBRARIES(mysqladmin mysqlclient wsock32)
+MYSQL_ADD_EXECUTABLE(mysqladmin mysqladmin.cc)
+TARGET_LINK_LIBRARIES(mysqladmin mysqlclient)
-MYSQL_ADD_EXECUTABLE(mysqlslap mysqlslap.c DESTINATION bin)
+MYSQL_ADD_EXECUTABLE(mysqlslap mysqlslap.c)
SET_SOURCE_FILES_PROPERTIES(mysqlslap.c PROPERTIES COMPILE_FLAGS "-DTHREADS")
-TARGET_LINK_LIBRARIES(mysqlslap mysqlclient mysys zlib wsock32 dbug)
+TARGET_LINK_LIBRARIES(mysqlslap mysqlclient)
+
+# "WIN32" also covers 64 bit. "echo" is used in some files below "mysql-test/".
+IF(WIN32)
+ MYSQL_ADD_EXECUTABLE(echo echo.c COMPONENT Junk)
+ENDIF(WIN32)
+
+# async_example is just a code example, do not install it.
+ADD_EXECUTABLE(async_example async_example.c)
+TARGET_LINK_LIBRARIES(async_example mysqlclient)
+
+SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap mysql_plugin
+PROPERTIES HAS_CXX TRUE)
+ADD_DEFINITIONS(-DHAVE_DLOPEN)
-MYSQL_ADD_EXECUTABLE(echo echo.c COMPONENT Test)
diff --git a/client/Makefile.am b/client/Makefile.am
deleted file mode 100644
index f8a0a3f7139..00000000000
--- a/client/Makefile.am
+++ /dev/null
@@ -1,125 +0,0 @@
-# Copyright (c) 2000, 2011, Oracle and/or its affiliates
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-# This file is public domain and comes with NO WARRANTY of any kind
-
-if THREAD_SAFE_CLIENT
-LIBMYSQLCLIENT_LA = $(top_builddir)/libmysql_r/libmysqlclient_r.la
-else
-LIBMYSQLCLIENT_LA = $(top_builddir)/libmysql/libmysqlclient.la
-endif
-
-INCLUDES = -I$(top_builddir)/include \
- -I$(top_srcdir)/include \
- -I$(top_srcdir)/regex \
- @ZLIB_INCLUDES@ \
- $(openssl_includes)
-
-LIBS = @CLIENT_LIBS@
-
-LDADD= @CLIENT_EXTRA_LDFLAGS@ $(CLIENT_THREAD_LIBS) \
- $(top_builddir)/libmysql/libmysqlclient.la
-
-noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \
- client_priv.h
-
-EXTRA_DIST = get_password.c CMakeLists.txt echo.c
-
-BUILT_SOURCES = link_sources
-
-CLEANFILES = $(BUILT_SOURCES)
-
-bin_PROGRAMS = mysql \
- mysqladmin \
- mysqlbinlog \
- mysqlcheck \
- mysqldump \
- mysqlimport \
- mysqlshow \
- mysqlslap \
- mysqltest \
- mysql_upgrade
-
-mysql_SOURCES = mysql.cc readline.cc sql_string.cc \
- completion_hash.cc
-mysql_LDADD = @readline_link@ @TERMCAP_LIB@ \
- $(LDADD) $(CXXLDFLAGS)
-mysqladmin_SOURCES = mysqladmin.cc
-
-mysqlbinlog_SOURCES = mysqlbinlog.cc \
- $(top_srcdir)/mysys/mf_tempdir.c \
- $(top_srcdir)/mysys/my_new.cc \
- $(top_srcdir)/mysys/my_bit.c \
- $(top_srcdir)/mysys/my_bitmap.c \
- $(top_srcdir)/mysys/my_vle.c \
- $(top_srcdir)/mysys/base64.c \
- $(top_srcdir)/mysys/checksum.c
-mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS)
-
-mysqldump_SOURCES= mysqldump.c \
- my_user.c \
- $(top_srcdir)/mysys/mf_getdate.c
-
-mysqlimport_SOURCES= mysqlimport.c
-mysqlimport_CFLAGS= -DTHREAD -UUNDEF_THREADS_HACK
-mysqlimport_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
- @CLIENT_EXTRA_LDFLAGS@ \
- $(LIBMYSQLCLIENT_LA)
-
-mysqlshow_SOURCES= mysqlshow.c
-
-mysqlslap_SOURCES= mysqlslap.c
-mysqlslap_CFLAGS= -DTHREAD -UMYSQL_CLIENT_NO_THREADS
-mysqlslap_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
- @CLIENT_EXTRA_LDFLAGS@ \
- $(LIBMYSQLCLIENT_LA)
-
-mysqltest_SOURCES= mysqltest.cc
-mysqltest_CXXFLAGS= -DTHREAD -UMYSQL_CLIENT_NO_THREADS
-mysqltest_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
- @CLIENT_EXTRA_LDFLAGS@ \
- $(top_builddir)/mysys/libmysys.a \
- $(LIBMYSQLCLIENT_LA) \
- $(top_builddir)/regex/libregex.la
-
-mysql_upgrade_SOURCES= mysql_upgrade.c \
- $(top_srcdir)/mysys/my_getpagesize.c
-
-# Fix for mit-threads
-DEFS = -DMYSQL_CLIENT_NO_THREADS \
- -DDEFAULT_MYSQL_HOME='"$(prefix)"' \
- -DMYSQL_DATADIR='"$(localstatedir)"'
-
-sql_src=log_event.h mysql_priv.h rpl_constants.h \
- rpl_utility.h rpl_tblmap.h rpl_tblmap.cc \
- log_event.cc my_decimal.h my_decimal.cc \
- log_event_old.h log_event_old.cc \
- rpl_record_old.h rpl_record_old.cc \
- rpl_utility.h rpl_utility.cc \
- sql_list.h rpl_filter.h sql_list.cc rpl_filter.cc
-strings_src=decimal.c strings_def.h
-
-link_sources:
- for f in $(sql_src) ; do \
- rm -f $$f; \
- @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \
- done; \
- for f in $(strings_src) ; do \
- rm -f $$f; \
- @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \
- done; \
- rm -f my_user.c; \
- @LN_CP_F@ $(top_srcdir)/sql-common/my_user.c my_user.c;
- echo timestamp > link_sources;
diff --git a/client/async_example.c b/client/async_example.c
new file mode 100644
index 00000000000..ccb60950904
--- /dev/null
+++ b/client/async_example.c
@@ -0,0 +1,216 @@
+/*
+ Copyright 2011 Kristian Nielsen and Monty Program Ab.
+
+ This file is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef __WIN__
+#include <poll.h>
+#else
+#include <WinSock2.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <mysql.h>
+
+#define SL(s) (s), sizeof(s)
+
+static const char *my_groups[]= { "client", NULL };
+
+static int
+wait_for_mysql(MYSQL *mysql, int status)
+{
+#ifdef __WIN__
+ fd_set rs, ws, es;
+ int res;
+ struct timeval tv, *timeout;
+ my_socket s= mysql_get_socket(mysql);
+ FD_ZERO(&rs);
+ FD_ZERO(&ws);
+ FD_ZERO(&es);
+ if (status & MYSQL_WAIT_READ)
+ FD_SET(s, &rs);
+ if (status & MYSQL_WAIT_WRITE)
+ FD_SET(s, &ws);
+ if (status & MYSQL_WAIT_EXCEPT)
+ FD_SET(s, &es);
+ if (status & MYSQL_WAIT_TIMEOUT)
+ {
+ tv.tv_sec= mysql_get_timeout_value(mysql);
+ tv.tv_usec= 0;
+ timeout= &tv;
+ }
+ else
+ timeout= NULL;
+ res= select(1, &rs, &ws, &es, timeout);
+ if (res == 0)
+ return MYSQL_WAIT_TIMEOUT;
+ else if (res == SOCKET_ERROR)
+ {
+ /*
+ In a real event framework, we should handle errors and re-try the select.
+ */
+ return MYSQL_WAIT_TIMEOUT;
+ }
+ else
+ {
+ int status= 0;
+ if (FD_ISSET(s, &rs))
+ status|= MYSQL_WAIT_READ;
+ if (FD_ISSET(s, &ws))
+ status|= MYSQL_WAIT_WRITE;
+ if (FD_ISSET(s, &es))
+ status|= MYSQL_WAIT_EXCEPT;
+ return status;
+ }
+#else
+ struct pollfd pfd;
+ int timeout;
+ int res;
+
+ pfd.fd= mysql_get_socket(mysql);
+ pfd.events=
+ (status & MYSQL_WAIT_READ ? POLLIN : 0) |
+ (status & MYSQL_WAIT_WRITE ? POLLOUT : 0) |
+ (status & MYSQL_WAIT_EXCEPT ? POLLPRI : 0);
+ if (status & MYSQL_WAIT_TIMEOUT)
+ timeout= 1000*mysql_get_timeout_value(mysql);
+ else
+ timeout= -1;
+ res= poll(&pfd, 1, timeout);
+ if (res == 0)
+ return MYSQL_WAIT_TIMEOUT;
+ else if (res < 0)
+ {
+ /*
+ In a real event framework, we should handle EINTR and re-try the poll.
+ */
+ return MYSQL_WAIT_TIMEOUT;
+ }
+ else
+ {
+ int status= 0;
+ if (pfd.revents & POLLIN)
+ status|= MYSQL_WAIT_READ;
+ if (pfd.revents & POLLOUT)
+ status|= MYSQL_WAIT_WRITE;
+ if (pfd.revents & POLLPRI)
+ status|= MYSQL_WAIT_EXCEPT;
+ return status;
+ }
+#endif
+}
+
+static void
+fatal(MYSQL *mysql, const char *msg)
+{
+ fprintf(stderr, "%s: %s\n", msg, mysql_error(mysql));
+ exit(1);
+}
+
+static void
+doit(const char *host, const char *user, const char *password)
+{
+ int err;
+ MYSQL mysql, *ret;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int status;
+
+ mysql_init(&mysql);
+ mysql_options(&mysql, MYSQL_OPT_NONBLOCK, 0);
+ mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "myapp");
+
+ /* Returns 0 when done, else flag for what to wait for when need to block. */
+ status= mysql_real_connect_start(&ret, &mysql, host, user, password, NULL,
+ 0, NULL, 0);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_real_connect_cont(&ret, &mysql, status);
+ }
+
+ if (!ret)
+ fatal(&mysql, "Failed to mysql_real_connect()");
+
+ status= mysql_real_query_start(&err, &mysql, SL("SHOW STATUS"));
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_real_query_cont(&err, &mysql, status);
+ }
+ if (err)
+ fatal(&mysql, "mysql_real_query() returns error");
+
+ /* This method cannot block. */
+ res= mysql_use_result(&mysql);
+ if (!res)
+ fatal(&mysql, "mysql_use_result() returns error");
+
+ for (;;)
+ {
+ status= mysql_fetch_row_start(&row, res);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_fetch_row_cont(&row, res, status);
+ }
+ if (!row)
+ break;
+ printf("%s: %s\n", row[0], row[1]);
+ }
+ if (mysql_errno(&mysql))
+ fatal(&mysql, "Got error while retrieving rows");
+ mysql_free_result(res);
+
+ /*
+ mysql_close() sends a COM_QUIT packet, and so in principle could block
+ waiting for the socket to accept the data.
+ In practise, for many applications it will probably be fine to use the
+ blocking mysql_close().
+ */
+ status= mysql_close_start(&mysql);
+ while (status)
+ {
+ status= wait_for_mysql(&mysql, status);
+ status= mysql_close_cont(&mysql, status);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ int err;
+
+ if (argc != 4)
+ {
+ fprintf(stderr, "Usage: %s <host> <user> <password>\n", argv[0]);
+ exit(1);
+ }
+
+ err= mysql_library_init(argc, argv, (char **)my_groups);
+ if (err)
+ {
+ fprintf(stderr, "Fatal: mysql_library_init() returns error: %d\n", err);
+ exit(1);
+ }
+
+ doit(argv[1], argv[2], argv[3]);
+
+ mysql_library_end();
+
+ return 0;
+}
diff --git a/client/client_priv.h b/client/client_priv.h
index d948fb7f98f..607bd3997c1 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -21,7 +21,6 @@
#include <my_sys.h>
#include <m_string.h>
#include <mysql.h>
-#include <mysql_embed.h>
#include <errmsg.h>
#include <my_getopt.h>
@@ -33,19 +32,10 @@
# endif
#endif
-/* Version numbers for deprecation messages */
-#define VER_CELOSIA "5.6"
-
-#define WARN_DEPRECATED(Ver,Old,New) \
- do { \
- printf("Warning: The option '%s' is deprecated and will be removed " \
- "in a future release. Please use %s instead.\n", (Old), (New)); \
- } while(0);
-
enum options_client
{
OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET,
- OPT_PAGER, OPT_NOPAGER, OPT_TEE, OPT_NOTEE,
+ OPT_PAGER, OPT_TEE,
OPT_LOW_PRIORITY, OPT_AUTO_REPAIR, OPT_COMPRESS,
OPT_DROP, OPT_LOCKS, OPT_KEYWORDS, OPT_DELAYED, OPT_OPTIMIZE,
OPT_FTB, OPT_LTB, OPT_ENC, OPT_O_ENC, OPT_ESC, OPT_TABLES,
@@ -60,12 +50,9 @@ enum options_client
OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION,
OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH,
OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_SERVER_ARG,
- OPT_POSITION, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME,
+ OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME,
OPT_SIGINT_IGNORE, OPT_HEXBLOB, OPT_ORDER_BY_PRIMARY, OPT_COUNT,
OPT_FLUSH_TABLES,
-#ifdef HAVE_NDBCLUSTER_DB
- OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING,
-#endif
OPT_TRIGGERS,
OPT_MYSQL_ONLY_PRINT,
OPT_MYSQL_LOCK_DIRECTORY,
@@ -73,7 +60,10 @@ enum options_client
OPT_IMPORT_USE_THREADS,
OPT_MYSQL_NUMBER_OF_QUERY,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
- OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_CREATE_SLAP_SCHEMA,
+ OPT_TZ_UTC, OPT_CREATE_SLAP_SCHEMA,
+ OPT_MYSQLDUMP_SLAVE_APPLY,
+ OPT_MYSQLDUMP_SLAVE_DATA,
+ OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT,
OPT_SLAP_CSV, OPT_SLAP_CREATE_STRING,
OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE, OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
@@ -91,15 +81,36 @@ enum options_client
OPT_SLAP_NO_DROP,
OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT_MODE, OPT_SERVER_ID,
OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT,
+ OPT_AUTO_VERTICAL_OUTPUT,
OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE,
OPT_WRITE_BINLOG, OPT_DUMP_DATE,
+ OPT_INIT_COMMAND,
+ OPT_PLUGIN_DIR,
+ OPT_DEFAULT_AUTH,
OPT_ABORT_SOURCE_ON_ERROR,
- OPT_FIRST_SLAVE,
- OPT_ALL,
OPT_REWRITE_DB,
- OPT_PLUGIN_DIR,
- OPT_DEFAULT_PLUGIN,
OPT_REPORT_PROGRESS,
OPT_SKIP_ANNOTATE_ROWS_EVENTS,
OPT_MAX_CLIENT_OPTION /* should be always the last */
};
+
+/**
+ First mysql version supporting the information schema.
+*/
+#define FIRST_INFORMATION_SCHEMA_VERSION 50003
+
+/**
+ Name of the information schema database.
+*/
+#define INFORMATION_SCHEMA_DB_NAME "information_schema"
+
+/**
+ First mysql version supporting the performance schema.
+*/
+#define FIRST_PERFORMANCE_SCHEMA_VERSION 50503
+
+/**
+ Name of the performance schema database.
+*/
+#define PERFORMANCE_SCHEMA_DB_NAME "performance_schema"
+
diff --git a/client/completion_hash.cc b/client/completion_hash.cc
index cd0ea17dfaf..9ffb2082c06 100644
--- a/client/completion_hash.cc
+++ b/client/completion_hash.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,7 +11,7 @@
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 */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/* Quick & light hash implementation for tab completion purposes
*
@@ -22,7 +22,6 @@
#include <my_global.h>
#include <m_string.h>
-#undef SAFEMALLOC // Speed things up
#include <my_sys.h>
#include "completion_hash.h"
@@ -213,7 +212,7 @@ void completion_hash_clean(HashTable *ht)
void completion_hash_free(HashTable *ht)
{
completion_hash_clean(ht);
- my_free(ht->arBuckets, MYF(0));
+ my_free(ht->arBuckets);
}
diff --git a/client/get_password.c b/client/get_password.c
index c6653183f48..09d307b5553 100644
--- a/client/get_password.c
+++ b/client/get_password.c
@@ -23,10 +23,6 @@
#include <m_string.h>
#include <m_ctype.h>
-#if defined(HAVE_BROKEN_GETPASS) && !defined(HAVE_GETPASSPHRASE)
-#undef HAVE_GETPASS
-#endif
-
#ifdef HAVE_GETPASS
#ifdef HAVE_PWD_H
#include <pwd.h>
diff --git a/client/my_readline.h b/client/my_readline.h
index 30e59b613bc..11ace987b44 100644
--- a/client/my_readline.h
+++ b/client/my_readline.h
@@ -1,3 +1,6 @@
+#ifndef CLIENT_MY_READLINE_INCLUDED
+#define CLIENT_MY_READLINE_INCLUDED
+
/*
Copyright (c) 2000, 2011, Oracle and/or its affiliates
@@ -35,3 +38,5 @@ extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file);
extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char * str);
extern char *batch_readline(LINE_BUFFER *buffer);
extern void batch_readline_end(LINE_BUFFER *buffer);
+
+#endif /* CLIENT_MY_READLINE_INCLUDED */
diff --git a/client/mysql.cc b/client/mysql.cc
index a811bacdab0..67878b36227 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -15,10 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#define COPYRIGHT_NOTICE "\
-This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
-and you are welcome to modify and redistribute it under the GPL v2 license\n"
-
/* mysql command tool
* Commands compatible with mSQL by David J. Hughes
*
@@ -60,11 +56,6 @@ static char *server_version= NULL;
/* Array of options to pass to libemysqld */
#define MAX_SERVER_ARGS 64
-/* Version numbers for deprecation messages */
-#define VER_CELOSIA "5.6"
-
-void* sql_alloc(unsigned size); // Don't use mysqld alloc for these
-void sql_element_free(void *ptr);
#include "sql_string.h"
extern "C" {
@@ -97,9 +88,10 @@ extern "C" {
#undef bcmp // Fix problem with new readline
#if defined(__WIN__)
#include <conio.h>
-#elif !defined(__NETWARE__)
+#else
#include <readline/readline.h>
#define HAVE_READLINE
+#define USE_POPEN
#endif
}
@@ -108,16 +100,12 @@ extern "C" {
#define vidattr(A) {} // Can't get this to work
#endif
-#ifdef FN_NO_CASE_SENCE
+#ifdef FN_NO_CASE_SENSE
#define cmp_database(cs,A,B) my_strcasecmp((cs), (A), (B))
#else
#define cmp_database(cs,A,B) strcmp((A),(B))
#endif
-#if !defined(__WIN__) && !defined(__NETWARE__) && !defined(THREAD)
-#define USE_POPEN
-#endif
-
#include "completion_hash.h"
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
@@ -150,8 +138,9 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
vertical=0, line_numbers=1, column_names=1,opt_html=0,
opt_xml=0,opt_nopager=1, opt_outfile=0, named_cmds= 0,
tty_password= 0, opt_nobeep=0, opt_reconnect=1,
- default_charset_used= 0, opt_secure_auth= 0,
+ opt_secure_auth= 0,
default_pager_set= 0, opt_sigint_ignore= 0,
+ auto_vertical_output= 0,
show_warnings= 0, executing_query= 0,
ignore_spaces= 0, opt_progress_reports;
static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error;
@@ -166,7 +155,8 @@ static int connect_flag=CLIENT_INTERACTIVE;
static int interrupted_query= 0;
static char *current_host,*current_db,*current_user=0,*opt_password=0,
*current_prompt=0, *delimiter_str= 0,
- *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
+ *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME,
+ *opt_init_command= 0;
static char *histfile;
static char *histfile_tmp;
static String glob_buffer,old_buffer;
@@ -176,7 +166,7 @@ static int wait_time = 5;
static STATUS status;
static ulong select_limit,max_join_size,opt_connect_timeout=0;
static char mysql_charsets_dir[FN_REFLEN+1];
-static char *opt_plugin_dir= 0, *opt_default_auth;
+static char *opt_plugin_dir= 0, *opt_default_auth= 0;
static const char *xmlmeta[] = {
"&", "&amp;",
"<", "&lt;",
@@ -196,6 +186,7 @@ static MEM_ROOT hash_mem_root;
static uint prompt_counter;
static char delimiter[16]= DEFAULT_DELIMITER;
static uint delimiter_length= 1;
+unsigned short terminal_width= 80;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
@@ -249,6 +240,8 @@ static const char* construct_prompt();
static char *get_arg(char *line, my_bool get_next_arg);
static void init_username();
static void add_int_to_prompt(int toadd);
+static int get_result_width(MYSQL_RES *res);
+static int get_field_disp_length(MYSQL_FIELD * field);
#ifndef EMBEDDED_LIBRARY
static uint last_progress_report_length= 0;
static void report_progress(const MYSQL *mysql, uint stage, uint max_stage,
@@ -471,7 +464,6 @@ static COMMANDS commands[] = {
{ "FORCE", 0, 0, 0, ""},
{ "FOREIGN", 0, 0, 0, ""},
{ "FOUND", 0, 0, 0, ""},
- { "FRAC_SECOND", 0, 0, 0, ""},
{ "FROM", 0, 0, 0, ""},
{ "FULL", 0, 0, 0, ""},
{ "FULLTEXT", 0, 0, 0, ""},
@@ -640,10 +632,6 @@ static COMMANDS commands[] = {
{ "QUARTER", 0, 0, 0, ""},
{ "QUERY", 0, 0, 0, ""},
{ "QUICK", 0, 0, 0, ""},
- { "RAID0", 0, 0, 0, ""},
- { "RAID_CHUNKS", 0, 0, 0, ""},
- { "RAID_CHUNKSIZE", 0, 0, 0, ""},
- { "RAID_TYPE", 0, 0, 0, ""},
{ "READ", 0, 0, 0, ""},
{ "READS", 0, 0, 0, ""},
{ "REAL", 0, 0, 0, ""},
@@ -716,7 +704,6 @@ static COMMANDS commands[] = {
{ "SQL_NO_CACHE", 0, 0, 0, ""},
{ "SQL_SMALL_RESULT", 0, 0, 0, ""},
{ "SQL_THREAD", 0, 0, 0, ""},
- { "SQL_TSI_FRAC_SECOND", 0, 0, 0, ""},
{ "SQL_TSI_SECOND", 0, 0, 0, ""},
{ "SQL_TSI_MINUTE", 0, 0, 0, ""},
{ "SQL_TSI_HOUR", 0, 0, 0, ""},
@@ -907,6 +894,7 @@ static COMMANDS commands[] = {
{ "LAST_INSERT_ID", 0, 0, 0, ""},
{ "ISSIMPLE", 0, 0, 0, ""},
{ "LAST_DAY", 0, 0, 0, ""},
+ { "LAST_VALUE", 0, 0, 0, ""},
{ "LCASE", 0, 0, 0, ""},
{ "LEAST", 0, 0, 0, ""},
{ "LENGTH", 0, 0, 0, ""},
@@ -1084,6 +1072,10 @@ static void mysql_end_timer(ulong start_time,char *buff);
static void nice_time(double sec,char *buff,bool part_second);
extern "C" sig_handler mysql_end(int sig);
extern "C" sig_handler handle_sigint(int sig);
+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
+static sig_handler window_resize(int sig);
+#endif
+
int main(int argc,char *argv[])
{
@@ -1134,7 +1126,11 @@ int main(int argc,char *argv[])
close(stdout_fileno_copy); /* Clean up dup(). */
}
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ {
+ my_end(0);
+ exit(1);
+ }
defaults_argv=argv;
if (get_options(argc, (char **) argv))
{
@@ -1166,8 +1162,8 @@ int main(int argc,char *argv[])
if (sql_connect(current_host,current_db,current_user,opt_password,
opt_silent))
{
- quick=1; // Avoid history
- status.exit_status=1;
+ quick= 1; // Avoid history
+ status.exit_status= 1;
mysql_end(-1);
}
if (!status.batch)
@@ -1179,6 +1175,13 @@ int main(int argc,char *argv[])
signal(SIGINT, handle_sigint); // Catch SIGINT to clean up
signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up
+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
+ /* Readline will call this if it installs a handler */
+ signal(SIGWINCH, window_resize);
+ /* call the SIGWINCH handler to get the default term width */
+ window_resize(0);
+#endif
+
put_info("Welcome to the MariaDB monitor. Commands end with ; or \\g.",
INFO_INFO);
sprintf((char*) glob_buffer.ptr(),
@@ -1208,7 +1211,7 @@ int main(int argc,char *argv[])
strncmp(link_name, "/dev/null", 10) == 0)
{
/* The .mysql_history file is a symlink to /dev/null, don't use it */
- my_free(histfile, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(histfile);
histfile= 0;
}
}
@@ -1269,23 +1272,23 @@ sig_handler mysql_end(int sig)
glob_buffer.free();
old_buffer.free();
processed_prompt.free();
- my_free(server_version,MYF(MY_ALLOW_ZERO_PTR));
- my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
- my_free(opt_mysql_unix_port,MYF(MY_ALLOW_ZERO_PTR));
- my_free(histfile,MYF(MY_ALLOW_ZERO_PTR));
- my_free(histfile_tmp,MYF(MY_ALLOW_ZERO_PTR));
- my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
- my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
- my_free(current_user,MYF(MY_ALLOW_ZERO_PTR));
- my_free(full_username,MYF(MY_ALLOW_ZERO_PTR));
- my_free(part_username,MYF(MY_ALLOW_ZERO_PTR));
- my_free(default_prompt,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(server_version);
+ my_free(opt_password);
+ my_free(opt_mysql_unix_port);
+ my_free(histfile);
+ my_free(histfile_tmp);
+ my_free(current_db);
+ my_free(current_host);
+ my_free(current_user);
+ my_free(full_username);
+ my_free(part_username);
+ my_free(default_prompt);
#ifdef HAVE_SMEM
- my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(shared_memory_base_name);
#endif
- my_free(current_prompt,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(current_prompt);
while (embedded_server_arg_count > 1)
- my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
+ my_free(embedded_server_args[--embedded_server_arg_count]);
mysql_server_end();
free_defaults(defaults_argv);
my_end(my_end_arg);
@@ -1357,6 +1360,16 @@ err:
}
+#if defined(HAVE_TERMIOS_H) && defined(GWINSZ_IN_SYS_IOCTL)
+sig_handler window_resize(int sig)
+{
+ struct winsize window_size;
+
+ if (ioctl(fileno(stdin), TIOCGWINSZ, &window_size) == 0)
+ terminal_width= window_size.ws_col;
+}
+#endif
+
static struct my_option my_long_options[] =
{
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
@@ -1367,10 +1380,6 @@ static struct my_option my_long_options[] =
"Abort 'source filename' operations in case of errors",
&batch_abort_on_error, &batch_abort_on_error, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-#ifdef __NETWARE__
- {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
{"auto-rehash", OPT_AUTO_REHASH,
"Enable automatic rehashing. One doesn't need to use 'rehash' to get table "
"and field completion, but startup and reconnecting may take a longer time. "
@@ -1382,6 +1391,11 @@ static struct my_option my_long_options[] =
"completion. This gives a quicker start of mysql and disables rehashing "
"on reconnect.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
+ "Automatically switch to vertical output mode if the result is wider "
+ "than the terminal width.",
+ &auto_vertical_output, &auto_vertical_output, 0, GET_BOOL, NO_ARG, 0,
+ 0, 0, 0, 0, 0},
{"batch", 'B',
"Don't use history file. Disable interactive behavior. (Enables --silent.)",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -1433,21 +1447,18 @@ static struct my_option my_long_options[] =
"is disabled by default.",
&named_cmds, &named_cmds, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
- {"no-named-commands", 'g',
- "Named commands are disabled. Use \\* form only, or use named commands "
- "only in the beginning of a line ending with a semicolon (;). Since "
- "version 10.9, the client now starts with this option ENABLED by default. "
- "Disable with '-G'. Long format commands still work from the first line. "
- "WARNING: option deprecated; use --disable-named-commands instead.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"ignore-spaces", 'i', "Ignore space after function names.",
&ignore_spaces, &ignore_spaces, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
+ {"init-command", OPT_INIT_COMMAND,
+ "SQL Command to execute when connecting to MySQL server. Will "
+ "automatically be re-executed when reconnecting.",
+ &opt_init_command, &opt_init_command, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"local-infile", OPT_LOCAL_INFILE, "Enable/disable LOAD DATA LOCAL INFILE.",
- &opt_local_infile,
- &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ &opt_local_infile, &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"no-beep", 'b', "Turn off beep on error.", &opt_nobeep,
- &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host.", &current_host,
&current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"html", 'H', "Produce HTML output.", &opt_html, &opt_html,
@@ -1456,7 +1467,7 @@ static struct my_option my_long_options[] =
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"line-numbers", OPT_LINE_NUMBERS, "Write line numbers for errors.",
&line_numbers, &line_numbers, 0, GET_BOOL,
- NO_ARG, 1, 0, 0, 0, 0, 0},
+ NO_ARG, 1, 0, 0, 0, 0, 0},
{"skip-line-numbers", 'L', "Don't write line number for errors.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"unbuffered", 'n', "Flush buffer after each query.", &unbuffered,
@@ -1467,10 +1478,6 @@ static struct my_option my_long_options[] =
{"skip-column-names", 'N',
"Don't write column names in results.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"set-variable", 'O',
- "Change the value of a variable. Please note that this option is "
- "deprecated; you can set variables directly with --variable-name=value.",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"sigint-ignore", OPT_SIGINT_IGNORE, "Ignore SIGINT (CTRL-C).",
&opt_sigint_ignore, &opt_sigint_ignore, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -1486,10 +1493,6 @@ static struct my_option my_long_options[] =
"This option does not work in batch mode. Disable with --disable-pager. "
"This option is disabled by default.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
- {"no-pager", OPT_NOPAGER,
- "Disable pager and print to stdout. See interactive help (\\h) also. "
- "WARNING: option deprecated; use --disable-pager instead.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"password", 'p',
"Password to use when connecting to server. If password is not given it's asked from the tty.",
@@ -1543,9 +1546,6 @@ static struct my_option my_long_options[] =
"Does not work in batch mode. Disable with --disable-tee. "
"This option is disabled by default.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"no-tee", OPT_NOTEE, "Disable outfile. See interactive help (\\h) also. "
- "WARNING: Option deprecated; use --disable-tee instead.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifndef DONT_ALLOW_USER_CHANGE
{"user", 'u', "User for login if not current user.", &current_user,
&current_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -1592,11 +1592,11 @@ static struct my_option my_long_options[] =
&show_warnings, &show_warnings, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
{"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
- (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+ &opt_plugin_dir, &opt_plugin_dir, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"default_auth", OPT_PLUGIN_DIR,
+ {"default_auth", OPT_DEFAULT_AUTH,
"Default authentication client-side plugin to use.",
- (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+ &opt_default_auth, &opt_default_auth, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -1604,11 +1604,6 @@ static struct my_option my_long_options[] =
static void usage(int version)
{
- /* Divert all help information on NetWare to logger screen. */
-#ifdef __NETWARE__
-#define printf consoleprintf
-#endif
-
#if defined(USE_LIBEDIT_INTERFACE)
const char* readline= "";
#else
@@ -1631,10 +1626,6 @@ static void usage(int version)
my_print_help(my_long_options);
print_defaults("my", load_default_groups);
my_print_variables(my_long_options);
- NETWARE_SET_SCREEN_MODE(1);
-#ifdef __NETWARE__
-#undef printf
-#endif
}
@@ -1643,18 +1634,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
switch(optid) {
-#ifdef __NETWARE__
- case OPT_AUTO_CLOSE:
- setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
- break;
-#endif
case OPT_CHARSETS_DIR:
strmake(mysql_charsets_dir, argument, sizeof(mysql_charsets_dir) - 1);
charsets_dir = mysql_charsets_dir;
break;
- case OPT_DEFAULT_CHARSET:
- default_charset_used= 1;
- break;
case OPT_DELIMITER:
if (argument == disabled_my_option)
{
@@ -1688,11 +1671,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
else
init_tee(argument);
break;
- case OPT_NOTEE:
- WARN_DEPRECATED(VER_CELOSIA, "--no-tee", "--disable-tee");
- if (opt_outfile)
- end_tee();
- break;
case OPT_PAGER:
if (argument == disabled_my_option)
opt_nopager= 1;
@@ -1711,10 +1689,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_nopager= 1;
}
break;
- case OPT_NOPAGER:
- WARN_DEPRECATED(VER_CELOSIA, "--no-pager", "--disable-pager");
- opt_nopager= 1;
- break;
case OPT_MYSQL_PROTOCOL:
#ifndef EMBEDDED_LIBRARY
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
@@ -1758,25 +1732,19 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (!(status.line_buff= batch_readline_command(status.line_buff, argument)))
return 1;
break;
- case 'g':
- WARN_DEPRECATED(VER_CELOSIA, "-g, --no-named-commands", "--skip-named-commands");
- break;
case 'o':
if (argument == disabled_my_option)
one_database= 0;
else
one_database= skip_updates= 1;
break;
- case 'O':
- WARN_DEPRECATED(VER_CELOSIA, "-O, --set-variable", "--variable-name=value");
- break;
case 'p':
if (argument == disabled_my_option)
argument= (char*) ""; // Don't require password
if (argument)
{
char *start= argument;
- my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_password);
opt_password= my_strdup(argument, MYF(MY_FAE));
while (*argument) *argument++= 'x'; // Destroy argument
if (*start)
@@ -1818,11 +1786,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case 'V':
usage(1);
- exit(0);
+ status.exit_status= 0;
+ mysql_end(-1);
case 'I':
case '?':
usage(0);
- exit(0);
+ status.exit_status= 0;
+ mysql_end(-1);
}
return 0;
}
@@ -1869,10 +1839,6 @@ static int get_options(int argc, char **argv)
opt_progress_reports= 0;
}
- if (strcmp(default_charset, charset_info->csname) &&
- !(charset_info= get_charset_by_csname(default_charset,
- MY_CS_PRIMARY, MYF(MY_WME))))
- exit(1);
if (argc > 1)
{
usage(0);
@@ -1881,7 +1847,7 @@ static int get_options(int argc, char **argv)
if (argc == 1)
{
skip_updates= 0;
- my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(current_db);
current_db= my_strdup(*argv, MYF(MY_WME));
}
if (tty_password)
@@ -1902,10 +1868,6 @@ static int get_options(int argc, char **argv)
static int read_and_execute(bool interactive)
{
-#if defined(__NETWARE__)
- char linebuffer[254];
- String buffer;
-#endif
#if defined(__WIN__)
String tmpbuf;
String buffer;
@@ -1950,18 +1912,8 @@ static int read_and_execute(bool interactive)
if (opt_outfile && glob_buffer.is_empty())
fflush(OUTFILE);
-#if defined(__WIN__) || defined(__NETWARE__)
+#if defined(__WIN__)
tee_fputs(prompt, stdout);
-#if defined(__NETWARE__)
- line=fgets(linebuffer, sizeof(linebuffer)-1, stdin);
- /* Remove the '\n' */
- if (line)
- {
- char *p = strrchr(line, '\n');
- if (p != NULL)
- *p = '\0';
- }
-#else
if (!tmpbuf.is_alloced())
tmpbuf.alloc(65535);
tmpbuf.length(0);
@@ -1982,12 +1934,11 @@ static int read_and_execute(bool interactive)
*/
if (line)
line= buffer.c_ptr();
-#endif /* __NETWARE__ */
#else
if (opt_outfile)
fputs(prompt, OUTFILE);
line= readline(prompt);
-#endif /* defined(__WIN__) || defined(__NETWARE__) */
+#endif /* defined(__WIN__) */
/*
When Ctrl+d or Ctrl+z is pressed, the line may be NULL on some OS
@@ -2040,10 +1991,8 @@ static int read_and_execute(bool interactive)
}
}
-#if defined(__WIN__) || defined(__NETWARE__)
- buffer.free();
-#endif
#if defined(__WIN__)
+ buffer.free();
tmpbuf.free();
#endif
@@ -2392,8 +2341,10 @@ static bool add_line(String &buffer,char *line,char *in_string,
#ifdef HAVE_READLINE
+C_MODE_START
static char *new_command_generator(const char *text, int);
-extern "C" char **new_mysql_completion (const char *text, int start, int end);
+static char **new_mysql_completion(const char *text, int start, int end);
+C_MODE_END
/*
Tell the GNU Readline library how to complete. We want to try to complete
@@ -2525,9 +2476,9 @@ static void initialize_readline (char *name)
array of matches, or NULL if there aren't any.
*/
-char **new_mysql_completion (const char *text,
- int start __attribute__((unused)),
- int end __attribute__((unused)))
+static char **new_mysql_completion(const char *text,
+ int start __attribute__((unused)),
+ int end __attribute__((unused)))
{
if (!status.batch && !quick)
#if defined(USE_NEW_READLINE_INTERFACE)
@@ -2781,7 +2732,7 @@ static int reconnect(void)
}
if (!connected)
return put_info("Can't connect to the server\n",INFO_ERROR);
- my_free(server_version,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(server_version);
server_version= 0;
/* purecov: end */
return 0;
@@ -2795,7 +2746,7 @@ static void get_current_db()
if (one_database)
return;
- my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(current_db);
current_db= NULL;
/* In case of error below current_db will be NULL */
if (!mysql_query(&mysql, "SELECT DATABASE()") &&
@@ -2971,7 +2922,7 @@ com_help(String *buffer __attribute__((unused)),
}
put_info("\nGeneral information about MariaDB can be found at\n"
- "http://askmonty.org/wiki/index.php/Manual:Contents\n", INFO_INFO);
+ "http://mariadb.org\n", INFO_INFO);
put_info("List of all MySQL commands:", INFO_INFO);
if (!named_cmds)
put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO);
@@ -3021,7 +2972,6 @@ com_charset(String *buffer __attribute__((unused)), char *line)
charset_info= new_cs;
mysql_set_character_set(&mysql, charset_info->csname);
default_charset= (char *)charset_info->csname;
- default_charset_used= 1;
put_info("Charset changed", INFO_INFO);
}
else put_info("Charset is not found", INFO_INFO);
@@ -3149,7 +3099,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
print_table_data_html(result);
else if (opt_xml)
print_table_data_xml(result);
- else if (vertical)
+ else if (vertical || (auto_vertical_output && (terminal_width < get_result_width(result))))
print_table_data_vertically(result);
else if (opt_silent && verbose <= 2 && !output_tables)
print_tab_data(result);
@@ -3480,6 +3430,65 @@ print_table_data(MYSQL_RES *result)
my_afree((uchar*) num_flag);
}
+/**
+ Return the length of a field after it would be rendered into text.
+
+ This doesn't know or care about multibyte characters. Assume we're
+ using such a charset. We can't know that all of the upcoming rows
+ for this column will have bytes that each render into some fraction
+ of a character. It's at least possible that a row has bytes that
+ all render into one character each, and so the maximum length is
+ still the number of bytes. (Assumption 1: This can't be better
+ because we can never know the number of characters that the DB is
+ going to send -- only the number of bytes. 2: Chars <= Bytes.)
+
+ @param field Pointer to a field to be inspected
+
+ @returns number of character positions to be used, at most
+*/
+static int get_field_disp_length(MYSQL_FIELD *field)
+{
+ uint length= column_names ? field->name_length : 0;
+
+ if (quick)
+ length= max(length, field->length);
+ else
+ length= max(length, field->max_length);
+
+ if (length < 4 && !IS_NOT_NULL(field->flags))
+ length= 4; /* Room for "NULL" */
+
+ return length;
+}
+
+/**
+ For a new result, return the max number of characters that any
+ upcoming row may return.
+
+ @param result Pointer to the result to judge
+
+ @returns The max number of characters in any row of this result
+*/
+static int get_result_width(MYSQL_RES *result)
+{
+ unsigned int len= 0;
+ MYSQL_FIELD *field;
+ MYSQL_FIELD_OFFSET offset;
+
+#ifndef DBUG_OFF
+ offset= mysql_field_tell(result);
+ DBUG_ASSERT(offset == 0);
+#else
+ offset= 0;
+#endif
+
+ while ((field= mysql_fetch_field(result)) != NULL)
+ len+= get_field_disp_length(field) + 3; /* plus bar, space, & final space */
+
+ (void) mysql_field_seek(result, offset);
+
+ return len + 1; /* plus final bar. */
+}
static void
tee_print_sized_data(const char *data, unsigned int data_length, unsigned int total_bytes_to_send, bool right_justified)
@@ -3962,8 +3971,6 @@ static int
com_quit(String *buffer __attribute__((unused)),
char *line __attribute__((unused)))
{
- /* let the screen auto close on a normal shutdown */
- NETWARE_SET_SCREEN_MODE(SCR_AUTOCLOSE_ON_EXIT);
status.exit_status=0;
return 1;
}
@@ -4041,12 +4048,12 @@ com_connect(String *buffer, char *line)
tmp= get_arg(buff, 0);
if (tmp && *tmp)
{
- my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(current_db);
current_db= my_strdup(tmp, MYF(MY_WME));
tmp= get_arg(buff, 1);
if (tmp)
{
- my_free(current_host,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(current_host);
current_host=my_strdup(tmp,MYF(MY_WME));
}
}
@@ -4231,7 +4238,7 @@ com_use(String *buffer __attribute__((unused)), char *line)
if (mysql_select_db(&mysql,tmp))
return put_error(&mysql);
}
- my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(current_db);
current_db=my_strdup(tmp,MYF(MY_WME));
#ifdef HAVE_READLINE
if (select_db > 1)
@@ -4362,7 +4369,7 @@ char *mysql_authentication_dialog_ask(MYSQL *mysql, int type,
s= get_tty_password("");
strnmov(buf, s, buf_len);
buf[buf_len-1]= 0;
- my_free(s, MYF(0));
+ my_free(s);
}
else
{
@@ -4385,6 +4392,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
mysql_close(&mysql);
}
mysql_init(&mysql);
+ if (opt_init_command)
+ mysql_options(&mysql, MYSQL_INIT_COMMAND, opt_init_command);
if (opt_connect_timeout)
{
uint timeout=opt_connect_timeout;
@@ -4397,7 +4406,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
mysql_options(&mysql, MYSQL_SECURE_AUTH, (char *) &opt_secure_auth);
if (using_opt_local_infile)
mysql_options(&mysql,MYSQL_OPT_LOCAL_INFILE, (char*) &opt_local_infile);
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
if (opt_use_ssl)
mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
@@ -4418,8 +4427,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
select_limit,max_join_size);
mysql_options(&mysql, MYSQL_INIT_COMMAND, init_command);
}
- if (default_charset_used)
- mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+
+ mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
if (opt_plugin_dir && *opt_plugin_dir)
mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
@@ -4428,8 +4437,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
if (!mysql_real_connect(&mysql, host, user, password,
- database, opt_mysql_port, opt_mysql_unix_port,
- connect_flag | CLIENT_MULTI_STATEMENTS))
+ database, opt_mysql_port, opt_mysql_unix_port,
+ connect_flag | CLIENT_MULTI_STATEMENTS))
{
if (!silent ||
(mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&
@@ -4441,7 +4450,9 @@ sql_real_connect(char *host,char *database,char *user,char *password,
}
return -1; // Retryable
}
-
+
+ charset_info= mysql.charset;
+
connected=1;
#ifndef EMBEDDED_LIBRARY
mysql.reconnect= debug_info_flag; // We want to know if this happens
@@ -4529,12 +4540,12 @@ com_status(String *buffer __attribute__((unused)),
mysql_free_result(result);
}
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
if ((status_str= mysql_get_ssl_cipher(&mysql)))
tee_fprintf(stdout, "SSL:\t\t\tCipher in use is %s\n",
status_str);
else
-#endif /* HAVE_OPENSSL */
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
tee_puts("SSL:\t\t\tNot in use", stdout);
if (skip_updates)
@@ -4764,7 +4775,6 @@ void tee_fprintf(FILE *file, const char *fmt, ...)
{
va_list args;
- NETWARE_YIELD;
va_start(args, fmt);
(void) vfprintf(file, fmt, args);
va_end(args);
@@ -4780,7 +4790,6 @@ void tee_fprintf(FILE *file, const char *fmt, ...)
void tee_fputs(const char *s, FILE *file)
{
- NETWARE_YIELD;
fputs(s, file);
if (opt_outfile)
fputs(s, OUTFILE);
@@ -4789,7 +4798,6 @@ void tee_fputs(const char *s, FILE *file)
void tee_puts(const char *s, FILE *file)
{
- NETWARE_YIELD;
fputs(s, file);
fputc('\n', file);
if (opt_outfile)
@@ -4806,7 +4814,7 @@ void tee_putc(int c, FILE *file)
putc(c, OUTFILE);
}
-#if defined(__WIN__) || defined(__NETWARE__)
+#if defined(__WIN__)
#include <time.h>
#else
#include <sys/times.h>
@@ -4818,8 +4826,8 @@ void tee_putc(int c, FILE *file)
static ulong start_timer(void)
{
-#if defined(__WIN__) || defined(__NETWARE__)
- return clock();
+#if defined(__WIN__)
+ return clock();
#else
struct tms tms_tmp;
return times(&tms_tmp);
@@ -5058,8 +5066,8 @@ static void add_int_to_prompt(int toadd)
static void init_username()
{
- my_free(full_username,MYF(MY_ALLOW_ZERO_PTR));
- my_free(part_username,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(full_username);
+ my_free(part_username);
MYSQL_RES *result;
LINT_INIT(result);
@@ -5078,7 +5086,7 @@ static int com_prompt(String *buffer __attribute__((unused)),
{
char *ptr=strchr(line, ' ');
prompt_counter = 0;
- my_free(current_prompt,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(current_prompt);
current_prompt=my_strdup(ptr ? ptr+1 : default_prompt,MYF(MY_WME));
if (!ptr)
tee_fprintf(stdout, "Returning to default PROMPT of %s\n", default_prompt);
@@ -5088,18 +5096,6 @@ static int com_prompt(String *buffer __attribute__((unused)),
}
#ifndef EMBEDDED_LIBRARY
-/* Keep sql_string library happy */
-
-void *sql_alloc(size_t Size)
-{
- return my_malloc(Size,MYF(MY_WME));
-}
-
-void sql_element_free(void *ptr)
-{
- my_free(ptr,MYF(0));
-}
-
static void report_progress(const MYSQL *mysql, uint stage, uint max_stage,
double progress, const char *proc_info,
uint proc_info_length)
diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c
new file mode 100644
index 00000000000..f4e3111b7b7
--- /dev/null
+++ b/client/mysql_plugin.c
@@ -0,0 +1,1206 @@
+/*
+ Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <m_string.h>
+#include <mysql.h>
+#include <my_getopt.h>
+#include <my_dir.h>
+#include <my_global.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#define SHOW_VERSION "1.0.0"
+#define PRINT_VERSION do { printf("%s Ver %s Distrib %s\n", \
+ my_progname, SHOW_VERSION, MYSQL_SERVER_VERSION); \
+ } while(0)
+
+/* Global variables. */
+static uint my_end_arg= 0;
+static uint opt_verbose=0;
+static uint opt_no_defaults= 0;
+static uint opt_print_defaults= 0;
+static char *opt_datadir=0, *opt_basedir=0,
+ *opt_plugin_dir=0, *opt_plugin_ini=0,
+ *opt_mysqld=0, *opt_my_print_defaults=0;
+static char bootstrap[FN_REFLEN];
+
+
+/* plugin struct */
+struct st_plugin
+{
+ const char *name; /* plugin name */
+ const char *so_name; /* plugin so (library) name */
+ const char *components[16]; /* components to load */
+} plugin_data;
+
+
+/* Options */
+static struct my_option my_long_options[] =
+{
+ {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"basedir", 'b', "The basedir for the server.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"datadir", 'd', "The datadir for the server.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"plugin-dir", 'p', "The plugin dir for the server.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"plugin-ini", 'i', "Read plugin information from configuration file "
+ "specified instead of from <plugin-dir>/<plugin_name>.ini.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"no-defaults", 'n', "Do not read values from configuration file.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"print-defaults", 'P', "Show default values from configuration file.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"mysqld", 'm', "Path to mysqld executable. Example: /sbin/temp1/mysql/bin",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"my-print-defaults", 'f', "Path to my_print_defaults executable. "
+ "Example: /source/temp11/extra",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"verbose", 'v',
+ "More verbose output; you can use this multiple times to get even more "
+ "verbose output.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+
+/* Methods */
+static int process_options(int argc, char *argv[], char *operation);
+static int check_access();
+static int find_tool(const char *tool_name, char *tool_path);
+static int find_plugin(char *tp_path);
+static int build_bootstrap_file(char *operation, char *bootstrap);
+static int dump_bootstrap_file(char *bootstrap_file);
+static int bootstrap_server(char *server_path, char *bootstrap_file);
+
+
+int main(int argc,char *argv[])
+{
+ int error= 0;
+ char tp_path[FN_REFLEN];
+ char server_path[FN_REFLEN];
+ char operation[16];
+
+ MY_INIT(argv[0]);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
+ plugin_data.name= 0; // initialize name
+
+ /*
+ The following operations comprise the method for enabling or disabling
+ a plugin. We begin by processing the command options then check the
+ directories specified for --datadir, --basedir, --plugin-dir, and
+ --plugin-ini (if specified). If the directories are Ok, we then look
+ for the mysqld executable and the plugin soname. Finally, we build a
+ bootstrap command file for use in bootstraping the server.
+
+ If any step fails, the method issues an error message and the tool exits.
+
+ 1) Parse, execute, and verify command options.
+ 2) Check access to directories.
+ 3) Look for mysqld executable.
+ 4) Look for the plugin.
+ 5) Build a bootstrap file with commands to enable or disable plugin.
+
+ */
+ if ((error= process_options(argc, argv, operation)) ||
+ (error= check_access()) ||
+ (error= find_tool("mysqld" FN_EXEEXT, server_path)) ||
+ (error= find_plugin(tp_path)) ||
+ (error= build_bootstrap_file(operation, bootstrap)))
+ goto exit;
+
+ /* Dump the bootstrap file if --verbose specified. */
+ if (opt_verbose && ((error= dump_bootstrap_file(bootstrap))))
+ goto exit;
+
+ /* Start the server in bootstrap mode and execute bootstrap commands */
+ error= bootstrap_server(server_path, bootstrap);
+
+exit:
+ /* Remove file */
+ my_delete(bootstrap, MYF(0));
+ if (opt_verbose && error == 0)
+ {
+ printf("# Operation succeeded.\n");
+ }
+
+ my_end(my_end_arg);
+ exit(error ? 1 : 0);
+ return 0; /* No compiler warnings */
+}
+
+
+/**
+ Get a temporary file name.
+
+ @param[out] filename The file name of the temporary file
+ @param[in] ext An extension for the file (optional)
+
+ @retval int error = 1, success = 0
+*/
+
+static int make_tempfile(char *filename, const char *ext)
+{
+ int fd= 0;
+
+ if ((fd=create_temp_file(filename, NullS, ext, O_CREAT | O_WRONLY,
+ MYF(MY_WME))) < 0)
+ {
+ fprintf(stderr, "ERROR: Cannot generate temporary file. Error code: %d.\n",
+ fd);
+ return 1;
+ }
+ my_close(fd, MYF(0));
+ return 0;
+}
+
+
+/**
+ Get the value of an option from a string read from my_print_defaults output.
+
+ @param[in] line The line (string) read from the file
+ @param[in] item The option to search for (e.g. --datadir)
+
+ @returns NULL if not found, string containing value if found
+*/
+
+static char *get_value(char *line, const char *item)
+{
+ char *destination= 0;
+ int item_len= (int)strlen(item);
+ int line_len = (int)strlen(line);
+
+ if ((strncasecmp(line, item, item_len) == 0))
+ {
+ int start= 0;
+ char *s= 0;
+
+ s = line + item_len + 1;
+ destination= my_strndup(s, line_len - start, MYF(MY_FAE));
+ destination[line_len - item_len - 2]= 0;
+ }
+ return destination;
+}
+
+
+/**
+ Run a command in a shell.
+
+ This function will attempt to execute the command specified by using the
+ popen() method to open a shell and execute the command passed and store the
+ output in a result file. If the --verbose option was specified, it will open
+ the result file and print the contents to stdout.
+
+ @param[in] cmd The command to execute.
+ @param[in] mode The mode for popen() (e.g. "r", "w", "rw")
+
+ @return int error code or 0 for success.
+*/
+
+static int run_command(char* cmd, const char *mode)
+{
+ char buf[512]= {0};
+ FILE *res_file;
+ int error;
+
+ if (!(res_file= popen(cmd, mode)))
+ return -1;
+
+ if (opt_verbose)
+ {
+ while (fgets(buf, sizeof(buf), res_file))
+ {
+ fprintf(stdout, "%s", buf);
+ }
+ }
+ error= pclose(res_file);
+ return error;
+}
+
+
+#ifdef __WIN__
+/**
+ Check to see if there are spaces in a path.
+
+ @param[in] path The Windows path to examine.
+
+ @retval int spaces found = 1, no spaces = 0
+*/
+static int has_spaces(const char *path)
+{
+ if (strchr(path, ' ') != NULL)
+ return 1;
+ return 0;
+}
+
+
+/**
+ Convert a Unix path to a Windows path.
+
+ @param[in] path The Windows path to examine.
+
+ @returns string containing path with / changed to \\
+*/
+static char *convert_path(const char *argument)
+{
+ /* Convert / to \\ to make Windows paths */
+ char *winfilename= my_strdup(argument, MYF(MY_FAE));
+ char *pos, *end;
+ int length= strlen(argument);
+
+ for (pos= winfilename, end= pos+length ; pos < end ; pos++)
+ {
+ if (*pos == '/')
+ {
+ *pos= '\\';
+ }
+ }
+ return winfilename;
+}
+
+
+/**
+ Add quotes if the path has spaces in it.
+
+ @param[in] path The Windows path to examine.
+
+ @returns string containing excaped quotes if spaces found in path
+*/
+static char *add_quotes(const char *path)
+{
+ char windows_cmd_friendly[FN_REFLEN];
+
+ if (has_spaces(path))
+ snprintf(windows_cmd_friendly, sizeof(windows_cmd_friendly),
+ "\"%s\"", path);
+ else
+ snprintf(windows_cmd_friendly, sizeof(windows_cmd_friendly),
+ "%s", path);
+ return my_strdup(windows_cmd_friendly, MYF(MY_FAE));
+}
+#endif
+
+
+/**
+ Get the default values from the my.cnf file.
+
+ This method gets the default values for the following parameters:
+
+ --datadir
+ --basedir
+ --plugin-dir
+ --plugin-ini
+
+ These values are used if the user has not specified a value.
+
+ @retval int error = 1, success = 0
+*/
+
+static int get_default_values()
+{
+ char tool_path[FN_REFLEN];
+ char defaults_cmd[FN_REFLEN];
+ char defaults_file[FN_REFLEN];
+ char line[FN_REFLEN];
+ int error= 0;
+ int ret= 0;
+ FILE *file= 0;
+
+ bzero(tool_path, FN_REFLEN);
+ if ((error= find_tool("my_print_defaults" FN_EXEEXT, tool_path)))
+ goto exit;
+ else
+ {
+ if ((error= make_tempfile(defaults_file, "txt")))
+ goto exit;
+
+#ifdef __WIN__
+ {
+ char *format_str= 0;
+
+ if (has_spaces(tool_path) || has_spaces(defaults_file))
+ format_str = "\"%s mysqld > %s\"";
+ else
+ format_str = "%s mysqld > %s";
+
+ snprintf(defaults_cmd, sizeof(defaults_cmd), format_str,
+ add_quotes(tool_path), add_quotes(defaults_file));
+ if (opt_verbose)
+ {
+ printf("# my_print_defaults found: %s\n", tool_path);
+ }
+ }
+#else
+ snprintf(defaults_cmd, sizeof(defaults_cmd),
+ "%s mysqld > %s", tool_path, defaults_file);
+#endif
+
+ /* Execute the command */
+ if (opt_verbose)
+ {
+ printf("# Command: %s\n", defaults_cmd);
+ }
+ error= run_command(defaults_cmd, "r");
+ if (error)
+ {
+ fprintf(stderr, "ERROR: my_print_defaults failed. Error code: %d.\n",
+ ret);
+ goto exit;
+ }
+ /* Now open the file and read the defaults we want. */
+ file= fopen(defaults_file, "r");
+ while (fgets(line, FN_REFLEN, file) != NULL)
+ {
+ char *value= 0;
+
+ if ((opt_datadir == 0) && ((value= get_value(line, "--datadir"))))
+ {
+ opt_datadir= my_strdup(value, MYF(MY_FAE));
+ }
+ if ((opt_basedir == 0) && ((value= get_value(line, "--basedir"))))
+ {
+ opt_basedir= my_strdup(value, MYF(MY_FAE));
+ }
+ if ((opt_plugin_dir == 0) && ((value= get_value(line, "--plugin_dir"))))
+ {
+ opt_plugin_dir= my_strdup(value, MYF(MY_FAE));
+ }
+ if ((opt_plugin_ini == 0) && ((value= get_value(line, "--plugin_ini"))))
+ {
+ opt_plugin_ini= my_strdup(value, MYF(MY_FAE));
+ }
+ }
+ }
+exit:
+ if (file)
+ {
+ fclose(file);
+ /* Remove file */
+ my_delete(defaults_file, MYF(0));
+ }
+ return error;
+}
+
+
+/**
+ Print usage.
+*/
+
+static void usage(void)
+{
+ PRINT_VERSION;
+ puts("Copyright (c) 2011, Oracle and/or its affiliates. "
+ "All rights reserved.\n");
+ puts("Enable or disable plugins.");
+ printf("\nUsage: %s [options] <plugin> ENABLE|DISABLE\n\nOptions:\n",
+ my_progname);
+ my_print_help(my_long_options);
+ puts("\n");
+}
+
+
+/**
+ Print the default values as read from the my.cnf file.
+
+ This method displays the default values for the following parameters:
+
+ --datadir
+ --basedir
+ --plugin-dir
+ --plugin-ini
+
+*/
+
+static void print_default_values(void)
+{
+ printf("%s would have been started with the following arguments:\n",
+ my_progname);
+ get_default_values();
+ if (opt_datadir)
+ {
+ printf("--datadir=%s ", opt_datadir);
+ }
+ if (opt_basedir)
+ {
+ printf("--basedir=%s ", opt_basedir);
+ }
+ if (opt_plugin_dir)
+ {
+ printf("--plugin_dir=%s ", opt_plugin_dir);
+ }
+ if (opt_plugin_ini)
+ {
+ printf("--plugin_ini=%s ", opt_plugin_ini);
+ }
+ if (opt_mysqld)
+ {
+ printf("--mysqld=%s ", opt_mysqld);
+ }
+ if (opt_my_print_defaults)
+ {
+ printf("--my_print_defaults=%s ", opt_my_print_defaults);
+ }
+ printf("\n");
+}
+
+
+/**
+ Process the arguments and identify an option and store its value.
+
+ @param[in] optid The single character shortcut for the argument.
+ @param[in] my_option Structure of legal options.
+ @param[in] argument The argument value to process.
+*/
+
+static my_bool
+get_one_option(int optid,
+ const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch(optid) {
+ case 'n':
+ opt_no_defaults++;
+ break;
+ case 'P':
+ opt_print_defaults++;
+ print_default_values();
+ break;
+ case 'v':
+ opt_verbose++;
+ break;
+ case 'V':
+ PRINT_VERSION;
+ exit(0);
+ break;
+ case '?':
+ case 'I': /* Info */
+ usage();
+ exit(0);
+ case 'd':
+ opt_datadir= my_strdup(argument, MYF(MY_FAE));
+ break;
+ case 'b':
+ opt_basedir= my_strdup(argument, MYF(MY_FAE));
+ break;
+ case 'p':
+ opt_plugin_dir= my_strdup(argument, MYF(MY_FAE));
+ break;
+ case 'i':
+ opt_plugin_ini= my_strdup(argument, MYF(MY_FAE));
+ break;
+ case 'm':
+ opt_mysqld= my_strdup(argument, MYF(MY_FAE));
+ break;
+ case 'f':
+ opt_my_print_defaults= my_strdup(argument, MYF(MY_FAE));
+ break;
+ }
+ return 0;
+}
+
+
+/**
+ Check to see if a file exists.
+
+ @param[in] filename File to locate.
+
+ @retval int file not found = 1, file found = 0
+*/
+
+static int file_exists(char * filename)
+{
+ MY_STAT stat_arg;
+
+ if (!my_stat(filename, &stat_arg, MYF(0)))
+ {
+ return 0;
+ }
+ return 1;
+}
+
+
+/**
+ Search a specific path and sub directory for a file name.
+
+ @param[in] base_path Original path to use.
+ @param[in] tool_name Name of the tool to locate.
+ @param[in] subdir The sub directory to search.
+ @param[out] tool_path If tool found, return complete path.
+
+ @retval int error = 1, success = 0
+*/
+
+static int search_dir(const char * base_path, const char *tool_name,
+ const char *subdir, char *tool_path)
+{
+ char new_path[FN_REFLEN];
+ char source_path[FN_REFLEN];
+
+ strcpy(source_path, base_path);
+ strcat(source_path, subdir);
+ fn_format(new_path, tool_name, source_path, "", MY_UNPACK_FILENAME);
+ if (file_exists(new_path))
+ {
+ strcpy(tool_path, new_path);
+ return 1;
+ }
+ return 0;
+}
+
+
+/**
+ Search known common paths and sub directories for a file name.
+
+ @param[in] base_path Original path to use.
+ @param[in] tool_name Name of the tool to locate.
+ @param[out] tool_path If tool found, return complete path.
+
+ @retval int error = 1, success = 0
+*/
+
+static int search_paths(const char *base_path, const char *tool_name,
+ char *tool_path)
+{
+ int i= 0;
+
+ static const char *paths[]= {
+ "", "/share/", "/scripts/", "/bin/", "/sbin/", "/libexec/",
+ "/mysql/", "/sql/",
+ };
+ for (i = 0 ; i < (int)array_elements(paths); i++)
+ {
+ if (search_dir(base_path, tool_name, paths[i], tool_path))
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ Read the plugin ini file.
+
+ This function attempts to read the plugin config file from the plugin_dir
+ path saving the data in the the st_plugin structure. If the file is not
+ found or the file cannot be read, an error is generated.
+
+ @retval int error = 1, success = 0
+*/
+
+static int load_plugin_data(char *plugin_name, char *config_file)
+{
+ FILE *file_ptr;
+ char path[FN_REFLEN];
+ char line[1024];
+ char *reason= 0;
+ char *res;
+ int i= -1;
+
+ if (opt_plugin_ini == 0)
+ {
+ fn_format(path, config_file, opt_plugin_dir, "", MYF(0));
+ opt_plugin_ini= my_strdup(path, MYF(MY_FAE));
+ }
+ if (!file_exists(opt_plugin_ini))
+ {
+ reason= (char *)"File does not exist.";
+ goto error;
+ }
+
+ file_ptr= fopen(opt_plugin_ini, "r");
+ if (file_ptr == NULL)
+ {
+ reason= (char *)"Cannot open file.";
+ goto error;
+ }
+
+ /* save name */
+ plugin_data.name= my_strdup(plugin_name, MYF(MY_WME));
+
+ /* Read plugin components */
+ while (i < 16)
+ {
+ res= fgets(line, sizeof(line), file_ptr);
+ /* strip /n */
+ if (line[strlen(line)-1] == '\n')
+ {
+ line[strlen(line)-1]= '\0';
+ }
+ if (res == NULL)
+ {
+ if (i < 1)
+ {
+ reason= (char *)"Bad format in plugin configuration file.";
+ fclose(file_ptr);
+ goto error;
+ }
+ break;
+ }
+ if ((line[0] == '#') || (line[0] == '\n')) // skip comment and blank lines
+ {
+ continue;
+ }
+ if (i == -1) // if first pass, read this line as so_name
+ {
+ /* Add proper file extension for soname */
+ strcat(line, FN_SOEXT);
+ /* save so_name */
+ plugin_data.so_name= my_strdup(line, MYF(MY_WME|MY_ZEROFILL));
+ i++;
+ }
+ else
+ {
+ if (strlen(line) > 0)
+ {
+ plugin_data.components[i]= my_strdup(line, MYF(MY_WME));
+ i++;
+ }
+ else
+ {
+ plugin_data.components[i]= NULL;
+ }
+ }
+ }
+
+ fclose(file_ptr);
+ return 0;
+
+error:
+ fprintf(stderr, "ERROR: Cannot read plugin config file %s. %s\n",
+ plugin_name, reason);
+ return 1;
+}
+
+
+/**
+ Check the options for validity.
+
+ This function checks the arguments for validity issuing the appropriate
+ error message if arguments are missing or invalid. On success, @operation
+ is set to either "ENABLE" or "DISABLE".
+
+ @param[in] argc The number of arguments.
+ @param[in] argv The arguments.
+ @param[out] operation The operation chosen (enable|disable)
+
+ @retval int error = 1, success = 0
+*/
+
+static int check_options(int argc, char **argv, char *operation)
+{
+ int i= 0; // loop counter
+ int num_found= 0; // number of options found (shortcut loop)
+ char config_file[FN_REFLEN]; // configuration file name
+ char plugin_name[FN_REFLEN]; // plugin name
+
+ /* Form prefix strings for the options. */
+ const char *basedir_prefix = "--basedir=";
+ int basedir_len= strlen(basedir_prefix);
+ const char *datadir_prefix = "--datadir=";
+ int datadir_len= strlen(datadir_prefix);
+ const char *plugin_dir_prefix = "--plugin_dir=";
+ int plugin_dir_len= strlen(plugin_dir_prefix);
+
+ strcpy(plugin_name, "");
+ for (i = 0; i < argc && num_found < 5; i++)
+ {
+
+ if (!argv[i])
+ {
+ continue;
+ }
+ if ((strcasecmp(argv[i], "ENABLE") == 0) ||
+ (strcasecmp(argv[i], "DISABLE") == 0))
+ {
+ strcpy(operation, argv[i]);
+ num_found++;
+ }
+ else if ((strncasecmp(argv[i], basedir_prefix, basedir_len) == 0) &&
+ !opt_basedir)
+ {
+ opt_basedir= my_strndup(argv[i]+basedir_len,
+ strlen(argv[i])-basedir_len, MYF(MY_FAE));
+ num_found++;
+ }
+ else if ((strncasecmp(argv[i], datadir_prefix, datadir_len) == 0) &&
+ !opt_datadir)
+ {
+ opt_datadir= my_strndup(argv[i]+datadir_len,
+ strlen(argv[i])-datadir_len, MYF(MY_FAE));
+ num_found++;
+ }
+ else if ((strncasecmp(argv[i], plugin_dir_prefix, plugin_dir_len) == 0) &&
+ !opt_plugin_dir)
+ {
+ opt_plugin_dir= my_strndup(argv[i]+plugin_dir_len,
+ strlen(argv[i])-plugin_dir_len, MYF(MY_FAE));
+ num_found++;
+ }
+ /* read the plugin config file and check for match against argument */
+ else
+ {
+ strcpy(plugin_name, argv[i]);
+ strcpy(config_file, argv[i]);
+ strcat(config_file, ".ini");
+ }
+ }
+
+ if (!opt_basedir)
+ {
+ fprintf(stderr, "ERROR: Missing --basedir option.\n");
+ return 1;
+ }
+
+ if (!opt_datadir)
+ {
+ fprintf(stderr, "ERROR: Missing --datadir option.\n");
+ return 1;
+ }
+
+ if (!opt_plugin_dir)
+ {
+ fprintf(stderr, "ERROR: Missing --plugin_dir option.\n");
+ return 1;
+ }
+ /* If a plugin was specified, read the config file. */
+ else if (strlen(plugin_name) > 0)
+ {
+ if (load_plugin_data(plugin_name, config_file))
+ {
+ return 1;
+ }
+ if (strcasecmp(plugin_data.name, plugin_name) != 0)
+ {
+ fprintf(stderr, "ERROR: plugin name requested does not match config "
+ "file data.\n");
+ return 1;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: No plugin specified.\n");
+ return 1;
+ }
+
+ if ((strlen(operation) == 0))
+ {
+ fprintf(stderr, "ERROR: missing operation. Please specify either "
+ "'<plugin> ENABLE' or '<plugin> DISABLE'.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/**
+ Parse, execute, and verify command options.
+
+ This method handles all of the option processing including the optional
+ features for displaying data (--print-defaults, --help ,etc.) that do not
+ result in an attempt to ENABLE or DISABLE of a plugin.
+
+ @param[in] arc Count of arguments
+ @param[in] argv Array of arguments
+ @param[out] operation Operation (ENABLE or DISABLE)
+
+ @retval int error = 1, success = 0, exit program = -1
+*/
+
+static int process_options(int argc, char *argv[], char *operation)
+{
+ int error= 0;
+ int i= 0;
+
+ /* Parse and execute command-line options */
+ if ((error= handle_options(&argc, &argv, my_long_options, get_one_option)))
+ goto exit;
+
+ /* If the print defaults option used, exit. */
+ if (opt_print_defaults)
+ {
+ error= -1;
+ goto exit;
+ }
+
+ /* Add a trailing directory separator if not present */
+ if (opt_basedir)
+ {
+ i= (int)strlength(opt_basedir);
+ if (opt_basedir[i-1] != FN_LIBCHAR || opt_basedir[i-1] != FN_LIBCHAR2)
+ {
+ char buff[FN_REFLEN];
+
+ strncpy(buff, opt_basedir, sizeof(buff) - 1);
+#ifdef __WIN__
+ strncat(buff, "/", sizeof(buff) - strlen(buff) - 1);
+#else
+ strncat(buff, FN_DIRSEP, sizeof(buff) - strlen(buff) - 1);
+#endif
+ buff[sizeof(buff) - 1]= 0;
+ my_delete(opt_basedir, MYF(0));
+ opt_basedir= my_strdup(buff, MYF(MY_FAE));
+ }
+ }
+
+ /*
+ If the user did not specify the option to skip loading defaults from a
+ config file and the required options are not present or there was an error
+ generated when the defaults were read from the file, exit.
+ */
+ if (!opt_no_defaults && ((error= get_default_values())))
+ {
+ error= -1;
+ goto exit;
+ }
+
+ /*
+ Check to ensure required options are present and validate the operation.
+ Note: this method also validates the plugin specified by attempting to
+ read a configuration file named <plugin_name>.ini from the --plugin-dir
+ or --plugin-ini location if the --plugin-ini option presented.
+ */
+ strcpy(operation, "");
+ if ((error = check_options(argc, argv, operation)))
+ {
+ goto exit;
+ }
+
+ if (opt_verbose)
+ {
+ printf("# basedir = %s\n", opt_basedir);
+ printf("# plugin_dir = %s\n", opt_plugin_dir);
+ printf("# datadir = %s\n", opt_datadir);
+ printf("# plugin_ini = %s\n", opt_plugin_ini);
+ }
+
+exit:
+ return error;
+}
+
+
+/**
+ Check access
+
+ This method checks to ensure all of the directories (opt_basedir,
+ opt_plugin_dir, opt_datadir, and opt_plugin_ini) are accessible by
+ the user.
+
+ @retval int error = 1, success = 0
+*/
+
+static int check_access()
+{
+ int error= 0;
+
+ if ((error= my_access(opt_basedir, F_OK)))
+ {
+ fprintf(stderr, "ERROR: Cannot access basedir at '%s'.\n",
+ opt_basedir);
+ goto exit;
+ }
+ if ((error= my_access(opt_plugin_dir, F_OK)))
+ {
+ fprintf(stderr, "ERROR: Cannot access plugin_dir at '%s'.\n",
+ opt_plugin_dir);
+ goto exit;
+ }
+ if ((error= my_access(opt_datadir, F_OK)))
+ {
+ fprintf(stderr, "ERROR: Cannot access datadir at '%s'.\n",
+ opt_datadir);
+ goto exit;
+ }
+ if (opt_plugin_ini && (error= my_access(opt_plugin_ini, F_OK)))
+ {
+ fprintf(stderr, "ERROR: Cannot access plugin config file at '%s'.\n",
+ opt_plugin_ini);
+ goto exit;
+ }
+ if (opt_mysqld && (error= my_access(opt_mysqld, F_OK)))
+ {
+ fprintf(stderr, "ERROR: Cannot access mysqld path '%s'.\n",
+ opt_mysqld);
+ goto exit;
+ }
+ if (opt_my_print_defaults && (error= my_access(opt_my_print_defaults, F_OK)))
+ {
+ fprintf(stderr, "ERROR: Cannot access my-print-defaults path '%s'.\n",
+ opt_my_print_defaults);
+ goto exit;
+ }
+
+exit:
+ return error;
+}
+
+
+/**
+ Locate the tool and form tool path.
+
+ @param[in] tool_name Name of the tool to locate.
+ @param[out] tool_path If tool found, return complete path.
+
+ @retval int error = 1, success = 0
+*/
+
+static int find_tool(const char *tool_name, char *tool_path)
+{
+ int i= 0;
+
+ const char *paths[]= {
+ opt_mysqld, opt_basedir, opt_my_print_defaults, "/usr",
+ "/usr/local/mysql", "/usr/sbin", "/usr/share", "/extra", "/extra/debug",
+ "/extra/release", "/bin", "/usr/bin", "/mysql/bin"
+ };
+ for (i= 0; i < (int)array_elements(paths); i++)
+ {
+ if (paths[i] && (search_paths(paths[i], tool_name, tool_path)))
+ goto found;
+ }
+ fprintf(stderr, "WARNING: Cannot find %s.\n", tool_name);
+ return 1;
+found:
+ if (opt_verbose)
+ printf("# Found tool '%s' as '%s'.\n", tool_name, tool_path);
+ return 0;
+}
+
+
+/**
+ Find the plugin library.
+
+ This function attempts to use the @c plugin_dir option passed on the
+ command line to locate the plugin.
+
+ @param[out] tp_path The actual path to plugin with FN_SOEXT applied.
+
+ @retval int error = 1, success = 0
+*/
+
+static int find_plugin(char *tp_path)
+{
+ /* Check for existance of plugin */
+ fn_format(tp_path, plugin_data.so_name, opt_plugin_dir, "", MYF(0));
+ if (!file_exists(tp_path))
+ {
+ fprintf(stderr, "ERROR: The plugin library is missing or in a different"
+ " location.\n");
+ return 1;
+ }
+ else if (opt_verbose)
+ {
+ printf("# Found plugin '%s' as '%s'\n", plugin_data.name, tp_path);
+ }
+ return 0;
+}
+
+
+/**
+ Build the boostrap file.
+
+ Create a new file and populate it with SQL commands to ENABLE or DISABLE
+ the plugin via REPLACE and DELETE operations on the mysql.plugin table.
+
+ param[in] operation The type of operation (ENABLE or DISABLE)
+ param[out] bootstrap A FILE* pointer
+
+ @retval int error = 1, success = 0
+*/
+
+static int build_bootstrap_file(char *operation, char *bootstrap)
+{
+ int error= 0;
+ FILE *file= 0;
+
+ /*
+ Perform plugin operation : ENABLE or DISABLE
+
+ The following creates a temporary bootstrap file and populates it with
+ the appropriate SQL commands for the operation. For ENABLE, REPLACE
+ statements are created. For DISABLE, DELETE statements are created. The
+ values for these statements are derived from the plugin_data read from the
+ <plugin_name>.ini configuration file. Once the file is built, a call to
+ mysqld is made in read only, bootstrap modes to read the SQL statements
+ and execute them.
+
+ Note: Replace was used so that if a user loads a newer version of a
+ library with a different library name, the new library name is
+ used for symbols that match.
+ */
+ if ((error= make_tempfile(bootstrap, "sql")))
+ {
+ /* Fail if we cannot create a temporary file for the bootstrap commands. */
+ fprintf(stderr, "ERROR: Cannot create bootstrap file.\n");
+ goto exit;
+ }
+ if ((file= fopen(bootstrap, "w+")) == NULL)
+ {
+ fprintf(stderr, "ERROR: Cannot open bootstrap file for writing.\n");
+ error= 1;
+ goto exit;
+ }
+ if (strcasecmp(operation, "enable") == 0)
+ {
+ int i= 0;
+ fprintf(file, "REPLACE INTO mysql.plugin VALUES ");
+ for (i= 0; i < (int)array_elements(plugin_data.components); i++)
+ {
+ /* stop when we read the end of the symbol list - marked with NULL */
+ if (plugin_data.components[i] == NULL)
+ {
+ break;
+ }
+ if (i > 0)
+ {
+ fprintf(file, ", ");
+ }
+ fprintf(file, "('%s','%s')",
+ plugin_data.components[i], plugin_data.so_name);
+ }
+ fprintf(file, ";\n");
+ if (opt_verbose)
+ {
+ printf("# Enabling %s...\n", plugin_data.name);
+ }
+ }
+ else
+ {
+ fprintf(file,
+ "DELETE FROM mysql.plugin WHERE dl = '%s';", plugin_data.so_name);
+ if (opt_verbose)
+ {
+ printf("# Disabling %s...\n", plugin_data.name);
+ }
+ }
+
+exit:
+ fclose(file);
+ return error;
+}
+
+
+/**
+ Dump bootstrap file.
+
+ Read the contents of the bootstrap file and print it out.
+
+ @param[in] bootstrap_file Name of bootstrap file to read
+
+ @retval int error = 1, success = 0
+*/
+
+static int dump_bootstrap_file(char *bootstrap_file)
+{
+ char *ret= 0;
+ int error= 0;
+ char query_str[512];
+ FILE *file= 0;
+
+ if ((file= fopen(bootstrap_file, "r")) == NULL)
+ {
+ fprintf(stderr, "ERROR: Cannot open bootstrap file for reading.\n");
+ error= 1;
+ goto exit;
+ }
+ ret= fgets(query_str, 512, file);
+ if (ret == 0)
+ {
+ fprintf(stderr, "ERROR: Cannot read bootstrap file.\n");
+ error= 1;
+ goto exit;
+ }
+ printf("# Query: %s\n", query_str);
+
+exit:
+ if (file)
+ {
+ fclose(file);
+ }
+ return error;
+}
+
+
+/**
+ Bootstrap the server
+
+ Create a command line sequence to launch mysqld in bootstrap mode. This
+ will allow mysqld to launch a minimal server instance to read and
+ execute SQL commands from a file piped in (the boostrap file). We use
+ the --no-defaults option to skip reading values from the config file.
+
+ The bootstrap mode skips loading of plugins and many other subsystems.
+ This allows the mysql_plugin tool to insert the correct rows into the
+ mysql.plugin table (for ENABLE) or delete the rows (for DISABLE). Once
+ the server is launched in normal mode, the plugin will be loaded
+ (for ENABLE) or not loaded (for DISABLE). In this way, we avoid the
+ (sometimes) complicated LOAD PLUGIN commands.
+
+ @param[in] server_path Path to server executable
+ @param[in] bootstrap_file Name of bootstrap file to read
+
+ @retval int error = 1, success = 0
+*/
+
+static int bootstrap_server(char *server_path, char *bootstrap_file)
+{
+ char bootstrap_cmd[FN_REFLEN];
+ int error= 0;
+
+#ifdef __WIN__
+ char *format_str= 0;
+ const char *verbose_str= NULL;
+
+
+ if (opt_verbose)
+ verbose_str= "--console";
+ else
+ verbose_str= "";
+ if (has_spaces(opt_datadir) || has_spaces(opt_basedir) ||
+ has_spaces(bootstrap_file))
+ format_str= "\"%s %s --bootstrap --datadir=%s --basedir=%s < %s\"";
+ else
+ format_str= "%s %s --bootstrap --datadir=%s --basedir=%s < %s";
+
+ snprintf(bootstrap_cmd, sizeof(bootstrap_cmd), format_str,
+ add_quotes(convert_path(server_path)), verbose_str,
+ add_quotes(opt_datadir), add_quotes(opt_basedir),
+ add_quotes(bootstrap_file));
+#else
+ snprintf(bootstrap_cmd, sizeof(bootstrap_cmd),
+ "%s --no-defaults --bootstrap --datadir=%s --basedir=%s"
+ " < %s", server_path, opt_datadir, opt_basedir, bootstrap_file);
+#endif
+
+ /* Execute the command */
+ if (opt_verbose)
+ {
+ printf("# Command: %s\n", bootstrap_cmd);
+ }
+ error= run_command(bootstrap_cmd, "r");
+ if (error)
+ fprintf(stderr,
+ "ERROR: Unexpected result from bootstrap. Error code: %d.\n",
+ error);
+
+ return error;
+}
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 014e4fe65cb..71bc936cfe6 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -1,5 +1,6 @@
/*
Copyright (c) 2006, 2012, Oracle and/or its affiliates.
+ Copyright (C) 2010, 2012, Monty Program 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
@@ -38,15 +39,18 @@
static char mysql_path[FN_REFLEN];
static char mysqlcheck_path[FN_REFLEN];
-static my_bool opt_force, debug_info_flag, debug_check_flag, opt_silent;
-static my_bool opt_not_used; /* For compatiblity */
-static uint my_end_arg= 0, opt_verbose;
+static my_bool opt_force, opt_verbose, debug_info_flag, debug_check_flag,
+ opt_systables_only;
+static my_bool opt_not_used, opt_silent;
+static uint my_end_arg= 0;
static char *opt_user= (char*)"root";
static DYNAMIC_STRING ds_args;
static DYNAMIC_STRING conn_args;
static char *opt_password= 0;
+static char *opt_plugin_dir= 0, *opt_default_auth= 0;
+
static my_bool tty_password= 0;
static char opt_tmpdir[FN_REFLEN] = "";
@@ -61,7 +65,7 @@ static my_bool not_used; /* Can't use GET_BOOL without a value pointer */
static my_bool opt_write_binlog;
-#include <help_start.h>
+#define OPT_SILENT OPT_MAX_CLIENT_OPTION
static struct my_option my_long_options[]=
{
@@ -94,6 +98,10 @@ static struct my_option my_long_options[]=
{"default-character-set", OPT_DEFAULT_CHARSET,
"Not used by mysql_upgrade. Only for backward compatibility.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_DEFAULT_AUTH,
+ "Default authentication client-side plugin to use.",
+ &opt_default_auth, &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade "
"has already been executed for the current version of MySQL.",
&opt_force, &opt_force, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -107,6 +115,9 @@ static struct my_option my_long_options[]=
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ &opt_plugin_dir, &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection or 0 for default to, in "
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
#if MYSQL_PORT_DEFAULT == 0
@@ -122,13 +133,17 @@ static struct my_option my_long_options[]=
"Base name of shared memory.", 0,
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"silent", 's', "Print less information", &opt_silent,
+ {"silent", OPT_SILENT, "Print less information", &opt_silent,
&opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"socket", 'S', "The socket file to use for connection.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#include <sslopt-longopts.h>
{"tmpdir", 't', "Directory for temporary files.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"upgrade-system-tables", 's', "Only upgrade the system tables "
+ "do not try to upgrade the data.",
+ &opt_systables_only, &opt_systables_only, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"user", 'u', "User for login if not current user.", &opt_user,
&opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"verbose", 'v', "Display more output about the process.",
@@ -141,8 +156,6 @@ static struct my_option my_long_options[]=
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-#include <help_end.h>
-
static void free_used_memory(void)
{
@@ -215,6 +228,9 @@ static void add_one_option(DYNAMIC_STRING* ds,
case GET_STR:
arg= argument;
break;
+ case GET_BOOL:
+ arg= (*(my_bool *)opt->value) ? "1" : "0";
+ break;
default:
die("internal error at %s: %d",__FILE__, __LINE__);
}
@@ -236,9 +252,9 @@ get_one_option(int optid, const struct my_option *opt,
printf("%s Ver %s Distrib %s, for %s (%s)\n",
my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
- puts("MySQL utility for upgrading databases to new MySQL versions.\n");
+ puts("MariaDB utility for upgrading databases to new MariaDB versions.\n");
my_print_help(my_long_options);
- exit(0);
+ die(0);
break;
case '#':
@@ -282,11 +298,13 @@ get_one_option(int optid, const struct my_option *opt,
}
add_option= 0;
break;
- case 's':
+ case OPT_SILENT:
opt_verbose= 0;
add_option= 0;
break;
case 'f': /* --force */
+ case 's': /* --upgrade-system-tables */
+ case OPT_WRITE_BINLOG: /* --write-binlog */
add_option= FALSE;
break;
@@ -296,6 +314,8 @@ get_one_option(int optid, const struct my_option *opt,
case 'S': /* --socket */
case OPT_MYSQL_PROTOCOL: /* --protocol */
case OPT_SHARED_MEMORY_BASE_NAME: /* --shared-memory-base-name */
+ case OPT_PLUGIN_DIR: /* --plugin-dir */
+ case OPT_DEFAULT_AUTH: /* --default-auth */
add_one_option(&conn_args, opt, argument);
break;
}
@@ -814,7 +834,7 @@ static int run_sql_fix_privilege_tables(void)
}
dynstr_free(&ds_result);
- return found_real_errors;
+ DBUG_RETURN(found_real_errors);
}
@@ -833,9 +853,6 @@ int main(int argc, char **argv)
char self_name[FN_REFLEN];
MY_INIT(argv[0]);
-#ifdef __NETWARE__
- setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
-#endif
#if __WIN__
if (GetModuleFileName(NULL, self_name, FN_REFLEN) == 0)
@@ -848,7 +865,8 @@ int main(int argc, char **argv)
init_dynamic_string(&conn_args, "", 512, 256))
die("Out of memory");
- load_defaults("my", load_default_groups, &argc, &argv);
+ if (load_defaults("my", load_default_groups, &argc, &argv))
+ die(NULL);
defaults_argv= argv; /* Must be freed by 'free_defaults' */
if (handle_options(&argc, &argv, my_long_options, get_one_option))
@@ -872,8 +890,15 @@ int main(int argc, char **argv)
/* Find mysql */
find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"), self_name);
- /* Find mysqlcheck */
- find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name);
+ if (!opt_systables_only)
+ {
+ /* Find mysqlcheck */
+ find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name);
+ }
+ else
+ {
+ printf("The --upgrade-system-tables option was used, databases won't be touched.\n");
+ }
/*
Read the mysql_upgrade_info file to check if mysql_upgrade
@@ -890,8 +915,8 @@ int main(int argc, char **argv)
/*
Run "mysqlcheck" and "mysql_fix_privilege_tables.sql"
*/
- if (run_mysqlcheck_fixnames() ||
- run_mysqlcheck_upgrade() ||
+ if ((!opt_systables_only &&
+ (run_mysqlcheck_fixnames() || run_mysqlcheck_upgrade())) ||
run_sql_fix_privilege_tables())
{
/*
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index a7aa73fb02a..e2ebb883f77 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -1,5 +1,6 @@
/*
Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2012, Monty Program 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
@@ -12,16 +13,13 @@
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* maintaince of mysql databases */
#include "client_priv.h"
#include <signal.h>
-#ifdef THREAD
#include <my_pthread.h> /* because of signal() */
-#endif
#include <sys/stat.h>
#include <mysql.h>
#include <sql_common.h>
@@ -33,7 +31,7 @@
#define MAX_TRUNC_LENGTH 3
char *host= NULL, *user= 0, *opt_password= 0,
- *default_charset= NULL;
+ *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME;
char truncated_var_names[MAX_MYSQL_VAR][MAX_TRUNC_LENGTH];
char ex_var_names[MAX_MYSQL_VAR][FN_REFLEN];
ulonglong last_values[MAX_MYSQL_VAR];
@@ -46,6 +44,7 @@ static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations;
static uint opt_count_iterations= 0, my_end_arg;
static ulong opt_connect_timeout, opt_shutdown_timeout;
static char * unix_port=0;
+static char *opt_plugin_dir= 0, *opt_default_auth= 0;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
@@ -125,10 +124,6 @@ static TYPELIB command_typelib=
static struct my_option my_long_options[] =
{
-#ifdef __NETWARE__
- {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
{"count", 'c',
"Number of iterations to make. This works with -i (--sleep) only.",
&nr_iterations, &nr_iterations, 0, GET_UINT,
@@ -144,7 +139,8 @@ static struct my_option my_long_options[] =
&debug_info_flag, &debug_info_flag,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"force", 'f',
- "Don't ask for confirmation on drop database; with multiple commands, continue even if an error occurs.",
+ "Don't ask for confirmation on drop database; with multiple commands, "
+ "continue even if an error occurs.",
&option_force, &option_force, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
{"compress", 'C', "Use compression in server/client protocol.",
@@ -175,8 +171,7 @@ static struct my_option my_long_options[] =
"/etc/services, "
#endif
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
- &tcp_port,
- &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ &tcp_port, &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"relative", 'r',
@@ -184,10 +179,6 @@ static struct my_option my_long_options[] =
"Currently only works with extended-status.",
&opt_relative, &opt_relative, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
- {"set-variable", 'O',
- "Change the value of a variable. Please note that this option is "
- "deprecated; you can set variables directly with --variable-name=value.",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifdef HAVE_SMEM
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
"Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name,
@@ -222,6 +213,13 @@ static struct my_option my_long_options[] =
{"shutdown_timeout", OPT_SHUTDOWN_TIMEOUT, "", &opt_shutdown_timeout,
&opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG,
SHUTDOWN_DEF_TIMEOUT, 0, 3600*12, 0, 1, 0},
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ &opt_plugin_dir, &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_DEFAULT_AUTH,
+ "Default authentication client-side plugin to use.",
+ &opt_default_auth, &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -236,11 +234,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
int error = 0;
switch(optid) {
-#ifdef __NETWARE__
- case OPT_AUTO_CLOSE:
- setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
- break;
-#endif
case 'c':
opt_count_iterations= 1;
break;
@@ -250,7 +243,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (argument)
{
char *start=argument;
- my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_password);
opt_password=my_strdup(argument,MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start)
@@ -294,9 +287,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
charsets_dir = argument;
#endif
break;
- case 'O':
- WARN_DEPRECATED(VER_CELOSIA, "--set-variable", "--variable-name=value");
- break;
case OPT_MYSQL_PROTOCOL:
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
opt->name);
@@ -313,19 +303,18 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
int main(int argc,char *argv[])
{
- int error= 0, ho_error;
+ int error= 0;
MYSQL mysql;
char **commands, **save_argv;
MY_INIT(argv[0]);
mysql_init(&mysql);
- load_defaults("my",load_default_groups,&argc,&argv);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
+ if ((error= load_defaults("my",load_default_groups,&argc,&argv)))
+ goto err1;
save_argv = argv; /* Save for free_defaults */
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
- {
- free_defaults(save_argv);
- exit(ho_error);
- }
+ if ((error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ goto err2;
if (debug_info_flag)
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
if (debug_check_flag)
@@ -340,8 +329,10 @@ int main(int argc,char *argv[])
if (tty_password)
opt_password = get_tty_password(NullS);
- VOID(signal(SIGINT,endprog)); /* Here if abort */
- VOID(signal(SIGTERM,endprog)); /* Here if abort */
+ (void) signal(SIGINT,endprog); /* Here if abort */
+ (void) signal(SIGTERM,endprog); /* Here if abort */
+
+ sf_leaking_memory=0; /* from now on we cleanup properly */
if (opt_compress)
mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
@@ -363,10 +354,15 @@ int main(int argc,char *argv[])
if (shared_memory_base_name)
mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
#endif
- if (default_charset)
- mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+ mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
error_flags= (myf)(opt_nobeep ? 0 : ME_BELL);
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
if (sql_connect(&mysql, option_wait))
{
/*
@@ -382,7 +378,8 @@ int main(int argc,char *argv[])
/* Return 0 if all commands are PING */
for (; argc > 0; argv++, argc--)
{
- if (find_type(argv[0], &command_typelib, 2) != ADMIN_PING)
+ if (find_type(argv[0], &command_typelib, FIND_TYPE_BASIC) !=
+ ADMIN_PING)
{
error= 1;
break;
@@ -468,14 +465,17 @@ int main(int argc,char *argv[])
} /* got connection */
mysql_close(&mysql);
- my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
- my_free(user,MYF(MY_ALLOW_ZERO_PTR));
+err2:
+ mysql_library_end();
+ my_free(opt_password);
+ my_free(user);
#ifdef HAVE_SMEM
- my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(shared_memory_base_name);
#endif
free_defaults(save_argv);
+err1:
my_end(my_end_arg);
- exit(error ? 1 : 0);
+ exit(error);
return 0;
}
@@ -606,7 +606,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
for (; argc > 0 ; argv++,argc--)
{
int command;
- switch ((command= find_type(argv[0],&command_typelib,2))) {
+ switch ((command= find_type(argv[0],&command_typelib,FIND_TYPE_BASIC))) {
case ADMIN_CREATE:
{
char buff[FN_REFLEN+20];
@@ -686,7 +686,6 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
REFRESH_MASTER | REFRESH_TABLE_STATS |
REFRESH_INDEX_STATS |
REFRESH_USER_STATS |
- REFRESH_SLOW_QUERY_LOG |
REFRESH_CLIENT_STATS)))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
@@ -890,7 +889,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_SLOW_LOG:
{
- if (mysql_query(mysql,"flush slow query logs"))
+ if (mysql_query(mysql,"flush slow logs"))
{
my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -997,23 +996,38 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
char buff[128],crypted_pw[64];
time_t start_time;
+ char *typed_password= NULL, *verified= NULL;
/* Do initialization the same way as we do in mysqld */
start_time=time((time_t*) 0);
my_rnd_init(&rand_st,(ulong) start_time,(ulong) start_time/2);
- if (argc < 2)
+ if (argc < 1)
{
my_printf_error(0, "Too few arguments to change password", error_flags);
return 1;
}
- if (argv[1][0])
+ else if (argc == 1)
+ {
+ /* prompt for password */
+ typed_password= get_tty_password("New password: ");
+ verified= get_tty_password("Confirm new password: ");
+ if (strcmp(typed_password, verified) != 0)
+ {
+ my_printf_error(0,"Passwords don't match",MYF(ME_BELL));
+ return -1;
+ }
+ }
+ else
+ typed_password= argv[1];
+
+ if (typed_password[0])
{
- char *pw= argv[1];
- bool old= (find_type(argv[0], &command_typelib, 2) ==
+ bool old= (find_type(argv[0], &command_typelib, FIND_TYPE_BASIC) ==
ADMIN_OLD_PASSWORD);
#ifdef __WIN__
- uint pw_len= (uint) strlen(pw);
- if (pw_len > 1 && pw[0] == '\'' && pw[pw_len-1] == '\'')
+ size_t pw_len= strlen(typed_password);
+ if (pw_len > 1 && typed_password[0] == '\'' &&
+ typed_password[pw_len-1] == '\'')
printf("Warning: single quotes were not trimmed from the password by"
" your command\nline client, as you might have expected.\n");
#endif
@@ -1051,9 +1065,9 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
}
if (old)
- make_scrambled_password_323(crypted_pw, pw);
+ make_scrambled_password_323(crypted_pw, typed_password);
else
- make_scrambled_password(crypted_pw, pw);
+ make_scrambled_password(crypted_pw, typed_password);
}
else
crypted_pw[0]=0; /* No password */
@@ -1088,6 +1102,12 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return -1;
}
}
+ /* free up memory from prompted password */
+ if (typed_password != argv[1])
+ {
+ my_free(typed_password);
+ my_free(verified);
+ }
argc--; argv++;
break;
}
@@ -1145,13 +1165,11 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return 0;
}
-#include <help_start.h>
static void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s on %s\n",my_progname,ADMIN_VERSION,
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
- NETWARE_SET_SCREEN_MODE(1);
}
@@ -1185,8 +1203,8 @@ static void usage(void)
kill id,id,... Kill mysql threads");
#if MYSQL_VERSION_ID >= 32200
puts("\
- password new-password Change old password to new-password, MySQL 4.1 hashing.\n\
- old-password new-password Change old password to new-password in old format.\n");
+ password [new-password] Change old password to new-password in current format\n\
+ old-password [new-password] Change old password to new-password in old format");
#endif
puts("\
ping Check if mysqld is alive\n\
@@ -1201,7 +1219,6 @@ static void usage(void)
version Get version info from server");
}
-#include <help_end.h>
static int drop_db(MYSQL *mysql, const char *db)
{
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index de44ef5d927..777e68902dd 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -1,5 +1,6 @@
/*
Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2012, Monty Program 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
@@ -30,23 +31,24 @@
#define MYSQL_CLIENT
#undef MYSQL_SERVER
+#define TABLE TABLE_CLIENT
#include "client_priv.h"
#include <my_time.h>
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
-#include "mysql_priv.h"
+#include "sql_priv.h"
#include "log_event.h"
#include "sql_common.h"
#include "my_dir.h"
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
-/* Needed for Rpl_filter */
-CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
#include "sql_string.h" // needed for Rpl_filter
#include "sql_list.h" // needed for Rpl_filter
#include "rpl_filter.h"
-Rpl_filter *binlog_filter;
+#include "mysqld.h"
+
+Rpl_filter *binlog_filter= 0;
#define BIN_LOG_HEADER_SIZE 4
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
@@ -54,6 +56,8 @@ Rpl_filter *binlog_filter;
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES)
+/* Needed for Rpl_filter */
+CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
char server_version[SERVER_VERSION_LENGTH];
ulong server_id = 0;
@@ -69,35 +73,37 @@ static FILE *result_file;
#ifndef DBUG_OFF
static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
#endif
-static const char *load_default_groups[]=
+static const char *load_groups[]=
{ "mysqlbinlog", "client", "client-server", "client-mariadb", 0 };
static void error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
static void warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0;
-static bool opt_hexdump= 0;
+static bool opt_hexdump= 0, opt_version= 0;
const char *base64_output_mode_names[]=
{"NEVER", "AUTO", "ALWAYS", "UNSPEC", "DECODE-ROWS", NullS};
TYPELIB base64_output_mode_typelib=
{ array_elements(base64_output_mode_names) - 1, "",
base64_output_mode_names, NULL };
static enum_base64_output_mode opt_base64_output_mode= BASE64_OUTPUT_UNSPEC;
-static const char *opt_base64_output_mode_str= NullS;
-static const char* database= 0;
+static char *opt_base64_output_mode_str= NullS;
+static char* database= 0;
static my_bool force_opt= 0, short_form= 0, remote_opt= 0;
static my_bool debug_info_flag, debug_check_flag;
static my_bool force_if_open_opt= 1;
static my_bool opt_verify_binlog_checksum= 1;
static ulonglong offset = 0;
-static const char* host = 0;
+static char* host = 0;
static int port= 0;
static uint my_end_arg;
static const char* sock= 0;
+static char *opt_plugindir= 0, *opt_default_auth= 0;
+
#ifdef HAVE_SMEM
static char *shared_memory_base_name= 0;
#endif
-static const char* user = 0;
+static char* user = 0;
static char* pass = 0;
static char *charset= 0;
@@ -172,7 +178,7 @@ Log_event* read_remote_annotate_event(uchar* net_buf, ulong event_len,
error_msg, glob_description_event,
opt_verify_binlog_checksum)))
{
- my_free(event_buf, MYF(0));
+ my_free(event_buf);
return 0;
}
/*
@@ -273,7 +279,7 @@ public:
int init()
{
return init_dynamic_array(&file_names, sizeof(File_name_record),
- 100,100 CALLER_INFO);
+ 100, 100);
}
void init_by_dir_name(const char *dir)
@@ -295,7 +301,7 @@ public:
{
if (ptr->fname)
{
- my_free(ptr->fname, MYF(MY_WME));
+ my_free(ptr->fname);
delete ptr->event;
bzero((char *)ptr, sizeof(File_name_record));
}
@@ -518,12 +524,13 @@ Exit_status Load_log_processor::process_first_event(const char *bname,
ptr= fname + target_dir_name_len;
memcpy(ptr,bname,blen);
ptr+= blen;
- ptr+= my_sprintf(ptr, (ptr, "-%x", file_id));
+ ptr+= sprintf(ptr, "-%x", file_id);
if ((file= create_unique_file(fname,ptr)) < 0)
{
error("Could not construct local filename %s%s.",
target_dir_name,bname);
+ my_free(fname);
delete ce;
DBUG_RETURN(ERROR_STOP);
}
@@ -531,9 +538,15 @@ Exit_status Load_log_processor::process_first_event(const char *bname,
rec.fname= fname;
rec.event= ce;
+ /*
+ fname is freed in process_event()
+ after Execute_load_query_log_event or Execute_load_log_event
+ will have been processed, otherwise in Load_log_processor::destroy()
+ */
if (set_dynamic(&file_names, (uchar*)&rec, file_id))
{
error("Out of memory.");
+ my_free(fname);
delete ce;
DBUG_RETURN(ERROR_STOP);
}
@@ -742,6 +755,31 @@ print_use_stmt(PRINT_EVENT_INFO* pinfo, const Query_log_event *ev)
/**
+ Print "SET skip_replication=..." statement when needed.
+
+ Not all servers support this (only MariaDB from some version on). So we
+ mark the SET to only execute from the version of MariaDB that supports it,
+ and also only output it if we actually see events with the flag set, to not
+ get spurious errors on MySQL@Oracle servers of higher version that do not
+ support the flag.
+
+ So we start out assuming @@skip_replication is 0, and only output a SET
+ statement when it changes.
+*/
+static void
+print_skip_replication_statement(PRINT_EVENT_INFO *pinfo, const Log_event *ev)
+{
+ int cur_val;
+
+ cur_val= (ev->flags & LOG_EVENT_SKIP_REPLICATION_F) != 0;
+ if (cur_val == pinfo->skip_replication)
+ return; /* Not changed. */
+ fprintf(result_file, "/*!50521 SET skip_replication=%d*/%s\n",
+ cur_val, pinfo->delimiter);
+ pinfo->skip_replication= cur_val;
+}
+
+/**
Prints the given event in base64 format.
The header is printed to the head cache and the body is printed to
@@ -885,7 +923,10 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
goto end;
}
else
+ {
+ print_skip_replication_statement(print_event_info, ev);
ev->print(result_file, print_event_info);
+ }
if (head->error == -1)
goto err;
break;
@@ -918,6 +959,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
}
else
{
+ print_skip_replication_statement(print_event_info, ev);
ce->print(result_file, print_event_info, TRUE);
if (head->error == -1)
goto err;
@@ -970,7 +1012,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
*/
convert_path_to_forward_slashes((char*) ce->fname);
ce->print(result_file, print_event_info, TRUE);
- my_free((char*)ce->fname,MYF(MY_WME));
+ my_free((void*)ce->fname);
delete ce;
if (head->error == -1)
goto err;
@@ -989,10 +1031,16 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
if (head->error == -1)
goto err;
if (!remote_opt)
+ {
ev->free_temp_buf(); // free memory allocated in dump_local_log_entries
+ }
else
- // disassociate but not free dump_remote_log_entries time memory
+ {
+ /*
+ disassociate but not free dump_remote_log_entries time memory
+ */
ev->temp_buf= 0;
+ }
/*
We don't want this event to be deleted now, so let's hide it (I
(Guilhem) should later see if this triggers a non-serious Valgrind
@@ -1028,11 +1076,12 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
if (fname)
{
convert_path_to_forward_slashes(fname);
+ print_skip_replication_statement(print_event_info, ev);
exlq->print(result_file, print_event_info, fname);
if (head->error == -1)
{
if (fname)
- my_free(fname, MYF(MY_WME));
+ my_free(fname);
goto err;
}
}
@@ -1042,7 +1091,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
}
if (fname)
- my_free(fname, MYF(MY_WME));
+ my_free(fname);
break;
}
case ANNOTATE_ROWS_EVENT:
@@ -1163,6 +1212,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
/* FALL THROUGH */
}
default:
+ print_skip_replication_statement(print_event_info, ev);
ev->print(result_file, print_event_info);
if (head->error == -1)
goto err;
@@ -1192,14 +1242,10 @@ end:
}
-static struct my_option my_long_options[] =
+static struct my_option my_options[] =
{
{"help", '?', "Display this help and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#ifdef __NETWARE__
- {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
{"base64-output", OPT_BASE64_OUTPUT_MODE,
/* 'unspec' is not mentioned because it is just a placeholder. */
"Determine when the output statements should be base64-encoded BINLOG "
@@ -1207,10 +1253,11 @@ static struct my_option my_long_options[] =
"row-based events; 'decode-rows' decodes row events into commented SQL "
"statements if the --verbose option is also given; 'auto' prints base64 "
"only when necessary (i.e., for row-based events and format description "
- "events); 'always' prints base64 whenever possible. 'always' is for "
- "debugging only and should not be used in a production system. If this "
- "argument is not given, the default is 'auto'; if it is given with no "
- "argument, 'always' is used.",
+ "events); 'always' prints base64 whenever possible. 'always' is "
+ "deprecated, will be removed in a future version, and should not be used "
+ "in a production system. --base64-output with no 'name' argument is "
+ "equivalent to --base64-output=always and is also deprecated. If no "
+ "--base64-output[=name] option is given at all, the default is 'auto'.",
&opt_base64_output_mode_str, &opt_base64_output_mode_str,
0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
/*
@@ -1235,6 +1282,10 @@ static struct my_option my_long_options[] =
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
&debug_info_flag, &debug_info_flag,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_DEFAULT_AUTH,
+ "Default authentication client-side plugin to use.",
+ &opt_default_auth, &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"disable-log-bin", 'D', "Disable binary log. This is useful, if you "
"enabled --to-last-log and are sending the output to the same MySQL server. "
"This way you could avoid an endless loop. You would also like to use it "
@@ -1260,6 +1311,9 @@ static struct my_option my_long_options[] =
0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p', "Password to connect to remote server.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ &opt_plugindir, &opt_plugindir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection or 0 for default to, in "
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
#if MYSQL_PORT_DEFAULT == 0
@@ -1268,11 +1322,6 @@ static struct my_option my_long_options[] =
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
&port, &port, 0, GET_INT, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
- {"position", OPT_POSITION, "Deprecated. Use --start-position instead.",
- &start_position, &start_position, 0, GET_ULL,
- REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
- /* COM_BINLOG_DUMP accepts only 4 bytes for the position */
- (ulonglong)(~(uint32)0), 0, 0, 0},
{"protocol", OPT_MYSQL_PROTOCOL,
"The protocol to use for connection (tcp, socket, pipe, memory).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -1281,7 +1330,7 @@ static struct my_option my_long_options[] =
0, 0},
{"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"server-id", OPT_SERVER_ID,
+ {"server-id", 0,
"Extract only binlog entries created by the server having the given id.",
&server_id, &server_id, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -1301,7 +1350,7 @@ static struct my_option my_long_options[] =
&short_form, &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"socket", 'S', "The socket file to use for connection.",
- &sock, &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
+ &sock, &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
0, 0},
{"start-datetime", OPT_START_DATETIME,
"Start reading the binlog at first event having a datetime equal or "
@@ -1433,23 +1482,22 @@ static void warning(const char *format,...)
*/
static void cleanup()
{
- my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*) database, MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*) host, MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*) user, MYF(MY_ALLOW_ZERO_PTR));
- my_free((char*) dirname_for_local_load, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(pass);
+ my_free(database);
+ my_free(host);
+ my_free(user);
+ my_free(const_cast<char*>(dirname_for_local_load));
+ delete binlog_filter;
delete glob_description_event;
if (mysql)
mysql_close(mysql);
}
-#include <help_start.h>
static void print_version()
{
printf("%s Ver 3.3 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
- NETWARE_SET_SCREEN_MODE(1);
}
@@ -1461,8 +1509,8 @@ static void usage()
Dumps a MySQL binary log in a format usable for viewing or for piping to\n\
the mysql command line client.\n\n");
printf("Usage: %s [options] log-files\n", my_progname);
- my_print_help(my_long_options);
- my_print_variables(my_long_options);
+ my_print_help(my_options);
+ my_print_variables(my_options);
}
@@ -1488,7 +1536,6 @@ static my_time_t convert_str_to_timestamp(const char* str)
my_system_gmt_sec(&l_time, &dummy_my_timezone, &dummy_in_dst_time_gap);
}
-#include <help_end.h>
extern "C" my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
@@ -1496,11 +1543,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
{
bool tty_password=0;
switch (optid) {
-#ifdef __NETWARE__
- case OPT_AUTO_CLOSE:
- setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
- break;
-#endif
#ifndef DBUG_OFF
case '#':
DBUG_PUSH(argument ? argument : default_dbug_option);
@@ -1514,7 +1556,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
argument= (char*) ""; // Don't require password
if (argument)
{
- my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(pass);
char *start=argument;
pass= my_strdup(argument,MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */
@@ -1531,9 +1573,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'R':
remote_opt= 1;
break;
- case OPT_POSITION:
- WARN_DEPRECATED(VER_CELOSIA, "--position", "--start-position");
- break;
case OPT_MYSQL_PROTOCOL:
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
opt->name);
@@ -1608,10 +1647,12 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case 'V':
print_version();
- exit(0);
+ opt_version= 1;
+ break;
case '?':
usage();
- exit(0);
+ opt_version= 1;
+ break;
}
if (tty_password)
pass= get_tty_password(NullS);
@@ -1625,7 +1666,7 @@ static int parse_args(int *argc, char*** argv)
int ho_error;
result_file = stdout;
- if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
+ if ((ho_error=handle_options(argc, argv, my_options, get_one_option)))
exit(ho_error);
if (debug_info_flag)
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
@@ -1656,6 +1697,12 @@ static Exit_status safe_connect()
return ERROR_STOP;
}
+ if (opt_plugindir && *opt_plugindir)
+ mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugindir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
if (opt_protocol)
mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
#ifdef HAVE_SMEM
@@ -2333,27 +2380,37 @@ int main(int argc, char** argv)
my_init_time(); // for time functions
init_alloc_root(&s_mem_root, 16384, 0);
+ if (load_defaults("my", load_groups, &argc, &argv))
+ exit(1);
+
if (!(binlog_filter= new Rpl_filter))
{
error("Failed to create Rpl_filter");
exit(1);
}
- if (load_defaults("my", load_default_groups, &argc, &argv))
- exit(1);
-
defaults_argv= argv;
parse_args(&argc, (char***)&argv);
- if (!argc)
+ if (!argc || opt_version)
{
- usage();
+ if (!argc)
+ usage();
+ cleanup();
free_defaults(defaults_argv);
- exit(1);
+ my_end(my_end_arg);
+ exit(!opt_version);
}
if (opt_base64_output_mode == BASE64_OUTPUT_UNSPEC)
opt_base64_output_mode= BASE64_OUTPUT_AUTO;
+ if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
+ warning("The --base64-output=always flag and the --base64-output flag "
+ "(with '=MODE' omitted), are deprecated. "
+ "The output generated when these flags are used cannot be "
+ "parsed by mysql 5.6.0 and later. "
+ "The flags will be removed in a future version. "
+ "Please use --base64-output=auto instead.");
my_set_max_open_files(open_files_limit);
@@ -2429,7 +2486,6 @@ int main(int argc, char** argv)
my_fclose(result_file, MYF(0));
cleanup();
free_annotate_event();
- delete binlog_filter;
free_root(&s_mem_root, MYF(0));
free_defaults(defaults_argv);
my_free_open_file_info();
@@ -2453,12 +2509,13 @@ void *sql_alloc(size_t size)
the server
*/
+#undef TABLE
#include "my_decimal.h"
#include "decimal.c"
#include "my_decimal.cc"
#include "log_event.cc"
#include "log_event_old.cc"
+#include "rpl_utility.cc"
#include "sql_string.cc"
#include "sql_list.cc"
#include "rpl_filter.cc"
-#include "rpl_utility.cc"
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index bfc18161380..4218f2da62c 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -1,5 +1,6 @@
/*
Copyright (c) 2001, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2011, Monty Program 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
@@ -15,6 +16,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+/* By Jani Tolonen, 2001-04-20, MySQL Development Team */
+
#define CHECK_VERSION "2.7.0"
#include "client_priv.h"
@@ -42,14 +45,13 @@ static int my_end_arg;
static char * opt_mysql_unix_port = 0;
static char *opt_password = 0, *current_user = 0,
*default_charset= 0, *current_host= 0;
+static char *opt_plugin_dir= 0, *opt_default_auth= 0;
static int first_error = 0;
-DYNAMIC_ARRAY tables4repair;
-#ifdef HAVE_SMEM
+DYNAMIC_ARRAY tables4repair, tables4rebuild;
static char *shared_memory_base_name=0;
-#endif
static uint opt_protocol=0;
-enum operations { DO_CHECK, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE };
+enum operations { DO_CHECK=1, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE };
static struct my_option my_long_options[] =
{
@@ -63,10 +65,6 @@ static struct my_option my_long_options[] =
"Instead of issuing one query for each table, use one query per database, naming all tables in the database in a comma-separated list.",
&opt_all_in_1, &opt_all_in_1, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
-#ifdef __NETWARE__
- {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
{"auto-repair", OPT_AUTO_REPAIR,
"If a checked table is corrupted, automatically fix it. Repairing will be done after all tables have been checked, if corrupted ones were found.",
&opt_auto_repair, &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0,
@@ -105,6 +103,10 @@ static struct my_option my_long_options[] =
{"default-character-set", OPT_DEFAULT_CHARSET,
"Set the default character set.", &default_charset,
&default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_DEFAULT_AUTH,
+ "Default authentication client-side plugin to use.",
+ &opt_default_auth, &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"fast",'F', "Check only tables that haven't been closed properly.",
&opt_fast, &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
0},
@@ -127,12 +129,13 @@ static struct my_option my_long_options[] =
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"host",'h', "Connect to host.", &current_host,
- &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ &current_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"medium-check", 'm',
"Faster than extended-check, but only finds 99.99 percent of all errors. Should be good enough for most cases.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"write-binlog", OPT_WRITE_BINLOG,
- "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Enabled by default; use --skip-write-binlog when commands should not be sent to replication slaves.",
+ "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Use --skip-write-binlog "
+ "when commands should not be sent to replication slaves.",
&opt_write_binlog, &opt_write_binlog, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
{"optimize", 'o', "Optimize table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
@@ -144,14 +147,16 @@ static struct my_option my_long_options[] =
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ &opt_plugin_dir, &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection or 0 for default to, in "
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
#if MYSQL_PORT_DEFAULT == 0
"/etc/services, "
#endif
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
- &opt_mysql_port,
- &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
+ &opt_mysql_port, &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0,
0},
{"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -213,18 +218,17 @@ static uint fixed_name_length(const char *name);
static char *fix_table_name(char *dest, char *src);
int what_to_do = 0;
-#include <help_start.h>
static void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n", my_progname, CHECK_VERSION,
MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
- NETWARE_SET_SCREEN_MODE(1);
} /* print_version */
static void usage(void)
{
+ DBUG_ENTER("usage");
print_version();
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
puts("This program can be used to CHECK (-c, -m, -C), REPAIR (-r), ANALYZE (-a),");
@@ -244,20 +248,18 @@ static void usage(void)
print_defaults("my", load_default_groups);
my_print_help(my_long_options);
my_print_variables(my_long_options);
+ DBUG_VOID_RETURN;
} /* usage */
-#include <help_end.h>
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
+ int orig_what_to_do= what_to_do;
+ DBUG_ENTER("get_one_option");
+
switch(optid) {
-#ifdef __NETWARE__
- case OPT_AUTO_CLOSE:
- setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
- break;
-#endif
case 'a':
what_to_do = DO_ANALYZE;
break;
@@ -292,7 +294,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (argument)
{
char *start = argument;
- my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_password);
opt_password = my_strdup(argument, MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start)
@@ -331,13 +333,21 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt->name);
break;
}
- return 0;
+
+ if (orig_what_to_do && (what_to_do != orig_what_to_do))
+ {
+ fprintf(stderr, "Error: %s doesn't support multiple contradicting commands.\n",
+ my_progname);
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
}
static int get_options(int *argc, char ***argv)
{
int ho_error;
+ DBUG_ENTER("get_options");
if (*argc == 1)
{
@@ -345,8 +355,6 @@ static int get_options(int *argc, char ***argv)
exit(0);
}
- load_defaults("my", load_default_groups, argc, argv);
-
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
exit(ho_error);
@@ -370,29 +378,32 @@ static int get_options(int *argc, char ***argv)
If there's no --default-character-set option given with
--fix-table-name or --fix-db-name set the default character set to "utf8".
*/
- if (!default_charset && (opt_fix_db_names || opt_fix_table_names))
+ if (!default_charset)
{
- default_charset= (char*) "utf8";
+ if (opt_fix_db_names || opt_fix_table_names)
+ default_charset= (char*) "utf8";
+ else
+ default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME;
}
- if (default_charset && !get_charset_by_csname(default_charset, MY_CS_PRIMARY,
- MYF(MY_WME)))
+ if (strcmp(default_charset, MYSQL_AUTODETECT_CHARSET_NAME) &&
+ !get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME)))
{
printf("Unsupported character set: %s\n", default_charset);
- return 1;
+ DBUG_RETURN(1);
}
if (*argc > 0 && opt_alldbs)
{
printf("You should give only options, no arguments at all, with option\n");
printf("--all-databases. Please see %s --help for more information.\n",
my_progname);
- return 1;
+ DBUG_RETURN(1);
}
if (*argc < 1 && !opt_alldbs)
{
printf("You forgot to give the arguments! Please see %s --help\n",
my_progname);
printf("for more information.\n");
- return 1;
+ DBUG_RETURN(1);
}
if (tty_password)
opt_password = get_tty_password(NullS);
@@ -400,7 +411,7 @@ static int get_options(int *argc, char ***argv)
my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
if (debug_check_flag)
my_end_arg= MY_CHECK_ERROR;
- return(0);
+ DBUG_RETURN((0));
} /* get_options */
@@ -409,13 +420,14 @@ static int process_all_databases()
MYSQL_ROW row;
MYSQL_RES *tableres;
int result = 0;
+ DBUG_ENTER("process_all_databases");
if (mysql_query(sock, "SHOW DATABASES") ||
!(tableres = mysql_store_result(sock)))
{
my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
MYF(0), mysql_error(sock));
- return 1;
+ DBUG_RETURN(1);
}
if (verbose)
printf("Processing databases\n");
@@ -424,7 +436,8 @@ static int process_all_databases()
if (process_one_db(row[0]))
result = 1;
}
- return result;
+ mysql_free_result(tableres);
+ DBUG_RETURN(result);
}
/* process_all_databases */
@@ -432,6 +445,8 @@ static int process_all_databases()
static int process_databases(char **db_names)
{
int result = 0;
+ DBUG_ENTER("process_databases");
+
if (verbose)
printf("Processing databases\n");
for ( ; *db_names ; db_names++)
@@ -439,14 +454,16 @@ static int process_databases(char **db_names)
if (process_one_db(*db_names))
result = 1;
}
- return result;
+ DBUG_RETURN(result);
} /* process_databases */
static int process_selected_tables(char *db, char **table_names, int tables)
{
+ DBUG_ENTER("process_selected_tables");
+
if (use_db(db))
- return 1;
+ DBUG_RETURN(1);
if (opt_all_in_1 && what_to_do != DO_UPGRADE)
{
/*
@@ -463,7 +480,7 @@ static int process_selected_tables(char *db, char **table_names, int tables)
if (!(table_names_comma_sep = (char *)
my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
- return 1;
+ DBUG_RETURN(1);
for (end = table_names_comma_sep + 1; tables > 0;
tables--, table_names++)
@@ -473,12 +490,12 @@ static int process_selected_tables(char *db, char **table_names, int tables)
}
*--end = 0;
handle_request_for_tables(table_names_comma_sep + 1, (uint) (tot_length - 1));
- my_free(table_names_comma_sep, MYF(0));
+ my_free(table_names_comma_sep);
}
else
for (; tables > 0; tables--, table_names++)
handle_request_for_tables(*table_names, fixed_name_length(*table_names));
- return 0;
+ DBUG_RETURN(0);
} /* process_selected_tables */
@@ -486,20 +503,24 @@ static uint fixed_name_length(const char *name)
{
const char *p;
uint extra_length= 2; /* count the first/last backticks */
-
+ DBUG_ENTER("fixed_name_length");
+
for (p= name; *p; p++)
{
if (*p == '`')
extra_length++;
else if (*p == '.')
extra_length+= 2;
+
}
- return (uint) ((p - name) + extra_length);
+ DBUG_RETURN((uint) ((p - name) + extra_length));
}
static char *fix_table_name(char *dest, char *src)
{
+ DBUG_ENTER("fix_table_name");
+
*dest++= '`';
for (; *src; src++)
{
@@ -517,27 +538,28 @@ static char *fix_table_name(char *dest, char *src)
}
}
*dest++= '`';
- return dest;
+
+ DBUG_RETURN(dest);
}
static int process_all_tables_in_db(char *database)
{
- MYSQL_RES *res;
+ MYSQL_RES *UNINIT_VAR(res);
MYSQL_ROW row;
uint num_columns;
my_bool system_database= 0;
+ DBUG_ENTER("process_all_tables_in_db");
- LINT_INIT(res);
if (use_db(database))
- return 1;
+ DBUG_RETURN(1);
if ((mysql_query(sock, "SHOW /*!50002 FULL*/ TABLES") &&
mysql_query(sock, "SHOW TABLES")) ||
!(res= mysql_store_result(sock)))
{
my_printf_error(0, "Error: Couldn't get table list for database %s: %s",
MYF(0), database, mysql_error(sock));
- return 1;
+ DBUG_RETURN(1);
}
if (!strcmp(database, "mysql") || !strcmp(database, "MYSQL"))
@@ -563,7 +585,7 @@ static int process_all_tables_in_db(char *database)
if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
{
mysql_free_result(res);
- return 1;
+ DBUG_RETURN(1);
}
for (end = tables + 1; (row = mysql_fetch_row(res)) ;)
{
@@ -576,7 +598,7 @@ static int process_all_tables_in_db(char *database)
*--end = 0;
if (tot_length)
handle_request_for_tables(tables + 1, tot_length - 1);
- my_free(tables, MYF(0));
+ my_free(tables);
}
else
{
@@ -594,7 +616,7 @@ static int process_all_tables_in_db(char *database)
}
}
mysql_free_result(res);
- return 0;
+ DBUG_RETURN(0);
} /* process_all_tables_in_db */
@@ -603,8 +625,10 @@ static int fix_table_storage_name(const char *name)
{
char qbuf[100 + NAME_LEN*4];
int rc= 0;
+ DBUG_ENTER("fix_table_storage_name");
+
if (strncmp(name, "#mysql50#", 9))
- return 1;
+ DBUG_RETURN(1);
sprintf(qbuf, "RENAME TABLE `%s` TO `%s`", name, name + 9);
if (mysql_query(sock, qbuf))
{
@@ -614,15 +638,17 @@ static int fix_table_storage_name(const char *name)
}
if (verbose)
printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
- return rc;
+ DBUG_RETURN(rc);
}
static int fix_database_storage_name(const char *name)
{
char qbuf[100 + NAME_LEN*4];
int rc= 0;
+ DBUG_ENTER("fix_database_storage_name");
+
if (strncmp(name, "#mysql50#", 9))
- return 1;
+ DBUG_RETURN(1);
sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name);
if (mysql_query(sock, qbuf))
{
@@ -632,11 +658,36 @@ static int fix_database_storage_name(const char *name)
}
if (verbose)
printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
- return rc;
+ DBUG_RETURN(rc);
+}
+
+static int rebuild_table(char *name)
+{
+ char *query, *ptr;
+ int rc= 0;
+ DBUG_ENTER("rebuild_table");
+
+ query= (char*)my_malloc(sizeof(char) * (12 + fixed_name_length(name) + 6 + 1),
+ MYF(MY_WME));
+ if (!query)
+ DBUG_RETURN(1);
+ ptr= strmov(query, "ALTER TABLE ");
+ ptr= fix_table_name(ptr, name);
+ ptr= strxmov(ptr, " FORCE", NullS);
+ if (mysql_real_query(sock, query, (uint)(ptr - query)))
+ {
+ fprintf(stderr, "Failed to %s\n", query);
+ fprintf(stderr, "Error: %s\n", mysql_error(sock));
+ rc= 1;
+ }
+ my_free(query);
+ DBUG_RETURN(rc);
}
static int process_one_db(char *database)
{
+ DBUG_ENTER("process_one_db");
+
if (verbose)
puts(database);
if (what_to_do == DO_UPGRADE)
@@ -648,35 +699,42 @@ static int process_one_db(char *database)
database+= 9;
}
if (rc || !opt_fix_table_names)
- return rc;
+ DBUG_RETURN(rc);
}
- return process_all_tables_in_db(database);
+ DBUG_RETURN(process_all_tables_in_db(database));
}
static int use_db(char *database)
{
- if (mysql_get_server_version(sock) >= 50003 &&
- !my_strcasecmp(&my_charset_latin1, database, "information_schema"))
- return 1;
+ DBUG_ENTER("use_db");
+
+ if (mysql_get_server_version(sock) >= FIRST_INFORMATION_SCHEMA_VERSION &&
+ !my_strcasecmp(&my_charset_latin1, database, INFORMATION_SCHEMA_DB_NAME))
+ DBUG_RETURN(1);
+ if (mysql_get_server_version(sock) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
+ !my_strcasecmp(&my_charset_latin1, database, PERFORMANCE_SCHEMA_DB_NAME))
+ DBUG_RETURN(1);
if (mysql_select_db(sock, database))
{
DBerror(sock, "when selecting the database");
- return 1;
+ DBUG_RETURN(1);
}
- return 0;
+ DBUG_RETURN(0);
} /* use_db */
static int disable_binlog()
{
const char *stmt= "SET SQL_LOG_BIN=0";
+ DBUG_ENTER("disable_binlog");
+
if (mysql_query(sock, stmt))
{
fprintf(stderr, "Failed to %s\n", stmt);
fprintf(stderr, "Error: %s\n", mysql_error(sock));
- return 1;
+ DBUG_RETURN(1);
}
- return 0;
+ DBUG_RETURN(0);
}
static int handle_request_for_tables(char *tables, uint length)
@@ -685,6 +743,7 @@ static int handle_request_for_tables(char *tables, uint length)
char table_name_buff[NAME_CHAR_LEN*2*2+1], *table_name;
uint query_length= 0;
const char *op = 0;
+ DBUG_ENTER("handle_request_for_tables");
options[0] = 0;
end = options;
@@ -711,16 +770,15 @@ static int handle_request_for_tables(char *tables, uint length)
op= (opt_write_binlog) ? "OPTIMIZE" : "OPTIMIZE NO_WRITE_TO_BINLOG";
break;
case DO_UPGRADE:
- return fix_table_storage_name(tables);
+ DBUG_RETURN(fix_table_storage_name(tables));
}
if (!(query =(char *) my_malloc((sizeof(char)*(length+110)), MYF(MY_WME))))
- return 1;
+ DBUG_RETURN(1);
if (opt_all_in_1)
{
/* No backticks here as we added them before */
- query_length= my_sprintf(query,
- (query, "%s TABLE %s %s", op, tables, options));
+ query_length= sprintf(query, "%s TABLE %s %s", op, tables, options);
table_name= tables;
}
else
@@ -739,23 +797,22 @@ static int handle_request_for_tables(char *tables, uint length)
{
sprintf(message, "when executing '%s TABLE ... %s'", op, options);
DBerror(sock, message);
- my_free(query, MYF(0));
- return 1;
+ my_free(query);
+ DBUG_RETURN(1);
}
print_result();
if (opt_flush_tables)
{
- query_length= my_sprintf(query,
- (query, "FLUSH TABLES %s", table_name));
+ query_length= sprintf(query, "FLUSH TABLES %s", table_name);
if (mysql_real_query(sock, query, query_length))
{
DBerror(sock, query);
- my_free(query, MYF(0));
- return 1;
+ my_free(query);
+ DBUG_RETURN(1);
}
}
- my_free(query, MYF(0));
- return 0;
+ my_free(query);
+ DBUG_RETURN(0);
}
@@ -765,7 +822,8 @@ static void print_result()
MYSQL_ROW row;
char prev[(NAME_LEN+9)*2+2];
uint i;
- my_bool found_error=0;
+ my_bool found_error=0, table_rebuild=0;
+ DBUG_ENTER("print_result");
res = mysql_use_result(sock);
@@ -784,8 +842,14 @@ static void print_result()
*/
if (found_error && opt_auto_repair && what_to_do != DO_REPAIR &&
strcmp(row[3],"OK"))
- insert_dynamic(&tables4repair, (uchar*) prev);
+ {
+ if (table_rebuild)
+ insert_dynamic(&tables4rebuild, (uchar*) prev);
+ else
+ insert_dynamic(&tables4repair, (uchar*) prev);
+ }
found_error=0;
+ table_rebuild=0;
if (opt_silent)
continue;
}
@@ -798,12 +862,16 @@ static void print_result()
we have to run upgrade on it. In this case we write a nicer message
than "Please do "REPAIR TABLE""...
*/
- if (!strcmp(row[2],"error") && strinstr(row[3],"REPAIR TABLE") != 0)
+ if (!strcmp(row[2],"error") && strstr(row[3],"REPAIR TABLE"))
printf("%-50s %s", row[0], "Needs upgrade");
else
printf("%s\n%-9s: %s", row[0], row[2], row[3]);
if (strcmp(row[2],"note"))
+ {
found_error=1;
+ if (opt_auto_repair && strstr(row[3], "ALTER TABLE") != NULL)
+ table_rebuild=1;
+ }
}
else
printf("%-9s: %s", row[2], row[3]);
@@ -812,8 +880,14 @@ static void print_result()
}
/* add the last table to be repaired to the list */
if (found_error && opt_auto_repair && what_to_do != DO_REPAIR)
- insert_dynamic(&tables4repair, (uchar*) prev);
+ {
+ if (table_rebuild)
+ insert_dynamic(&tables4rebuild, (uchar*) prev);
+ else
+ insert_dynamic(&tables4repair, (uchar*) prev);
+ }
mysql_free_result(res);
+ DBUG_VOID_RETURN;
}
@@ -834,28 +908,34 @@ static int dbConnect(char *host, char *user, char *passwd)
#endif
if (opt_protocol)
mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
-#ifdef HAVE_SMEM
if (shared_memory_base_name)
mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
-#endif
- if (default_charset)
- mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
+
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(&mysql_connection, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
+ mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
if (!(sock = mysql_real_connect(&mysql_connection, host, user, passwd,
NULL, opt_mysql_port, opt_mysql_unix_port, 0)))
{
DBerror(&mysql_connection, "when trying to connect");
- return 1;
+ DBUG_RETURN(1);
}
mysql_connection.reconnect= 1;
- return 0;
+ DBUG_RETURN(0);
} /* dbConnect */
static void dbDisconnect(char *host)
{
+ DBUG_ENTER("dbDisconnect");
if (verbose > 1)
fprintf(stderr, "# Disconnecting from %s...\n", host ? host : "localhost");
mysql_close(sock);
+ DBUG_VOID_RETURN;
} /* dbDisconnect */
@@ -871,45 +951,52 @@ static void DBerror(MYSQL *mysql, const char *when)
static void safe_exit(int error)
{
+ DBUG_ENTER("safe_exit");
if (!first_error)
first_error= error;
if (ignore_errors)
- return;
+ DBUG_VOID_RETURN;
if (sock)
mysql_close(sock);
+ sf_leaking_memory= 1; /* don't check for memory leaks */
exit(error);
+ DBUG_VOID_RETURN;
}
int main(int argc, char **argv)
{
+ int ret= EX_USAGE;
+ char **defaults_argv;
+
MY_INIT(argv[0]);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
/*
** Check out the args
*/
+ if (load_defaults("my", load_default_groups, &argc, &argv))
+ goto end2;
+
+ defaults_argv= argv;
if (get_options(&argc, &argv))
- {
- my_end(my_end_arg);
- exit(EX_USAGE);
- }
+ goto end1;
+ sf_leaking_memory=0; /* from now on we cleanup properly */
+
+ ret= EX_MYSQLERR;
if (dbConnect(current_host, current_user, opt_password))
- exit(EX_MYSQLERR);
+ goto end1;
+ ret= 1;
if (!opt_write_binlog)
{
if (disable_binlog())
- {
- first_error= 1;
goto end;
- }
}
if (opt_auto_repair &&
- my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64))
- {
- first_error = 1;
+ (my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64) ||
+ my_init_dynamic_array(&tables4rebuild, sizeof(char)*(NAME_LEN*2+2),16,64)))
goto end;
- }
if (opt_alldbs)
process_all_databases();
@@ -923,7 +1010,7 @@ int main(int argc, char **argv)
{
uint i;
- if (!opt_silent && tables4repair.elements)
+ if (!opt_silent && (tables4repair.elements || tables4rebuild.elements))
puts("\nRepairing tables");
what_to_do = DO_REPAIR;
for (i = 0; i < tables4repair.elements ; i++)
@@ -931,15 +1018,24 @@ int main(int argc, char **argv)
char *name= (char*) dynamic_array_ptr(&tables4repair, i);
handle_request_for_tables(name, fixed_name_length(name));
}
+ for (i = 0; i < tables4rebuild.elements ; i++)
+ rebuild_table((char*) dynamic_array_ptr(&tables4rebuild, i));
}
+ ret= test(first_error);
+
end:
dbDisconnect(current_host);
if (opt_auto_repair)
+ {
delete_dynamic(&tables4repair);
- my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
-#ifdef HAVE_SMEM
- my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
-#endif
+ delete_dynamic(&tables4rebuild);
+ }
+ end1:
+ my_free(opt_password);
+ my_free(shared_memory_base_name);
+ mysql_library_end();
+ free_defaults(defaults_argv);
+ end2:
my_end(my_end_arg);
- return(first_error!=0);
+ return ret;
} /* main */
diff --git a/client/mysqldump.c b/client/mysqldump.c
index b4db4400341..284ea1e760a 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1,5 +1,6 @@
/*
Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2012, Monty Program 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
@@ -12,7 +13,7 @@
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* mysqldump.c - Dump a tables contents and format to an ASCII file
@@ -52,7 +53,6 @@
#include "mysql.h"
#include "mysql_version.h"
#include "mysqld_error.h"
-#include "../sql/ha_ndbcluster_tables.h"
#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
@@ -117,6 +117,8 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
opt_complete_insert= 0, opt_drop_database= 0,
opt_replace_into= 0,
opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1,
+ opt_slave_apply= 0,
+ opt_include_master_host_port= 0,
opt_events= 0, opt_comments_used= 0,
opt_alltspcs=0, opt_notspcs= 0;
static my_bool insert_pat_inited= 0, debug_info_flag= 0, debug_check_flag= 0;
@@ -137,7 +139,10 @@ static my_bool server_supports_switching_charsets= TRUE;
static ulong opt_compatible_mode= 0;
#define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1
#define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2
+#define MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL 1
+#define MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL 2
static uint opt_mysql_port= 0, opt_master_data;
+static uint opt_slave_data;
static uint my_end_arg;
static char * opt_mysql_unix_port=0;
static int first_error=0;
@@ -150,6 +155,7 @@ FILE *stderror_file=0;
static char *shared_memory_base_name=0;
#endif
static uint opt_protocol= 0;
+static char *opt_plugin_dir= 0, *opt_default_auth= 0;
/*
Dynamic_string wrapper functions. In this file use these
@@ -198,9 +204,6 @@ HASH ignore_table;
static struct my_option my_long_options[] =
{
- {"all", OPT_ALL, "Deprecated. Use --create-options instead.",
- &create_options, &create_options, 0, GET_BOOL, NO_ARG, 1,
- 0, 0, 0, 0, 0},
{"all-databases", 'A',
"Dump all the databases. This will be same as --databases with all databases selected.",
&opt_alldbs, &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
@@ -225,10 +228,10 @@ static struct my_option my_long_options[] =
{"allow-keywords", OPT_KEYWORDS,
"Allow creation of column names that are keywords.", &opt_keywords,
&opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-#ifdef __NETWARE__
- {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
+ {"apply-slave-statements", OPT_MYSQLDUMP_SLAVE_APPLY,
+ "Adds 'STOP SLAVE' prior to 'CHANGE MASTER' and 'START SLAVE' to bottom of dump.",
+ &opt_slave_apply, &opt_slave_apply, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
"Directory for character set files.", (char**) &charsets_dir,
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -236,13 +239,20 @@ static struct my_option my_long_options[] =
&opt_comments, &opt_comments, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
{"compatible", OPT_COMPATIBLE,
- "Change the dump to be compatible with a given mode. By default tables are dumped in a format optimized for MySQL. Legal modes are: ansi, mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb, no_key_options, no_table_options, no_field_options. One can use several modes separated by commas. Note: Requires MySQL server version 4.1.0 or higher. This option is ignored with earlier server versions.",
+ "Change the dump to be compatible with a given mode. By default tables "
+ "are dumped in a format optimized for MySQL. Legal modes are: ansi, "
+ "mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb, no_key_options, "
+ "no_table_options, no_field_options. One can use several modes separated "
+ "by commas. Note: Requires MySQL server version 4.1.0 or higher. "
+ "This option is ignored with earlier server versions.",
&opt_compatible_mode_str, &opt_compatible_mode_str, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"compact", OPT_COMPACT,
- "Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs. Enables options --skip-add-drop-table --skip-add-locks --skip-comments --skip-disable-keys --skip-set-charset.",
- &opt_compact, &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
- 0, 0},
+ "Give less verbose output (useful for debugging). Disables structure "
+ "comments and header/footer constructs. Enables options --skip-add-"
+ "drop-table --skip-add-locks --skip-comments --skip-disable-keys "
+ "--skip-set-charset.",
+ &opt_compact, &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"complete-insert", 'c', "Use complete insert statements.",
&opt_complete_insert, &opt_complete_insert, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -281,8 +291,22 @@ static struct my_option my_long_options[] =
&opt_delete_master_logs, &opt_delete_master_logs, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"disable-keys", 'K',
- "'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", &opt_disable_keys,
+ "'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER "
+ "TABLE tb_name ENABLE KEYS */; will be put in the output.", &opt_disable_keys,
&opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"dump-slave", OPT_MYSQLDUMP_SLAVE_DATA,
+ "This causes the binary log position and filename of the master to be "
+ "appended to the dumped data output. Setting the value to 1, will print"
+ "it as a CHANGE MASTER command in the dumped data output; if equal"
+ " to 2, that command will be prefixed with a comment symbol. "
+ "This option will turn --lock-all-tables on, unless "
+ "--single-transaction is specified too (in which case a "
+ "global read lock is only taken a short time at the beginning of the dump "
+ "- don't forget to read about --single-transaction below). In all cases "
+ "any action on logs will happen at the exact moment of the dump."
+ "Option automatically turns --lock-tables off.",
+ &opt_slave_data, &opt_slave_data, 0,
+ GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL, 0, 0, 0},
{"events", 'E', "Dump events.",
&opt_events, &opt_events, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -291,24 +315,18 @@ static struct my_option my_long_options[] =
&extended_insert, &extended_insert, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
{"fields-terminated-by", OPT_FTB,
- "Fields in the output file are terminated by the given string.",
- &fields_terminated, &fields_terminated, 0,
+ "Fields in the output file are terminated by the given string.",
+ &fields_terminated, &fields_terminated, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"fields-enclosed-by", OPT_ENC,
- "Fields in the output file are enclosed by the given character.",
- &enclosed, &enclosed, 0,
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
+ "Fields in the output file are enclosed by the given character.",
+ &enclosed, &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
{"fields-optionally-enclosed-by", OPT_O_ENC,
- "Fields in the output file are optionally enclosed by the given character.",
- &opt_enclosed, &opt_enclosed, 0,
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
- {"fields-escaped-by", OPT_ESC,
+ "Fields in the output file are optionally enclosed by the given character.",
+ &opt_enclosed, &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
+ {"fields-escaped-by", OPT_ESC,
"Fields in the output file are escaped by the given character.",
- &escaped, &escaped, 0,
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"first-slave", OPT_FIRST_SLAVE, "Deprecated, renamed to --lock-all-tables.",
- &opt_lock_all_tables, &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
- 0, 0, 0, 0, 0, 0},
+ &escaped, &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"flush-logs", 'F', "Flush logs file in server before starting dump. "
"Note that if you dump many databases at once (using the option "
"--databases= or --all-databases), the logs will be flushed for "
@@ -342,10 +360,15 @@ static struct my_option my_long_options[] =
"be specified with both database and table names, e.g., "
"--ignore-table=database.table.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"include-master-host-port", OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT,
+ "Adds 'MASTER_HOST=<host>, MASTER_PORT=<port>' to 'CHANGE MASTER TO..' "
+ "in dump produced with --dump-slave.", &opt_include_master_host_port,
+ &opt_include_master_host_port, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
&opt_ignore, &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
- {"lines-terminated-by", OPT_LTB,
+ {"lines-terminated-by", OPT_LTB,
"Lines in the output file are terminated by the given string.",
&lines_terminated, &lines_terminated, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -396,7 +419,7 @@ static struct my_option my_long_options[] =
NO_ARG, 0, 0, 0, 0, 0, 0},
{"no-data", 'd', "No row information.", &opt_no_data,
&opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"no-set-names", 'N',"Suppress the SET NAMES statement",
+ {"no-set-names", 'N', "Same as --skip-set-charset.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"opt", OPT_OPTIMIZE,
"Same as --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys. Enabled by default, disable with --skip-opt.",
@@ -426,18 +449,17 @@ static struct my_option my_long_options[] =
&opt_replace_into, &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"result-file", 'r',
- "Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed).",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ "Direct output to a given file. This option should be used in systems "
+ "(e.g., DOS, Windows) that use carriage-return linefeed pairs (\\r\\n) "
+ "to separate text lines. This option ensures that only a single newline "
+ "is used.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"routines", 'R', "Dump stored routines (functions and procedures).",
- &opt_routines, &opt_routines, 0, GET_BOOL,
- NO_ARG, 0, 0, 0, 0, 0, 0},
+ &opt_routines, &opt_routines, 0, GET_BOOL,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
{"set-charset", OPT_SET_CHARSET,
- "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.",
+ "Add 'SET NAMES default_character_set' to the output.",
&opt_set_charset, &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
0, 0, 0, 0, 0},
- {"set-variable", 'O',
- "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifdef HAVE_SMEM
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
"Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name,
@@ -496,6 +518,13 @@ static struct my_option my_long_options[] =
&where, &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ &opt_plugin_dir, &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_DEFAULT_AUTH,
+ "Default authentication client-side plugin to use.",
+ &opt_default_auth, &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -528,7 +557,6 @@ static int dump_tablespaces(char* ts_where);
static void print_comment(FILE *sql_file, my_bool is_error, const char *format,
...);
-#include <help_start.h>
/*
Print the supplied message if in verbose mode
@@ -551,6 +579,8 @@ static void verbose_msg(const char *fmt, ...)
vfprintf(stderr, fmt, args);
va_end(args);
+ fflush(stderr);
+
DBUG_VOID_RETURN;
}
@@ -570,19 +600,17 @@ void check_io(FILE *file)
static void print_version(void)
{
- printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
+ printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname_short,DUMP_VERSION,
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
- NETWARE_SET_SCREEN_MODE(1);
} /* print_version */
static void short_usage_sub(void)
{
- printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
+ printf("Usage: %s [OPTIONS] database [tables]\n", my_progname_short);
printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n",
- my_progname);
- printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname);
- NETWARE_SET_SCREEN_MODE(1);
+ my_progname_short);
+ printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname_short);
}
@@ -601,11 +629,9 @@ static void usage(void)
static void short_usage(void)
{
short_usage_sub();
- printf("For more options, use %s --help\n", my_progname);
+ printf("For more options, use %s --help\n", my_progname_short);
}
-#include <help_end.h>
-
static void write_header(FILE *sql_file, char *db_name)
{
@@ -718,12 +744,6 @@ static void write_footer(FILE *sql_file)
} /* write_footer */
-static void free_table_ent(char *key)
-{
- my_free(key, MYF(0));
-}
-
-
uchar* get_table_key(const char *entry, size_t *length,
my_bool not_used __attribute__((unused)))
{
@@ -737,18 +757,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
switch (optid) {
-#ifdef __NETWARE__
- case OPT_AUTO_CLOSE:
- setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
- break;
-#endif
case 'p':
if (argument == disabled_my_option)
argument= (char*) ""; /* Don't require password */
if (argument)
{
char *start=argument;
- my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_password);
opt_password=my_strdup(argument,MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start)
@@ -804,19 +819,14 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case '?':
usage();
exit(0);
- case 'O':
- WARN_DEPRECATED(VER_CELOSIA, "--set-variable", "--variable-name=value");
- break;
- case (int) OPT_ALL:
- WARN_DEPRECATED(VER_CELOSIA, "--all", "--create-options");
- break;
- case (int) OPT_FIRST_SLAVE:
- WARN_DEPRECATED(VER_CELOSIA, "--first-slave", "--lock-all-tables");
- break;
case (int) OPT_MASTER_DATA:
if (!argument) /* work like in old versions */
opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL;
break;
+ case (int) OPT_MYSQLDUMP_SLAVE_DATA:
+ if (!argument) /* work like in old versions */
+ opt_slave_data= MYSQL_OPT_SLAVE_DATA_EFFECTIVE_SQL;
+ break;
case (int) OPT_OPTIMIZE:
extended_insert= opt_drop= opt_lock= quick= create_options=
opt_disable_keys= lock_tables= opt_set_charset= 1;
@@ -912,12 +922,12 @@ static int get_options(int *argc, char ***argv)
opt_net_buffer_length= *mysql_params->p_net_buffer_length;
md_result_file= stdout;
- load_defaults("my",load_default_groups,argc,argv);
+ if (load_defaults("my",load_default_groups,argc,argv))
+ return 1;
defaults_argv= *argv;
- if (hash_init(&ignore_table, charset_info, 16, 0, 0,
- (hash_get_key) get_table_key,
- (hash_free_key) free_table_ent, 0))
+ if (my_hash_init(&ignore_table, charset_info, 16, 0, 0,
+ (my_hash_get_key) get_table_key, my_free, 0))
return(EX_EOM);
/* Don't copy internal log tables */
if (my_hash_insert(&ignore_table,
@@ -946,33 +956,44 @@ static int get_options(int *argc, char ***argv)
fields_terminated))
{
fprintf(stderr,
- "%s: You must use option --tab with --fields-...\n", my_progname);
+ "%s: You must use option --tab with --fields-...\n", my_progname_short);
return(EX_USAGE);
}
+ /* We don't delete master logs if slave data option */
+ if (opt_slave_data)
+ {
+ opt_lock_all_tables= !opt_single_transaction;
+ opt_master_data= 0;
+ opt_delete_master_logs= 0;
+ }
+
/* Ensure consistency of the set of binlog & locking options */
if (opt_delete_master_logs && !opt_master_data)
opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL;
if (opt_single_transaction && opt_lock_all_tables)
{
fprintf(stderr, "%s: You can't use --single-transaction and "
- "--lock-all-tables at the same time.\n", my_progname);
+ "--lock-all-tables at the same time.\n", my_progname_short);
return(EX_USAGE);
}
if (opt_master_data)
+ {
opt_lock_all_tables= !opt_single_transaction;
+ opt_slave_data= 0;
+ }
if (opt_single_transaction || opt_lock_all_tables)
lock_tables= 0;
if (enclosed && opt_enclosed)
{
- fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
+ fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname_short);
return(EX_USAGE);
}
if ((opt_databases || opt_alldbs) && path)
{
fprintf(stderr,
"%s: --databases or --all-databases can't be used with --tab.\n",
- my_progname);
+ my_progname_short);
return(EX_USAGE);
}
if (strcmp(default_charset, charset_info->csname) &&
@@ -1024,7 +1045,7 @@ static void die(int error_num, const char* fmt_reason, ...)
my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
va_end(args);
- fprintf(stderr, "%s: %s\n", my_progname, buffer);
+ fprintf(stderr, "%s: %s\n", my_progname_short, buffer);
fflush(stderr);
ignore_errors= 0; /* force the exit */
@@ -1058,7 +1079,7 @@ static void maybe_die(int error_num, const char* fmt_reason, ...)
my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
va_end(args);
- fprintf(stderr, "%s: %s\n", my_progname, buffer);
+ fprintf(stderr, "%s: %s\n", my_progname_short, buffer);
fflush(stderr);
maybe_exit(error_num);
@@ -1371,120 +1392,68 @@ static int switch_character_set_results(MYSQL *mysql, const char *cs_name)
}
/**
- Rewrite CREATE TRIGGER statement, enclosing DEFINER clause in
- version-specific comment.
-
- This function parses the CREATE TRIGGER statement and encloses
- DEFINER-clause in version-specific comment:
- input query: CREATE DEFINER=a@b TRIGGER ...
- rewritten query: CREATE * / / *!50017 DEFINER=a@b * / / *!50003 TRIGGER ...
-
- @note This function will go away when WL#3995 is implemented.
-
- @param[in] trigger_def_str CREATE TRIGGER statement string.
- @param[in] trigger_def_length length of the trigger_def_str.
-
- @return pointer to the new allocated query string.
-*/
-
-static char *cover_definer_clause_in_trigger(const char *trigger_def_str,
- uint trigger_def_length)
-{
- char *query_str= NULL;
- char *definer_begin= my_case_str(trigger_def_str, trigger_def_length,
- C_STRING_WITH_LEN(" DEFINER"));
- char *definer_end;
-
- if (!definer_begin)
- return NULL;
-
- definer_end= my_case_str(definer_begin, strlen(definer_begin),
- C_STRING_WITH_LEN(" TRIGGER"));
-
- if (definer_end)
- {
- char *query_str_tail;
-
- /*
- Allocate memory for new query string: original string
- from SHOW statement and version-specific comments.
- */
- query_str= alloc_query_str(trigger_def_length + 23);
-
- query_str_tail= strnmov(query_str,
- trigger_def_str,
- definer_begin - trigger_def_str);
-
- query_str_tail= strmov(query_str_tail,
- "*/ /*!50017");
-
- query_str_tail= strnmov(query_str_tail,
- definer_begin,
- definer_end - definer_begin);
-
- query_str_tail= strxmov(query_str_tail,
- "*/ /*!50003",
- definer_end,
- NullS);
- }
-
- return query_str;
-}
-
-/**
- Rewrite CREATE FUNCTION or CREATE PROCEDURE statement, enclosing DEFINER
- clause in version-specific comment.
+ Rewrite statement, enclosing DEFINER clause in version-specific comment.
- This function parses the CREATE FUNCTION | PROCEDURE statement and
- encloses DEFINER-clause in version-specific comment:
+ This function parses any CREATE statement and encloses DEFINER-clause in
+ version-specific comment:
input query: CREATE DEFINER=a@b FUNCTION ...
rewritten query: CREATE * / / *!50020 DEFINER=a@b * / / *!50003 FUNCTION ...
@note This function will go away when WL#3995 is implemented.
- @param[in] def_str CREATE FUNCTION|PROCEDURE statement string.
- @param[in] def_str_length length of the def_str.
+ @param[in] stmt_str CREATE statement string.
+ @param[in] stmt_length Length of the stmt_str.
+ @param[in] definer_version_str Minimal MySQL version number when
+ DEFINER clause is supported in the
+ given statement.
+ @param[in] definer_version_length Length of definer_version_str.
+ @param[in] stmt_version_str Minimal MySQL version number when the
+ given statement is supported.
+ @param[in] stmt_version_length Length of stmt_version_str.
+ @param[in] keyword_str Keyword to look for after CREATE.
+ @param[in] keyword_length Length of keyword_str.
@return pointer to the new allocated query string.
*/
-static char *cover_definer_clause_in_sp(const char *def_str,
- uint def_str_length)
+static char *cover_definer_clause(const char *stmt_str,
+ uint stmt_length,
+ const char *definer_version_str,
+ uint definer_version_length,
+ const char *stmt_version_str,
+ uint stmt_version_length,
+ const char *keyword_str,
+ uint keyword_length)
{
- char *query_str= NULL;
- char *definer_begin= my_case_str(def_str, def_str_length,
+ char *definer_begin= my_case_str(stmt_str, stmt_length,
C_STRING_WITH_LEN(" DEFINER"));
- char *definer_end;
+ char *definer_end= NULL;
+
+ char *query_str= NULL;
+ char *query_ptr;
if (!definer_begin)
return NULL;
definer_end= my_case_str(definer_begin, strlen(definer_begin),
- C_STRING_WITH_LEN(" PROCEDURE"));
+ keyword_str, keyword_length);
if (!definer_end)
- {
- definer_end= my_case_str(definer_begin, strlen(definer_begin),
- C_STRING_WITH_LEN(" FUNCTION"));
- }
+ return NULL;
- if (definer_end)
- {
- char *query_str_tail;
+ /*
+ Allocate memory for new query string: original string
+ from SHOW statement and version-specific comments.
+ */
+ query_str= alloc_query_str(stmt_length + 23);
- /*
- Allocate memory for new query string: original string
- from SHOW statement and version-specific comments.
- */
- query_str= alloc_query_str(def_str_length + 23);
-
- query_str_tail= strnmov(query_str, def_str, definer_begin - def_str);
- query_str_tail= strmov(query_str_tail, "*/ /*!50020");
- query_str_tail= strnmov(query_str_tail, definer_begin,
- definer_end - definer_begin);
- query_str_tail= strxmov(query_str_tail, "*/ /*!50003",
- definer_end, NullS);
- }
+ query_ptr= strnmov(query_str, stmt_str, definer_begin - stmt_str);
+ query_ptr= strnmov(query_ptr, C_STRING_WITH_LEN("*/ /*!"));
+ query_ptr= strnmov(query_ptr, definer_version_str, definer_version_length);
+ query_ptr= strnmov(query_ptr, definer_begin, definer_end - definer_begin);
+ query_ptr= strnmov(query_ptr, C_STRING_WITH_LEN("*/ /*!"));
+ query_ptr= strnmov(query_ptr, stmt_version_str, stmt_version_length);
+ query_ptr= strxmov(query_ptr, definer_end, NullS);
return query_str;
}
@@ -1516,16 +1485,17 @@ static void free_resources()
{
if (md_result_file && md_result_file != stdout)
my_fclose(md_result_file, MYF(0));
- my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
- my_free(current_host, MYF(MY_ALLOW_ZERO_PTR));
- if (hash_inited(&ignore_table))
- hash_free(&ignore_table);
+ my_free(opt_password);
+ my_free(current_host);
+ if (my_hash_inited(&ignore_table))
+ my_hash_free(&ignore_table);
if (extended_insert)
dynstr_free(&extended_row);
if (insert_pat_inited)
dynstr_free(&insert_pat);
if (defaults_argv)
free_defaults(defaults_argv);
+ mysql_library_end();
my_end(my_end_arg);
}
@@ -1570,9 +1540,16 @@ static int connect_to_db(char *host, char *user,char *passwd)
mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
#endif
mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
- if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd,
- NULL,opt_mysql_port,opt_mysql_unix_port,
- 0)))
+
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(&mysql_connection, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(&mysql_connection, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
+ mysql= &mysql_connection; /* So we can mysql_close() it properly */
+ if (!mysql_real_connect(&mysql_connection,host,user,passwd,
+ NULL,opt_mysql_port,opt_mysql_unix_port, 0))
{
DB_error(&mysql_connection, "when trying to connect");
DBUG_RETURN(1);
@@ -1631,7 +1608,7 @@ static void unescape(FILE *file,char *pos,uint length)
fputs(tmp, file);
fputc('\'', file);
check_io(file);
- my_free(tmp, MYF(MY_WME));
+ my_free(tmp);
DBUG_VOID_RETURN;
} /* unescape */
@@ -2175,6 +2152,8 @@ static uint dump_events_for_db(char *db)
*/
if (strlen(row[3]) != 0)
{
+ char *query_str;
+
if (opt_drop)
fprintf(sql_file, "/*!50106 DROP EVENT IF EXISTS %s */%s\n",
event_name, delimiter);
@@ -2182,7 +2161,7 @@ static uint dump_events_for_db(char *db)
if (create_delimiter(row[3], delimiter, sizeof(delimiter)) == NULL)
{
fprintf(stderr, "%s: Warning: Can't create delimiter for event '%s'\n",
- my_progname, event_name);
+ my_progname_short, event_name);
DBUG_RETURN(1);
}
@@ -2201,31 +2180,36 @@ static uint dump_events_for_db(char *db)
row[4], /* character_set_results */
row[5]); /* collation_connection */
}
- else
- {
- /*
- mysqldump is being run against the server, that does not
- provide character set information in SHOW CREATE
- statements.
+ else
+ {
+ /*
+ mysqldump is being run against the server, that does not
+ provide character set information in SHOW CREATE
+ statements.
- NOTE: the dump may be incorrect, since character set
- information is required in order to restore event properly.
- */
+ NOTE: the dump may be incorrect, since character set
+ information is required in order to restore event properly.
+ */
- fprintf(sql_file,
- "--\n"
- "-- WARNING: old server version. "
- "The following dump may be incomplete.\n"
- "--\n");
- }
+ fprintf(sql_file,
+ "--\n"
+ "-- WARNING: old server version. "
+ "The following dump may be incomplete.\n"
+ "--\n");
+ }
switch_sql_mode(sql_file, delimiter, row[1]);
switch_time_zone(sql_file, delimiter, row[2]);
+ query_str= cover_definer_clause(row[3], strlen(row[3]),
+ C_STRING_WITH_LEN("50117"),
+ C_STRING_WITH_LEN("50106"),
+ C_STRING_WITH_LEN(" EVENT"));
+
fprintf(sql_file,
"/*!50106 %s */ %s\n",
- (const char *) row[3],
+ (const char *) (query_str != NULL ? query_str : row[3]),
(const char *) delimiter);
restore_time_zone(sql_file, delimiter);
@@ -2264,7 +2248,7 @@ static uint dump_events_for_db(char *db)
mysql_free_result(event_list_res);
if (lock_tables)
- VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
+ (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES");
DBUG_RETURN(0);
}
@@ -2404,7 +2388,16 @@ static uint dump_routines_for_db(char *db)
fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n",
routine_type[i], routine_name);
- query_str= cover_definer_clause_in_sp(row[2], strlen(row[2]));
+ query_str= cover_definer_clause(row[2], strlen(row[2]),
+ C_STRING_WITH_LEN("50020"),
+ C_STRING_WITH_LEN("50003"),
+ C_STRING_WITH_LEN(" FUNCTION"));
+
+ if (!query_str)
+ query_str= cover_definer_clause(row[2], strlen(row[2]),
+ C_STRING_WITH_LEN("50020"),
+ C_STRING_WITH_LEN("50003"),
+ C_STRING_WITH_LEN(" PROCEDURE"));
if (mysql_num_fields(routine_res) >= 6)
{
@@ -2460,7 +2453,7 @@ static uint dump_routines_for_db(char *db)
}
}
- my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(query_str);
}
} /* end of routine printing */
mysql_free_result(routine_res);
@@ -2480,7 +2473,7 @@ static uint dump_routines_for_db(char *db)
DBUG_RETURN(1);
if (lock_tables)
- VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
+ (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES");
DBUG_RETURN(0);
}
@@ -2617,6 +2610,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (strcmp(field->name, "View") == 0)
{
char *scv_buff= NULL;
+ my_ulonglong n_cols;
verbose_msg("-- It's a view, create dummy table for view\n");
@@ -2631,8 +2625,8 @@ static uint get_table_structure(char *table, char *db, char *table_type,
the same name in order to satisfy views that depend on this view.
The table will be removed when the actual view is created.
- The properties of each column, aside from the data type, are not
- preserved in this temporary table, because they are not necessary.
+ The properties of each column, are not preserved in this temporary
+ table, because they are not necessary.
This will not be necessary once we can determine dependencies
between views and can simply dump them in the appropriate order.
@@ -2652,15 +2646,30 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (mysql_errno(mysql) == ER_VIEW_INVALID)
fprintf(sql_file, "\n-- failed on view %s: %s\n\n", result_table, scv_buff ? scv_buff : "");
- my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(scv_buff);
DBUG_RETURN(0);
}
else
- my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(scv_buff);
- if (mysql_num_rows(result))
+ n_cols= mysql_num_rows(result);
+ if (0 != n_cols)
{
+
+ /*
+ The actual formula is based on the column names and how the .FRM
+ files are stored and is too volatile to be repeated here.
+ Thus we simply warn the user if the columns exceed a limit we
+ know works most of the time.
+ */
+ if (n_cols >= 1000)
+ fprintf(stderr,
+ "-- Warning: Creating a stand-in table for view %s may"
+ " fail when replaying the dump file produced because "
+ "of the number of columns exceeding 1000. Exercise "
+ "caution when replaying the produced dump file.\n",
+ table);
if (opt_drop)
{
/*
@@ -2687,14 +2696,19 @@ static uint get_table_structure(char *table, char *db, char *table_type,
row= mysql_fetch_row(result);
- fprintf(sql_file, " %s %s", quote_name(row[0], name_buff, 0),
- row[1]);
+ /*
+ The actual column type doesn't matter anyway, since the table will
+ be dropped at run time.
+ We do tinyint to avoid hitting the row size limit.
+ */
+ fprintf(sql_file, " %s tinyint NOT NULL",
+ quote_name(row[0], name_buff, 0));
while((row= mysql_fetch_row(result)))
{
/* col name, col type */
- fprintf(sql_file, ",\n %s %s",
- quote_name(row[0], name_buff, 0), row[1]);
+ fprintf(sql_file, ",\n %s tinyint NOT NULL",
+ quote_name(row[0], name_buff, 0));
}
/*
@@ -2799,7 +2813,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
else
{
verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n",
- my_progname, mysql_error(mysql));
+ my_progname_short, mysql_error(mysql));
my_snprintf(query_buff, sizeof(query_buff), show_fields_stmt, db, table);
@@ -2910,7 +2924,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
goto continue_xml;
}
fprintf(stderr, "%s: Can't get keys for table %s (%s)\n",
- my_progname, result_table, mysql_error(mysql));
+ my_progname_short, result_table, mysql_error(mysql));
if (path)
my_fclose(sql_file, MYF(MY_WME));
DBUG_RETURN(0);
@@ -3135,9 +3149,10 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs,
continue;
}
- query_str= cover_definer_clause_in_trigger(row[2], strlen(row[2]));
-
-
+ query_str= cover_definer_clause(row[2], strlen(row[2]),
+ C_STRING_WITH_LEN("50017"),
+ C_STRING_WITH_LEN("50003"),
+ C_STRING_WITH_LEN(" TRIGGER"));
if (switch_db_collation(sql_file, db_name, ";",
db_cl_name, row[5], &db_cl_altered))
DBUG_RETURN(TRUE);
@@ -3164,7 +3179,7 @@ static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs,
DBUG_RETURN(TRUE);
}
- my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(query_str);
}
DBUG_RETURN(FALSE);
@@ -3565,7 +3580,7 @@ static void dump_table(char *table, char *db)
if (mysql_num_fields(res) != num_fields)
{
fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n",
- my_progname, result_table);
+ my_progname_short, result_table);
error= EX_CONSCHECK;
goto err;
}
@@ -3649,7 +3664,7 @@ static void dump_table(char *table, char *db)
{
if (length)
{
- if (!IS_NUM_FIELD(field))
+ if (!(field->flags & NUM_FLAG))
{
/*
"length * 2 + 2" is OK for both HEX and non-HEX modes:
@@ -3717,7 +3732,7 @@ static void dump_table(char *table, char *db)
}
if (row[i])
{
- if (!IS_NUM_FIELD(field))
+ if (!(field->flags & NUM_FLAG))
{
if (opt_xml)
{
@@ -3830,7 +3845,7 @@ static void dump_table(char *table, char *db)
{
my_snprintf(buf, sizeof(buf),
"%s: Error %d: %s when dumping table %s at row: %ld\n",
- my_progname,
+ my_progname_short,
mysql_errno(mysql),
mysql_error(mysql),
result_table,
@@ -4024,8 +4039,8 @@ static int dump_tablespaces(char* ts_where)
DBUG_RETURN(0);
}
- my_printf_error(0, "Error: '%s' when trying to dump tablespaces",
- MYF(0), mysql_error(mysql));
+ fprintf(stderr, "%s: Error: '%s' when trying to dump tablespaces\n",
+ my_progname_short, mysql_error(mysql));
DBUG_RETURN(1);
}
@@ -4154,31 +4169,41 @@ static int dump_all_databases()
return 1;
while ((row= mysql_fetch_row(tableres)))
{
- if (mysql_get_server_version(mysql) >= 50003 &&
- !my_strcasecmp(&my_charset_latin1, row[0], "information_schema"))
+ if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
+ !my_strcasecmp(&my_charset_latin1, row[0], INFORMATION_SCHEMA_DB_NAME))
+ continue;
+
+ if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
+ !my_strcasecmp(&my_charset_latin1, row[0], PERFORMANCE_SCHEMA_DB_NAME))
continue;
if (dump_all_tables_in_db(row[0]))
result=1;
}
+ mysql_free_result(tableres);
if (seen_views)
{
if (mysql_query(mysql, "SHOW DATABASES") ||
!(tableres= mysql_store_result(mysql)))
{
- my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
- MYF(0), mysql_error(mysql));
+ fprintf(stderr, "%s: Error: Couldn't execute 'SHOW DATABASES': %s\n",
+ my_progname_short, mysql_error(mysql));
return 1;
}
while ((row= mysql_fetch_row(tableres)))
{
- if (mysql_get_server_version(mysql) >= 50003 &&
- !my_strcasecmp(&my_charset_latin1, row[0], "information_schema"))
+ if (mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
+ !my_strcasecmp(&my_charset_latin1, row[0], INFORMATION_SCHEMA_DB_NAME))
+ continue;
+
+ if (mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
+ !my_strcasecmp(&my_charset_latin1, row[0], PERFORMANCE_SCHEMA_DB_NAME))
continue;
if (dump_all_views_in_db(row[0]))
result=1;
}
+ mysql_free_result(tableres);
}
return result;
}
@@ -4307,8 +4332,6 @@ static int init_dumping(char *database, int init_func(char*))
check_io(md_result_file);
}
}
- if (extended_insert)
- init_dynamic_string_checked(&extended_row, "", 1024, 1024);
return 0;
} /* init_dumping */
@@ -4317,7 +4340,7 @@ static int init_dumping(char *database, int init_func(char*))
my_bool include_table(const uchar *hash_key, size_t len)
{
- return !hash_search(&ignore_table, hash_key, len);
+ return ! my_hash_search(&ignore_table, hash_key, len);
}
@@ -4379,6 +4402,8 @@ static int dump_all_tables_in_db(char *database)
if (mysql_refresh(mysql, REFRESH_LOG))
DB_error(mysql, "when doing refresh");
/* We shall continue here, if --force was given */
+ else
+ verbose_msg("-- dump_all_tables_in_db : logs flushed successfully!\n");
}
while ((table= getTableName(0)))
{
@@ -4386,7 +4411,7 @@ static int dump_all_tables_in_db(char *database)
if (include_table((uchar*) hash_key, end - hash_key))
{
dump_table(table,database);
- my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(order_by);
order_by= 0;
if (opt_dump_triggers && mysql_get_server_version(mysql) >= 50009)
{
@@ -4415,7 +4440,7 @@ static int dump_all_tables_in_db(char *database)
check_io(md_result_file);
}
if (lock_tables)
- VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
+ (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES");
if (flush_privileges && using_mysql_db == 0)
{
fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n");
@@ -4476,6 +4501,8 @@ static my_bool dump_all_views_in_db(char *database)
if (mysql_refresh(mysql, REFRESH_LOG))
DB_error(mysql, "when doing refresh");
/* We shall continue here, if --force was given */
+ else
+ verbose_msg("-- dump_all_views_in_db : logs flushed successfully!\n");
}
while ((table= getTableName(0)))
{
@@ -4489,7 +4516,7 @@ static my_bool dump_all_views_in_db(char *database)
check_io(md_result_file);
}
if (lock_tables)
- VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
+ (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES");
return 0;
} /* dump_all_tables_in_db */
@@ -4538,7 +4565,7 @@ static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
}
mysql_free_result(table_res);
}
- DBUG_PRINT("exit", ("new_table_name: %s", val_or_null(name)));
+ DBUG_PRINT("exit", ("new_table_name: %s", name));
DBUG_RETURN(name);
}
@@ -4585,10 +4612,12 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
}
end= pos;
- /* Can't LOCK TABLES in INFORMATION_SCHEMA, so don't try. */
+ /* Can't LOCK TABLES in I_S / P_S, so don't try. */
if (lock_tables &&
- !(mysql_get_server_version(mysql) >= 50003 &&
- !my_strcasecmp(&my_charset_latin1, db, "information_schema")))
+ !(mysql_get_server_version(mysql) >= FIRST_INFORMATION_SCHEMA_VERSION &&
+ !my_strcasecmp(&my_charset_latin1, db, INFORMATION_SCHEMA_DB_NAME)) &&
+ !(mysql_get_server_version(mysql) >= FIRST_PERFORMANCE_SCHEMA_VERSION &&
+ !my_strcasecmp(&my_charset_latin1, db, PERFORMANCE_SCHEMA_DB_NAME)))
{
if (mysql_real_query(mysql, lock_tables_query.str,
lock_tables_query.length-1))
@@ -4612,6 +4641,8 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
DB_error(mysql, "when doing refresh");
}
/* We shall countinue here, if --force was given */
+ else
+ verbose_msg("-- dump_selected_tables : logs flushed successfully!\n");
}
if (opt_xml)
print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NullS);
@@ -4651,7 +4682,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
dump_routines_for_db(db);
}
free_root(&root, MYF(0));
- my_free(order_by, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(order_by);
order_by= 0;
if (opt_xml)
{
@@ -4659,7 +4690,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
check_io(md_result_file);
}
if (lock_tables)
- VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES"));
+ (void) mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES");
DBUG_RETURN(0);
} /* dump_selected_tables */
@@ -4667,7 +4698,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
{
MYSQL_ROW row;
- MYSQL_RES *master;
+ MYSQL_RES *UNINIT_VAR(master);
char binlog_pos_file[FN_REFLEN];
char binlog_pos_offset[LONGLONG_LEN+1];
char *file, *offset;
@@ -4698,8 +4729,8 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
if (!ignore_errors)
{
/* SHOW MASTER STATUS reports nothing and --force is not enabled */
- my_printf_error(0, "Error: Binlogging on server not active",
- MYF(0));
+ fprintf(stderr, "%s: Error: Binlogging on server not active\n",
+ my_progname_short);
maybe_exit(EX_MYSQLERR);
return 1;
}
@@ -4711,10 +4742,9 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
}
/* SHOW MASTER STATUS reports file and position */
- if (opt_comments)
- print_comment(md_result_file, 0,
- "\n--\n-- Position to start replication or point-in-time "
- "recovery from\n--\n\n");
+ print_comment(md_result_file, 0,
+ "\n--\n-- Position to start replication or point-in-time "
+ "recovery from\n--\n\n");
fprintf(md_result_file,
"%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
comment_prefix, file, offset);
@@ -4726,6 +4756,130 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos)
return 0;
}
+static int do_stop_slave_sql(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ /* We need to check if the slave sql is running in the first place */
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ return(1);
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[11])
+ {
+ /* if SLAVE SQL is not running, we don't stop it */
+ if (!strcmp(row[11],"No"))
+ {
+ mysql_free_result(slave);
+ /* Silently assume that they don't have the slave running */
+ return(0);
+ }
+ }
+ }
+ mysql_free_result(slave);
+
+ /* now, stop slave if running */
+ if (mysql_query_with_error_report(mysql_con, 0, "STOP SLAVE SQL_THREAD"))
+ return(1);
+
+ return(0);
+}
+
+static int add_stop_slave(void)
+{
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- stop slave statement to make a recovery dump)\n--\n\n");
+ fprintf(md_result_file, "STOP SLAVE;\n");
+ return(0);
+}
+
+static int add_slave_statements(void)
+{
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- start slave statement to make a recovery dump)\n--\n\n");
+ fprintf(md_result_file, "START SLAVE;\n");
+ return(0);
+}
+
+static int do_show_slave_status(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave= 0;
+ const char *comment_prefix=
+ (opt_slave_data == MYSQL_OPT_SLAVE_DATA_COMMENTED_SQL) ? "-- " : "";
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ {
+ if (!ignore_errors)
+ {
+ /* SHOW SLAVE STATUS reports nothing and --force is not enabled */
+ fprintf(stderr, "%s: Error: Slave not set up\n", my_progname_short);
+ }
+ mysql_free_result(slave);
+ return 1;
+ }
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[9] && row[21])
+ {
+ /* SHOW MASTER STATUS reports file and position */
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- Position to start replication or point-in-time "
+ "recovery from (the master of this slave)\n--\n\n");
+
+ fprintf(md_result_file, "%sCHANGE MASTER TO ", comment_prefix);
+
+ if (opt_include_master_host_port)
+ {
+ if (row[1])
+ fprintf(md_result_file, "MASTER_HOST='%s', ", row[1]);
+ if (row[3])
+ fprintf(md_result_file, "MASTER_PORT=%s, ", row[3]);
+ }
+ fprintf(md_result_file,
+ "MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n", row[9], row[21]);
+
+ check_io(md_result_file);
+ }
+ mysql_free_result(slave);
+ }
+ return 0;
+}
+
+static int do_start_slave_sql(MYSQL *mysql_con)
+{
+ MYSQL_RES *slave;
+ /* We need to check if the slave sql is stopped in the first place */
+ if (mysql_query_with_error_report(mysql_con, &slave, "SHOW SLAVE STATUS"))
+ return(1);
+ else
+ {
+ MYSQL_ROW row= mysql_fetch_row(slave);
+ if (row && row[11])
+ {
+ /* if SLAVE SQL is not running, we don't start it */
+ if (!strcmp(row[11],"Yes"))
+ {
+ mysql_free_result(slave);
+ /* Silently assume that they don't have the slave running */
+ return(0);
+ }
+ }
+ }
+ mysql_free_result(slave);
+
+ /* now, start slave if stopped */
+ if (mysql_query_with_error_report(mysql_con, 0, "START SLAVE"))
+ {
+ fprintf(stderr, "%s: Error: Unable to start slave\n", my_progname_short);
+ return 1;
+ }
+ return(0);
+}
+
+
static int do_flush_tables_read_lock(MYSQL *mysql_con)
{
@@ -4792,6 +4946,7 @@ static int purge_bin_logs_to(MYSQL *mysql_con, char* log_name)
static int start_transaction(MYSQL *mysql_con)
{
+ verbose_msg("-- Starting transaction...\n");
/*
We use BEGIN for old servers. --single-transaction --master-data will fail
on old servers, but that's ok as it was already silently broken (it didn't
@@ -4846,7 +5001,7 @@ static ulong find_set(TYPELIB *lib, const char *x, uint length,
for (; pos != end && *pos != ','; pos++) ;
var_len= (uint) (pos - start);
strmake(buff, start, min(sizeof(buff) - 1, var_len));
- find= find_type(buff, lib, var_len);
+ find= find_type(buff, lib, FIND_TYPE_BASIC);
if (!find)
{
*err_pos= (char*) start;
@@ -5360,8 +5515,9 @@ int main(int argc, char **argv)
char bin_log_name[FN_REFLEN];
int exit_code;
int consistent_binlog_pos= 0;
- MY_INIT("mysqldump");
+ MY_INIT(argv[0]);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
compatible_mode_normal_str[0]= 0;
default_charset= (char *)mysql_universal_client_charset;
bzero((char*) &ignore_table, sizeof(ignore_table));
@@ -5372,6 +5528,7 @@ int main(int argc, char **argv)
free_resources();
exit(exit_code);
}
+ sf_leaking_memory=0; /* from now on we cleanup properly */
/*
Disable comments in xml mode if 'comments' option is not explicitly used.
@@ -5396,38 +5553,64 @@ int main(int argc, char **argv)
if (!path)
write_header(md_result_file, *argv);
+ if (opt_slave_data && do_stop_slave_sql(mysql))
+ goto err;
+
if (opt_single_transaction && opt_master_data)
{
/* See if we can avoid FLUSH TABLES WITH READ LOCK (MariaDB 5.3+). */
consistent_binlog_pos= check_consistent_binlog_pos(NULL, NULL);
}
- if ((opt_lock_all_tables || (opt_master_data && !consistent_binlog_pos)) &&
+ if ((opt_lock_all_tables || (opt_master_data && !consistent_binlog_pos) ||
+ (opt_single_transaction && flush_logs)) &&
do_flush_tables_read_lock(mysql))
goto err;
- if (opt_single_transaction && start_transaction(mysql))
- goto err;
- if (opt_delete_master_logs)
+
+ /*
+ Flush logs before starting transaction since
+ this causes implicit commit starting mysql-5.5.
+ */
+ if (opt_lock_all_tables || opt_master_data ||
+ (opt_single_transaction && flush_logs) ||
+ opt_delete_master_logs)
{
- if (mysql_refresh(mysql, REFRESH_LOG) ||
- get_bin_log_name(mysql, bin_log_name, sizeof(bin_log_name)))
- goto err;
+ if (flush_logs || opt_delete_master_logs)
+ {
+ if (mysql_refresh(mysql, REFRESH_LOG))
+ goto err;
+ verbose_msg("-- main : logs flushed successfully!\n");
+ }
+
+ /* Not anymore! That would not be sensible. */
flush_logs= 0;
}
- if (opt_lock_all_tables || opt_master_data)
+
+ if (opt_delete_master_logs)
{
- if (flush_logs && mysql_refresh(mysql, REFRESH_LOG))
+ if (get_bin_log_name(mysql, bin_log_name, sizeof(bin_log_name)))
goto err;
- flush_logs= 0; /* not anymore; that would not be sensible */
}
+
+ if (opt_single_transaction && start_transaction(mysql))
+ goto err;
+
+ /* Add 'STOP SLAVE to beginning of dump */
+ if (opt_slave_apply && add_stop_slave())
+ goto err;
if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos))
goto err;
+ if (opt_slave_data && do_show_slave_status(mysql))
+ goto err;
if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no commit! */
goto err;
if (opt_alltspcs)
dump_all_tablespaces();
+ if (extended_insert)
+ init_dynamic_string_checked(&extended_row, "", 1024, 1024);
+
if (opt_alldbs)
{
if (!opt_alltspcs && !opt_notspcs)
@@ -5449,6 +5632,14 @@ int main(int argc, char **argv)
dump_databases(argv);
}
+ /* if --dump-slave , start the slave sql thread */
+ if (opt_slave_data && do_start_slave_sql(mysql))
+ goto err;
+
+ /* add 'START SLAVE' to end of dump */
+ if (opt_slave_apply && add_slave_statements())
+ goto err;
+
/* ensure dumped data flushed */
if (md_result_file && fflush(md_result_file))
{
@@ -5461,7 +5652,7 @@ int main(int argc, char **argv)
goto err;
#ifdef HAVE_SMEM
- my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(shared_memory_base_name);
#endif
/*
No reason to explicitely COMMIT the transaction, neither to explicitely
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 0067f5b3a8b..77d0cd0a7d3 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -59,23 +59,21 @@ static char *opt_password=0, *current_user=0,
*current_host=0, *current_db=0, *fields_terminated=0,
*lines_terminated=0, *enclosed=0, *opt_enclosed=0,
*escaped=0, *opt_columns=0,
- *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
+ *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME;
static uint opt_mysql_port= 0, opt_protocol= 0;
static char * opt_mysql_unix_port=0;
+static char *opt_plugin_dir= 0, *opt_default_auth= 0;
static longlong opt_ignore_lines= -1;
-static CHARSET_INFO *charset_info= &my_charset_latin1;
#include <sslopt-vars.h>
+static char **argv_to_free;
+
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
#endif
static struct my_option my_long_options[] =
{
-#ifdef __NETWARE__
- {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
{"character-sets-dir", OPT_CHARSETS_DIR,
"Directory for character set files.", (char**) &charsets_dir,
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -97,6 +95,10 @@ static struct my_option my_long_options[] =
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
&debug_info_flag, &debug_info_flag,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_DEFAULT_AUTH,
+ "Default authentication client-side plugin to use.",
+ &opt_default_auth, &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"delete", 'd', "First delete all rows from table.", &opt_delete,
&opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"fields-terminated-by", OPT_FTB,
@@ -146,6 +148,9 @@ static struct my_option my_long_options[] =
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ &opt_plugin_dir, &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection or 0 for default to, in "
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
#if MYSQL_PORT_DEFAULT == 0
@@ -190,13 +195,11 @@ static struct my_option my_long_options[] =
static const char *load_default_groups[]=
{ "mysqlimport","client", "client-server", "client-mariadb", 0 };
-#include <help_start.h>
static void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n" ,my_progname,
IMPORT_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
- NETWARE_SET_SCREEN_MODE(1);
}
@@ -219,25 +222,19 @@ file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n");
my_print_variables(my_long_options);
}
-#include <help_end.h>
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
switch(optid) {
-#ifdef __NETWARE__
- case OPT_AUTO_CLOSE:
- setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
- break;
-#endif
case 'p':
if (argument == disabled_my_option)
argument= (char*) ""; /* Don't require password */
if (argument)
{
char *start=argument;
- my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_password);
opt_password=my_strdup(argument,MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start)
@@ -293,10 +290,6 @@ static int get_options(int *argc, char ***argv)
fprintf(stderr, "You can't use --ignore (-i) and --replace (-r) at the same time.\n");
return(1);
}
- if (strcmp(default_charset, charset_info->csname) &&
- !(charset_info= get_charset_by_csname(default_charset,
- MY_CS_PRIMARY, MYF(MY_WME))))
- exit(1);
if (*argc < 2)
{
usage();
@@ -451,6 +444,14 @@ static MYSQL *db_connect(char *host, char *database,
if (shared_memory_base_name)
mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
#endif
+
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
+ mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
if (!(mysql_real_connect(mysql,host,user,passwd,
database,opt_mysql_port,opt_mysql_unix_port,
0)))
@@ -482,10 +483,18 @@ static void db_disconnect(char *host, MYSQL *mysql)
static void safe_exit(int error, MYSQL *mysql)
{
- if (ignore_errors)
+ if (error && ignore_errors)
return;
if (mysql)
mysql_close(mysql);
+
+#ifdef HAVE_SMEM
+ my_free(shared_memory_base_name);
+#endif
+ free_defaults(argv_to_free);
+ mysql_library_end();
+ my_free(opt_password);
+ my_end(my_end_arg);
exit(error);
}
@@ -604,10 +613,11 @@ error:
int main(int argc, char **argv)
{
int error=0;
- char **argv_to_free;
MY_INIT(argv[0]);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ return 1;
/* argv is changed in the program */
argv_to_free= argv;
if (get_options(&argc, &argv))
@@ -615,6 +625,7 @@ int main(int argc, char **argv)
free_defaults(argv_to_free);
return(1);
}
+ sf_leaking_memory=0; /* from now on we cleanup properly */
#ifdef HAVE_LIBPTHREAD
if (opt_use_threads && !lock_tables)
@@ -625,8 +636,8 @@ int main(int argc, char **argv)
pthread_attr_setdetachstate(&attr,
PTHREAD_CREATE_DETACHED);
- VOID(pthread_mutex_init(&counter_mutex, NULL));
- VOID(pthread_cond_init(&count_threshhold, NULL));
+ pthread_mutex_init(&counter_mutex, NULL);
+ pthread_cond_init(&count_threshhold, NULL);
for (counter= 0; *argv != NULL; argv++) /* Loop through tables */
{
@@ -665,8 +676,8 @@ int main(int argc, char **argv)
pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
}
pthread_mutex_unlock(&counter_mutex);
- VOID(pthread_mutex_destroy(&counter_mutex));
- VOID(pthread_cond_destroy(&count_threshhold));
+ pthread_mutex_destroy(&counter_mutex);
+ pthread_cond_destroy(&count_threshhold);
pthread_attr_destroy(&attr);
}
else
@@ -693,11 +704,6 @@ int main(int argc, char **argv)
exitcode= error;
db_disconnect(current_host, mysql);
}
- my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
-#ifdef HAVE_SMEM
- my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
-#endif
- free_defaults(argv_to_free);
- my_end(my_end_arg);
+ safe_exit(0, 0);
return(exitcode);
}
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 7d73c0108cf..323c4282ff4 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -1,5 +1,6 @@
/*
Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2012, Monty Program 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
@@ -35,7 +36,8 @@ static my_bool tty_password= 0, opt_table_type= 0;
static my_bool debug_info_flag= 0, debug_check_flag= 0;
static uint my_end_arg= 0;
static uint opt_verbose=0;
-static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
+static char *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME;
+static char *opt_plugin_dir= 0, *opt_default_auth= 0;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
@@ -67,9 +69,13 @@ int main(int argc, char **argv)
char *wild;
MYSQL mysql;
MY_INIT(argv[0]);
- load_defaults("my",load_default_groups,&argc,&argv);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ exit(1);
+
get_options(&argc,&argv);
+ sf_leaking_memory=0; /* from now on we cleanup properly */
wild=0;
if (argc)
{
@@ -125,6 +131,12 @@ int main(int argc, char **argv)
#endif
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
if (!(mysql_real_connect(&mysql,host,user,opt_password,
(first_argument_uses_wildcards) ? "" :
argv[0],opt_mysql_port,opt_mysql_unix_port,
@@ -151,10 +163,9 @@ int main(int argc, char **argv)
break;
}
mysql_close(&mysql); /* Close & free connection */
- if (opt_password)
- my_free(opt_password,MYF(0));
+ my_free(opt_password);
#ifdef HAVE_SMEM
- my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(shared_memory_base_name);
#endif
my_end(my_end_arg);
exit(error ? 1 : 0);
@@ -163,10 +174,6 @@ int main(int argc, char **argv)
static struct my_option my_long_options[] =
{
-#ifdef __NETWARE__
- {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
{"character-sets-dir", 'c', "Directory for character set files.",
(char**) &charsets_dir, (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
0, 0, 0, 0, 0},
@@ -188,6 +195,10 @@ static struct my_option my_long_options[] =
{"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
&debug_info_flag, &debug_info_flag,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_DEFAULT_AUTH,
+ "Default authentication client-side plugin to use.",
+ &opt_default_auth, &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host.", &host, &host, 0, GET_STR,
@@ -201,6 +212,9 @@ static struct my_option my_long_options[] =
"Password to use when connecting to server. If password is not given, it's "
"solicited on the tty.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ &opt_plugin_dir, &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection or 0 for default to, in "
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
#if MYSQL_PORT_DEFAULT == 0
@@ -243,14 +257,11 @@ static struct my_option my_long_options[] =
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-
-#include <help_start.h>
static void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION,
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
- NETWARE_SET_SCREEN_MODE(1);
}
@@ -272,18 +283,12 @@ are shown.");
my_print_variables(my_long_options);
}
-#include <help_end.h>
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
switch(optid) {
-#ifdef __NETWARE__
- case OPT_AUTO_CLOSE:
- setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
- break;
-#endif
case 'v':
opt_verbose++;
break;
@@ -293,7 +298,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (argument)
{
char *start=argument;
- my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_password);
opt_password=my_strdup(argument,MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start)
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index f568ef9d2e2..8e70a2609c3 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -13,12 +13,8 @@
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
- original idea: Brian Aker via playing with ab for too many years
- coded by: Patrick Galbraith
*/
-
/*
MySQL Slap
@@ -128,6 +124,7 @@ static char *host= NULL, *opt_password= NULL, *user= NULL,
*pre_system= NULL,
*post_system= NULL,
*opt_mysql_unix_port= NULL;
+static char *opt_plugin_dir= 0, *opt_default_auth= 0;
const char *delimiter= "\n";
@@ -321,8 +318,13 @@ int main(int argc, char **argv)
option_string *eptr;
MY_INIT(argv[0]);
+ sf_leaking_memory=1; /* don't report memory leaks on early exits */
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ {
+ my_end(0);
+ exit(1);
+ }
defaults_argv=argv;
if (get_options(&argc,&argv))
{
@@ -330,6 +332,7 @@ int main(int argc, char **argv)
my_end(0);
exit(1);
}
+ sf_leaking_memory=0; /* from now on we cleanup properly */
/* Seed the random number generator if we will be using it. */
if (auto_generate_sql)
@@ -348,6 +351,12 @@ int main(int argc, char **argv)
mysql_init(&mysql);
set_mysql_connect_options(&mysql);
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
if (!opt_only_print)
{
if (!(mysql_real_connect(&mysql, host, user, opt_password,
@@ -362,10 +371,10 @@ int main(int argc, char **argv)
}
}
- VOID(pthread_mutex_init(&counter_mutex, NULL));
- VOID(pthread_cond_init(&count_threshhold, NULL));
- VOID(pthread_mutex_init(&sleeper_mutex, NULL));
- VOID(pthread_cond_init(&sleep_threshhold, NULL));
+ pthread_mutex_init(&counter_mutex, NULL);
+ pthread_cond_init(&count_threshhold, NULL);
+ pthread_mutex_init(&sleeper_mutex, NULL);
+ pthread_cond_init(&sleep_threshhold, NULL);
/* Main iterations loop */
eptr= engine_options;
@@ -396,19 +405,17 @@ int main(int argc, char **argv)
} while (eptr ? (eptr= eptr->next) : 0);
- VOID(pthread_mutex_destroy(&counter_mutex));
- VOID(pthread_cond_destroy(&count_threshhold));
- VOID(pthread_mutex_destroy(&sleeper_mutex));
- VOID(pthread_cond_destroy(&sleep_threshhold));
+ pthread_mutex_destroy(&counter_mutex);
+ pthread_cond_destroy(&count_threshhold);
+ pthread_mutex_destroy(&sleeper_mutex);
+ pthread_cond_destroy(&sleep_threshhold);
if (!opt_only_print)
mysql_close(&mysql); /* Close & free connection */
/* now free all the strings we created */
- if (opt_password)
- my_free(opt_password, MYF(0));
-
- my_free(concurrency, MYF(0));
+ my_free(opt_password);
+ my_free(concurrency);
statement_cleanup(create_statements);
statement_cleanup(query_statements);
@@ -417,10 +424,10 @@ int main(int argc, char **argv)
option_cleanup(engine_options);
#ifdef HAVE_SMEM
- if (shared_memory_base_name)
- my_free(shared_memory_base_name, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(shared_memory_base_name);
#endif
free_defaults(defaults_argv);
+ mysql_library_end();
my_end(my_end_arg);
return 0;
@@ -518,7 +525,7 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
if (opt_csv_str)
print_conclusions_csv(&conclusion);
- my_free(head_sptr, MYF(0));
+ my_free(head_sptr);
}
@@ -602,6 +609,10 @@ static struct my_option my_long_options[] =
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"debug-info", 'T', "Print some debug info at exit.", &debug_info_flag,
&debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_DEFAULT_AUTH,
+ "Default authentication client-side plugin to use.",
+ &opt_default_auth, &opt_default_auth, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"delimiter", 'F',
"Delimiter to use in SQL statements supplied in file or command line.",
(char**) &delimiter, (char**) &delimiter, 0, GET_STR, REQUIRED_ARG,
@@ -646,6 +657,9 @@ static struct my_option my_long_options[] =
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ &opt_plugin_dir, &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection.", &opt_mysql_port,
&opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
0},
@@ -698,8 +712,6 @@ static struct my_option my_long_options[] =
};
-#include <help_start.h>
-
static void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname, SLAP_VERSION,
@@ -717,7 +729,6 @@ static void usage(void)
my_print_help(my_long_options);
}
-#include <help_end.h>
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
@@ -725,11 +736,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
{
DBUG_ENTER("get_one_option");
switch(optid) {
-#ifdef __NETWARE__
- case OPT_AUTO_CLOSE:
- setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
- break;
-#endif
case 'v':
verbose++;
break;
@@ -739,7 +745,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (argument)
{
char *start= argument;
- my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_password);
opt_password= my_strdup(argument,MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start)
@@ -1390,7 +1396,7 @@ get_options(int *argc,char ***argv)
tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0));
parse_delimiter(tmp_string, &create_statements, delimiter[0]);
- my_free(tmp_string, MYF(0));
+ my_free(tmp_string);
}
else if (create_string)
{
@@ -1419,7 +1425,7 @@ get_options(int *argc,char ***argv)
if (user_supplied_query)
actual_queries= parse_delimiter(tmp_string, &query_statements,
delimiter[0]);
- my_free(tmp_string, MYF(0));
+ my_free(tmp_string);
}
else if (user_supplied_query)
{
@@ -1450,7 +1456,7 @@ get_options(int *argc,char ***argv)
if (user_supplied_pre_statements)
(void)parse_delimiter(tmp_string, &pre_statements,
delimiter[0]);
- my_free(tmp_string, MYF(0));
+ my_free(tmp_string);
}
else if (user_supplied_pre_statements)
{
@@ -1481,7 +1487,7 @@ get_options(int *argc,char ***argv)
if (user_supplied_post_statements)
(void)parse_delimiter(tmp_string, &post_statements,
delimiter[0]);
- my_free(tmp_string, MYF(0));
+ my_free(tmp_string);
}
else if (user_supplied_post_statements)
{
@@ -1585,9 +1591,9 @@ drop_primary_key_list(void)
if (primary_keys_number_of)
{
for (counter= 0; counter < primary_keys_number_of; counter++)
- my_free(primary_keys[counter], MYF(0));
+ my_free(primary_keys[counter]);
- my_free(primary_keys, MYF(0));
+ my_free(primary_keys);
}
return 0;
@@ -2204,11 +2210,9 @@ option_cleanup(option_string *stmt)
for (ptr= stmt; ptr; ptr= nptr)
{
nptr= ptr->next;
- if (ptr->string)
- my_free(ptr->string, MYF(0));
- if (ptr->option)
- my_free(ptr->option, MYF(0));
- my_free(ptr, MYF(0));
+ my_free(ptr->string);
+ my_free(ptr->option);
+ my_free(ptr);
}
}
@@ -2222,9 +2226,8 @@ statement_cleanup(statement *stmt)
for (ptr= stmt; ptr; ptr= nptr)
{
nptr= ptr->next;
- if (ptr->string)
- my_free(ptr->string, MYF(0));
- my_free(ptr, MYF(0));
+ my_free(ptr->string);
+ my_free(ptr);
}
}
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 2cf3faae0b6..5415b653615 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
- Copyright (c) 2009, 2012 Monty Program Ab.
+ Copyright (c) 2009, 2012, Monty Program 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
@@ -12,8 +12,7 @@
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/*
mysqltest
@@ -34,7 +33,7 @@
And many others
*/
-#define MTEST_VERSION "3.3"
+#define MTEST_VERSION "3.4"
#include "client_priv.h"
#include <mysql_version.h>
@@ -64,6 +63,12 @@
#define SIGNAL_FMT "signal %d"
#endif
+static my_bool non_blocking_api_enabled= 0;
+#if !defined(EMBEDDED_LIBRARY)
+#define WRAP_NONBLOCK_ENABLED non_blocking_api_enabled
+#include "../tests/nonblock-wrappers.h"
+#endif
+
/* Use cygwin for --exec and --system before 5.0 */
#if MYSQL_VERSION_ID < 50000
#define USE_CYGWIN
@@ -75,6 +80,8 @@
#define MAX_DELIMITER_LENGTH 16
#define DEFAULT_MAX_CONN 64
+#define DIE_BUFF_SIZE 8192
+
/* Flags controlling send and reap */
#define QUERY_SEND_FLAG 1
#define QUERY_REAP_FLAG 2
@@ -83,27 +90,28 @@
static int setenv(const char *name, const char *value, int overwrite);
#endif
+C_MODE_START
+static sig_handler signal_handler(int sig);
+static my_bool get_one_option(int optid, const struct my_option *,
+ char *argument);
+C_MODE_END
+
enum {
- OPT_SKIP_SAFEMALLOC=OPT_MAX_CLIENT_OPTION,
- OPT_PS_PROTOCOL, OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
- OPT_MAX_CONNECT_RETRIES, OPT_MAX_CONNECTIONS,
- OPT_MARK_PROGRESS, OPT_LOG_DIR, OPT_TAIL_LINES,
- OPT_GLOBAL_SUBST, OPT_MY_CONNECT_TIMEOUT
+ OPT_LOG_DIR=OPT_MAX_CLIENT_OPTION, OPT_RESULT_FORMAT_VERSION
};
static int record= 0, opt_sleep= -1;
static char *opt_db= 0, *opt_pass= 0;
const char *opt_user= 0, *opt_host= 0, *unix_sock= 0, *opt_basedir= "./";
-#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
-#endif
const char *opt_logdir= "";
-const char *opt_include= 0, *opt_charsets_dir;
+const char *opt_prologue= 0, *opt_charsets_dir;
static int opt_port= 0;
static int opt_max_connect_retries;
+static int opt_result_format_version;
static int opt_max_connections= DEFAULT_MAX_CONN;
+static int error_count= 0;
static my_bool opt_compress= 0, silent= 0, verbose= 0;
-static int opt_connect_timeout= -1;
static my_bool debug_info_flag= 0, debug_check_flag= 0;
static my_bool tty_password= 0;
static my_bool opt_mark_progress= 0;
@@ -119,8 +127,7 @@ static my_bool disable_connect_log= 1;
static my_bool disable_warnings= 0, disable_column_names= 0;
static my_bool prepare_warnings_enabled= 0;
static my_bool disable_info= 1;
-static char *opt_plugin_dir= 0, *opt_default_auth;
-static my_bool abort_on_error= 1;
+static my_bool abort_on_error= 1, opt_continue_on_error= 0;
static my_bool server_initialized= 0;
static my_bool is_windows= 0;
static char **default_argv;
@@ -128,12 +135,49 @@ static const char *load_default_groups[]=
{ "mysqltest", "client", "client-server", "client-mariadb", 0 };
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
+/* Info on properties that can be set with --enable_X and --disable_X */
+
+struct property {
+ my_bool *var; /* Actual variable */
+ my_bool set; /* Has been set for ONE command */
+ my_bool old; /* If set, thus is the old value */
+ my_bool reverse; /* Varible is true if disabled */
+ const char *env_name; /* Env. variable name */
+};
+
+static struct property prop_list[] = {
+ { &abort_on_error, 0, 1, 0, "$ENABLED_ABORT_ON_ERROR" },
+ { &disable_connect_log, 0, 1, 1, "$ENABLED_CONNECT_LOG" },
+ { &disable_info, 0, 1, 1, "$ENABLED_INFO" },
+ { &display_metadata, 0, 0, 0, "$ENABLED_METADATA" },
+ { &ps_protocol_enabled, 0, 0, 0, "$ENABLED_PS_PROTOCOL" },
+ { &disable_query_log, 0, 0, 1, "$ENABLED_QUERY_LOG" },
+ { &disable_result_log, 0, 0, 1, "$ENABLED_RESULT_LOG" },
+ { &disable_warnings, 0, 0, 1, "$ENABLED_WARNINGS" }
+};
+
+static my_bool once_property= FALSE;
+
+enum enum_prop {
+ P_ABORT= 0,
+ P_CONNECT,
+ P_INFO,
+ P_META,
+ P_PS,
+ P_QUERY,
+ P_RESULT,
+ P_WARN,
+ P_MAX
+};
+
static uint start_lineno= 0; /* Start line of current command */
static uint my_end_arg= 0;
/* Number of lines of the result to include in failure report */
static uint opt_tail_lines= 0;
+static uint opt_connect_timeout= 0;
+
static char delimiter[MAX_DELIMITER_LENGTH]= ";";
static uint delimiter_length= 1;
@@ -165,7 +209,7 @@ static struct st_block *cur_block, *block_stack_end;
struct st_test_file
{
FILE* file;
- const char *file_name;
+ char *file_name;
uint lineno; /* Current line in file */
};
@@ -173,7 +217,6 @@ static struct st_test_file file_stack[16];
static struct st_test_file* cur_file;
static struct st_test_file* file_stack_end;
-
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
static const char *embedded_server_groups[]=
@@ -199,6 +242,10 @@ static ulonglong timer_now(void);
static ulong connection_retry_sleep= 100000; /* Microseconds */
+static const char *opt_plugin_dir;
+static const char *opt_suite_dir, *opt_overlay_dir;
+static size_t suite_dir_len, overlay_dir_len;
+
/* Precompiled re's */
static my_regex_t ps_re; /* the query can be run using PS protocol */
static my_regex_t sp_re; /* the query can be run as a SP */
@@ -240,8 +287,9 @@ typedef struct
int str_val_len;
int int_val;
int alloced_len;
- int int_dirty; /* do not update string if int is updated until first read */
- int alloced;
+ bool int_dirty; /* do not update string if int is updated until first read */
+ bool is_int;
+ bool alloced;
} VAR;
/*Perl/shell-like variable registers */
@@ -261,13 +309,16 @@ struct st_connection
my_bool pending;
#ifdef EMBEDDED_LIBRARY
+ pthread_t tid;
const char *cur_query;
int cur_query_len;
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- pthread_t tid;
+ int command, result;
+ pthread_mutex_t query_mutex;
+ pthread_cond_t query_cond;
+ pthread_mutex_t result_mutex;
+ pthread_cond_t result_cond;
int query_done;
- my_bool has_thread, mutex_inited;
+ my_bool has_thread;
#endif /*EMBEDDED_LIBRARY*/
};
@@ -294,8 +345,7 @@ enum enum_commands {
Q_SEND, Q_REAP,
Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
Q_PING, Q_EVAL,
- Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
- Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
+ Q_EVAL_RESULT,
Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
Q_ENABLE_CONNECT_LOG, Q_DISABLE_CONNECT_LOG,
@@ -311,6 +361,7 @@ enum enum_commands {
Q_LOWERCASE,
Q_START_TIMER, Q_END_TIMER,
Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
+ Q_ENABLE_NON_BLOCKING_API, Q_DISABLE_NON_BLOCKING_API,
Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
Q_IF,
Q_DISABLE_PARSING, Q_ENABLE_PARSING,
@@ -320,12 +371,13 @@ enum enum_commands {
Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
Q_LIST_FILES, Q_LIST_FILES_WRITE_FILE, Q_LIST_FILES_APPEND_FILE,
Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER,
+ Q_RESULT_FORMAT_VERSION,
Q_MOVE_FILE, Q_REMOVE_FILES_WILDCARD, Q_SEND_EVAL,
Q_ENABLE_PREPARE_WARNINGS, Q_DISABLE_PREPARE_WARNINGS,
-
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
- Q_COMMENT_WITH_COMMAND
+ Q_COMMENT_WITH_COMMAND,
+ Q_EMPTY_LINE
};
@@ -358,9 +410,6 @@ const char *command_names[]=
"replace_column",
"ping",
"eval",
- "rpl_probe",
- "enable_rpl_parse",
- "disable_rpl_parse",
"eval_result",
/* Enable/disable that the _query_ is logged to result file */
"enable_query_log",
@@ -394,6 +443,8 @@ const char *command_names[]=
"character_set",
"disable_ps_protocol",
"enable_ps_protocol",
+ "enable_non_blocking_api",
+ "disable_non_blocking_api",
"disable_reconnect",
"enable_reconnect",
"if",
@@ -423,6 +474,7 @@ const char *command_names[]=
"list_files_append_file",
"send_shutdown",
"shutdown_server",
+ "result_format",
"move_file",
"remove_files_wildcard",
"send_eval",
@@ -479,28 +531,56 @@ TYPELIB command_typelib= {array_elements(command_names),"",
command_names, 0};
DYNAMIC_STRING ds_res;
+/* Points to ds_warning in run_query, so it can be freed */
+DYNAMIC_STRING *ds_warn= 0;
struct st_command *curr_command= 0;
char builtin_echo[FN_REFLEN];
+struct st_replace_regex
+{
+DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
+
+/*
+Temporary storage areas for substitutions. To reduce unnessary copying
+and memory freeing/allocation, we pre-allocate two buffers, and alternate
+their use, one for input/one for output, the roles changing on the next
+st_regex substition. At the end of substitutions buf points to the
+one containing the final result.
+*/
+char* buf;
+char* even_buf;
+char* odd_buf;
+int even_buf_len;
+int odd_buf_len;
+};
+
+struct st_replace_regex *glob_replace_regex= 0;
+
+struct st_replace;
+struct st_replace *glob_replace= 0;
+void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
+const char *from, int len);
+
static void cleanup_and_exit(int exit_code) __attribute__((noreturn));
-void die(const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2) __attribute__((noreturn));
-void abort_not_supported_test(const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2) __attribute__((noreturn));
-void verbose_msg(const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2);
-void log_msg(const char *fmt, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2);
+void really_die(const char *msg) __attribute__((noreturn));
+void report_or_die(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
+void die(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2)
+ __attribute__((noreturn));
+static void make_error_message(char *buf, size_t len, const char *fmt, va_list args);
+void abort_not_supported_test(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2)
+ __attribute__((noreturn));
+void verbose_msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
+void log_msg(const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
VAR* var_from_env(const char *, const char *);
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
int val_len);
-void var_free(void* v);
VAR* var_get(const char *var_name, const char** var_name_end,
my_bool raw, my_bool ignore_not_existing);
-void eval_expr(VAR* v, const char *p, const char** p_end, bool do_eval= true);
+void eval_expr(VAR* v, const char *p, const char** p_end,
+ bool open_end=false, bool do_eval=true);
my_bool match_delimiter(int c, const char *delim, uint length);
void dump_result_to_reject_file(char *buf, int size);
void dump_warning_messages();
@@ -511,6 +591,8 @@ void str_to_file(const char *fname, char *str, int size);
void str_to_file2(const char *fname, char *str, int size, my_bool append);
void fix_win_paths(const char *val, int len);
+const char *get_errname_from_code (uint error_code);
+int multi_reg_replace(struct st_replace_regex* r,char* val);
#ifdef __WIN__
void free_tmp_sh_file();
@@ -541,6 +623,8 @@ void free_all_replace(){
free_replace_column();
}
+void var_set_int(const char* name, int value);
+
class LogFile {
FILE* m_file;
@@ -561,8 +645,7 @@ public:
void open(const char* dir, const char* name, const char* ext)
{
DBUG_ENTER("LogFile::open");
- DBUG_PRINT("enter", ("dir: '%s', name: '%s'",
- val_or_null(dir), val_or_null(name)));
+ DBUG_PRINT("enter", ("dir: '%s', name: '%s'", dir, name));
if (!name)
{
m_file= stdout;
@@ -657,9 +740,8 @@ public:
DBUG_VOID_RETURN;
}
- IF_DBUG(buf[bytes]= '\0';)
- DBUG_PRINT("info", ("Read %lu bytes from file, buf: %s",
- (unsigned long)bytes, buf));
+ DBUG_PRINT("info", ("Read %zu bytes from file, buf: %.*s",
+ bytes, (int)bytes, buf));
char* show_from= buf + bytes;
while(show_from > buf && lines > 0 )
@@ -722,14 +804,6 @@ public:
LogFile log_file;
LogFile progress_file;
-
-/* Disable functions that only exist in MySQL 4.0 */
-#if MYSQL_VERSION_ID < 40000
-void mysql_enable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
-void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
-int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
-my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
-#endif
void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
int len);
void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
@@ -744,12 +818,17 @@ void handle_error(struct st_command*,
unsigned int err_errno, const char *err_error,
const char *err_sqlstate, DYNAMIC_STRING *ds);
void handle_no_error(struct st_command*);
+void revert_properties();
static void handle_no_active_connection(struct st_command* command,
struct st_connection *cn, DYNAMIC_STRING *ds);
#ifdef EMBEDDED_LIBRARY
+#define EMB_SEND_QUERY 1
+#define EMB_READ_QUERY_RESULT 2
+#define EMB_END_CONNECTION 3
+
/* workaround for MySQL BUG#57491 */
#undef MY_WME
#define MY_WME 0
@@ -757,90 +836,140 @@ static void handle_no_active_connection(struct st_command* command,
/* attributes of the query thread */
pthread_attr_t cn_thd_attrib;
+
/*
- send_one_query executes query in separate thread, which is
- necessary in embedded library to run 'send' in proper way.
- This implementation doesn't handle errors returned
- by mysql_send_query. It's technically possible, though
- I don't see where it is needed.
+ This procedure represents the connection and actually
+ runs queries when in the EMBEDDED-SERVER mode.
+ The run_query_normal() just sends request for running
+ mysql_send_query and mysql_read_query_result() here.
*/
-pthread_handler_t send_one_query(void *arg)
+
+pthread_handler_t connection_thread(void *arg)
{
struct st_connection *cn= (struct st_connection*)arg;
- if (!cn->mysql)
- return 0;
-
mysql_thread_init();
- VOID(mysql_send_query(cn->mysql, cn->cur_query, cn->cur_query_len));
+ while (cn->command != EMB_END_CONNECTION)
+ {
+ if (!cn->command)
+ {
+ pthread_mutex_lock(&cn->query_mutex);
+ while (!cn->command)
+ pthread_cond_wait(&cn->query_cond, &cn->query_mutex);
+ pthread_mutex_unlock(&cn->query_mutex);
+ }
+ switch (cn->command)
+ {
+ case EMB_END_CONNECTION:
+ goto end_thread;
+ case EMB_SEND_QUERY:
+ cn->result= mysql_send_query(cn->mysql, cn->cur_query, cn->cur_query_len);
+ break;
+ case EMB_READ_QUERY_RESULT:
+ cn->result= mysql_read_query_result(cn->mysql);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ cn->command= 0;
+ pthread_mutex_lock(&cn->result_mutex);
+ cn->query_done= 1;
+ pthread_cond_signal(&cn->result_cond);
+ pthread_mutex_unlock(&cn->result_mutex);
+ }
- mysql_thread_end();
- pthread_mutex_lock(&cn->mutex);
+end_thread:
cn->query_done= 1;
- VOID(pthread_cond_signal(&cn->cond));
- pthread_mutex_unlock(&cn->mutex);
+ mysql_thread_end();
pthread_exit(0);
return 0;
}
-static int do_send_query(struct st_connection *cn, const char *q, int q_len,
- int flags)
+static void wait_query_thread_done(struct st_connection *con)
{
- if (!cn->mysql)
- die("Trying to send a query without a connection");
+ DBUG_ASSERT(con->has_thread);
+ if (!con->query_done)
+ {
+ pthread_mutex_lock(&con->result_mutex);
+ while (!con->query_done)
+ pthread_cond_wait(&con->result_cond, &con->result_mutex);
+ pthread_mutex_unlock(&con->result_mutex);
+ }
+}
- if (flags & QUERY_REAP_FLAG)
- return mysql_send_query(cn->mysql, q, q_len);
- if (!cn->mutex_inited &&
- (pthread_mutex_init(&cn->mutex, NULL) ||
- pthread_cond_init(&cn->cond, NULL)))
- die("Error in the thread library");
+static void signal_connection_thd(struct st_connection *cn, int command)
+{
+ DBUG_ASSERT(cn->has_thread);
+ cn->query_done= 0;
+ cn->command= command;
+ pthread_mutex_lock(&cn->query_mutex);
+ pthread_cond_signal(&cn->query_cond);
+ pthread_mutex_unlock(&cn->query_mutex);
+}
+
- cn->mutex_inited= 1;
+/*
+ Sometimes we try to execute queries when the connection is closed.
+ It's done to make sure it was closed completely.
+ So that if our connection is closed (cn->has_thread == 0), we just return
+ the mysql_send_query() result which is an error in this case.
+*/
+
+static int do_send_query(struct st_connection *cn, const char *q, int q_len)
+{
+ if (!cn->has_thread)
+ return mysql_send_query(cn->mysql, q, q_len);
cn->cur_query= q;
cn->cur_query_len= q_len;
- cn->query_done= 0;
- if (pthread_create(&cn->tid, &cn_thd_attrib, send_one_query, (void*)cn))
- die("Cannot start new thread for query");
-
- cn->has_thread= TRUE;
+ signal_connection_thd(cn, EMB_SEND_QUERY);
return 0;
}
-static void wait_query_thread_end(struct st_connection *con)
+static int do_read_query_result(struct st_connection *cn)
{
- if (!con->query_done)
- {
- pthread_mutex_lock(&con->mutex);
- while (!con->query_done)
- pthread_cond_wait(&con->cond, &con->mutex);
- pthread_mutex_unlock(&con->mutex);
- }
- if (con->has_thread)
- {
-#ifndef __WIN__
- /* May hang on Windows, but the problem it solves is not seen there */
- pthread_join(con->tid, NULL);
-#endif
- con->has_thread= FALSE;
- }
+ DBUG_ASSERT(cn->has_thread);
+ wait_query_thread_done(cn);
+ signal_connection_thd(cn, EMB_READ_QUERY_RESULT);
+ wait_query_thread_done(cn);
+
+ return cn->result;
}
-static void free_embedded_data(struct st_connection *con)
+
+static void emb_close_connection(struct st_connection *cn)
{
- if (con->mutex_inited)
- {
- con->mutex_inited= 0;
- pthread_mutex_destroy(&con->mutex);
- pthread_cond_destroy(&con->cond);
- }
+ if (!cn->has_thread)
+ return;
+ wait_query_thread_done(cn);
+ signal_connection_thd(cn, EMB_END_CONNECTION);
+ pthread_join(cn->tid, NULL);
+ cn->has_thread= FALSE;
+ pthread_mutex_destroy(&cn->query_mutex);
+ pthread_cond_destroy(&cn->query_cond);
+ pthread_mutex_destroy(&cn->result_mutex);
+ pthread_cond_destroy(&cn->result_cond);
+}
+
+
+static void init_connection_thd(struct st_connection *cn)
+{
+ cn->query_done= 1;
+ cn->command= 0;
+ if (pthread_mutex_init(&cn->query_mutex, NULL) ||
+ pthread_cond_init(&cn->query_cond, NULL) ||
+ pthread_mutex_init(&cn->result_mutex, NULL) ||
+ pthread_cond_init(&cn->result_cond, NULL) ||
+ pthread_create(&cn->tid, &cn_thd_attrib, connection_thread, (void*)cn))
+ die("Error in the thread library");
+ cn->has_thread=TRUE;
}
#else /*EMBEDDED_LIBRARY*/
-#define do_send_query(cn,q,q_len,flags) mysql_send_query(cn->mysql, q, q_len)
-#define free_embedded_data(next_con) do { } while(0)
+#define init_connection_thd(X) do { } while(0)
+#define do_send_query(cn,q,q_len) mysql_send_query(cn->mysql, q, q_len)
+#define do_read_query_result(cn) mysql_read_query_result(cn->mysql)
#endif /*EMBEDDED_LIBRARY*/
@@ -865,7 +994,10 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
else
{
if (!(v= var_get(p, &p, 0, 0)))
- die("Bad variable in eval");
+ {
+ report_or_die( "Bad variable in eval");
+ return;
+ }
dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
}
break;
@@ -1147,14 +1279,20 @@ void handle_command_error(struct st_command *command, uint error,
{
DBUG_ENTER("handle_command_error");
DBUG_PRINT("enter", ("error: %d", error));
+ var_set_int("$sys_errno",sys_errno);
+ var_set_int("$errno",error);
if (error != 0)
{
int i;
if (command->abort_on_error)
- die("command \"%.*s\" failed with error: %u my_errno: %d errno: %d",
+ {
+ report_or_die("command \"%.*s\" failed with error: %u my_errno: %d "
+ "errno: %d",
command->first_word_len, command->query, error, my_errno,
sys_errno);
+ DBUG_VOID_RETURN;
+ }
i= match_expected_error(command, error, NULL);
@@ -1163,20 +1301,25 @@ void handle_command_error(struct st_command *command, uint error,
DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %u, errno: %d",
command->first_word_len, command->query, error,
sys_errno));
+ revert_properties();
DBUG_VOID_RETURN;
}
if (command->expected_errors.count > 0)
- die("command \"%.*s\" failed with wrong error: %u my_errno: %d errno: %d",
- command->first_word_len, command->query, error, my_errno, sys_errno);
+ report_or_die("command \"%.*s\" failed with wrong error: %u "
+ "my_errno: %d errno: %d",
+ command->first_word_len, command->query, error, my_errno,
+ sys_errno);
}
else if (command->expected_errors.err[0].type == ERR_ERRNO &&
command->expected_errors.err[0].code.errnum != 0)
{
/* Error code we wanted was != 0, i.e. not an expected success */
- die("command \"%.*s\" succeeded - should have failed with errno %d...",
+ report_or_die("command \"%.*s\" succeeded - should have failed with "
+ "errno %d...",
command->first_word_len, command->query,
command->expected_errors.err[0].code.errnum);
}
+ revert_properties();
DBUG_VOID_RETURN;
}
@@ -1186,6 +1329,9 @@ void close_connections()
DBUG_ENTER("close_connections");
for (--next_con; next_con >= connections; --next_con)
{
+#ifdef EMBEDDED_LIBRARY
+ emb_close_connection(next_con);
+#endif
if (next_con->stmt)
mysql_stmt_close(next_con->stmt);
next_con->stmt= 0;
@@ -1193,10 +1339,9 @@ void close_connections()
next_con->mysql= 0;
if (next_con->util_mysql)
mysql_close(next_con->util_mysql);
- my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
- free_embedded_data(next_con);
+ my_free(next_con->name);
}
- my_free(connections, MYF(MY_WME));
+ my_free(connections);
DBUG_VOID_RETURN;
}
@@ -1225,7 +1370,7 @@ void close_files()
DBUG_PRINT("info", ("closing file: %s", cur_file->file_name));
fclose(cur_file->file);
}
- my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(cur_file->file_name);
cur_file->file_name= 0;
}
DBUG_VOID_RETURN;
@@ -1240,27 +1385,29 @@ void free_used_memory()
if (connections)
close_connections();
close_files();
- hash_free(&var_hash);
+ my_hash_free(&var_hash);
for (i= 0 ; i < q_lines.elements ; i++)
{
struct st_command **q= dynamic_element(&q_lines, i, struct st_command**);
- my_free((*q)->query_buf,MYF(MY_ALLOW_ZERO_PTR));
+ my_free((*q)->query_buf);
if ((*q)->content.str)
dynstr_free(&(*q)->content);
- my_free((*q),MYF(0));
+ my_free((*q));
}
for (i= 0; i < 10; i++)
{
if (var_reg[i].alloced_len)
- my_free(var_reg[i].str_val, MYF(MY_WME));
+ my_free(var_reg[i].str_val);
}
while (embedded_server_arg_count > 1)
- my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
+ my_free(embedded_server_args[--embedded_server_arg_count]);
delete_dynamic(&q_lines);
dynstr_free(&ds_res);
+ if (ds_warn)
+ dynstr_free(ds_warn);
free_all_replace();
- my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_pass);
free_defaults(default_argv);
free_root(&require_file_root, MYF(0));
free_re();
@@ -1279,6 +1426,17 @@ static void cleanup_and_exit(int exit_code)
/* Only call mysql_server_end if mysql_server_init has been called */
if (server_initialized)
mysql_server_end();
+
+ /*
+ mysqltest is fundamentally written in a way that makes impossible
+ to free all memory before exit (consider memory allocated
+ for frame local DYNAMIC_STRING's and die() invoked down the stack.
+
+ We close stderr here to stop unavoidable safemalloc reports
+ from polluting the output.
+ */
+ fclose(stderr);
+
my_end(my_end_arg);
if (!silent) {
@@ -1298,52 +1456,63 @@ static void cleanup_and_exit(int exit_code)
}
}
+ sf_leaking_memory= 0; /* all memory should be freed by now */
exit(exit_code);
}
-void print_file_stack()
+size_t print_file_stack(char *s, const char *end)
{
+ char *start= s;
struct st_test_file* err_file= cur_file;
if (err_file == file_stack)
- return;
+ return 0;
for (;;)
{
err_file--;
- fprintf(stderr, "included from %s at line %d:\n",
- err_file->file_name, err_file->lineno);
+ s+= my_snprintf(s, end - s, "included from %s at line %d:\n",
+ err_file->file_name, err_file->lineno);
if (err_file == file_stack)
break;
}
+ return s - start;
}
-void die(const char *fmt, ...)
-{
- static int dying= 0;
- va_list args;
- DBUG_ENTER("die");
- DBUG_PRINT("enter", ("start_lineno: %d", start_lineno));
- fflush(stdout);
- /* Print the error message */
- fprintf(stderr, "mysqltest: ");
+static void make_error_message(char *buf, size_t len, const char *fmt, va_list args)
+{
+ char *s= buf, *end= buf + len;
+ s+= my_snprintf(s, end - s, "mysqltest: ");
if (cur_file && cur_file != file_stack)
{
- fprintf(stderr, "In included file \"%s\": \n",
- cur_file->file_name);
- print_file_stack();
+ s+= my_snprintf(s, end - s, "In included file \"%s\": \n",
+ cur_file->file_name);
+ s+= print_file_stack(s, end);
}
+
if (start_lineno > 0)
- fprintf(stderr, "At line %u: ", start_lineno);
- if (fmt)
- {
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- }
- else
- fprintf(stderr, "unknown error");
- fprintf(stderr, "\n");
+ s+= my_snprintf(s, end -s, "At line %u: ", start_lineno);
+ if (!fmt)
+ fmt= "unknown error";
+
+ s+= my_vsnprintf(s, end - s, fmt, args);
+ s+= my_snprintf(s, end -s, "\n", start_lineno);
+}
+
+void die(const char *fmt, ...)
+{
+ char buff[DIE_BUFF_SIZE];
+ va_list args;
+ va_start(args, fmt);
+ make_error_message(buff, sizeof(buff), fmt, args);
+ really_die(buff);
+}
+
+void really_die(const char *msg)
+{
+ static int dying= 0;
+ fflush(stdout);
+ fprintf(stderr, "%s", msg);
fflush(stderr);
/*
@@ -1367,6 +1536,28 @@ void die(const char *fmt, ...)
cleanup_and_exit(1);
}
+void report_or_die(const char *fmt, ...)
+{
+ va_list args;
+ DBUG_ENTER("report_or_die");
+
+ char buff[DIE_BUFF_SIZE];
+
+ va_start(args, fmt);
+ make_error_message(buff, sizeof(buff), fmt, args);
+ va_end(args);
+
+ if (opt_continue_on_error)
+ {
+ /* Just log the error and continue */
+ replace_dynstr_append(&ds_res, buff);
+ error_count++;
+ DBUG_VOID_RETURN;
+ }
+
+ really_die(buff);
+}
+
void abort_not_supported_test(const char *fmt, ...)
{
@@ -1379,7 +1570,10 @@ void abort_not_supported_test(const char *fmt, ...)
file_stack->file_name);
fprintf(stderr, "Detected in file %s at line %d\n",
cur_file->file_name, cur_file->lineno);
- print_file_stack();
+
+ char buff[DIE_BUFF_SIZE];
+ print_file_stack(buff, buff + sizeof(buff));
+ fprintf(stderr, "%s", buff);
/* Print error message */
va_start(args, fmt);
@@ -1511,7 +1705,10 @@ static int run_command(char* cmd,
DBUG_PRINT("enter", ("cmd: %s", cmd));
if (!(res_file= popen(cmd, "r")))
- die("popen(\"%s\", \"r\") failed", cmd);
+ {
+ report_or_die("popen(\"%s\", \"r\") failed", cmd);
+ return -1;
+ }
while (fgets(buf, sizeof(buf), res_file))
{
@@ -1611,7 +1808,10 @@ static int diff_check(const char *diff_name)
if (!(res_file= popen(buf, "r")))
die("popen(\"%s\", \"r\") failed", buf);
- /* if diff is not present, nothing will be in stdout to increment have_diff */
+ /*
+ if diff is not present, nothing will be in stdout to increment
+ have_diff
+ */
if (fgets(buf, sizeof(buf), res_file))
have_diff= 1;
@@ -1924,7 +2124,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
void check_result()
{
- const char* mess= "Result content mismatch\n";
+ const char *mess= 0;
DBUG_ENTER("check_result");
DBUG_ASSERT(result_file_name);
@@ -1932,9 +2132,13 @@ void check_result()
switch (compare_files(log_file.file_name(), result_file_name)) {
case RESULT_OK:
- break; /* ok */
+ if (!error_count)
+ break; /* ok */
+ mess= "Got errors while running test";
+ /* Fallthrough */
case RESULT_LENGTH_MISMATCH:
- mess= "Result length mismatch\n";
+ if (!mess)
+ mess= "Result length mismatch\n";
/* Fallthrough */
case RESULT_CONTENT_MISMATCH:
{
@@ -1944,6 +2148,10 @@ void check_result()
*/
char reject_file[FN_REFLEN];
size_t reject_length;
+
+ if (!mess)
+ mess= "Result content mismatch\n";
+
dirname_part(reject_file, result_file_name, &reject_length);
if (access(reject_file, W_OK) == 0)
@@ -2043,11 +2251,13 @@ static int strip_surrounding(char* str, char c1, char c2)
static void strip_parentheses(struct st_command *command)
{
if (strip_surrounding(command->first_argument, '(', ')'))
- die("%.*s - argument list started with '%c' must be ended with '%c'",
- command->first_word_len, command->query, '(', ')');
+ die("%.*s - argument list started with '%c' must be ended with '%c'",
+ command->first_word_len, command->query, '(', ')');
}
+C_MODE_START
+
static uchar *get_var_key(const uchar* var, size_t *len,
my_bool __attribute__((unused)) t)
{
@@ -2058,6 +2268,34 @@ static uchar *get_var_key(const uchar* var, size_t *len,
}
+static void var_free(void *v)
+{
+ VAR *var= (VAR*) v;
+ my_free(var->str_val);
+ if (var->alloced)
+ my_free(var);
+}
+
+C_MODE_END
+
+void var_check_int(VAR *v)
+{
+ char *endptr;
+ char *str= v->str_val;
+
+ /* Initially assume not a number */
+ v->int_val= 0;
+ v->is_int= false;
+ v->int_dirty= false;
+ if (!str) return;
+
+ v->int_val = (int) strtol(str, &endptr, 10);
+ /* It is an int if strtol consumed something up to end/space/tab */
+ if (endptr > str && (!*endptr || *endptr == ' ' || *endptr == '\t'))
+ v->is_int= true;
+}
+
+
VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
int val_len)
{
@@ -2067,6 +2305,8 @@ VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
name_len = strlen(name);
if (!val_len && val)
val_len = strlen(val) ;
+ if (!val)
+ val_len= 0;
val_alloc_len = val_len + 16; /* room to grow */
if (!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
+ name_len+2, MYF(MY_WME))))
@@ -2087,27 +2327,17 @@ VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
die("Out of memory");
if (val)
- {
memcpy(tmp_var->str_val, val, val_len);
- tmp_var->str_val[val_len]= 0;
- }
+ tmp_var->str_val[val_len]= 0;
+
+ var_check_int(tmp_var);
tmp_var->name_len = name_len;
tmp_var->str_val_len = val_len;
tmp_var->alloced_len = val_alloc_len;
- tmp_var->int_val = (val) ? atoi(val) : 0;
- tmp_var->int_dirty = 0;
return tmp_var;
}
-void var_free(void *v)
-{
- my_free(((VAR*) v)->str_val, MYF(MY_WME));
- if (((VAR*)v)->alloced)
- my_free(v, MYF(MY_WME));
-}
-
-
VAR* var_from_env(const char *name, const char *def_val)
{
const char *tmp;
@@ -2149,8 +2379,8 @@ VAR* var_get(const char *var_name, const char **var_name_end, my_bool raw,
if (length >= MAX_VAR_NAME_LENGTH)
die("Too long variable name: %s", save_var_name);
- if (!(v = (VAR*) hash_search(&var_hash, (const uchar*) save_var_name,
- length)))
+ if (!(v = (VAR*) my_hash_search(&var_hash, (const uchar*) save_var_name,
+ length)))
{
char buff[MAX_VAR_NAME_LENGTH+1];
strmake(buff, save_var_name, length);
@@ -2164,7 +2394,7 @@ VAR* var_get(const char *var_name, const char **var_name_end, my_bool raw,
if (!raw && v->int_dirty)
{
sprintf(v->str_val, "%d", v->int_val);
- v->int_dirty = 0;
+ v->int_dirty= false;
v->str_val_len = strlen(v->str_val);
}
if (var_name_end)
@@ -2181,7 +2411,7 @@ err:
VAR *var_obtain(const char *name, int len)
{
VAR* v;
- if ((v = (VAR*)hash_search(&var_hash, (const uchar *) name, len)))
+ if ((v = (VAR*)my_hash_search(&var_hash, (const uchar *) name, len)))
return v;
v = var_init(0, name, len, "", 0);
my_hash_insert(&var_hash, (uchar*)v);
@@ -2226,7 +2456,7 @@ void var_set(const char *var_name, const char *var_name_end,
if (v->int_dirty)
{
sprintf(v->str_val, "%d", v->int_val);
- v->int_dirty= 0;
+ v->int_dirty=false;
v->str_val_len= strlen(v->str_val);
}
/* setenv() expects \0-terminated strings */
@@ -2259,6 +2489,51 @@ void var_set_int(const char* name, int value)
void var_set_errno(int sql_errno)
{
var_set_int("$mysql_errno", sql_errno);
+ var_set_string("$mysql_errname", get_errname_from_code(sql_errno));
+}
+
+/* Functions to handle --disable and --enable properties */
+
+void set_once_property(enum_prop prop, my_bool val)
+{
+ property &pr= prop_list[prop];
+ pr.set= 1;
+ pr.old= *pr.var;
+ *pr.var= val;
+ var_set_int(pr.env_name, (val != pr.reverse));
+ once_property= TRUE;
+}
+
+void set_property(st_command *command, enum_prop prop, my_bool val)
+{
+ char* p= command->first_argument;
+ if (p && !strcmp (p, "ONCE"))
+ {
+ command->last_argument= p + 4;
+ set_once_property(prop, val);
+ return;
+ }
+ property &pr= prop_list[prop];
+ *pr.var= val;
+ pr.set= 0;
+ var_set_int(pr.env_name, (val != pr.reverse));
+}
+
+void revert_properties()
+{
+ if (! once_property)
+ return;
+ for (int i= 0; i < (int) P_MAX; i++)
+ {
+ property &pr= prop_list[i];
+ if (pr.set)
+ {
+ *pr.var= pr.old;
+ pr.set= 0;
+ var_set_int(pr.env_name, (pr.old != pr.reverse));
+ }
+ }
+ once_property=FALSE;
}
@@ -2327,8 +2602,8 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
if (mysql_real_query(mysql, ds_query.str, ds_query.length))
{
- handle_error (curr_command, mysql_errno(mysql), mysql_error(mysql),
- mysql_sqlstate(mysql), &ds_res);
+ handle_error(curr_command, mysql_errno(mysql), mysql_error(mysql),
+ mysql_sqlstate(mysql), &ds_res);
/* If error was acceptable, return empty string */
dynstr_free(&ds_query);
eval_expr(var, "", 0);
@@ -2336,7 +2611,12 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
}
if (!(res= mysql_store_result(mysql)))
- die("Query '%s' didn't return a result set", ds_query.str);
+ {
+ report_or_die("Query '%s' didn't return a result set", ds_query.str);
+ dynstr_free(&ds_query);
+ eval_expr(var, "", 0);
+ return;
+ }
dynstr_free(&ds_query);
if ((row= mysql_fetch_row(res)) && row[0])
@@ -2356,13 +2636,29 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
if (row[i])
{
/* Add column to tab separated string */
- dynstr_append_mem(&result, row[i], lengths[i]);
+ char *val= row[i];
+ int len= lengths[i];
+
+ if (glob_replace_regex)
+ {
+ /* Regex replace */
+ if (!multi_reg_replace(glob_replace_regex, (char*)val))
+ {
+ val= glob_replace_regex->buf;
+ len= strlen(val);
+ }
+ }
+
+ if (glob_replace)
+ replace_strings_append(glob_replace, &result, val, len);
+ else
+ dynstr_append_mem(&result, val, len);
}
dynstr_append_mem(&result, "\t", 1);
}
end= result.str + result.length-1;
/* Evaluation should not recurse via backtick */
- eval_expr(var, result.str, (const char**) &end, false);
+ eval_expr(var, result.str, (const char**) &end, false, false);
dynstr_free(&result);
}
else
@@ -2373,6 +2669,59 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
}
+static void
+set_result_format_version(ulong new_version)
+{
+ switch (new_version){
+ case 1:
+ /* The first format */
+ break;
+ case 2:
+ /* New format that also writes comments and empty lines
+ from test file to result */
+ break;
+ default:
+ die("Version format %lu has not yet been implemented", new_version);
+ break;
+ }
+ opt_result_format_version= new_version;
+}
+
+
+/*
+ Set the result format version to use when generating
+ the .result file
+*/
+
+static void
+do_result_format_version(struct st_command *command)
+{
+ long version;
+ static DYNAMIC_STRING ds_version;
+ const struct command_arg result_format_args[] = {
+ {"version", ARG_STRING, TRUE, &ds_version, "Version to use"}
+ };
+
+ DBUG_ENTER("do_result_format_version");
+
+ check_command_args(command, command->first_argument,
+ result_format_args,
+ sizeof(result_format_args)/sizeof(struct command_arg),
+ ',');
+
+ /* Convert version number to int */
+ if (!str2int(ds_version.str, 10, (long) 0, (long) INT_MAX, &version))
+ die("Invalid version number: '%s'", ds_version.str);
+
+ set_result_format_version(version);
+
+ dynstr_append(&ds_res, "result_format: ");
+ dynstr_append_mem(&ds_res, ds_version.str, ds_version.length);
+ dynstr_append(&ds_res, "\n");
+ dynstr_free(&ds_version);
+}
+
+
/*
Set variable from the result of a field in a query
@@ -2442,16 +2791,23 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
/* Run the query */
if (mysql_real_query(mysql, ds_query.str, ds_query.length))
{
- handle_error (curr_command, mysql_errno(mysql), mysql_error(mysql),
- mysql_sqlstate(mysql), &ds_res);
+ handle_error(curr_command, mysql_errno(mysql), mysql_error(mysql),
+ mysql_sqlstate(mysql), &ds_res);
/* If error was acceptable, return empty string */
dynstr_free(&ds_query);
+ dynstr_free(&ds_col);
eval_expr(var, "", 0);
DBUG_VOID_RETURN;
}
if (!(res= mysql_store_result(mysql)))
- die("Query '%s' didn't return a result set", ds_query.str);
+ {
+ report_or_die("Query '%s' didn't return a result set", ds_query.str);
+ dynstr_free(&ds_query);
+ dynstr_free(&ds_col);
+ eval_expr(var, "", 0);
+ return;
+ }
{
/* Find column number from the given column name */
@@ -2471,8 +2827,11 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
if (col_no == -1)
{
mysql_free_result(res);
- die("Could not find column '%s' in the result of '%s'",
- ds_col.str, ds_query.str);
+ report_or_die("Could not find column '%s' in the result of '%s'",
+ ds_col.str, ds_query.str);
+ dynstr_free(&ds_query);
+ dynstr_free(&ds_col);
+ return;
}
DBUG_PRINT("info", ("Found column %d with name '%s'",
i, fields[i].name));
@@ -2501,7 +2860,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
break;
}
}
- eval_expr(var, value, 0, false);
+ eval_expr(var, value, 0, false, false);
}
dynstr_free(&ds_query);
mysql_free_result(res);
@@ -2513,6 +2872,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var)
void var_copy(VAR *dest, VAR *src)
{
dest->int_val= src->int_val;
+ dest->is_int= src->is_int;
dest->int_dirty= src->int_dirty;
/* Alloc/realloc data for str_val in dest */
@@ -2531,7 +2891,8 @@ void var_copy(VAR *dest, VAR *src)
}
-void eval_expr(VAR *v, const char *p, const char **p_end, bool do_eval)
+void eval_expr(VAR *v, const char *p, const char **p_end,
+ bool open_end, bool do_eval)
{
DBUG_ENTER("eval_expr");
@@ -2553,7 +2914,7 @@ void eval_expr(VAR *v, const char *p, const char **p_end, bool do_eval)
/* Make sure there was just a $variable and nothing else */
const char* end= *p_end + 1;
- if (end < expected_end)
+ if (end < expected_end && !open_end)
die("Found junk '%.*s' after $variable in expression",
(int)(expected_end - end - 1), end);
@@ -2602,48 +2963,134 @@ void eval_expr(VAR *v, const char *p, const char **p_end, bool do_eval)
v->str_val_len = new_val_len;
memcpy(v->str_val, p, new_val_len);
v->str_val[new_val_len] = 0;
- v->int_val=atoi(p);
- DBUG_PRINT("info", ("atoi on '%s', returns: %d", p, v->int_val));
- v->int_dirty=0;
+ var_check_int(v);
}
DBUG_VOID_RETURN;
}
-int open_file(const char *name)
+bool open_and_set_current(const char *name)
+{
+ FILE *opened= fopen(name, "rb");
+
+ if (!opened)
+ return false;
+
+ cur_file++;
+ cur_file->file= opened;
+ cur_file->file_name= my_strdup(name, MYF(MY_FAE));
+ cur_file->lineno=1;
+ return true;
+}
+
+
+void open_file(const char *name)
{
char buff[FN_REFLEN];
size_t length;
+ const char *curname= cur_file->file_name;
DBUG_ENTER("open_file");
DBUG_PRINT("enter", ("name: %s", name));
- /* Extract path from current file and try it as base first */
- if (dirname_part(buff, cur_file->file_name, &length))
+ if (cur_file == file_stack_end)
+ die("Source directives are nesting too deep");
+
+ if (test_if_hard_path(name))
{
- strxmov(buff, buff, name, NullS);
- if (access(buff, F_OK) == 0){
- DBUG_PRINT("info", ("The file exists"));
- name= buff;
- }
+ if (open_and_set_current(name))
+ DBUG_VOID_RETURN;
}
- if (!test_if_hard_path(name))
+ else
{
- strxmov(buff, opt_basedir, name, NullS);
- name=buff;
- }
- fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
+ /*
+ if overlay-dir is specified, and the file is located somewhere
+ under overlay-dir or under suite-dir, the search works as follows:
+
+ 0.let suffix be current file dirname relative to siute-dir or overlay-dir
+ 1.try in overlay-dir/suffix
+ 2.try in suite-dir/suffix
+ 3.try in overlay-dir
+ 4.try in suite-dir
+ 5.try in basedir
+
+ consider an example: 'rty' overlay of the 'qwe' suite,
+ file qwe/include/some.inc contains the line
+ --source thing.inc
+ we look for it in this order:
+ 0.suffix is "include/"
+ 1.try in rty/include/thing.inc
+ 2.try in qwe/include/thing.inc
+ 3.try in try/thing.inc | this is useful when t/a.test has
+ 4.try in qwe/thing.inc | source include/b.inc;
+ 5.try in mysql-test/include/thing.inc
+
+ otherwise the search is as follows
+ 1.try in current file dirname
+ 3.try in overlay-dir (if any)
+ 4.try in suite-dir
+ 5.try in basedir
+ */
- if (cur_file == file_stack_end)
- die("Source directives are nesting too deep");
- cur_file++;
- if (!(cur_file->file = fopen(buff, "rb")))
- {
- cur_file--;
- die("Could not open '%s' for reading, errno: %d", buff, errno);
+ bool in_overlay= opt_overlay_dir &&
+ !strncmp(curname, opt_overlay_dir, overlay_dir_len);
+ bool in_suiteir= opt_overlay_dir && !in_overlay &&
+ !strncmp(curname, opt_suite_dir, suite_dir_len);
+ if (in_overlay || in_suiteir)
+ {
+ size_t prefix_len = in_overlay ? overlay_dir_len : suite_dir_len;
+ char buf2[FN_REFLEN], *suffix= buf2 + prefix_len;
+ dirname_part(buf2, curname, &length);
+
+ /* 1. first we look in the overlay dir */
+ strxnmov(buff, sizeof(buff), opt_overlay_dir, suffix, name, NullS);
+
+ /*
+ Overlayed rty/include/thing.inc can contain the line
+ --source thing.inc
+ which would mean to include qwe/include/thing.inc.
+ But it looks like including "itself", so don't try to open the file,
+ if buff contains the same file name as curname.
+ */
+ if (strcmp(buff, curname) && open_and_set_current(buff))
+ DBUG_VOID_RETURN;
+
+ /* 2. if that failed, we look in the suite dir */
+ strxnmov(buff, sizeof(buff), opt_suite_dir, suffix, name, NullS);
+
+ /* buff can not be equal to curname, as a file can never include itself */
+ if (open_and_set_current(buff))
+ DBUG_VOID_RETURN;
+ }
+ else
+ {
+ /* 1. try in current file dirname */
+ dirname_part(buff, curname, &length);
+ strxnmov(buff, sizeof(buff), buff, name, NullS);
+ if (open_and_set_current(buff))
+ DBUG_VOID_RETURN;
+ }
+
+ /* 3. now, look in the overlay dir */
+ if (opt_overlay_dir)
+ {
+ strxmov(buff, opt_overlay_dir, name, NullS);
+ if (open_and_set_current(buff))
+ DBUG_VOID_RETURN;
+ }
+
+ /* 4. if that failed - look in the suite dir */
+ strxmov(buff, opt_suite_dir, name, NullS);
+ if (open_and_set_current(buff))
+ DBUG_VOID_RETURN;
+
+ /* 5. the last resort - look in the base dir */
+ strxnmov(buff, sizeof(buff), opt_basedir, name, NullS);
+ if (open_and_set_current(buff))
+ DBUG_VOID_RETURN;
}
- cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
- cur_file->lineno=1;
- DBUG_RETURN(0);
+
+ die("Could not open '%s' for reading, errno: %d", name, errno);
+ DBUG_VOID_RETURN;
}
@@ -2824,7 +3271,10 @@ void do_exec(struct st_command *command)
while (*cmd && my_isspace(charset_info, *cmd))
cmd++;
if (!*cmd)
- die("Missing argument in exec");
+ {
+ report_or_die("Missing argument in exec");
+ return;
+ }
command->last_argument= command->end;
init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
@@ -2856,10 +3306,12 @@ void do_exec(struct st_command *command)
DBUG_PRINT("info", ("Executing '%s' as '%s'",
command->first_argument, ds_cmd.str));
- if (!(res_file= my_popen(&ds_cmd, "r")) && command->abort_on_error)
+ if (!(res_file= my_popen(&ds_cmd, "r")))
{
dynstr_free(&ds_cmd);
- die("popen(\"%s\", \"r\") failed", command->first_argument);
+ if (command->abort_on_error)
+ report_or_die("popen(\"%s\", \"r\") failed", command->first_argument);
+ return;
}
ds_result= &ds_res;
@@ -2896,11 +3348,12 @@ void do_exec(struct st_command *command)
if (command->abort_on_error)
{
- log_msg("exec of '%s' failed, error: %d, status: %d, errno: %d",
- ds_cmd.str, error, status, errno);
+ report_or_die("exec of '%s' failed, error: %d, status: %d, errno: %d\n"
+ "Output from before failure:\n%s\n",
+ ds_cmd.str, error, status, errno,
+ ds_res.str);
dynstr_free(&ds_cmd);
- die("command \"%s\" failed\n\nOutput from before failure:\n%s\n",
- command->first_argument, ds_res.str);
+ return;
}
DBUG_PRINT("info",
@@ -2915,8 +3368,8 @@ void do_exec(struct st_command *command)
{
dynstr_free(&ds_cmd);
if (command->expected_errors.count > 0)
- die("command \"%s\" failed with wrong error: %d",
- command->first_argument, status);
+ report_or_die("command \"%s\" failed with wrong error: %d",
+ command->first_argument, status);
}
}
else if (command->expected_errors.err[0].type == ERR_ERRNO &&
@@ -2926,8 +3379,10 @@ void do_exec(struct st_command *command)
log_msg("exec of '%s failed, error: %d, errno: %d",
ds_cmd.str, error, errno);
dynstr_free(&ds_cmd);
- die("command \"%s\" succeeded - should have failed with errno %d...",
- command->first_argument, command->expected_errors.err[0].code.errnum);
+ report_or_die("command \"%s\" succeeded - should have failed with "
+ "errno %d...",
+ command->first_argument,
+ command->expected_errors.err[0].code.errnum);
}
dynstr_free(&ds_cmd);
@@ -2961,11 +3416,14 @@ int do_modify_var(struct st_command *command,
const char *p= command->first_argument;
VAR* v;
if (!*p)
- die("Missing argument to %.*s", command->first_word_len, command->query);
+ die("Missing argument to %.*s", command->first_word_len,
+ command->query);
if (*p != '$')
die("The argument to %.*s must be a variable (start with $)",
command->first_word_len, command->query);
v= var_get(p, &p, 1, 0);
+ if (! v->is_int)
+ die("Cannot perform inc/dec on a non-numeric value");
switch (op) {
case DO_DEC:
v->int_val--;
@@ -2977,7 +3435,7 @@ int do_modify_var(struct st_command *command,
die("Invalid operator to do_modify_var");
break;
}
- v->int_dirty= 1;
+ v->int_dirty= true;
command->last_argument= (char*)++p;
return 0;
}
@@ -3025,7 +3483,10 @@ void do_system(struct st_command *command)
DBUG_ENTER("do_system");
if (strlen(command->first_argument) == 0)
- die("Missing arguments to system, nothing to do!");
+ {
+ report_or_die("Missing arguments to system, nothing to do!");
+ return;
+ }
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
@@ -3046,12 +3507,14 @@ void do_system(struct st_command *command)
if (my_system(&ds_cmd))
{
if (command->abort_on_error)
- die("system command '%s' failed", command->first_argument);
-
- /* If ! abort_on_error, log message and continue */
- dynstr_append(&ds_res, "system command '");
- replace_dynstr_append(&ds_res, command->first_argument);
- dynstr_append(&ds_res, "' failed\n");
+ report_or_die("system command '%s' failed", command->first_argument);
+ else
+ {
+ /* If ! abort_on_error, log message and continue */
+ dynstr_append(&ds_res, "system command '");
+ replace_dynstr_append(&ds_res, command->first_argument);
+ dynstr_append(&ds_res, "' failed\n");
+ }
}
command->last_argument= command->end;
@@ -3237,8 +3700,9 @@ void do_copy_file(struct st_command *command)
' ');
DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
+ /* MY_HOLD_ORIGINAL_MODES prevents attempts to chown the file */
error= (my_copy(ds_from_file.str, ds_to_file.str,
- MYF(MY_DONT_OVERWRITE_FILE | MY_WME)) != 0);
+ MYF(MY_DONT_OVERWRITE_FILE | MY_WME | MY_HOLD_ORIGINAL_MODES)) != 0);
handle_command_error(command, error, my_errno);
dynstr_free(&ds_from_file);
dynstr_free(&ds_to_file);
@@ -3295,8 +3759,8 @@ void do_move_file(struct st_command *command)
void do_chmod_file(struct st_command *command)
{
- int error;
long mode= 0;
+ int err_code;
static DYNAMIC_STRING ds_mode;
static DYNAMIC_STRING ds_file;
const struct command_arg chmod_file_args[] = {
@@ -3316,10 +3780,10 @@ void do_chmod_file(struct st_command *command)
die("You must write a 4 digit octal number for mode");
DBUG_PRINT("info", ("chmod %o %s", (uint)mode, ds_file.str));
- error= 0;
- if (chmod(ds_file.str, mode))
- error= 1;
- handle_command_error(command, error, errno);
+ err_code= chmod(ds_file.str, mode);
+ if (err_code < 0)
+ err_code= 1;
+ handle_command_error(command, err_code, errno);
dynstr_free(&ds_mode);
dynstr_free(&ds_file);
DBUG_VOID_RETURN;
@@ -3597,12 +4061,12 @@ void read_until_delimiter(DYNAMIC_STRING *ds,
No characters except \n are allowed on
the same line as the command
*/
- die("Trailing characters found after command");
+ report_or_die("Trailing characters found after command");
}
if (feof(cur_file->file))
- die("End of file encountered before '%s' delimiter was found",
- ds_delimiter->str);
+ report_or_die("End of file encountered before '%s' delimiter was found",
+ ds_delimiter->str);
if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
{
@@ -4006,8 +4470,13 @@ void do_perl(struct st_command *command)
/* Format the "perl <filename>" command */
my_snprintf(buf, sizeof(buf), "perl %s", temp_file_path);
- if (!(res_file= popen(buf, "r")) && command->abort_on_error)
- die("popen(\"%s\", \"r\") failed", buf);
+ if (!(res_file= popen(buf, "r")))
+ {
+ if (command->abort_on_error)
+ die("popen(\"%s\", \"r\") failed", buf);
+ dynstr_free(&ds_delimiter);
+ return;
+ }
while (fgets(buf, sizeof(buf), res_file))
{
@@ -4038,7 +4507,7 @@ void do_perl(struct st_command *command)
abort_not_supported_test("perl not found in path");
#endif
else
- handle_command_error(command, WEXITSTATUS(error), my_errno);
+ handle_command_error(command, exstat, my_errno);
}
dynstr_free(&ds_delimiter);
DBUG_VOID_RETURN;
@@ -4162,14 +4631,14 @@ void do_sync_with_master2(struct st_command *command, long offset)
information is not initialized, the arguments are
incorrect, or an error has occured
*/
- die("%.*s failed: '%s' returned NULL "\
+ die("%.*s failed: '%s' returned NULL " \
"indicating slave SQL thread failure",
command->first_word_len, command->query, query_buf);
}
if (result == -1)
- die("%.*s failed: '%s' returned -1 "\
+ die("%.*s failed: '%s' returned -1 " \
"indicating timeout after %d seconds",
command->first_word_len, command->query, query_buf, timeout);
else
@@ -4209,12 +4678,8 @@ int do_save_master_pos()
MYSQL_ROW row;
MYSQL *mysql = cur_con->mysql;
const char *query;
- int rpl_parse;
DBUG_ENTER("do_save_master_pos");
- rpl_parse = mysql_rpl_parse_enabled(mysql);
- mysql_disable_rpl_parse(mysql);
-
#ifdef HAVE_NDB_BINLOG
/*
Wait for ndb binlog to be up-to-date with all changes
@@ -4255,7 +4720,7 @@ int do_save_master_pos()
const char latest_applied_binlog_epoch_str[]=
"latest_applied_binlog_epoch=";
if (count)
- sleep(1);
+ my_sleep(100*1000); /* 100ms */
if (mysql_query(mysql, query= "show engine ndb status"))
die("failed in '%s': %d %s", query,
mysql_errno(mysql), mysql_error(mysql));
@@ -4344,7 +4809,7 @@ int do_save_master_pos()
count++;
if (latest_handled_binlog_epoch >= start_epoch)
do_continue= 0;
- else if (count > 30)
+ else if (count > 300) /* 30s */
{
break;
}
@@ -4364,10 +4829,6 @@ int do_save_master_pos()
strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1);
master_pos.pos = strtoul(row[1], (char**) 0, 10);
mysql_free_result(res);
-
- if (rpl_parse)
- mysql_enable_rpl_parse(mysql);
-
DBUG_RETURN(0);
}
@@ -4426,33 +4887,11 @@ void do_let(struct st_command *command)
var_set(var_name, var_name_end, let_rhs_expr.str,
(let_rhs_expr.str + let_rhs_expr.length));
dynstr_free(&let_rhs_expr);
+ revert_properties();
DBUG_VOID_RETURN;
}
-int do_rpl_probe(struct st_command *command __attribute__((unused)))
-{
- DBUG_ENTER("do_rpl_probe");
- if (mysql_rpl_probe(cur_con->mysql))
- die("Failed in mysql_rpl_probe(): '%s'", mysql_error(cur_con->mysql));
- DBUG_RETURN(0);
-}
-
-
-int do_enable_rpl_parse(struct st_command *command __attribute__((unused)))
-{
- mysql_enable_rpl_parse(cur_con->mysql);
- return 0;
-}
-
-
-int do_disable_rpl_parse(struct st_command *command __attribute__((unused)))
-{
- mysql_disable_rpl_parse(cur_con->mysql);
- return 0;
-}
-
-
/*
Sleep the number of specified seconds
@@ -4494,7 +4933,8 @@ int do_sleep(struct st_command *command, my_bool real_sleep)
while (my_isspace(charset_info, *p))
p++;
if (!*p)
- die("Missing argument to %.*s", command->first_word_len, command->query);
+ die("Missing argument to %.*s", command->first_word_len,
+ command->query);
sleep_start= p;
/* Check that arg starts with a digit, not handled by my_strtod */
if (!my_isdigit(charset_info, *sleep_start))
@@ -4566,16 +5006,21 @@ int query_get_string(MYSQL* mysql, const char* query,
MYSQL_ROW row;
if (mysql_query(mysql, query))
- die("'%s' failed: %d %s", query,
- mysql_errno(mysql), mysql_error(mysql));
+ {
+ report_or_die("'%s' failed: %d %s", query,
+ mysql_errno(mysql), mysql_error(mysql));
+ return 1;
+ }
if ((res= mysql_store_result(mysql)) == NULL)
- die("Failed to store result: %d %s",
- mysql_errno(mysql), mysql_error(mysql));
+ {
+ report_or_die("Failed to store result: %d %s",
+ mysql_errno(mysql), mysql_error(mysql));
+ return 1;
+ }
if ((row= mysql_fetch_row(res)) == NULL)
{
mysql_free_result(res);
- ds= 0;
return 1;
}
init_dynamic_string(ds, (row[column] ? row[column] : "NULL"), ~0, 32);
@@ -4695,18 +5140,19 @@ void do_shutdown_server(struct st_command *command)
}
-#if MYSQL_VERSION_ID >= 50000
-/* List of error names to error codes, available from 5.0 */
+/* List of error names to error codes */
typedef struct
{
const char *name;
uint code;
+ const char *text;
} st_error;
static st_error global_error_names[] =
{
+ { "<No error>", -1U, "" },
#include <mysqld_ername.h>
- { 0, 0 }
+ { 0, 0, 0 }
};
uint get_errcode_from_name(char *error_name, char *error_end)
@@ -4735,28 +5181,58 @@ uint get_errcode_from_name(char *error_name, char *error_end)
die("Unknown SQL error name '%s'", error_name);
DBUG_RETURN(0);
}
-#else
-uint get_errcode_from_name(char *error_name __attribute__((unused)),
- char *error_end __attribute__((unused)))
+
+const char *get_errname_from_code (uint error_code)
{
- abort_not_in_this_version();
- return 0; /* Never reached */
-}
-#endif
+ st_error *e= global_error_names;
+ DBUG_ENTER("get_errname_from_code");
+ DBUG_PRINT("enter", ("error_code: %d", error_code));
+ if (! error_code)
+ {
+ DBUG_RETURN("");
+ }
+ for (; e->name; e++)
+ {
+ if (e->code == error_code)
+ {
+ DBUG_RETURN(e->name);
+ }
+ }
+ /* Apparently, errors without known names may occur */
+ DBUG_RETURN("<Unknown>");
+}
void do_get_errcodes(struct st_command *command)
{
struct st_match_err *to= saved_expected_errors.err;
- char *p= command->first_argument;
- uint count= 0;
-
DBUG_ENTER("do_get_errcodes");
- if (!*p)
+ if (!*command->first_argument)
die("Missing argument(s) to 'error'");
+ /* TODO: Potentially, there is a possibility of variables
+ being expanded twice, e.g.
+
+ let $errcodes = 1,\$a;
+ let $a = 1051;
+ error $errcodes;
+ DROP TABLE unknown_table;
+ ...
+ Got one of the listed errors
+
+ But since it requires manual escaping, it does not seem
+ particularly dangerous or error-prone.
+ */
+ DYNAMIC_STRING ds;
+ init_dynamic_string(&ds, 0, command->query_len + 64, 256);
+ do_eval(&ds, command->first_argument, command->end, !is_windows);
+ char *p= ds.str;
+
+ uint count= 0;
+ char *next;
+
do
{
char *end;
@@ -4770,6 +5246,17 @@ void do_get_errcodes(struct st_command *command)
while (*end && *end != ',' && *end != ' ')
end++;
+ next=end;
+
+ /* code to handle variables passed to mysqltest */
+ if( *p == '$')
+ {
+ const char* fin;
+ VAR *var = var_get(p,&fin,0,0);
+ p=var->str_val;
+ end=p+var->str_val_len;
+ }
+
if (*p == 'S')
{
char *to_ptr= to->code.sqlstate;
@@ -4822,7 +5309,7 @@ void do_get_errcodes(struct st_command *command)
while (*p && p != end)
{
if (!my_isdigit(charset_info, *p))
- die("Invalid argument to error: '%s' - "\
+ die("Invalid argument to error: '%s' - " \
"the errno may only consist of digits[0-9]",
command->first_argument);
p++;
@@ -4844,7 +5331,7 @@ void do_get_errcodes(struct st_command *command)
die("Too many errorcodes specified");
/* Set pointer to the end of the last error code */
- p= end;
+ p= next;
/* Find next ',' */
while (*p && *p != ',')
@@ -4855,11 +5342,15 @@ void do_get_errcodes(struct st_command *command)
} while (*p);
- command->last_argument= p;
+ command->last_argument= command->first_argument;
+ while (*command->last_argument)
+ command->last_argument++;
+
to->type= ERR_EMPTY; /* End of data */
DBUG_PRINT("info", ("Expected errors: %d", count));
saved_expected_errors.count= count;
+ dynstr_free(&ds);
DBUG_VOID_RETURN;
}
@@ -5052,7 +5543,7 @@ void do_close_connection(struct st_command *command)
we need to check if the query's thread was finished and probably wait
(embedded-server specific)
*/
- wait_query_thread_end(con);
+ emb_close_connection(con);
#endif /*EMBEDDED_LIBRARY*/
if (con->stmt)
mysql_stmt_close(con->stmt);
@@ -5060,14 +5551,13 @@ void do_close_connection(struct st_command *command)
mysql_close(con->mysql);
con->mysql= 0;
- free_embedded_data(con);
if (con->util_mysql)
mysql_close(con->util_mysql);
con->util_mysql= 0;
con->pending= FALSE;
- my_free(con->name, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(con->name);
/*
When the connection is closed set name to "-closed_connection-"
@@ -5278,6 +5768,7 @@ do_handle_error:
var_set_errno(0);
handle_no_error(command);
+ revert_properties();
return 1; /* Connected */
}
@@ -5326,6 +5817,7 @@ void do_connect(struct st_command *command)
static DYNAMIC_STRING ds_port;
static DYNAMIC_STRING ds_sock;
static DYNAMIC_STRING ds_options;
+ static DYNAMIC_STRING ds_default_auth;
#ifdef HAVE_SMEM
static DYNAMIC_STRING ds_shm;
#endif
@@ -5337,7 +5829,8 @@ void do_connect(struct st_command *command)
{ "database", ARG_STRING, FALSE, &ds_database, "Database to select after connect" },
{ "port", ARG_STRING, FALSE, &ds_port, "Port to connect to" },
{ "socket", ARG_STRING, FALSE, &ds_sock, "Socket to connect with" },
- { "options", ARG_STRING, FALSE, &ds_options, "Options to use while connecting" }
+ { "options", ARG_STRING, FALSE, &ds_options, "Options to use while connecting" },
+ { "default_auth", ARG_STRING, FALSE, &ds_default_auth, "Default authentication to use" }
};
DBUG_ENTER("do_connect");
@@ -5422,16 +5915,20 @@ void do_connect(struct st_command *command)
if (!(con_slot= find_connection_by_name("-closed_connection-")))
die("Connection limit exhausted, you can have max %d connections",
opt_max_connections);
- my_free(con_slot->name, MYF(0));
+ my_free(con_slot->name);
con_slot->name= 0;
}
-#ifdef EMBEDDED_LIBRARY
- con_slot->query_done= 1;
- con_slot->has_thread= FALSE;
-#endif
+ init_connection_thd(con_slot);
+
if (!(con_slot->mysql= mysql_init(0)))
die("Failed on mysql_init()");
+
+ if (opt_connect_timeout)
+ mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
+ (void *) &opt_connect_timeout);
+
+ mysql_options(con_slot->mysql, MYSQL_OPT_NONBLOCK, 0);
if (opt_compress || con_compress)
mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
mysql_options(con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
@@ -5440,18 +5937,14 @@ void do_connect(struct st_command *command)
if (opt_charsets_dir)
mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_DIR,
opt_charsets_dir);
- if (opt_connect_timeout >= 0)
- mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
- &opt_connect_timeout);
-
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
if (opt_use_ssl)
con_ssl= 1;
#endif
if (con_ssl)
{
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
mysql_ssl_set(con_slot->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
#if MYSQL_VERSION_ID >= 50000
@@ -5493,6 +5986,12 @@ void do_connect(struct st_command *command)
if (ds_database.length == 0)
dynstr_set(&ds_database, opt_db);
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(con_slot->mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (ds_default_auth.length)
+ mysql_options(con_slot->mysql, MYSQL_DEFAULT_AUTH, ds_default_auth.str);
+
/* Special database to allow one to connect without a database name */
if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
dynstr_set(&ds_database, "");
@@ -5521,6 +6020,7 @@ void do_connect(struct st_command *command)
dynstr_free(&ds_port);
dynstr_free(&ds_sock);
dynstr_free(&ds_options);
+ dynstr_free(&ds_default_auth);
#ifdef HAVE_SMEM
dynstr_free(&ds_shm);
#endif
@@ -5560,6 +6060,40 @@ int do_done(struct st_command *command)
return 0;
}
+/* Operands available in if or while conditions */
+
+enum block_op {
+ EQ_OP,
+ NE_OP,
+ GT_OP,
+ GE_OP,
+ LT_OP,
+ LE_OP,
+ ILLEG_OP
+};
+
+
+enum block_op find_operand(const char *start)
+{
+ char first= *start;
+ char next= *(start+1);
+
+ if (first == '=' && next == '=')
+ return EQ_OP;
+ if (first == '!' && next == '=')
+ return NE_OP;
+ if (first == '>' && next == '=')
+ return GE_OP;
+ if (first == '>')
+ return GT_OP;
+ if (first == '<' && next == '=')
+ return LE_OP;
+ if (first == '<')
+ return LT_OP;
+
+ return ILLEG_OP;
+}
+
/*
Process start of a "if" or "while" statement
@@ -5585,6 +6119,13 @@ int do_done(struct st_command *command)
A '!' can be used before the <expr> to indicate it should
be executed if it evaluates to zero.
+ <expr> can also be a simple comparison condition:
+
+ <variable> <op> <expr>
+
+ The left hand side must be a variable, the right hand side can be a
+ variable, number, string or `query`. Operands are ==, !=, <, <=, >, >=.
+ == and != can be used for strings, all can be used for numerical values.
*/
void do_block(enum block_cmd cmd, struct st_command* command)
@@ -5620,6 +6161,9 @@ void do_block(enum block_cmd cmd, struct st_command* command)
if (!expr_start++)
die("missing '(' in %s", cmd_name);
+ while (my_isspace(charset_info, *expr_start))
+ expr_start++;
+
/* Check for !<expr> */
if (*expr_start == '!')
{
@@ -5640,14 +6184,110 @@ void do_block(enum block_cmd cmd, struct st_command* command)
die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
var_init(&v,0,0,0,0);
- eval_expr(&v, expr_start, &expr_end);
+ /* If expression starts with a variable, it may be a compare condition */
+
+ if (*expr_start == '$')
+ {
+ const char *curr_ptr= expr_end;
+ eval_expr(&v, expr_start, &curr_ptr, true);
+ while (my_isspace(charset_info, *++curr_ptr))
+ {}
+ /* If there was nothing past the variable, skip condition part */
+ if (curr_ptr == expr_end)
+ goto NO_COMPARE;
+
+ enum block_op operand= find_operand(curr_ptr);
+ if (operand == ILLEG_OP)
+ die("Found junk '%.*s' after $variable in condition",
+ (int)(expr_end - curr_ptr), curr_ptr);
+
+ /* We could silently allow this, but may be confusing */
+ if (not_expr)
+ die("Negation and comparison should not be combined, please rewrite");
+
+ /* Skip the 1 or 2 chars of the operand, then white space */
+ if (operand == LT_OP || operand == GT_OP)
+ {
+ curr_ptr++;
+ }
+ else
+ {
+ curr_ptr+= 2;
+ }
+ while (my_isspace(charset_info, *curr_ptr))
+ curr_ptr++;
+ if (curr_ptr == expr_end)
+ die("Missing right operand in comparison");
+
+ /* Strip off trailing white space */
+ while (my_isspace(charset_info, expr_end[-1]))
+ expr_end--;
+ /* strip off ' or " around the string */
+ if (*curr_ptr == '\'' || *curr_ptr == '"')
+ {
+ if (expr_end[-1] != *curr_ptr)
+ die("Unterminated string value");
+ curr_ptr++;
+ expr_end--;
+ }
+ VAR v2;
+ var_init(&v2,0,0,0,0);
+ eval_expr(&v2, curr_ptr, &expr_end);
+
+ if ((operand!=EQ_OP && operand!=NE_OP) && ! (v.is_int && v2.is_int))
+ die("Only == and != are supported for string values");
+
+ /* Now we overwrite the first variable with 0 or 1 (for false or true) */
+
+ switch (operand)
+ {
+ case EQ_OP:
+ if (v.is_int)
+ v.int_val= (v2.is_int && v2.int_val == v.int_val);
+ else
+ v.int_val= !strcmp (v.str_val, v2.str_val);
+ break;
+
+ case NE_OP:
+ if (v.is_int)
+ v.int_val= ! (v2.is_int && v2.int_val == v.int_val);
+ else
+ v.int_val= (strcmp (v.str_val, v2.str_val) != 0);
+ break;
+
+ case LT_OP:
+ v.int_val= (v.int_val < v2.int_val);
+ break;
+ case LE_OP:
+ v.int_val= (v.int_val <= v2.int_val);
+ break;
+ case GT_OP:
+ v.int_val= (v.int_val > v2.int_val);
+ break;
+ case GE_OP:
+ v.int_val= (v.int_val >= v2.int_val);
+ break;
+ case ILLEG_OP:
+ die("Impossible operator, this cannot happen");
+ }
+
+ v.is_int= TRUE;
+ var_free(&v2);
+ } else
+ {
+ if (*expr_start != '`' && ! my_isdigit(charset_info, *expr_start))
+ die("Expression in if/while must beging with $, ` or a number");
+ eval_expr(&v, expr_start, &expr_end);
+ }
+
+ NO_COMPARE:
/* Define inner block */
cur_block++;
cur_block->cmd= cmd;
- if (v.int_val)
+ if (v.is_int)
{
- cur_block->ok= TRUE;
+ cur_block->ok= (v.int_val != 0);
} else
/* Any non-empty string which does not begin with 0 is also TRUE */
{
@@ -5755,7 +6395,7 @@ my_bool end_of_query(int c)
int read_line(char *buf, int size)
{
- char c, UNINIT_VAR(last_quote);
+ char c, UNINIT_VAR(last_quote), last_char= 0;
char *p= buf, *buf_end= buf + size - 1;
int skip_char= 0;
my_bool have_slash= FALSE;
@@ -5778,7 +6418,7 @@ int read_line(char *buf, int size)
fclose(cur_file->file);
cur_file->file= 0;
}
- my_free((uchar*) cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(cur_file->file_name);
cur_file->file_name= 0;
if (cur_file == file_stack)
{
@@ -5859,14 +6499,24 @@ int read_line(char *buf, int size)
}
else if (my_isspace(charset_info, c))
{
- /* Skip all space at begining of line */
if (c == '\n')
{
+ if (last_char == '\n')
+ {
+ /* Two new lines in a row, return empty line */
+ DBUG_PRINT("info", ("Found two new lines in a row"));
+ *p++= c;
+ *p= 0;
+ DBUG_RETURN(0);
+ }
+
/* Query hasn't started yet */
start_lineno= cur_file->lineno;
DBUG_PRINT("info", ("Query hasn't started yet, start_lineno: %d",
start_lineno));
}
+
+ /* Skip all space at begining of line */
skip_char= 1;
}
else if (end_of_query(c))
@@ -5907,6 +6557,8 @@ int read_line(char *buf, int size)
}
+ last_char= c;
+
if (!skip_char)
{
/* Could be a multibyte character */
@@ -5942,7 +6594,7 @@ int read_line(char *buf, int size)
*p++= c;
}
}
- die("The input buffer is too small for this query.x\n" \
+ die("The input buffer is too small for this query.x\n" \
"check your query or increase MAX_QUERY and recompile");
DBUG_RETURN(0);
}
@@ -6116,9 +6768,10 @@ int read_command(struct st_command** command_ptr)
DBUG_RETURN(1);
}
- convert_to_format_v1(read_command_buf);
+ if (opt_result_format_version == 1)
+ convert_to_format_v1(read_command_buf);
- DBUG_PRINT("info", ("query: %s", read_command_buf));
+ DBUG_PRINT("info", ("query: '%s'", read_command_buf));
if (*p == '#')
{
command->type= Q_COMMENT;
@@ -6128,6 +6781,10 @@ int read_command(struct st_command** command_ptr)
command->type= Q_COMMENT_WITH_COMMAND;
p+= 2; /* Skip past -- */
}
+ else if (*p == '\n')
+ {
+ command->type= Q_EMPTY_LINE;
+ }
/* Skip leading spaces */
while (*p && my_isspace(charset_info, *p))
@@ -6164,13 +6821,19 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0, 0},
{"basedir", 'b', "Basedir for tests.", &opt_basedir,
&opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"character-sets-dir", OPT_CHARSETS_DIR,
+ {"character-sets-dir", 0,
"Directory for character set files.", &opt_charsets_dir,
&opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"compress", 'C', "Use the compressed server/client protocol.",
&opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
- {"cursor-protocol", OPT_CURSOR_PROTOCOL, "Use cursors for prepared statements.",
+ {"continue-on-error", 0,
+ "Continue test even if we got an error. "
+ "This is mostly useful when testing a storage engine to see what from a test file it can execute, "
+ "or to find all syntax errors in a newly created big test file",
+ &opt_continue_on_error, &opt_continue_on_error, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"cursor-protocol", 0, "Use cursors for prepared statements.",
&cursor_protocol, &cursor_protocol, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"database", 'D', "Database to use.", &opt_db, &opt_db, 0,
@@ -6182,32 +6845,27 @@ static struct my_option my_long_options[] =
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
+ {"debug-check", 0, "Check memory and open file usage at exit.",
&debug_check_flag, &debug_check_flag, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
+ {"debug-info", 0, "Print some debug info at exit.",
&debug_info_flag, &debug_info_flag,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"global-subst", OPT_GLOBAL_SUBST, "argument should be 'X,Y' ;"
- " substitute string X with another Y accross the whole test's current"
- " result before comparing with expected result file",
- &global_subst, &global_subst, 0,
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host.", &opt_host, &opt_host, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"include", 'i', "Include SQL before each test case.", &opt_include,
- &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"prologue", 0, "Include SQL before each test case.", &opt_prologue,
+ &opt_prologue, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"logdir", OPT_LOG_DIR, "Directory for log files", &opt_logdir,
&opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"mark-progress", OPT_MARK_PROGRESS,
+ {"mark-progress", 0,
"Write line number and elapsed time to <testname>.progress.",
&opt_mark_progress, &opt_mark_progress, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
+ {"max-connect-retries", 0,
"Maximum number of attempts to connect to server.",
&opt_max_connect_retries, &opt_max_connect_retries, 0,
GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
- {"max-connections", OPT_MAX_CONNECTIONS,
+ {"max-connections", 0,
"Max number of open connections to server",
&opt_max_connections, &opt_max_connections, 0,
GET_INT, REQUIRED_ARG, DEFAULT_MAX_CONN, 8, 5120, 0, 0, 0},
@@ -6222,10 +6880,14 @@ static struct my_option my_long_options[] =
#endif
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
&opt_port, &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"ps-protocol", OPT_PS_PROTOCOL,
+ {"ps-protocol", 0,
"Use prepared-statement protocol for communication.",
&ps_protocol, &ps_protocol, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"non-blocking-api", 0,
+ "Use the non-blocking client API for communication.",
+ &non_blocking_api_enabled, &non_blocking_api_enabled, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"quiet", 's', "Suppress all normal output.", &silent,
&silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"record", 'r', "Record output of test_file into result file.",
@@ -6233,40 +6895,37 @@ static struct my_option my_long_options[] =
{"result-file", 'R', "Read/store result from/in this file.",
&result_file_name, &result_file_name, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"result-format-version", OPT_RESULT_FORMAT_VERSION,
+ "Version of the result file format to use",
+ &opt_result_format_version,
+ &opt_result_format_version, 0,
+ GET_INT, REQUIRED_ARG, 1, 1, 2, 0, 0, 0},
{"server-arg", 'A', "Send option value to embedded server as a parameter.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-file", 'F', "Read embedded server arguments from file.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-#ifdef HAVE_SMEM
- {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
+ {"shared-memory-base-name", 0,
"Base name of shared memory.", &shared_memory_base_name,
&shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
0, 0, 0},
-#endif
{"silent", 's', "Suppress all normal output. Synonym for --quiet.",
&silent, &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"skip-safemalloc", OPT_SKIP_SAFEMALLOC,
- "Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG,
- 0, 0, 0, 0, 0, 0},
{"sleep", 'T', "Always sleep this many seconds on sleep commands.",
&opt_sleep, &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0,
0, 0, 0},
{"socket", 'S', "The socket file to use for connection.",
&unix_sock, &unix_sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
0, 0, 0},
- {"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select.",
+ {"sp-protocol", 0, "Use stored procedures for select.",
&sp_protocol, &sp_protocol, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#include "sslopt-longopts.h"
- {"tail-lines", OPT_TAIL_LINES,
+ {"tail-lines", 0,
"Number of lines of the result to include in a failure report.",
&opt_tail_lines, &opt_tail_lines, 0,
GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
{"test-file", 'x', "Read test from/in this file (default stdin).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"connect-timeout", OPT_MY_CONNECT_TIMEOUT, "Client connection timeout",
- (uchar**) &opt_connect_timeout, (uchar**) &opt_connect_timeout, 0,
- GET_INT, REQUIRED_ARG, -1, -1, 0, 0, 0, 0},
{"timer-file", 'm', "File where the timing in microseconds is stored.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"tmpdir", 't', "Temporary directory where sockets are put.",
@@ -6277,22 +6936,24 @@ static struct my_option my_long_options[] =
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"view-protocol", OPT_VIEW_PROTOCOL, "Use views for select.",
+ {"view-protocol", 0, "Use views for select.",
&view_protocol, &view_protocol, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
- (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"default_auth", OPT_PLUGIN_DIR,
- "Default authentication client-side plugin to use.",
- (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+ {"connect_timeout", 0,
+ "Number of seconds before connection timeout.",
+ &opt_connect_timeout, &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG,
+ 120, 0, 3600 * 12, 0, 0, 0},
+ {"plugin_dir", 0, "Directory for client-side plugins.",
+ &opt_plugin_dir, &opt_plugin_dir, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"overlay-dir", 0, "Overlay directory.", &opt_overlay_dir,
+ &opt_overlay_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"suite-dir", 0, "Suite directory.", &opt_suite_dir,
+ &opt_suite_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-#include <help_start.h>
-
void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
@@ -6310,8 +6971,6 @@ void usage()
my_print_variables(my_long_options);
}
-#include <help_end.h>
-
/*
Read arguments for embedded server and put them into
@@ -6360,8 +7019,7 @@ void read_embedded_server_arguments(const char *name)
static my_bool
-get_one_option(int optid, const struct my_option *opt,
- char *argument)
+get_one_option(int optid, const struct my_option *opt, char *argument)
{
switch(optid) {
case '#':
@@ -6409,7 +7067,7 @@ get_one_option(int optid, const struct my_option *opt,
argument= (char*) ""; // Don't require password
if (argument)
{
- my_free(opt_pass, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(opt_pass);
opt_pass= my_strdup(argument, MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */
tty_password= 0;
@@ -6442,10 +7100,8 @@ get_one_option(int optid, const struct my_option *opt,
case 'F':
read_embedded_server_arguments(argument);
break;
- case OPT_SKIP_SAFEMALLOC:
-#ifdef SAFEMALLOC
- sf_malloc_quick=1;
-#endif
+ case OPT_RESULT_FORMAT_VERSION:
+ set_result_format_version(opt_result_format_version);
break;
case 'V':
print_version();
@@ -6466,7 +7122,9 @@ get_one_option(int optid, const struct my_option *opt,
int parse_args(int argc, char **argv)
{
- load_defaults("my",load_default_groups,&argc,&argv);
+ if (load_defaults("my",load_default_groups,&argc,&argv))
+ exit(1);
+
default_argv= argv;
if ((handle_options(&argc, &argv, my_long_options, get_one_option)))
@@ -6496,11 +7154,17 @@ int parse_args(int argc, char **argv)
memcpy(global_subst_to, comma+1, strlen(comma));
}
+ if (!opt_suite_dir)
+ opt_suite_dir= "./";
+ suite_dir_len= strlen(opt_suite_dir);
+ overlay_dir_len= opt_overlay_dir ? strlen(opt_overlay_dir) : 0;
+
if (!record)
{
/* Check that the result file exists */
if (result_file_name && access(result_file_name, F_OK) != 0)
- die("The specified result file '%s' does not exist", result_file_name);
+ die("The specified result file '%s' does not exist",
+ result_file_name);
}
return 0;
@@ -6589,6 +7253,8 @@ void init_win_path_patterns()
"$MYSQL_TMP_DIR",
"$MYSQLTEST_VARDIR",
"$MASTER_MYSOCK",
+ "$MYSQL_SHAREDIR",
+ "$MYSQL_LIBDIR",
"./test/" };
int num_paths= sizeof(paths)/sizeof(char*);
int i;
@@ -6613,7 +7279,7 @@ void init_win_path_patterns()
/* Don't insert zero length strings in patterns array */
if (strlen(p) == 0)
{
- my_free(p, MYF(0));
+ my_free(p);
continue;
}
@@ -6637,7 +7303,7 @@ void free_win_path_patterns()
for (i=0 ; i < patterns.elements ; i++)
{
const char** pattern= dynamic_element(&patterns, i, const char**);
- my_free((char*) *pattern, MYF(0));
+ my_free((void *) *pattern);
}
delete_dynamic(&patterns);
}
@@ -6825,8 +7491,8 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
}
if (error != MYSQL_NO_DATA)
- die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: error: %d",
- error);
+ die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: "
+ "error: %d", error);
if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
die("mysql_fetch didn't end with MYSQL_NO_DATA from statement: %d %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
@@ -6834,12 +7500,12 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
for (i= 0; i < num_fields; i++)
{
/* Free data for output */
- my_free(my_bind[i].buffer, MYF(MY_WME | MY_FAE));
+ my_free(my_bind[i].buffer);
}
/* Free array with bind structs, lengths and NULL flags */
- my_free(my_bind , MYF(MY_WME | MY_FAE));
- my_free(length , MYF(MY_WME | MY_FAE));
- my_free(is_null , MYF(MY_WME | MY_FAE));
+ my_free(my_bind);
+ my_free(length);
+ my_free(is_null);
}
@@ -7024,21 +7690,13 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
/*
Send the query
*/
- if (do_send_query(cn, query, query_len, flags))
+ if (do_send_query(cn, query, query_len))
{
handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
}
}
-#ifdef EMBEDDED_LIBRARY
- /*
- Here we handle 'reap' command, so we need to check if the
- query's thread was finished and probably wait
- */
- else if (flags & QUERY_REAP_FLAG)
- wait_query_thread_end(cn);
-#endif /*EMBEDDED_LIBRARY*/
if (!(flags & QUERY_REAP_FLAG))
{
cn->pending= TRUE;
@@ -7051,7 +7709,7 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
When on first result set, call mysql_read_query_result to retrieve
answer to the query sent earlier
*/
- if ((counter==0) && mysql_read_query_result(mysql))
+ if ((counter==0) && do_read_query_result(cn))
{
/* we've failed to collect the result set */
cn->pending= TRUE;
@@ -7073,8 +7731,6 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
if (!disable_result_log)
{
- ulonglong UNINIT_VAR(affected_rows); /* Ok to be undef if 'disable_info' is set */
-
if (res)
{
MYSQL_FIELD *fields= mysql_fetch_fields(res);
@@ -7091,10 +7747,10 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
/*
Need to call mysql_affected_rows() before the "new"
- query to find the warnings
+ query to find the warnings.
*/
if (!disable_info)
- affected_rows= mysql_affected_rows(mysql);
+ append_info(ds, mysql_affected_rows(mysql), mysql_info(mysql));
/*
Add all warnings to the result. We can't do this if we are in
@@ -7109,9 +7765,6 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length);
}
}
-
- if (!disable_info)
- append_info(ds, affected_rows, mysql_info(mysql));
}
if (res)
@@ -7132,6 +7785,7 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
/* If we come here the query is both executed and read successfully */
handle_no_error(command);
+ revert_properties();
end:
@@ -7184,7 +7838,8 @@ static int match_expected_error(struct st_command *command,
NULL is quite likely, but not in conjunction with a SQL-state expect!
*/
if (unlikely(err_sqlstate == NULL))
- die("expecting a SQL-state (%s) from query '%s' which cannot produce one...",
+ die("expecting a SQL-state (%s) from query '%s' which cannot "
+ "produce one...",
command->expected_errors.err[i].code.sqlstate, command->query);
if (strncmp(command->expected_errors.err[i].code.sqlstate,
@@ -7238,7 +7893,11 @@ void handle_error(struct st_command *command,
}
if (command->abort_on_error)
- die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
+ {
+ report_or_die("query '%s' failed: %d: %s", command->query, err_errno,
+ err_error);
+ DBUG_VOID_RETURN;
+ }
DBUG_PRINT("info", ("expected_errors.count: %d",
command->expected_errors.count));
@@ -7265,6 +7924,7 @@ void handle_error(struct st_command *command,
dynstr_append(ds,"Got one of the listed errors\n");
}
/* OK */
+ revert_properties();
DBUG_VOID_RETURN;
}
@@ -7283,15 +7943,18 @@ void handle_error(struct st_command *command,
if (command->expected_errors.count > 0)
{
if (command->expected_errors.err[0].type == ERR_ERRNO)
- die("query '%s' failed with wrong errno %d: '%s', instead of %d...",
- command->query, err_errno, err_error,
- command->expected_errors.err[0].code.errnum);
+ report_or_die("query '%s' failed with wrong errno %d: '%s', instead of "
+ "%d...",
+ command->query, err_errno, err_error,
+ command->expected_errors.err[0].code.errnum);
else
- die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
- command->query, err_sqlstate, err_error,
- command->expected_errors.err[0].code.sqlstate);
+ report_or_die("query '%s' failed with wrong sqlstate %s: '%s', "
+ "instead of %s...",
+ command->query, err_sqlstate, err_error,
+ command->expected_errors.err[0].code.sqlstate);
}
+ revert_properties();
DBUG_VOID_RETURN;
}
@@ -7315,17 +7978,18 @@ void handle_no_error(struct st_command *command)
command->expected_errors.err[0].code.errnum != 0)
{
/* Error code we wanted was != 0, i.e. not an expected success */
- die("query '%s' succeeded - should have failed with errno %d...",
- command->query, command->expected_errors.err[0].code.errnum);
+ report_or_die("query '%s' succeeded - should have failed with errno %d...",
+ command->query, command->expected_errors.err[0].code.errnum);
}
else if (command->expected_errors.err[0].type == ERR_SQLSTATE &&
strcmp(command->expected_errors.err[0].code.sqlstate,"00000") != 0)
{
/* SQLSTATE we wanted was != "00000", i.e. not an expected success */
- die("query '%s' succeeded - should have failed with sqlstate %s...",
- command->query, command->expected_errors.err[0].code.sqlstate);
+ report_or_die("query '%s' succeeded - should have failed with "
+ "sqlstate %s...",
+ command->query,
+ command->expected_errors.err[0].code.sqlstate);
}
-
DBUG_VOID_RETURN;
}
@@ -7453,9 +8117,6 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
handle_no_error(command);
if (!disable_result_log)
{
- ulonglong affected_rows;
- LINT_INIT(affected_rows);
-
/*
Not all statements creates a result set. If there is one we can
now create another normal result set that contains the meta
@@ -7498,11 +8159,11 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
}
/*
- Need to grab affected rows information before getting
- warnings here
+ Fetch info before fetching warnings, since it will be reset
+ otherwise.
*/
if (!disable_info)
- affected_rows= mysql_affected_rows(mysql);
+ append_info(ds, mysql_stmt_affected_rows(stmt), mysql_info(mysql));
if (!disable_warnings)
{
@@ -7526,8 +8187,6 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
ds_execute_warnings.length);
}
}
- if (!disable_info)
- append_info(ds, affected_rows, mysql_info(mysql));
}
end:
@@ -7545,6 +8204,8 @@ end:
var_set_errno(mysql_stmt_errno(stmt));
+ revert_properties();
+
/* Close the statement if reconnect, need new prepare */
if (mysql->reconnect)
{
@@ -7575,8 +8236,13 @@ int util_query(MYSQL* org_mysql, const char* query){
if (!(mysql= mysql_init(mysql)))
die("Failed in mysql_init()");
+ if (opt_connect_timeout)
+ mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT,
+ (void *) &opt_connect_timeout);
+
/* enable local infile, in non-binary builds often disabled by default */
mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, 0);
+ mysql_options(mysql, MYSQL_OPT_NONBLOCK, 0);
safe_connect(mysql, "util", org_mysql->host, org_mysql->user,
org_mysql->passwd, org_mysql->db, org_mysql->port,
org_mysql->unix_socket);
@@ -7620,12 +8286,14 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
DBUG_ENTER("run_query");
if (cn->pending && (flags & QUERY_SEND_FLAG))
- die ("Cannot run query on connection between send and reap");
+ die("Cannot run query on connection between send and reap");
if (!(flags & QUERY_SEND_FLAG) && !cn->pending)
- die ("Cannot reap on a connection without pending send");
+ die("Cannot reap on a connection without pending send");
init_dynamic_string(&ds_warnings, NULL, 0, 256);
+ ds_warn= &ds_warnings;
+
/*
Evaluate query if this is an eval command
*/
@@ -7791,7 +8459,8 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
ds, &ds_warnings);
dynstr_free(&ds_warnings);
- if (command->type == Q_EVAL)
+ ds_warn= 0;
+ if (command->type == Q_EVAL || command->type == Q_SEND_EVAL)
dynstr_free(&eval_query);
if (display_result_sorted)
@@ -7805,13 +8474,14 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
if (sp_created)
{
if (util_query(mysql, "DROP PROCEDURE mysqltest_tmp_sp "))
- die("Failed to drop sp: %d: %s", mysql_errno(mysql), mysql_error(mysql));
+ report_or_die("Failed to drop sp: %d: %s", mysql_errno(mysql),
+ mysql_error(mysql));
}
if (view_created)
{
if (util_query(mysql, "DROP VIEW mysqltest_tmp_v "))
- die("Failed to drop view: %d: %s",
+ report_or_die("Failed to drop view: %d: %s",
mysql_errno(mysql), mysql_error(mysql));
}
@@ -7837,8 +8507,8 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
char *re_eprint(int err)
{
static char epbuf[100];
- size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL,
- epbuf, sizeof(epbuf));
+ size_t len __attribute__((unused))=
+ my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf));
assert(len <= sizeof(epbuf));
return(epbuf);
}
@@ -7947,7 +8617,7 @@ void get_command_type(struct st_command* command)
save= command->query[command->first_word_len];
command->query[command->first_word_len]= 0;
- type= find_type(command->query, &command_typelib, 1+2);
+ type= find_type(command->query, &command_typelib, FIND_TYPE_NO_PREFIX);
command->query[command->first_word_len]= save;
if (type > 0)
{
@@ -7975,9 +8645,10 @@ void get_command_type(struct st_command* command)
else
{
/* -- "comment" that didn't contain a mysqltest command */
- die("Found line beginning with -- that didn't contain "\
- "a valid mysqltest command, check your syntax or "\
+ report_or_die("Found line beginning with -- that didn't contain " \
+ "a valid mysqltest command, check your syntax or " \
"use # if you intended to write a comment");
+ command->type= Q_COMMENT;
}
}
@@ -8047,14 +8718,17 @@ static void dump_backtrace(void)
fprintf(stderr, "read_command_buf (%p): ", read_command_buf);
my_safe_print_str(read_command_buf, sizeof(read_command_buf));
+ fputc('\n', stderr);
if (conn)
{
fprintf(stderr, "conn->name (%p): ", conn->name);
my_safe_print_str(conn->name, conn->name_len);
+ fputc('\n', stderr);
#ifdef EMBEDDED_LIBRARY
fprintf(stderr, "conn->cur_query (%p): ", conn->cur_query);
my_safe_print_str(conn->cur_query, conn->cur_query_len);
+ fputc('\n', stderr);
#endif
}
fputs("Attempting backtrace...\n", stderr);
@@ -8159,6 +8833,9 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
DBUG_ENTER("main");
+ /* mysqltest has no way to free all its memory correctly */
+ sf_leaking_memory= 1;
+
save_file[0]= 0;
TMPDIR[0]= 0;
@@ -8189,7 +8866,7 @@ int main(int argc, char **argv)
my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
- if (hash_init2(&var_hash, 64, charset_info,
+ if (my_hash_init2(&var_hash, 64, charset_info,
128, 0, 0, get_var_key, var_free, MYF(0)))
die("Variable hash initialization failed");
@@ -8237,6 +8914,7 @@ int main(int argc, char **argv)
next_con= connections + 1;
var_set_int("$PS_PROTOCOL", ps_protocol);
+ var_set_int("$NON_BLOCKING_API", non_blocking_api_enabled);
var_set_int("$SP_PROTOCOL", sp_protocol);
var_set_int("$VIEW_PROTOCOL", view_protocol);
var_set_int("$CURSOR_PROTOCOL", cursor_protocol);
@@ -8264,6 +8942,7 @@ int main(int argc, char **argv)
cur_file->file_name= my_strdup("<stdin>", MYF(MY_WME));
cur_file->lineno= 1;
}
+ var_set_string("MYSQLTEST_FILE", cur_file->file_name);
init_re();
/* Cursor protcol implies ps protocol */
@@ -8276,8 +8955,12 @@ int main(int argc, char **argv)
cursor_protocol_enabled= cursor_protocol;
st_connection *con= connections;
+ init_connection_thd(con);
if (! (con->mysql= mysql_init(0)))
die("Failed in mysql_init()");
+ if (opt_connect_timeout)
+ mysql_options(con->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
+ (void *) &opt_connect_timeout);
if (opt_compress)
mysql_options(con->mysql,MYSQL_OPT_COMPRESS,NullS);
mysql_options(con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
@@ -8293,10 +8976,7 @@ int main(int argc, char **argv)
if (opt_plugin_dir && *opt_plugin_dir)
mysql_options(con->mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
- if (opt_default_auth && *opt_default_auth)
- mysql_options(con->mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
-
-#ifdef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
if (opt_use_ssl)
{
@@ -8318,6 +8998,7 @@ int main(int argc, char **argv)
if (!(con->name = my_strdup("default", MYF(MY_WME))))
die("Out of memory");
+ mysql_options(con->mysql, MYSQL_OPT_NONBLOCK, 0);
safe_connect(con->mysql, con->name, opt_host, opt_user, opt_pass,
opt_db, opt_port, unix_sock);
@@ -8334,9 +9015,9 @@ int main(int argc, char **argv)
set_current_connection(con);
- if (opt_include)
+ if (opt_prologue)
{
- open_file(opt_include);
+ open_file(opt_prologue);
}
verbose_msg("Start processing test commands from '%s' ...", cur_file->file_name);
@@ -8402,66 +9083,49 @@ int main(int argc, char **argv)
case Q_DISCONNECT:
case Q_DIRTY_CLOSE:
do_close_connection(command); break;
- case Q_RPL_PROBE: do_rpl_probe(command); break;
- case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(command); break;
- case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(command); break;
case Q_ENABLE_PREPARE_WARNINGS: prepare_warnings_enabled=1; break;
case Q_DISABLE_PREPARE_WARNINGS: prepare_warnings_enabled=0; break;
case Q_ENABLE_QUERY_LOG:
- disable_query_log= 0;
- var_set_int("$ENABLED_QUERY_LOG", 1);
+ set_property(command, P_QUERY, 0);
break;
case Q_DISABLE_QUERY_LOG:
- disable_query_log= 1;
- var_set_int("$ENABLED_QUERY_LOG", 0);
+ set_property(command, P_QUERY, 1);
break;
case Q_ENABLE_ABORT_ON_ERROR:
- abort_on_error= 1;
- var_set_int("$ENABLED_ABORT_ON_ERROR", 1);
+ set_property(command, P_ABORT, 1);
break;
case Q_DISABLE_ABORT_ON_ERROR:
- abort_on_error= 0;
- var_set_int("$ENABLED_ABORT_ON_ERROR", 0);
+ set_property(command, P_ABORT, 0);
break;
case Q_ENABLE_RESULT_LOG:
- disable_result_log= 0;
- var_set_int("$ENABLED_RESULT_LOG", 1);
+ set_property(command, P_RESULT, 0);
break;
case Q_DISABLE_RESULT_LOG:
- disable_result_log=1;
- var_set_int("$ENABLED_RESULT_LOG", 0);
+ set_property(command, P_RESULT, 1);
break;
case Q_ENABLE_CONNECT_LOG:
- disable_connect_log=0;
- var_set_int("$ENABLED_CONNECT_LOG", 1);
+ set_property(command, P_CONNECT, 0);
break;
case Q_DISABLE_CONNECT_LOG:
- disable_connect_log=1;
- var_set_int("$ENABLED_CONNECT_LOG", 0);
+ set_property(command, P_CONNECT, 1);
break;
case Q_ENABLE_WARNINGS:
- disable_warnings= 0;
- var_set_int("$ENABLED_WARNINGS", 1);
+ set_property(command, P_WARN, 0);
break;
case Q_DISABLE_WARNINGS:
- disable_warnings= 1;
- var_set_int("$ENABLED_WARNINGS", 0);
+ set_property(command, P_WARN, 1);
break;
case Q_ENABLE_INFO:
- disable_info= 0;
- var_set_int("$ENABLED_INFO", 1);
+ set_property(command, P_INFO, 0);
break;
case Q_DISABLE_INFO:
- disable_info= 1;
- var_set_int("$ENABLED_INFO", 0);
+ set_property(command, P_INFO, 1);
break;
case Q_ENABLE_METADATA:
- display_metadata= 1;
- var_set_int("$ENABLED_METADATA", 1);
+ set_property(command, P_META, 1);
break;
case Q_DISABLE_METADATA:
- display_metadata= 0;
- var_set_int("$ENABLED_METADATA", 0);
+ set_property(command, P_META, 0);
break;
case Q_ENABLE_COLUMN_NAMES:
disable_column_names= 0;
@@ -8501,6 +9165,7 @@ int main(int argc, char **argv)
case Q_MOVE_FILE: do_move_file(command); break;
case Q_CHMOD_FILE: do_chmod_file(command); break;
case Q_PERL: do_perl(command); break;
+ case Q_RESULT_FORMAT_VERSION: do_result_format_version(command); break;
case Q_DELIMITER:
do_delimiter(command);
break;
@@ -8627,9 +9292,38 @@ int main(int argc, char **argv)
do_sync_with_master2(command, 0);
break;
}
- case Q_COMMENT: /* Ignore row */
+ case Q_COMMENT:
+ {
command->last_argument= command->end;
+
+ /* Don't output comments in v1 */
+ if (opt_result_format_version == 1)
+ break;
+
+ /* Don't output comments if query logging is off */
+ if (disable_query_log)
+ break;
+
+ /* Write comment's with two starting #'s to result file */
+ const char* p= command->query;
+ if (p && *p == '#' && *(p+1) == '#')
+ {
+ dynstr_append_mem(&ds_res, command->query, command->query_len);
+ dynstr_append(&ds_res, "\n");
+ }
break;
+ }
+ case Q_EMPTY_LINE:
+ /* Don't output newline in v1 */
+ if (opt_result_format_version == 1)
+ break;
+
+ /* Don't output newline if query logging is off */
+ if (disable_query_log)
+ break;
+
+ dynstr_append(&ds_res, "\n");
+ break;
case Q_PING:
handle_command_error(command, mysql_ping(cur_con->mysql), -1);
break;
@@ -8657,12 +9351,18 @@ int main(int argc, char **argv)
do_set_charset(command);
break;
case Q_DISABLE_PS_PROTOCOL:
- ps_protocol_enabled= 0;
+ set_property(command, P_PS, 0);
/* Close any open statements */
close_statements();
break;
case Q_ENABLE_PS_PROTOCOL:
- ps_protocol_enabled= ps_protocol;
+ set_property(command, P_PS, ps_protocol);
+ break;
+ case Q_DISABLE_NON_BLOCKING_API:
+ non_blocking_api_enabled= 0;
+ break;
+ case Q_ENABLE_NON_BLOCKING_API:
+ non_blocking_api_enabled= 1;
break;
case Q_DISABLE_RECONNECT:
set_reconnect(cur_con->mysql, 0);
@@ -8676,7 +9376,7 @@ int main(int argc, char **argv)
if (parsing_disabled == 0)
parsing_disabled= 1;
else
- die("Parsing is already disabled");
+ report_or_die("Parsing is already disabled");
break;
case Q_ENABLE_PARSING:
/*
@@ -8686,7 +9386,7 @@ int main(int argc, char **argv)
if (parsing_disabled == 1)
parsing_disabled= 0;
else
- die("Parsing is already enabled");
+ report_or_die("Parsing is already enabled");
break;
case Q_DIE:
/* Abort test with error code and error message */
@@ -8890,13 +9590,14 @@ void do_get_replace_column(struct st_command *command)
if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
die("Wrong column number to replace_column in '%s'", command->query);
if (!*from)
- die("Wrong number of arguments to replace_column in '%s'", command->query);
+ die("Wrong number of arguments to replace_column in '%s'",
+ command->query);
to= get_string(&buff, &from, command);
- my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
+ my_free(replace_column[column_number-1]);
replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
set_if_bigger(max_replace_column, column_number);
}
- my_free(start, MYF(0));
+ my_free(start);
command->last_argument= command->end;
DBUG_VOID_RETURN;
@@ -8910,7 +9611,7 @@ void free_replace_column()
{
if (replace_column[i])
{
- my_free(replace_column[i], 0);
+ my_free(replace_column[i]);
replace_column[i]= 0;
}
}
@@ -8928,20 +9629,15 @@ void free_replace_column()
typedef struct st_pointer_array { /* when using array-strings */
TYPELIB typelib; /* Pointer to strings */
uchar *str; /* Strings is here */
- int7 *flag; /* Flag about each var. */
+ uint8 *flag; /* Flag about each var. */
uint array_allocs,max_count,length,max_length;
} POINTER_ARRAY;
-struct st_replace;
struct st_replace *init_replace(char * *from, char * *to, uint count,
char * word_end_chars);
int insert_pointer_name(reg1 POINTER_ARRAY *pa,char * name);
-void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
- const char *from, int len);
void free_pointer_array(POINTER_ARRAY *pa);
-struct st_replace *glob_replace;
-
/*
Get arguments for replace. The syntax is:
replace from to [from to ...]
@@ -8991,7 +9687,7 @@ void do_get_replace(struct st_command *command)
die("Can't initialize replace from '%s'", command->query);
free_pointer_array(&from_array);
free_pointer_array(&to_array);
- my_free(start, MYF(0));
+ my_free(start);
command->last_argument= command->end;
DBUG_VOID_RETURN;
}
@@ -9000,11 +9696,8 @@ void do_get_replace(struct st_command *command)
void free_replace()
{
DBUG_ENTER("free_replace");
- if (glob_replace)
- {
- my_free(glob_replace,MYF(0));
- glob_replace=0;
- }
+ my_free(glob_replace);
+ glob_replace= NULL;
DBUG_VOID_RETURN;
}
@@ -9088,26 +9781,6 @@ struct st_regex
int icase; /* true if the match is case insensitive */
};
-struct st_replace_regex
-{
- DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
-
- /*
- Temporary storage areas for substitutions. To reduce unnessary copying
- and memory freeing/allocation, we pre-allocate two buffers, and alternate
- their use, one for input/one for output, the roles changing on the next
- st_regex substition. At the end of substitutions buf points to the
- one containing the final result.
- */
- char* buf;
- char* even_buf;
- char* odd_buf;
- int even_buf_len;
- int odd_buf_len;
-};
-
-struct st_replace_regex *glob_replace_regex= 0;
-
int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
char *string, int icase);
@@ -9224,7 +9897,7 @@ struct st_replace_regex* init_replace_regex(char* expr)
return res;
err:
- my_free(res,0);
+ my_free(res);
die("Error parsing replace_regex \"%s\"", expr);
return 0;
}
@@ -9306,7 +9979,13 @@ void do_get_replace_regex(struct st_command *command)
{
char *expr= command->first_argument;
free_replace_regex();
- if (!(glob_replace_regex=init_replace_regex(expr)))
+ /* Allow variable for the *entire* list of replacements */
+ if (*expr == '$')
+ {
+ VAR *val= var_get(expr, NULL, 0, 1);
+ expr= val ? val->str_val : NULL;
+ }
+ if (expr && *expr && !(glob_replace_regex=init_replace_regex(expr)))
die("Could not init replace_regex");
command->last_argument= command->end;
}
@@ -9316,9 +9995,9 @@ void free_replace_regex()
if (glob_replace_regex)
{
delete_dynamic(&glob_replace_regex->regex_arr);
- my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
- my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
- my_free(glob_replace_regex,MYF(0));
+ my_free(glob_replace_regex->even_buf);
+ my_free(glob_replace_regex->odd_buf);
+ my_free(glob_replace_regex);
glob_replace_regex=0;
}
}
@@ -9513,7 +10192,7 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
str_p= str_end;
}
}
- my_free(subs, MYF(0));
+ my_free(subs);
my_regfree(&r);
*res_p= 0;
*buf_p= buf;
@@ -9637,7 +10316,7 @@ REPLACE *init_replace(char * *from, char * *to,uint count,
free_sets(&sets);
DBUG_RETURN(0);
}
- VOID(make_new_set(&sets)); /* Set starting set */
+ (void) make_new_set(&sets); /* Set starting set */
make_sets_invisible(&sets); /* Hide previus sets */
used_sets=-1;
word_states=make_new_set(&sets); /* Start of new word */
@@ -9645,7 +10324,7 @@ REPLACE *init_replace(char * *from, char * *to,uint count,
if (!(follow=(FOLLOWS*) my_malloc((states+2)*sizeof(FOLLOWS),MYF(MY_WME))))
{
free_sets(&sets);
- my_free(found_set,MYF(0));
+ my_free(found_set);
DBUG_RETURN(0);
}
@@ -9839,9 +10518,9 @@ REPLACE *init_replace(char * *from, char * *to,uint count,
replace[i].next[j]=(REPLACE*) (rep_str+(-sets.set[i].next[j]-1));
}
}
- my_free(follow,MYF(0));
+ my_free(follow);
free_sets(&sets);
- my_free(found_set,MYF(0));
+ my_free(found_set);
DBUG_PRINT("exit",("Replace table has %d states",sets.count));
DBUG_RETURN(replace);
}
@@ -9857,7 +10536,7 @@ int init_sets(REP_SETS *sets,uint states)
if (!(sets->bit_buffer=(uint*) my_malloc(sizeof(uint)*sets->size_of_bits*
SET_MALLOC_HUNC,MYF(MY_WME))))
{
- my_free(sets->set,MYF(0));
+ my_free(sets->set);
return 1;
}
return 0;
@@ -9918,8 +10597,8 @@ void free_last_set(REP_SETS *sets)
void free_sets(REP_SETS *sets)
{
- my_free(sets->set_buffer,MYF(0));
- my_free(sets->bit_buffer,MYF(0));
+ my_free(sets->set_buffer);
+ my_free(sets->bit_buffer);
return;
}
@@ -10057,12 +10736,12 @@ int insert_pointer_name(reg1 POINTER_ARRAY *pa,char * name)
if (!(pa->str= (uchar*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
MYF(MY_WME))))
{
- my_free((char*) pa->typelib.type_names,MYF(0));
+ my_free(pa->typelib.type_names);
DBUG_RETURN (-1);
}
pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(uchar*)+
sizeof(*pa->flag));
- pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
+ pa->flag= (uint8*) (pa->typelib.type_names+pa->max_count);
pa->length=0;
pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
pa->array_allocs=1;
@@ -10098,14 +10777,14 @@ int insert_pointer_name(reg1 POINTER_ARRAY *pa,char * name)
pa->typelib.type_names=new_array;
old_count=pa->max_count;
pa->max_count=len/(sizeof(uchar*) + sizeof(*pa->flag));
- pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
+ pa->flag= (uint8*) (pa->typelib.type_names+pa->max_count);
memcpy((uchar*) pa->flag,(char *) (pa->typelib.type_names+old_count),
old_count*sizeof(*pa->flag));
}
pa->flag[pa->typelib.count]=0; /* Reset flag */
pa->typelib.type_names[pa->typelib.count++]= (char*) pa->str+pa->length;
pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */
- VOID(strmov((char*) pa->str+pa->length,name));
+ (void) strmov((char*) pa->str+pa->length,name);
pa->length+=length;
DBUG_RETURN(0);
} /* insert_pointer_name */
@@ -10118,9 +10797,9 @@ void free_pointer_array(POINTER_ARRAY *pa)
if (pa->typelib.count)
{
pa->typelib.count=0;
- my_free((char*) pa->typelib.type_names,MYF(0));
+ my_free(pa->typelib.type_names);
pa->typelib.type_names=0;
- my_free(pa->str,MYF(0));
+ my_free(pa->str);
}
} /* free_pointer_array */
diff --git a/client/readline.cc b/client/readline.cc
index b44862062e1..791a044e0e1 100644
--- a/client/readline.cc
+++ b/client/readline.cc
@@ -47,7 +47,7 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
return 0;
if (init_line_buffer(line_buff,my_fileno(file),IO_SIZE,max_size))
{
- my_free(line_buff,MYF(0));
+ my_free(line_buff);
return 0;
}
return line_buff;
@@ -75,8 +75,8 @@ void batch_readline_end(LINE_BUFFER *line_buff)
{
if (line_buff)
{
- my_free(line_buff->buffer,MYF(MY_ALLOW_ZERO_PTR));
- my_free(line_buff,MYF(0));
+ my_free(line_buff->buffer);
+ my_free(line_buff);
}
}
@@ -89,7 +89,7 @@ LINE_BUFFER *batch_readline_command(LINE_BUFFER *line_buff, char * str)
return 0;
if (init_line_buffer_from_string(line_buff,str))
{
- my_free(line_buff,MYF(0));
+ my_free(line_buff);
return 0;
}
return line_buff;
diff --git a/client/sql_string.cc b/client/sql_string.cc.dontuse
index 57518423f4b..64219886dd0 100644
--- a/client/sql_string.cc
+++ b/client/sql_string.cc.dontuse
@@ -25,18 +25,20 @@
#include <my_sys.h>
#include <m_string.h>
#include <m_ctype.h>
-#ifdef HAVE_FCONVERT
-#include <floatingpoint.h>
-#endif
+#include <mysql_com.h>
+
#include "sql_string.h"
/*****************************************************************************
** String functions
*****************************************************************************/
-bool String::real_alloc(uint32 arg_length)
+bool String::real_alloc(uint32 length)
{
- arg_length=ALIGN_SIZE(arg_length+1);
+ uint32 arg_length= ALIGN_SIZE(length + 1);
+ DBUG_ASSERT(arg_length > length);
+ if (arg_length <= length)
+ return TRUE; /* Overflow */
str_length=0;
if (Alloced_length < arg_length)
{
@@ -59,6 +61,9 @@ bool String::real_alloc(uint32 arg_length)
bool String::realloc(uint32 alloc_length)
{
uint32 len=ALIGN_SIZE(alloc_length+1);
+ DBUG_ASSERT(len > alloc_length);
+ if (len <= alloc_length)
+ return TRUE; /* Overflow */
if (Alloced_length < len)
{
char *new_ptr;
@@ -111,83 +116,17 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs)
{
char buff[FLOATING_POINT_BUFFER];
uint dummy_errors;
+ size_t len;
str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
- uint32 len= my_sprintf(buff,(buff, "%.15g",num));// Enough for a DATETIME
+ len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
}
-#ifdef HAVE_FCONVERT
- int decpt,sign;
- char *pos,*to;
-
- VOID(fconvert(num,(int) decimals,&decpt,&sign,buff+1));
- if (!my_isdigit(&my_charset_latin1, buff[1]))
- { // Nan or Inf
- pos=buff+1;
- if (sign)
- {
- buff[0]='-';
- pos=buff;
- }
- uint dummy_errors;
- return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs, &dummy_errors);
- }
- if (alloc((uint32) ((uint32) decpt+3+decimals)))
- return TRUE;
- to=Ptr;
- if (sign)
- *to++='-';
-
- pos=buff+1;
- if (decpt < 0)
- { /* value is < 0 */
- *to++='0';
- if (!decimals)
- goto end;
- *to++='.';
- if ((uint32) -decpt > decimals)
- decpt= - (int) decimals;
- decimals=(uint32) ((int) decimals+decpt);
- while (decpt++ < 0)
- *to++='0';
- }
- else if (decpt == 0)
- {
- *to++= '0';
- if (!decimals)
- goto end;
- *to++='.';
- }
- else
- {
- while (decpt-- > 0)
- *to++= *pos++;
- if (!decimals)
- goto end;
- *to++='.';
- }
- while (decimals--)
- *to++= *pos++;
-
-end:
- *to=0;
- str_length=(uint32) (to-Ptr);
- return FALSE;
-#else
-#ifdef HAVE_SNPRINTF
- buff[sizeof(buff)-1]=0; // Safety
- IF_DBUG(int num_chars= )
- snprintf(buff, sizeof(buff)-1, "%.*f",(int) decimals, num);
- DBUG_ASSERT(num_chars > 0);
- DBUG_ASSERT(num_chars < (int) sizeof(buff));
-#else
- sprintf(buff,"%.*f",(int) decimals,num);
-#endif
- return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs,
+ len= my_fcvt(num, decimals, buff, NULL);
+ return copy(buff, (uint32) len, &my_charset_latin1, cs,
&dummy_errors);
-#endif
}
@@ -670,7 +609,8 @@ void String::qs_append(const char *str, uint32 len)
void String::qs_append(double d)
{
char *buff = Ptr + str_length;
- str_length+= my_sprintf(buff, (buff, "%.15g", d));
+ str_length+= my_gcvt(d, MY_GCVT_ARG_DOUBLE, FLOATING_POINT_BUFFER - 1, buff,
+ NULL);
}
void String::qs_append(double *d)
diff --git a/client/sql_string.h b/client/sql_string.h.dontuse
index 6adf8f91fd0..67155ebcee7 100644
--- a/client/sql_string.h
+++ b/client/sql_string.h.dontuse
@@ -1,5 +1,7 @@
-/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+#ifndef SQL_STRING_INCLUDED
+#define SQL_STRING_INCLUDED
+
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
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
@@ -12,22 +14,14 @@
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/* This file is originally from the mysql distribution. Coded by monty */
-#ifndef CLIENT_SQL_STRING_H
-#define CLIENT_SQL_STRING_H
-
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
-#ifndef NOT_FIXED_DEC
-#define NOT_FIXED_DEC 31
-#endif
-
class String;
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
@@ -38,13 +32,13 @@ uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
class String
{
char *Ptr;
- uint32 str_length,Alloced_length;
+ uint32 str_length,Alloced_length, extra_alloc;
bool alloced;
CHARSET_INFO *str_charset;
public:
String()
{
- Ptr=0; str_length=Alloced_length=0; alloced=0;
+ Ptr=0; str_length=Alloced_length=extra_alloc=0; alloced=0;
str_charset= &my_charset_bin;
}
String(uint32 length_arg)
@@ -54,23 +48,24 @@ public:
}
String(const char *str, CHARSET_INFO *cs)
{
- Ptr=(char*) str; str_length=(uint) strlen(str); Alloced_length=0; alloced=0;
+ Ptr=(char*) str; str_length= (uint32) strlen(str);
+ Alloced_length= extra_alloc= 0; alloced=0;
str_charset=cs;
}
String(const char *str,uint32 len, CHARSET_INFO *cs)
{
- Ptr=(char*) str; str_length=len; Alloced_length=0; alloced=0;
+ Ptr=(char*) str; str_length=len; Alloced_length= extra_alloc=0; alloced=0;
str_charset=cs;
}
String(char *str,uint32 len, CHARSET_INFO *cs)
{
- Ptr=(char*) str; Alloced_length=str_length=len; alloced=0;
+ Ptr=(char*) str; Alloced_length=str_length=len; extra_alloc= 0; alloced=0;
str_charset=cs;
}
String(const String &str)
{
Ptr=str.Ptr ; str_length=str.str_length ;
- Alloced_length=str.Alloced_length; alloced=0;
+ Alloced_length=str.Alloced_length; extra_alloc= 0; alloced=0;
str_charset=str.str_charset;
}
static void *operator new(size_t size, MEM_ROOT *mem_root)
@@ -185,7 +180,7 @@ public:
{
alloced=0;
Alloced_length=0;
- my_free(Ptr,MYF(0));
+ my_free(Ptr);
Ptr=0;
str_length=0; /* Safety */
}
@@ -367,4 +362,4 @@ public:
}
};
-#endif
+#endif /* SQL_STRING_INCLUDED */