Commit 17d544d3 authored by Otto Kekäläinen's avatar Otto Kekäläinen
Browse files

Imported Upstream version 10.0.18

parent 18012179
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.cc text
*.cpp text
*.h text
*.test text
# Declare files that will always have LF line endings on checkout.
*.result text eol=lf
storage/connect/mysql-test/connect/std_data/*.txt text eol=lf
storage/connect/mysql-test/connect/std_data/*.dat text eol=lf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
*.c diff=cpp
*.h diff=cpp
*.cc diff=cpp
......
*-t
*.a
*.ctest
*.o
*.reject
*.so
*.so.*
*.spec
*~
*.bak
.*.swp
*.ninja
.ninja_*
......@@ -15,6 +11,8 @@ errmsg.sys
typescript
CMakeCache.txt
CMakeFiles/
MakeFile
install_manifest.txt
CPackConfig.cmake
CPackSourceConfig.cmake
CTestTestfile.cmake
......@@ -138,6 +136,8 @@ sql-bench/test-select
sql-bench/test-table-elimination
sql-bench/test-transactions
sql-bench/test-wisconsin
sql/lex_token.h
sql/gen_lex_token
sql/gen_lex_hash
sql/lex_hash.h
sql/mysql_tzinfo_to_sql
......@@ -166,8 +166,6 @@ storage/myisam/myisamlog
storage/myisam/myisampack
storage/myisam/rt_test
storage/myisam/sp_test
storage/perfschema/gen_pfs_lex_token
storage/perfschema/pfs_lex_token.h
storage/tokudb/ft-index/buildheader/db.h
storage/tokudb/ft-index/buildheader/make_tdb
storage/tokudb/ft-index/buildheader/runcat.sh
......@@ -193,10 +191,6 @@ storage/tokudb/ft-index/tools/tokudb_dump
storage/tokudb/ft-index/tools/tokudb_gen
storage/tokudb/ft-index/tools/tokudb_load
storage/tokudb/ft-index/tools/tokuftdump
storage/tokudb/ft-index/ft/ftverify
storage/tokudb/ft-index/ft/tdb-recover
storage/tokudb/ft-index/ft/tdb_logprint
storage/tokudb/ft-index/ft/tokuftdump
storage/tokudb/ft-index/xz/
support-files/MySQL-shared-compat.spec
support-files/binary-configure
......@@ -230,3 +224,228 @@ storage/mroonga/vendor/groonga/src/grnslap
storage/mroonga/vendor/groonga/src/groonga
storage/mroonga/vendor/groonga/src/groonga-benchmark
storage/mroonga/vendor/groonga/src/suggest/groonga-suggest-create-dataset
storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result
storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result
# C and C++
# Compiled Object files
*.slo
*.o
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Compiled Static libraries
*.lib
*.a
*.la
*.lai
*.lo
# Compiled Dynamic libraries
*.so
*.so.*
*.dylib
*.dll
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
*.sln
*.vcproj
*.vcproj.*
*.vcproj.*.*
*.vcproj.*.*.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Roslyn cache directories
*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# If using the old MSBuild-Integrated Package Restore, uncomment this:
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
# sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
......@@ -443,7 +443,7 @@ ADD_SUBDIRECTORY(packaging/solaris)
IF(NOT CMAKE_CROSSCOMPILING)
SET(EXPORTED comp_err comp_sql factorial)
IF(NOT WITHOUT_SERVER)
SET(EXPORTED ${EXPORTED} gen_lex_hash gen_pfs_lex_token)
SET(EXPORTED ${EXPORTED} gen_lex_hash gen_lex_token)
ENDIF()
# minimal target to build only binaries for export
ADD_CUSTOM_TARGET(import_executables DEPENDS ${EXPORTED})
......
commit: 5c66abf0b0de6d632f85a57c841f80d28a7e0337
date: 2015-02-25 16:34:33 +0100
build-date: 2015-02-25 16:41:06 +0100
short: 5c66abf
commit: 5c833689ac98991ea85a1a50565e2b1a6abe6c1f
date: 2015-05-06 12:41:21 +0200
build-date: 2015-05-06 12:49:07 +0200
short: 5c83368
branch: HEAD
MySQL source 10.0.17
MySQL source 10.0.18
MYSQL_VERSION_MAJOR=10
MYSQL_VERSION_MINOR=0
MYSQL_VERSION_PATCH=17
MYSQL_VERSION_PATCH=18
/*
Copyright (c) 2006, 2013, Oracle and/or its affiliates.
Copyright (c) 2010, 2013, Monty Program Ab.
Copyright (c) 2010, 2015, MariaDB
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
......@@ -36,6 +36,8 @@
# endif
#endif
static int phase = 0;
static int phases_total = 6;
static char mysql_path[FN_REFLEN];
static char mysqlcheck_path[FN_REFLEN];
......@@ -45,6 +47,8 @@ static my_bool opt_not_used, opt_silent;
static uint my_end_arg= 0;
static char *opt_user= (char*)"root";
static my_bool upgrade_from_mysql;
static DYNAMIC_STRING ds_args;
static DYNAMIC_STRING conn_args;
......@@ -206,12 +210,12 @@ static void die(const char *fmt, ...)
}
static int verbose(const char *fmt, ...)
static void verbose(const char *fmt, ...)
{
va_list args;
if (opt_silent)
return 0;
return;
/* Print the verbose message */
va_start(args, fmt);
......@@ -222,7 +226,6 @@ static int verbose(const char *fmt, ...)
fflush(stdout);
}
va_end(args);
return 0;
}
......@@ -740,10 +743,21 @@ static void print_conn_args(const char *tool_name)
in the server using "mysqlcheck --check-upgrade .."
*/
static int run_mysqlcheck_upgrade(const char *arg1, const char *arg2)
static int run_mysqlcheck_upgrade(my_bool mysql_db_only)
{
const char *what= mysql_db_only ? "mysql database" : "tables";
const char *arg1= mysql_db_only ? "--databases" : "--all-databases";
const char *arg2= mysql_db_only ? "mysql" : "--skip-database=mysql";
int retch;
if (opt_systables_only && !mysql_db_only)
{
verbose("Phase %d/%d: Checking and upgrading %s... Skipped",
++phase, phases_total, what);
return 0;
}
verbose("Phase %d/%d: Checking and upgrading %s", ++phase, phases_total, what);
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
retch= run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
"--no-defaults",
ds_args.str,
......@@ -757,12 +771,77 @@ static int run_mysqlcheck_upgrade(const char *arg1, const char *arg2)
arg1, arg2,
"2>&1",
NULL);
return retch;
}
#define EVENTS_STRUCT_LEN 7000
static my_bool is_mysql()
{
my_bool ret= TRUE;
DYNAMIC_STRING ds_events_struct;
if (init_dynamic_string(&ds_events_struct, NULL,
EVENTS_STRUCT_LEN, EVENTS_STRUCT_LEN))
die("Out of memory");
if (run_query("show create table mysql.event",
&ds_events_struct, FALSE) ||
strstr(ds_events_struct.str, "IGNORE_BAD_TABLE_OPTIONS") != NULL)
ret= FALSE;
else
verbose("MySQL upgrade detected");
dynstr_free(&ds_events_struct);
return(ret);
}
static int run_mysqlcheck_views(void)
{
const char *upgrade_views="--process-views=YES";
if (upgrade_from_mysql)
{
/*
this has to ignore opt_systables_only, because upgrade_from_mysql
is determined by analyzing systables. if we honor opt_systables_only
here, views won't be fixed by subsequent mysql_upgrade runs
*/
upgrade_views="--process-views=UPGRADE_FROM_MYSQL";
verbose("Phase %d/%d: Fixing views from mysql", ++phase, phases_total);
}
else if (opt_systables_only)
{
verbose("Phase %d/%d: Fixing views... Skipped", ++phase, phases_total);
return 0;
}
else
verbose("Phase %d/%d: Fixing views", ++phase, phases_total);
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
"--no-defaults",
ds_args.str,
"--all-databases", "--repair",
upgrade_views,
"--skip-process-tables",
opt_verbose ? "--verbose": "",
opt_silent ? "--silent": "",
opt_write_binlog ? "--write-binlog" : "--skip-write-binlog",
"2>&1",
NULL);
}
static int run_mysqlcheck_fixnames(void)
{
verbose("Phase 3/5: Fixing table and database names");
if (opt_systables_only)
{
verbose("Phase %d/%d: Fixing table and database names ... Skipped",
++phase, phases_total);
return 0;
}
verbose("Phase %d/%d: Fixing table and database names",
++phase, phases_total);
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
......@@ -850,6 +929,9 @@ static int run_sql_fix_privilege_tables(void)
if (init_dynamic_string(&ds_result, "", 512, 512))
die("Out of memory");
verbose("Phase %d/%d: Running 'mysql_fix_privilege_tables'",
++phase, phases_total);
/*
Individual queries can not be executed independently by invoking
a forked mysql client, because the script uses session variables
......@@ -1019,23 +1101,19 @@ int main(int argc, char **argv)
if (opt_version_check && check_version_match())
die("Upgrade failed");
upgrade_from_mysql= is_mysql();
/*
Run "mysqlcheck" and "mysql_fix_privilege_tables.sql"
*/
verbose("Phase 1/5: Checking mysql database");
if (run_mysqlcheck_upgrade("--databases", "mysql"))
die("Upgrade failed" );
verbose("Phase 2/5: Running 'mysql_fix_privilege_tables'...");
if (run_sql_fix_privilege_tables())
if (run_mysqlcheck_upgrade(TRUE) ||
run_mysqlcheck_views() ||
run_sql_fix_privilege_tables() ||
run_mysqlcheck_fixnames() ||
run_mysqlcheck_upgrade(FALSE))
die("Upgrade failed" );
if (!opt_systables_only &&
(run_mysqlcheck_fixnames() ||
verbose("Phase 4/5: Checking and upgrading tables") ||
run_mysqlcheck_upgrade("--all-databases","--skip-database=mysql")))
die("Upgrade failed" );
verbose("Phase 5/5: Running 'FLUSH PRIVILEGES'...");
verbose("Phase %d/%d: Running 'FLUSH PRIVILEGES'", ++phase, phases_total);
if (run_query("FLUSH PRIVILEGES", NULL, TRUE))
die("Upgrade failed" );
......@@ -1044,6 +1122,8 @@ int main(int argc, char **argv)
/* Create a file indicating upgrade has been performed */
create_mysql_upgrade_info_file();
DBUG_ASSERT(phase == phases_total);
free_used_memory();
my_end(my_end_arg);
exit(0);
......
/*
Copyright (c) 2000, 2014, Oracle and/or its affiliates.
Copyright (c) 2010, 2014, Monty Program Ab.
Copyright (c) 2010, 2015, MariaDB
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
......@@ -1249,6 +1249,9 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
static char **mask_password(int argc, char ***argv)
{
char **temp_argv;
if (!argc)
return NULL;
temp_argv= (char **)(my_malloc(sizeof(char *) * argc, MYF(MY_WME)));
argc--;
while (argc > 0)
......
/*
Copyright (c) 2001, 2013, Oracle and/or its affiliates.
Copyright (c) 2010, 2013, Monty Program Ab.
Copyright (c) 2010, 2015, MariaDB
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
......@@ -18,7 +18,7 @@
/* By Jani Tolonen, 2001-04-20, MySQL Development Team */
#define CHECK_VERSION "2.7.3-MariaDB"
#define CHECK_VERSION "2.7.4-MariaDB"
#include "client_priv.h"
#include <m_ctype.h>
......@@ -42,7 +42,8 @@ static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0,
opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0,
tty_password= 0, opt_frm= 0, debug_info_flag= 0, debug_check_flag= 0,
opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0;
opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0,
opt_do_tables= 1;
static my_bool opt_write_binlog= 1, opt_flush_tables= 0;
static uint verbose = 0, opt_mysql_port=0;
static int my_end_arg;
......@@ -56,7 +57,17 @@ DYNAMIC_ARRAY tables4repair, tables4rebuild, alter_table_cmds;
static char *shared_memory_base_name=0;
static uint opt_protocol=0;
enum operations { DO_CHECK=1, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE };
enum operations { DO_CHECK=1, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_FIX_NAMES };
const char *operation_name[]=
{
"???", "check", "repair", "analyze", "optimize", "fix names"
};
typedef enum { DO_VIEWS_NO, DO_VIEWS_YES, DO_VIEWS_FROM_MYSQL } enum_do_views;
const char *do_views_opts[]= {"NO", "YES", "UPGRADE_FROM_MYSQL", NullS};
TYPELIB do_views_typelib= { array_elements(do_views_opts) - 1, "",
do_views_opts, NULL };
static ulong opt_do_views= DO_VIEWS_NO;
static struct my_option my_long_options[] =
{
......@@ -200,6 +211,14 @@ static struct my_option my_long_options[] =
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},
{"process-views", 0,
"Perform the requested operation (check or repair) on views. "
"One of: NO, YES (correct the checksum, if necessary, add the "
"mariadb-version field), UPGRADE_FROM_MYSQL (same as YES and toggle "
"the algorithm MERGE<->TEMPTABLE.", &opt_do_views, &opt_do_views,
&do_views_typelib, GET_ENUM, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"process-tables", 0, "Perform the requested operation on tables.",
&opt_do_tables, &opt_do_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
......@@ -216,7 +235,7 @@ static int process_selected_tables(char *db, char **table_names, int tables);
static int process_all_tables_in_db(char *database);
static int process_one_db(char *database);
static int use_db(char *database);
static int handle_request_for_tables(char *tables, uint length);
static int handle_request_for_tables(char *tables, size_t length, my_bool view);
static int dbConnect(char *host, char *user,char *passwd);
static void dbDisconnect(char *host);
static void DBerror(MYSQL *mysql, const char *when);
......@@ -294,11 +313,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
what_to_do = DO_OPTIMIZE;
break;
case OPT_FIX_DB_NAMES:
what_to_do= DO_UPGRADE;
what_to_do= DO_FIX_NAMES;
opt_databases= 1;
break;
case OPT_FIX_TABLE_NAMES:
what_to_do= DO_UPGRADE;
what_to_do= DO_FIX_NAMES;
break;
case 'p':
if (argument == disabled_my_option)
......@@ -339,7 +358,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'v':
verbose++;
break;
case 'V': print_version(); exit(0);
case 'V':
print_version(); exit(0);
break;
case OPT_MYSQL_PROTOCOL:
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
opt->name);
......@@ -348,7 +369,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (orig_what_to_do && (what_to_do != orig_what_to_do))
{
fprintf(stderr, "Error: %s doesn't support multiple contradicting commands.\n",
fprintf(stderr, "Error: %s doesn't support multiple contradicting commands.\n",
my_progname);
DBUG_RETURN(1);
}
......@@ -370,6 +391,12 @@ static int get_options(int *argc, char ***argv)
if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
exit(ho_error);
if (what_to_do == DO_REPAIR && !opt_do_views && !opt_do_tables)
{
fprintf(stderr, "Error: Nothing to repair when both "
"--process-tables=NO and --process-views=NO\n");
exit(1);
}
if (!what_to_do)
{
size_t pnlen= strlen(my_progname);
......@@ -386,6 +413,13 @@ static int get_options(int *argc, char ***argv)
what_to_do = DO_CHECK;
}
if (opt_do_views && what_to_do != DO_REPAIR && what_to_do != DO_CHECK)
{
fprintf(stderr, "Error: %s doesn't support %s for views.\n",
my_progname, operation_name[what_to_do]);
exit(1);
}
/*
If there's no --default-character-set option given with
--fix-table-name or --fix-db-name set the default character set to "utf8".
......@@ -470,13 +504,41 @@ static int process_databases(char **db_names)
} /* process_databases */
/* returns: -1 for error, 1 for view, 0 for table */
static int is_view(const char *table)
{
char query[1024];
MYSQL_RES *res;
MYSQL_FIELD *field;
int view;
DBUG_ENTER("is_view");
my_snprintf(query, sizeof(query), "SHOW CREATE TABLE %`s", table);
if (mysql_query(sock, query))
{
fprintf(stderr, "Failed to %s\n", query);
fprintf(stderr, "Error: %s\n", mysql_error(sock));
my_free(query);
DBUG_RETURN(-1);
}
res= mysql_store_result(sock);
field= mysql_fetch_field(res);
view= (strcmp(field->name,"View") == 0) ? 1 : 0;
mysql_free_result(res);
DBUG_RETURN(view);
}
static int process_selected_tables(char *db, char **table_names, int tables)
{
int view;
char *table;
uint table_len;
DBUG_ENTER("process_selected_tables");
if (use_db(db))
DBUG_RETURN(1);
if (opt_all_in_1 && what_to_do != DO_UPGRADE)
if (opt_all_in_1 && what_to_do != DO_FIX_NAMES)
{
/*
We need table list in form `a`, `b`, `c`
......@@ -487,6 +549,15 @@ static int process_selected_tables(char *db, char **table_names, int tables)
size_t tot_length= 0;
int i= 0;
if (opt_do_tables && opt_do_views)
{
fprintf(stderr, "Error: %s cannot process both tables and views "
"in one command (--process-tables=YES "
"--process-views=YES --all-in-1).\n",
my_progname);
DBUG_RETURN(1);
}
for (i = 0; i < tables; i++)
tot_length+= fixed_name_length(*(table_names + i)) + 2;
......@@ -501,12 +572,20 @@ static int process_selected_tables(char *db, char **table_names, int tables)
*end++= ',';
}
*--end = 0;
handle_request_for_tables(table_names_comma_sep + 1, (uint) (tot_length - 1));
handle_request_for_tables(table_names_comma_sep + 1, tot_length - 1,
opt_do_views != 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));
{
table= *table_names;
table_len= fixed_name_length(*table_names);
view= is_view(table);
if (view < 0)
continue;
handle_request_for_tables(table, table_len, (view == 1));
}
DBUG_RETURN(0);
} /* process_selected_tables */
......@@ -553,6 +632,7 @@ static int process_all_tables_in_db(char *database)
MYSQL_ROW row;
uint num_columns;
my_bool system_database= 0;
my_bool view= FALSE;
DBUG_ENTER("process_all_tables_in_db");
if (use_db(database))
......@@ -571,7 +651,7 @@ static int process_all_tables_in_db(char *database)
num_columns= mysql_num_fields(res);
if (opt_all_in_1 && what_to_do != DO_UPGRADE)
if (opt_all_in_1 && what_to_do != DO_FIX_NAMES)
{
/*
We need table list in form `a`, `b`, `c`
......@@ -582,8 +662,17 @@ static int process_all_tables_in_db(char *database)
char *tables, *end;
uint tot_length = 0;
char *views, *views_end;
uint tot_views_length = 0;
while ((row = mysql_fetch_row(res)))
tot_length+= fixed_name_length(row[0]) + 2;
{
if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0) &&
opt_do_views)
tot_views_length+= fixed_name_length(row[0]) + 2;
else if (opt_do_tables)
tot_length+= fixed_name_length(row[0]) + 2;
}
mysql_data_seek(res, 0);
if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
......@@ -591,32 +680,62 @@ static int process_all_tables_in_db(char *database)
mysql_free_result(res);
DBUG_RETURN(1);
}
for (end = tables + 1; (row = mysql_fetch_row(res)) ;)
if (!(views=(char *) my_malloc(sizeof(char)*tot_views_length+4, MYF(MY_WME))))
{
if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
continue;
my_free(tables);
mysql_free_result(res);
DBUG_RETURN(1);
}
end= fix_table_name(end, row[0]);
*end++= ',';
for (end = tables + 1, views_end= views + 1; (row = mysql_fetch_row(res)) ;)
{
if ((num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
{
if (!opt_do_views)
continue;
views_end= fix_table_name(views_end, row[0]);
*views_end++= ',';
}
else
{
if (!opt_do_tables)
continue;
end= fix_table_name(end, row[0]);
*end++= ',';
}
}
*--end = 0;
*--views_end = 0;
if (tot_length)
handle_request_for_tables(tables + 1, tot_length - 1);
handle_request_for_tables(tables + 1, tot_length - 1, FALSE);
if (tot_views_length)
handle_request_for_tables(views + 1, tot_views_length - 1, TRUE);
my_free(tables);
my_free(views);
}
else
{
while ((row = mysql_fetch_row(res)))
{
/* Skip views if we don't perform renaming. */
if ((what_to_do != DO_UPGRADE) && (num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
continue;
if ((what_to_do != DO_FIX_NAMES) && (num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
{
if (!opt_do_views)
continue;
view= TRUE;
}
else
{
if (!opt_do_tables)
continue;
view= FALSE;
}
if (system_database &&
(!strcmp(row[0], "general_log") ||
!strcmp(row[0], "slow_log")))
continue; /* Skip logging tables */
handle_request_for_tables(row[0], fixed_name_length(row[0]));
handle_request_for_tables(row[0], fixed_name_length(row[0]), view);
}
}
mysql_free_result(res);
......@@ -704,7 +823,7 @@ static int process_one_db(char *database)
if (verbose)
puts(database);
if (what_to_do == DO_UPGRADE)
if (what_to_do == DO_FIX_NAMES)
{
int rc= 0;
if (opt_fix_db_names && !strncmp(database,"#mysql50#", 9))
......@@ -743,15 +862,17 @@ static int disable_binlog()
return run_query(stmt, 0);
}
static int handle_request_for_tables(char *tables, uint length)
static int handle_request_for_tables(char *tables, size_t length, my_bool view)
{
char *query, *end, options[100], message[100];
char table_name_buff[NAME_CHAR_LEN*2*2+1], *table_name;
uint query_length= 0;
const char *op = 0;
const char *tab_view;
DBUG_ENTER("handle_request_for_tables");
options[0] = 0;
tab_view= view ? " VIEW " : " TABLE ";
end = options;
switch (what_to_do) {
case DO_CHECK:
......@@ -764,18 +885,28 @@ static int handle_request_for_tables(char *tables, uint length)
if (opt_upgrade) end = strmov(end, " FOR UPGRADE");
break;
case DO_REPAIR:
op= (opt_write_binlog) ? "REPAIR" : "REPAIR NO_WRITE_TO_BINLOG";
if (opt_quick) end = strmov(end, " QUICK");
if (opt_extended) end = strmov(end, " EXTENDED");
if (opt_frm) end = strmov(end, " USE_FRM");
op= opt_write_binlog ? "REPAIR" : "REPAIR NO_WRITE_TO_BINLOG";
if (view)
{
if (opt_do_views == DO_VIEWS_FROM_MYSQL) end = strmov(end, " FROM MYSQL");
}
else
{
if (opt_quick) end = strmov(end, " QUICK");
if (opt_extended) end = strmov(end, " EXTENDED");
if (opt_frm) end = strmov(end, " USE_FRM");
}
break;
case DO_ANALYZE:
DBUG_ASSERT(!view);
op= (opt_write_binlog) ? "ANALYZE" : "ANALYZE NO_WRITE_TO_BINLOG";
break;
case DO_OPTIMIZE:
DBUG_ASSERT(!view);
op= (opt_write_binlog) ? "OPTIMIZE" : "OPTIMIZE NO_WRITE_TO_BINLOG";
break;
case DO_UPGRADE:
case DO_FIX_NAMES:
DBUG_ASSERT(!view);
DBUG_RETURN(fix_table_storage_name(tables));
}
......@@ -784,14 +915,15 @@ static int handle_request_for_tables(char *tables, uint length)
if (opt_all_in_1)
{
/* No backticks here as we added them before */
query_length= sprintf(query, "%s TABLE %s %s", op, tables, options);
query_length= sprintf(query, "%s%s%s %s", op,
tab_view, tables, options);
table_name= tables;
}
else
{
char *ptr, *org;
org= ptr= strmov(strmov(query, op), " TABLE ");
org= ptr= strmov(strmov(query, op), tab_view);
ptr= fix_table_name(ptr, tables);
strmake(table_name_buff, org, MY_MIN((int) sizeof(table_name_buff)-1,
(int) (ptr - org)));
......@@ -803,7 +935,7 @@ static int handle_request_for_tables(char *tables, uint length)
puts(query);
if (mysql_real_query(sock, query, query_length))
{
sprintf(message, "when executing '%s TABLE ... %s'", op, options);
sprintf(message, "when executing '%s%s... %s'", op, tab_view, options);
DBerror(sock, message);
my_free(query);
DBUG_RETURN(1);
......@@ -1064,7 +1196,7 @@ int main(int argc, char **argv)
for (i = 0; i < tables4repair.elements ; i++)
{
char *name= (char*) dynamic_array_ptr(&tables4repair, i);
handle_request_for_tables(name, fixed_name_length(name));
handle_request_for_tables(name, fixed_name_length(name), FALSE);
}
for (i = 0; i < tables4rebuild.elements ; i++)
rebuild_table((char*) dynamic_array_ptr(&tables4rebuild, i));
......
......@@ -5912,6 +5912,8 @@ void do_connect(struct st_command *command)
my_bool con_ssl= 0, con_compress= 0;
my_bool con_pipe= 0;
my_bool con_shm __attribute__ ((unused))= 0;
int read_timeout= 0;
int write_timeout= 0;
struct st_connection* con_slot;
static DYNAMIC_STRING ds_connection_name;
......@@ -6008,6 +6010,16 @@ void do_connect(struct st_command *command)
con_pipe= 1;
else if (length == 3 && !strncmp(con_options, "SHM", 3))
con_shm= 1;
else if (strncasecmp(con_options, "read_timeout=",
sizeof("read_timeout=")-1) == 0)
{
read_timeout= atoi(con_options + sizeof("read_timeout=")-1);
}
else if (strncasecmp(con_options, "write_timeout=",
sizeof("write_timeout=")-1) == 0)
{
write_timeout= atoi(con_options + sizeof("write_timeout=")-1);
}
else
die("Illegal option to connect: %.*s",
(int) (end - con_options), con_options);
......@@ -6080,6 +6092,18 @@ void do_connect(struct st_command *command)
if (opt_protocol)
mysql_options(con_slot->mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
if (read_timeout)
{
mysql_options(con_slot->mysql, MYSQL_OPT_READ_TIMEOUT,
(char*)&read_timeout);
}
if (write_timeout)
{
mysql_options(con_slot->mysql, MYSQL_OPT_WRITE_TIMEOUT,
(char*)&write_timeout);
}
#ifdef HAVE_SMEM
if (con_shm)
{
......
# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2014, 2015, 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
......@@ -18,11 +18,11 @@
MACRO(ADD_COMPILE_FLAGS)
SET(FILES "")
SET(FLAGS "")
SET(COMPILE_FLAGS)
SET(COMPILE_FLAGS_SEEN)
FOREACH(ARG ${ARGV})
IF(ARG STREQUAL "COMPILE_FLAGS")
SET(COMPILE_FLAGS "COMPILE_FLAGS")
ELSEIF(COMPILE_FLAGS)
SET(COMPILE_FLAGS_SEEN 1)
ELSEIF(COMPILE_FLAGS_SEEN)
LIST(APPEND FLAGS ${ARG})
ELSE()
LIST(APPEND FILES ${ARG})
......
......@@ -34,6 +34,7 @@
#define TT_USEFRM 1
#define TT_FOR_UPGRADE 2
#define TT_FROM_MYSQL 4
/* Bits set in out_flag */
#define O_NEW_DATA 2
......
/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2010, 2015, 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
......@@ -41,7 +41,6 @@
do {} while (0)
#endif
#ifdef HAVE_PSI_STATEMENT_INTERFACE
#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE
#define MYSQL_DIGEST_START(LOCKER) \
inline_mysql_digest_start(LOCKER)
......@@ -49,17 +48,13 @@
#define MYSQL_DIGEST_START(LOCKER) \
NULL
#endif
#else
#define MYSQL_DIGEST_START(LOCKER) \
NULL
#endif
#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE
#define MYSQL_ADD_TOKEN(LOCKER, T, Y) \
inline_mysql_add_token(LOCKER, T, Y)
#define MYSQL_DIGEST_END(LOCKER, DIGEST) \
inline_mysql_digest_end(LOCKER, DIGEST)
#else
#define MYSQL_ADD_TOKEN(LOCKER, T, Y) \
NULL
#define MYSQL_DIGEST_END(LOCKER, DIGEST) \
do {} while (0)
#endif
#ifdef HAVE_PSI_STATEMENT_INTERFACE
......@@ -132,20 +127,17 @@ inline_mysql_digest_start(PSI_statement_locker *locker)
PSI_digest_locker* digest_locker= NULL;
if (likely(locker != NULL))
digest_locker= PSI_STATEMENT_CALL(digest_start)(locker);
digest_locker= PSI_DIGEST_CALL(digest_start)(locker);
return digest_locker;
}
#endif
#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE
static inline struct PSI_digest_locker *
inline_mysql_add_token(PSI_digest_locker *locker, uint token,
void *yylval)
static inline void
inline_mysql_digest_end(PSI_digest_locker *locker, const sql_digest_storage *digest)
{
if (likely(locker != NULL))
locker= PSI_STATEMENT_CALL(digest_add_token)(locker, token,
(OPAQUE_LEX_YYSTYPE*)yylval);
return locker;
PSI_DIGEST_CALL(digest_end)(locker, digest);
}
#endif
......
/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2008, 2015, 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
......@@ -43,18 +43,8 @@
C_MODE_START
struct TABLE_SHARE;
/*
There are 3 known bison parsers in the server:
- (1) the SQL parser itself, sql/sql_yacc.yy
- (2) storage/innobase/fts/fts0pars.y
- (3) storage/innobase/pars/pars0grm.y
What is instrumented here are the tokens from the SQL query text (1),
to make digests.
Now, to avoid name pollution and conflicts with different YYSTYPE definitions,
an opaque structure is used here.
The real type to use when invoking the digest api is LEX_YYSTYPE.
*/
struct OPAQUE_LEX_YYSTYPE;
struct sql_digest_storage;
/**
@file mysql/psi/psi.h
......@@ -952,29 +942,6 @@ struct PSI_table_locker_state_v1
uint m_index;
};
#define PSI_MAX_DIGEST_STORAGE_SIZE 1024
/**
Structure to store token count/array for a statement
on which digest is to be calculated.
*/
struct PSI_digest_storage
{
my_bool m_full;
int m_byte_count;
/** Character set number. */
uint m_charset_number;
unsigned char m_token_array[PSI_MAX_DIGEST_STORAGE_SIZE];
};
typedef struct PSI_digest_storage PSI_digest_storage;
struct PSI_digest_locker_state
{
int m_last_id_index;
PSI_digest_storage m_digest_storage;
};
typedef struct PSI_digest_locker_state PSI_digest_locker_state;
/* Duplicate of NAME_LEN, to avoid dependency on mysql_com.h */
#define PSI_SCHEMA_NAME_LEN (64 * 3)
......@@ -1037,7 +1004,7 @@ struct PSI_statement_locker_state_v1
/** Metric, number of sort scans. */
ulong m_sort_scan;
/** Statement digest. */
PSI_digest_locker_state m_digest_state;
const struct sql_digest_storage *m_digest;
/** Current schema name. */
char m_schema_name[PSI_SCHEMA_NAME_LEN];
/** Length in bytes of @c m_schema_name. */
......@@ -1902,11 +1869,15 @@ typedef void (*set_socket_info_v1_t)(struct PSI_socket *socket,
*/
typedef void (*set_socket_thread_owner_v1_t)(struct PSI_socket *socket);
/**
Get a digest locker for the current statement.
@param locker a statement locker for the running thread
*/
typedef struct PSI_digest_locker * (*digest_start_v1_t)
(struct PSI_statement_locker *locker);
typedef struct PSI_digest_locker* (*digest_add_token_v1_t)
(struct PSI_digest_locker *locker, uint token, struct OPAQUE_LEX_YYSTYPE *yylval);
typedef void (*digest_end_v1_t)
(struct PSI_digest_locker *locker, const struct sql_digest_storage *digest);
/**
Stores an array of connection attributes
......@@ -2118,8 +2089,8 @@ struct PSI_v1
set_socket_thread_owner_v1_t set_socket_thread_owner;
/** @sa digest_start_v1_t. */
digest_start_v1_t digest_start;
/** @sa digest_add_token_v1_t. */
digest_add_token_v1_t digest_add_token;
/** @sa digest_end_v1_t. */
digest_end_v1_t digest_end;
/** @sa set_thread_connect_attrs_v1_t. */
set_thread_connect_attrs_v1_t set_thread_connect_attrs;
};
......@@ -2414,6 +2385,10 @@ extern MYSQL_PLUGIN_IMPORT PSI *PSI_server;
#define PSI_STATEMENT_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_DIGEST_CALL
#define PSI_DIGEST_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_TABLE_CALL
#define PSI_TABLE_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
......
#include "mysql/psi/psi.h"
C_MODE_START
struct TABLE_SHARE;
struct OPAQUE_LEX_YYSTYPE;
struct sql_digest_storage;
struct PSI_mutex;
typedef struct PSI_mutex PSI_mutex;
struct PSI_rwlock;
......
#include "mysql/psi/psi.h"
C_MODE_START
struct TABLE_SHARE;
struct OPAQUE_LEX_YYSTYPE;
struct sql_digest_storage;
struct PSI_mutex;
typedef struct PSI_mutex PSI_mutex;
struct PSI_rwlock;
......@@ -241,20 +241,6 @@ struct PSI_table_locker_state_v1
void *m_wait;
uint m_index;
};
struct PSI_digest_storage
{
my_bool m_full;
int m_byte_count;
uint m_charset_number;
unsigned char m_token_array[1024];
};
typedef struct PSI_digest_storage PSI_digest_storage;
struct PSI_digest_locker_state
{
int m_last_id_index;
PSI_digest_storage m_digest_storage;
};
typedef struct PSI_digest_locker_state PSI_digest_locker_state;
struct PSI_statement_locker_state_v1
{
my_bool m_discarded;
......@@ -280,7 +266,7 @@ struct PSI_statement_locker_state_v1
ulong m_sort_range;
ulong m_sort_rows;
ulong m_sort_scan;
PSI_digest_locker_state m_digest_state;
const struct sql_digest_storage *m_digest;
char m_schema_name[(64 * 3)];
uint m_schema_name_length;
};
......@@ -508,8 +494,8 @@ typedef void (*set_socket_info_v1_t)(struct PSI_socket *socket,
typedef void (*set_socket_thread_owner_v1_t)(struct PSI_socket *socket);
typedef struct PSI_digest_locker * (*digest_start_v1_t)
(struct PSI_statement_locker *locker);
typedef struct PSI_digest_locker* (*digest_add_token_v1_t)
(struct PSI_digest_locker *locker, uint token, struct OPAQUE_LEX_YYSTYPE *yylval);
typedef void (*digest_end_v1_t)
(struct PSI_digest_locker *locker, const struct sql_digest_storage *digest);
typedef int (*set_thread_connect_attrs_v1_t)(const char *buffer, uint length,
const void *from_cs);
struct PSI_v1
......@@ -610,7 +596,7 @@ struct PSI_v1
set_socket_info_v1_t set_socket_info;
set_socket_thread_owner_v1_t set_socket_thread_owner;
digest_start_v1_t digest_start;
digest_add_token_v1_t digest_add_token;
digest_end_v1_t digest_end;
set_thread_connect_attrs_v1_t set_thread_connect_attrs;
};
typedef struct PSI_v1 PSI;
......
#include "mysql/psi/psi.h"
C_MODE_START
struct TABLE_SHARE;
struct OPAQUE_LEX_YYSTYPE;
struct sql_digest_storage;
struct PSI_mutex;
typedef struct PSI_mutex PSI_mutex;
struct PSI_rwlock;
......
......@@ -150,7 +150,7 @@ enum enum_ssl_init_error
{
SSL_INITERR_NOERROR= 0, SSL_INITERR_CERT, SSL_INITERR_KEY,
SSL_INITERR_NOMATCH, SSL_INITERR_BAD_PATHS, SSL_INITERR_CIPHERS,
SSL_INITERR_MEMFAIL, SSL_INITERR_LASTERR
SSL_INITERR_MEMFAIL, SSL_INITERR_DH, SSL_INITERR_LASTERR
};
const char* sslGetErrString(enum enum_ssl_init_error err);
......
......@@ -44,7 +44,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql-common/client_plugin.c ../sql-common/mysql_async.c
../sql/password.c ../sql/discover.cc ../sql/derror.cc
../sql/field.cc ../sql/field_conv.cc
../sql/filesort_utils.cc
../sql/filesort_utils.cc ../sql/sql_digest.cc
../sql/filesort.cc ../sql/gstream.cc ../sql/slave.cc
../sql/signal_handler.cc
../sql/handler.cc ../sql/hash_filo.cc ../sql/hostname.cc
......
......@@ -101,6 +101,35 @@ if (!$annotate)
{
--echo # No Annotate_rows events should appear below
}
--echo ########################################################################
--echo # Ensure that a replication failure doesn't segfault - MDEV-7864
--echo ########################################################################
DELETE FROM t3 WHERE a=2;
connection master;
INSERT INTO t5 (a) SELECT a.a*10000+b.a*1000+c.a*100+d.a*10 FROM t5 a, t5 b, t5 c, t5 d;
INSERT INTO t3 (a) SELECT a FROM t5 WHERE a > 10;
DELETE t3 FROM t3 INNER JOIN t5 ON t3.a=t5.a;
connection slave;
--echo ---- Wait until slave stops with an error ----
# Wait until the slave tries to run the query, fails with key not
# found error, and stops the SQL thread.
let $slave_sql_errno= 1032; # Can't find record
source include/wait_for_slave_sql_error.inc;
--let $err= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1)
--replace_regex /end_log_pos [0-9]+/end_log_pos END_LOG_POS/
--disable_query_log
--eval SELECT "$err" as 'Last_SQL_Error (expected "Delete_rows_v1 event on table test1.t3; Can\'t find record in \'t3\'" error)'
--enable_query_log
call mtr.add_suppression("Slave: Can't find record in 't3' Error_code: 1032");
SET GLOBAL sql_slave_skip_counter=1;
START SLAVE;
connection master;
sync_slave_with_master;
--echo ########################################################################
FLUSH LOGS;
......
#
# Compare a field to an utf8 string literal with illegal byte sequences
#
--echo #
--echo # Start of ctype_utf8_ilseq.inc
--echo #
--eval CREATE TABLE t1 ENGINE=$ENGINE AS SELECT REPEAT(' ', 60) AS ch LIMIT 0;
ALTER TABLE t1
ADD id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
ADD KEY(ch);
SHOW CREATE TABLE t1;
INSERT INTO t1 (ch) VALUES ('admin'),('admin1');
SELECT ch FROM t1 WHERE ch='admin𝌆';
SELECT ch FROM t1 IGNORE KEY (ch) WHERE ch='admin𝌆';
SELECT ch FROM t1 FORCE KEY (ch) WHERE ch='admin𝌆';
DELETE FROM t1;
INSERT INTO t1 (ch) VALUES ('a'), ('a?'), ('a??'), ('a???'), ('a????');
INSERT INTO t1 (ch) VALUES ('ab'),('a?b'),('a??b'),('a???b'),('a????b');
INSERT INTO t1 (ch) VALUES ('az'),('a?z'),('a??z'),('a???z'),('a????z');
INSERT INTO t1 (ch) VALUES ('z');
# LATIN SMALL LETTER A + LATIN CAPITAL LETTER E WITH GRAVE
INSERT INTO t1 (ch) VALUES (_utf8 0x61D080);
# LATIN SMALL LETTER A + ARMENIAN SMALL LETTER REH
INSERT INTO t1 (ch) VALUES (_utf8 0x61D680);
SELECT ch FROM t1 IGNORE KEY (ch) WHERE ch='a𝌆' ORDER BY ch;
SELECT ch FROM t1 IGNORE KEY (ch) WHERE ch='a𝌆b' ORDER BY ch;
SELECT ch FROM t1 FORCE KEY (ch) WHERE ch='a𝌆' ORDER BY ch;
SELECT ch FROM t1 FORCE KEY (ch) WHERE ch='a𝌆b' ORDER BY ch;
SELECT ch FROM t1 IGNORE KEY (ch) WHERE ch<'a𝌆' ORDER BY ch;
SELECT ch FROM t1 IGNORE KEY (ch) WHERE ch<'a𝌆b' ORDER BY ch;
SELECT ch FROM t1 FORCE KEY (ch) WHERE ch<'a𝌆' ORDER BY ch;
SELECT ch FROM t1 FORCE KEY (ch) WHERE ch<'a𝌆b' ORDER BY ch;
SELECT ch FROM t1 IGNORE KEY (ch) WHERE ch>'a𝌆' ORDER BY ch;
SELECT ch FROM t1 IGNORE KEY (ch) WHERE ch>'a𝌆b' ORDER BY ch;
SELECT ch FROM t1 FORCE KEY (ch) WHERE ch>'a𝌆' ORDER BY ch;
SELECT ch FROM t1 FORCE KEY (ch) WHERE ch>'a𝌆b' ORDER BY ch;
ALTER TABLE t1 DROP KEY ch;
--echo # 0xD18F would be a good 2-byte character, 0xD1 is an incomplete sequence
SET @query=CONCAT('SELECT ch FROM t1 WHERE ch=''a', 0xD1,'''');
PREPARE stmt FROM @query;
EXECUTE stmt;
SET @query=CONCAT('SELECT ch FROM t1 WHERE ch=''a', 0xD1,'b''');
PREPARE stmt FROM @query;
EXECUTE stmt;
#
# Non-equality comparison currently work differently depending on collation:
#
# - utf8_general_ci falls back to memcmp() on bad byte
# - utf8_unicode_ci treats bad bytes greater than any valid character
#
# For example, these two characters:
# _utf8 0xD080 (U+00C8 LATIN CAPITAL LETTER E WITH GRAVE)
# _utf8 0xD680 (U+0580 ARMENIAN SMALL LETTER REH)
#
# will give different results (depending on collation) when compared
# to an incomplete byte sequence 0xD1 (mb2head not followed by mb2tail).
#
# For utf8_general_ci the result depends on the valid side:
# - 0xD080 is smaller than 0xD1, because 0xD0 < 0xD1
# - 0xD680 is greater than 0xD1, because 0xD6 > 0xD1
#
# For utf8_unicode_ci the result does not depend on the valid side:
# - 0xD080 is smaller than 0xD1, because 0xD1 is greater than any valid character
# - 0xD680 is smaller than 0xD1, because 0xD1 is greater than any valid character
#
# utf8_general_ci should be eventually fixed to treat bad bytes greater
# than any valid character, similar to utf8_unicode_ci.
#
SET @query=CONCAT('SELECT ch FROM t1 WHERE ch<''a', 0xD1,''' ORDER BY ch');
PREPARE stmt FROM @query;
EXECUTE stmt;
SET @query=CONCAT('SELECT ch FROM t1 WHERE ch>''a', 0xD1,''' ORDER BY ch');
PREPARE stmt FROM @query;
EXECUTE stmt;
--echo # 0xEA9A96 would be a good 3-byte character, 0xEA9A is an incomplete sequence
SET @query=CONCAT('SELECT ch FROM t1 WHERE ch=''a', 0xEA9A,''' ORDER BY ch');
PREPARE stmt FROM @query;
EXECUTE stmt;
SET @query=CONCAT('SELECT ch FROM t1 WHERE ch=''a', 0xEA9A,'b'' ORDER BY ch');
PREPARE stmt FROM @query;
EXECUTE stmt;
--echo # 0x8F is a bad byte sequence (an mb2tail without mb2head)
SET @query=CONCAT('SELECT ch FROM t1 WHERE ch=''a', 0x8F,''' ORDER BY ch');
PREPARE stmt FROM @query;
EXECUTE stmt;
SET @query=CONCAT('SELECT ch FROM t1 WHERE ch=''a', 0x8F,'b'' ORDER BY ch');
PREPARE stmt FROM @query;
EXECUTE stmt;
--echo # 0x8F8F is a bad byte sequence (an mb2tail without mb2head, two times)
SET @query=CONCAT('SELECT ch FROM t1 WHERE ch=''a', 0x8F8F,''' ORDER BY ch');
PREPARE stmt FROM @query;
EXECUTE stmt;
SET @query=CONCAT('SELECT ch FROM t1 WHERE ch=''a', 0x8F8F,'b'' ORDER BY ch');
PREPARE stmt FROM @query;
EXECUTE stmt;
DROP TABLE t1;
--echo #
--echo # End of ctype_utf8_ilseq.inc
--echo #
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment