diff options
author | Alexander Nozdrin <alexander.nozdrin@oracle.com> | 2011-08-15 18:29:38 +0400 |
---|---|---|
committer | Alexander Nozdrin <alexander.nozdrin@oracle.com> | 2011-08-15 18:29:38 +0400 |
commit | 6e5bbf513810448e84872069065a0561e0d70a93 (patch) | |
tree | e40e3ed079113e0bbbb9270aaccddcea851b3d77 | |
parent | 888b8793a256040ab9b7e008c52936da75a3d116 (diff) | |
download | mariadb-git-6e5bbf513810448e84872069065a0561e0d70a93.tar.gz |
Cherry-picking WL#5710 from mysql-5.5 to mysql-5.5.16-release.
Original revision id:
# revno: 3489 [merge]
# revision-id: tatjana.nuernberg@oracle.com-20110811120945-c6x9a5d2du8s9oj2
# parent: tatjana.nuernberg@oracle.com-20110811112736-so8r813hs8dmf7nr
# parent: chuck.bell@oracle.com-20110810183949-2s9uxcuoux2p668e
# committer: Tatjana Azundris Nuernberg <tatjana.nuernberg@oracle.com>
# branch nick: 55-9
# timestamp: Thu 2011-08-11 13:09:45 +0100
# message:
# auto-merge
This merge revision also has a patch for Bug 12664445, which has been also
taken to 5.5.16.
22 files changed, 2219 insertions, 96 deletions
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 80c5bbd1c9f..c5bda7d8a35 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -54,6 +54,9 @@ ADD_DEPENDENCIES(mysql_upgrade GenFixPrivs) 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) TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient) @@ -69,7 +72,7 @@ IF(WIN32) MYSQL_ADD_EXECUTABLE(echo echo.c) ENDIF(WIN32) -SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap +SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap mysql_plugin PROPERTIES HAS_CXX TRUE) ADD_DEFINITIONS(-DHAVE_DLOPEN) diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c new file mode 100644 index 00000000000..6679fa9ca6f --- /dev/null +++ b/client/mysql_plugin.c @@ -0,0 +1,1192 @@ +/* + Copyright (c) 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 + 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]); + 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) +#ifdef __WIN__ + if (opt_basedir[i-1] != '/') + strcat(opt_basedir, "//"); +#else + strcat(opt_basedir, FN_DIRSEP); +#endif + } + + /* + 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 ((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 ((error= my_access(opt_mysqld, F_OK))) + { + fprintf(stderr, "ERROR: Cannot access mysqld path '%s'.\n", + opt_mysqld); + goto exit; + } + if ((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_basedir, opt_mysqld, 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 INSERT 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, INSERT + 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. + */ + 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, "INSERT IGNORE 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 name = '%s';", plugin_data.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", 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; + int ret= 0; + +#ifdef __WIN__ + char *format_str= 0; + char *verbose_str= ""; + + if (opt_verbose) + strcat(verbose_str, "--console"); + 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", + ret); + + return error; +} diff --git a/include/my_global.h b/include/my_global.h index f465d031b62..924c83cd951 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -603,6 +603,8 @@ typedef SOCKET_SIZE_TYPE size_socket; #define FN_LIBCHAR '\\' #define FN_LIBCHAR2 '/' #define FN_DIRSEP "/\\" /* Valid directory separators */ +#define FN_EXEEXT ".exe" +#define FN_SOEXT ".dll" #define FN_ROOTDIR "\\" #define FN_DEVCHAR ':' #define FN_NETWORK_DRIVES /* Uses \\ to indicate network drives */ @@ -611,6 +613,8 @@ typedef SOCKET_SIZE_TYPE size_socket; #define FN_LIBCHAR '/' #define FN_LIBCHAR2 '/' #define FN_DIRSEP "/" /* Valid directory separators */ +#define FN_EXEEXT "" +#define FN_SOEXT ".so" #define FN_ROOTDIR "/" #endif diff --git a/mysql-test/include/daemon_example_bad_format.ini b/mysql-test/include/daemon_example_bad_format.ini new file mode 100644 index 00000000000..8f880ef0ba0 --- /dev/null +++ b/mysql-test/include/daemon_example_bad_format.ini @@ -0,0 +1,8 @@ +# +# Plugin configuration file. Place the following on a separate line: +# +# library binary file name (without .so or .dll) +# component_name +# [component_name] - additional components in plugin +# +libdaemon_example diff --git a/mysql-test/include/daemon_example_bad_soname.ini b/mysql-test/include/daemon_example_bad_soname.ini new file mode 100644 index 00000000000..5f42b5a6214 --- /dev/null +++ b/mysql-test/include/daemon_example_bad_soname.ini @@ -0,0 +1,9 @@ +# +# Plugin configuration file. Place the following on a separate line: +# +# library binary file name (without .so or .dll) +# component_name +# [component_name] - additional components in plugin +# +libdaemon_BADNAME +daemon_BADNAME diff --git a/mysql-test/include/plugin.defs b/mysql-test/include/plugin.defs index e07c603c8e5..6fbe4f68328 100644 --- a/mysql-test/include/plugin.defs +++ b/mysql-test/include/plugin.defs @@ -39,3 +39,4 @@ ha_archive storage/archive ARCHIVE_PLUGIN ha_blackhole storage/blackhole BLACKHOLE_PLUGIN ha_federated storage/federated FEDERATED_PLUGIN mypluglib plugin/fulltext SIMPLE_PARSER +libdaemon_example plugin/daemon_example DAEMONEXAMPLE diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 82d17a21f89..ec0ca74b1d1 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -168,6 +168,7 @@ my $opt_suites; our $opt_verbose= 0; # Verbose output, enable with --verbose our $exe_mysql; +our $exe_mysql_plugin; our $exe_mysqladmin; our $exe_mysqltest; our $exe_libtool; @@ -1950,6 +1951,7 @@ sub executable_setup () { # Look for the client binaries $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin"); $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql"); + $exe_mysql_plugin= mtr_exe_exists("$path_client_bindir/mysql_plugin"); $exe_mysql_embedded= mtr_exe_maybe_exists("$basedir/libmysqld/examples/mysql_embedded"); @@ -2357,6 +2359,7 @@ sub environment_setup { $ENV{'MYSQLADMIN'}= native_path($exe_mysqladmin); $ENV{'MYSQL_CLIENT_TEST'}= mysql_client_test_arguments(); $ENV{'EXE_MYSQL'}= $exe_mysql; + $ENV{'MYSQL_PLUGIN'}= $exe_mysql_plugin; $ENV{'MYSQL_EMBEDDED'}= $exe_mysql_embedded; # ---------------------------------------------------- diff --git a/mysql-test/r/mysql_plugin.result b/mysql-test/r/mysql_plugin.result new file mode 100644 index 00000000000..949f3748236 --- /dev/null +++ b/mysql-test/r/mysql_plugin.result @@ -0,0 +1,110 @@ +# +# Ensure the plugin isn't loaded. +# +SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name; +name dl +# +# Enable the plugin... +# +# +# Ensure the plugin is now loaded. +# +SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name; +name dl +daemon_example libdaemon_example.so +# +# Disable the plugin... +# +# +# Ensure the plugin isn't loaded. +# +SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name; +name dl +# +# Attempt to load non-existant plugin +# +ERROR: Cannot read plugin config file NOT_THERE_AT_ALL. File does not exist. +# +# Attempt to use non-existant plugin.ini file +# +ERROR: Cannot read plugin config file daemon_example. File does not exist. +# +# Attempt to omit the plugin +# +ERROR: No plugin specified. +# +# Attempt to omit DISABLE|ENABLE +# +ERROR: missing operation. Please specify either '<plugin> ENABLE' or '<plugin> DISABLE'. +# +# Attempt to use bad paths - datadir +# +ERROR: Cannot access datadir at '/data_not_there/'. +# +# Attempt to use bad paths - basedir +# +ERROR: Cannot access basedir at '/basedir_not_there/'. +# +# Attempt to use bad paths - plugin_dir +# +ERROR: Cannot read plugin config file daemon_example. File does not exist. +# +# Attempt to use bad paths - mysqld +# +ERROR: Cannot access mysqld path '/mysqld_not_there/'. +# +# Attempt to use bad paths - my_print_defaults +# +ERROR: Cannot access my-print-defaults path '/my_print_defaults_not_there/'. +# +# Missing library +# +ERROR: The plugin library is missing or in a different location. +# +# Bad format for config file +# +ERROR: Cannot read plugin config file daemon_example. Bad format in plugin configuration file. +# +# Missing base_dir option +# +ERROR: Missing --basedir option. +# +# Missing data_dir option +# +ERROR: Missing --datadir option. +# +# Missing plugin_dir option +# +ERROR: Missing --plugin_dir option. +# +# Show the help. +# +mysql_plugin Ver V.V.VV Distrib XX.XX.XX +Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + +Enable or disable plugins. + +Usage: mysql_plugin [options] <plugin> ENABLE|DISABLE + +Options: + -?, --help Display this help and exit. + -b, --basedir=name The basedir for the server. + -d, --datadir=name The datadir for the server. + -p, --plugin-dir=name + The plugin dir for the server. + -i, --plugin-ini=name + Read plugin information from configuration file specified + instead of from <plugin-dir>/<plugin_name>.ini. + -n, --no-defaults Do not read values from configuration file. + -P, --print-defaults + Show default values from configuration file. + -m, --mysqld=name Path to mysqld executable. Example: /sbin/temp1/mysql/bin + -f, --my-print-defaults=name + Path to my_print_defaults executable. Example: + /source/temp11/extra + -v, --verbose More verbose output; you can use this multiple times to + get even more verbose output. + -V, --version Output version information and exit. + + +mysql_plugin Ver V.V.VV Distrib XX.XX.XX diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index 3cee368853f..715ad9e2c15 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -11,13 +11,7 @@ There should be *no* long test name listed below: select variable_name as `There should be *no* variables listed below:` from t2 left join t1 on variable_name=test_name where test_name is null; There should be *no* variables listed below: -INNODB_ROLLBACK_SEGMENTS -INNODB_STATS_METHOD -INNODB_FILE_FORMAT_MAX INNODB_LARGE_PREFIX -INNODB_ROLLBACK_SEGMENTS -INNODB_STATS_METHOD -INNODB_FILE_FORMAT_MAX INNODB_LARGE_PREFIX drop table t1; drop table t2; diff --git a/mysql-test/suite/sys_vars/r/innodb_file_format_check_basic.result b/mysql-test/suite/sys_vars/r/innodb_file_format_check_basic.result index c59e1b802f4..9167585f1d6 100644 --- a/mysql-test/suite/sys_vars/r/innodb_file_format_check_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_file_format_check_basic.result @@ -1,59 +1,80 @@ -SET @start_global_value = @@global.innodb_file_format_max; +SET @start_global_value = @@global.innodb_file_format_check; SELECT @start_global_value; @start_global_value -Antelope -Valid values are 'Antelope' and 'Barracuda' -select @@global.innodb_file_format_max in ('Antelope', 'Barracuda'); -@@global.innodb_file_format_max in ('Antelope', 'Barracuda') -1 -select @@global.innodb_file_format_max; -@@global.innodb_file_format_max -Antelope -select @@session.innodb_file_format_max; -ERROR HY000: Variable 'innodb_file_format_max' is a GLOBAL variable -show global variables like 'innodb_file_format_max'; +1 +Valid values are 'ON' and 'OFF' +SELECT @@global.innodb_file_format_check in (0, 1); +@@global.innodb_file_format_check in (0, 1) +1 +SELECT @@global.innodb_file_format_check; +@@global.innodb_file_format_check +1 +SELECT @@session.innodb_file_format_check; +ERROR HY000: Variable 'innodb_file_format_check' is a GLOBAL variable +SHOW global variables LIKE 'innodb_file_format_check'; Variable_name Value -innodb_file_format_max Antelope -show session variables like 'innodb_file_format_max'; +innodb_file_format_check ON +SHOW session variables LIKE 'innodb_file_format_check'; Variable_name Value -innodb_file_format_max Antelope -select * from information_schema.global_variables where variable_name='innodb_file_format_max'; -VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_MAX Antelope -select * from information_schema.session_variables where variable_name='innodb_file_format_max'; -VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_MAX Antelope -set global innodb_file_format_max='Antelope'; -select @@global.innodb_file_format_max; -@@global.innodb_file_format_max -Antelope -select * from information_schema.global_variables where variable_name='innodb_file_format_max'; -VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_MAX Antelope -select * from information_schema.session_variables where variable_name='innodb_file_format_max'; -VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_MAX Antelope -set @@global.innodb_file_format_max='Barracuda'; -select @@global.innodb_file_format_max; -@@global.innodb_file_format_max -Barracuda -select * from information_schema.global_variables where variable_name='innodb_file_format_max'; +innodb_file_format_check ON +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_file_format_check'; VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_MAX Barracuda -select * from information_schema.session_variables where variable_name='innodb_file_format_max'; +INNODB_FILE_FORMAT_CHECK ON +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_file_format_check'; VARIABLE_NAME VARIABLE_VALUE -INNODB_FILE_FORMAT_MAX Barracuda -set session innodb_file_format_max='Salmon'; -ERROR HY000: Variable 'innodb_file_format_max' is a GLOBAL variable and should be set with SET GLOBAL -set @@session.innodb_file_format_max='Salmon'; -ERROR HY000: Variable 'innodb_file_format_max' is a GLOBAL variable and should be set with SET GLOBAL -set global innodb_file_format_max=1.1; -ERROR 42000: Incorrect argument type to variable 'innodb_file_format_max' -set global innodb_file_format_max=1e1; -ERROR 42000: Incorrect argument type to variable 'innodb_file_format_max' -set global innodb_file_format_max='Salmon'; -ERROR 42000: Variable 'innodb_file_format_max' can't be set to the value of 'Salmon' -SET @@global.innodb_file_format_max = @start_global_value; -SELECT @@global.innodb_file_format_max; -@@global.innodb_file_format_max -Antelope +INNODB_FILE_FORMAT_CHECK ON +SET @@global.innodb_file_format_check='Off'; +ERROR HY000: Variable 'innodb_file_format_check' is a read only variable +Expected error 'Read only variable' +SET @@global.innodb_file_format_check=1; +ERROR HY000: Variable 'innodb_file_format_check' is a read only variable +Expected error 'Read only variable' +SET @@global.innodb_file_format_check=0; +ERROR HY000: Variable 'innodb_file_format_check' is a read only variable +Expected error 'Read only variable' +SET @@global.innodb_file_format_check='On'; +ERROR HY000: Variable 'innodb_file_format_check' is a read only variable +Expected error 'Read only variable' +SET session innodb_large_prefix='OFF'; +ERROR HY000: Variable 'innodb_large_prefix' is a GLOBAL variable and should be set with SET GLOBAL +SET @@session.innodb_stats_on_metadata='ON'; +ERROR HY000: Variable 'innodb_stats_on_metadata' is a GLOBAL variable and should be set with SET GLOBAL +SELECT IF(@@GLOBAL.innodb_file_format_check, "ON", "OFF") = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='innodb_file_format_check'; +IF(@@GLOBAL.innodb_file_format_check, "ON", "OFF") = VARIABLE_VALUE +1 +1 Expected +SELECT COUNT(@@GLOBAL.innodb_file_format_check); +COUNT(@@GLOBAL.innodb_file_format_check) +1 +1 Expected +SELECT COUNT(VARIABLE_VALUE) +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='innodb_file_format_check'; +COUNT(VARIABLE_VALUE) +1 +1 Expected +SELECT @@innodb_file_format_check = @@GLOBAL.innodb_file_format_check; +@@innodb_file_format_check = @@GLOBAL.innodb_file_format_check +1 +1 Expected +SELECT COUNT(@@innodb_file_format_check); +COUNT(@@innodb_file_format_check) +1 +1 Expected +SELECT COUNT(@@local.innodb_file_format_check); +ERROR HY000: Variable 'innodb_file_format_check' is a GLOBAL variable +Expected error 'Variable is a GLOBAL variable' +SELECT COUNT(@@SESSION.innodb_file_format_check); +ERROR HY000: Variable 'innodb_file_format_check' is a GLOBAL variable +Expected error 'Variable is a GLOBAL variable' +SELECT COUNT(@@GLOBAL.innodb_file_format_check); +COUNT(@@GLOBAL.innodb_file_format_check) +1 +1 Expected +SELECT innodb_file_format_check = @@SESSION.innodb_file_format_check; +ERROR 42S22: Unknown column 'innodb_file_format_check' in 'field list' +Expected error 'Readonly variable' diff --git a/mysql-test/suite/sys_vars/r/innodb_file_format_max_basic.result b/mysql-test/suite/sys_vars/r/innodb_file_format_max_basic.result new file mode 100644 index 00000000000..32b2262c091 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_file_format_max_basic.result @@ -0,0 +1,65 @@ +SET @start_global_value = @@global.innodb_file_format_max; +SELECT @start_global_value; +@start_global_value +Antelope +Valid values are 'Antelope' and 'Barracuda' +SELECT @@global.innodb_file_format_max in ('Antelope', 'Barracuda'); +@@global.innodb_file_format_max in ('Antelope', 'Barracuda') +1 +SELECT @@global.innodb_file_format_max; +@@global.innodb_file_format_max +Antelope +SELECT @@session.innodb_file_format_max; +ERROR HY000: Variable 'innodb_file_format_max' is a GLOBAL variable +SHOW global variables LIKE 'innodb_file_format_max'; +Variable_name Value +innodb_file_format_max Antelope +SHOW session variables LIKE 'innodb_file_format_max'; +Variable_name Value +innodb_file_format_max Antelope +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_file_format_max'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_FILE_FORMAT_MAX Antelope +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_file_format_max'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_FILE_FORMAT_MAX Antelope +SET global innodb_file_format_max='Antelope'; +SELECT @@global.innodb_file_format_max; +@@global.innodb_file_format_max +Antelope +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_file_format_max'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_FILE_FORMAT_MAX Antelope +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_file_format_max'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_FILE_FORMAT_MAX Antelope +SET @@global.innodb_file_format_max='Barracuda'; +SELECT @@global.innodb_file_format_max; +@@global.innodb_file_format_max +Barracuda +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_file_format_max'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_FILE_FORMAT_MAX Barracuda +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_file_format_max'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_FILE_FORMAT_MAX Barracuda +SET session innodb_file_format_max='Salmon'; +ERROR HY000: Variable 'innodb_file_format_max' is a GLOBAL variable and should be set with SET GLOBAL +SET @@session.innodb_file_format_max='Salmon'; +ERROR HY000: Variable 'innodb_file_format_max' is a GLOBAL variable and should be set with SET GLOBAL +SET global innodb_file_format_max=1.1; +ERROR 42000: Incorrect argument type to variable 'innodb_file_format_max' +SET global innodb_file_format_max=1e1; +ERROR 42000: Incorrect argument type to variable 'innodb_file_format_max' +SET global innodb_file_format_max='Salmon'; +ERROR 42000: Variable 'innodb_file_format_max' can't be set to the value of 'Salmon' +SET @@global.innodb_file_format_max = @start_global_value; +SELECT @@global.innodb_file_format_max; +@@global.innodb_file_format_max +Antelope diff --git a/mysql-test/suite/sys_vars/r/innodb_rollback_segments_basic.result b/mysql-test/suite/sys_vars/r/innodb_rollback_segments_basic.result new file mode 100644 index 00000000000..a8d392eee38 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_rollback_segments_basic.result @@ -0,0 +1,64 @@ +SET @start_global_value = @@global.innodb_rollback_segments; +SELECT @start_global_value; +@start_global_value +128 +Valid values are zero or above +SELECT @@global.innodb_rollback_segments >=0; +@@global.innodb_rollback_segments >=0 +1 +SELECT @@global.innodb_rollback_segments <=128; +@@global.innodb_rollback_segments <=128 +1 +SELECT @@global.innodb_rollback_segments; +@@global.innodb_rollback_segments +128 +SELECT @@session.innodb_rollback_segments; +ERROR HY000: Variable 'innodb_rollback_segments' is a GLOBAL variable +SHOW global variables LIKE 'innodb_rollback_segments'; +Variable_name Value +innodb_rollback_segments 128 +SHOW session variables LIKE 'innodb_rollback_segments'; +Variable_name Value +innodb_rollback_segments 128 +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_rollback_segments'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_ROLLBACK_SEGMENTS 128 +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_rollback_segments'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_ROLLBACK_SEGMENTS 128 +SET global innodb_rollback_segments=100; +SELECT @@global.innodb_rollback_segments; +@@global.innodb_rollback_segments +100 +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_rollback_segments'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_ROLLBACK_SEGMENTS 100 +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_rollback_segments'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_ROLLBACK_SEGMENTS 100 +SET session innodb_rollback_segments=1; +ERROR HY000: Variable 'innodb_rollback_segments' is a GLOBAL variable and should be set with SET GLOBAL +SET global innodb_rollback_segments=1.1; +ERROR 42000: Incorrect argument type to variable 'innodb_rollback_segments' +SET global innodb_rollback_segments=1e1; +ERROR 42000: Incorrect argument type to variable 'innodb_rollback_segments' +SET global innodb_rollback_segments="foo"; +ERROR 42000: Incorrect argument type to variable 'innodb_rollback_segments' +SET global innodb_rollback_segments=-7; +Warnings: +Warning 1292 Truncated incorrect innodb_rollback_segments value: '-7' +SELECT @@global.innodb_rollback_segments; +@@global.innodb_rollback_segments +1 +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_rollback_segments'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_ROLLBACK_SEGMENTS 1 +SET @@global.innodb_rollback_segments = @start_global_value; +SELECT @@global.innodb_rollback_segments; +@@global.innodb_rollback_segments +128 diff --git a/mysql-test/suite/sys_vars/r/innodb_stats_method_basic.result b/mysql-test/suite/sys_vars/r/innodb_stats_method_basic.result new file mode 100644 index 00000000000..6599ca9edb6 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_stats_method_basic.result @@ -0,0 +1,83 @@ +SET @start_global_value = @@global.innodb_stats_method; +SELECT @start_global_value; +@start_global_value +nulls_equal +Valid values are 'nulls_equal', 'nulls_unequal', 'nulls_ignored' +SELECT @@global.innodb_stats_method in ('nulls_equal', 'nulls_unequal', +'nulls_ignored'); +@@global.innodb_stats_method in ('nulls_equal', 'nulls_unequal', +'nulls_ignored') +1 +SELECT @@global.innodb_stats_method; +@@global.innodb_stats_method +nulls_equal +SELECT @@session.innodb_stats_method; +ERROR HY000: Variable 'innodb_stats_method' is a GLOBAL variable +SHOW global variables LIKE 'innodb_stats_method'; +Variable_name Value +innodb_stats_method nulls_equal +SHOW session variables LIKE 'innodb_stats_method'; +Variable_name Value +innodb_stats_method nulls_equal +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_stats_method'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_STATS_METHOD nulls_equal +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_stats_method'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_STATS_METHOD nulls_equal +SET global innodb_stats_method='nulls_equal'; +SELECT @@global.innodb_stats_method; +@@global.innodb_stats_method +nulls_equal +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_stats_method'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_STATS_METHOD nulls_equal +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_stats_method'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_STATS_METHOD nulls_equal +SET @@global.innodb_stats_method='nulls_unequal'; +SELECT @@global.innodb_stats_method; +@@global.innodb_stats_method +nulls_unequal +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_stats_method'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_STATS_METHOD nulls_unequal +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_stats_method'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_STATS_METHOD nulls_unequal +SET global innodb_stats_method=2; +SELECT @@global.innodb_stats_method; +@@global.innodb_stats_method +nulls_ignored +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_stats_method'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_STATS_METHOD nulls_ignored +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_stats_method'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_STATS_METHOD nulls_ignored +SET session innodb_stats_method='nulls_equal'; +ERROR HY000: Variable 'innodb_stats_method' is a GLOBAL variable and should be set with SET GLOBAL +SET @@session.innodb_stats_method='nulls_ignored'; +ERROR HY000: Variable 'innodb_stats_method' is a GLOBAL variable and should be set with SET GLOBAL +SET global innodb_stats_method=1.1; +ERROR 42000: Incorrect argument type to variable 'innodb_stats_method' +SET global innodb_stats_method=4; +ERROR 42000: Variable 'innodb_stats_method' can't be set to the value of '4' +SET global innodb_stats_method=-2; +ERROR 42000: Variable 'innodb_stats_method' can't be set to the value of '-2' +SET global innodb_stats_method=1e1; +ERROR 42000: Incorrect argument type to variable 'innodb_stats_method' +SET global innodb_stats_method='some'; +ERROR 42000: Variable 'innodb_stats_method' can't be set to the value of 'some' +SET @@global.innodb_stats_method = @start_global_value; +SELECT @@global.innodb_stats_method; +@@global.innodb_stats_method +nulls_equal diff --git a/mysql-test/suite/sys_vars/t/innodb_file_format_check_basic.test b/mysql-test/suite/sys_vars/t/innodb_file_format_check_basic.test index cbf25af2442..f9f61b9380c 100644 --- a/mysql-test/suite/sys_vars/t/innodb_file_format_check_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_file_format_check_basic.test @@ -1,55 +1,95 @@ - - -# 2010-01-25 - Added # +# 2011-08-02 - Added +# + --source include/not_embedded.inc --source include/have_innodb.inc -SET @start_global_value = @@global.innodb_file_format_max; +SET @start_global_value = @@global.innodb_file_format_check; SELECT @start_global_value; # # exists as global only # ---echo Valid values are 'Antelope' and 'Barracuda' -select @@global.innodb_file_format_max in ('Antelope', 'Barracuda'); -select @@global.innodb_file_format_max; +--echo Valid values are 'ON' and 'OFF' +SELECT @@global.innodb_file_format_check in (0, 1); +SELECT @@global.innodb_file_format_check; + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.innodb_file_format_check; +SHOW global variables LIKE 'innodb_file_format_check'; +SHOW session variables LIKE 'innodb_file_format_check'; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_file_format_check'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_file_format_check'; + +# +# show that it's read only +# + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.innodb_file_format_check='Off'; +--echo Expected error 'Read only variable' + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.innodb_file_format_check=1; +--echo Expected error 'Read only variable' + --error ER_INCORRECT_GLOBAL_LOCAL_VAR -select @@session.innodb_file_format_max; -show global variables like 'innodb_file_format_max'; -show session variables like 'innodb_file_format_max'; -select * from information_schema.global_variables where variable_name='innodb_file_format_max'; -select * from information_schema.session_variables where variable_name='innodb_file_format_max'; - -# -# show that it's writable -# -set global innodb_file_format_max='Antelope'; -select @@global.innodb_file_format_max; -select * from information_schema.global_variables where variable_name='innodb_file_format_max'; -select * from information_schema.session_variables where variable_name='innodb_file_format_max'; -set @@global.innodb_file_format_max='Barracuda'; -select @@global.innodb_file_format_max; -select * from information_schema.global_variables where variable_name='innodb_file_format_max'; -select * from information_schema.session_variables where variable_name='innodb_file_format_max'; +SET @@global.innodb_file_format_check=0; +--echo Expected error 'Read only variable' + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET @@global.innodb_file_format_check='On'; +--echo Expected error 'Read only variable' + --error ER_GLOBAL_VARIABLE -set session innodb_file_format_max='Salmon'; +SET session innodb_large_prefix='OFF'; --error ER_GLOBAL_VARIABLE -set @@session.innodb_file_format_max='Salmon'; +SET @@session.innodb_stats_on_metadata='ON'; # -# incorrect types +# Check if the value in GLOBAL Table matches value in variable # ---error ER_WRONG_TYPE_FOR_VAR -set global innodb_file_format_max=1.1; ---error ER_WRONG_TYPE_FOR_VAR -set global innodb_file_format_max=1e1; ---error ER_WRONG_VALUE_FOR_VAR -set global innodb_file_format_max='Salmon'; + +SELECT IF(@@GLOBAL.innodb_file_format_check, "ON", "OFF") = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='innodb_file_format_check'; +--echo 1 Expected + +SELECT COUNT(@@GLOBAL.innodb_file_format_check); +--echo 1 Expected + +SELECT COUNT(VARIABLE_VALUE) +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='innodb_file_format_check'; +--echo 1 Expected # -# Cleanup +# Check if accessing variable with and without GLOBAL point to same variable # +SELECT @@innodb_file_format_check = @@GLOBAL.innodb_file_format_check; +--echo 1 Expected + +# +# Check if innodb_doublewrite can be accessed with and without @@ sign +# + +SELECT COUNT(@@innodb_file_format_check); +--echo 1 Expected + +--Error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT COUNT(@@local.innodb_file_format_check); +--echo Expected error 'Variable is a GLOBAL variable' + +--Error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT COUNT(@@SESSION.innodb_file_format_check); +--echo Expected error 'Variable is a GLOBAL variable' + +SELECT COUNT(@@GLOBAL.innodb_file_format_check); +--echo 1 Expected -SET @@global.innodb_file_format_max = @start_global_value; -SELECT @@global.innodb_file_format_max; +--Error ER_BAD_FIELD_ERROR +SELECT innodb_file_format_check = @@SESSION.innodb_file_format_check; +--echo Expected error 'Readonly variable' diff --git a/mysql-test/suite/sys_vars/t/innodb_file_format_max_basic.test b/mysql-test/suite/sys_vars/t/innodb_file_format_max_basic.test new file mode 100644 index 00000000000..c2cb4cb47bb --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_file_format_max_basic.test @@ -0,0 +1,60 @@ +# +# 2011-08-02 - Added +# +--source include/not_embedded.inc +--source include/have_innodb.inc + +SET @start_global_value = @@global.innodb_file_format_max; +SELECT @start_global_value; + +# +# exists as global only +# +--echo Valid values are 'Antelope' and 'Barracuda' +SELECT @@global.innodb_file_format_max in ('Antelope', 'Barracuda'); +SELECT @@global.innodb_file_format_max; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.innodb_file_format_max; +SHOW global variables LIKE 'innodb_file_format_max'; +SHOW session variables LIKE 'innodb_file_format_max'; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_file_format_max'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_file_format_max'; + +# +# show that it's writable +# +SET global innodb_file_format_max='Antelope'; +SELECT @@global.innodb_file_format_max; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_file_format_max'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_file_format_max'; +SET @@global.innodb_file_format_max='Barracuda'; +SELECT @@global.innodb_file_format_max; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_file_format_max'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_file_format_max'; +--error ER_GLOBAL_VARIABLE +SET session innodb_file_format_max='Salmon'; +--error ER_GLOBAL_VARIABLE +SET @@session.innodb_file_format_max='Salmon'; + +# +# incorrect types +# +--error ER_WRONG_TYPE_FOR_VAR +SET global innodb_file_format_max=1.1; +--error ER_WRONG_TYPE_FOR_VAR +SET global innodb_file_format_max=1e1; +--error ER_WRONG_VALUE_FOR_VAR +SET global innodb_file_format_max='Salmon'; + +# +# Cleanup +# + +SET @@global.innodb_file_format_max = @start_global_value; +SELECT @@global.innodb_file_format_max; diff --git a/mysql-test/suite/sys_vars/t/innodb_rollback_segments_basic.test b/mysql-test/suite/sys_vars/t/innodb_rollback_segments_basic.test new file mode 100644 index 00000000000..9f0b70a528f --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_rollback_segments_basic.test @@ -0,0 +1,58 @@ +# +# 2011-08-01 Added +# + +--source include/have_innodb.inc + +SET @start_global_value = @@global.innodb_rollback_segments; +SELECT @start_global_value; + +# +# exists as global only +# +--echo Valid values are zero or above +SELECT @@global.innodb_rollback_segments >=0; +SELECT @@global.innodb_rollback_segments <=128; +SELECT @@global.innodb_rollback_segments; + +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.innodb_rollback_segments; +SHOW global variables LIKE 'innodb_rollback_segments'; +SHOW session variables LIKE 'innodb_rollback_segments'; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_rollback_segments'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_rollback_segments'; + +# +# show that it's writable +# +SET global innodb_rollback_segments=100; +SELECT @@global.innodb_rollback_segments; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_rollback_segments'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_rollback_segments'; +--error ER_GLOBAL_VARIABLE +SET session innodb_rollback_segments=1; + +# +# incorrect types +# +--error ER_WRONG_TYPE_FOR_VAR +SET global innodb_rollback_segments=1.1; +--error ER_WRONG_TYPE_FOR_VAR +SET global innodb_rollback_segments=1e1; +--error ER_WRONG_TYPE_FOR_VAR +SET global innodb_rollback_segments="foo"; +SET global innodb_rollback_segments=-7; +SELECT @@global.innodb_rollback_segments; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_rollback_segments'; + +# +# cleanup +# + +SET @@global.innodb_rollback_segments = @start_global_value; +SELECT @@global.innodb_rollback_segments; diff --git a/mysql-test/suite/sys_vars/t/innodb_stats_method_basic.test b/mysql-test/suite/sys_vars/t/innodb_stats_method_basic.test new file mode 100644 index 00000000000..f01574c3683 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_stats_method_basic.test @@ -0,0 +1,72 @@ +# +# 2011-08-05 - Added +# + +--source include/have_innodb.inc + +SET @start_global_value = @@global.innodb_stats_method; +SELECT @start_global_value; + +# +# exists as global only +# +--echo Valid values are 'nulls_equal', 'nulls_unequal', 'nulls_ignored' +SELECT @@global.innodb_stats_method in ('nulls_equal', 'nulls_unequal', +'nulls_ignored'); +SELECT @@global.innodb_stats_method; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.innodb_stats_method; +SHOW global variables LIKE 'innodb_stats_method'; +SHOW session variables LIKE 'innodb_stats_method'; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_stats_method'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_stats_method'; + +# +# show that it's writable +# +SET global innodb_stats_method='nulls_equal'; +SELECT @@global.innodb_stats_method; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_stats_method'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_stats_method'; +SET @@global.innodb_stats_method='nulls_unequal'; +SELECT @@global.innodb_stats_method; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_stats_method'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_stats_method'; +SET global innodb_stats_method=2; +SELECT @@global.innodb_stats_method; +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_stats_method'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_stats_method'; + +--error ER_GLOBAL_VARIABLE +SET session innodb_stats_method='nulls_equal'; +--error ER_GLOBAL_VARIABLE +SET @@session.innodb_stats_method='nulls_ignored'; + +# +# incorrect types +# +--error ER_WRONG_TYPE_FOR_VAR +SET global innodb_stats_method=1.1; +--error ER_WRONG_VALUE_FOR_VAR +SET global innodb_stats_method=4; +--error ER_WRONG_VALUE_FOR_VAR +SET global innodb_stats_method=-2; +--error ER_WRONG_TYPE_FOR_VAR +SET global innodb_stats_method=1e1; +--error ER_WRONG_VALUE_FOR_VAR +SET global innodb_stats_method='some'; + +# +# Cleanup +# + +SET @@global.innodb_stats_method = @start_global_value; +SELECT @@global.innodb_stats_method; diff --git a/mysql-test/t/mysql_plugin-master.opt b/mysql-test/t/mysql_plugin-master.opt new file mode 100644 index 00000000000..061ca907902 --- /dev/null +++ b/mysql-test/t/mysql_plugin-master.opt @@ -0,0 +1 @@ +--plugin-dir=$DAEMONEXAMPLE_DIR diff --git a/mysql-test/t/mysql_plugin.test b/mysql-test/t/mysql_plugin.test new file mode 100644 index 00000000000..9e71db1a451 --- /dev/null +++ b/mysql-test/t/mysql_plugin.test @@ -0,0 +1,318 @@ +# +# Test mysql_plugin tool +# +# This test contains test cases for testing the mysql_plugin client with +# the daemon_example plugin. Test cases include tests for: +# +# - successful enable/disable +# - incorrect paths +# - missing paths/options +# +# Implementation Notes +# +# The mysql_plugin tool now accepts --mysqld the path to mysqld server. The +# mysqld path is extracted from MYSQLD_BOOTSTRAP_CMD line. We also extract +# the path of MYSQLD_BASEDIR (where mysql exists) and use it for the errmsg +# file. The directories differ between Windows and Unix but the Perl script +# included below will pick as per platform. +# +# The test is also designed to issue the --skip directive if the location of +# the mysqld, my_print_defaults, or daemon_example.ini files cannot be found. +# + +--source include/not_embedded.inc + +# Add the datadir, basedir, plugin_dir to the bootstrap command +let $MYSQLD_DATADIR= `select @@datadir`; +let $MYSQL_BASEDIR= `select @@basedir`; +let $MYSQL_ERRMSG_BASEDIR=`select @@lc_messages_dir`; +let $PLUGIN_DIR=`select @@plugin_dir`; + +--disable_abort_on_error + +# Perl script to extract the location of the basedir from environment +# variables. This is needed to ensure the test will run on the PB machines +# designed to test release as well as debug builds. It also checks for the +# location of the my_print_defaults and daemon_example.ini files. + +perl; +use File::Basename; + my ($mysqld)= split " ", $ENV{MYSQLD_BOOTSTRAP_CMD}; + my $mysqld_basedir=dirname($mysqld); + my $my_print_defaults= $ENV{MYSQL_MY_PRINT_DEFAULTS}; + my $my_print_defaults_basedir=dirname($my_print_defaults); + my $daemonexample_ini= "$ENV{DAEMONEXAMPLE_DIR}/daemon_example.ini"; + my $plugindir_ini= "$ENV{PLUGIN_DIR}/daemon_example.ini"; + my $notfound= ""; + open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/mysqld.inc") or die; + print FILE "let \$MYSQLD= $mysqld;\n"; + print FILE "let \$MYSQLD_BASEDIR= $mysqld_basedir;\n"; + print FILE "let \$MYSQL_MY_PRINT_DEFAULTS_BASEDIR= $my_print_defaults_basedir;\n"; + if ((!-e $daemonexample_ini) || (!-r $daemonexample_ini)) + { + print FILE "let \$DAEMONEXAMPLE_DIR= $not_found;\n"; + } + if ((!-e $plugindir_ini) || (!-r $plugindir_ini)) + { + print FILE "let \$PLUGIN_DIR= $not_found;\n"; + } + close FILE; +EOF + + +source $MYSQL_TMP_DIR/mysqld.inc; +remove_file $MYSQL_TMP_DIR/mysqld.inc; + +# The mysql_plugin tool expects a directory structure like in the installed +# mysql version, so errmsg.sys will be copied to "basedir/share", we create +# and remove this structure. + +--mkdir $MYSQLD_BASEDIR/share +--mkdir $MYSQLD_BASEDIR/share/mysql +--copy_file $MYSQL_ERRMSG_BASEDIR/english/errmsg.sys $MYSQLD_BASEDIR/share/errmsg.sys +--copy_file $MYSQL_ERRMSG_BASEDIR/english/errmsg.sys $MYSQLD_BASEDIR/share/mysql/errmsg.sys + +# The mysql_plugin tool now accepts --my-print-defaults which points to the +# executable my_print_defaults.exe we can get this path from the variable +# $MYSQL_MY_PRINT_DEFAULTS. + +# Check for my_print_defaults location. Skip if not found. +if ($MYSQL_MY_PRINT_DEFAULTS_BASEDIR == '') +{ + --skip Test requires known location of my_print_defaults executable. +} + +# Check for mysqld location. Skip if not found. +if ($MYSQLD == '') +{ + --skip Test requires known location of mysqld executable. +} + +# Check for daemon_example.ini location. Skip if not found in either +# the plugin_dir path or the daemon_example_dir path. +if ($PLUGIN_DIR == '') +{ + if ($DAEMONEXAMPLE_DIR == '') + { + --skip Test requires known location of daemon_example.ini file. + } + let $PLUGIN_DIR = $DAEMONEXAMPLE_DIR; +} + +# Build client command for reuse. + +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN --datadir=$MYSQLD_DATADIR --basedir=$MYSQLD_BASEDIR --plugin-dir=$PLUGIN_DIR --mysqld=$MYSQLD_BASEDIR --my-print-defaults=$MYSQL_MY_PRINT_DEFAULTS_BASEDIR; + +--echo # +--echo # Ensure the plugin isn't loaded. +--echo # +SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name; + +--echo # +--echo # Enable the plugin... +--echo # +let $expect_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; +# MTR will remove this file later, but this might be too late. +--error 0,1 +--remove_file $expect_file +--write_file $expect_file +wait +EOF +--shutdown_server 10 +--source include/wait_until_disconnected.inc + +# +# Enable the plugin +# +--exec $MYSQL_PLUGIN_CMD ENABLE daemon_example + +# +# Ensure enabling an enabled plugin doesn't fail +--exec $MYSQL_PLUGIN_CMD ENABLE daemon_example + +# +# Restart the server +# +--append_file $expect_file +restart +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc + +--echo # +--echo # Ensure the plugin is now loaded. +--echo # +--replace_regex /\.dll/.so/ +SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name; + +--echo # +--echo # Disable the plugin... +--echo # +# MTR will remove this file later, but this might be too late. +--error 0,1 +--remove_file $expect_file +--write_file $expect_file +wait +EOF +--shutdown_server 10 +--source include/wait_until_disconnected.inc + +# +# Disable the plugin +# +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example + +# +# Restart the server +# +--append_file $expect_file +restart +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc + +--echo # +--echo # Ensure the plugin isn't loaded. +--echo # +SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name; + +# +# Stop the server for error conditions +# +let $expect_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect; +# MTR will remove this file later, but this might be too late. +--error 0,1 +--remove_file $expect_file +--write_file $expect_file +wait +EOF +--shutdown_server 10 +--source include/wait_until_disconnected.inc + +--echo # +--echo # Attempt to load non-existant plugin +--echo # +--error 1,2,256 +--exec $MYSQL_PLUGIN_CMD DISABLE NOT_THERE_AT_ALL 2>&1 + +--echo # +--echo # Attempt to use non-existant plugin.ini file +--echo # +--error 1,2,7,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example --plugin-ini=/NOT/THERE/pi.ini 2>&1 + +--echo # +--echo # Attempt to omit the plugin +--echo # +--error 1,2,256 +--exec $MYSQL_PLUGIN_CMD DISABLE 2>&1 + +--echo # +--echo # Attempt to omit DISABLE|ENABLE +--echo # +--error 1,2,256 +--exec $MYSQL_PLUGIN_CMD daemon_example 2>&1 + +--echo # +--echo # Attempt to use bad paths - datadir +--echo # +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN -n --datadir=/data_not_there/ --basedir=$MYSQL_BASEDIR --plugin-dir=$PLUGIN_DIR --mysqld=$MYSQLD_BASEDIR --my-print-defaults=$MYSQL_MY_PRINT_DEFAULTS_BASEDIR; +--error 1,2,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example 2>&1 + +--echo # +--echo # Attempt to use bad paths - basedir +--echo # +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=/basedir_not_there/ --plugin-dir=$PLUGIN_DIR --mysqld=$MYSQLD_BASEDIR --my-print-defaults=$MYSQL_MY_PRINT_DEFAULTS_BASEDIR; +--error 1,2,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example 2>&1 + +--echo # +--echo # Attempt to use bad paths - plugin_dir +--echo # +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=$MYSQL_BASEDIR --plugin-dir=/plugin_not_there/ --mysqld=$MYSQLD_BASEDIR --my-print-defaults=$MYSQL_MY_PRINT_DEFAULTS_BASEDIR; +--error 1,2,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example 2>&1 + +--echo # +--echo # Attempt to use bad paths - mysqld +--echo # +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=$MYSQL_BASEDIR --plugin-dir=$PLUGIN_DIR --mysqld=/mysqld_not_there/ --my-print-defaults=$MYSQL_MY_PRINT_DEFAULTS_BASEDIR; +--error 1,2,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example 2>&1 + +--echo # +--echo # Attempt to use bad paths - my_print_defaults +--echo # +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=$MYSQL_BASEDIR --plugin-dir=$PLUGIN_DIR --mysqld=$MYSQLD_BASEDIR --my-print-defaults=/my_print_defaults_not_there/; +--error 1,2,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example 2>&1 + + +--echo # +--echo # Missing library +--echo # +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=$MYSQL_BASEDIR --plugin-dir=$PLUGIN_DIR --plugin-ini=$MYSQL_TEST_DIR/include/daemon_example_bad_soname.ini --mysqld=$MYSQLD_BASEDIR --my-print-defaults=$MYSQL_MY_PRINT_DEFAULTS_BASEDIR; +--error 1,2,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example 2>&1 + +--echo # +--echo # Bad format for config file +--echo # +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=$MYSQL_BASEDIR --plugin-dir=$PLUGIN_DIR --plugin-ini=$MYSQL_TEST_DIR/include/daemon_example_bad_format.ini --mysqld=$MYSQLD_BASEDIR --my-print-defaults=$MYSQL_MY_PRINT_DEFAULTS_BASEDIR; +--error 1,2,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example 2>&1 + +--echo # +--echo # Missing base_dir option +--echo # +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --plugin-dir=$PLUGIN_DIR --mysqld=$MYSQLD_BASEDIR --my-print-defaults=$MYSQL_MY_PRINT_DEFAULTS_BASEDIR; +--error 1,2,139,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example 2>&1 + +--echo # +--echo # Missing data_dir option +--echo # +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN -n --basedir=$MYSQL_BASEDIR --plugin-dir=$PLUGIN_DIR --mysqld=$MYSQLD_BASEDIR --my-print-defaults=$MYSQL_MY_PRINT_DEFAULTS_BASEDIR; +--error 1,2,139,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example 2>&1 + +--echo # +--echo # Missing plugin_dir option +--echo # +let $MYSQL_PLUGIN_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQL_DATADIR --basedir=$MYSQL_BASEDIR --mysqld=$MYSQLD_BASEDIR --my-print-defaults=$MYSQL_MY_PRINT_DEFAULTS_BASEDIR; +--error 1,2,139,256 +--exec $MYSQL_PLUGIN_CMD DISABLE daemon_example 2>&1 + +--echo # +--echo # Show the help. +--echo # +replace_result $MYSQL_PLUGIN mysql_plugin; +--replace_regex /Ver [0-9.]+ Distrib [0-9.]+/Ver V.V.VV Distrib XX.XX.XX/ +--exec $MYSQL_PLUGIN --help + +replace_result $MYSQL_PLUGIN mysql_plugin; +--replace_regex /Ver [0-9.]+ Distrib [0-9.]+/Ver V.V.VV Distrib XX.XX.XX/ +--exec $MYSQL_PLUGIN --version + +# +# Restart the server +# +--append_file $expect_file +restart +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc + +# +# Cleanup +# MTR will remove this file later, but this might be too late. +--error 0,1 +--remove_file $expect_file + +# Cleanup the share folder in the binary path. +--remove_file $MYSQLD_BASEDIR/share/errmsg.sys +--rmdir $MYSQLD_BASEDIR/share/mysql +--rmdir $MYSQLD_BASEDIR/share + +--enable_abort_on_error diff --git a/plugin/daemon_example/CMakeLists.txt b/plugin/daemon_example/CMakeLists.txt index 60aa00687ba..1623c3025d7 100644 --- a/plugin/daemon_example/CMakeLists.txt +++ b/plugin/daemon_example/CMakeLists.txt @@ -15,3 +15,5 @@ MYSQL_ADD_PLUGIN(daemon_example daemon_example.cc MODULE_ONLY MODULE_OUTPUT_NAME "libdaemon_example") + +INSTALL(FILES daemon_example.ini DESTINATION ${INSTALL_PLUGINDIR}) diff --git a/plugin/daemon_example/daemon_example.ini b/plugin/daemon_example/daemon_example.ini new file mode 100644 index 00000000000..7c6d4d1456e --- /dev/null +++ b/plugin/daemon_example/daemon_example.ini @@ -0,0 +1,9 @@ +# +# Plugin configuration file. Place the following on a separate line: +# +# library binary file name (without .so or .dll) +# component_name +# [component_name] - additional components in plugin +# +libdaemon_example +daemon_example diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 9bbf846e706..b32a7dd836c 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -1000,6 +1000,7 @@ echo "=====" >> $STATUS_HISTORY %attr(755, root, root) %{_bindir}/mysql_setpermission %attr(755, root, root) %{_bindir}/mysql_tzinfo_to_sql %attr(755, root, root) %{_bindir}/mysql_upgrade +%attr(755, root, root) %{_bindir}/mysql_plugin %attr(755, root, root) %{_bindir}/mysql_zap %attr(755, root, root) %{_bindir}/mysqlbug %attr(755, root, root) %{_bindir}/mysqld_multi @@ -1015,6 +1016,7 @@ echo "=====" >> $STATUS_HISTORY %attr(755, root, root) %{_sbindir}/mysqld %attr(755, root, root) %{_sbindir}/mysqld-debug %attr(755, root, root) %{_sbindir}/rcmysql +%attr(755, root, root) %{_libdir}/mysql/plugin/daemon_example.ini %if %{WITH_TCMALLOC} %attr(755, root, root) %{_libdir}/mysql/%{malloc_lib_target} @@ -1113,6 +1115,10 @@ echo "=====" >> $STATUS_HISTORY - Source plugin library files list from cmake-generated file. +* Mon Jul 25 2011 Chuck Bell <chuck.bell@oracle.com> + +- Added the mysql_plugin client - enables or disables plugins. + * Thu Jul 21 2011 Sunanda Menon <sunanda.menon@oracle.com> - Fix bug#12561297: Added the MySQL embedded binary |