diff options
1402 files changed, 68019 insertions, 36950 deletions
diff --git a/.gitignore b/.gitignore index 3f28c0fb66b..9c2e1d7a8c0 100644 --- a/.gitignore +++ b/.gitignore @@ -99,6 +99,7 @@ pcre/pcre_chartables.c pcre/pcregrep pcre/pcretest pcre/test*grep +plugin/auth_pam/auth_pam_tool plugin/aws_key_management/aws-sdk-cpp plugin/aws_key_management/aws_sdk_cpp plugin/aws_key_management/aws_sdk_cpp-prefix @@ -181,6 +182,7 @@ storage/maria/ma_sp_test storage/maria/ma_test1 storage/maria/ma_test2 storage/maria/ma_test3 +storage/maria/test_ma_backup storage/myisam/mi_test1 storage/myisam/mi_test2 storage/myisam/mi_test3 diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index e9bede9c746..7e6f0831423 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -122,7 +122,8 @@ get_make_parallel_flag # SSL library to use.--with-ssl will select our bundled yaSSL # implementation of SSL. --with-ssl=yes will first try system library # then the boundled one --with-ssl=system will use the system library. -SSL_LIBRARY=--with-ssl=system +# We use bundled by default as this is guaranteed to work with Galera +SSL_LIBRARY=--with-ssl if [ "x$warning_mode" = "xpedantic" ]; then warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -D_POSIX_SOURCE" @@ -194,6 +195,8 @@ base_configs="$base_configs --with-extra-charsets=complex " base_configs="$base_configs --enable-thread-safe-client " base_configs="$base_configs --with-big-tables $maintainer_mode" base_configs="$base_configs --with-plugin-aria --with-aria-tmp-tables" +# Following is to get tokudb to work +base_configs="$base_configs --with-jemalloc=NO" if test -d "$path/../cmd-line-utils/readline" then diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b172204120..5415efb66db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,14 @@ ELSE() ENDIF() PROJECT(${MYSQL_PROJECT_NAME}) +IF(CMAKE_VERSION VERSION_LESS "3.1") + IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") + ENDIF() +ELSE() + SET(CMAKE_CXX_STANDARD 11) +ENDIF() + SET(CPACK_PACKAGE_NAME "MariaDB") SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MariaDB: a very fast and robust SQL database server") SET(CPACK_PACKAGE_URL "http://mariadb.org") diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000..64af450d29f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,47 @@ +# How to contribute + +MariaDB Server has a vibrant community contributing in a wide range of areas. There are many valuable ways you can contribute to MariaDB. + +### Engage online with other community members +--- +- [MariaDB on Zulip](https://mariadb.zulipchat.com/) +- [maria-developers mailing list](http://launchpad.net/~maria-developers) +- [maria-discuss mailing list](http://launchpad.net/~maria-discuss) +- [maria-docs mailing list](http://launchpad.net/~maria-docs) +- ircs://chat.freenode.net/maria ([see the IRC page on the Knowledge Base](https://mariadb.com/kb/en/meta/irc-chat-servers-and-zulip-instance/) for help with IRC). +- The MariaDB Foundation and MariaDB Corporation have a presence on Reddit, Twitter, Facebook and Google Plus. See the [social media page](https://mariadb.com/kb/en/mariadb/social-media/). + +### Help document MariaDB +---- +- Contribute towards [documenting MariaDB Server](https://mariadb.com/kb/en/meta/writing-editing-library-articles/) and its ecosystem by adding new content or improving existing content. +- [Translate](https://mariadb.com/kb/en/meta/translating-library-articles/) existing documentation. + +### Help debug and develop MariaDB +----- +- [Report bugs](https://jira.mariadb.org/) +- Test development versions +- Write code to fix bugs or develop new features (see [Getting Started for Developers](https://mariadb.org/getting-started-for-developers)).See also [list of beginner friendly tasks](https://jira.mariadb.org/browse/MDEV-15736?jql=resolution%20%3D%20Unresolved%20AND%20labels%20%3D%20beginner-friendly%20ORDER%20BY%20updated%20DESC) +- Help with code quality control +- Participate in packaging for different Linux distributions + +### Sponsor or donate +--- +You’re very welcome to support MariaDB Server as an individual, or talk your company into joining the Foundation as a sponsoring member. See the [Sponsor page](https://mariadb.org/donate/). + +### Events, meetups and conferences +--- +- Attend an event + - [Events and Conferences page](https://mariadb.org/events/) + - [mariadb.meetup.com](http://mariadb.meetup.com/) + +### Live QA for beginner contributors +---- +MariaDB has a dedicated time each week when we answer new contributor questions live on Zulip and IRC. +From 8:00 to 10:00 UTC on Mondays, and 10:00 to 12:00 UTC on Thursdays, anyone can ask any questions they’d like, +and a live developer will be available to assist. +New contributors can ask questions any time, but we will provide immediate feedback during that interval. + +### Additional resources +---- + - [MariaDB Foundation ](https://mariadb.org/) + - [Knowledge Base](https://mariadb.com/kb/en/) diff --git a/Docs/INSTALL-BINARY b/Docs/INSTALL-BINARY index 7ff33c7051e..2bd6daaea17 100644 --- a/Docs/INSTALL-BINARY +++ b/Docs/INSTALL-BINARY @@ -1,7 +1,9 @@ MariaDB and MySQL have identical install methods. In this document we -describe how to install MariaDB; However all documentation at www.mysql.com -also applies. +describe how to install MariaDB. +The full documentation for installing MariaDB can be found at +https://mariadb.com/kb/en/library/binary-packages/ +However most documentation at www.mysql.com also applies. 2.2. Installing MariaDB from Generic Binaries on Unix/Linux @@ -33,7 +35,8 @@ also applies. If you run into problems and need to file a bug report, please report them to: http://mariadb.org/jira - See the instructions in Section 1.6, "How to Report Bugs or Problems." + See the instructions at + https://mariadb.com/kb/en/mariadb-community-bug-reporting The basic commands that you must execute to install and use a MariaDB binary distribution are: @@ -79,10 +82,9 @@ shell> useradd -g mysql mysql is protected, you must perform the installation as root.) shell> cd /usr/local - 3. Obtain a distribution file using the instructions in Section - 2.1.3, "How to Get MariaDB." For a given release, binary - distributions for all platforms are built from the same MariaDB - source distribution. + 3. Obtain a distribution file using the instructions at + https://mariadb.com/kb/en/library/where-to-download-mariadb/ + The description below describes how to install a MariaDB tar file. 4. Unpack the distribution, which creates the installation directory. Then create a symbolic link to that directory: @@ -149,8 +151,8 @@ shell> chown -R mysql data machine, you can copy support-files/mysql.server to the location where your system has its startup files. More information can be found in the support-files/mysql.server - script itself and in Section 2.13.1.2, "Starting and Stopping - MariaDB Automatically." + script itself and at + https://mariadb.com/kb/en/starting-and-stopping-mariadb-automatically. 10. You can set up new accounts using the bin/mysql_setpermission script if you install the DBI and DBD::mysql Perl modules. See Section 4.6.14, "mysql_setpermission --- Interactively Set @@ -181,8 +183,8 @@ shell> bin/mysqld_safe --user=mysql & find some information in the host_name.err file in the data directory. - More information about mysqld_safe is given in Section 4.3.2, - "mysqld_safe --- MySQL Server Startup Script." + More information about mysqld_safe can be found at + https://mariadb.com/kb/en/mysqld_safe Note diff --git a/Docs/glibc-2.2.5.patch b/Docs/glibc-2.2.5.patch deleted file mode 100644 index ef5d40b6899..00000000000 --- a/Docs/glibc-2.2.5.patch +++ /dev/null @@ -1,137 +0,0 @@ -diff -r -c --exclude='*.info*' glibc-2.2.5.org/linuxthreads/internals.h glibc-2.2.5/linuxthreads/internals.h -*** glibc-2.2.5.org/linuxthreads/internals.h Thu Nov 29 08:44:16 2001 ---- glibc-2.2.5/linuxthreads/internals.h Tue May 21 10:51:53 2002 -*************** -*** 343,349 **** - THREAD_SELF implementation is used, this must be a power of two and - a multiple of PAGE_SIZE. */ - #ifndef STACK_SIZE -! #define STACK_SIZE (2 * 1024 * 1024) - #endif - - /* The initial size of the thread stack. Must be a multiple of PAGE_SIZE. */ ---- 343,349 ---- - THREAD_SELF implementation is used, this must be a power of two and - a multiple of PAGE_SIZE. */ - #ifndef STACK_SIZE -! #define STACK_SIZE (128 * 1024) - #endif - - /* The initial size of the thread stack. Must be a multiple of PAGE_SIZE. */ -diff -r -c --exclude='*.info*' glibc-2.2.5.org/linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h glibc-2.2.5/linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h -*** glibc-2.2.5.org/linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h Thu Jun 8 21:49:49 2000 ---- glibc-2.2.5/linuxthreads/sysdeps/unix/sysv/linux/bits/local_lim.h Tue May 21 10:52:58 2002 -*************** -*** 64,70 **** - /* The number of threads per process. */ - #define _POSIX_THREAD_THREADS_MAX 64 - /* This is the value this implementation supports. */ -! #define PTHREAD_THREADS_MAX 1024 - - /* Maximum amount by which a process can descrease its asynchronous I/O - priority level. */ ---- 64,70 ---- - /* The number of threads per process. */ - #define _POSIX_THREAD_THREADS_MAX 64 - /* This is the value this implementation supports. */ -! #define PTHREAD_THREADS_MAX 4096 - - /* Maximum amount by which a process can descrease its asynchronous I/O - priority level. */ -diff -r -c --exclude='*.info*' glibc-2.2.5.org/nss/nsswitch.c glibc-2.2.5/nss/nsswitch.c -*** glibc-2.2.5.org/nss/nsswitch.c Tue Jul 17 10:21:36 2001 ---- glibc-2.2.5/nss/nsswitch.c Tue May 21 10:59:55 2002 -*************** -*** 496,501 **** ---- 496,502 ---- - { - service_user *new_service; - const char *name; -+ int name_alloc_len; - - while (isspace (line[0])) - ++line; -*************** -*** 510,522 **** - if (name == line) - return result; - - - new_service = (service_user *) malloc (sizeof (service_user) -! + (line - name + 1)); - if (new_service == NULL) - return result; - -! *((char *) __mempcpy (new_service->name, name, line - name)) = '\0'; - - /* Set default actions. */ - new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; ---- 511,534 ---- - if (name == line) - return result; - -+ name_alloc_len = line - name + 1; -+ -+ #ifdef DO_STATIC_NSS -+ if (!((name_alloc_len == 6 && strncmp(name,"files",5) == 0) || -+ (name_alloc_len == 4 && strncmp(name,"dns",3) == 0))) -+ { -+ name = (char*) "files"; -+ name_alloc_len = 6; -+ } -+ #endif - - new_service = (service_user *) malloc (sizeof (service_user) -! + name_alloc_len); - if (new_service == NULL) - return result; - -! *((char *) __mempcpy (new_service->name, name, name_alloc_len-1)) = '\0'; -! - - /* Set default actions. */ - new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; -diff -r -c --exclude='*.info*' glibc-2.2.5.org/time/Makefile glibc-2.2.5/time/Makefile -*** glibc-2.2.5.org/time/Makefile Fri Aug 10 01:59:41 2001 ---- glibc-2.2.5/time/Makefile Tue May 21 11:01:11 2002 -*************** -*** 37,44 **** - - include ../Rules - -! tz-cflags = -DTZDIR='"$(zonedir)"' \ -! -DTZDEFAULT='"$(localtime-file)"' \ - -DTZDEFRULES='"$(posixrules-file)"' - - CFLAGS-tzfile.c = $(tz-cflags) ---- 37,44 ---- - - include ../Rules - -! tz-cflags = -DTZDIR='"/usr/share/zoneinfo/"' \ -! -DTZDEFAULT='"/etc/localtime"' \ - -DTZDEFRULES='"$(posixrules-file)"' - - CFLAGS-tzfile.c = $(tz-cflags) -diff -r -c --exclude='*.info*' glibc-2.2.5.org/timezone/Makefile glibc-2.2.5/timezone/Makefile -*** glibc-2.2.5.org/timezone/Makefile Thu Aug 30 00:45:25 2001 ---- glibc-2.2.5/timezone/Makefile Tue May 21 11:01:57 2002 -*************** -*** 159,166 **** - - $(objpfx)zic: $(objpfx)scheck.o $(objpfx)ialloc.o - -! tz-cflags = -DTZDIR='"$(zonedir)"' \ -! -DTZDEFAULT='"$(localtime-file)"' \ - -DTZDEFRULES='"$(posixrules-file)"' \ - -DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone - ---- 159,166 ---- - - $(objpfx)zic: $(objpfx)scheck.o $(objpfx)ialloc.o - -! tz-cflags = -DTZDIR='"/usr/share/zoneinfo/"' \ -! -DTZDEFAULT='"/etc/localtime"' \ - -DTZDEFRULES='"$(posixrules-file)"' \ - -DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone - diff --git a/Docs/linuxthreads.txt b/Docs/linuxthreads.txt deleted file mode 100644 index 552415fe794..00000000000 --- a/Docs/linuxthreads.txt +++ /dev/null @@ -1,19 +0,0 @@ -[Note this information is obsolete] - -Notes on compiling glibc for the standard MySQL binary: - - - make sure you have gcc 2.95 and gmake 3.79 or newer - - wget ftp://ftp.gnu.org/pub/gnu/glibc/glibc-2.2.5.tar.gz - - wget ftp://ftp.gnu.org/pub/gnu/glibc/glibc-linuxthreads-2.2.5.tar.gz - - tar zxvf glibc-2.2.5.tar.gz ; cd glibc-2.2.5 ; - tar zxvf ../glibc-linuxthreads-2.2.5.tar.gz - - patch -p1 < ~/bk/mysql/Docs/glibc-2.2.5.patch - - ./configure --prefix=/usr/local/mysql-glibc --enable-static-nss \ - --disable-shared --enable-add-ons=linuxthreads --target=i386 \ - --host=i386-pc-linux-gnu - - make - - possible problems - if compiler is not properly installed, one can get - "cpp: too many input" files error - easiest way to solve - SUSE RPM for gcc - 2.95 - - surun make install - - To build the binaries, run Build-tools/Do-linux-build diff --git a/Docs/sp-imp-spec.txt b/Docs/sp-imp-spec.txt deleted file mode 100644 index 52389ea50f4..00000000000 --- a/Docs/sp-imp-spec.txt +++ /dev/null @@ -1,1100 +0,0 @@ - - Implementation specification for Stored Procedures - ================================================== - - -- How parsing and execution of queries work - - In order to execute a query, the function sql_parse.cc:mysql_parse() is - called, which in turn calls the parser (yyparse()) with an updated Lex - structure as the result. mysql_parse() then calls mysql_execute_command() - which dispatches on the command code (in Lex) to the corresponding code for - executing that particular query. - - There are three structures involved in the execution of a query which are of - interest to the stored procedure implementation: - - - Lex (mentioned above) is the "compiled" query, that is the output from - the parser and what is then interpreted to do the actual work. - It constains an enum value (sql_command) which is the query type, and - all the data collected by the parser needed for the execution (table - names, fields, values, etc). - - THD is the "run-time" state of a connection, containing all that is - needed for a particular client connection, and, among other things, the - Lex structure currently being executed. - - Item_*: During parsing, all data is translated into "items", objects of - the subclasses of "Item", such as Item_int, Item_real, Item_string, etc, - for basic datatypes, and also various more specialized Item types for - expressions to be evaluated (Item_func objects). - - -- How to fit Stored Procedure into this scheme - - - An overview of the classes and files for stored procedures - (More detailed APIs at the end of this file) - - - class sp_head (sp_head.{cc,h}) - This contains, among other things, an array of "instructions" and the - method for executing the procedure. - - - class sp_pcontext (sp_pcontext.{cc,h} - This is the parse context for the procedure. It's primarily used during - parsing to keep track of local parameters, variables and labels, but - it's also used at CALL time do find parameters mode (IN, OUT or INOUT) - and type when setting up the runtime context. - - - class sp_instr (sp_head.{cc,h}) - This is the base class for "instructions", that is, what is generated - by the parser. It turns out that we only need a minimum of 5 different - sub classes: - - sp_instr_stmt - Execute a statement. This is the "call-out" any normal SQL statement, - like a SELECT, INSERT etc. It contains the Lex structure for the - statement in question. - - sp_instr_set - Set the value of a local variable (or parameter) - - sp_instr_jump - An unconditional jump. - - sp_instr_jump_if_not - Jump if condition is not true. It turns out that the negative test is - most convenient when generating the code for the flow control - constructs. - - sp_instr_freturn - Return a value from a FUNCTION and exit. - For condition HANDLERs some special instructions are also needed, see - that section below. - - - class sp_rcontext (sp_rcontext.h) - This is the runtime context in the THD structure. - It contains an array of items, the parameters and local variables for - the currently executing stored procedure. - This means that variable value lookup is in runtime is constant time, - a simple index operation. - - - class Item_splocal (Item.{cc,h}) - This is a subclass of Item. Its sole purpose is to hide the fact that - the real Item is actually in the current frame (runtime context). - It contains the frame offset and defers all methods to the real Item - in the frame. This is what the parser generates for local variables. - - - Utility functions (sp.{cc,h}) - This contains functions for creating, dropping and finding a stored - procedure in the mysql.proc table (or the internal cache). - - - - Parsing CREATE PROCEDURE ... - - When parsing a CREATE PROCEDURE the parser first initializes the - sphead and spcont (runtime context) fields in the Lex. - The sql_command code for the result of parsing a is - SQLCOM_CREATE_PROCEDURE. - - The parsing of the parameter list and body is relatively - straight-forward: - - - Parameters: - name, type and mode (IN/OUT/INOUT) is pushed to spcont - - Declared local variables: - Same as parameters (mode is then IN) - - Local Variable references: - If an identifier is found in in spcont, an Item_splocal is created - with the variable's frame index, otherwise an Item_field or Item_ref - is created (as before). - - Statements: - The Lex in THD is replaced by a new Lex structure and the statement, - is parsed as usual. A sp_instr_stmt is created, containing the new - Lex, and added to the instructions in sphead. - Afterwards, the procedure's Lex is restored in THD. - - SET var: - Setting a local variable generates a sp_instr_set instruction, - containing the variable's frame offset, the expression (an Item), - and the type. - - Flow control: - Flow control constructs like, IF, WHILE, etc, generate a conditional - and unconditional jumps in the "obvious" way, but a few notes may - be required: - - Forward jumps: When jumping forward, the exact destination is not - known at the time of the creation of the jump instruction. The - sphead therefore contains list of instruction-label pairs for - each forward reference. When the position later is known, the - instructions in the list are updated with the correct location. - - Loop constructs have optional labels. If a loop doesn't have a - label, an anonymous label is generated to simplify the parsing. - - There are two types of CASE. The "simple" case is implemented - with an anonymous variable bound to the value to be tested. - - - - A simple example - - Parsing the procedure: - - create procedure a(s char(16)) - begin - declare x int; - set x = 3; - while x > 0 do - set x = x-1; - insert into db.tab values (x, s); - end while; - end - - would generate the following structures: - ______ - thd: | | _________ - | lex -+--->| | ___________________ - |______| | spcont -+------------------->| "s",in,char(16):0 | - | sphead -+------ |("x",in,int :1)| - |_________| | |___________________| - ____V__________________ - | m_name: "a" | - | m_defstr: "create ..."| - | m_instr: ... | - |_______________________| - - Note that the contents of the spcont is changing during the parsing, - at all times reflecting the state of the would-be runtime frame. - The m_instr is an array of instructions: - - Pos. Instruction - 0 sp_instr_set(1, '3') - 1 sp_instr_jump_if_not(5, 'x>0') - 2 sp_instr_set(1, 'x-1') - 3 sp_instr_stmt('insert into ...') - 4 sp_instr_jump(1) - 5 <end> - - Here, '3', 'x>0', etc, represent the Items or Lex for the respective - expressions or statements. - - - - Parsing CREATE FUNCTION ... - - Creating a functions is essentially the same thing as for a PROCEDURE, - with the addition that a FUNCTION has a return type and a RETURN - statement, but no OUT or INOUT parameters. - - The main difference during parsing is that we store the result type - in the sp_head. However, there are big differences when it comes to - invoking a FUNCTION. (See below.) - - - - Storing, caching, dropping... - - As seen above, the entired definition string, including the "CREATE - PROCEDURE" (or "FUNCTION") is kept. The procedure definition string is - stored in the table mysql.proc with the name and type as the key, the - type being one of the enum ("procedure","function"). - - A PROCEDURE is just stored in the mysql.proc table. A FUNCTION has an - additional requirement. They will be called in expressions with the same - syntax as UDFs, so UDFs and stored FUNCTIONs share the namespace. Thus, - we must make sure that we do not have UDFs and FUNCTIONs with the same - name (even if they are stored in different places). - - This means that we can reparse the procedure as many time as we want. - The first time, the resulting Lex is used to store the procedure in - the database (using the function sp.c:sp_create_procedure()). - - The simplest way would be to just leave it at that, and re-read the - procedure from the database each time it is called. (And in fact, that's - the way the earliest implementation will work.) - However, this is not very efficient, and we can do better. The full - implementation should work like this: - - 1) Upon creation time, parse and store the procedure. Note that we still - need to parse it to catch syntax errors, but we can't check if called - procedures exists for instance. - 2) Upon first CALL, read from the database, parse it, and cache the - resulting Lex in memory. This time we can do more error checking. - 3) Upon subsequent CALLs, use the cached Lex. - - Note that this implies that the Lex structure with its sphead must be - reentrant, that is, reusable and shareable between different threads - and calls. The runtime state for a procedure is kept in the sp_rcontext - in THD. - - The mechanisms of storing, finding, and dropping procedures are - encapsulated in the files sp.{cc,h}. - - - - CALLing a procedure - - A CALL is parsed just like any statement. The resulting Lex has the - sql_command SQLCOM_CALL, the procedure's name and the parameters are - pushed to the Lex' value_list. - - sql_parse.cc:mysql_execute_command() then uses sp.cc:sp_find() to - get the sp_head for the procedure (which may have been read from the - database or fetched from the in-memory cache) and calls the sp_head's - method execute(). - Note: It's important that substatements called by the procedure do not - do send_ok(). Fortunately, there is a flag in THD->net to disable - this during CALLs. If a substatement fails, it will however send - an error back to the client, so the CALL mechanism must return - immediately and without sending an error. - - The sp_head::execute() method works as follows: - - 1) Keep a pointer to the old runtime context in THD (if any) - 2) Create a new runtime context. The information about the required size - is in sp_head's parse time context. - 3) Push each parameter (from the CALL's Lex->value_list) to the new - context. If it's an OUT or INOUT parameter, the parameter's offset - in the caller's frame is set in the new context as well. - 4) For each instruction, call its execute() method. - The result is a pointer to the next instruction to execute (or NULL) - if an error occurred. - 5) On success, set the new values of the OUT and INOUT parameters in - the caller's frame. - - - USE database - - Before executing the instruction we also keeps the current default - database (if any). If this was changed during execution (i.e. a "USE" - statement has been executed), we restore the current database to the - original. - - This is the most useful way to handle USE in procedures. If we didn't, - the caller would find himself in a different database after calling - a function, which can be confusing. - Restoring the database also gives full freedom to the procedure writer: - - It's possible to write "general" procedures that are independent of - the actual database name. - - It's possible to write procedures that work on a particular database - by calling USE, without having to use fully qualified table names - everywhere (which doesn't help if you want to call other, "general", - procedures anyway). - - - Evaluating Items - - There are three occasions where we need to evaluate an expression: - - - When SETing a variable - - When CALLing a procedure - - When testing an expression for a branch (in IF, WHILE, etc) - - The semantics in stored procedures is "call-by-value", so we have to - evaluate any "func" Items at the point of the CALL or SET, otherwise - we would get a kind of "lazy" evaluation with unexpected results with - respect to OUT parameters for instance. - For this the support function, sp_head.cc:eval_func_item() is needed. - - - - Calling a FUNCTION - - Functions don't have an explicit call keyword like procedures. Instead, - they appear in expressions with the conventional syntax "fun(arg, ...)". - The problem is that we already have User Defined Functions (UDFs) which - are called the same way. A UDF is detected by the lexical analyzer (not - the parser!), in the find_keyword() function, and returns a UDF_*_FUNC - or UDA_*_SUM token with the udf_func object as the yylval. - - So, stored functions must be handled in a simpilar way, and as a - consequence, UDFs and functions must not have the same name. - - - Detecting and parsing a FUNCTION invocation - - The existence of UDFs are checked during the lexical analysis (in - sql_lex.cc:find_keyword()). This has the drawback that they must - exist before they are referred to, which was ok before SPs existed, - but then it becomes a problem. The first implementation of SP FUNCTIONs - will work the same way, but this should be fixed a.s.a.p. (This will - required some reworking of the way UDFs are handled, which is why it's - not done from the start.) - For the time being, a FUNCTION is detected the same way, and returns - the token SP_FUNC. During the parsing we only check for the *existence* - of the function, we don't parse it, since wa can't call the parser - recursively. - - When encountering a SP_FUNC with parameters in the expression parser, - an instance of the new Item_func_sp class is created. Unlike UDFs, we - don't have different classes for different return types, since we at - this point don't know the type. - - - Collecting FUNCTIONs to invoke - - A FUNCTION differs from a PROCEDURE in one important aspect: Whereas a - PROCEDURE is CALLed as statement by itself, a FUNCTION is invoked - "on-the-fly" during the execution of *another* statement. - This makes things a lot more complicated compared to CALL: - - We can't read and parse the FUNCTION from the mysql.proc table at the - point of invocation; the server requires that all tables used are - opened and locked at the beginning of the query execution. - One "obvious" solution would be to simply push "mysql.proc" to the list - of tables used by the query, but this implies a "join" with this table - if the query is a select, so it doesn't work (and we can't exclude this - table easily; since a privileged used might in fact want to search - the proc table). - Another solution would of course be to allow the opening and closing - of the mysql.proc table during a query execution, but this it not - possible at the present. - - So, the solution is to collect the names of the referred FUNCTIONs during - parsing in the lex. - Then, before doing anything else in mysql_execute_command(), read all - functions from the database an keep them in the THD, where the function - sp_find_function() can find them during the execution. - Note: Even with an in-memory cache, we must still make sure that the - functions are indeed read and cached at this point. - The code that read and cache functions from the database must also be - invoked recursively for each read FUNCTION to make sure we have *all* the - functions we need. - - - - Parsing DROP PROCEDURE/FUNCTION - - The procedure name is pushed to Lex->value_list. - The sql_command code for the result of parsing a is - SQLCOM_DROP_PROCEDURE/SQLCOM_DROP_FUNCTION. - - Dropping is done by simply getting the procedure with the sp_find() - function and calling sp_drop() (both in sp.{cc,h}). - - DROP PROCEDURE/FUNCTION also supports the non-standard "IF EXISTS", - analogous to other DROP statements in MySQL. - - - - Condition and Handlers - - Condition names are lexical entities and are kept in the parser context - just like variables. But, condition are just "aliases" for SQLSTATE - strings, or mysqld error codes (which is a non-standard extension in - MySQL), and are only used during parsing. - - Handlers comes in three types, CONTINUE, EXIT and UNDO. The latter is - like an EXIT handler with an implicit rollback, and is currently not - implemented. - The EXIT handler jumps to the end of its BEGIN-END block when finished. - The CONTINUE handler returns to the statement following that which - invoked the handler. - - The handlers in effect at any point is part of each thread's runtime - state, so we need to push and pop handlers in the sp_rcontext during - execution. We use special instructions for this: - - sp_instr_hpush_jump - Push a handler. The instruction contains the necessary information, - like which conditions we handle and the location of the handler. - The jump takes us to the location after the handler code. - - sp_instr_hpop - Pop the handlers of the current frame (which we are just leaving). - - It might seems strange to jump past the handlers like that, but there's - no extra cost in doing this, and for technical reasons it's easiest for - the parser to generate the handler instructions when they occur in the - source. - - When an error occurs, one of the error routines is called and an error - message is normally sent back to the client immediately. - Catching a condition must be done in these error routines (there are - quite a few) to prevent them from doing this. We do this by calling - a method in the THD's sp_rcontext (if there is one). If a handler is - found, this is recorded in the context and the routine returns without - sending the error message. - The execution loop (sp_head::execute()) checks for this after each - statement and invokes the handler that has been found. If several - errors or warnings occurs during one statement, only the first is - caught, the rest are ignored. - - Invoking and returning from a handler is trivial in the EXIT case. - We simply jump to it, and it will have an sp_instr_jump as its last - instruction. - - Calling and returning from a CONTINUE handler poses some special - problems. Since we need to return to the point after its invocation, - we push the return location on a stack in the sp_rcontext (this is - done by the execution loop). The handler then ends with a special - instruction, sp_instr_hreturn, which returns to this location. - - CONTINUE handlers have one additional problem: They are parsed at - the lexical level where they occur, so variable offsets will assume - that it's actually called at that level. However, a handler might be - invoked from a sub-block where additional local variables have been - declared, which will then share the location of any local variables - in the handler itself. So, when calling a CONTINUE handler, we need - to save any local variables above the handler's frame offset, and - restore them upon return. (This is not a problem for EXIT handlers, - since they will leave the block anyway.) - This is taken care of by the execution loop and the sp_instr_hreturn - instruction. - - - Examples: - - - EXIT handler - begin - declare x int default 0; - - begin - declare exit handler for 'XXXXX' set x = 1; - - (statement1); - (statement2); - end; - (statement3); - end - - Pos. Instruction - 0 sp_instr_set(0, '0') - 1 sp_instr_hpush_jump(4, 1) # location and frame size - 2 sp_instr_set(0, '1') - 3 sp_instr_jump(6) - 4 sp_instr_stmt('statement1') - 5 sp_instr_stmt('statement2') - 6 sp_instr_hpop(1) - 7 sp_instr_stmt('statement3') - - - CONTINUE handler - create procedure hndlr1(val int) - begin - declare x int default 0; - declare foo condition for 1146; - declare continue handler for foo set x = 1; - - insert into t3 values ("hndlr1", val); # Non-existing table? - if x>0 then - insert into t1 values ("hndlr1", val); # This instead then - end if; - end| - - Pos. Instruction - 0 sp_instr_set(1, '0') - 1 sp_instr_hpush_jump(4, 2) - 2 sp_instr_set(1, '1') - 3 sp_instr_hreturn(2) # frame size - 4 sp_instr_stmt('insert ... t3 ...') - 5 sp_instr_jump_if_not(7, 'x>0') - 6 sp_instr_stmt('insert ... t1 ...') - 7 sp_instr_hpop(2) - - - - Cursors - - For stored procedures to be really useful, you want to have cursors. - MySQL doesn't yet have "real" cursor support (with API and ODBC support, - allowing updating, arbitrary scrolling, etc), but a simple asensitive, - non-scrolling, read-only cursor can be implemented in SPs using the - class Protocol_cursor. - This class intecepts the creation and sending of results sets and instead - stores it in-memory, as MYSQL_FIELDS and MYSQL_ROWS (as in the client API). - - To support this, we need the usual name binding support in sp_pcontext - (similar to variables and conditions) to keep track on declared cursor - names, and a corresponding run-time mechanism in sp_rcontext. - Cursors are lexically scoped like everything with a body or BEGIN/END - block, so they are pushed and poped as usual (see conditions and variables - above). - The basic operations on a cursor are OPEN, FETCH and CLOSE, which will - each have a corresponding instruction. In addition, we need instructions - to push a new cursor (this will encapsulate the LEX of the SELECT statement - of the cursor), and a pop instruction: - - sp_instr_cpush - Push a cursor to the sp_rcontext. This instruction contains the LEX - for the select statement - - sp_instr_cpop - Pop a number of cursors from the sp_rcontext. - - sp_instr_copen - Open a cursor: This will execute the select and get the result set - in a sepeate memroot. - - sp_instr_cfetch - Fetch the next row from the in-memory result set. The instruction - contains a list of the variables (frame offsets) to set. - - sp_instr_cclose - Free the result set. - - A cursor is a separate class, sp_cursor (defined in sp_rcontex.h) which - encapsulates the basic operations used by the above instructions. - This class contains the LEX, Protocol_cursor object, and its memroot, - as well as the cursor's current state. - Compiling and executing is fairly straight-forward. sp_instr_copen is - a subclass of sp_instr_stmt and uses its mechanism to execute a - substatement. - - - Example: - - begin - declare x int; - declare c cursor for select a from t1; - - open c; - fetch c into x; - close c; - end - - Pos. Instruction - 0 sp_instr_cpush('select a from ...') - 1 sp_instr_copen(0) # The 0'th cursor - 2 sp_instr_cfetch(0) # Contains the variable list - 3 sp_instr_cclose(0) - 4 sp_instr_cpop(1) - - - - - The SP cache - - There are two ways to cache SPs: - - 1) one global cache, share by all threads/connections, - 2) one cache per thread. - - There are pros and cons with both methods: - - 1) Pros: Save memory, each SP only read from table once, - Cons: Needs locking (= serialization at access), requires thread-safe - data structures, - 2) Pros: Fast, no locking required (almost), limited thread-safe - requirement, - Cons: Uses more memory, each SP read from table once per thread. - - Unfortunately, we cannot use alternative 1 for the time being, as most - of the data structures to be cached (lex and items) are not reentrant - and thread-safe. (Things are modified at execution, we have THD pointers - stored everywhere, etc.) - This leaves us with alternative 2, one cache per thread; or actually - two, since we keep FUNCTIONs and PROCEDUREs in separate caches. - This is not that terrible; the only case when it will perform - significantly worse than a global cache is when we have an application - where new threads are connecting, calling a procedure, and disconnecting, - over and over again. - - The cache implementation itself is simple and straightforward, a hashtable - wrapped in a class and a C API (see APIs below). - - There is however one issue with multiple caches: dropping and altering - procedures. Normally, this should be a very rare event in a running - system; it's typically something you do during development and testing, - so it's not unthinkable that we would simply ignore the issue and let - any threads running with a cached version of an SP keep doing so until - its disconnected. - But assuming we want to keep the caches consistent with respect to drop - and alter, it can be done: - - 1) A global counter is needed, initialized to 0 at start. - 2) At each DROP or ALTER, increase the counter by one. - 3) Each cache has its own copy of the counter, copied at the last read. - 4) When looking up a name in the cache, first check if the global counter - is larger than the local copy. - If so, clear the cache and return "not found", and update the local - counter; otherwise, lookup as usual. - - This minimizes the cost to a single brief lock for the access of an - integer when operating normally. Only in the event of an actual drop or - alter, is the cache cleared. This may seem to be drastic, but since we - assume that this is a rare event, it's not a problem. - It would of course be possible to have a much more fine-grained solution, - keeping track of each SP, but the overhead of doing so is not worth the - effort. - - - - Class and function APIs - This is an outline of the key types. Some types and other details - in the actual files have been omitted for readability. - - - The parser context: sp_pcontext.h - - typedef enum - { - sp_param_in, - sp_param_out, - sp_param_inout - } sp_param_mode_t; - - typedef struct - { - LEX_STRING name; - enum enum_field_types type; - sp_param_mode_t mode; - uint offset; // Offset in current frame - my_bool isset; - } sp_pvar_t; - - typedef struct sp_cond_type - { - enum { number, state, warning, notfound, exception } type; - char sqlstate[6]; - uint mysqlerr; - } sp_cond_type_t; - - class sp_pcontext - { - sp_pcontext(); - - // Return the maximum frame size - uint max_framesize(); - - // Return the current frame size - uint current_framesize(); - - // Return the number of parameters - uint params(); - - // Set the number of parameters to the current frame size - void set_params(); - - // Set type of the variable at offset 'i' in the frame - void set_type(uint i, enum enum_field_types type); - - // Mark the i:th variable to "set" (i.e. having a value) with - // 'val' true. - void set_isset(uint i, my_bool val); - - // Push the variable 'name' to the frame. - void push_var(LEX_STRING *name, - enum enum_field_types type, sp_param_mode_t mode); - - // Pop 'num' variables from the frame. - void pop_var(uint num = 1); - - // Find variable by name - sp_pvar_t *find_pvar(LEX_STRING *name); - - // Find variable by index - sp_pvar_t *find_pvar(uint i); - - // Push label 'name' of instruction index 'ip' to the label context - sp_label_t *push_label(char *name, uint ip); - - // Find label 'name' in the context - sp_label_t *find_label(char *name); - - // Return the last pushed label - sp_label_t *last_label(); - - // Return and remove the last pushed label. - sp_label_t *pop_label(); - - // Push a condition to the context - void push_cond(LEX_STRING *name, sp_cond_type_t *val); - - // Pop a 'num' condition from the context - void pop_cond(uint num); - - // Find a condition in the context - sp_cond_type_t *find_cond(LEX_STRING *name); - - // Increase the handler count - void add_handler(); - - // Returns the handler count - uint handlers(); - - // Push a cursor - void push_cursor(LEX_STRING *name); - - // Find a cursor - my_bool find_cursor(LEX_STRING *name, uint *poff); - - // Pop 'num' cursors - void pop_cursor(uint num); - - // Return the number of cursors - uint cursors(); - } - - - - The run-time context (call frame): sp_rcontext.h - - #define SP_HANDLER_NONE 0 - #define SP_HANDLER_EXIT 1 - #define SP_HANDLER_CONTINUE 2 - #define SP_HANDLER_UNDO 3 - - typedef struct - { - struct sp_cond_type *cond; - uint handler; // Location of handler - int type; - uint foffset; // Frame offset for the handlers declare level - } sp_handler_t; - - class sp_rcontext - { - // 'fsize' is the max size of the context, 'hmax' the number of handlers, - // 'cmax' the number of cursors - sp_rcontext(uint fsize, uint hmax, , uint cmax); - - // Push value (parameter) 'i' to the frame - void push_item(Item *i); - - // Set slot 'idx' to value 'i' - void set_item(uint idx, Item *i); - - // Return the item in slot 'idx' - Item *get_item(uint idx); - - // Set the "out" index 'oidx' for slot 'idx. If it's an IN slot, - // use 'oidx' -1. - void set_oindex(uint idx, int oidx); - - // Return the "out" index for slot 'idx' - int get_oindex(uint idx); - - // Set the FUNCTION result - void set_result(Item *i); - - // Get the FUNCTION result - Item *get_result(); - - // Push handler at location 'h' for condition 'cond'. 'f' is the - // current variable frame size. - void push_handler(sp_cond_type_t *cond, uint h, int type, uint f); - - // Pop 'count' handlers - void pop_handlers(uint count); - - // Find a handler for this error. This sets the state for a found - // handler in the context. If called repeatedly without clearing, - // only the first call's state is kept. - int find_handler(uint sql_errno); - - // Returns 1 if a handler has been found, with '*ip' and '*fp' set - // to the handler location and frame size respectively. - int found_handler(uint *ip, uint *fp); - - // Clear the found handler state. - void clear_handler(); - - // Push a return address for a CONTINUE handler - void push_hstack(uint ip); - - // Pop the CONTINUE handler return stack - uint pop_hstack(); - - // Save variables from frame index 'fp' and up. - void save_variables(uint fp); - - // Restore saved variables from to frame index 'fp' and up. - void restore_variables(uint fp); - - // Push a cursor for the statement (lex) - void push_cursor(LEX *lex); - - // Pop 'count' cursors - void pop_cursors(uint count); - - // Pop all cursors - void pop_all_cursors(); - - // Get the 'i'th cursor - sp_cursor *get_cursor(uint i); - - } - - - - The procedure: sp_head.h - - #define TYPE_ENUM_FUNCTION 1 - #define TYPE_ENUM_PROCEDURE 2 - - class sp_head - { - int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE - - sp_head(); - - void init(LEX_STRING *name, LEX *lex, LEX_STRING *comment, char suid); - - // Store this procedure in the database. This is a wrapper around - // the function sp_create_procedure(). - int create(THD *); - - // Invoke a FUNCTION - int - execute_function(THD *thd, Item **args, uint argcount, Item **resp); - - // CALL a PROCEDURE - int - execute_procedure(THD *thd, List<Item> *args); - - // Add the instruction to this procedure. - void add_instr(sp_instr *); - - // Returns the number of instructions. - uint instructions(); - - // Returns the last instruction - sp_instr *last_instruction(); - - // Resets lex in 'thd' and keeps a copy of the old one. - void reset_lex(THD *); - - // Restores lex in 'thd' from our copy, but keeps some status from the - // one in 'thd', like ptr, tables, fields, etc. - void restore_lex(THD *); - - // Put the instruction on the backpatch list, associated with - // the label. - void push_backpatch(sp_instr *, struct sp_label *); - - // Update all instruction with this label in the backpatch list to - // the current position. - void backpatch(struct sp_label *); - - // Returns the SP name (with optional length in '*lenp'). - char *name(uint *lenp = 0); - - // Returns the result type for a function - Item_result result(); - - // Sets various attributes - void sp_set_info(char *creator, uint creatorlen, - longlong created, longlong modified, - bool suid, char *comment, uint commentlen); - } - - - - Instructions - - - The base class: - class sp_instr - { - // 'ip' is the index of this instruction - sp_instr(uint ip); - - // Execute this instrution. - // '*nextp' will be set to the index of the next instruction - // to execute. (For most instruction this will be the - // instruction following this one.) - // Returns 0 on success, non-zero if some error occurred. - virtual int execute(THD *, uint *nextp) - } - - - Statement instruction: - class sp_instr_stmt : public sp_instr - { - sp_instr_stmt(uint ip); - - int execute(THD *, uint *nextp); - - // Set the statement's Lex - void set_lex(LEX *); - - // Return the statement's Lex - LEX *get_lex(); - } - - - SET instruction: - class sp_instr_set : public sp_instr - { - // 'offset' is the variable's frame offset, 'val' the value, - // and 'type' the variable type. - sp_instr_set(uint ip, - uint offset, Item *val, enum enum_field_types type); - - int execute(THD *, uint *nextp); - } - - - Unconditional jump - class sp_instr_jump : public sp_instr - { - // No destination, must be set. - sp_instr_jump(uint ip); - - // 'dest' is the destination instruction index. - sp_instr_jump(uint ip, uint dest); - - int execute(THD *, uint *nextp); - - // Set the destination instruction 'dest'. - void set_destination(uint dest); - } - - - Conditional jump - class sp_instr_jump_if_not : public sp_instr_jump - { - // Jump if 'i' evaluates to false. Destination not set yet. - sp_instr_jump_if_not(uint ip, Item *i); - - // Jump to 'dest' if 'i' evaluates to false. - sp_instr_jump_if_not(uint ip, Item *i, uint dest) - - int execute(THD *, uint *nextp); - } - - - Return a function value - class sp_instr_freturn : public sp_instr - { - // Return the value 'val' - sp_instr_freturn(uint ip, Item *val, enum enum_field_types type); - - int execute(THD *thd, uint *nextp); - } - - - Push a handler and jump - class sp_instr_hpush_jump : public sp_instr_jump - { - // Push handler of type 'htype', with current frame size 'fp' - sp_instr_hpush_jump(uint ip, int htype, uint fp); - - int execute(THD *thd, uint *nextp); - - // Add condition for this handler - void add_condition(struct sp_cond_type *cond); - } - - - Pops handlers - class sp_instr_hpop : public sp_instr - { - // Pop 'count' handlers - sp_instr_hpop(uint ip, uint count); - - int execute(THD *thd, uint *nextp); - } - - - Return from a CONTINUE handler - class sp_instr_hreturn : public sp_instr - { - // Return from handler, and restore variables to 'fp'. - sp_instr_hreturn(uint ip, uint fp); - - int execute(THD *thd, uint *nextp); - } - - - Push a CURSOR - class sp_instr_cpush : public sp_instr_stmt - { - // Push a cursor for statement 'lex' - sp_instr_cpush(uint ip, LEX *lex) - - int execute(THD *thd, uint *nextp); - } - - - Pop CURSORs - class sp_instr_cpop : public sp_instr_stmt - { - // Pop 'count' cursors - sp_instr_cpop(uint ip, uint count) - - int execute(THD *thd, uint *nextp); - } - - - Open a CURSOR - class sp_instr_copen : public sp_instr_stmt - { - // Open the 'c'th cursor - sp_instr_copen(uint ip, uint c); - - int execute(THD *thd, uint *nextp); - } - - - Close a CURSOR - class sp_instr_cclose : public sp_instr - { - // Close the 'c'th cursor - sp_instr_cclose(uint ip, uint c); - - int execute(THD *thd, uint *nextp); - } - - - Fetch a row with CURSOR - class sp_instr_cfetch : public sp_instr - { - // Fetch next with the 'c'th cursor - sp_instr_cfetch(uint ip, uint c); - - int execute(THD *thd, uint *nextp); - - // Add a target variable for the fetch - void add_to_varlist(struct sp_pvar *var); - } - - - - Utility functions: sp.h - - #define SP_OK 0 - #define SP_KEY_NOT_FOUND -1 - #define SP_OPEN_TABLE_FAILED -2 - #define SP_WRITE_ROW_FAILED -3 - #define SP_DELETE_ROW_FAILED -4 - #define SP_GET_FIELD_FAILED -5 - #define SP_PARSE_ERROR -6 - - // Finds a stored procedure given its name. Returns NULL if not found. - sp_head *sp_find_procedure(THD *, LEX_STRING *name); - - // Store the procedure 'name' in the database. 'def' is the complete - // definition string ("create procedure ..."). - int sp_create_procedure(THD *, - char *name, uint namelen, - char *def, uint deflen, - char *comment, uint commentlen, bool suid); - - // Drop the procedure 'name' from the database. - int sp_drop_procedure(THD *, char *name, uint namelen); - - // Finds a stored function given its name. Returns NULL if not found. - sp_head *sp_find_function(THD *, LEX_STRING *name); - - // Store the function 'name' in the database. 'def' is the complete - // definition string ("create function ..."). - int sp_create_function(THD *, - char *name, uint namelen, - char *def, uint deflen, - char *comment, uint commentlen, bool suid); - - // Drop the function 'name' from the database. - int sp_drop_function(THD *, char *name, uint namelen); - - - - The cache: sp_cache.h - - /* Initialize the SP caching once at startup */ - void sp_cache_init(); - - /* Clear the cache *cp and set *cp to NULL */ - void sp_cache_clear(sp_cache **cp); - - /* Insert an SP to cache. If **cp points to NULL, it's set to a - new cache */ - void sp_cache_insert(sp_cache **cp, sp_head *sp); - - /* Lookup an SP in cache */ - sp_head *sp_cache_lookup(sp_cache **cp, char *name, uint namelen); - - /* Remove an SP from cache */ - void sp_cache_remove(sp_cache **cp, sp_head *sp); - - - - The mysql.proc schema: - - CREATE TABLE proc ( - db char(64) binary DEFAULT '' NOT NULL, - name char(64) DEFAULT '' NOT NULL, - type enum('FUNCTION','PROCEDURE') NOT NULL, - specific_name char(64) DEFAULT '' NOT NULL, - language enum('SQL') DEFAULT 'SQL' NOT NULL, - sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL, - is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, - security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, - param_list blob DEFAULT '' NOT NULL, - returns char(64) DEFAULT '' NOT NULL, - body blob DEFAULT '' NOT NULL, - definer char(77) binary DEFAULT '' NOT NULL, - created timestamp, - modified timestamp, - sql_mode set( - 'REAL_AS_FLOAT', - 'PIPES_AS_CONCAT', - 'ANSI_QUOTES', - 'IGNORE_SPACE', - 'IGNORE_BAD_TABLE_OPTIONS', - 'ONLY_FULL_GROUP_BY', - 'NO_UNSIGNED_SUBTRACTION', - 'NO_DIR_IN_CREATE', - 'POSTGRESQL', - 'ORACLE', - 'MSSQL', - 'DB2', - 'MAXDB', - 'NO_KEY_OPTIONS', - 'NO_TABLE_OPTIONS', - 'NO_FIELD_OPTIONS', - 'MYSQL323', - 'MYSQL40', - 'ANSI', - 'NO_AUTO_VALUE_ON_ZERO' - ) DEFAULT 0 NOT NULL, - comment char(64) binary DEFAULT '' NOT NULL, - PRIMARY KEY (db,name,type) - ) comment='Stored Procedures'; - - -- - diff --git a/KNOWN_BUGS.txt b/KNOWN_BUGS.txt index 56c9102b0cd..af65c98590d 100644 --- a/KNOWN_BUGS.txt +++ b/KNOWN_BUGS.txt @@ -1,35 +1,15 @@ -This file should contain all known fatal bugs in Mariadb and the Aria -storage engine for the last source or binary release. Minor bugs, -extensions and feature requests, and bugs found since this release can -be found in the MariaDB bugs database at: http://mariadb.org/jira and -in the MySQL bugs databases at: http://bugs.mysql.com/ (category -"Maria storage engine"). +This file should contain all known fatal bugs in MariaDB for the last +source or binary release. Minor bugs, extensions and feature requests, +and bugs found since this release can be found in the MariaDB bugs +database at: https://jira.mariadb.org There should not normally be any bugs which affect normal operations in any MariaDB release. Still, there are always exceptions and edge cases and that is what this file is for. -If you have found a bug that is not listed here, please add it to -http://mariadb.org/jira so we can either fix it for next release or in -the worst case add it here for others to know! +If you have find bug please add it to https://jira.mariadb.org so +that we are can try to fix it for the next release. You can also add +feature request to the JIRA. - -IMPORTANT: - -If you have been using the Maria (now Aria) storage engine with the -MySQL-5.1-Maria-alpha build and are upgrading to a newer MariaDB you -MUST run [m]aria_chk --recover on all your Aria tables. This is because -we made an incompatible change with how the transaction id is stored -and old transaction id's must be reset! - -cd mysql-data-directory -aria_chk --recover */*.MAI - -Going forward, we will do our best to not introduce any incompatible -changes in the data format for Aria tables. If this would be ever be -needed, we will, if possible, support both the old and the new version -to make upgrades as easy as possible. - -Note that for the MariaDB 5.1 release the Aria storage engine is -classified as 'beta'; It should work, but use it with caution. Please -report all bugs to http://mariadb.org/jira so we can fix them! +The latest documentation for the MariaDB server can be found at: +https://mariadb.com/kb diff --git a/README.md b/README.md index 5e3ef4ed21d..07e917b039a 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,20 @@ Code status: ------------ -* [](https://travis-ci.org/MariaDB/server) travis-ci.org (10.3 branch) +* [](https://travis-ci.org/MariaDB/server) travis-ci.org (10.4 branch) ## MariaDB: drop-in replacement for MySQL MariaDB is designed as a drop-in replacement of MySQL(R) with more features, new storage engines, fewer bugs, and better performance. -MariaDB is brought to you by the MariaDB Foundation. +MariaDB is brought to you by the MariaDB Foundation and the MariaDB corporation. Please read the CREDITS file for details about the MariaDB Foundation, and who is developing MariaDB. MariaDB is developed by many of the original developers of MySQL who -now work for the MariaDB Foundation and the MariaDB Corporation, and by many people in -the community. +now work for the MariaDB Corporation, the MariaDB Foundation and by +many people in the community. MySQL, which is the base of MariaDB, is a product and trademark of Oracle Corporation, Inc. For a list of developers and other contributors, @@ -23,28 +23,35 @@ list of active contributors. A description of the MariaDB project and a manual can be found at: -https://mariadb.org/ - https://mariadb.com/kb/en/ https://mariadb.com/kb/en/mariadb-vs-mysql-features/ -https://mariadb.com/kb/en/mariadb-versus-mysql-features/ - https://mariadb.com/kb/en/mariadb-versus-mysql-compatibility/ +https://mariadb.com/kb/en/library/new-and-old-releases/ + +https://mariadb.org/ + As MariaDB is a full replacement of MySQL, the MySQL manual at http://dev.mysql.com/doc is generally applicable. -Help: +Help ----- More help is available from the Maria Discuss mailing list https://launchpad.net/~maria-discuss and the #maria IRC channel on Freenode. +Live QA for beginner contributors +---- +MariaDB has a dedicated time each week when we answer new contributor questions live on Zulip and IRC. +From 8:00 to 10:00 UTC on Mondays, and 10:00 to 12:00 UTC on Thursdays, +anyone can ask any questions they’d like, and a live developer will be available to assist. + +New contributors can ask questions any time, but we will provide immediate feedback during that interval. -License: +License -------- *************************************************************************** @@ -61,7 +68,7 @@ and COPYING.thirdparty files. *************************************************************************** -Bug Reports: +Bug Reports ------------ Bug and/or error reports regarding MariaDB should be submitted at: @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=10 -MYSQL_VERSION_MINOR=3 -MYSQL_VERSION_PATCH=12 -SERVER_MATURITY=stable +MYSQL_VERSION_MINOR=4 +MYSQL_VERSION_PATCH=1 +SERVER_MATURITY=alpha diff --git a/client/client_priv.h b/client/client_priv.h index ada72187569..ffdf0fc4b8f 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -49,7 +49,7 @@ enum options_client OPT_SSL_CIPHER, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE, OPT_DELETE_MASTER_LOGS, OPT_COMPACT, OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL, - OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM, OPT_SKIP_OPTIMIZATION, + OPT_FRM, OPT_SKIP_OPTIMIZATION, OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH, OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_SERVER_ARG, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME, diff --git a/client/mysql.cc b/client/mysql.cc index 3d722cb94ba..a20a1665071 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -196,9 +196,6 @@ static char delimiter[16]= DEFAULT_DELIMITER; static uint delimiter_length= 1; unsigned short terminal_width= 80; -#ifdef HAVE_SMEM -static char *shared_memory_base_name=0; -#endif static uint opt_protocol=0; static CHARSET_INFO *charset_info= &my_charset_latin1; @@ -281,9 +278,9 @@ static COMMANDS commands[] = { { "edit", 'e', com_edit, 0, "Edit command with $EDITOR."}, #endif { "ego", 'G', com_ego, 0, - "Send command to mysql server, display result vertically."}, + "Send command to MariaDB server, display result vertically."}, { "exit", 'q', com_quit, 0, "Exit mysql. Same as quit."}, - { "go", 'g', com_go, 0, "Send command to mysql server." }, + { "go", 'g', com_go, 0, "Send command to MariaDB server." }, { "help", 'h', com_help, 1, "Display this help." }, #ifdef USE_POPEN { "nopager",'n', com_nopager,0, "Disable pager, print to stdout." }, @@ -1340,9 +1337,6 @@ sig_handler mysql_end(int sig) my_free(full_username); my_free(part_username); my_free(default_prompt); -#ifdef HAVE_SMEM - my_free(shared_memory_base_name); -#endif my_free(current_prompt); while (embedded_server_arg_count > 1) my_free(embedded_server_args[--embedded_server_arg_count]); @@ -1373,10 +1367,6 @@ static bool do_connect(MYSQL *mysql, const char *host, const char *user, #endif if (opt_protocol) mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); -#endif if (opt_plugin_dir && *opt_plugin_dir) mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir); @@ -1547,7 +1537,7 @@ static struct my_option my_long_options[] = &ignore_spaces, &ignore_spaces, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"init-command", OPT_INIT_COMMAND, - "SQL Command to execute when connecting to MySQL server. Will " + "SQL Command to execute when connecting to MariaDB server. Will " "automatically be re-executed when reconnecting.", &opt_init_command, &opt_init_command, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -1609,10 +1599,10 @@ static struct my_option my_long_options[] = "Get progress reports for long running commands (like ALTER TABLE)", &opt_progress_reports, &opt_progress_reports, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"prompt", OPT_PROMPT, "Set the mysql prompt to this value.", + {"prompt", OPT_PROMPT, "Set the command line prompt to this value.", ¤t_prompt, ¤t_prompt, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"quick", 'q', "Don't cache result, print it row by row. This may slow down the server " @@ -1626,11 +1616,6 @@ static struct my_option my_long_options[] = &opt_reconnect, &opt_reconnect, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"silent", 's', "Be more silent. Print results with a tab as separator, " "each row on new line.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", &shared_memory_base_name, - &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif {"socket", 'S', "The socket file to use for connection.", &opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -3142,7 +3127,7 @@ com_help(String *buffer __attribute__((unused)), put_info("\nGeneral information about MariaDB can be found at\n" "http://mariadb.org\n", INFO_INFO); - put_info("List of all MySQL commands:", INFO_INFO); + put_info("List of all client commands:", INFO_INFO); if (!named_cmds) put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO); for (i = 0; commands[i].name; i++) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index ef1630dd0e3..ee10996d678 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -111,7 +111,7 @@ static struct my_option my_long_options[]= &opt_default_auth, &opt_default_auth, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade " - "has already been executed for the current version of MySQL.", + "has already been executed for the current version of MariaDB.", &opt_force, &opt_force, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"host", 'h', "Connect to host.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -135,13 +135,8 @@ static struct my_option my_long_options[]= "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, - "The protocol to use for connection (tcp, socket, pipe, memory).", + "The protocol to use for connection (tcp, socket, pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", 0, - 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif {"silent", OPT_SILENT, "Print less information", &opt_silent, &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", @@ -354,7 +349,6 @@ get_one_option(int optid, const struct my_option *opt, case 'P': /* --port */ case 'S': /* --socket */ case OPT_MYSQL_PROTOCOL: /* --protocol */ - case OPT_SHARED_MEMORY_BASE_NAME: /* --shared-memory-base-name */ case OPT_PLUGIN_DIR: /* --plugin-dir */ case OPT_DEFAULT_AUTH: /* --default-auth */ add_one_option_cmd_line(&conn_args, opt, argument); @@ -814,7 +808,7 @@ static my_bool is_mysql() strstr(ds_events_struct.str, "IGNORE_BAD_TABLE_OPTIONS") != NULL) ret= FALSE; else - verbose("MySQL upgrade detected"); + verbose("MariaDB upgrade detected"); dynstr_free(&ds_events_struct); return(ret); @@ -884,10 +878,14 @@ static int run_mysqlcheck_fixnames(void) static const char *expected_errors[]= { + "ERROR 1051", /* Unknown table */ "ERROR 1060", /* Duplicate column name */ "ERROR 1061", /* Duplicate key name */ "ERROR 1054", /* Unknown column */ + "ERROR 1146", /* Table does not exist */ "ERROR 1290", /* RR_OPTION_PREVENTS_STATEMENT */ + "ERROR 1347", /* 'mysql.user' is not of type 'BASE TABLE' */ + "ERROR 1348", /* Column 'Show_db_priv' is not updatable */ 0 }; @@ -1198,7 +1196,7 @@ int main(int argc, char **argv) */ if (!opt_force && upgrade_already_done(0)) { - printf("This installation of MySQL is already upgraded to %s, " + printf("This installation of MariaDB is already upgraded to %s, " "use --force if you still need to run mysql_upgrade\n", MYSQL_SERVER_VERSION); goto end; diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 5e7fb80b2b5..35afe06eade 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -49,9 +49,6 @@ static char * unix_port=0; static char *opt_plugin_dir= 0, *opt_default_auth= 0; static bool sql_log_bin_off= false; -#ifdef HAVE_SMEM -static char *shared_memory_base_name=0; -#endif static uint opt_protocol=0; static myf error_flags; /* flags to pass to my_printf_error, like ME_BELL */ @@ -185,18 +182,13 @@ static struct my_option my_long_options[] = #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", &tcp_port, &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relative", 'r', "Show difference between current and previous values when used with -i. " "Currently only works with extended-status.", &opt_relative, &opt_relative, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name, - 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif {"silent", 's', "Silently exit if one can't connect to server.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", @@ -367,10 +359,6 @@ int main(int argc,char *argv[]) #endif if (opt_protocol) mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); -#endif mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); error_flags= (myf)(opt_nobeep ? 0 : ME_BELL); @@ -496,9 +484,6 @@ err2: mysql_library_end(); my_free(opt_password); my_free(user); -#ifdef HAVE_SMEM - my_free(shared_memory_base_name); -#endif free_defaults(save_argv); my_end(my_end_arg); return error; @@ -588,7 +573,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) if (!info) { info=1; - fputs("Waiting for MySQL server to answer",stderr); + fputs("Waiting for MariaDB server to answer",stderr); (void) fflush(stderr); } else diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 14656705805..a5995e103ef 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -124,9 +124,6 @@ static uint my_end_arg; static const char* sock= 0; static char *opt_plugindir= 0, *opt_default_auth= 0; -#ifdef HAVE_SMEM -static const char *shared_memory_base_name= 0; -#endif static char* user = 0; static char* pass = 0; static char *charset= 0; @@ -1601,7 +1598,7 @@ static struct my_option my_options[] = &opt_default_auth, &opt_default_auth, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"disable-log-bin", 'D', "Disable binary log. This is useful, if you " - "enabled --to-last-log and are sending the output to the same MySQL server. " + "enabled --to-last-log and are sending the output to the same MariaDB server. " "This way you could avoid an endless loop. You would also like to use it " "when restoring after a crash to avoid duplication of the statements you " "already have. NOTE: you will need a SUPER privilege to use this option.", @@ -1644,9 +1641,9 @@ static struct my_option my_options[] = &port, &port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, - "The protocol to use for connection (tcp, socket, pipe, memory).", + "The protocol to use for connection (tcp, socket, pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"read-from-remote-server", 'R', "Read binary logs from a MySQL server.", + {"read-from-remote-server", 'R', "Read binary logs from a MariaDB server.", &remote_opt, &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"raw", 0, "Requires -R. Output raw binlog data instead of SQL " @@ -1685,12 +1682,6 @@ static struct my_option my_options[] = {"set-charset", OPT_SET_CHARSET, "Add 'SET NAMES character_set' to the output.", &charset, &charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", &shared_memory_base_name, - &shared_memory_base_name, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif {"short-form", 's', "Just show regular queries: no extra info, no " "row-based events and no row counts. This is mainly for testing only, " "and should not be used to feed to the MariaDB server. " @@ -1705,7 +1696,7 @@ static struct my_option my_options[] = {"start-datetime", OPT_START_DATETIME, "Start reading the binlog at first event having a datetime equal or " "posterior to the argument; the argument must be a date and time " - "in the local time zone, in any format accepted by the MySQL server " + "in the local time zone, in any format accepted by the MariaDB server " "for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 " "(you should probably use quotes for your shell to set it properly).", &start_datetime_str, &start_datetime_str, @@ -1723,7 +1714,7 @@ static struct my_option my_options[] = {"stop-datetime", OPT_STOP_DATETIME, "Stop reading the binlog at first event having a datetime equal or " "posterior to the argument; the argument must be a date and time " - "in the local time zone, in any format accepted by the MySQL server " + "in the local time zone, in any format accepted by the MariaDB server " "for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 " "(you should probably use quotes for your shell to set it properly).", &stop_datetime_str, &stop_datetime_str, @@ -1747,7 +1738,7 @@ static struct my_option my_options[] = 0, 0, 0, 0, 0, 0}, {"to-last-log", 't', "Requires -R. Will not stop at the end of the \ requested binlog but rather continue printing until the end of the last \ -binlog of the MySQL server. If you send the output to the same MySQL server, \ +binlog of the MariaDB server. If you send the output to the same MariaDB server, \ that may lead to an endless loop.", &to_last_remote_log, &to_last_remote_log, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -1884,7 +1875,7 @@ static void usage() print_version(); puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); printf("\ -Dumps a MySQL binary log in a format usable for viewing or for piping to\n\ +Dumps a MariaDB binary log in a format usable for viewing or for piping to\n\ the mysql command line client.\n\n"); printf("Usage: %s [options] log-files\n", my_progname); print_defaults("my",load_groups); @@ -1902,7 +1893,7 @@ static my_time_t convert_str_to_timestamp(const char* str) uint dummy_in_dst_time_gap; /* We require a total specification (date AND time) */ - if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &status) || + if (str_to_datetime_or_date(str, (uint) strlen(str), &l_time, 0, &status) || l_time.time_type != MYSQL_TIMESTAMP_DATETIME || status.warnings) { error("Incorrect date and time argument: %s", str); @@ -2134,11 +2125,6 @@ static Exit_status safe_connect() if (opt_protocol) mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol); -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME, - shared_memory_base_name); -#endif mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "mysqlbinlog"); @@ -2295,7 +2281,7 @@ static Exit_status check_master_version() break; default: error("Could not find server version: " - "Master reported unrecognized MySQL version '%s'.", row[0]); + "Master reported unrecognized MariaDB version '%s'.", row[0]); goto err; } if (!glob_description_event || !glob_description_event->is_valid()) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 5e366c5e3d1..432c7abcbe1 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -55,7 +55,6 @@ static int first_error = 0; static char *opt_skip_database; DYNAMIC_ARRAY tables4repair, tables4rebuild, alter_table_cmds; DYNAMIC_ARRAY views4repair; -static char *shared_memory_base_name=0; static uint opt_protocol=0; enum operations { DO_CHECK=1, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_FIX_NAMES }; @@ -179,7 +178,7 @@ static struct my_option my_long_options[] = "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", &opt_mysql_port, &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"quick", 'q', "If you are using this option with CHECK TABLE, it prevents the check from scanning the rows to check for wrong links. This is the fastest check. If you are using this option with REPAIR TABLE, it will try to repair only the index tree. This is the fastest repair method for a table.", @@ -188,11 +187,6 @@ static struct my_option my_long_options[] = {"repair", 'r', "Can fix almost anything except unique keys that aren't unique.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name, - 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif {"silent", 's', "Print only error messages.", &opt_silent, &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip_database", 0, "Don't process the database specified as argument", @@ -1112,8 +1106,6 @@ static int dbConnect(char *host, char *user, char *passwd) #endif if (opt_protocol) mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); - if (shared_memory_base_name) - mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); if (opt_plugin_dir && *opt_plugin_dir) mysql_options(&mysql_connection, MYSQL_PLUGIN_DIR, opt_plugin_dir); @@ -1253,8 +1245,7 @@ int main(int argc, char **argv) delete_dynamic(&alter_table_cmds); } end1: - my_free(opt_password); - my_free(shared_memory_base_name); + my_free(opt_password);; mysql_library_end(); free_defaults(defaults_argv); my_end(my_end_arg); diff --git a/client/mysqldump.c b/client/mysqldump.c index a2ed3c0504c..48eb2dfdb5e 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -159,9 +159,6 @@ static MYSQL_RES *routine_res, *routine_list_res; FILE *md_result_file= 0; FILE *stderror_file=0; -#ifdef HAVE_SMEM -static char *shared_memory_base_name=0; -#endif static uint opt_protocol= 0; static char *opt_plugin_dir= 0, *opt_default_auth= 0; @@ -257,10 +254,10 @@ static struct my_option my_long_options[] = 1, 0, 0, 0, 0, 0}, {"compatible", OPT_COMPATIBLE, "Change the dump to be compatible with a given mode. By default tables " - "are dumped in a format optimized for MySQL. Legal modes are: ansi, " + "are dumped in a format optimized for MariaDB. Legal modes are: ansi, " "mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb, no_key_options, " "no_table_options, no_field_options. One can use several modes separated " - "by commas. Note: Requires MySQL server version 4.1.0 or higher. " + "by commas. Note: Requires MariaDB server version 4.1.0 or higher. " "This option is ignored with earlier server versions.", &opt_compatible_mode_str, &opt_compatible_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -277,7 +274,7 @@ static struct my_option my_long_options[] = &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"create-options", 'a', - "Include all MySQL specific create options.", + "Include all MariaDB specific create options.", &create_options, &create_options, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"databases", 'B', @@ -472,7 +469,7 @@ static struct my_option my_long_options[] = &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, - "The protocol to use for connection (tcp, socket, pipe, memory).", + "The protocol to use for connection (tcp, socket, pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"quick", 'q', "Don't buffer query, dump directly to stdout.", &quick, &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, @@ -494,11 +491,6 @@ static struct my_option my_long_options[] = "Add 'SET NAMES default_character_set' to the output.", &opt_set_charset, &opt_set_charset, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name, - 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif /* Note that the combination --single-transaction --master-data will give bullet-proof binlog position only if server >=4.1.3. That's the @@ -650,7 +642,7 @@ static void usage(void) { print_version(); puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); - puts("Dumping structure and contents of MySQL databases and tables."); + puts("Dumping structure and contents of MariaDB databases and tables."); short_usage_sub(stdout); print_defaults("my",load_default_groups); puts(""); @@ -708,7 +700,7 @@ static void write_header(FILE *sql_file, char *db_name) else if (!opt_compact) { print_comment(sql_file, 0, - "-- MySQL dump %s Distrib %s, for %s (%s)\n--\n", + "-- MariaDB dump %s Distrib %s, for %s (%s)\n--\n", DUMP_VERSION, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE); print_comment(sql_file, 0, "-- Host: %s ", @@ -1719,10 +1711,6 @@ static int connect_to_db(char *host, char *user,char *passwd) #endif if (opt_protocol) mysql_options(&mysql_connection,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(&mysql_connection,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); -#endif mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset); if (opt_plugin_dir && *opt_plugin_dir) @@ -5527,7 +5515,7 @@ static int start_transaction(MYSQL *mysql_con) if ((mysql_get_server_version(mysql_con) < 40100) && opt_master_data) { fprintf(stderr, "-- %s: the combination of --single-transaction and " - "--master-data requires a MySQL server version of at least 4.1 " + "--master-data requires a MariaDB server version of at least 4.1 " "(current server's version is %s). %s\n", ignore_errors ? "Warning" : "Error", mysql_con->server_version ? mysql_con->server_version : "unknown", @@ -6255,10 +6243,6 @@ err: if (opt_slave_data) do_start_slave_sql(mysql); -#ifdef HAVE_SMEM - my_free(shared_memory_base_name); -#endif - dbDisconnect(current_host); if (!path) write_footer(md_result_file); diff --git a/client/mysqlimport.c b/client/mysqlimport.c index c7432992d45..977e0e6ca1e 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -65,10 +65,6 @@ static longlong opt_ignore_lines= -1; static char **argv_to_free; -#ifdef HAVE_SMEM -static char *shared_memory_base_name=0; -#endif - static struct my_option my_long_options[] = { {"character-sets-dir", OPT_CHARSETS_DIR, @@ -157,15 +153,10 @@ static struct my_option my_long_options[] = &opt_mysql_port, &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replace", 'r', "If duplicate unique key was found, replace old row.", &replace, &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name, - 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif {"silent", 's', "Be more silent.", &silent, &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", @@ -204,13 +195,14 @@ static void usage(void) { puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc."); puts("Copyright 2008-2011 Oracle and Monty Program Ab."); + puts("Copyright 2012-2019 MariaDB Corporation Ab."); print_version(); puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); printf("\ Loads tables from text files in various formats. The base name of the\n\ text file must be the name of the table that should be used.\n\ -If one uses sockets to connect to the MySQL server, the server will open and\n\ -read the text file directly. In other cases the client will open the text\n\ +If one uses sockets to connect to the MariaDB server, the server will open\n\ +and read the text file directly. In other cases the client will open the text\n\ file. The SQL command 'LOAD DATA INFILE' is used to import the rows.\n"); printf("\nUsage: %s [OPTIONS] database textfile...\n",my_progname); @@ -458,10 +450,6 @@ static MYSQL *db_connect(char *host, char *database, #endif if (opt_protocol) mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); -#endif if (opt_plugin_dir && *opt_plugin_dir) mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir); @@ -514,9 +502,6 @@ static void safe_exit(int error, MYSQL *mysql) if (mysql) mysql_close(mysql); -#ifdef HAVE_SMEM - my_free(shared_memory_base_name); -#endif free_defaults(argv_to_free); mysql_library_end(); my_free(opt_password); diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 484ca661d9e..a6108ef4fc1 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -39,9 +39,6 @@ static uint opt_verbose=0; static char *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME; static char *opt_plugin_dir= 0, *opt_default_auth= 0; -#ifdef HAVE_SMEM -static char *shared_memory_base_name=0; -#endif static uint opt_protocol=0; static void get_options(int *argc,char ***argv); @@ -131,10 +128,7 @@ int main(int argc, char **argv) #endif if (opt_protocol) mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); -#endif + mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); if (opt_plugin_dir && *opt_plugin_dir) @@ -177,9 +171,6 @@ error: mysql_close(&mysql); /* Close & free connection */ my_free(opt_password); mysql_server_end(); -#ifdef HAVE_SMEM - my_free(shared_memory_base_name); -#endif free_defaults(defaults_argv); my_end(my_end_arg); exit(error ? 1 : 0); @@ -243,14 +234,8 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"protocol", OPT_MYSQL_PROTOCOL, - "The protocol to use for connection (tcp, socket, pipe, memory).", + "The protocol to use for connection (tcp, socket, pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", &shared_memory_base_name, - &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, -#endif {"show-table-type", 't', "Show table type column.", &opt_table_type, &opt_table_type, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -283,7 +268,7 @@ static void usage(void) { print_version(); puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); - puts("Shows the structure of a MySQL database (databases, tables, and columns).\n"); + puts("Shows the structure of a MariaDB database (databases, tables, and columns).\n"); printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname); puts("\n\ If last argument contains a shell or SQL wildcard (*,?,% or _) then only\n\ @@ -673,7 +658,7 @@ list_table_status(MYSQL *mysql,const char *db,const char *wild) fprintf(stderr,"%s: Cannot get status for db: %s, table: %s: %s\n", my_progname,db,wild ? wild : "",mysql_error(mysql)); if (mysql_errno(mysql) == ER_PARSE_ERROR) - fprintf(stderr,"This error probably means that your MySQL server doesn't support the\n\'show table status' command.\n"); + fprintf(stderr,"This error probably means that your MariaDB server doesn't support the\n\'show table status' command.\n"); return 1; } diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 4cb6cbcc15b..8c79da88e41 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -98,9 +98,6 @@ TODO: #define snprintf _snprintf #endif -#ifdef HAVE_SMEM -static char *shared_memory_base_name=0; -#endif /* Global Thread counter */ uint thread_counter; @@ -309,10 +306,6 @@ void set_mysql_connect_options(MYSQL *mysql) #endif if (opt_protocol) mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); -#endif mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset); } @@ -423,10 +416,6 @@ int main(int argc, char **argv) statement_cleanup(pre_statements); statement_cleanup(post_statements); option_cleanup(engine_options); - -#ifdef HAVE_SMEM - my_free(shared_memory_base_name); -#endif free_defaults(defaults_argv); mysql_library_end(); my_end(my_end_arg); @@ -634,7 +623,7 @@ static struct my_option my_long_options[] = {"host", 'h', "Connect to host.", &host, &host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"init-command", OPT_INIT_COMMAND, - "SQL Command to execute when connecting to MySQL server. Will " + "SQL Command to execute when connecting to MariaDB server. Will " "automatically be re-executed when reconnecting.", &opt_init_command, &opt_init_command, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -689,17 +678,11 @@ static struct my_option my_long_options[] = &pre_system, &pre_system, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, - "The protocol to use for connection (tcp, socket, pipe, memory).", + "The protocol to use for connection (tcp, socket, pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"query", 'q', "Query to run or file containing query to run.", &user_supplied_query, &user_supplied_query, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", &shared_memory_base_name, - &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, -#endif {"silent", 's', "Run program in silent mode - no output.", &opt_silent, &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 47e92eba7f8..a65dcc7da93 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -107,7 +107,6 @@ enum { static int record= 0, opt_sleep= -1; static char *opt_db= 0, *opt_pass= 0; const char *opt_user= 0, *opt_host= 0, *unix_sock= 0, *opt_basedir= "./"; -static char *shared_memory_base_name=0; const char *opt_logdir= ""; const char *opt_prologue= 0, *opt_charsets_dir; static int opt_port= 0; @@ -5950,7 +5949,6 @@ do_handle_error: <opts> - options to use for the connection * SSL - use SSL if available * COMPRESS - use compression if available - * SHM - use shared memory if available * PIPE - use named pipe if available */ @@ -5962,7 +5960,6 @@ void do_connect(struct st_command *command) char *ssl_cipher __attribute__((unused))= 0; 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; int connect_timeout= 0; @@ -5977,9 +5974,6 @@ void do_connect(struct st_command *command) static DYNAMIC_STRING ds_sock; static DYNAMIC_STRING ds_options; static DYNAMIC_STRING ds_default_auth; -#ifdef HAVE_SMEM - static DYNAMIC_STRING ds_shm; -#endif const struct command_arg connect_args[] = { { "connection name", ARG_STRING, TRUE, &ds_connection_name, "Name of the connection" }, { "host", ARG_STRING, TRUE, &ds_host, "Host to connect to" }, @@ -6008,19 +6002,15 @@ void do_connect(struct st_command *command) die("Illegal argument for port: '%s'", ds_port.str); } -#ifdef HAVE_SMEM - /* Shared memory */ - init_dynamic_string(&ds_shm, ds_sock.str, 0, 0); -#endif - /* Sock */ if (ds_sock.length) { /* If the socket is specified just as a name without path + or an abstract socket indicator ('@'), then append tmpdir in front */ - if (*ds_sock.str != FN_LIBCHAR) + if (*ds_sock.str != FN_LIBCHAR && *ds_sock.str != '@') { char buff[FN_REFLEN]; fn_format(buff, ds_sock.str, TMPDIR, "", 0); @@ -6060,8 +6050,6 @@ void do_connect(struct st_command *command) con_compress= 1; else if (length == 4 && !strncmp(con_options, "PIPE", 4)) 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) { @@ -6167,22 +6155,6 @@ void do_connect(struct st_command *command) (char*)&connect_timeout); } -#ifdef HAVE_SMEM - if (con_shm) - { - uint protocol= MYSQL_PROTOCOL_MEMORY; - if (!ds_shm.length) - die("Missing shared memory base name"); - mysql_options(con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, ds_shm.str); - mysql_options(con_slot->mysql, MYSQL_OPT_PROTOCOL, &protocol); - } - else if (shared_memory_base_name) - { - mysql_options(con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, - shared_memory_base_name); - } -#endif - /* Use default db name */ if (ds_database.length == 0) dynstr_set(&ds_database, opt_db); @@ -6222,9 +6194,6 @@ void do_connect(struct st_command *command) dynstr_free(&ds_sock); dynstr_free(&ds_options); dynstr_free(&ds_default_auth); -#ifdef HAVE_SMEM - dynstr_free(&ds_shm); -#endif DBUG_VOID_RETURN; } @@ -7116,7 +7085,7 @@ static struct my_option my_long_options[] = GET_INT, REQUIRED_ARG, DEFAULT_MAX_CONN, 8, 5120, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", + {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection or 0 for default to, in " "order of preference, my.cnf, $MYSQL_TCP_PORT, " @@ -7149,10 +7118,6 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"server-file", 'F', "Read embedded server arguments from file.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"shared-memory-base-name", 0, - "Base name of shared memory.", &shared_memory_base_name, - &shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, - 0, 0, 0}, {"silent", 's', "Suppress all normal output. Synonym for --quiet.", &silent, &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"sleep", 'T', "Always sleep this many seconds on sleep commands.", @@ -7213,7 +7178,7 @@ void usage() { print_version(); puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); - printf("Runs a test against the mysql server and compares output with a results file.\n\n"); + printf("Runs a test against the MariaDB server and compares output with a results file.\n\n"); printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname); print_defaults("my",load_default_groups); puts(""); @@ -7971,7 +7936,7 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) static void handle_no_active_connection(struct st_command *command, struct st_connection *cn, DYNAMIC_STRING *ds) { - handle_error(command, 2006, "MySQL server has gone away", "000000", ds); + handle_error(command, 2006, "MariaDB server has gone away", "000000", ds); cn->pending= FALSE; var_set_errno(2006); } @@ -9290,7 +9255,7 @@ int main(int argc, char **argv) if (mysql_server_init(embedded_server_arg_count, embedded_server_args, (char**) embedded_server_groups)) - die("Can't initialize MySQL server"); + die("Can't initialize MariaDB server"); server_initialized= 1; if (cur_file == file_stack && cur_file->file == 0) { @@ -9349,11 +9314,6 @@ int main(int argc, char **argv) } #endif -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(con->mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); -#endif - if (!(con->name = my_strdup("default", MYF(MY_WME)))) die("Out of memory"); mysql_options(con->mysql, MYSQL_OPT_NONBLOCK, 0); @@ -10022,7 +9982,7 @@ void do_get_replace(struct st_command *command) char *buff, *start; char word_end_chars[256], *pos; POINTER_ARRAY to_array, from_array; - DBUG_ENTER("get_replace"); + DBUG_ENTER("do_get_replace"); free_replace(); diff --git a/cmake/configure.pl b/cmake/configure.pl index c502a172a22..dfd961ee085 100644 --- a/cmake/configure.pl +++ b/cmake/configure.pl @@ -145,6 +145,11 @@ foreach my $option (@ARGV) $cmakeargs = $cmakeargs." -DPLUGIN_".uc($1)."=".uc($2); next; } + if($option =~ /without-wsrep/) + { + $cmakeargs = $cmakeargs." -DWITH_WSREP=OFF"; + next; + } if($option =~ /with-zlib-dir=bundled/) { $cmakeargs = $cmakeargs." -DWITH_ZLIB=bundled"; @@ -185,6 +190,16 @@ foreach my $option (@ARGV) $cmakeargs = $cmakeargs." -DCMAKE_BUILD_TYPE=Debug -DSECURITY_HARDENED=OFF"; next; } + if($option =~ /with-(.*)=(.*)/) + { + $cmakeargs = $cmakeargs. " -DWITH_" . uc($1) . "=" . uc($2); + next; + } + if($option =~ /without-(.*)=(.*)/) + { + $cmakeargs = $cmakeargs. " -DWITHOUT_" . uc($1) . "=" . uc($2); + next; + } if($option =~ /prefix=/) { $cmake_install_prefix= substr($option, 7); diff --git a/cmake/os/Windows.cmake b/cmake/os/Windows.cmake index d7e748a6d71..44a9c2e823c 100644 --- a/cmake/os/Windows.cmake +++ b/cmake/os/Windows.cmake @@ -96,7 +96,8 @@ IF(MSVC) # Disable mingw based pkg-config found in Strawberry perl SET(PKG_CONFIG_EXECUTABLE 0 CACHE INTERNAL "") - SET(MSVC_CRT_TYPE /MT CACHE STRING + + SET(MSVC_CRT_TYPE /MD CACHE STRING "Runtime library - specify runtime library for linking (/MT,/MTd,/MD,/MDd)" ) SET(VALID_CRT_TYPES /MTd /MDd /MD /MT) @@ -106,9 +107,7 @@ IF(MSVC) IF(MSVC_CRT_TYPE MATCHES "/MD") # Dynamic runtime (DLLs), need to install CRT libraries. - SET(CMAKE_INSTALL_MFC_LIBRARIES TRUE)# upgrade wizard SET(CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT VCCRT) - SET(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS TRUE) SET(CMAKE_INSTALL_UCRT_LIBRARIES TRUE) IF(MSVC_CRT_TYPE STREQUAL "/MDd") SET (CMAKE_INSTALL_DEBUG_LIBRARIES_ONLY TRUE) @@ -277,3 +276,17 @@ ENDIF() SET(FN_NO_CASE_SENSE 1) SET(USE_SYMDIR 1) + +# Force static C runtime for targets in current directory +# (useful to get rid of MFC dll's dependency, or in installer) +MACRO(FORCE_STATIC_CRT) + FOREACH(flag + CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG_INIT + CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG_INIT + CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL + ) + STRING(REGEX REPLACE "/MD[d]?" "/MT" "${flag}" "${${flag}}" ) + ENDFOREACH() +ENDMACRO() diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index 2ba3aec16b4..f51015e436c 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -153,6 +153,7 @@ SET(HAVE_SIGSET CACHE INTERNAL "") SET(HAVE_SIGTERM 1 CACHE INTERNAL "") SET(HAVE_SIGTHREADMASK CACHE INTERNAL "") SET(HAVE_SIGWAIT CACHE INTERNAL "") +SET(HAVE_SIGWAITINFO CACHE INTERNAL "") SET(HAVE_SIZEOF_CHARP TRUE CACHE INTERNAL "") SET(SIZEOF_CHARP ${CMAKE_SIZEOF_VOID_P} CACHE INTERNAL "") SET(HAVE_SIZEOF_IN6_ADDR TRUE CACHE INTERNAL "") diff --git a/config.h.cmake b/config.h.cmake index 3974c2a3618..247d983c501 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -219,6 +219,7 @@ #cmakedefine HAVE_SIGACTION 1 #cmakedefine HAVE_SIGTHREADMASK 1 #cmakedefine HAVE_SIGWAIT 1 +#cmakedefine HAVE_SIGWAITINFO 1 #cmakedefine HAVE_SLEEP 1 #cmakedefine HAVE_SNPRINTF 1 #cmakedefine HAVE_STPCPY 1 diff --git a/configure.cmake b/configure.cmake index 42ba2496105..08eac106e6a 100644 --- a/configure.cmake +++ b/configure.cmake @@ -400,6 +400,7 @@ CHECK_FUNCTION_EXISTS (setlocale HAVE_SETLOCALE) CHECK_FUNCTION_EXISTS (sigaction HAVE_SIGACTION) CHECK_FUNCTION_EXISTS (sigthreadmask HAVE_SIGTHREADMASK) CHECK_FUNCTION_EXISTS (sigwait HAVE_SIGWAIT) +CHECK_FUNCTION_EXISTS (sigwaitinfo HAVE_SIGWAITINFO) CHECK_FUNCTION_EXISTS (sigset HAVE_SIGSET) CHECK_FUNCTION_EXISTS (sleep HAVE_SLEEP) CHECK_FUNCTION_EXISTS (snprintf HAVE_SNPRINTF) diff --git a/debian/additions/debian-start.inc.sh b/debian/additions/debian-start.inc.sh index 0640bf9c2a6..fa5b1299bdc 100755 --- a/debian/additions/debian-start.inc.sh +++ b/debian/additions/debian-start.inc.sh @@ -60,7 +60,7 @@ function upgrade_system_tables_if_necessary() { # errors as the script is designed to be idempotent. LC_ALL=C $MYUPGRADE \ 2>&1 \ - | egrep -v '^(1|@had|ERROR (1054|1060|1061))' \ + | egrep -v '^(1|@had|ERROR (1051|1054|1060|1061|1146|1347|1348))' \ | logger -p daemon.warn -i -t$0 } diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh index 4e66f13615f..1c72ad28a3d 100755 --- a/debian/autobake-deb.sh +++ b/debian/autobake-deb.sh @@ -16,11 +16,11 @@ export DEB_BUILD_OPTIONS="nocheck $DEB_BUILD_OPTIONS" if [[ $TRAVIS ]] then # On Travis-CI, the log must stay under 4MB so make the build less verbose - sed -i -e '/Add support for verbose builds/,+2d' debian/rules + sed -i -e '/Add support for verbose builds/,/^$/d' debian/rules # Don't include test suite package on Travis-CI to make the build time shorter - sed '/Package: mariadb-test-data/,+28d' -i debian/control - sed '/Package: mariadb-test/,+36d' -i debian/control + sed '/Package: mariadb-test-data/,/^$/d' -i debian/control + sed '/Package: mariadb-test$/,/^$/d' -i debian/control # Don't build the test package at all to save time and disk space sed 's|DINSTALL_MYSQLTESTDIR=share/mysql/mysql-test|DINSTALL_MYSQLTESTDIR=false|' -i debian/rules @@ -47,7 +47,7 @@ GCCVERSION=$(gcc -dumpfullversion -dumpversion | sed -e 's/\.\([0-9][0-9]\)/\1/g if ! apt-cache madison libcrack2-dev | grep 'libcrack2-dev *| *2\.9' >/dev/null 2>&1 then sed '/libcrack2-dev/d' -i debian/control - sed '/Package: mariadb-plugin-cracklib/,+9d' -i debian/control + sed '/Package: mariadb-plugin-cracklib/,/^$/d' -i debian/control fi # If libpcre3-dev (>= 2:8.35-3.2~) is not available (before Debian Jessie or Ubuntu Wily) @@ -67,9 +67,9 @@ then sed 's/ --with systemd//' -i debian/rules sed '/systemd/d' -i debian/rules sed '/\.service/d' -i debian/rules - sed '/galera_new_cluster/d' -i debian/mariadb-server-10.3.install - sed '/galera_recovery/d' -i debian/mariadb-server-10.3.install - sed '/mariadb-service-convert/d' -i debian/mariadb-server-10.3.install + sed '/galera_new_cluster/d' -i debian/mariadb-server-10.4.install + sed '/galera_recovery/d' -i debian/mariadb-server-10.4.install + sed '/mariadb-service-convert/d' -i debian/mariadb-server-10.4.install fi # If libzstd-dev is not available (before Debian Stretch and Ubuntu Xenial) @@ -94,7 +94,7 @@ fi # x86 32 bit. if [[ $GCCVERSION -lt 40800 ]] || [[ $(arch) =~ i[346]86 ]] || [[ $TRAVIS ]] then - sed '/Package: mariadb-plugin-rocksdb/,+14d' -i debian/control + sed '/Package: mariadb-plugin-rocksdb/,/^$/d' -i debian/control fi # AWS SDK requires c++11 -capable compiler. @@ -112,7 +112,7 @@ Breaks: mariadb-aws-key-management-10.1, mariadb-aws-key-management-10.2 Replaces: mariadb-aws-key-management-10.1, mariadb-aws-key-management-10.2 -Depends: mariadb-server-10.3, +Depends: mariadb-server-10.4, \${misc:Depends}, \${shlibs:Depends} Description: Amazon Web Service Key Management Service Plugin for MariaDB @@ -127,12 +127,12 @@ fi # Mroonga, TokuDB never built on Travis CI anyway, see build flags above if [[ $TRAVIS ]] then - sed -i -e "/Package: mariadb-plugin-tokudb/,+19d" debian/control - sed -i -e "/Package: mariadb-plugin-mroonga/,+17d" debian/control - sed -i -e "/Package: mariadb-plugin-spider/,+18d" debian/control - sed -i -e "/Package: mariadb-plugin-oqgraph/,+16d" debian/control - sed -i -e "/usr\/lib\/mysql\/plugin\/ha_sphinx.so/d" debian/mariadb-server-10.3.install - sed -i -e "/Package: libmariadbd-dev/,+19d" debian/control + sed -i -e "/Package: mariadb-plugin-tokudb/,/^$/d" debian/control + sed -i -e "/Package: mariadb-plugin-mroonga/,/^$/d" debian/control + sed -i -e "/Package: mariadb-plugin-spider/,/^$/d" debian/control + sed -i -e "/Package: mariadb-plugin-oqgraph/,/^$/d" debian/control + sed -i -e "/usr\/lib\/mysql\/plugin\/ha_sphinx.so/d" debian/mariadb-server-10.4.install + sed -i -e "/Package: libmariadbd-dev/,/^$/d" debian/control fi # Adjust changelog, add new version diff --git a/debian/changelog b/debian/changelog index dec49bd4282..053727796d0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +mariadb-10.4 (1:10.4.0) unstable; urgency=low + + * Initial release. + + -- Otto Kekäläinen <otto@debian.org> Sun, 05 Aug 2018 00:06:30 -0500 + mariadb-10.3 (1:10.3.0) unstable; urgency=low * Bump epoch to supersede 1:10.1.29-6 in Debian diff --git a/debian/control b/debian/control index d352f9a3712..c990f4cfe5a 100644 --- a/debian/control +++ b/debian/control @@ -1,4 +1,4 @@ -Source: mariadb-10.3 +Source: mariadb-10.4 Section: database Priority: optional Maintainer: MariaDB Developers <maria-developers@lists.launchpad.net> @@ -38,6 +38,51 @@ Homepage: http://mariadb.org/ Vcs-Browser: https://github.com/MariaDB/server/ Vcs-Git: https://github.com/MariaDB/server.git +Package: libmariadb3 +Architecture: any +Multi-Arch: same +Section: libs +Depends: mariadb-common, + ${misc:Depends}, + ${shlibs:Depends} +Conflicts: libmariadbclient18 (<< 10.2.0), + mariadb-galera-server-10.0 (<< 10.0.5), + mariadb-galera-server-5.5 (<< 5.5.33), + mariadb-server-10.0 (<< 10.0.5), + mariadb-server-5.1, + mariadb-server-5.2, + mariadb-server-5.3, + mariadb-server-5.5 (<< 5.5.33) +Description: MariaDB database client library + MariaDB is a fast, stable and true multi-user, multi-threaded SQL database + server. SQL (Structured Query Language) is the most popular database query + language in the world. The main goals of MariaDB are speed, robustness and + ease of use. + . + This package includes the client library. + +Package: libmariadb3-compat +Architecture: any +Section: libs +Depends: libmariadb3, + mariadb-common, + ${misc:Depends}, + ${shlibs:Depends} +Breaks: libmysqlclient19, + libmysqlclient20 +Replaces: libmysqlclient19, + libmysqlclient20 +Provides: libmysqlclient19, + libmysqlclient20 +Description: MariaDB database client library MySQL compat package + MariaDB is a fast, stable and true multi-user, multi-threaded SQL database + server. SQL (Structured Query Language) is the most popular database query + language in the world. The main goals of MariaDB are speed, robustness and + ease of use. + . + This package includes the client runtime libraries that simulate and replace + the equivalents found in MySQL 5.6 and 5.7 (mysqlclient19 and 20). + Package: libmariadb-dev Architecture: any Multi-Arch: same @@ -90,53 +135,6 @@ Description: MariaDB Connector/C, compatibility symlinks This package includes compatibility symlinks to allow sources expecting the MySQL client libraries to be built against MariaDB Connector/C. -Package: libmariadb3 -Architecture: any -Multi-Arch: same -Section: libs -Depends: mariadb-common, - ${misc:Depends}, - ${shlibs:Depends} -Conflicts: libmariadbclient18 (<< 10.2.0), - mariadb-galera-server-10.0 (<< 10.0.5), - mariadb-galera-server-5.5 (<< 5.5.33), - mariadb-server-10.0 (<< 10.0.5), - mariadb-server-5.1, - mariadb-server-5.2, - mariadb-server-5.3, - mariadb-server-5.5 (<< 5.5.33) -Breaks: libmariadbclient18 (<< ${source:Version}) -Replaces: libmariadbclient18 (<< ${source:Version}) -Description: MariaDB database client library - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the client library. - -Package: libmariadb3-compat -Architecture: any -Section: libs -Depends: libmariadb3, - mariadb-common, - ${misc:Depends}, - ${shlibs:Depends} -Breaks: libmysqlclient19, - libmysqlclient20 -Replaces: libmysqlclient19, - libmysqlclient20 -Provides: libmysqlclient19, - libmysqlclient20 -Description: MariaDB database client library MySQL compat package - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes the client runtime libraries that simulate and replace - the equivalents found in MySQL 5.6 and 5.7 (mysqlclient19 and 20). - Package: libmariadbclient18 Section: libs Architecture: any @@ -169,6 +167,22 @@ Description: Virtual package to satisfy external libmysqlclient18 depends This package provides compatibility symlinks for binaries that expect to find libmysqlclient.so.18 will automatically use libmariadb.so.3 instead. +Package: libmariadbd19 +Architecture: any +Multi-Arch: same +Section: libs +Depends: ${misc:Depends}, + ${shlibs:Depends} +Breaks: libmariadbd-dev (<< ${source:Version}) +Replaces: libmariadbd-dev (<< ${source:Version}) +Description: MariaDB embedded database, shared library + MariaDB is a fast, stable and true multi-user, multi-threaded SQL database + server. SQL (Structured Query Language) is the most popular database query + language in the world. The main goals of MariaDB are speed, robustness and + ease of use. + . + This package includes a shared library for embedded MariaDB applications + Package: libmariadbd-dev Architecture: any Multi-Arch: same @@ -189,22 +203,6 @@ Description: MariaDB embedded database, development files . This package includes the embedded server library development and header files. -Package: libmariadbd19 -Architecture: any -Multi-Arch: same -Section: libs -Depends: ${misc:Depends}, - ${shlibs:Depends} -Breaks: libmariadbd-dev (<< ${source:Version}) -Replaces: libmariadbd-dev (<< ${source:Version}) -Description: MariaDB embedded database, shared library - MariaDB is a fast, stable and true multi-user, multi-threaded SQL database - server. SQL (Structured Query Language) is the most popular database query - language in the world. The main goals of MariaDB are speed, robustness and - ease of use. - . - This package includes a shared library for embedded MariaDB applications - Package: mysql-common Architecture: all Depends: ${misc:Depends}, @@ -232,7 +230,7 @@ Description: MariaDB database common files (e.g. /etc/mysql/conf.d/mariadb.cnf) This package includes files needed by all versions of the client library (e.g. /etc/mysql/conf.d/mariadb.cnf). -Package: mariadb-client-core-10.3 +Package: mariadb-client-core-10.4 Architecture: any Depends: mariadb-common (>= ${source:Version}), ${misc:Depends}, @@ -240,6 +238,7 @@ Depends: mariadb-common (>= ${source:Version}), Conflicts: mariadb-client-10.0, mariadb-client-10.1, mariadb-client-10.2, + mariadb-client-10.3, mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3, @@ -247,6 +246,7 @@ Conflicts: mariadb-client-10.0, mariadb-client-core-10.0, mariadb-client-core-10.1, mariadb-client-core-10.2, + mariadb-client-core-10.3, mariadb-client-core-5.1, mariadb-client-core-5.2, mariadb-client-core-5.3, @@ -263,6 +263,7 @@ Conflicts: mariadb-client-10.0, Replaces: mariadb-client-10.0, mariadb-client-10.1, mariadb-client-10.2, + mariadb-client-10.3, mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3, @@ -270,6 +271,7 @@ Replaces: mariadb-client-10.0, mariadb-client-core-10.0, mariadb-client-core-10.1, mariadb-client-core-10.2, + mariadb-client-core-10.3, mariadb-client-core-5.1, mariadb-client-core-5.2, mariadb-client-core-5.3, @@ -298,10 +300,10 @@ Description: MariaDB database core client binaries . This package includes the core client files, as used by Akonadi. -Package: mariadb-client-10.3 +Package: mariadb-client-10.4 Architecture: any Depends: debianutils (>=1.6), - mariadb-client-core-10.3 (>= ${source:Version}), + mariadb-client-core-10.4 (>= ${source:Version}), mariadb-common, ${misc:Depends}, ${perl:Depends}, @@ -310,6 +312,7 @@ Conflicts: mariadb-client (<< ${source:Version}), mariadb-client-10.0, mariadb-client-10.1, mariadb-client-10.2, + mariadb-client-10.3, mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3, @@ -325,6 +328,7 @@ Replaces: mariadb-client (<< ${source:Version}), mariadb-client-10.0, mariadb-client-10.1, mariadb-client-10.2, + mariadb-client-10.3, mariadb-client-5.1, mariadb-client-5.2, mariadb-client-5.3, @@ -356,13 +360,15 @@ Description: MariaDB database client binaries This package includes the client binaries and the additional tools innotop and mysqlreport. -Package: mariadb-server-core-10.3 +Package: mariadb-server-core-10.4 Architecture: any Depends: mariadb-common (>= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} Conflicts: mariadb-server-core-10.0, mariadb-server-core-10.1, + mariadb-server-core-10.2, + mariadb-server-core-10.3, mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.3, @@ -377,16 +383,17 @@ Conflicts: mariadb-server-core-10.0, Breaks: mariadb-client-10.0, mariadb-client-10.1, mariadb-client-10.2, - mariadb-client-10.3 (<< ${source:Version}), - mariadb-server-10.3 (<< ${source:Version}) + mariadb-client-10.3, + mariadb-server-10.3 Replaces: mariadb-client-10.0, mariadb-client-10.1, mariadb-client-10.2, - mariadb-client-10.3 (<< ${source:Version}), - mariadb-server-10.3 (<< ${source:Version}), + mariadb-client-10.3, + mariadb-server-10.3, mariadb-server-core-10.0, mariadb-server-core-10.1, mariadb-server-core-10.2, + mariadb-server-core-10.3, mariadb-server-core-5.1, mariadb-server-core-5.2, mariadb-server-core-5.3, @@ -413,7 +420,7 @@ Description: MariaDB database core server files . This package includes the core server files, as used by Akonadi. -Package: mariadb-server-10.3 +Package: mariadb-server-10.4 Architecture: any Suggests: mailx, mariadb-test, @@ -429,8 +436,8 @@ Depends: galera-3 (>=25.3), libdbi-perl, lsb-base (>= 3.0-10), lsof, - mariadb-client-10.3 (>= ${source:Version}), - mariadb-server-core-10.3 (>= ${binary:Version}), + mariadb-client-10.4 (>= ${source:Version}), + mariadb-server-core-10.4 (>= ${binary:Version}), passwd, perl (>= 5.6), psmisc, @@ -442,6 +449,7 @@ Conflicts: mariadb-server (<< ${source:Version}), mariadb-server-10.0, mariadb-server-10.1, mariadb-server-10.2, + mariadb-server-10.3, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, @@ -464,6 +472,7 @@ Replaces: libmariadbclient-dev (<< 5.5.0), mariadb-server-10.0, mariadb-server-10.1, mariadb-server-10.2, + mariadb-server-10.3, mariadb-server-5.1, mariadb-server-5.2, mariadb-server-5.3, @@ -492,11 +501,11 @@ Description: MariaDB database server binaries Package: mariadb-server Architecture: all -Depends: mariadb-server-10.3 (>= ${source:Version}), +Depends: mariadb-server-10.4 (>= ${source:Version}), ${misc:Depends} Description: MariaDB database server (metapackage depending on the latest version) This is an empty package that depends on the current "best" version of - mariadb-server (currently mariadb-server-10.3), as determined by the MariaDB + mariadb-server (currently mariadb-server-10.4), as determined by the MariaDB maintainers. Install this package if in doubt about which MariaDB version you need. That will install the version recommended by the package maintainers. @@ -508,18 +517,34 @@ Description: MariaDB database server (metapackage depending on the latest versio Package: mariadb-client Architecture: all -Depends: mariadb-client-10.3 (>= ${source:Version}), +Depends: mariadb-client-10.4 (>= ${source:Version}), ${misc:Depends} Description: MariaDB database client (metapackage depending on the latest version) This is an empty package that depends on the current "best" version of - mariadb-client (currently mariadb-client-10.3), as determined by the MariaDB + mariadb-client (currently mariadb-client-10.4), as determined by the MariaDB maintainers. Install this package if in doubt about which MariaDB version you want, as this is the one considered to be in the best shape. +Package: mariadb-backup +Architecture: any +Breaks: mariadb-backup-10.1, + mariadb-backup-10.2 +Replaces: mariadb-backup-10.1, + mariadb-backup-10.2 +Depends: mariadb-client-core-10.4 (= ${binary:Version}), + ${misc:Depends}, + ${shlibs:Depends} +Description: Backup tool for MariaDB server + This backup tool is guaranteed to be compatible with MariaDB. + Based on Xtrabackup, but improved to work with MariaDB. + . + Plese refer to the MariaDB Knowledge Base on more information on + how to use this tool. + Package: mariadb-plugin-connect Architecture: any Depends: libxml2, - mariadb-server-10.3 (= ${binary:Version}), + mariadb-server-10.4 (= ${binary:Version}), unixodbc, ${misc:Depends}, ${shlibs:Depends} @@ -537,8 +562,7 @@ Description: Connect storage engine for MariaDB Package: mariadb-plugin-rocksdb Architecture: amd64 arm64 mips64el ppc64el -Depends: mariadb-server-10.3 (= ${binary:Version}), - libzstd1, +Depends: mariadb-server-10.4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: mariadb-rocksdb-engine-10.2, @@ -554,7 +578,7 @@ Description: RocksDB storage engine for MariaDB Package: mariadb-plugin-oqgraph Architecture: any Depends: libjudydebian1, - mariadb-server-10.3 (= ${binary:Version}), + mariadb-server-10.4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: mariadb-oqgraph-engine-10.1, @@ -570,18 +594,18 @@ Description: OQGraph storage engine for MariaDB Package: mariadb-plugin-tokudb Architecture: amd64 -Depends: mariadb-server-10.3 (= ${binary:Version}), - libjemalloc1 (>= 3.0.0~), +Depends: libjemalloc1 (>= 3.0.0~), + mariadb-server-10.4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: mariadb-server-10.0, mariadb-server-10.1, mariadb-server-10.2, - mariadb-server-10.3 (<< ${source:Version}) + mariadb-server-10.3 Replaces: mariadb-server-10.0, mariadb-server-10.1, mariadb-server-10.2, - mariadb-server-10.3 (<< ${source:Version}) + mariadb-server-10.3 Description: TokuDB storage engine for MariaDB The TokuDB storage engine is for use in high-performance and write-intensive environments, offering increased compression and better performance based @@ -590,17 +614,17 @@ Description: TokuDB storage engine for MariaDB Package: mariadb-plugin-mroonga Architecture: any-alpha any-amd64 any-arm any-arm64 any-i386 any-ia64 any-mips64el any-mips64r6el any-mipsel any-mipsr6el any-nios2 any-powerpcel any-ppc64el any-sh3 any-sh4 any-tilegx -Depends: mariadb-server-10.3 (= ${binary:Version}), +Depends: mariadb-server-10.4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: mariadb-server-10.0, mariadb-server-10.1, mariadb-server-10.2, - mariadb-server-10.3 (<< ${source:Version}) + mariadb-server-10.3 Replaces: mariadb-server-10.0, mariadb-server-10.1, mariadb-server-10.2, - mariadb-server-10.3 (<< ${source:Version}) + mariadb-server-10.3 Description: Mroonga storage engine for MariaDB Mroonga (formerly named Groonga Storage Engine) is a storage engine that provides fast CJK-ready full text searching using column store. @@ -608,17 +632,17 @@ Description: Mroonga storage engine for MariaDB Package: mariadb-plugin-spider Architecture: any -Depends: mariadb-server-10.3 (= ${binary:Version}), +Depends: mariadb-server-10.4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: mariadb-server-10.0, mariadb-server-10.1, mariadb-server-10.2, - mariadb-server-10.3 (<< ${source:Version}) + mariadb-server-10.3 Replaces: mariadb-server-10.0, mariadb-server-10.1, mariadb-server-10.2, - mariadb-server-10.3 (<< ${source:Version}) + mariadb-server-10.3 Description: Spider storage engine for MariaDB The Spider storage engine with built-in sharding features. It supports partitioning and xa transactions, and allows tables of different MariaDB @@ -627,17 +651,17 @@ Description: Spider storage engine for MariaDB Package: mariadb-plugin-cassandra Architecture: any -Depends: mariadb-server-10.3 (= ${binary:Version}), +Depends: mariadb-server-10.4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: mariadb-server-10.0, mariadb-server-10.1, mariadb-server-10.2, - mariadb-server-10.3 (<< ${source:Version}) + mariadb-server-10.3 Replaces: mariadb-server-10.0, mariadb-server-10.1, mariadb-server-10.2, - mariadb-server-10.3 (<< ${source:Version}) + mariadb-server-10.3 Description: Cassandra storage engine for MariaDB The Cassandra Storage Engine allows access to data in a Cassandra cluster from MariaDB, combining the best of SQL and no-SQL worlds. Cassandra SE (storage @@ -649,7 +673,7 @@ Description: Cassandra storage engine for MariaDB Package: mariadb-plugin-gssapi-server Architecture: any Depends: libgssapi-krb5-2, - mariadb-server-10.3, + mariadb-server-10.4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: mariadb-gssapi-server-10.1, @@ -667,7 +691,7 @@ Description: GSSAPI authentication plugin for MariaDB server Package: mariadb-plugin-gssapi-client Architecture: any Depends: libgssapi-krb5-2, - mariadb-client-10.3, + mariadb-client-10.4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: mariadb-gssapi-client-10.1, @@ -682,26 +706,10 @@ Description: GSSAPI authentication plugin for MariaDB client . This package contains the client parts. -Package: mariadb-backup -Architecture: any -Breaks: mariadb-backup-10.1, - mariadb-backup-10.2 -Replaces: mariadb-backup-10.1, - mariadb-backup-10.2 -Depends: mariadb-client-core-10.3 (= ${binary:Version}), - ${misc:Depends}, - ${shlibs:Depends} -Description: Backup tool for MariaDB server - This backup tool is guaranteed to be compatible with MariaDB. - Based on Xtrabackup, but improved to work with MariaDB. - . - Plese refer to the MariaDB Knowledge Base on more information on - how to use this tool. - Package: mariadb-plugin-cracklib-password-check Architecture: any Depends: libcrack2 (>= 2.9.0), - mariadb-server-10.3, + mariadb-server-10.4 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Description: CrackLib Password Validation Plugin for MariaDB @@ -710,8 +718,8 @@ Description: CrackLib Password Validation Plugin for MariaDB Package: mariadb-test Architecture: any -Depends: mariadb-client-10.3 (= ${binary:Version}), - mariadb-server-10.3 (= ${binary:Version}), +Depends: mariadb-client-10.4 (= ${binary:Version}), + mariadb-server-10.4 (= ${binary:Version}), mariadb-test-data (= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} @@ -719,6 +727,7 @@ Breaks: mariadb-server-5.5, mariadb-test-10.0, mariadb-test-10.1, mariadb-test-10.2, + mariadb-test-10.3, mariadb-test-5.5, mysql-testsuite, mysql-testsuite-5.5, @@ -729,6 +738,7 @@ Replaces: mariadb-server-5.5, mariadb-test-10.0, mariadb-test-10.1, mariadb-test-10.2, + mariadb-test-10.3, mariadb-test-5.5, mysql-testsuite, mysql-testsuite-5.5, diff --git a/debian/libmariadbd-dev.install b/debian/libmariadbd-dev.install index 2c14af5ab31..13d961409cc 100644 --- a/debian/libmariadbd-dev.install +++ b/debian/libmariadbd-dev.install @@ -1,4 +1,4 @@ -usr/lib/*/libmysqld.a usr/lib/*/libmariadbd.a -usr/lib/*/libmysqld.so usr/lib/*/libmariadbd.so +usr/lib/*/libmysqld.a +usr/lib/*/libmysqld.so diff --git a/debian/mariadb-client-10.3.README.Debian b/debian/mariadb-client-10.4.README.Debian index 64f0f509951..64f0f509951 100644 --- a/debian/mariadb-client-10.3.README.Debian +++ b/debian/mariadb-client-10.4.README.Debian diff --git a/debian/mariadb-client-10.3.docs b/debian/mariadb-client-10.4.docs index c09092629c3..c09092629c3 100644 --- a/debian/mariadb-client-10.3.docs +++ b/debian/mariadb-client-10.4.docs diff --git a/debian/mariadb-client-10.3.install b/debian/mariadb-client-10.4.install index 945bf77c689..945bf77c689 100644 --- a/debian/mariadb-client-10.3.install +++ b/debian/mariadb-client-10.4.install diff --git a/debian/mariadb-client-10.3.links b/debian/mariadb-client-10.4.links index 4a504969246..4a504969246 100644 --- a/debian/mariadb-client-10.3.links +++ b/debian/mariadb-client-10.4.links diff --git a/debian/mariadb-client-10.3.manpages b/debian/mariadb-client-10.4.manpages index 6f3e2bc188c..6f3e2bc188c 100644 --- a/debian/mariadb-client-10.3.manpages +++ b/debian/mariadb-client-10.4.manpages diff --git a/debian/mariadb-client-10.3.menu b/debian/mariadb-client-10.4.menu index 1894442ca20..58f7ebfc45f 100644 --- a/debian/mariadb-client-10.3.menu +++ b/debian/mariadb-client-10.4.menu @@ -1,3 +1,3 @@ # According to /usr/share/menu/ policy 1.4, not /usr/share/doc/debian-policy/ -?package(mariadb-client-10.3):needs="text" section="Applications/Data Management"\ +?package(mariadb-client-10.4):needs="text" section="Applications/Data Management"\ title="Innotop" command="/usr/bin/innotop" diff --git a/debian/mariadb-client-core-10.3.install b/debian/mariadb-client-core-10.4.install index a2781309439..a2781309439 100644 --- a/debian/mariadb-client-core-10.3.install +++ b/debian/mariadb-client-core-10.4.install diff --git a/debian/mariadb-plugin-rocksdb.install b/debian/mariadb-plugin-rocksdb.install index b9a6f7dc432..403c7f291b6 100644 --- a/debian/mariadb-plugin-rocksdb.install +++ b/debian/mariadb-plugin-rocksdb.install @@ -1,5 +1,5 @@ etc/mysql/conf.d/rocksdb.cnf etc/mysql/mariadb.conf.d -usr/bin/mysql_ldb usr/bin/myrocks_hotbackup +usr/bin/mysql_ldb usr/bin/sst_dump usr/lib/mysql/plugin/ha_rocksdb.so diff --git a/debian/mariadb-plugin-tokudb.install b/debian/mariadb-plugin-tokudb.install index e8925c1d4f1..40dd0e78c65 100644 --- a/debian/mariadb-plugin-tokudb.install +++ b/debian/mariadb-plugin-tokudb.install @@ -3,6 +3,6 @@ etc/systemd/system/mariadb.service.d/tokudb.conf usr/bin/tokuft_logprint usr/bin/tokuftdump usr/lib/mysql/plugin/ha_tokudb.so -usr/share/doc/mariadb-server-10.3/README.md usr/share/doc/mariadb-plugin-tokudb/README.md +usr/share/doc/mariadb-server-10.4/README.md usr/share/doc/mariadb-plugin-tokudb/README.md usr/share/man/man1/tokuft_logprint.1 usr/share/man/man1/tokuftdump.1 diff --git a/debian/mariadb-server-10.3.README.Debian b/debian/mariadb-server-10.4.README.Debian index 1e8b86f867c..1e8b86f867c 100644 --- a/debian/mariadb-server-10.3.README.Debian +++ b/debian/mariadb-server-10.4.README.Debian diff --git a/debian/mariadb-server-10.3.config b/debian/mariadb-server-10.4.config index 44640f2a441..44640f2a441 100644 --- a/debian/mariadb-server-10.3.config +++ b/debian/mariadb-server-10.4.config diff --git a/debian/mariadb-server-10.3.dirs b/debian/mariadb-server-10.4.dirs index 5057fe806c3..5057fe806c3 100644 --- a/debian/mariadb-server-10.3.dirs +++ b/debian/mariadb-server-10.4.dirs diff --git a/debian/mariadb-server-10.3.install b/debian/mariadb-server-10.4.install index a7d4d665892..f115b212c98 100644 --- a/debian/mariadb-server-10.3.install +++ b/debian/mariadb-server-10.4.install @@ -40,6 +40,8 @@ usr/bin/wsrep_sst_xtrabackup usr/bin/wsrep_sst_xtrabackup-v2 usr/lib/mysql/plugin/auth_ed25519.so usr/lib/mysql/plugin/auth_pam.so +usr/lib/mysql/plugin/auth_pam_tool_dir/auth_pam_tool +usr/lib/mysql/plugin/auth_pam_v1.so usr/lib/mysql/plugin/auth_socket.so usr/lib/mysql/plugin/disks.so usr/lib/mysql/plugin/file_key_management.so @@ -57,8 +59,8 @@ usr/lib/mysql/plugin/server_audit.so usr/lib/mysql/plugin/simple_password_check.so usr/lib/mysql/plugin/sql_errlog.so usr/lib/mysql/plugin/wsrep_info.so -usr/share/apport/package-hooks/source_mariadb-10.3.py -usr/share/doc/mariadb-server-10.3/mysqld.sym.gz +usr/share/apport/package-hooks/source_mariadb-10.4.py +usr/share/doc/mariadb-server-10.4/mysqld.sym.gz usr/share/man/man1/aria_chk.1 usr/share/man/man1/aria_dump_log.1 usr/share/man/man1/aria_ftdump.1 diff --git a/debian/mariadb-server-10.3.logcheck.ignore.paranoid b/debian/mariadb-server-10.4.logcheck.ignore.paranoid index 00cc5c3e29d..00cc5c3e29d 100644 --- a/debian/mariadb-server-10.3.logcheck.ignore.paranoid +++ b/debian/mariadb-server-10.4.logcheck.ignore.paranoid diff --git a/debian/mariadb-server-10.3.logcheck.ignore.server b/debian/mariadb-server-10.4.logcheck.ignore.server index a0b4792ecda..a0b4792ecda 100644 --- a/debian/mariadb-server-10.3.logcheck.ignore.server +++ b/debian/mariadb-server-10.4.logcheck.ignore.server diff --git a/debian/mariadb-server-10.3.logcheck.ignore.workstation b/debian/mariadb-server-10.4.logcheck.ignore.workstation index a0b4792ecda..a0b4792ecda 100644 --- a/debian/mariadb-server-10.3.logcheck.ignore.workstation +++ b/debian/mariadb-server-10.4.logcheck.ignore.workstation diff --git a/debian/mariadb-server-10.3.mysql-server.logrotate b/debian/mariadb-server-10.4.mysql-server.logrotate index 4111a276dc3..4111a276dc3 100644 --- a/debian/mariadb-server-10.3.mysql-server.logrotate +++ b/debian/mariadb-server-10.4.mysql-server.logrotate diff --git a/debian/mariadb-server-10.3.mysql.default b/debian/mariadb-server-10.4.mysql.default index 146c5a87a84..146c5a87a84 100644 --- a/debian/mariadb-server-10.3.mysql.default +++ b/debian/mariadb-server-10.4.mysql.default diff --git a/debian/mariadb-server-10.3.mysql.init b/debian/mariadb-server-10.4.mysql.init index 35a52d5d8db..bcc366e95b7 100644 --- a/debian/mariadb-server-10.3.mysql.init +++ b/debian/mariadb-server-10.4.mysql.init @@ -158,7 +158,7 @@ case "${1:-''}" in if ! mysqld_status check_dead warn; then log_end_msg 1 - log_failure_msg "Please stop MariaDB manually and read /usr/share/doc/mariadb-server-10.3/README.Debian.gz!" + log_failure_msg "Please stop MariaDB manually and read /usr/share/doc/mariadb-server-10.4/README.Debian.gz!" exit -1 else log_end_msg 0 diff --git a/debian/mariadb-server-10.3.postinst b/debian/mariadb-server-10.4.postinst index 7874a691268..c813c9bd8b3 100644 --- a/debian/mariadb-server-10.3.postinst +++ b/debian/mariadb-server-10.4.postinst @@ -26,6 +26,8 @@ invoke() { MYSQL_BOOTSTRAP="/usr/sbin/mysqld --bootstrap --user=mysql --disable-log-bin --skip-grant-tables --default-storage-engine=myisam" +have_global_priv_table= + set_mysql_rootpw() { # forget we ever saw the password. don't use reset to keep the seen status db_set mysql-server/root_password "" @@ -36,13 +38,23 @@ set_mysql_rootpw() { return 1 fi - # this avoids us having to call "test" or "[" on $rootpw cat << EOF > $tfile USE mysql; SET sql_log_bin=0; +EOF + if test -n "$have_global_priv_table"; then + cat << EOF >> $tfile +UPDATE global_priv SET priv=json_set(priv, '$.plugin', 'mysql_native_password', '$.authentication_string', PASSWORD("$rootpw")) WHERE user='root'; +EOF + else + cat << EOF >> $tfile UPDATE user SET password=PASSWORD("$rootpw") WHERE user='root'; +EOF + fi + cat << EOF >> $tfile FLUSH PRIVILEGES; EOF + # this avoids us having to call "test" or "[" on $rootpw if grep -q 'PASSWORD("")' $tfile; then retval=0 else @@ -135,7 +147,7 @@ EOF # Clean up old flags before setting new one rm -f $mysql_datadir/debian-*.flag # Flag data dir to avoid downgrades - touch $mysql_datadir/debian-10.3.flag + touch $mysql_datadir/debian-10.4.flag # initiate databases. Output is not allowed by debconf :-( # This will fail if we are upgrading an existing database; in this case @@ -149,6 +161,9 @@ EOF $ERR_LOGGER set -e + if test -f $mysql_datadir/mysql/global_priv.frm; then + have_global_priv_table=yes + fi # To avoid downgrades. touch $mysql_statedir/debian-$VER.flag @@ -197,20 +212,29 @@ EOF chown 0:0 $dc chmod 0600 $dc - replace_query=`/bin/echo -e \ + if test -n "$have_global_priv_table"; then + replace_query=`/bin/echo -e \ "USE mysql;\n" \ - "SET sql_mode='';\n" \ - "REPLACE INTO user SET " \ - " host='localhost', user='debian-sys-maint', password=password('$pass'), " \ - " Select_priv='Y', Insert_priv='Y', Update_priv='Y', Delete_priv='Y', " \ - " Create_priv='Y', Drop_priv='Y', Reload_priv='Y', Shutdown_priv='Y', " \ - " Process_priv='Y', File_priv='Y', Grant_priv='Y', References_priv='Y', " \ - " Index_priv='Y', Alter_priv='Y', Super_priv='Y', Show_db_priv='Y', "\ - " Create_tmp_table_priv='Y', Lock_tables_priv='Y', Execute_priv='Y', "\ - " Repl_slave_priv='Y', Repl_client_priv='Y', Create_view_priv='Y', "\ - " Show_view_priv='Y', Create_routine_priv='Y', Alter_routine_priv='Y', "\ - " Create_user_priv='Y', Event_priv='Y', Trigger_priv='Y',"\ - " ssl_cipher='', x509_issuer='', x509_subject='';"`; + "SELECT json_object('access',cast(-1 as unsigned), " \ + "'plugin', 'mysql_native_password', " \ + "'authentication_string', password('$pass')) INTO @all_privileges;\n"\ + "REPLACE global_priv VALUES ('localhost', 'debian-sys-maint', @all_privileges);"` + else + replace_query=`/bin/echo -e \ + "USE mysql;\n" \ + "SET sql_mode='';\n" \ + "REPLACE INTO user SET " \ + " host='localhost', user='debian-sys-maint', password=password('$pass'), " \ + " Select_priv='Y', Insert_priv='Y', Update_priv='Y', Delete_priv='Y', " \ + " Create_priv='Y', Drop_priv='Y', Reload_priv='Y', Shutdown_priv='Y', " \ + " Process_priv='Y', File_priv='Y', Grant_priv='Y', References_priv='Y', " \ + " Index_priv='Y', Alter_priv='Y', Super_priv='Y', Show_db_priv='Y', "\ + " Create_tmp_table_priv='Y', Lock_tables_priv='Y', Execute_priv='Y', "\ + " Repl_slave_priv='Y', Repl_client_priv='Y', Create_view_priv='Y', "\ + " Show_view_priv='Y', Create_routine_priv='Y', Alter_routine_priv='Y', "\ + " Create_user_priv='Y', Event_priv='Y', Trigger_priv='Y',"\ + " ssl_cipher='', x509_issuer='', x509_subject='';"`; + fi db_get mysql-server/root_password && rootpw="$RET" if ! set_mysql_rootpw; then diff --git a/debian/mariadb-server-10.3.postrm b/debian/mariadb-server-10.4.postrm index 6ab40df2e12..bb9ba8cec68 100644 --- a/debian/mariadb-server-10.3.postrm +++ b/debian/mariadb-server-10.4.postrm @@ -49,9 +49,9 @@ if [ "$1" = "purge" -a ! \( -x /usr/sbin/mysqld -o -L /usr/sbin/mysqld \) ]; the rm -f /var/log/mysql.{log,err}{,.0,.[1234567].gz} rm -rf /var/log/mysql - db_input high mariadb-server-10.3/postrm_remove_databases || true + db_input high mariadb-server-10.4/postrm_remove_databases || true db_go || true - db_get mariadb-server-10.3/postrm_remove_databases || true + db_get mariadb-server-10.4/postrm_remove_databases || true if [ "$RET" = "true" ]; then # never remove the debian.cnf when the databases are still existing # else we ran into big trouble on the next install! diff --git a/debian/mariadb-server-10.3.preinst b/debian/mariadb-server-10.4.preinst index cbfc4640c41..7b0540506ae 100644 --- a/debian/mariadb-server-10.3.preinst +++ b/debian/mariadb-server-10.4.preinst @@ -49,7 +49,7 @@ stop_server() { ################################ main() ########################## -this_version=10.3 +this_version=10.4 max_upgradeable_version=5.7 # Check if a flag file is found that indicates a previous MariaDB or MySQL @@ -113,7 +113,7 @@ fi # Instead simply move the old datadir and create a new for this_version. if [ ! -z "$downgrade_detected" ] then - db_input critical mariadb-server-10.3/old_data_directory_saved || true + db_input critical mariadb-server-10.4/old_data_directory_saved || true db_go echo "The file $mysql_datadir/debian-$found_version.flag indicates a" 1>&2 echo "version that cannot automatically be upgraded. Therefore the" 1>&2 diff --git a/debian/mariadb-server-10.3.prerm b/debian/mariadb-server-10.4.prerm index 0371bbfc844..0371bbfc844 100644 --- a/debian/mariadb-server-10.3.prerm +++ b/debian/mariadb-server-10.4.prerm diff --git a/debian/mariadb-server-10.3.py b/debian/mariadb-server-10.4.py index 99d3f0fd913..b44228daf8b 100644 --- a/debian/mariadb-server-10.3.py +++ b/debian/mariadb-server-10.4.py @@ -1,4 +1,4 @@ -'''apport package hook for mariadb-10.3 +'''apport package hook for mariadb-10.4 (c) 2009 Canonical Ltd. Author: Mathias Gug <mathias.gug@canonical.com> @@ -20,7 +20,7 @@ def _add_my_conf_files(report, filename): continue def add_info(report): - attach_conffiles(report, 'mariadb-server-10.3', conffiles=None) + attach_conffiles(report, 'mariadb-server-10.4', conffiles=None) key = 'Logs' + path_to_key('/var/log/daemon.log') report[key] = "" for line in read_file('/var/log/daemon.log').split('\n'): diff --git a/debian/mariadb-server-10.3.templates b/debian/mariadb-server-10.4.templates index 8ef29264678..a761ad76c6a 100644 --- a/debian/mariadb-server-10.3.templates +++ b/debian/mariadb-server-10.4.templates @@ -7,7 +7,7 @@ # Even minor modifications require translation updates and such # changes should be coordinated with translators and reviewers. -Template: mariadb-server-10.3/old_data_directory_saved +Template: mariadb-server-10.4/old_data_directory_saved Type: note _Description: The old data directory will be saved at new location A file named /var/lib/mysql/debian-*.flag exists on this system. @@ -19,7 +19,7 @@ _Description: The old data directory will be saved at new location . Please manually export/import your data (e.g. with mysqldump) if needed. -Template: mariadb-server-10.3/nis_warning +Template: mariadb-server-10.4/nis_warning Type: note #flag:translate!:3,5 _Description: Important note for NIS/YP users @@ -33,7 +33,7 @@ _Description: Important note for NIS/YP users . /var/lib/mysql: drwxr-xr-x mysql mysql -Template: mariadb-server-10.3/postrm_remove_databases +Template: mariadb-server-10.4/postrm_remove_databases Type: boolean Default: false _Description: Remove all MariaDB databases? @@ -66,7 +66,7 @@ _Description: Unable to set password for the MariaDB "root" user . You should check the account's password after the package installation. . - Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file + Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for more information. Template: mysql-server/password_mismatch diff --git a/debian/mariadb-server-10.3.triggers b/debian/mariadb-server-10.4.triggers index d1f5f5e14f1..d1f5f5e14f1 100644 --- a/debian/mariadb-server-10.3.triggers +++ b/debian/mariadb-server-10.4.triggers diff --git a/debian/mariadb-server-core-10.3.install b/debian/mariadb-server-core-10.4.install index 46c116b618d..46c116b618d 100644 --- a/debian/mariadb-server-core-10.3.install +++ b/debian/mariadb-server-core-10.4.install diff --git a/debian/mariadb-test-data.install b/debian/mariadb-test-data.install index 9e5356d061f..26b69c2941b 100644 --- a/debian/mariadb-test-data.install +++ b/debian/mariadb-test-data.install @@ -1,7 +1,7 @@ usr/share/mysql/mysql-test/collections usr/share/mysql/mysql-test/include -usr/share/mysql/mysql-test/plugin usr/share/mysql/mysql-test/main +usr/share/mysql/mysql-test/plugin usr/share/mysql/mysql-test/std_data usr/share/mysql/mysql-test/suite usr/share/mysql/mysql-test/unstable-tests diff --git a/debian/not-installed b/debian/not-installed index c151cf753e6..5341f6ca438 100644 --- a/debian/not-installed +++ b/debian/not-installed @@ -7,15 +7,15 @@ usr/lib/sysusers.d/sysusers.conf usr/lib/tmpfiles.d/tmpfiles.conf usr/lib/mysql/plugin/JavaWrappers.jar # These are only built if JNI/libjawt.so is installed from e.g. openjdk-8-jre-headless usr/lib/mysql/plugin/JdbcInterface.jar # These are only built if JNI/libjawt.so is installed from e.g. openjdk-8-jre-headless -usr/share/doc/mariadb-server-10.3/COPYING -usr/share/doc/mariadb-server-10.3/COPYING.AGPLv3 -usr/share/doc/mariadb-server-10.3/COPYING.GPLv2 -usr/share/doc/mariadb-server-10.3/COPYING.thirdparty -usr/share/doc/mariadb-server-10.3/CREDITS -usr/share/doc/mariadb-server-10.3/EXCEPTIONS-CLIENT -usr/share/doc/mariadb-server-10.3/INSTALL-BINARY -usr/share/doc/mariadb-server-10.3/PATENTS -usr/share/doc/mariadb-server-10.3/README-wsrep +usr/share/doc/mariadb-server-10.4/COPYING +usr/share/doc/mariadb-server-10.4/COPYING.AGPLv3 +usr/share/doc/mariadb-server-10.4/COPYING.GPLv2 +usr/share/doc/mariadb-server-10.4/COPYING.thirdparty +usr/share/doc/mariadb-server-10.4/CREDITS +usr/share/doc/mariadb-server-10.4/EXCEPTIONS-CLIENT +usr/share/doc/mariadb-server-10.4/INSTALL-BINARY +usr/share/doc/mariadb-server-10.4/PATENTS +usr/share/doc/mariadb-server-10.4/README-wsrep usr/share/groonga/COPYING usr/share/groonga-normalizer-mysql/lgpl-2.0.txt usr/share/groonga-normalizer-mysql/README.md diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in index f2af9ac992f..9499932064b 100644 --- a/debian/po/POTFILES.in +++ b/debian/po/POTFILES.in @@ -1 +1 @@ -[type: gettext/rfc822deb] mariadb-server-10.3.templates +[type: gettext/rfc822deb] mariadb-server-10.4.templates diff --git a/debian/po/ar.po b/debian/po/ar.po index 69ff80df4fa..c351e81bfbf 100644 --- a/debian/po/ar.po +++ b/debian/po/ar.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: templates\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2007-05-01 13:04+0300\n" "Last-Translator: Ossama M. Khayat <okhayat@yahoo.com>\n" @@ -27,13 +27,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -42,7 +42,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -50,20 +50,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Ù…Ù„Ø§ØØ¸Ø© هامة لمستخدمي NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -71,7 +71,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -83,13 +83,13 @@ msgstr "عليك أيضاً أن تقوم بالتأكد من صلاØÙŠØ§Øª Ù…Ø #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "إزالة جميع قواعد بيانات MariaDBØŸ" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -97,7 +97,7 @@ msgstr "الدليل /var/lib/mysql الذي ÙŠØØªÙˆÙŠ Ù‚ÙˆØ§Ø¹Ø¯ بيانات #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -108,13 +108,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "كلمة المرور الجديدة لمستخد \"root\" الخاص بـMariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -124,7 +124,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -132,7 +132,7 @@ msgstr "إن ترك الØÙ‚Ù„ ÙØ§Ø±ØºØ§Ù‹ØŒ Ùلن يتم تغيير كلمة #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 #, fuzzy #| msgid "New password for the MariaDB \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -140,13 +140,13 @@ msgstr "كلمة المرور الجديدة لمستخد \"root\" الخاص ب #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "تعذر تعيين كلمة مرور للمستخدم \"root\" الخاص بـMariaDB." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -158,7 +158,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -167,27 +167,27 @@ msgstr "يجب عليك التØÙ‚Ù‚ من كلمة مرور Ø§Ù„ØØ³Ø§Ø¨ عقب #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"الرجاء قراءة المل٠/usr/share/doc/mariadb-server-10.3/README.Debian للمزيد " +"الرجاء قراءة المل٠/usr/share/doc/mariadb-server-10.4/README.Debian للمزيد " "من المعلومات." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" diff --git a/debian/po/ca.po b/debian/po/ca.po index 7cc9bb340af..e2ba65054ba 100644 --- a/debian/po/ca.po +++ b/debian/po/ca.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-4.1\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2004-01-31 19:20GMT\n" "Last-Translator: Aleix Badia i Bosch <abadia@ica.es>\n" @@ -17,13 +17,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -32,7 +32,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -40,14 +40,14 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -55,7 +55,7 @@ msgstr "Nota important pels usuaris de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -63,7 +63,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -71,13 +71,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -85,7 +85,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -94,13 +94,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -108,25 +108,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -135,43 +135,43 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #, fuzzy #~| msgid "Should MySQL start on boot?" #~ msgid "Start the MariaDB server on boot?" -#~ msgstr "Voleu que el MariaDB s'iniciï a l'arrencada ?" +#~ msgstr "Voleu que el MariaDB s'inici� a l'arrencada ?" #, fuzzy #~ msgid "" #~ "The MariaDB server can be launched automatically at boot time or manually " #~ "with the '/etc/init.d/mysql start' command." #~ msgstr "" -#~ "El MariaDB es pot executar a l'arrencada o només si executeu manualment '/" -#~ "etc/init.d/mysql start'. Seleccioneu 'sí' si voleu que s'inicialitzi " -#~ "automàticament." +#~ "El MariaDB es pot executar a l'arrencada o nom�s si executeu manualment '/" +#~ "etc/init.d/mysql start'. Seleccioneu 's�' si voleu que s'inicialitzi " +#~ "autom�ticament." #, fuzzy #~ msgid "" @@ -180,7 +180,7 @@ msgstr "" #~ "permissions (the uid/gid may be different)." #~ msgstr "" #~ "Per utilitzar la base de dades de MySQL heu d'afegir un usuari i grup " -#~ "equivalent al següent i assegurar-vos que el directori /var/lib/mysql " +#~ "equivalent al seg�ent i assegurar-vos que el directori /var/lib/mysql " #~ "tingui els permisos correctes." #~ msgid "" @@ -203,13 +203,13 @@ msgstr "" #~ msgid "" #~ "MySQL will only install if you have a non-numeric hostname that is " #~ "resolvable via the /etc/hosts file. E.g. if the \"hostname\" command " -#~ "returns \"myhostname\" then there must be a line like \"10.3.0.1 " +#~ "returns \"myhostname\" then there must be a line like \"10.4.0.1 " #~ "myhostname\"." #~ msgstr "" -#~ "El MySQL només s'instal·la en cas de tenir un nom d'ordinador central que " -#~ "no sigui numèric i que es pugui resoldre a través del fitxer /etc/hosts. " +#~ "El MySQL nom�s s'instal�la en cas de tenir un nom d'ordinador central que " +#~ "no sigui num�ric i que es pugui resoldre a trav�s del fitxer /etc/hosts. " #~ "Ex. si l'ordre \"hostname\" retorna \"myhostname\", llavors hi ha d'haver " -#~ "una línia com la següent \"10.3.0.1 myhostname\"." +#~ "una l�nia com la seg�ent \"10.4.0.1 myhostname\"." #, fuzzy #~ msgid "" @@ -217,7 +217,7 @@ msgstr "" #~ "is used in the start/stop and cron scripts. Don't delete." #~ msgstr "" #~ "Es crea un nou usuari de mysql \"debian-sys-maint\". S'utilitza per les " -#~ "seqüències d'inicialització i aturada del cron, no el suprimiu." +#~ "seq��ncies d'inicialitzaci� i aturada del cron, no el suprimiu." #, fuzzy #~ msgid "" @@ -226,8 +226,8 @@ msgstr "" #~ "there, never only the password!" #~ msgstr "" #~ "Recordeu posar una contrasenya al superusuari del MySQL. Si utilitzeu un " -#~ "fitxer /root/.my.cnf, escriviu sempre allà les línies \"user\" i " -#~ "\"password\".; mai només la contrasenya. Per a més informació feu una " +#~ "fitxer /root/.my.cnf, escriviu sempre all� les l�nies \"user\" i " +#~ "\"password\".; mai nom�s la contrasenya. Per a m�s informaci� feu una " #~ "ullada a /usr/share/doc/mysql-server/README.Debian." #, fuzzy @@ -241,12 +241,12 @@ msgstr "" #~ "Networking is disabled by default for security reasons. You can enable it " #~ "by commenting out the skip-networking option in /etc/mysql/my.cnf." #~ msgstr "" -#~ "La xarxa està inhabilitada per defecte per a raons de seguretat. La podeu " -#~ "habilitar descomentant l'opció de skip-networking del fitxer /etc/mysql/" +#~ "La xarxa est� inhabilitada per defecte per a raons de seguretat. La podeu " +#~ "habilitar descomentant l'opci� de skip-networking del fitxer /etc/mysql/" #~ "my.cnf." #~ msgid "security and update notice" -#~ msgstr "Avís de seguretat i actualització" +#~ msgstr "Av�s de seguretat i actualitzaci�" #~ msgid "Please run mysql_fix_privilege_tables !" #~ msgstr "Executeu mysql_fix_privilege_tables" @@ -274,18 +274,18 @@ msgstr "" #~ "mysql_fix_privilege_tables script during this upgrade regardless of if " #~ "the server is currently running or not!" #~ msgstr "" -#~ "Les últimes versions de MySQL tenen un sistema de privilegis més " +#~ "Les �ltimes versions de MySQL tenen un sistema de privilegis m�s " #~ "elaborat. Per utilitzar-lo cal afegir nous camps a les taules de la base " -#~ "de dades \"mysql\". Aquesta tasca la realitza la seqüència " -#~ "mysql_fix_privilege_tables durant l'actualització independentment de si " -#~ "el servidor s'està executant o no!" +#~ "de dades \"mysql\". Aquesta tasca la realitza la seq��ncia " +#~ "mysql_fix_privilege_tables durant l'actualitzaci� independentment de si " +#~ "el servidor s'est� executant o no!" #~ msgid "" #~ "This script is not supposed to give any user more rights that he had " #~ "before, if you encounter such a case, please contact me." #~ msgstr "" -#~ "Aquesta seqüència no assigna privilegis d'usuari diferents als que ja " -#~ "tenia, en cas que us trobéssiu en aquesta situació, poseu-vos en contacte " +#~ "Aquesta seq��ncia no assigna privilegis d'usuari diferents als que ja " +#~ "tenia, en cas que us trob�ssiu en aquesta situaci�, poseu-vos en contacte " #~ "amb mi." #~ msgid "" @@ -295,7 +295,7 @@ msgstr "" #~ msgstr "" #~ "Voleu suprimir tots els continguts de /var/lib/mysql quan es purgui el " #~ "paquet mysql-server amb l'ordre \"dpkg --purge mysql-server\". (ex. " -#~ "suprimir-ho tot inclòs la configuració) ? (per defecte no)" +#~ "suprimir-ho tot incl�s la configuraci�) ? (per defecte no)" #~ msgid "Make MySQL reachable via network?" #~ msgstr "Voleu fer accessible el MySQL via xarxa ?" @@ -305,7 +305,7 @@ msgstr "" #~ "necessary for use on a single computer and could be a security problem." #~ msgstr "" #~ "Voleu que el MySQL escolti a un port TCP accessible des de la xarxa ? " -#~ "Aquesta opció no és imprescindible en ordinadors aïllats i podria " +#~ "Aquesta opci� no �s imprescindible en ordinadors a�llats i podria " #~ "provocar un problema de seguretat." #~ msgid "Enable chroot mode?" @@ -318,6 +318,6 @@ msgstr "" #~ "files." #~ msgstr "" #~ "El MySQL es pot executar en una entorn tancat al directori /var/lib/" -#~ "mysql_jail perquè els usuaris no puguin modificar cap fitxer fora del " -#~ "directori.Aquesta opció també augmenta la seguretat envers els crackers, " +#~ "mysql_jail perqu� els usuaris no puguin modificar cap fitxer fora del " +#~ "directori.Aquesta opci� tamb� augmenta la seguretat envers els crackers, " #~ "jaque no poden modificar els fitxers del sistema." diff --git a/debian/po/cs.po b/debian/po/cs.po index a991150fafb..c0d66613637 100644 --- a/debian/po/cs.po +++ b/debian/po/cs.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2007-05-01 13:01+0200\n" "Last-Translator: Miroslav Kure <kurem@debian.cz>\n" @@ -26,13 +26,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -41,7 +41,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -49,20 +49,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Důležitá poznámka pro uživatele NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -70,7 +70,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -83,13 +83,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Odstranit vÅ¡echny MariaDB databáze?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -99,7 +99,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -111,13 +111,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nové heslo MariaDB uživatele \"root\":" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -127,7 +127,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -135,7 +135,7 @@ msgstr "Ponecháte-li pole prázdné, heslo se nezmÄ›nÃ." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -143,13 +143,13 @@ msgstr "Nové heslo MariaDB uživatele \"root\":" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Nelze nastavit heslo MariaDB uživatele \"root\"" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -161,7 +161,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -170,26 +170,26 @@ msgstr "Po instalaci balÃku byste mÄ›li heslo ověřit." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"VÃce informacà naleznete v /usr/share/doc/mariadb-server-10.3/README.Debian." +"VÃce informacà naleznete v /usr/share/doc/mariadb-server-10.4/README.Debian." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" @@ -310,13 +310,13 @@ msgstr "" #~ msgid "" #~ "MySQL will only install if you have a non-numeric hostname that is " #~ "resolvable via the /etc/hosts file. E.g. if the \"hostname\" command " -#~ "returns \"myhostname\" then there must be a line like \"10.3.0.1 " +#~ "returns \"myhostname\" then there must be a line like \"10.4.0.1 " #~ "myhostname\"." #~ msgstr "" #~ "MySQL se nainstaluje pouze v pÅ™ÃpadÄ›, že použÃváte nenumerické jméno " #~ "poÄÃtaÄe, které se dá pÅ™eložit pÅ™es soubor /etc/hosts. NapÅ™. když pÅ™Ãkaz " #~ "\"hostname\" vrátà \"diamond\", tak v /etc/hosts musà existovat obdobný " -#~ "řádek jako \"10.3.0.1 diamond\"." +#~ "řádek jako \"10.4.0.1 diamond\"." #~ msgid "" #~ "A new mysql user \"debian-sys-maint\" will be created. This mysql account " diff --git a/debian/po/da.po b/debian/po/da.po index 7684daee58a..06d40cd58af 100644 --- a/debian/po/da.po +++ b/debian/po/da.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-4.1\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2007-05-30 22:41+0200\n" "Last-Translator: Claus Hindsgaul <claus.hindsgaul@gmail.com>\n" @@ -27,13 +27,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -42,7 +42,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -50,20 +50,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Vigtig oplysning til NIS/YP-brugere" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -71,7 +71,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -80,17 +80,17 @@ msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" msgstr "" -"Du bør også tjekke filrettighederne og ejerskabet af mappen /var/lib/mysql:" +"Du b�r ogs� tjekke filrettighederne og ejerskabet af mappen /var/lib/mysql:" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Fjern alle MariaDB-databaser?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -100,43 +100,43 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " "the data should be kept." msgstr "" "Hvis du fjerner MariaDB-pakken for senere at installere en nyere version, " -"eller hvis en anden mariadb-server-pakke allerede benytter den, bør dataene " +"eller hvis en anden mariadb-server-pakke allerede benytter den, b�r dataene " "bevares." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Ny adgangskode for MariaDB's \"root\"-bruger:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." msgstr "" -"Selvom det ikke kræves, anbefales det kraftigt, at du sætter en adgangskode " +"Selvom det ikke kr�ves, anbefales det kraftigt, at du s�tter en adgangskode " "for MariaDB's administrationsbruger \"root\"." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." -msgstr "Hvis du lader dette felt stå tomt, vil adgangskoden ikke blive ændret." +msgstr "Hvis du lader dette felt st� tomt, vil adgangskoden ikke blive �ndret." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -144,61 +144,61 @@ msgstr "Ny adgangskode for MariaDB's \"root\"-bruger:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" -msgstr "Kunne ikke sætte adgangskoden for MariaDB's \"root\"-bruger" +msgstr "Kunne ikke s�tte adgangskoden for MariaDB's \"root\"-bruger" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " "because of a communication problem with the MariaDB server." msgstr "" "Der opstod en fejl, da adgangskoden for MariaDB's administrationsbruger blev " -"forsøgt ændret. Dette kan være sket, fordi brugeren allerede har en " +"fors�gt �ndret. Dette kan v�re sket, fordi brugeren allerede har en " "adgangskode, eller fordi der var problemer med at kommunikere med MariaDB-" "serveren." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." -msgstr "Du bør tjekke kontoens adgangskode efter pakkeinstallationen." +msgstr "Du b�r tjekke kontoens adgangskode efter pakkeinstallationen." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"Se filen /usr/share/doc/mariadb-server-10.3/README.Debian for yderligere " +"Se filen /usr/share/doc/mariadb-server-10.4/README.Debian for yderligere " "oplysninger." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #~ msgid "Really proceed with downgrade?" -#~ msgstr "Ønsker du virkelig at fortsætte nedgraderingen?" +#~ msgstr "�nsker du virkelig at forts�tte nedgraderingen?" #~ msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." #~ msgstr "" -#~ "Der er en fil med navnet /var/lib/mysql/debian-*.flag på dette system." +#~ "Der er en fil med navnet /var/lib/mysql/debian-*.flag p� dette system." #, fuzzy #~| msgid "" @@ -208,7 +208,7 @@ msgstr "" #~ "Such a file is an indication that a mariadb-server package with a higher " #~ "version has been installed previously." #~ msgstr "" -#~ "Sådan en fil tyder på at der tidligere har været installeret en højere " +#~ "S�dan en fil tyder p� at der tidligere har v�ret installeret en h�jere " #~ "version af mariadb-server-pakken." #~ msgid "" @@ -232,7 +232,7 @@ msgstr "" #~ "To use MariaDB, the following entries for users and groups should be " #~ "added to the system:" #~ msgstr "" -#~ "Nedenstående linjer for brugere og grupper skal tilføjes dette system for " +#~ "Nedenst�ende linjer for brugere og grupper skal tilf�jes dette system for " #~ "at benytte MariaDB:" #~ msgid "Cannot upgrade if ISAM tables are present!" @@ -246,18 +246,18 @@ msgstr "" #~ "mysql-server-4.1 gets removed nevertheless just reinstall it to convert " #~ "those tables." #~ msgstr "" -#~ "Nyere versioner af MySQL kan ikke længere benytte det gamle ISAM-" -#~ "tabelformat, og det er derfor nødvendigt at konvertere dine tabeller til " +#~ "Nyere versioner af MySQL kan ikke l�ngere benytte det gamle ISAM-" +#~ "tabelformat, og det er derfor n�dvendigt at konvertere dine tabeller til " #~ "f.eks. MyISAM forud for opgraderingen med \"mysql_convert_table_format\" " #~ "eller \"ALTER TABLE x ENGINE=MyISAM\". Installationen af mysql-server-5.1 " #~ "afbrydes nu. Skulle din gamle mysql-server-4.1 alligevel bliver " -#~ "afinstalleret, så geninstallér den blot og konverter tabellerne." +#~ "afinstalleret, s� geninstall�r den blot og konverter tabellerne." #~ msgid "" #~ "Support MySQL connections from hosts running Debian \"sarge\" or older?" #~ msgstr "" -#~ "Understøt MySQL-forbindelser fra maskiner, der kører Debian \"Sarge\" " -#~ "eller ældre?" +#~ "Underst�t MySQL-forbindelser fra maskiner, der k�rer Debian \"Sarge\" " +#~ "eller �ldre?" #~ msgid "" #~ "In old versions of MySQL clients on Debian, passwords were not stored " @@ -265,10 +265,10 @@ msgstr "" #~ "PHP) from hosts running Debian 3.1 Sarge will not be able to connect to " #~ "recent accounts or accounts whose password have been changed." #~ msgstr "" -#~ "Gamle udgaver af MySQL-klienter på Debian gemte ikke adgangskoderne " +#~ "Gamle udgaver af MySQL-klienter p� Debian gemte ikke adgangskoderne " #~ "sikkert. Dette er blevet forbedret siden da, men klienter (f.eks. PHP) " -#~ "fra maskiner, der kører Debian 3.1 Sarge vil ikke kunne forbinde til " -#~ "nyere konti eller konti, hvis adgangskode er blevet ændret." +#~ "fra maskiner, der k�rer Debian 3.1 Sarge vil ikke kunne forbinde til " +#~ "nyere konti eller konti, hvis adgangskode er blevet �ndret." #~ msgid "" #~ "To use mysql you must install an equivalent user and group to the " @@ -276,7 +276,7 @@ msgstr "" #~ "permissions (the uid/gid may be different)." #~ msgstr "" #~ "For at kunne bruge mysql skal du installere en bruger og en gruppe, der " -#~ "svarer til nedenstående, og sikre dig at /var/lib/mysql har de rigtige " +#~ "svarer til nedenst�ende, og sikre dig at /var/lib/mysql har de rigtige " #~ "adgangsrettigheder (uid/gid kan afvige)." #~ msgid "" @@ -295,14 +295,14 @@ msgstr "" #~ msgid "" #~ "If you do not provide a password no changes will be made to the account." -#~ msgstr "Hvis du ikke angiver en adgangskode, vil kontoen ikke blive ændret." +#~ msgstr "Hvis du ikke angiver en adgangskode, vil kontoen ikke blive �ndret." #~ msgid "" #~ "When installation finishes, you should verify that the account is " #~ "properly protected with a password (see README.Debian for more " #~ "information)." #~ msgstr "" -#~ "Når installationen afsluttes, bør du tjekke at kontoen er ordentligt " +#~ "N�r installationen afsluttes, b�r du tjekke at kontoen er ordentligt " #~ "beskyttet med en adgangskode (se README.Debian for yderligere " #~ "oplysninger)." @@ -314,12 +314,12 @@ msgstr "" #~ "corrupted! This script also enhances the privilege tables but is not " #~ "supposed to give any user more rights that he had before," #~ msgstr "" -#~ "Du skal køre \"mysql_upgrade\" efter opgraderingen, da tabellerne eller " -#~ "kan blive ødelagt! Dette script forbedrer også rettighedstabellerne, men " +#~ "Du skal k�re \"mysql_upgrade\" efter opgraderingen, da tabellerne eller " +#~ "kan blive �delagt! Dette script forbedrer ogs� rettighedstabellerne, men " #~ "burde ikke give nogen bruger flere rettigheder, end han havde tidligere," #~ msgid "Please also read http://www.mysql.com/doc/en/Upgrade.html" -#~ msgstr "Læs også http://www.mysql.com/doc/en/Upgrade.html" +#~ msgstr "L�s ogs� http://www.mysql.com/doc/en/Upgrade.html" #~ msgid "Install Hints" #~ msgstr "Installationstips" @@ -331,17 +331,17 @@ msgstr "" #~ msgstr "" #~ "Ved opgraderinger fra MySQL 3.23, der fulgte med Debian Woody, kan de " #~ "symbolske /var/lib/mysql or /var/log/mysql blive fjernet ved et uheld, og " -#~ "må genskabes manuelt." +#~ "m� genskabes manuelt." #~ msgid "" #~ "MySQL will only install if you have a non-numeric hostname that is " #~ "resolvable via the /etc/hosts file. E.g. if the \"hostname\" command " -#~ "returns \"myhostname\" then there must be a line like \"10.3.0.1 " +#~ "returns \"myhostname\" then there must be a line like \"10.4.0.1 " #~ "myhostname\"." #~ msgstr "" -#~ "MySQL vil kun blive installeret, hvis du har et ikke-numerisk værtsnavn, " -#~ "som kan slås op i filen /ets/hosts. Hvis f.eks. kommandoen \"hostname\" " -#~ "svarer med \"mitvaertsnavn\", skal du have en linje a'la \"10.3.0.1 " +#~ "MySQL vil kun blive installeret, hvis du har et ikke-numerisk v�rtsnavn, " +#~ "som kan sl�s op i filen /ets/hosts. Hvis f.eks. kommandoen \"hostname\" " +#~ "svarer med \"mitvaertsnavn\", skal du have en linje a'la \"10.4.0.1 " #~ "mitvaertsnavn\" i /etc/hosts." #~ msgid "" @@ -356,8 +356,8 @@ msgstr "" #~ "root/.my.cnf, always write the \"user\" and the \"password\" lines in " #~ "there, never only the password!" #~ msgstr "" -#~ "Husk at sætte en ADGANGSKODE for MySQLs root-bruger! Hvis du bruger en /" -#~ "etc/.my.cnf, så skriv altid \"user\"- og \"password\"-linjer ind her, " +#~ "Husk at s�tte en ADGANGSKODE for MySQLs root-bruger! Hvis du bruger en /" +#~ "etc/.my.cnf, s� skriv altid \"user\"- og \"password\"-linjer ind her, " #~ "ikke kun adgangskoden!" #~ msgid "" @@ -365,7 +365,7 @@ msgstr "" #~ "by all MySQL versions, not necessarily only the one you are about to " #~ "purge?" #~ msgstr "" -#~ "Skal jeg fjerne hele mappetræet /var/lib/mysql, som benyttes af alle " +#~ "Skal jeg fjerne hele mappetr�et /var/lib/mysql, som benyttes af alle " #~ "MySQL-versioner, ikke kun den version, du er ved at slette?" #~ msgid "" @@ -373,7 +373,7 @@ msgstr "" #~ "make use of it mysql_fix_privilege_tables must be executed manually. The " #~ "script is not supposed to give any user more rights that he had before," #~ msgstr "" -#~ "En sjælden gang imellem, f.eks. ved nye hovedversioner, sker det at " -#~ "rettighedssystemet forbedres. For at gøre brug af dette, skal " -#~ "mysql_fix_privilege_tables køres manuelt. Scriptet vil ikke give nogen " +#~ "En sj�lden gang imellem, f.eks. ved nye hovedversioner, sker det at " +#~ "rettighedssystemet forbedres. For at g�re brug af dette, skal " +#~ "mysql_fix_privilege_tables k�res manuelt. Scriptet vil ikke give nogen " #~ "bruger flere rettigheder, end vedkommende havde tidligere," diff --git a/debian/po/de.po b/debian/po/de.po index 2e75376cc21..19e03ad88bd 100644 --- a/debian/po/de.po +++ b/debian/po/de.po @@ -15,7 +15,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1_5.1.37-1_de\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2009-08-27 22:41+0200\n" "Last-Translator: Thomas Mueller <thomas.mueller@tmit.eu>\n" @@ -29,13 +29,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -44,7 +44,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -52,20 +52,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Wichtige Anmerkung für NIS/YP-Benutzer!" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -75,7 +75,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -85,13 +85,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Alle MariaDB-Datenbanken entfernen?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -101,7 +101,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -113,13 +113,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Neues Passwort für den MariaDB »root«-Benutzer:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -129,25 +129,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "Wenn dieses Feld freigelassen wird, wird das Passwort nicht geändert." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Wiederholen Sie das Passwort für den MariaDB-»root«-Benutzer:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Konnte für den MariaDB-»root«-Benutzer kein Passwort setzen" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -160,7 +160,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" "Sie sollten das Passwort des administrativen Benutzers nach der " @@ -168,13 +168,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-5.1/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" "Für weitere Informationen lesen Sie /usr/share/doc/mariadb-server-5.1/README." @@ -182,13 +182,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "Passwort-Eingabefehler" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" "Die beiden von Ihnen eingegebenen Passwörter sind nicht identisch. Bitte " diff --git a/debian/po/es.po b/debian/po/es.po index 927bf904be7..825cda108ab 100644 --- a/debian/po/es.po +++ b/debian/po/es.po @@ -40,7 +40,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1_5.0.24-3\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2007-05-28 22:21+0200\n" "Last-Translator: Javier Fernández-Sanguino <jfs@debian.org>\n" @@ -52,13 +52,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -67,7 +67,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -75,20 +75,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante para los usuarios de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -96,7 +96,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -110,13 +110,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "¿Desea eliminar todas las bases de datos MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -126,7 +126,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -138,13 +138,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nueva contraseña para el usuario «root» de MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -154,7 +154,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -162,7 +162,7 @@ msgstr "No se modificará la contraseña si deja el espacio en blanco." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -170,13 +170,13 @@ msgstr "Nueva contraseña para el usuario «root» de MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "No se pudo fijar la contraseña para el usuario «root» de MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -189,7 +189,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" "DeberÃa comprobar la contraseña de la cuenta después de la instalación del " @@ -197,27 +197,27 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"Consulte /usr/share/doc/mariadb-server-10.3/README.Debian para más " +"Consulte /usr/share/doc/mariadb-server-10.4/README.Debian para más " "información." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" @@ -354,13 +354,13 @@ msgstr "" #~ msgid "" #~ "MySQL will only install if you have a non-numeric hostname that is " #~ "resolvable via the /etc/hosts file. E.g. if the \"hostname\" command " -#~ "returns \"myhostname\" then there must be a line like \"10.3.0.1 " +#~ "returns \"myhostname\" then there must be a line like \"10.4.0.1 " #~ "myhostname\"." #~ msgstr "" #~ "Sólo se instalará MySQL si tiene un nombre de equipo que no sea una " #~ "dirección IP y pueda resolverse a través del archivo /etc/hosts. Por " #~ "ejemplo, si la orden «hostname» devuelve «MiNombreEquipo» entonces deberá " -#~ "existir una lÃnea «10.3.0.1 MiNombreEquipo» en dicho archivo." +#~ "existir una lÃnea «10.4.0.1 MiNombreEquipo» en dicho archivo." #~ msgid "" #~ "A new mysql user \"debian-sys-maint\" will be created. This mysql account " diff --git a/debian/po/eu.po b/debian/po/eu.po index 91b7f1e341d..4c22d656c79 100644 --- a/debian/po/eu.po +++ b/debian/po/eu.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: eu\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2009-07-29 11:59+0200\n" "Last-Translator: Piarres Beobide <pi@beobide.net>\n" @@ -20,13 +20,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -35,7 +35,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -43,20 +43,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "NIS/YP erabiltzaileentzat ohar garrantzitsua" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -64,7 +64,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -78,13 +78,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Ezabatu MariaDB datubase guztiak?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -93,7 +93,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -105,13 +105,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "MariaDB \"root\" erabiltzailearen pasahitz berria:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -121,7 +121,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -129,19 +129,19 @@ msgstr "Eremua hau zurian utziaz gero ez da pasahitza aldatuko." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Errepikatu MariaDB \"root\" erabiltzailearen pasahitza:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Ezin da MariaDB \"root\" erabiltzailearen pasahitza ezarri" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -153,34 +153,34 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" "Kontuaren pasahitza egiaztatu beharko zenuke paketea instalatu aurretik." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" -#| "Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +#| "Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"Mesedez irakurri /usr/share/doc/mariadb-server-10.3/README.Debian fitxategia " +"Mesedez irakurri /usr/share/doc/mariadb-server-10.4/README.Debian fitxategia " "xehetasun gehiagorako." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "Pasahitz sarrera errorea" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "Idatzi dituzun bi pasahitzak ez dira berdina. Mesedez saiatu berriz." diff --git a/debian/po/fr.po b/debian/po/fr.po index 192d7de496e..46ae1e7ffbc 100644 --- a/debian/po/fr.po +++ b/debian/po/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: fr\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2009-08-08 14:56+0200\n" "Last-Translator: Christian Perrier <bubulle@debian.org>\n" @@ -22,13 +22,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -37,7 +37,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -45,20 +45,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Note importante pour les utilisateurs NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -68,7 +68,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -78,13 +78,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Faut-il supprimer toutes les bases de données MariaDB ?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -94,7 +94,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -105,13 +105,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nouveau mot de passe du superutilisateur de MariaDB :" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -121,26 +121,26 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "Si ce champ est laissé vide, le mot de passe ne sera pas changé." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Confirmation du mot de passe du superutilisateur de MariaDB :" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" "Impossible de changer le mot de passe de l'utilisateur « root » de MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -152,7 +152,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" "Vous devriez vérifier le mot de passe de ce compte après l'installation du " @@ -160,27 +160,27 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" -#| "Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +#| "Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"Veuillez consulter le fichier /usr/share/doc/mysql-server-10.3/README.Debian " +"Veuillez consulter le fichier /usr/share/doc/mysql-server-10.4/README.Debian " "pour plus d'informations." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "Erreur de saisie du mot de passe" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" "Le mot de passe et sa confirmation ne sont pas identiques. Veuillez " diff --git a/debian/po/gl.po b/debian/po/gl.po index cc17ee481a8..948cd8fd839 100644 --- a/debian/po/gl.po +++ b/debian/po/gl.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2007-04-20 09:44+0200\n" "Last-Translator: Jacobo Tarrio <jtarrio@debian.org>\n" @@ -17,13 +17,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -32,7 +32,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -40,20 +40,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante para os usuarios de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -61,7 +61,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -75,13 +75,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "¿Eliminar tódalas bases de datos de MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -91,7 +91,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -103,13 +103,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Novo contrasinal para o usuario \"root\" de MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -119,7 +119,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -127,7 +127,7 @@ msgstr "Se deixa o campo en branco, non se ha cambiar o contrasinal." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -135,13 +135,13 @@ msgstr "Novo contrasinal para o usuario \"root\" de MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Non se puido establecer o contrasinal do usuario \"root\" de MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -153,7 +153,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -162,27 +162,27 @@ msgstr "DeberÃa comprobar o contrasinal da conta trala instalación do paquete. #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"Consulte o ficheiro /usr/share/doc/mariadb-server-10.3/README.Debian para " +"Consulte o ficheiro /usr/share/doc/mariadb-server-10.4/README.Debian para " "máis información." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" diff --git a/debian/po/it.po b/debian/po/it.po index d1761b879e4..336bfe3fa43 100644 --- a/debian/po/it.po +++ b/debian/po/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1 5.1.37 italian debconf templates\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2009-08-08 11:03+0200\n" "Last-Translator: Luca Monducci <luca.mo@tiscali.it>\n" @@ -18,13 +18,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -33,7 +33,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -41,20 +41,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante per gli utenti NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -64,7 +64,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -74,13 +74,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Eliminare tutti i database MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -90,7 +90,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -102,13 +102,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nuova password per l'utente «root» di MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -118,25 +118,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "Se questo campo è lasciato vuoto, la password non viene cambiata." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Ripetere la password per l'utente «root» di MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Impossibile impostare la password per l'utente «root» di MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -149,34 +149,34 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" "Al termine dell'installazione si deve verificare la password dell'account." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" -#| "Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +#| "Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" "Per maggiori informazioni si consulti il file /usr/share/doc/mariadb-" -"server-10.3/README.Debian." +"server-10.4/README.Debian." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "Errore di inserimento della password" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "Le due password inserite sono diverse. Riprovare." diff --git a/debian/po/ja.po b/debian/po/ja.po index 8ca7993a140..ba7bb52763c 100644 --- a/debian/po/ja.po +++ b/debian/po/ja.po @@ -15,7 +15,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1 5.1.37-1\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2009-09-01 08:25+0900\n" "Last-Translator: Hideki Yamane (Debian-JP) <henrich@debian.or.jp>\n" @@ -27,13 +27,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -42,7 +42,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -50,20 +50,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "NIS/YP ユーザã¸ã®é‡è¦ãªæ³¨æ„" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -73,7 +73,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -81,13 +81,13 @@ msgstr "/var/lib/mysql ã®æ‰€æœ‰è€…権é™ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹å¿…è¦ã‚‚ã‚り㾠#. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "ã™ã¹ã¦ã® MariaDB データベースを削除ã—ã¾ã™ã‹?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -97,7 +97,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -109,13 +109,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "MariaDB ã® \"root\" ユーザã«å¯¾ã™ã‚‹æ–°ã—ã„パスワード:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -125,25 +125,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "ã“ã®å€¤ã‚’空ã®ã¾ã¾ã«ã—ã¦ãŠã„ãŸå ´åˆã¯ã€ãƒ‘スワードã¯å¤‰æ›´ã•れã¾ã›ã‚“。" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "MariaDB ã® \"root\" ユーザã«å¯¾ã™ã‚‹æ–°ã—ã„パスワード:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "MariaDB ã® \"root\" ユーザã®ãƒ‘スワードをè¨å®šã§ãã¾ã›ã‚“" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -155,33 +155,33 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" "パッケージã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å¾Œã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ‘スワードを確èªã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" -#| "Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +#| "Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"詳細㯠/usr/share/doc/mariadb-server-10.3/README.Debian ã‚’å‚ç…§ã—ã¦ãã ã•ã„。" +"詳細㯠/usr/share/doc/mariadb-server-10.4/README.Debian ã‚’å‚ç…§ã—ã¦ãã ã•ã„。" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "パスワード入力エラー" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "入力ã•れãŸäºŒã¤ã®ãƒ‘スワードãŒä¸€è‡´ã—ã¾ã›ã‚“。å†å…¥åŠ›ã—ã¦ãã ã•ã„。" diff --git a/debian/po/nb.po b/debian/po/nb.po index 06acfd8c25c..4a3e7514513 100644 --- a/debian/po/nb.po +++ b/debian/po/nb.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql_nb\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2007-02-18 12:13+0100\n" "Last-Translator: Bjørn Steensrud <bjornst@powertech.no>\n" @@ -19,13 +19,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -34,7 +34,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -42,14 +42,14 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -57,7 +57,7 @@ msgstr "Viktig merknad for NIS/YP-brukere!" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -65,7 +65,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -73,13 +73,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -87,7 +87,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 #, fuzzy #| msgid "" #| "The script is about to remove the data directory /var/lib/mysql. If it is " @@ -104,7 +104,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "New password for the MariaDB \"root\" user:" @@ -112,7 +112,7 @@ msgstr "Nytt passord for MariaDBs «root»-bruker:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "" #| "It is highly recommended that you set a password for the MySQL " @@ -126,13 +126,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -140,7 +140,7 @@ msgstr "Nytt passord for MariaDBs «root»-bruker:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "Unable to set password for MySQL \"root\" user" msgid "Unable to set password for the MariaDB \"root\" user" @@ -148,7 +148,7 @@ msgstr "Klarer ikke angi passord for MariaDBs «root»-bruker" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "It seems an error occurred while setting the password for the MySQL " @@ -167,27 +167,27 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" diff --git a/debian/po/nl.po b/debian/po/nl.po index 65112a9f0a0..8dea3504592 100644 --- a/debian/po/nl.po +++ b/debian/po/nl.po @@ -6,9 +6,9 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1 5.0.30-1\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" -"PO-Revision-Date: 2006-02-19 10.30+0100\n" +"PO-Revision-Date: 2006-02-19 10.40+0100\n" "Last-Translator: Thijs Kinkhorst <thijs@debian.org>\n" "Language-Team: Debian-Dutch <debian-l10n-dutch@lists.debian.org>\n" "Language: \n" @@ -18,13 +18,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -33,7 +33,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -41,14 +41,14 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -56,7 +56,7 @@ msgstr "Belangrijke opmerking voor gebruikers van NIS/YP!" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -64,7 +64,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -72,13 +72,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -86,7 +86,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 #, fuzzy #| msgid "" #| "The script is about to remove the data directory /var/lib/mysql. If it is " @@ -104,7 +104,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "New password for the MariaDB \"root\" user:" @@ -112,7 +112,7 @@ msgstr "Nieuw wachtwoord voor de MariaDB \"root\"-gebruiker:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "" #| "It is highly recommended that you set a password for the MySQL " @@ -126,13 +126,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -140,7 +140,7 @@ msgstr "Nieuw wachtwoord voor de MariaDB \"root\"-gebruiker:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "Unable to set password for MySQL \"root\" user" msgid "Unable to set password for the MariaDB \"root\" user" @@ -148,7 +148,7 @@ msgstr "Kan het wachtwoord voor de MariaDB \"root\"-gebruiker niet instellen" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "It seems an error occurred while setting the password for the MySQL " @@ -167,27 +167,27 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" diff --git a/debian/po/pt.po b/debian/po/pt.po index 106802ee87b..2d1834deda3 100644 --- a/debian/po/pt.po +++ b/debian/po/pt.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2007-05-05 21:01+0100\n" "Last-Translator: Miguel Figueiredo <elmig@debianpt.org>\n" @@ -18,13 +18,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -33,7 +33,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -41,20 +41,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante para utilizadores de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -62,7 +62,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -75,13 +75,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Remover todas as bases de dados MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -91,7 +91,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -103,13 +103,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nova palavra-passe para o utilizador \"root\" do MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -119,7 +119,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -128,7 +128,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -136,7 +136,7 @@ msgstr "Nova palavra-passe para o utilizador \"root\" do MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" "Não foi possÃvel definir a palavra-passe para o utilizador \"root\" do " @@ -144,7 +144,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -157,7 +157,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -167,27 +167,27 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" "Para mais informação por favor leia o ficheiro /usr/share/doc/mariadb-" -"server-10.3/README.Debian." +"server-10.4/README.Debian." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" diff --git a/debian/po/pt_BR.po b/debian/po/pt_BR.po index cf072b0cc7a..31c9239f217 100644 --- a/debian/po/pt_BR.po +++ b/debian/po/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2007-04-21 15:59-0300\n" "Last-Translator: André LuÃs Lopes <andrelop@debian.org>\n" @@ -21,13 +21,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -36,7 +36,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -44,20 +44,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Aviso importante para usuários NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -65,7 +65,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -78,13 +78,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Remover todas as bases de dados do MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -94,7 +94,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -106,13 +106,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nova senha para o usuário \"root\" do MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -122,7 +122,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -130,7 +130,7 @@ msgstr "Caso este campo seja deixado em branco, a senha não sera mudada." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -138,13 +138,13 @@ msgstr "Nova senha para o usuário \"root\" do MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "ImpossÃvel definir senha para o usuário \"root\" do MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -157,7 +157,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -166,27 +166,27 @@ msgstr "Você deverá checar a senha dessa conta após a instalação deste paco #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"Por favor, leia o arquivo /usr/share/doc/mariadb-server-10.3/README.Debian " +"Por favor, leia o arquivo /usr/share/doc/mariadb-server-10.4/README.Debian " "para maiores informações." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" @@ -322,13 +322,13 @@ msgstr "" #~ msgid "" #~ "MySQL will only install if you have a non-numeric hostname that is " #~ "resolvable via the /etc/hosts file. E.g. if the \"hostname\" command " -#~ "returns \"myhostname\" then there must be a line like \"10.3.0.1 " +#~ "returns \"myhostname\" then there must be a line like \"10.4.0.1 " #~ "myhostname\"." #~ msgstr "" #~ "O MySQL será instalado somente caso você possua um nome de host NÃO " #~ "NUMÉRICO que possa ser resolvido através do arquivo /etc/hosts, ou seja, " #~ "caso o comando \"hostname\" retorne \"myhostname\", uma linha como " -#~ "\"10.3.0.1 myhostname\" deverá existir no arquivo /etc/hosts." +#~ "\"10.4.0.1 myhostname\" deverá existir no arquivo /etc/hosts." #~ msgid "" #~ "A new mysql user \"debian-sys-maint\" will be created. This mysql account " diff --git a/debian/po/ro.po b/debian/po/ro.po index ad2516da21e..328573c0357 100644 --- a/debian/po/ro.po +++ b/debian/po/ro.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: po-debconf://mysql-dfsg\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2006-12-20 21:27+0200\n" "Last-Translator: stan ioan-eugen <stan.ieugen@gmail.com>\n" @@ -19,13 +19,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -34,7 +34,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -42,14 +42,14 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -57,7 +57,7 @@ msgstr "Notă importantă pentru utilizatorii NIS/YP!" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -65,7 +65,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -73,13 +73,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -87,7 +87,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 #, fuzzy #| msgid "" #| "The script is about to remove the data directory /var/lib/mysql. If it is " @@ -104,7 +104,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "New password for the MariaDB \"root\" user:" @@ -112,7 +112,7 @@ msgstr "Noua parolă pentru utilizatorul „root†al MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 #, fuzzy #| msgid "" #| "It is highly recommended that you set a password for the MySQL " @@ -126,13 +126,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -140,7 +140,7 @@ msgstr "Noua parolă pentru utilizatorul „root†al MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "Unable to set password for MySQL \"root\" user" msgid "Unable to set password for the MariaDB \"root\" user" @@ -148,7 +148,7 @@ msgstr "Nu s-a putut stabili parola pentru utilizatorul „root†al MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" #| "It seems an error occurred while setting the password for the MySQL " @@ -167,27 +167,27 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" diff --git a/debian/po/ru.po b/debian/po/ru.po index 2c0bc7fee1f..baa70378169 100644 --- a/debian/po/ru.po +++ b/debian/po/ru.po @@ -17,7 +17,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1 5.1.37-1\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2009-08-06 20:27+0400\n" "Last-Translator: Yuri Kozlov <yuray@komyakino.ru>\n" @@ -32,13 +32,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -47,7 +47,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -55,20 +55,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Важное замечание Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -78,7 +78,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -86,13 +86,13 @@ msgstr "Также проверьте права доÑтупа и Ð²Ð»Ð°Ð´ÐµÐ»Ñ #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Удалить вÑе базы данных MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -101,7 +101,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -113,13 +113,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Ðовый пароль Ð´Ð»Ñ MariaDB Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ \"root\":" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -129,25 +129,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "ЕÑли оÑтавить поле пуÑтым, то пароль изменён не будет." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Повторите ввод Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð´Ð»Ñ MariaDB Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ \"root\":" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Ðевозможно задать пароль MariaDB пользователю \"root\"" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -159,32 +159,32 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "Проверьте пароль учётной запиÑи поÑле уÑтановки пакета." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" -#| "Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +#| "Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"ПодробноÑти Ñм. в файле /usr/share/doc/mariadb-server-10.3/README.Debian." +"ПодробноÑти Ñм. в файле /usr/share/doc/mariadb-server-10.4/README.Debian." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "Ошибка ввода паролÑ" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "Два введённых Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ðµ одинаковы. Повторите ввод." diff --git a/debian/po/sv.po b/debian/po/sv.po index ce830bd2319..e1bfe1f6d1b 100644 --- a/debian/po/sv.po +++ b/debian/po/sv.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-5.1 5.0.21-3\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2009-09-08 21:42+0100\n" "Last-Translator: Martin Bagge <brother@bsnet.se>\n" @@ -21,13 +21,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -36,7 +36,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -44,20 +44,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "Viktig information för NIS/YP-användare" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -67,7 +67,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -77,13 +77,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Ta bort alla MariaDB-databaser?" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -93,7 +93,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -105,13 +105,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nytt lösenord för MariaDBs \"root\"-användare:" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -121,25 +121,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "Om detta fält lämnas tom kommer lösenordet inte att ändras." #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Repetera lösenordet för MariaDBs \"root\"-användare:" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Kunde inte sätta lösenord för MariaDBs \"root\"-användare" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -152,33 +152,33 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "Du bör kontrollera kontots lösenord efter installationen av paketet." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 #, fuzzy #| msgid "" -#| "Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +#| "Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " #| "more information." msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" -"Läs filen /usr/share/doc/mariadb-server-10.3/README.Debian för mer " +"Läs filen /usr/share/doc/mariadb-server-10.4/README.Debian för mer " "information." #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "Fel vid inmatning av lösenord" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "De tvÃ¥ lösenorden du angav stämde inte överrens. Prova igen." diff --git a/debian/po/templates.pot b/debian/po/templates.pot index b0e3ee82576..46a4487480e 100644 --- a/debian/po/templates.pot +++ b/debian/po/templates.pot @@ -6,8 +6,8 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: mariadb-10.3\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Project-Id-Version: mariadb-10.4\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" @@ -19,13 +19,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -34,7 +34,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -42,20 +42,20 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "Important note for NIS/YP users" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -63,7 +63,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -71,13 +71,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -85,7 +85,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -94,13 +94,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -108,25 +108,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -135,26 +135,26 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" diff --git a/debian/po/tr.po b/debian/po/tr.po index ab8542d376f..6695bdd8a96 100644 --- a/debian/po/tr.po +++ b/debian/po/tr.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: mysql-dfsg-4.1\n" -"Report-Msgid-Bugs-To: mariadb-10.3@packages.debian.org\n" +"Report-Msgid-Bugs-To: mariadb-10.4@packages.debian.org\n" "POT-Creation-Date: 2016-10-08 01:26+0300\n" "PO-Revision-Date: 2004-06-05 08:53+0300\n" "Last-Translator: Gürkan Aslan <gurkan@iaslan.com>\n" @@ -18,13 +18,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "The old data directory will be saved at new location" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "A file named /var/lib/mysql/debian-*.flag exists on this system. The number " "indicates a database binary format version that cannot automatically be " @@ -33,7 +33,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Therefore the previous data directory will be renamed to /var/lib/mysql-* " "and a new data directory will be initialized at /var/lib/mysql." @@ -41,14 +41,14 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:2001 +#: ../mariadb-server-10.4.templates:2001 msgid "" "Please manually export/import your data (e.g. with mysqldump) if needed." msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -56,7 +56,7 @@ msgstr "NIS/YP kullanıcıları için önemli not!" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -64,7 +64,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.3.templates:3001 +#: ../mariadb-server-10.4.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -72,13 +72,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -86,7 +86,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.3.templates:4001 +#: ../mariadb-server-10.4.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -95,13 +95,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "New password for the MariaDB \"root\" user:" msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -109,25 +109,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:5001 +#: ../mariadb-server-10.4.templates:5001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.3.templates:6001 +#: ../mariadb-server-10.4.templates:6001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -136,27 +136,27 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:7001 +#: ../mariadb-server-10.4.templates:7001 msgid "" -"Please read the /usr/share/doc/mariadb-server-10.3/README.Debian file for " +"Please read the /usr/share/doc/mariadb-server-10.4/README.Debian file for " "more information." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.3.templates:8001 +#: ../mariadb-server-10.4.templates:8001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" @@ -202,12 +202,12 @@ msgstr "" #~ msgid "" #~ "MySQL will only install if you have a non-numeric hostname that is " #~ "resolvable via the /etc/hosts file. E.g. if the \"hostname\" command " -#~ "returns \"myhostname\" then there must be a line like \"10.3.0.1 " +#~ "returns \"myhostname\" then there must be a line like \"10.4.0.1 " #~ "myhostname\"." #~ msgstr "" #~ "MySQL sadece /etc/hosts dosyası yoluyla çözülebilir NUMERİK OLMAYAN bir " #~ "makine adına sahipseniz kurulacaktır. ÖrneÄŸin, eÄŸer \"hostname\" komutu " -#~ "\"makinem\" ismini döndürüyorsa, bu dosya içinde \"10.3.0.1 makinem\" " +#~ "\"makinem\" ismini döndürüyorsa, bu dosya içinde \"10.4.0.1 makinem\" " #~ "gibi bir satır olmalıdır." #, fuzzy diff --git a/debian/rules b/debian/rules index c3252fb585e..446b02b4164 100755 --- a/debian/rules +++ b/debian/rules @@ -121,8 +121,8 @@ override_dh_auto_install: ifneq (,$(filter linux,$(DEB_HOST_ARCH_OS))) # Copy systemd files to a location available for dh_installinit - cp $(BUILDDIR)/support-files/mariadb.service debian/mariadb-server-10.3.mariadb.service - cp $(BUILDDIR)/support-files/mariadb@.service debian/mariadb-server-10.3.mariadb@.service + cp $(BUILDDIR)/support-files/mariadb.service debian/mariadb-server-10.4.mariadb.service + cp $(BUILDDIR)/support-files/mariadb@.service debian/mariadb-server-10.4.mariadb@.service endif # make install @@ -135,12 +135,12 @@ endif # nm numeric soft is not enough, therefore extra sort in command # to satisfy Debian reproducible build requirements - nm --defined-only $(BUILDDIR)/sql/mysqld | LC_ALL=C sort | gzip -n -9 > $(TMP)/usr/share/doc/mariadb-server-10.3/mysqld.sym.gz + nm --defined-only $(BUILDDIR)/sql/mysqld | LC_ALL=C sort | gzip -n -9 > $(TMP)/usr/share/doc/mariadb-server-10.4/mysqld.sym.gz # rename and install AppArmor profile install -D -m 644 debian/apparmor-profile $(TMP)/etc/apparmor.d/usr.sbin.mysqld # install Apport hook - install -D -m 644 debian/mariadb-server-10.3.py $(TMP)/usr/share/apport/package-hooks/source_mariadb-10.3.py + install -D -m 644 debian/mariadb-server-10.4.py $(TMP)/usr/share/apport/package-hooks/source_mariadb-10.4.py # Install libmariadbclient18 compatibility links ln -s libmariadb.so.3 $(TMP)/usr/lib/$(DEB_HOST_MULTIARCH)/libmariadbclient.so diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt index 05b89290a6d..cd099dedf63 100644 --- a/extra/CMakeLists.txt +++ b/extra/CMakeLists.txt @@ -72,9 +72,6 @@ IF(WITH_INNOBASE_STORAGE_ENGINE) # We use the InnoDB code directly in case the code changes. ADD_DEFINITIONS("-DUNIV_INNOCHECKSUM") - IF(WITH_INNODB_BUG_ENDIAN_CRC32) - ADD_DEFINITIONS(-DINNODB_BUG_ENDIAN_CRC32) - ENDIF() # Avoid generating Hardware Capabilities due to crc32 instructions IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_SYSTEM_PROCESSOR MATCHES "i386") diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index 5c6cf74fd8e..de640a17765 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. - Copyright (c) 2014, 2017, MariaDB Corporation. + Copyright (c) 2014, 2018, MariaDB Corporation. 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 @@ -42,42 +42,18 @@ /* Only parts of these files are included from the InnoDB codebase. The parts not included are excluded by #ifndef UNIV_INNOCHECKSUM. */ -typedef void fil_space_t; - -#include "page0size.h" - -#define FLST_BASE_NODE_SIZE (4 + 2 * FIL_ADDR_SIZE) -#define FLST_NODE_SIZE (2 * FIL_ADDR_SIZE) -#define FSEG_PAGE_DATA FIL_PAGE_DATA -#define FSEG_HEADER_SIZE 10 -#define UT_BITS_IN_BYTES(b) (((b) + 7) / 8) - -#include "ut0ut.h" -#include "ut0byte.h" -#include "mtr0types.h" #include "mach0data.h" -#include "fsp0types.h" -#include "rem0rec.h" +#include "page0page.h" #include "buf0checksum.h" /* buf_calc_page_*() */ #include "buf0buf.h" /* buf_page_is_corrupted */ -#include "fil0fil.h" /* FIL_* */ -#include "page0page.h" /* PAGE_* */ #include "page0zip.h" /* page_zip_*() */ #include "trx0undo.h" /* TRX_* */ -#include "fsp0fsp.h" /* fsp_flags_get_page_size() & - fsp_flags_get_zip_size() */ #include "ut0crc32.h" /* ut_crc32_init() */ #include "fsp0pagecompress.h" /* fil_get_compression_alg_name */ #include "fil0crypt.h" /* fil_space_verify_crypt_checksum */ #include <string.h> -#ifdef UNIV_NONINL -# include "fsp0fsp.ic" -# include "mach0data.ic" -# include "ut0rnd.ic" -#endif - #ifndef PRIuMAX #define PRIuMAX "llu" #endif diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index a142ad70b26..fb7afe8b825 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -871,83 +871,6 @@ stop_query_killer() } -/* -Killing connections that wait for MDL lock. -If lock-ddl-per-table is used, there can be some DDL statements - -FLUSH TABLES would hang infinitely, if DDL statements are waiting for -MDL lock, which mariabackup currently holds. Therefore we start killing -those statements from a dedicated thread, until FLUSH TABLES WITH READ LOCK -succeeds. -*/ - -static os_event_t mdl_killer_stop_event; -static os_event_t mdl_killer_finished_event; - -static -os_thread_ret_t -DECLARE_THREAD(kill_mdl_waiters_thread(void *)) -{ - MYSQL *mysql; - if ((mysql = xb_mysql_connect()) == NULL) { - msg("Error: kill mdl waiters thread failed to connect\n"); - goto stop_thread; - } - - for(;;){ - if (os_event_wait_time(mdl_killer_stop_event, 1000) == 0) - break; - - MYSQL_RES *result = xb_mysql_query(mysql, - "SELECT ID, COMMAND, INFO FROM INFORMATION_SCHEMA.PROCESSLIST " - " WHERE State='Waiting for table metadata lock'", - true, true); - while (MYSQL_ROW row = mysql_fetch_row(result)) - { - char query[64]; - - if (row[1] && !strcmp(row[1], "Killed")) - continue; - - msg_ts("Killing MDL waiting %s ('%s') on connection %s\n", - row[1], row[2], row[0]); - snprintf(query, sizeof(query), "KILL QUERY %s", row[0]); - if (mysql_query(mysql, query) && (mysql_errno(mysql) != ER_NO_SUCH_THREAD)) { - msg("Error: failed to execute query %s: %s\n", query,mysql_error(mysql)); - exit(EXIT_FAILURE); - } - } - mysql_free_result(result); - } - - mysql_close(mysql); - -stop_thread: - msg_ts("Kill mdl waiters thread stopped\n"); - os_event_set(mdl_killer_finished_event); - os_thread_exit(); - return os_thread_ret_t(0); -} - - -static void start_mdl_waiters_killer() -{ - mdl_killer_stop_event = os_event_create(0); - mdl_killer_finished_event = os_event_create(0); - os_thread_create(kill_mdl_waiters_thread, 0, 0); -} - - -/* Tell MDL killer to stop and finish for its completion*/ -static void stop_mdl_waiters_killer() -{ - os_event_set(mdl_killer_stop_event); - os_event_wait(mdl_killer_finished_event); - - os_event_destroy(mdl_killer_stop_event); - os_event_destroy(mdl_killer_finished_event); -} - /*********************************************************************//** Function acquires either a backup tables lock, if supported by the server, or a global read lock (FLUSH TABLES WITH READ LOCK) @@ -970,30 +893,6 @@ lock_tables(MYSQL *connection) return(true); } - if (opt_lock_ddl_per_table) { - start_mdl_waiters_killer(); - } - - if (!opt_lock_wait_timeout && !opt_kill_long_queries_timeout) { - - /* We do first a FLUSH TABLES. If a long update is running, the - FLUSH TABLES will wait but will not stall the whole mysqld, and - when the long update is done the FLUSH TABLES WITH READ LOCK - will start and succeed quickly. So, FLUSH TABLES is to lower - the probability of a stage where both mysqldump and most client - connections are stalled. Of course, if a second long update - starts between the two FLUSHes, we have that bad stall. - - Option lock_wait_timeout serve the same purpose and is not - compatible with this trick. - */ - - msg_ts("Executing FLUSH NO_WRITE_TO_BINLOG TABLES...\n"); - - xb_mysql_query(connection, - "FLUSH NO_WRITE_TO_BINLOG TABLES", false); - } - if (opt_lock_wait_timeout) { if (!wait_for_no_updates(connection, opt_lock_wait_timeout, opt_lock_wait_threshold)) { @@ -1001,7 +900,7 @@ lock_tables(MYSQL *connection) } } - msg_ts("Executing FLUSH TABLES WITH READ LOCK...\n"); + msg_ts("Acquiring BACKUP LOCKS...\n"); if (opt_kill_long_queries_timeout) { start_query_killer(); @@ -1012,11 +911,10 @@ lock_tables(MYSQL *connection) "SET SESSION wsrep_causal_reads=0", false); } - xb_mysql_query(connection, "FLUSH TABLES WITH READ LOCK", false); - - if (opt_lock_ddl_per_table) { - stop_mdl_waiters_killer(); - } + xb_mysql_query(connection, "BACKUP STAGE START", true); + //xb_mysql_query(connection, "BACKUP STAGE FLUSH", true); + //xb_mysql_query(connection, "BACKUP STAGE BLOCK_DDL", true); + xb_mysql_query(connection, "BACKUP STAGE BLOCK_COMMIT", true); if (opt_kill_long_queries_timeout) { stop_query_killer(); @@ -1058,13 +956,8 @@ unlock_all(MYSQL *connection) os_thread_sleep(opt_debug_sleep_before_unlock * 1000); } - if (binlog_locked) { - msg_ts("Executing UNLOCK BINLOG\n"); - xb_mysql_query(connection, "UNLOCK BINLOG", false); - } - - msg_ts("Executing UNLOCK TABLES\n"); - xb_mysql_query(connection, "UNLOCK TABLES", false); + msg_ts("Executing BACKUP STAGE END\n"); + xb_mysql_query(connection, "BACKUP STAGE END", false); msg_ts("All tables unlocked\n"); } diff --git a/extra/mariabackup/ds_local.cc b/extra/mariabackup/ds_local.cc index 58353365cd6..eea4fcecdd8 100644 --- a/extra/mariabackup/ds_local.cc +++ b/extra/mariabackup/ds_local.cc @@ -64,7 +64,7 @@ local_init(const char *root) { char errbuf[MYSYS_STRERROR_SIZE]; my_strerror(errbuf, sizeof(errbuf),my_errno); - my_error(EE_CANT_MKDIR, MYF(ME_BELL | ME_WAITTANG), + my_error(EE_CANT_MKDIR, MYF(ME_BELL), root, my_errno,errbuf, my_errno); return NULL; } @@ -96,7 +96,7 @@ local_open(ds_ctxt_t *ctxt, const char *path, if (my_mkdir(dirpath, 0777, MYF(0)) < 0 && my_errno != EEXIST) { char errbuf[MYSYS_STRERROR_SIZE]; my_strerror(errbuf, sizeof(errbuf), my_errno); - my_error(EE_CANT_MKDIR, MYF(ME_BELL | ME_WAITTANG), + my_error(EE_CANT_MKDIR, MYF(ME_BELL), dirpath, my_errno, errbuf); return NULL; } diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 75760ad352b..0d113cc6b2c 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -475,9 +475,18 @@ DECLARE_THREAD(dbug_execute_in_new_connection)(void *arg) dbug_thread_param_t *par= (dbug_thread_param_t *)arg; int err = mysql_query(par->con, par->query); int err_no = mysql_errno(par->con); - DBUG_ASSERT(par->expect_err == err); - if (err && par->expect_errno) - DBUG_ASSERT(err_no == par->expect_errno); + if(par->expect_err != err) + { + msg("FATAL: dbug_execute_in_new_connection : mysql_query '%s' returns %d, instead of expected %d", + par->query, err, par->expect_err); + _exit(1); + } + if (err && par->expect_errno && par->expect_errno != err_no) + { + msg("FATAL: dbug_execute_in_new_connection: mysql_query '%s' returns mysql_errno %d, instead of expected %d", + par->query, err_no, par->expect_errno); + _exit(1); + } mysql_close(par->con); mysql_thread_end(); os_event_t done = par->done_event; @@ -686,16 +695,6 @@ static void backup_optimized_ddl_op_fail(ulint space_id) { } -/** Callback whenever MLOG_TRUNCATE happens. */ -static void backup_truncate_fail() -{ - msg("mariabackup: Incompatible TRUNCATE operation detected.%s\n", - opt_lock_ddl_per_table - ? "" - : " Use --lock-ddl-per-table to lock all tables before backup."); -} - - /* Retrieve default data directory, to be used with --copy-back. @@ -2665,8 +2664,7 @@ static lsn_t xtrabackup_copy_log(lsn_t start_lsn, lsn_t end_lsn, bool last) if (data_len == OS_FILE_LOG_BLOCK_SIZE) { /* We got a full log block. */ scanned_lsn += data_len; - } else if (data_len - >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE + } else if (data_len >= log_sys.trailer_offset() || data_len <= LOG_BLOCK_HDR_SIZE) { /* We got a garbage block (abrupt end of the log). */ msg("mariabackup: garbage block: " LSN_PF ",%zu\n", @@ -4226,7 +4224,6 @@ fail_before_log_copying_thread_start: log_copy_scanned_lsn = checkpoint_lsn_start; recv_sys->recovered_lsn = log_copy_scanned_lsn; log_optimized_ddl_op = backup_optimized_ddl_op; - log_truncate = backup_truncate_fail; if (xtrabackup_copy_logfile()) goto fail_before_log_copying_thread_start; @@ -4254,7 +4251,7 @@ fail_before_log_copying_thread_start: DBUG_EXECUTE_IF("check_mdl_lock_works", dbug_alter_thread_done = dbug_start_query_thread("ALTER TABLE test.t ADD COLUMN mdl_lock_column int", - "Waiting for table metadata lock", 1, ER_QUERY_INTERRUPTED);); + "Waiting for table metadata lock", 0, 0);); } datafiles_iter_t *it = datafiles_iter_new(); @@ -4472,6 +4469,7 @@ void backup_fix_ddl(void) } datafiles_iter_free(it); + DBUG_EXECUTE_IF("check_mdl_lock_works", DBUG_ASSERT(new_tables.size() == 0);); for (std::set<std::string>::iterator iter = new_tables.begin(); iter != new_tables.end(); iter++) { const char *space_name = iter->c_str(); diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index 07c95a79ddc..8eb0baa6eeb 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -41,24 +41,6 @@ const char *default_dbug_option="d:t:o,/tmp/my_print_defaults.trace"; static struct my_option my_long_options[] = { - /* - NB: --config-file is troublesome, because get_defaults_options() doesn't - know about it, but we pretend --config-file is like --defaults-file. In - fact they behave differently: see the comments at the top of - mysys/default.c for how --defaults-file should behave. - - This --config-file option behaves as: - - If it has a directory name part (absolute or relative), then only this - file is read; no error is given if the file doesn't exist - - If the file has no directory name part, the standard locations are - searched for a file of this name (and standard filename extensions are - added if the file has no extension) - */ - {"config-file", 'c', "Deprecated, please use --defaults-file instead. " - "Name of config file to read; if no extension is given, default " - "extension (e.g., .ini or .cnf) will be added", - (char**) &config_file, (char**) &config_file, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, #ifdef DBUG_OFF {"debug", '#', "This is a non-debug version. Catch this and exit", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -66,8 +48,8 @@ static struct my_option my_long_options[] = {"debug", '#', "Output debug log", (char**) &default_dbug_option, (char**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"defaults-file", 'c', "Like --config-file, except: if first option, " - "then read this file only, do not read global or per-user config " + {"defaults-file", 'c', + "Read this file only, do not read global or per-user config " "files; should be the first option", (char**) &config_file, (char*) &config_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -80,11 +62,6 @@ static struct my_option my_long_options[] = "In addition to the given groups, read also groups with this suffix", (char**) &my_defaults_group_suffix, (char**) &my_defaults_group_suffix, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"extra-file", 'e', - "Deprecated. Synonym for --defaults-extra-file.", - (void *)&my_defaults_extra_file, - (void *)&my_defaults_extra_file, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"mysqld", 0, "Read the same set of groups that the mysqld binary does.", &opt_mysqld, &opt_mysqld, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-defaults", 'n', "Return an empty string (useful for scripts).", @@ -107,7 +84,7 @@ static void cleanup_and_exit(int exit_code) static void version() { - printf("%s Ver 1.6 for %s at %s\n",my_progname,SYSTEM_TYPE, MACHINE_TYPE); + printf("%s Ver 1.7 for %s at %s\n",my_progname,SYSTEM_TYPE, MACHINE_TYPE); } diff --git a/extra/perror.c b/extra/perror.c index bd62401c8b2..49b1318cbb2 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -87,7 +87,7 @@ static void usage(void) { print_version(); puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000")); - printf("Print a description for a system error code or a MySQL error code.\n"); + printf("Print a description for a system error code or a MariaDB error code.\n"); printf("If you want to get the error for a negative error code, you should use\n-- before the first error code to tell perror that there was no more options.\n\n"); printf("Usage: %s [OPTIONS] [ERRORCODE [ERRORCODE...]]\n",my_progname); my_print_help(my_long_options); @@ -336,7 +336,7 @@ int main(int argc,char *argv[]) { found= 1; if (verbose) - printf("MySQL error code %3d: %s\n", code, msg); + printf("MariaDB error code %3d: %s\n", code, msg); else puts(msg); } @@ -344,7 +344,7 @@ int main(int argc,char *argv[]) { found= 1; if (verbose) - printf("MySQL error code %3d (%s): %s\n", code, name, msg); + printf("MariaDB error code %3d (%s): %s\n", code, name, msg); else puts(msg); } diff --git a/extra/resolve_stack_dump.c b/extra/resolve_stack_dump.c index dbd9941141d..78a32298dab 100644 --- a/extra/resolve_stack_dump.c +++ b/extra/resolve_stack_dump.c @@ -75,7 +75,7 @@ static void print_version(void) static void usage() { print_version(); - printf("MySQL AB, by Sasha Pachev\n"); + printf("MariaDB Corporation, originally created by Sasha Pachev\n"); printf("This software comes with ABSOLUTELY NO WARRANTY\n\n"); printf("Resolve numeric stack strace dump into symbols.\n\n"); printf("Usage: %s [OPTIONS] symbols-file [numeric-dump-file]\n", diff --git a/include/aria_backup.h b/include/aria_backup.h new file mode 100644 index 00000000000..bb2d06b0acd --- /dev/null +++ b/include/aria_backup.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2018 MariaDB corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +/* Interfaces for doing backups of Aria tables */ + +typedef struct st_aria_table_capabilities +{ + my_off_t header_size; + ulong bitmap_pages_covered; + uint block_size; + uint keypage_header; + my_bool checksum; + my_bool transactional; + /* This is true if the table can be copied without any locks */ + my_bool online_backup_safe; +} ARIA_TABLE_CAPABILITIES; + +int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap); +int aria_read_index(File kfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block, + uchar *buffer); +int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block, + uchar *buffer, size_t *bytes_read); diff --git a/include/json_lib.h b/include/json_lib.h index fed85b516d9..0f8cff79a32 100644 --- a/include/json_lib.h +++ b/include/json_lib.h @@ -174,11 +174,11 @@ enum json_value_types { JSON_VALUE_OBJECT=1, JSON_VALUE_ARRAY=2, - JSON_VALUE_STRING, - JSON_VALUE_NUMBER, - JSON_VALUE_TRUE, - JSON_VALUE_FALSE, - JSON_VALUE_NULL + JSON_VALUE_STRING=3, + JSON_VALUE_NUMBER=4, + JSON_VALUE_TRUE=5, + JSON_VALUE_FALSE=6, + JSON_VALUE_NULL=7 }; @@ -423,10 +423,14 @@ int json_path_parts_compare( int json_path_compare(const json_path_t *a, const json_path_t *b, enum json_value_types vt); +int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs); +int json_get_object_by_key(const char *js, size_t js_len, + const char *key, size_t key_len, + enum json_value_types *value_type, + const char **value_start, size_t *value_len); #ifdef __cplusplus } #endif #endif /* JSON_LIB_INCLUDED */ - diff --git a/include/m_ctype.h b/include/m_ctype.h index a4aa5b51218..c6273590bbe 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -362,7 +362,6 @@ extern MY_COLLATION_HANDLER my_collation_8bit_bin_handler; extern MY_COLLATION_HANDLER my_collation_8bit_simple_ci_handler; extern MY_COLLATION_HANDLER my_collation_8bit_nopad_bin_handler; extern MY_COLLATION_HANDLER my_collation_8bit_simple_nopad_ci_handler; -extern MY_COLLATION_HANDLER my_collation_ucs2_uca_handler; /* Some typedef to make it easy for C++ to make function pointers */ typedef int (*my_charset_conv_mb_wc)(CHARSET_INFO *, my_wc_t *, @@ -872,14 +871,6 @@ size_t my_strnxfrm_mb_nopad(CHARSET_INFO *, uchar *dst, size_t dstlen, uint nweights, const uchar *src, size_t srclen, uint flags); -size_t my_strnxfrm_unicode(CHARSET_INFO *, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags); - -size_t my_strnxfrm_unicode_nopad(CHARSET_INFO *, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags); - size_t my_strnxfrmlen_unicode(CHARSET_INFO *, size_t); size_t my_strnxfrm_unicode_full_bin(CHARSET_INFO *, diff --git a/include/m_string.h b/include/m_string.h index d50da8770c3..c8b5774b08c 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -99,7 +99,7 @@ extern char *strmake(char *dst,const char *src,size_t length); #define strmake_buf(D,S) strmake(D, S, sizeof(D) - 1) #else #define strmake_buf(D,S) ({ \ - typeof (D) __x __attribute__((unused)) = { 2 }; \ + __typeof__ (D) __x __attribute__((unused)) = { 2 }; \ strmake(D, S, sizeof(D) - 1); \ }) #endif diff --git a/include/my_global.h b/include/my_global.h index 37f78eabb4f..69b91f8b870 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -133,11 +133,6 @@ #define F_UNLCK 3 #define F_TO_EOF 0x3FFFFFFF -/* Shared memory and named pipe connections are supported. */ -#define HAVE_SMEM 1 -#define HAVE_NAMED_PIPE 1 -#define shared_memory_buffer_length 16000 -#define default_shared_memory_base_name "MYSQL" #endif /* _WIN32*/ @@ -1189,8 +1184,6 @@ typedef struct { const char *dli_fname, dli_fbase; } Dl_info; /* Things we don't need in the embedded version of MySQL */ /* TODO HF add #undef HAVE_VIO if we don't want client in embedded library */ -#undef HAVE_SMEM /* No shared memory */ - #else #define HAVE_REPLICATION #define HAVE_EXTERNAL_CLIENT diff --git a/include/my_pthread.h b/include/my_pthread.h index 2712c7d8ffd..843701ccab9 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -189,7 +189,19 @@ extern int my_pthread_create_detached; int sigwait(sigset_t *set, int *sig); #endif -#define my_sigwait(A,B) sigwait((A),(B)) +static inline int my_sigwait(sigset_t *set, int *sig, int *code) +{ +#ifdef HAVE_SIGWAITINFO + siginfo_t siginfo; + *sig= sigwaitinfo(set, &siginfo); + *code= siginfo.si_code; + return *sig < 0 ? errno : 0; +#else +#define SI_KERNEL 128 + *code= 0; + return sigwait(set, sig); +#endif +} #if defined(HAVE_SIGTHREADMASK) && !defined(HAVE_PTHREAD_SIGMASK) #define pthread_sigmask(A,B,C) sigthreadmask((A),(B),(C)) diff --git a/include/my_sys.h b/include/my_sys.h index 13ab7b12320..11993c02516 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -104,13 +104,12 @@ typedef struct my_aio_result { #define MY_GIVE_INFO 2U /* Give time info about process*/ #define MY_DONT_FREE_DBUG 4U /* Do not call DBUG_END() in my_end() */ -#define ME_BELL 4U /* Ring bell then printing message */ -#define ME_WAITTANG 0 /* Wait for a user action */ -#define ME_NOREFRESH 64U /* Write the error message to error log */ -#define ME_NOINPUT 0 /* Don't use the input library */ -#define ME_JUST_INFO 1024U /**< not error but just info */ -#define ME_JUST_WARNING 2048U /**< not error but just warning */ -#define ME_FATALERROR 4096U /* Fatal statement error */ +#define ME_BELL 4U /* Ring bell then printing message */ +#define ME_ERROR_LOG 64 /**< write the error message to error log */ +#define ME_ERROR_LOG_ONLY 128 /**< write the error message to error log only */ +#define ME_NOTE 1024 /**< not error but just info */ +#define ME_WARNING 2048 /**< not error but just warning */ +#define ME_FATAL 4096 /**< fatal statement error */ /* Bits in last argument to fn_format */ #define MY_REPLACE_DIR 1U /* replace dir in name with 'dir' */ @@ -329,7 +328,7 @@ typedef struct st_record_cache /* Used when caching records */ enum file_type { UNOPEN = 0, FILE_BY_OPEN, FILE_BY_CREATE, STREAM_BY_FOPEN, STREAM_BY_FDOPEN, - FILE_BY_MKSTEMP, FILE_BY_DUP + FILE_BY_O_TMPFILE, FILE_BY_MKSTEMP, FILE_BY_DUP }; struct st_my_file_info @@ -904,6 +903,7 @@ static inline char *safe_strdup_root(MEM_ROOT *root, const char *str) } extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len); extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len); +extern LEX_CSTRING safe_lexcstrdup_root(MEM_ROOT *root, const LEX_CSTRING str); extern my_bool my_compress(uchar *, size_t *, size_t *); extern my_bool my_uncompress(uchar *, size_t , size_t *); extern uchar *my_compress_alloc(const uchar *packet, size_t *len, diff --git a/include/my_time.h b/include/my_time.h index cec168c6fd6..27011be8b47 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -57,22 +57,20 @@ extern uchar days_in_month[]; /* Flags to str_to_datetime */ -/* - TIME_FUZZY_DATES is used for the result will only be used for comparison - purposes. Conversion is as relaxed as possible. -*/ -#define TIME_FUZZY_DATES 1U -#define TIME_DATETIME_ONLY 2U -#define TIME_TIME_ONLY 4U -#define TIME_NO_ZERO_IN_DATE (1UL << 23) /* == MODE_NO_ZERO_IN_DATE */ -#define TIME_NO_ZERO_DATE (1UL << 24) /* == MODE_NO_ZERO_DATE */ -#define TIME_INVALID_DATES (1UL << 25) /* == MODE_INVALID_DATES */ +#define C_TIME_NO_ZERO_IN_DATE (1UL << 23) /* == MODE_NO_ZERO_IN_DATE */ +#define C_TIME_NO_ZERO_DATE (1UL << 24) /* == MODE_NO_ZERO_DATE */ +#define C_TIME_INVALID_DATES (1UL << 25) /* == MODE_INVALID_DATES */ #define MYSQL_TIME_WARN_TRUNCATED 1U #define MYSQL_TIME_WARN_OUT_OF_RANGE 2U +#define MYSQL_TIME_WARN_EDOM 4U +#define MYSQL_TIME_WARN_ZERO_DATE 8U #define MYSQL_TIME_NOTE_TRUNCATED 16U -#define MYSQL_TIME_WARN_WARNINGS (MYSQL_TIME_WARN_TRUNCATED|MYSQL_TIME_WARN_OUT_OF_RANGE) +#define MYSQL_TIME_WARN_WARNINGS (MYSQL_TIME_WARN_TRUNCATED|\ + MYSQL_TIME_WARN_OUT_OF_RANGE|\ + MYSQL_TIME_WARN_EDOM|\ + MYSQL_TIME_WARN_ZERO_DATE) #define MYSQL_TIME_WARN_NOTES (MYSQL_TIME_NOTE_TRUNCATED) #define MYSQL_TIME_WARN_HAVE_WARNINGS(x) MY_TEST((x) & MYSQL_TIME_WARN_WARNINGS) @@ -81,6 +79,16 @@ extern uchar days_in_month[]; /* Useful constants */ #define SECONDS_IN_24H 86400L +/* Limits for the INTERVAL data type */ + + /* Number of hours between '0001-01-01 00h' and '9999-12-31 23h' */ +#define TIME_MAX_INTERVAL_HOUR 87649415 +#define TIME_MAX_INTERVAL_HOUR_CHAR_LENGTH 8 + +/* Number of full days between '0001-01-01' and '9999-12-31'*/ +#define TIME_MAX_INTERVAL_DAY 3652058 /*87649415/24*/ +#define TIME_MAX_INTERVAL_DAY_CHAR_LENGTH 7 + /* Limits for the TIME data type */ #define TIME_MAX_HOUR 838 #define TIME_MAX_MINUTE 59 @@ -100,35 +108,46 @@ typedef struct st_mysql_time_status { int warnings; uint precision; + uint nanoseconds; } MYSQL_TIME_STATUS; static inline void my_time_status_init(MYSQL_TIME_STATUS *status) { status->warnings= 0; status->precision= 0; + status->nanoseconds= 0; } my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date, ulonglong flags, int *was_cut); -my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time, - ulonglong flag, MYSQL_TIME_STATUS *status); -my_bool str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time, - ulonglong flags, MYSQL_TIME_STATUS *status); -longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res, - ulonglong flags, int *was_cut); - -static inline -longlong double_to_datetime(double nr, MYSQL_TIME *ltime, ulonglong flags, int *cut) -{ - if (nr < 0 || nr > LONGLONG_MAX) - nr= (double)LONGLONG_MAX; - return number_to_datetime((longlong) floor(nr), - (ulong)((nr-floor(nr))*TIME_SECOND_PART_FACTOR), - ltime, flags, cut); -} +my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *l_time, + ulong max_hour, MYSQL_TIME_STATUS *status); +my_bool str_to_datetime_or_date_or_time(const char *str, size_t length, + MYSQL_TIME *to, ulonglong flag, + MYSQL_TIME_STATUS *status, + ulong time_max_hour, + ulong time_err_hour); +my_bool +str_to_datetime_or_date_or_interval_hhmmssff(const char *str, size_t length, + MYSQL_TIME *to, ulonglong flag, + MYSQL_TIME_STATUS *status, + ulong time_max_hour, + ulong time_err_hour); +my_bool +str_to_datetime_or_date_or_interval_day(const char *str, size_t length, + MYSQL_TIME *to, ulonglong flag, + MYSQL_TIME_STATUS *status, + ulong time_max_hour, + ulong time_err_hour); +my_bool str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *to, + ulonglong flags, MYSQL_TIME_STATUS *status); + +longlong number_to_datetime_or_date(longlong nr, ulong sec_part, + MYSQL_TIME *time_res, + ulonglong flags, int *was_cut); +int number_to_time_only(my_bool neg, ulonglong nr, ulong sec_part, + ulong max_hour, MYSQL_TIME *to, int *was_cut); -int number_to_time(my_bool neg, ulonglong nr, ulong sec_part, - MYSQL_TIME *ltime, int *was_cut); ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *); ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *); ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *); @@ -191,6 +210,7 @@ void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type); #define MAX_DATE_STRING_REP_LENGTH 30 #define AUTO_SEC_PART_DIGITS DECIMAL_NOT_SPECIFIED +int my_interval_DDhhmmssff_to_str(const MYSQL_TIME *, char *to, uint digits); int my_time_to_str(const MYSQL_TIME *l_time, char *to, uint digits); int my_date_to_str(const MYSQL_TIME *l_time, char *to); int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint digits); diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index b122d888c6d..02a87c6db71 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -75,7 +75,7 @@ typedef struct st_mysql_xid MYSQL_XID; #define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104 /* MariaDB plugin interface version */ -#define MARIA_PLUGIN_INTERFACE_VERSION 0x010d +#define MARIA_PLUGIN_INTERFACE_VERSION 0x010e /* The allowable types of plugins diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index 89f7dcc36c4..0588b211b81 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -374,6 +374,51 @@ extern struct thd_wait_service_st { } *thd_wait_service; void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **v, int *vlen); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **v, int *vlen); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_auth.h b/include/mysql/plugin_auth.h index 638d9b57fd9..44e51c3fd0b 100644 --- a/include/mysql/plugin_auth.h +++ b/include/mysql/plugin_auth.h @@ -27,7 +27,7 @@ #include <mysql/plugin.h> -#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0201 +#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0202 #include <mysql/plugin_auth_common.h> @@ -60,7 +60,8 @@ typedef struct st_mysql_server_auth_info /** A corresponding column value from the mysql.user table for the - matching account name + matching account name or the preprocessed value, if preprocess_hash + method is not NULL */ const char *auth_string; @@ -130,6 +131,47 @@ struct st_mysql_auth used for authorization. */ int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info); + /** + Create a password hash (or digest) out of a plain-text password + + Used in SET PASSWORD, GRANT, and CREATE USER to convert user specified + plain-text password into a value that will be stored in mysql.user table. + + @see preprocess_hash + + @param password plain-text password + @param password_length plain-text password length + @param hash the digest will be stored there + @param hash_length in: hash buffer size + out: the actual length of the hash + + @return 0 for ok, 1 for error + + Can be NULL. + */ + int (*hash_password)(const char *password, size_t password_length, + char *hash, size_t *hash_length); + + /** + Prepare the password hash for authentication. + + Password hash is stored in the authentication_string column of the + mysql.user table in a text form. If a plugin needs to preprocess the + value somehow before the authentication (e.g. convert from hex or base64 + to binary), it can do it in this method. This way the conversion + will happen only once, not for every authentication attempt. + + The value written to the out buffer will be cached and later made + available to the authenticate_user() method in the + MYSQL_SERVER_AUTH_INFO::auth_string[] buffer. + + @return 0 for ok, 1 for error + + Can be NULL, in this case the mysql.user.authentication_string value will + be given to the authenticate_user() method as is, unconverted. + */ + int (*preprocess_hash)(const char *hash, size_t hash_length, + unsigned char *out, size_t *out_length); }; #ifdef __cplusplus diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index e515699cad6..cfb9201bb1e 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -374,6 +374,51 @@ extern struct thd_wait_service_st { } *thd_wait_service; void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **v, int *vlen); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **v, int *vlen); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); struct st_mysql_xid { long formatID; long gtrid_length; @@ -561,4 +606,8 @@ struct st_mysql_auth int interface_version; const char *client_auth_plugin; int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info); + int (*hash_password)(const char *password, size_t password_length, + char *hash, size_t *hash_length); + int (*preprocess_hash)(const char *hash, size_t hash_length, + unsigned char *out, size_t *out_length); }; diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp index 7defe0aec2c..7761a3e600d 100644 --- a/include/mysql/plugin_encryption.h.pp +++ b/include/mysql/plugin_encryption.h.pp @@ -374,6 +374,51 @@ extern struct thd_wait_service_st { } *thd_wait_service; void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **v, int *vlen); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **v, int *vlen); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index a36f51e74e1..2e775976015 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -374,6 +374,51 @@ extern struct thd_wait_service_st { } *thd_wait_service; void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **v, int *vlen); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **v, int *vlen); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_password_validation.h b/include/mysql/plugin_password_validation.h index e2763483db6..699d42d6b50 100644 --- a/include/mysql/plugin_password_validation.h +++ b/include/mysql/plugin_password_validation.h @@ -42,8 +42,8 @@ struct st_mariadb_password_validation Function provided by the plugin which should perform password validation and return 0 if the password has passed the validation. */ - int (*validate_password)(MYSQL_CONST_LEX_STRING *username, - MYSQL_CONST_LEX_STRING *password); + int (*validate_password)(const MYSQL_CONST_LEX_STRING *username, + const MYSQL_CONST_LEX_STRING *password); }; #ifdef __cplusplus diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp index 9701ad1b92f..7492642a3ee 100644 --- a/include/mysql/plugin_password_validation.h.pp +++ b/include/mysql/plugin_password_validation.h.pp @@ -374,6 +374,51 @@ extern struct thd_wait_service_st { } *thd_wait_service; void thd_wait_begin(void* thd, int wait_type); void thd_wait_end(void* thd); +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **v, int *vlen); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; +enum json_types json_type(const char *js, const char *js_end, + const char **v, int *vlen); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); struct st_mysql_xid { long formatID; long gtrid_length; @@ -531,6 +576,6 @@ void thd_wakeup_subsequent_commits(void* thd, int wakeup_error); struct st_mariadb_password_validation { int interface_version; - int (*validate_password)(MYSQL_CONST_LEX_STRING *username, - MYSQL_CONST_LEX_STRING *password); + int (*validate_password)(const MYSQL_CONST_LEX_STRING *username, + const MYSQL_CONST_LEX_STRING *password); }; diff --git a/include/mysql/service_json.h b/include/mysql/service_json.h new file mode 100644 index 00000000000..204417248c6 --- /dev/null +++ b/include/mysql/service_json.h @@ -0,0 +1,117 @@ +/* Copyright (C) 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +#ifndef MYSQL_SERVICE_JSON +#define MYSQL_SERVICE_JSON + +/** + @file + json service + + Esports JSON parsing methods for plugins to use. + + Fuctions of the service: + js_type - returns the type of the JSON argument, + and the parsed value if it's scalar (not object or array) + + js_get_array_item - expecs JSON array as an argument, + and returns the n_item's item's type and value + Returns JSV_NOTHING type if the array is shorter + than n_item and the actual length of the array in v_len. + + js_get_object_key - expects JSON object as an argument, + searches for a key in the object, return it's type and value. + JSV_NOTHING if no such key found, the number of keys + in v_len. + + js_get_object_nkey - expects JSON object as an argument. + finds n_key's key in the object, returns it's name, type and value. + JSV_NOTHING if object has less keys than n_key. +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +enum json_types +{ + JSV_BAD_JSON=-1, + JSV_NOTHING=0, + JSV_OBJECT=1, + JSV_ARRAY=2, + JSV_STRING=3, + JSV_NUMBER=4, + JSV_TRUE=5, + JSV_FALSE=6, + JSV_NULL=7 +}; + +extern struct json_service_st { + enum json_types (*json_type)(const char *js, const char *js_end, + const char **v, int *vlen); + enum json_types (*json_get_array_item)(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); + enum json_types (*json_get_object_key)(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); + enum json_types (*json_get_object_nkey)(const char *js,const char *js_end, + int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); + int (*json_escape_string)(const char *str,const char *str_end, + char *json, char *json_end); + int (*json_unescape_json)(const char *json_str, const char *json_end, + char *res, char *res_end); +} *json_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define json_type json_service->json_type +#define json_get_array_item json_service->json_get_array_item +#define json_get_object_key json_service->json_get_object_key +#define json_get_object_nkey json_service->json_get_object_nkey +#define json_escape_string json_service->json_escape_string +#define json_unescape_json json_service->json_unescape_json + +#else + +enum json_types json_type(const char *js, const char *js_end, + const char **v, int *vlen); +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen); +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen); +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen); +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end); +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end); + +#endif /*MYSQL_DYNAMIC_PLUGIN*/ + + +#ifdef __cplusplus +} +#endif + +#endif /*MYSQL_SERVICE_JSON */ + + diff --git a/include/mysql/service_my_print_error.h b/include/mysql/service_my_print_error.h index 5a71be74fd0..0046ba54f6d 100644 --- a/include/mysql/service_my_print_error.h +++ b/include/mysql/service_my_print_error.h @@ -32,10 +32,11 @@ extern "C" { #include <stdlib.h> #endif -#define ME_ERROR_LOG 64 /* Write the message to the error log */ -#define ME_NOTE 1024 /* Not an error, just a note */ -#define ME_WARNING 2048 /* Not an error, just a warning */ -#define ME_FATAL 4096 /* Fatal statement error */ +#define ME_ERROR_LOG 64 /* Write the message to the error log */ +#define ME_ERROR_LOG_ONLY 128 /* Write the error message to error log only */ +#define ME_NOTE 1024 /* Not an error, just a note */ +#define ME_WARNING 2048 /* Not an error, just a warning */ +#define ME_FATAL 4096 /* Fatal statement error */ extern struct my_print_error_service_st { void (*my_error_func)(unsigned int nr, unsigned long MyFlags, ...); diff --git a/include/mysql/services.h b/include/mysql/services.h index 6168c5ed8dc..6dc970df1e6 100644 --- a/include/mysql/services.h +++ b/include/mysql/services.h @@ -39,6 +39,7 @@ extern "C" { #include <mysql/service_thd_specifics.h> #include <mysql/service_thd_timezone.h> #include <mysql/service_thd_wait.h> +#include <mysql/service_json.h> /*#include <mysql/service_wsrep.h>*/ #ifdef __cplusplus diff --git a/include/mysql_com.h b/include/mysql_com.h index 902c0ff2706..8b0847ab399 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -231,6 +231,7 @@ enum enum_indicator_type #define REFRESH_DES_KEY_FILE (1ULL << 18) #define REFRESH_USER_RESOURCES (1ULL << 19) #define REFRESH_FOR_EXPORT (1ULL << 20) /* FLUSH TABLES ... FOR EXPORT */ +#define REFRESH_SSL (1ULL << 21) #define REFRESH_GENERIC (1ULL << 30) #define REFRESH_FAST (1ULL << 31) /* Intern flag */ diff --git a/include/mysql_embed.h b/include/mysql_embed.h index 12b18ff965e..3047593fb6c 100644 --- a/include/mysql_embed.h +++ b/include/mysql_embed.h @@ -25,7 +25,6 @@ /* TODO HF add #undef HAVE_VIO if we don't want client in embedded library */ #undef HAVE_DLOPEN /* No udf functions */ -#undef HAVE_SMEM /* No shared memory */ #endif /* EMBEDDED_LIBRARY */ #endif /* MYSQL_EMBED_INCLUDED */ diff --git a/include/service_versions.h b/include/service_versions.h index 753d6444475..050012d30b9 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -42,3 +42,4 @@ #define VERSION_thd_timezone 0x0100 #define VERSION_thd_wait 0x0100 #define VERSION_wsrep 0x0202 +#define VERSION_json 0x0100 diff --git a/include/violite.h b/include/violite.h index 55f8328df47..74b53f41fdd 100644 --- a/include/violite.h +++ b/include/violite.h @@ -38,7 +38,7 @@ typedef struct st_vio Vio; enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, VIO_TYPE_NAMEDPIPE, - VIO_TYPE_SSL, VIO_TYPE_SHARED_MEMORY + VIO_TYPE_SSL }; /** @@ -68,13 +68,6 @@ Vio* vio_new(my_socket sd, enum enum_vio_type type, uint flags); Vio* mysql_socket_vio_new(MYSQL_SOCKET mysql_socket, enum enum_vio_type type, uint flags); #ifdef __WIN__ Vio* vio_new_win32pipe(HANDLE hPipe); -Vio* vio_new_win32shared_memory(HANDLE handle_file_map, - HANDLE handle_map, - HANDLE event_server_wrote, - HANDLE event_server_read, - HANDLE event_client_wrote, - HANDLE event_client_read, - HANDLE event_conn_closed); #else #define HANDLE void * #endif /* __WIN__ */ @@ -89,6 +82,7 @@ size_t vio_write(Vio *vio, const uchar * buf, size_t size); int vio_blocking(Vio *vio, my_bool onoff, my_bool *old_mode); my_bool vio_is_blocking(Vio *vio); /* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible */ +int vio_nodelay(Vio *vio, my_bool on); int vio_fastsend(Vio *vio); /* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible */ int vio_keepalive(Vio *vio, my_bool onoff); @@ -264,22 +258,9 @@ struct st_vio #ifdef HAVE_OPENSSL void *ssl_arg; #endif -#ifdef HAVE_SMEM - HANDLE handle_file_map; - char *handle_map; - HANDLE event_server_wrote; - HANDLE event_server_read; - HANDLE event_client_wrote; - HANDLE event_client_read; - HANDLE event_conn_closed; - size_t shared_memory_remain; - char *shared_memory_pos; -#endif /* HAVE_SMEM */ #ifdef _WIN32 HANDLE hPipe; OVERLAPPED overlapped; - DWORD read_timeout_ms; - DWORD write_timeout_ms; #endif }; #endif /* vio_violite_h_ */ diff --git a/include/wsrep.h b/include/wsrep.h index 843b9c51198..f7a9b6b0231 100644 --- a/include/wsrep.h +++ b/include/wsrep.h @@ -50,10 +50,10 @@ #define WSREP_WARN(...) WSREP_LOG(sql_print_warning, ##__VA_ARGS__) #define WSREP_ERROR(...) WSREP_LOG(sql_print_error, ##__VA_ARGS__) -#define WSREP_SYNC_WAIT(thd_, before_) \ - { if (WSREP_CLIENT(thd_) && \ +#define WSREP_SYNC_WAIT(thd_, before_) \ + { if (WSREP_CLIENT(thd_) && \ wsrep_sync_wait(thd_, before_)) goto wsrep_error_label; } -#define WSREP_ERROR_LABEL wsrep_error_label + #else #define IF_WSREP(A,B) B #define DBUG_ASSERT_IF_WSREP(A) @@ -61,12 +61,11 @@ #define WSREP_INFO(...) #define WSREP_WARN(...) #define WSREP_ERROR(...) -#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) +#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) do { } while(0) #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) #define WSREP_TO_ISOLATION_END #define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_) #define WSREP_SYNC_WAIT(thd_, before_) -#define WSREP_ERROR_LABEL goto wsrep_error_label; wsrep_error_label #endif /* WITH_WSREP */ diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 537f40cbbbf..dfb5d4ce86f 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -118,7 +118,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/ha_sequence.cc ../sql/ha_sequence.h ../sql/temporary_tables.cc ../sql/session_tracker.cc - ../sql/proxy_protocol.cc + ../sql/proxy_protocol.cc ../sql/backup.cc ../sql/sql_tvc.cc ../sql/sql_tvc.h ../sql/opt_split.cc ../sql/item_vers.cc diff --git a/libmysqld/libmysql.c b/libmysqld/libmysql.c index b3ef96698ff..cd170b42b42 100644 --- a/libmysqld/libmysql.c +++ b/libmysqld/libmysql.c @@ -3215,7 +3215,8 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, size_t { MYSQL_TIME *tm= (MYSQL_TIME *)buffer; MYSQL_TIME_STATUS status; - str_to_time(value, length, tm, 0, &status); + str_to_datetime_or_date_or_time(value, length, tm, 0, &status, + TIME_MAX_HOUR, UINT_MAX32); err= status.warnings; *param->error= MY_TEST(err); break; @@ -3226,7 +3227,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, size_t { MYSQL_TIME *tm= (MYSQL_TIME *)buffer; MYSQL_TIME_STATUS status; - (void) str_to_datetime(value, length, tm, 0, &status); + (void) str_to_datetime_or_date(value, length, tm, 0, &status); err= status.warnings; *param->error= MY_TEST(err) && (param->buffer_type == MYSQL_TYPE_DATE && tm->time_type != MYSQL_TIMESTAMP_DATE); @@ -3350,7 +3351,7 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, case MYSQL_TYPE_DATETIME: { int error; - value= number_to_datetime(value, 0, (MYSQL_TIME *) buffer, 0, &error); + value= number_to_datetime_or_date(value, 0, (MYSQL_TIME *) buffer, 0, &error); *param->error= MY_TEST(error); break; } diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt index e20be6d7a7c..b99be7106e1 100644 --- a/libservices/CMakeLists.txt +++ b/libservices/CMakeLists.txt @@ -37,6 +37,7 @@ SET(MYSQLSERVICES_SOURCES thd_timezone_service.c thd_wait_service.c wsrep_service.c + json_service.c ) ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES}) diff --git a/libservices/json_service.c b/libservices/json_service.c new file mode 100644 index 00000000000..96b3b3fa532 --- /dev/null +++ b/libservices/json_service.c @@ -0,0 +1,19 @@ + +/* Copyright (c) 2018, Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <service_versions.h> +SERVICE_VERSION json_service= (void*)VERSION_json; diff --git a/man/my_print_defaults.1 b/man/my_print_defaults.1 index b01d24b2e86..507250f8ca8 100644 --- a/man/my_print_defaults.1 +++ b/man/my_print_defaults.1 @@ -74,14 +74,14 @@ Display a help message and exit\&. .\} .\" my_print_defaults: config-file option .\" config-file option: my_print_defaults -\fB\-\-config\-file=\fR\fB\fIfile_name\fR\fR, +\fB .\" my_print_defaults: defaults-file option .\" defaults-file option: my_print_defaults \fB\-\-defaults\-file=\fR\fB\fIfile_name\fR\fR, \fB\-c \fR\fB\fIfile_name\fR\fR .sp Read only the given option file\&. If no extension is given, default extension(.ini or .cnf) will -be used\&. \fB\-\-config-file\fR is deprecated, use \fB\-\-defaults\-file\fR instead\&. If \fB\-\-defaults\-file\fR is +be used\&. If \fB\-\-defaults\-file\fR is the first option, then read this file only, do not read global or per\-user config files; should be the first option. .RE .sp @@ -118,11 +118,10 @@ string is \fB\-\-defaults\-extra\-file=\fR\fB\fIfile_name\fR\fR, .\" my_print_defaults: extra-file option .\" extra-file option: my_print_defaults -\fB\-\-extra\-file=\fR\fB\fIfile_name\fR\fR, \fB\-e \fR\fB\fIfile_name\fR\fR .sp Read this option file after the global option file but (on Unix) before the user option -file\&. Should be the first option\&. \fB\-\-extra\-file\fR is deprecated, use \fB\-\-defaults\-extra\-file\fR\&. +file\&. Should be the first option\&. .RE .sp .RS 4 diff --git a/mysql-test/include/add_anonymous_users.inc b/mysql-test/include/add_anonymous_users.inc index 635a80e3dee..86ce529d1e2 100644 --- a/mysql-test/include/add_anonymous_users.inc +++ b/mysql-test/include/add_anonymous_users.inc @@ -1,7 +1,7 @@ # Allow anonymous users to connect disable_warnings; disable_query_log; -INSERT IGNORE INTO mysql.user (host, user) VALUES ('localhost',''); +INSERT IGNORE INTO mysql.global_priv (host, user) VALUES ('localhost',''); FLUSH PRIVILEGES; enable_query_log; enable_warnings; diff --git a/mysql-test/include/check-testcase.test b/mysql-test/include/check-testcase.test index 3c164eef8b6..a9c8e13fa7c 100644 --- a/mysql-test/include/check-testcase.test +++ b/mysql-test/include/check-testcase.test @@ -81,6 +81,18 @@ if (!$tmp) { SHOW SLAVE STATUS; } +# +# Ensure that we don't get warnings from mysql.proc (used by check_mysqld) +# + +--disable_query_log +--disable_warnings +--disable_result_log +select count(*) from mysql.proc; +--enable_result_log +--enable_warnings +--enable_query_log + call mtr.check_testcase(); let $datadir=`select @@datadir`; diff --git a/mysql-test/include/check_ftwrl_incompatible.inc b/mysql-test/include/check_ftwrl_incompatible.inc index 4787a69ea9c..a7e87c3750b 100644 --- a/mysql-test/include/check_ftwrl_incompatible.inc +++ b/mysql-test/include/check_ftwrl_incompatible.inc @@ -68,8 +68,7 @@ connection $con_aux1; --enable_query_log let $wait_condition= select count(*) = 1 from information_schema.processlist - where (state = "Waiting for global read lock" or - state = "Waiting for commit lock") and + where state = "Waiting for backup lock" and info = "$statement"; --source include/wait_condition.inc --disable_result_log @@ -116,8 +115,7 @@ connection $con_aux2; --enable_query_log let $wait_condition= select count(*) = 1 from information_schema.processlist - where (state = "Waiting for global read lock" or - state = "Waiting for commit lock") and + where state = "Waiting for backup lock" and info = "flush tables with read lock"; --source include/wait_condition.inc --disable_result_log diff --git a/mysql-test/include/deadlock.inc b/mysql-test/include/deadlock.inc index 2fa61f48624..7ac2a16fc44 100644 --- a/mysql-test/include/deadlock.inc +++ b/mysql-test/include/deadlock.inc @@ -94,7 +94,7 @@ insert into t2 values(0, 0), (1, 20), (2, 30); commit; connection con1; -select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE; +select a,b from t2 UNION (SELECT id, x from t1 FOR UPDATE); select * from t2; select * from t1; diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index 69a2b58288b..edae06ee7be 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -107,6 +107,7 @@ loose-performance-schema-consumer-thread-instrumentation=ON binlog-direct-non-transactional-updates default-storage-engine=myisam +use_stat_tables=preferably loose-ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem loose-ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem diff --git a/mysql-test/include/diff_tables.inc b/mysql-test/include/diff_tables.inc index b5ee4db0e8f..a29156cfce9 100644 --- a/mysql-test/include/diff_tables.inc +++ b/mysql-test/include/diff_tables.inc @@ -167,7 +167,7 @@ while ($_dt_tables) # the table to a file. --let $_dt_outfile= `SELECT @@datadir` --let $_dt_outfile= $_dt_outfile/diff_table-$_dt_connection-$_dt_database-$_dt_table - eval SELECT * FROM $_dt_database.$_dt_table ORDER BY `$_dt_column_list` INTO OUTFILE '$_dt_outfile'; + eval SELECT * INTO OUTFILE '$_dt_outfile' FROM $_dt_database.$_dt_table ORDER BY `$_dt_column_list`; # Compare files. if ($_dt_prev_outfile) diff --git a/mysql-test/include/maria_empty_logs.inc b/mysql-test/include/maria_empty_logs.inc index 78a08228caa..f1835c0d2c3 100644 --- a/mysql-test/include/maria_empty_logs.inc +++ b/mysql-test/include/maria_empty_logs.inc @@ -92,3 +92,15 @@ connection default; --disable_query_log eval use $default_db; --enable_query_log + +# +# Ensure that we don't get warnings from mysql.priv (used by check_mysqld) +# or test running after this one. +# +--disable_query_log +--disable_warnings +--disable_result_log +show table status from mysql; +--enable_result_log +--enable_warnings +--enable_query_log diff --git a/mysql-test/include/maria_verify_recovery.inc b/mysql-test/include/maria_verify_recovery.inc index b0f95d2a94b..bb782d5f4cc 100644 --- a/mysql-test/include/maria_verify_recovery.inc +++ b/mysql-test/include/maria_verify_recovery.inc @@ -97,3 +97,15 @@ while ($mms_table_to_use) connection default; # the effect of "use" is lost after a restart so we are back into db "test" use mysqltest; + +# +# Ensure that we don't get warnings from mysql.proc (used by check_mysqld) +# + +--disable_query_log +--disable_warnings +--disable_result_log +select count(*) from mysql.proc; +--enable_result_log +--enable_warnings +--enable_query_log diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql index f2c0b70e192..b5673b2a313 100644 --- a/mysql-test/include/mtr_check.sql +++ b/mysql-test/include/mtr_check.sql @@ -85,7 +85,6 @@ BEGIN mysql.help_category, mysql.help_keyword, mysql.help_relation, - mysql.host, mysql.plugin, mysql.proc, mysql.procs_priv, @@ -96,7 +95,7 @@ BEGIN mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, - mysql.user; + mysql.global_priv; -- verify that no plugin changed its disabled/enabled state SELECT * FROM INFORMATION_SCHEMA.PLUGINS; diff --git a/mysql-test/include/switch_to_mysql_global_priv.inc b/mysql-test/include/switch_to_mysql_global_priv.inc new file mode 100644 index 00000000000..78df6642760 --- /dev/null +++ b/mysql-test/include/switch_to_mysql_global_priv.inc @@ -0,0 +1,6 @@ +disable_query_log; +drop table mysql.user; +rename table mysql.user_bak to mysql.user; +rename table mysql.global_priv_bak to mysql.global_priv; +flush privileges; +enable_query_log; diff --git a/mysql-test/include/switch_to_mysql_user.inc b/mysql-test/include/switch_to_mysql_user.inc new file mode 100644 index 00000000000..f5801db6114 --- /dev/null +++ b/mysql-test/include/switch_to_mysql_user.inc @@ -0,0 +1,56 @@ +disable_query_log; +rename table mysql.user to mysql.user_bak; +CREATE TABLE mysql.user ( + Host char(60) binary DEFAULT '' NOT NULL, + User char(80) binary DEFAULT '' NOT NULL, + Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, + Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + Delete_history_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + ssl_type enum('','ANY','X509','SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, + ssl_cipher BLOB NOT NULL, + x509_issuer BLOB NOT NULL, + x509_subject BLOB NOT NULL, + max_questions int(11) unsigned DEFAULT 0 NOT NULL, + max_updates int(11) unsigned DEFAULT 0 NOT NULL, + max_connections int(11) unsigned DEFAULT 0 NOT NULL, + max_user_connections int(11) DEFAULT 0 NOT NULL, + plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, + authentication_string TEXT NOT NULL, + password_expired ENUM('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + is_role enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, + default_role char(80) binary DEFAULT '' NOT NULL, + max_statement_time decimal(12,6) DEFAULT 0 NOT NULL, + PRIMARY KEY Host (Host,User) +) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; +insert mysql.user select * from mysql.user_bak; +rename table mysql.global_priv to mysql.global_priv_bak; +flush privileges; +enable_query_log; diff --git a/mysql-test/include/system_db_struct.inc b/mysql-test/include/system_db_struct.inc index 9467c023dba..d043d209850 100644 --- a/mysql-test/include/system_db_struct.inc +++ b/mysql-test/include/system_db_struct.inc @@ -5,9 +5,9 @@ -- replace_result Tables_in_mysql Tables_in_db Tables_in_test Tables_in_db show tables; show create table db; -show create table host; show create table user; show create table func; +show create table global_priv; show create table tables_priv; show create table columns_priv; show create table procs_priv; diff --git a/mysql-test/include/wait_until_connected_again.inc b/mysql-test/include/wait_until_connected_again.inc index 26168d10558..15a1e5bf847 100644 --- a/mysql-test/include/wait_until_connected_again.inc +++ b/mysql-test/include/wait_until_connected_again.inc @@ -11,7 +11,7 @@ let $counter= 5000; let $mysql_errno= 9999; while ($mysql_errno) { - --error 0,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,ER_LOCK_WAIT_TIMEOUT,2002,2006,2013 + --error 0,ER_ACCESS_DENIED_ERROR,ER_SERVER_SHUTDOWN,ER_CONNECTION_KILLED,ER_LOCK_WAIT_TIMEOUT,2002,2006,2013 show status; dec $counter; @@ -19,13 +19,18 @@ while ($mysql_errno) { --die Server failed to restart } + if (!$mysql_errno) + { + # WSREP: SHOW STATUS queries are allowed even if wsrep + # is not ready. Make sure wsrep is ready before + # returning from this script + source include/wait_wsrep_ready.inc; + } + if ($mysql_errno == 1045) + { + let $mysql_errno=0; + } --sleep 0.1 } --enable_query_log --enable_result_log - -# WSREP: SHOW STATUS queries are allowed even if wsrep -# is not ready. Make sure wsrep is ready before -# returning from this script - ---source include/wait_wsrep_ready.inc diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm index 830b49d431f..d481058902f 100644 --- a/mysql-test/lib/My/ConfigFactory.pm +++ b/mysql-test/lib/My/ConfigFactory.pm @@ -209,13 +209,6 @@ my @mysqld_rules= { 'bind-address' => \&fix_bind_address }, ); -if (IS_WINDOWS) -{ - # For simplicity, we use the same names for shared memory and - # named pipes. - push(@mysqld_rules, {'shared-memory-base-name' => \&fix_socket}); -} - # # Rules to run for [client] section # - will be run in order listed here @@ -281,19 +274,6 @@ sub post_check_client_group { } $config->insert($client_group_name, $name_to, $option->value()) } - - if (IS_WINDOWS) - { - if (! $self->{ARGS}->{embedded}) - { - # Shared memory base may or may not be defined (e.g not defined in embedded) - my $shm = $group_to_copy_from->option("shared-memory-base-name"); - if (defined $shm) - { - $config->insert($client_group_name,"shared-memory-base-name", $shm->value()); - } - } - } } @@ -340,7 +320,6 @@ sub post_check_embedded_group { ( 'log-error', # Embedded server writes stderr to mysqltest's log file 'slave-net-timeout', # Embedded server are not build with replication - 'shared-memory-base-name', # No shared memory for embedded ); foreach my $option ( $mysqld->options(), $first_mysqld->options() ) { diff --git a/mysql-test/lib/generate-ssl-certs.sh b/mysql-test/lib/generate-ssl-certs.sh index 8f15ba9d521..6f492e9f61f 100755 --- a/mysql-test/lib/generate-ssl-certs.sh +++ b/mysql-test/lib/generate-ssl-certs.sh @@ -21,6 +21,11 @@ openssl rsa -in server-key.pem -out server-key.pem # sign the server certificate with CA certificate openssl ca -keyfile cakey.pem -days 7300 -batch -cert cacert.pem -policy policy_anything -out server-cert.pem -infiles demoCA/server-req.pem +# Certificate with different validity period (MDEV-7598) +openssl req -newkey rsa:1024 -keyout server-new-key.pem -out demoCA/server-new-req.pem -days 7301 -nodes -subj '/CN=server-new/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB' +openssl rsa -in server-new-key.pem -out server-new-key.pem +openssl ca -keyfile cakey.pem -days 7301 -batch -cert cacert.pem -policy policy_anything -out server-new-cert.pem -infiles demoCA/server-new-req.pem + openssl req -newkey rsa:8192 -keyout server8k-key.pem -out demoCA/server8k-req.pem -days 7300 -nodes -subj '/CN=server8k/C=FI/ST=Helsinki/L=Helsinki/O=MariaDB' openssl rsa -in server8k-key.pem -out server8k-key.pem openssl ca -keyfile cakey.pem -days 7300 -batch -cert cacert.pem -policy policy_anything -out server8k-cert.pem -infiles demoCA/server8k-req.pem diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 61ce88f9a5a..3fe57987713 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -291,6 +291,7 @@ sub combinations_from_file($$) @combs = ({ skip => $skip_combinations{$filename} }); } else { return () if @::opt_combinations or not -f $filename; + return () if ::using_extern(); # Read combinations file in my.cnf format mtr_verbose("Read combinations file $filename"); my $config= My::Config->new($filename); diff --git a/mysql-test/main/1st.result b/mysql-test/main/1st.result index cb2da3505f5..c630be1d61c 100644 --- a/mysql-test/main/1st.result +++ b/mysql-test/main/1st.result @@ -13,12 +13,12 @@ db event func general_log +global_priv gtid_slave_pos help_category help_keyword help_relation help_topic -host index_stats innodb_index_stats innodb_table_stats diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result index a896d24d510..92946b65e66 100644 --- a/mysql-test/main/alter_table.result +++ b/mysql-test/main/alter_table.result @@ -181,6 +181,7 @@ t1 0 a 2 b A 300 NULL NULL YES BTREE t1 1 b 1 b A 100 NULL NULL YES BTREE analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/mysql-test/main/alter_user.result b/mysql-test/main/alter_user.result index 76f811f18c7..cc3c4a43ffe 100644 --- a/mysql-test/main/alter_user.result +++ b/mysql-test/main/alter_user.result @@ -1,3 +1,4 @@ +select priv into @root_priv from mysql.global_priv where user='root' and host='localhost'; select * from mysql.user where user = 'root' and host = 'localhost'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 @@ -7,19 +8,19 @@ localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y alter user CURRENT_USER; select * from mysql.user where user = 'root' and host = 'localhost'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 mysql_native_password N N 0.000000 alter user CURRENT_USER(); select * from mysql.user where user = 'root' and host = 'localhost'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 mysql_native_password N N 0.000000 create user foo; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 mysql_native_password N N 0.000000 alter user foo; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 mysql_native_password N N 0.000000 # Test super privilege works correctly with a read only database. SET @start_read_only = @@global.read_only; SET GLOBAL read_only=1; @@ -51,37 +52,43 @@ Note 1396 Operation ALTER USER failed for 'boo' alter user foo identified by 'something'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N 0 0 0 0 N N 0.000000 +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N 0 0 0 0 mysql_native_password *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N 0.000000 alter user foo identified by 'something2'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *9CD58369E930E28C8996A89DB18B63294E6DC10C N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N 0 0 0 0 N N 0.000000 +% foo *9CD58369E930E28C8996A89DB18B63294E6DC10C N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N 0 0 0 0 mysql_native_password *9CD58369E930E28C8996A89DB18B63294E6DC10C N N 0.000000 alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N 0 0 0 0 N N 0.000000 +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N 0 0 0 0 mysql_native_password *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N 0.000000 alter user foo identified with 'somecoolplugin'; +ERROR HY000: Operation ALTER USER failed for 'foo'@'%' +show warnings; +Level Code Message +Warning 1524 Plugin 'somecoolplugin' is not loaded +Error 1396 Operation ALTER USER failed for 'foo'@'%' +alter user foo identified with 'mysql_old_password'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N 0 0 0 0 somecoolplugin N N 0.000000 -alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; +% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N 0 0 0 0 mysql_old_password N N 0.000000 +alter user foo identified with 'mysql_old_password' using '0123456789ABCDEF'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N 0 0 0 0 somecoolplugin somecoolpassphrase N N 0.000000 +% foo 0123456789ABCDEF N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N 0 0 0 0 mysql_old_password 0123456789ABCDEF N N 0.000000 # Test ssl related altering. alter user foo identified by 'something' require SSL; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N ANY 0 0 0 0 N N 0.000000 +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N ANY 0 0 0 0 mysql_native_password *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N 0.000000 alter user foo identified by 'something' require X509; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N X509 0 0 0 0 N N 0.000000 +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N X509 0 0 0 0 mysql_native_password *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N 0.000000 alter user foo identified by 'something' require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N SPECIFIED text foo_issuer foo_subject 0 0 0 0 N N 0.000000 +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N SPECIFIED text foo_issuer foo_subject 0 0 0 0 mysql_native_password *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N 0.000000 # Test resource limits altering. alter user foo with MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 @@ -89,5 +96,6 @@ MAX_CONNECTIONS_PER_HOUR 30 MAX_USER_CONNECTIONS 40; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N SPECIFIED text foo_issuer foo_subject 10 20 30 40 N N 0.000000 +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N N SPECIFIED text foo_issuer foo_subject 10 20 30 40 mysql_native_password *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N 0.000000 drop user foo; +update mysql.global_priv set priv=@root_priv where user='root' and host='localhost'; diff --git a/mysql-test/main/alter_user.test b/mysql-test/main/alter_user.test index ca444f70a70..9ea98615272 100644 --- a/mysql-test/main/alter_user.test +++ b/mysql-test/main/alter_user.test @@ -1,5 +1,7 @@ --source include/not_embedded.inc +select priv into @root_priv from mysql.global_priv where user='root' and host='localhost'; + select * from mysql.user where user = 'root' and host = 'localhost'; --echo # Test syntax --echo # @@ -53,10 +55,14 @@ select * from mysql.user where user = 'foo'; alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63'; select * from mysql.user where user = 'foo'; +--error ER_CANNOT_USER alter user foo identified with 'somecoolplugin'; +show warnings; + +alter user foo identified with 'mysql_old_password'; select * from mysql.user where user = 'foo'; -alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; +alter user foo identified with 'mysql_old_password' using '0123456789ABCDEF'; select * from mysql.user where user = 'foo'; --echo # Test ssl related altering. @@ -77,3 +83,5 @@ alter user foo with MAX_QUERIES_PER_HOUR 10 MAX_USER_CONNECTIONS 40; select * from mysql.user where user = 'foo'; drop user foo; + +update mysql.global_priv set priv=@root_priv where user='root' and host='localhost'; diff --git a/mysql-test/main/analyze.result b/mysql-test/main/analyze.result index 9dff94ab08c..dd785abcd42 100644 --- a/mysql-test/main/analyze.result +++ b/mysql-test/main/analyze.result @@ -3,6 +3,7 @@ lock tables t1 write; insert into t1 values(0); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK unlock tables; check table t1; @@ -15,6 +16,7 @@ lock tables t1 write; delete from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK unlock tables; check table t1; @@ -25,6 +27,7 @@ create table t1 (a bigint); insert into t1 values(0); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK check table t1; Table Op Msg_type Msg_text @@ -34,9 +37,13 @@ create table t1 (a mediumtext, fulltext key key1(a)) charset utf8 collate utf8_g insert into t1 values ('hello'); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'a' test.t1 analyze status OK analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'a' test.t1 analyze status Table is already up to date drop table t1; CREATE TABLE t1 (a int); diff --git a/mysql-test/main/analyze_stmt.result b/mysql-test/main/analyze_stmt.result index c3c98593210..1747fd63de6 100644 --- a/mysql-test/main/analyze_stmt.result +++ b/mysql-test/main/analyze_stmt.result @@ -250,6 +250,8 @@ insert into t1 values (1); analyze select * from t1 into @var; id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 NULL 100.00 NULL +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead drop table t1; # # MDEV-6394: ANALYZE DELETE .. RETURNING fails with ERROR 2027 Malformed packet @@ -284,6 +286,8 @@ insert into t1 values (1),(2); analyze select a from t1 where a <2 into @var; id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 2.00 100.00 50.00 Using where +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead analyze select a from t1 into @var; ERROR 42000: Result consisted of more than one row analyze insert into t1 select * from t1; diff --git a/mysql-test/main/auth_rpl.result b/mysql-test/main/auth_rpl.result index a3da7985da1..56f5f5e8f2b 100644 --- a/mysql-test/main/auth_rpl.result +++ b/mysql-test/main/auth_rpl.result @@ -15,7 +15,7 @@ connection master; connection slave; # Slave in-sync with master now. SELECT user, plugin, authentication_string FROM mysql.user WHERE user LIKE 'plug_user'; -user plugin authentication_string +User plugin authentication_string plug_user test_plugin_server plug_user # Cleanup (on slave). include/stop_slave.inc diff --git a/mysql-test/main/backup_aria.result b/mysql-test/main/backup_aria.result new file mode 100644 index 00000000000..d537711404f --- /dev/null +++ b/mysql-test/main/backup_aria.result @@ -0,0 +1,158 @@ +connect con1,localhost,root,,; +SET SESSION lock_wait_timeout = 1; +#----------------------------------------------------------------------- +# Single-threaded tests +#----------------------------------------------------------------------- +# Show the fate and impact of some SELECT /HANDLER ... READ +# sliding through the sequence. +CREATE TABLE t_permanent_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +INSERT INTO t_permanent_aria SET col1 = 1; +BACKUP STAGE START; +SELECT COUNT(*) FROM t_permanent_aria; +COUNT(*) +1 +HANDLER t_permanent_aria OPEN; +HANDLER t_permanent_aria READ FIRST; +col1 +1 +HANDLER t_permanent_aria CLOSE; +BACKUP STAGE FLUSH; +SELECT COUNT(*) FROM t_permanent_aria; +COUNT(*) +1 +HANDLER t_permanent_aria OPEN; +HANDLER t_permanent_aria READ FIRST; +col1 +1 +HANDLER t_permanent_aria CLOSE; +BACKUP STAGE BLOCK_DDL; +SELECT COUNT(*) FROM t_permanent_aria; +COUNT(*) +1 +HANDLER t_permanent_aria OPEN; +HANDLER t_permanent_aria READ FIRST; +col1 +1 +HANDLER t_permanent_aria CLOSE; +BACKUP STAGE BLOCK_COMMIT; +SELECT COUNT(*) FROM t_permanent_aria; +COUNT(*) +1 +HANDLER t_permanent_aria OPEN; +HANDLER t_permanent_aria READ FIRST; +col1 +1 +HANDLER t_permanent_aria CLOSE; +BACKUP STAGE END; +# In case the backup lock is taken by the current connection than +# - DML modifying some permanent table is not allowed +BACKUP STAGE START; +SET AUTOCOMMIT = 0; +INSERT INTO t_permanent_aria SET col1 = 1; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +SET AUTOCOMMIT = 1; +INSERT INTO t_permanent_aria SET col1 = 1; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +# - DDL creating or renaming a permanent table or a procedure is not +# allowed. +# The latter tries to modify a permanent system table. +CREATE TABLE throw_away (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +RENAME TABLE t_permanent_aria To throw_away; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +# - DDL creating a temporary table is allowed. +CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +# - DML modifying that temporary table is allowed. +INSERT INTO t_temporary_aria SET col1 = 1; +SELECT COUNT(*) FROM t_temporary_aria; +COUNT(*) +1 +BACKUP STAGE END; +# Show the fate and impact of some auto committed INSERT into temporary +# table sliding through the sequence. +SET AUTOCOMMIT = 1; +BACKUP STAGE START; +INSERT INTO t_temporary_aria SET col1 = 1; +BACKUP STAGE FLUSH; +INSERT INTO t_temporary_aria SET col1 = 1; +BACKUP STAGE BLOCK_DDL; +INSERT INTO t_temporary_aria SET col1 = 1; +BACKUP STAGE BLOCK_COMMIT; +INSERT INTO t_temporary_aria SET col1 = 1; +BACKUP STAGE END; +SELECT COUNT(*) FROM t_temporary_aria; +COUNT(*) +5 +# Show the fate and impact of some DROP/CREATE TEMPORARY TABLE sliding +# through the sequence. +SET AUTOCOMMIT = 1; +BACKUP STAGE START; +DROP TEMPORARY TABLE t_temporary_aria; +CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +BACKUP STAGE FLUSH; +DROP TEMPORARY TABLE t_temporary_aria; +CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +BACKUP STAGE BLOCK_DDL; +DROP TEMPORARY TABLE t_temporary_aria; +CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +BACKUP STAGE BLOCK_COMMIT; +DROP TEMPORARY TABLE t_temporary_aria; +CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +BACKUP STAGE END; +# Show that even more DDL on the temporary table is allowed. +BACKUP STAGE START; +TRUNCATE t_temporary_aria; +ALTER TABLE t_temporary_aria ADD COLUMN col2 INT; +ALTER TABLE t_temporary_aria ADD KEY idx(col2); +BACKUP STAGE END; +DROP TABLE t_permanent_aria; +#----------------------------------------------------------------------- +# Show that non transactional tables locks with BACKUP STAGE FLUSH +#----------------------------------------------------------------------- +set session lock_wait_timeout=default; +create table t1 (a int) engine=aria transactional=0; +insert into t1 values (1), (2); +connection con1; +backup stage start; +backup stage flush; +connection default; +select * from t1; +a +1 +2 +SET STATEMENT lock_wait_timeout=0 FOR INSERT INTO t1 values (3); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +INSERT INTO t1 values (4); +connection con1; +backup stage end; +connection default; +select * from t1; +a +1 +2 +4 +drop table t1; +#----------------------------------------------------------------------- +# Show that transactional tables doesn't lock with BACKUP STAGE FLUSH +#----------------------------------------------------------------------- +set session lock_wait_timeout=default; +create table t1 (a int) engine=aria transactional=1 page_checksum=1; +insert into t1 values (1), (2); +connection con1; +backup stage start; +backup stage flush; +connection default; +INSERT INTO t1 values (4); +connection con1; +backup stage end; +connection default; +select * from t1; +a +1 +2 +4 +drop table t1; +# +# Cleanup +# +disconnect con1; diff --git a/mysql-test/main/backup_aria.test b/mysql-test/main/backup_aria.test new file mode 100644 index 00000000000..7b741b829a1 --- /dev/null +++ b/mysql-test/main/backup_aria.test @@ -0,0 +1,157 @@ +######################################################################## +# Tests for Implement LOCK FOR BACKUP (MDEV-5336) +######################################################################## +# Check a non transactional table per ENGINE = Aria TRANSACTIONAL = 0. +# + +--source include/not_embedded.inc +# As non transactional engine we use Aria with TRANSACTIONAL = 0 +--source include/have_aria.inc + +# Following connections are used in a few of the following tests +connect (con1,localhost,root,,); + +SET SESSION lock_wait_timeout = 1; + +--echo #----------------------------------------------------------------------- +--echo # Single-threaded tests +--echo #----------------------------------------------------------------------- + +--echo # Show the fate and impact of some SELECT /HANDLER ... READ +--echo # sliding through the sequence. +CREATE TABLE t_permanent_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +INSERT INTO t_permanent_aria SET col1 = 1; +BACKUP STAGE START; +SELECT COUNT(*) FROM t_permanent_aria; +HANDLER t_permanent_aria OPEN; +HANDLER t_permanent_aria READ FIRST; +HANDLER t_permanent_aria CLOSE; +BACKUP STAGE FLUSH; +SELECT COUNT(*) FROM t_permanent_aria; +HANDLER t_permanent_aria OPEN; +HANDLER t_permanent_aria READ FIRST; +HANDLER t_permanent_aria CLOSE; +BACKUP STAGE BLOCK_DDL; +SELECT COUNT(*) FROM t_permanent_aria; +HANDLER t_permanent_aria OPEN; +HANDLER t_permanent_aria READ FIRST; +HANDLER t_permanent_aria CLOSE; +BACKUP STAGE BLOCK_COMMIT; +SELECT COUNT(*) FROM t_permanent_aria; +HANDLER t_permanent_aria OPEN; +HANDLER t_permanent_aria READ FIRST; +HANDLER t_permanent_aria CLOSE; +BACKUP STAGE END; + +--echo # In case the backup lock is taken by the current connection than +--echo # - DML modifying some permanent table is not allowed +BACKUP STAGE START; +SET AUTOCOMMIT = 0; +--error ER_BACKUP_LOCK_IS_ACTIVE +INSERT INTO t_permanent_aria SET col1 = 1; +SET AUTOCOMMIT = 1; +--error ER_BACKUP_LOCK_IS_ACTIVE +INSERT INTO t_permanent_aria SET col1 = 1; + +--echo # - DDL creating or renaming a permanent table or a procedure is not +--echo # allowed. +--echo # The latter tries to modify a permanent system table. + +--error ER_BACKUP_LOCK_IS_ACTIVE +CREATE TABLE throw_away (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +--error ER_BACKUP_LOCK_IS_ACTIVE +RENAME TABLE t_permanent_aria To throw_away; +--echo # - DDL creating a temporary table is allowed. +CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +--echo # - DML modifying that temporary table is allowed. +INSERT INTO t_temporary_aria SET col1 = 1; +SELECT COUNT(*) FROM t_temporary_aria; +BACKUP STAGE END; + +--echo # Show the fate and impact of some auto committed INSERT into temporary +--echo # table sliding through the sequence. +SET AUTOCOMMIT = 1; +BACKUP STAGE START; +INSERT INTO t_temporary_aria SET col1 = 1; +BACKUP STAGE FLUSH; +INSERT INTO t_temporary_aria SET col1 = 1; +BACKUP STAGE BLOCK_DDL; +INSERT INTO t_temporary_aria SET col1 = 1; +BACKUP STAGE BLOCK_COMMIT; +INSERT INTO t_temporary_aria SET col1 = 1; +BACKUP STAGE END; +SELECT COUNT(*) FROM t_temporary_aria; + +--echo # Show the fate and impact of some DROP/CREATE TEMPORARY TABLE sliding +--echo # through the sequence. + +SET AUTOCOMMIT = 1; +BACKUP STAGE START; +DROP TEMPORARY TABLE t_temporary_aria; +CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +BACKUP STAGE FLUSH; +DROP TEMPORARY TABLE t_temporary_aria; +CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +BACKUP STAGE BLOCK_DDL; +DROP TEMPORARY TABLE t_temporary_aria; +CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +BACKUP STAGE BLOCK_COMMIT; +DROP TEMPORARY TABLE t_temporary_aria; +CREATE TEMPORARY TABLE t_temporary_aria (col1 INT) ENGINE = Aria TRANSACTIONAL = 0; +BACKUP STAGE END; +--echo # Show that even more DDL on the temporary table is allowed. +BACKUP STAGE START; +TRUNCATE t_temporary_aria; +ALTER TABLE t_temporary_aria ADD COLUMN col2 INT; +ALTER TABLE t_temporary_aria ADD KEY idx(col2); +BACKUP STAGE END; + +DROP TABLE t_permanent_aria; + +--echo #----------------------------------------------------------------------- +--echo # Show that non transactional tables locks with BACKUP STAGE FLUSH +--echo #----------------------------------------------------------------------- + +set session lock_wait_timeout=default; +create table t1 (a int) engine=aria transactional=0; +insert into t1 values (1), (2); + +connection con1; +backup stage start; +backup stage flush; +connection default; +select * from t1; +--error ER_LOCK_WAIT_TIMEOUT +SET STATEMENT lock_wait_timeout=0 FOR INSERT INTO t1 values (3); +--send INSERT INTO t1 values (4) +connection con1; +backup stage end; +connection default; +--reap # send +select * from t1; +drop table t1; + +--echo #----------------------------------------------------------------------- +--echo # Show that transactional tables doesn't lock with BACKUP STAGE FLUSH +--echo #----------------------------------------------------------------------- + +set session lock_wait_timeout=default; +create table t1 (a int) engine=aria transactional=1 page_checksum=1; +insert into t1 values (1), (2); + +connection con1; +backup stage start; +backup stage flush; +connection default; +INSERT INTO t1 values (4); +connection con1; +backup stage end; +connection default; +select * from t1; +drop table t1; + +--echo # +--echo # Cleanup +--echo # + +disconnect con1; diff --git a/mysql-test/main/backup_interaction.result b/mysql-test/main/backup_interaction.result new file mode 100644 index 00000000000..20ba8fa0811 --- /dev/null +++ b/mysql-test/main/backup_interaction.result @@ -0,0 +1,520 @@ +# +# Check backup and FTWRL +# +flush tables with read lock; +backup stage start; +ERROR HY000: Can't execute the query because you have a conflicting read lock +unlock tables; +backup stage start; +flush tables with read lock; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +backup stage end; +# +# Check backup and FLUSH TABLES +# +flush tables; +backup stage start; +flush tables; +backup stage end; +# +# Check BACKUP STAGE under lock tables +# +create table t1 (a int); +lock table t1 write; +backup stage start; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +backup stage end; +ERROR HY000: You must start backup with "BACKUP STAGE START" +unlock tables; +lock table t1 read; +backup stage start; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +backup stage end; +ERROR HY000: You must start backup with "BACKUP STAGE START" +unlock tables; +# +# Check lock tables under BACKUP STAGE +# +backup stage start; +unlock tables; +select lock_mode from information_schema.metadata_lock_info; +lock_mode +MDL_BACKUP_START +lock table t1 write; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +lock table t1 read; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +unlock tables; +backup stage end; +drop table t1; +# +# Check setting readonly under BACKUP STAGE +# +backup stage start; +set @@global.read_only=1; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +backup stage end; +# also make sure going back from read-only mode is not allowed +set @@global.read_only=1; +backup stage start; +set @@global.read_only=0; +ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction +backup stage end; +set @@global.read_only=0; +# +# Check BACKUP STAGE under read_only +# +set @@global.read_only=1; +backup stage start; +backup stage end; +set @@global.read_only=0; +# +# Check that we can't create tables during backup +# +backup stage start; +create table t1 (a int); +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +backup stage end; +# also make sure we can't write to a table during backup +create table t1(a INT); +backup stage start; +insert into t1 values(1); +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +insert delayed into t1 values(1); +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +update t1 set a=1; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +delete from t1; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +truncate table t1; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +drop table t1; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +backup stage end; +drop table t1; +# +# BACKUP STAGE performs implicit commits +# +create table t1(a int) engine=InnoDB; +begin; +insert into t1 values(1); +select lock_mode from information_schema.metadata_lock_info; +lock_mode +MDL_SHARED_WRITE +backup stage start; +select lock_mode from information_schema.metadata_lock_info; +lock_mode +MDL_BACKUP_START +backup stage block_commit; +commit; +backup stage end; +drop table t1; +# Ensure that BACKUP STAGE ... does AUTOCOMMIT like most DDL. +# Sideeffect: +# Show the impact of not yet committed INSERT before sequence start +# and ROLLBACK sliding through the sequence. +CREATE TABLE t1 (col1 INT) ENGINE = InnoDB; +SET AUTOCOMMIT = 0; +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +ROLLBACK; +BACKUP STAGE END; +#---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +ROLLBACK; +BACKUP STAGE END; +#---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +ROLLBACK; +BACKUP STAGE END; +#---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +ROLLBACK; +BACKUP STAGE END; +#---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +ROLLBACK; +SELECT COUNT(*) = 5 AS expect_1 FROM t1; +expect_1 +1 +# Show the impact of not yet committed INSERT before sequence start +# and a COMMIT sliding through the sequence. +SET AUTOCOMMIT = 0; +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +COMMIT; +BACKUP STAGE END; +#---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +COMMIT; +BACKUP STAGE END; +#---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +COMMIT; +BACKUP STAGE END; +#---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +COMMIT; +BACKUP STAGE END; +#---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +COMMIT; +SELECT COUNT(*) = 10 AS expect_1 FROM t1; +expect_1 +1 +DELETE FROM t1; +COMMIT; +drop table t1; +# +# CHECK: RO transaction under BACKUP STAGE is a potential deadlock +# OTOH we most probably allow them under FTWRL as well +# +CREATE TABLE t1 (col1 INT) ENGINE = InnoDB; +insert into t1 values (1); +backup stage start; +backup stage block_commit; +begin; +select * from t1; +col1 +1 +select lock_mode from information_schema.metadata_lock_info; +lock_mode +MDL_BACKUP_WAIT_COMMIT +MDL_SHARED_READ +backup stage end; +select lock_mode from information_schema.metadata_lock_info; +lock_mode +drop table t1; +# +# Check that handler are closed by backup stage block_ddl +# +create table t1 (a int, key a (a)); +insert into t1 (a) values (1), (2), (3), (4), (5); +handler t1 open; +handler t1 read a prev; +a +5 +backup stage start; +handler t1 read a prev; +a +4 +backup stage flush; +backup stage block_ddl; +handler t1 read a prev; +a +5 +backup stage block_commit; +handler t1 read a prev; +a +4 +backup stage end; +handler t1 close; +drop table t1; +# Show the fate and impact of some SELECT /HANDLER ... READ +# sliding through the sequence. +CREATE TABLE t1_innodb (col1 INT) ENGINE = InnoDB; +INSERT INTO t1_innodb values (1),(2),(3); +COMMIT; +CREATE TABLE t1_myisam (col1 INT) ENGINE = MyISAM; +INSERT INTO t1_myisam values (1),(2),(3); +BACKUP STAGE START; +SELECT COUNT(*) FROM t1_innodb; +COUNT(*) +3 +SELECT * FROM t1_innodb; +col1 +1 +2 +3 +HANDLER t1_innodb OPEN; +HANDLER t1_innodb READ FIRST; +col1 +1 +HANDLER t1_innodb CLOSE; +SELECT COUNT(*) FROM t1_myisam; +COUNT(*) +3 +HANDLER t1_myisam OPEN; +HANDLER t1_myisam READ FIRST; +col1 +1 +HANDLER t1_myisam CLOSE; +BACKUP STAGE FLUSH; +SELECT COUNT(*) FROM t1_innodb; +COUNT(*) +3 +HANDLER t1_innodb OPEN; +HANDLER t1_innodb READ FIRST; +col1 +1 +HANDLER t1_innodb CLOSE; +SELECT COUNT(*) FROM t1_myisam; +COUNT(*) +3 +HANDLER t1_myisam OPEN; +HANDLER t1_myisam READ FIRST; +col1 +1 +HANDLER t1_myisam CLOSE; +BACKUP STAGE BLOCK_DDL; +SELECT COUNT(*) FROM t1_innodb; +COUNT(*) +3 +HANDLER t1_innodb OPEN; +HANDLER t1_innodb READ FIRST; +col1 +1 +HANDLER t1_innodb CLOSE; +SELECT COUNT(*) FROM t1_myisam; +COUNT(*) +3 +HANDLER t1_myisam OPEN; +HANDLER t1_myisam READ FIRST; +col1 +1 +HANDLER t1_myisam CLOSE; +BACKUP STAGE BLOCK_COMMIT; +SELECT COUNT(*) FROM t1_innodb; +COUNT(*) +3 +HANDLER t1_innodb OPEN; +HANDLER t1_innodb READ FIRST; +col1 +1 +HANDLER t1_innodb CLOSE; +SELECT COUNT(*) FROM t1_myisam; +COUNT(*) +3 +HANDLER t1_myisam OPEN; +HANDLER t1_myisam READ FIRST; +col1 +1 +HANDLER t1_myisam CLOSE; +BACKUP STAGE END; +drop table t1_innodb,t1_myisam; +# Show the fate and impact of some SET GLOBAL tx_read_only = 1/0 +# sliding through the sequence. +BACKUP STAGE START; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +BACKUP STAGE FLUSH; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +BACKUP STAGE BLOCK_DDL; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +BACKUP STAGE BLOCK_COMMIT; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +BACKUP STAGE END; +# Show the fate and impact of some SET SESSION sql_log_bin = 0/1 +# sliding through the sequence. +COMMIT; +SET SESSION sql_log_bin = 1; +BACKUP STAGE START; +SET SESSION sql_log_bin = 0; +SET SESSION sql_log_bin = 1; +BACKUP STAGE FLUSH; +SET SESSION sql_log_bin = 0; +SET SESSION sql_log_bin = 1; +BACKUP STAGE BLOCK_DDL; +SET SESSION sql_log_bin = 0; +SET SESSION sql_log_bin = 1; +BACKUP STAGE BLOCK_COMMIT; +SET SESSION sql_log_bin = 0; +SET SESSION sql_log_bin = 1; +BACKUP STAGE END; +#---- +SET SESSION sql_log_bin = 0; +BACKUP STAGE START; +SET SESSION sql_log_bin = 1; +SET SESSION sql_log_bin = 0; +BACKUP STAGE FLUSH; +SET SESSION sql_log_bin = 1; +SET SESSION sql_log_bin = 0; +BACKUP STAGE BLOCK_DDL; +SET SESSION sql_log_bin = 1; +SET SESSION sql_log_bin = 0; +BACKUP STAGE BLOCK_COMMIT; +SET SESSION sql_log_bin = 1; +SET SESSION sql_log_bin = 0; +BACKUP STAGE END; +SET SESSION sql_log_bin = 1; +#----------------------------------------------------------------------- +# BACKUP STAGE statements are not allowed in stored routines +#----------------------------------------------------------------------- +CREATE TABLE t1 (col1 INT); +CREATE PROCEDURE p1() +BEGIN +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +END| +ERROR 0A000: BACKUP STAGE is not allowed in stored procedures +CREATE FUNCTION f1 (s CHAR(20)) RETURNS INT DETERMINISTIC +BEGIN +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +RETURN 1; +END| +ERROR 0A000: BACKUP STAGE is not allowed in stored procedures +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW +BEGIN +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +END| +ERROR 0A000: BACKUP STAGE is not allowed in stored procedures +DROP TABLE t1; +#----------------------------------------------------------------------- +# Check BACKUP status variables +#----------------------------------------------------------------------- +SET SESSION lock_wait_timeout = 1; +FLUSH STATUS; +# Show how the status variable 'Com_backup' changes after BACKUP STAGE .. +SHOW STATUS LIKE 'Com_backup'; +Variable_name Value +Com_backup 0 +BACKUP STAGE START; +SHOW STATUS LIKE 'Com_backup'; +Variable_name Value +Com_backup 1 +BACKUP STAGE START; +ERROR HY000: Backup stage 'START' is same or before current backup stage 'START' +SHOW STATUS LIKE 'Com_backup'; +Variable_name Value +Com_backup 2 +BACKUP STAGE FLUSH; +SHOW STATUS LIKE 'Com_backup'; +Variable_name Value +Com_backup 3 +BACKUP STAGE BLOCK_DDL; +SHOW STATUS LIKE 'Com_backup'; +Variable_name Value +Com_backup 4 +BACKUP STAGE BLOCK_COMMIT; +SHOW STATUS LIKE 'Com_backup'; +Variable_name Value +Com_backup 5 +BACKUP STAGE END; +# In case the backup lock is taken by the current connection than +# - DML modifying some permanent table is not allowed +CREATE TABLE t1_innodb (col1 INT) ENGINE = InnoDB; +CREATE TABLE t1_myisam (col1 INT) ENGINE = MyISAM; +BACKUP STAGE START; +SET AUTOCOMMIT = 0; +INSERT INTO t1_innodb SET col1 = 1; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +SET AUTOCOMMIT = 1; +INSERT INTO t1_innodb SET col1 = 1; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +INSERT INTO t1_myisam SET col1 = 1; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +# - DDL creating or renaming a permanent table or a procedure etc. +# is not allowed. +CREATE TABLE throw_away (col1 INT) ENGINE = InnoDB; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +RENAME TABLE t1_innodb To throw_away; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +CREATE PROCEDURE p1() SELECT 13; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +CREATE PROCEDURE p1() SELECT 13; +ERROR HY000: Can't execute the command as you have a BACKUP STAGE active +BACKUP STAGE END; +DROP TABLE t1_innodb; +DROP TABLE t1_myisam; +# +# Creating and modifying TEMPORARY TABLES are allowed +# +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +CREATE TEMPORARY TABLE tmp (col1 INT); +DROP TEMPORARY TABLE tmp; +CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; +CREATE TEMPORARY TABLE t_temporary_myisam (col1 INT) ENGINE = MyISAM; +# - DML modifying that temporary table is allowed. +INSERT INTO t_temporary_innodb SET col1 = 1; +SELECT COUNT(*) FROM t_temporary_innodb; +COUNT(*) +1 +INSERT INTO t_temporary_myisam SET col1 = 1; +SELECT COUNT(*) FROM t_temporary_myisam; +COUNT(*) +1 +BACKUP STAGE END; +# Show the fate and impact of some auto committed INSERT into temporary +# table sliding through the sequence. +SET AUTOCOMMIT = 1; +BACKUP STAGE START; +INSERT INTO t_temporary_innodb SET col1 = 1; +INSERT INTO t_temporary_myisam SET col1 = 1; +BACKUP STAGE FLUSH; +INSERT INTO t_temporary_innodb SET col1 = 1; +INSERT INTO t_temporary_myisam SET col1 = 1; +BACKUP STAGE BLOCK_DDL; +INSERT INTO t_temporary_innodb SET col1 = 1; +INSERT INTO t_temporary_myisam SET col1 = 1; +BACKUP STAGE BLOCK_COMMIT; +INSERT INTO t_temporary_innodb SET col1 = 1; +INSERT INTO t_temporary_myisam SET col1 = 1; +BACKUP STAGE END; +SELECT COUNT(*) FROM t_temporary_innodb; +COUNT(*) +5 +# Show the fate and impact of some DROP/CREATE TEMPORARY TABLE sliding +# through the sequence. +SET AUTOCOMMIT = 1; +BACKUP STAGE START; +DROP TEMPORARY TABLE t_temporary_innodb; +CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; +BACKUP STAGE FLUSH; +DROP TEMPORARY TABLE t_temporary_innodb; +CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; +BACKUP STAGE BLOCK_DDL; +DROP TEMPORARY TABLE t_temporary_innodb; +CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; +BACKUP STAGE BLOCK_COMMIT; +DROP TEMPORARY TABLE t_temporary_innodb; +CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; +BACKUP STAGE END; +# Show that even more DDL on the temporary table is allowed. +BACKUP STAGE START; +TRUNCATE t_temporary_innodb; +ALTER TABLE t_temporary_innodb ADD COLUMN col2 INT; +ALTER TABLE t_temporary_innodb ADD KEY idx(col2); +BACKUP STAGE END; diff --git a/mysql-test/main/backup_interaction.test b/mysql-test/main/backup_interaction.test new file mode 100644 index 00000000000..f5362417c98 --- /dev/null +++ b/mysql-test/main/backup_interaction.test @@ -0,0 +1,503 @@ +######################################################################## +# Tests how BACKUP STAGE interacts with other commands (MDEV-5336) +######################################################################## + +--source include/have_innodb.inc +--source include/have_metadata_lock_info.inc + +--echo # +--echo # Check backup and FTWRL +--echo # + +flush tables with read lock; +--error ER_CANT_UPDATE_WITH_READLOCK +backup stage start; +unlock tables; +backup stage start; +--error ER_BACKUP_LOCK_IS_ACTIVE +flush tables with read lock; +backup stage end; + +--echo # +--echo # Check backup and FLUSH TABLES +--echo # + +flush tables; +backup stage start; +flush tables; +backup stage end; + +--echo # +--echo # Check BACKUP STAGE under lock tables +--echo # + +create table t1 (a int); +lock table t1 write; +--error ER_LOCK_OR_ACTIVE_TRANSACTION +backup stage start; +--error ER_BACKUP_NOT_RUNNING +backup stage end; +unlock tables; + +lock table t1 read; +--error ER_LOCK_OR_ACTIVE_TRANSACTION +backup stage start; +--error ER_BACKUP_NOT_RUNNING +backup stage end; +unlock tables; + + +--echo # +--echo # Check lock tables under BACKUP STAGE +--echo # +backup stage start; +unlock tables; +select lock_mode from information_schema.metadata_lock_info; + +--error ER_BACKUP_LOCK_IS_ACTIVE +lock table t1 write; +--error ER_BACKUP_LOCK_IS_ACTIVE +lock table t1 read; +unlock tables; +backup stage end; +drop table t1; + + +--echo # +--echo # Check setting readonly under BACKUP STAGE +--echo # +backup stage start; +--error ER_LOCK_OR_ACTIVE_TRANSACTION +set @@global.read_only=1; +backup stage end; + +--echo # also make sure going back from read-only mode is not allowed +set @@global.read_only=1; +backup stage start; +--error ER_LOCK_OR_ACTIVE_TRANSACTION +set @@global.read_only=0; +backup stage end; +set @@global.read_only=0; + +--echo # +--echo # Check BACKUP STAGE under read_only +--echo # + +set @@global.read_only=1; +backup stage start; +backup stage end; +set @@global.read_only=0; + +--echo # +--echo # Check that we can't create tables during backup +--echo # + +backup stage start; +--error ER_BACKUP_LOCK_IS_ACTIVE +create table t1 (a int); +backup stage end; + +--echo # also make sure we can't write to a table during backup +create table t1(a INT); +backup stage start; +--error ER_BACKUP_LOCK_IS_ACTIVE +insert into t1 values(1); +--error ER_BACKUP_LOCK_IS_ACTIVE +insert delayed into t1 values(1); +--error ER_BACKUP_LOCK_IS_ACTIVE +update t1 set a=1; +--error ER_BACKUP_LOCK_IS_ACTIVE +delete from t1; +--error ER_BACKUP_LOCK_IS_ACTIVE +truncate table t1; +--error ER_BACKUP_LOCK_IS_ACTIVE +drop table t1; +backup stage end; +drop table t1; + +--echo # +--echo # BACKUP STAGE performs implicit commits +--echo # +create table t1(a int) engine=InnoDB; +begin; +insert into t1 values(1); +select lock_mode from information_schema.metadata_lock_info; +backup stage start; +select lock_mode from information_schema.metadata_lock_info; +backup stage block_commit; +commit; +backup stage end; +drop table t1; + +--echo # Ensure that BACKUP STAGE ... does AUTOCOMMIT like most DDL. +--echo # Sideeffect: +--echo # Show the impact of not yet committed INSERT before sequence start +--echo # and ROLLBACK sliding through the sequence. + +CREATE TABLE t1 (col1 INT) ENGINE = InnoDB; +SET AUTOCOMMIT = 0; +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +ROLLBACK; +BACKUP STAGE END; +--echo #---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +ROLLBACK; +BACKUP STAGE END; +--echo #---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +ROLLBACK; +BACKUP STAGE END; +--echo #---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +ROLLBACK; +BACKUP STAGE END; +--echo #---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +ROLLBACK; +SELECT COUNT(*) = 5 AS expect_1 FROM t1; + +--echo # Show the impact of not yet committed INSERT before sequence start +--echo # and a COMMIT sliding through the sequence. + +SET AUTOCOMMIT = 0; +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +COMMIT; +BACKUP STAGE END; +--echo #---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +COMMIT; +BACKUP STAGE END; +--echo #---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +COMMIT; +BACKUP STAGE END; +--echo #---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +COMMIT; +BACKUP STAGE END; +--echo #---- +INSERT INTO t1 SET col1 = 1; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +COMMIT; +SELECT COUNT(*) = 10 AS expect_1 FROM t1; +DELETE FROM t1; +COMMIT; +drop table t1; + +--echo # +--echo # CHECK: RO transaction under BACKUP STAGE is a potential deadlock +--echo # OTOH we most probably allow them under FTWRL as well +--echo # + +CREATE TABLE t1 (col1 INT) ENGINE = InnoDB; +insert into t1 values (1); +backup stage start; +backup stage block_commit; +begin; +select * from t1; +select lock_mode from information_schema.metadata_lock_info; +backup stage end; +select lock_mode from information_schema.metadata_lock_info; +drop table t1; + +--echo # +--echo # Check that handler are closed by backup stage block_ddl +--echo # + +create table t1 (a int, key a (a)); +insert into t1 (a) values (1), (2), (3), (4), (5); +handler t1 open; +handler t1 read a prev; +backup stage start; +handler t1 read a prev; +backup stage flush; +backup stage block_ddl; +handler t1 read a prev; +backup stage block_commit; +handler t1 read a prev; +backup stage end; +handler t1 close; +drop table t1; + +--echo # Show the fate and impact of some SELECT /HANDLER ... READ +--echo # sliding through the sequence. + +CREATE TABLE t1_innodb (col1 INT) ENGINE = InnoDB; +INSERT INTO t1_innodb values (1),(2),(3); +COMMIT; +CREATE TABLE t1_myisam (col1 INT) ENGINE = MyISAM; +INSERT INTO t1_myisam values (1),(2),(3); +BACKUP STAGE START; +SELECT COUNT(*) FROM t1_innodb; +SELECT * FROM t1_innodb; +HANDLER t1_innodb OPEN; +HANDLER t1_innodb READ FIRST; +HANDLER t1_innodb CLOSE; +SELECT COUNT(*) FROM t1_myisam; +HANDLER t1_myisam OPEN; +HANDLER t1_myisam READ FIRST; +HANDLER t1_myisam CLOSE; +BACKUP STAGE FLUSH; +SELECT COUNT(*) FROM t1_innodb; +HANDLER t1_innodb OPEN; +HANDLER t1_innodb READ FIRST; +HANDLER t1_innodb CLOSE; +SELECT COUNT(*) FROM t1_myisam; +HANDLER t1_myisam OPEN; +HANDLER t1_myisam READ FIRST; +HANDLER t1_myisam CLOSE; +BACKUP STAGE BLOCK_DDL; +SELECT COUNT(*) FROM t1_innodb; +HANDLER t1_innodb OPEN; +HANDLER t1_innodb READ FIRST; +HANDLER t1_innodb CLOSE; +SELECT COUNT(*) FROM t1_myisam; +HANDLER t1_myisam OPEN; +HANDLER t1_myisam READ FIRST; +HANDLER t1_myisam CLOSE; +BACKUP STAGE BLOCK_COMMIT; +SELECT COUNT(*) FROM t1_innodb; +HANDLER t1_innodb OPEN; +HANDLER t1_innodb READ FIRST; +HANDLER t1_innodb CLOSE; +SELECT COUNT(*) FROM t1_myisam; +HANDLER t1_myisam OPEN; +HANDLER t1_myisam READ FIRST; +HANDLER t1_myisam CLOSE; +BACKUP STAGE END; +drop table t1_innodb,t1_myisam; + +--echo # Show the fate and impact of some SET GLOBAL tx_read_only = 1/0 +--echo # sliding through the sequence. + +BACKUP STAGE START; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +BACKUP STAGE FLUSH; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +BACKUP STAGE BLOCK_DDL; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +BACKUP STAGE BLOCK_COMMIT; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +BACKUP STAGE END; + +--echo # Show the fate and impact of some SET SESSION sql_log_bin = 0/1 +--echo # sliding through the sequence. +COMMIT; +SET SESSION sql_log_bin = 1; +BACKUP STAGE START; +SET SESSION sql_log_bin = 0; +SET SESSION sql_log_bin = 1; +BACKUP STAGE FLUSH; +SET SESSION sql_log_bin = 0; +SET SESSION sql_log_bin = 1; +BACKUP STAGE BLOCK_DDL; +SET SESSION sql_log_bin = 0; +SET SESSION sql_log_bin = 1; +BACKUP STAGE BLOCK_COMMIT; +SET SESSION sql_log_bin = 0; +SET SESSION sql_log_bin = 1; +BACKUP STAGE END; + +--echo #---- +SET SESSION sql_log_bin = 0; +BACKUP STAGE START; +SET SESSION sql_log_bin = 1; +SET SESSION sql_log_bin = 0; +BACKUP STAGE FLUSH; +SET SESSION sql_log_bin = 1; +SET SESSION sql_log_bin = 0; +BACKUP STAGE BLOCK_DDL; +SET SESSION sql_log_bin = 1; +SET SESSION sql_log_bin = 0; +BACKUP STAGE BLOCK_COMMIT; +SET SESSION sql_log_bin = 1; +SET SESSION sql_log_bin = 0; +BACKUP STAGE END; +SET SESSION sql_log_bin = 1; + +--echo #----------------------------------------------------------------------- +--echo # BACKUP STAGE statements are not allowed in stored routines +--echo #----------------------------------------------------------------------- + +CREATE TABLE t1 (col1 INT); + +delimiter |; +--error ER_SP_BADSTATEMENT +CREATE PROCEDURE p1() +BEGIN + BACKUP STAGE START; + BACKUP STAGE FLUSH; + BACKUP STAGE BLOCK_DDL; + BACKUP STAGE BLOCK_COMMIT; + BACKUP STAGE END; +END| + +--error ER_SP_BADSTATEMENT +CREATE FUNCTION f1 (s CHAR(20)) RETURNS INT DETERMINISTIC +BEGIN + BACKUP STAGE START; + BACKUP STAGE FLUSH; + BACKUP STAGE BLOCK_DDL; + BACKUP STAGE BLOCK_COMMIT; + BACKUP STAGE END; + RETURN 1; +END| + +--error ER_SP_BADSTATEMENT +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW +BEGIN + BACKUP STAGE START; + BACKUP STAGE FLUSH; + BACKUP STAGE BLOCK_DDL; + BACKUP STAGE BLOCK_COMMIT; + BACKUP STAGE END; +END| + +delimiter ;| +DROP TABLE t1; + +--echo #----------------------------------------------------------------------- +--echo # Check BACKUP status variables +--echo #----------------------------------------------------------------------- + +SET SESSION lock_wait_timeout = 1; + +FLUSH STATUS; + +# MDEV-5336 introduces the status variable Com_backup +--echo # Show how the status variable 'Com_backup' changes after BACKUP STAGE .. + +SHOW STATUS LIKE 'Com_backup'; +BACKUP STAGE START; +SHOW STATUS LIKE 'Com_backup'; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE START; +SHOW STATUS LIKE 'Com_backup'; +BACKUP STAGE FLUSH; +SHOW STATUS LIKE 'Com_backup'; +BACKUP STAGE BLOCK_DDL; +SHOW STATUS LIKE 'Com_backup'; +BACKUP STAGE BLOCK_COMMIT; +SHOW STATUS LIKE 'Com_backup'; +BACKUP STAGE END; + +--echo # In case the backup lock is taken by the current connection than +--echo # - DML modifying some permanent table is not allowed + +CREATE TABLE t1_innodb (col1 INT) ENGINE = InnoDB; +CREATE TABLE t1_myisam (col1 INT) ENGINE = MyISAM; + +BACKUP STAGE START; +SET AUTOCOMMIT = 0; +--error ER_BACKUP_LOCK_IS_ACTIVE +INSERT INTO t1_innodb SET col1 = 1; +SET AUTOCOMMIT = 1; +--error ER_BACKUP_LOCK_IS_ACTIVE +INSERT INTO t1_innodb SET col1 = 1; +--error ER_BACKUP_LOCK_IS_ACTIVE +INSERT INTO t1_myisam SET col1 = 1; +--echo # - DDL creating or renaming a permanent table or a procedure etc. +--echo # is not allowed. +--error ER_BACKUP_LOCK_IS_ACTIVE +CREATE TABLE throw_away (col1 INT) ENGINE = InnoDB; +--error ER_BACKUP_LOCK_IS_ACTIVE +RENAME TABLE t1_innodb To throw_away; +--error ER_BACKUP_LOCK_IS_ACTIVE +CREATE PROCEDURE p1() SELECT 13; +--error ER_BACKUP_LOCK_IS_ACTIVE +CREATE PROCEDURE p1() SELECT 13; +BACKUP STAGE END; +DROP TABLE t1_innodb; +DROP TABLE t1_myisam; + +--echo # +--echo # Creating and modifying TEMPORARY TABLES are allowed +--echo # + +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +CREATE TEMPORARY TABLE tmp (col1 INT); +DROP TEMPORARY TABLE tmp; + +CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; +CREATE TEMPORARY TABLE t_temporary_myisam (col1 INT) ENGINE = MyISAM; +--echo # - DML modifying that temporary table is allowed. +INSERT INTO t_temporary_innodb SET col1 = 1; +SELECT COUNT(*) FROM t_temporary_innodb; +INSERT INTO t_temporary_myisam SET col1 = 1; +SELECT COUNT(*) FROM t_temporary_myisam; +BACKUP STAGE END; + +--echo # Show the fate and impact of some auto committed INSERT into temporary +--echo # table sliding through the sequence. +SET AUTOCOMMIT = 1; +BACKUP STAGE START; +INSERT INTO t_temporary_innodb SET col1 = 1; +INSERT INTO t_temporary_myisam SET col1 = 1; +BACKUP STAGE FLUSH; +INSERT INTO t_temporary_innodb SET col1 = 1; +INSERT INTO t_temporary_myisam SET col1 = 1; +BACKUP STAGE BLOCK_DDL; +INSERT INTO t_temporary_innodb SET col1 = 1; +INSERT INTO t_temporary_myisam SET col1 = 1; +BACKUP STAGE BLOCK_COMMIT; +INSERT INTO t_temporary_innodb SET col1 = 1; +INSERT INTO t_temporary_myisam SET col1 = 1; +BACKUP STAGE END; +SELECT COUNT(*) FROM t_temporary_innodb; + +--echo # Show the fate and impact of some DROP/CREATE TEMPORARY TABLE sliding +--echo # through the sequence. +SET AUTOCOMMIT = 1; +BACKUP STAGE START; +DROP TEMPORARY TABLE t_temporary_innodb; +CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; +BACKUP STAGE FLUSH; +DROP TEMPORARY TABLE t_temporary_innodb; +CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; +BACKUP STAGE BLOCK_DDL; +DROP TEMPORARY TABLE t_temporary_innodb; +CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; +BACKUP STAGE BLOCK_COMMIT; +DROP TEMPORARY TABLE t_temporary_innodb; +CREATE TEMPORARY TABLE t_temporary_innodb (col1 INT) ENGINE = InnoDB; +BACKUP STAGE END; +--echo # Show that even more DDL on the temporary table is allowed. +BACKUP STAGE START; +TRUNCATE t_temporary_innodb; +ALTER TABLE t_temporary_innodb ADD COLUMN col2 INT; +ALTER TABLE t_temporary_innodb ADD KEY idx(col2); +BACKUP STAGE END; diff --git a/mysql-test/main/backup_lock.result b/mysql-test/main/backup_lock.result new file mode 100644 index 00000000000..95b2f520d90 --- /dev/null +++ b/mysql-test/main/backup_lock.result @@ -0,0 +1,219 @@ +# +# Testing which locks we get from all stages +# +BACKUP STAGE START; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_START Backup lock +BACKUP STAGE FLUSH; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_FLUSH Backup lock +BACKUP STAGE BLOCK_DDL; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_WAIT_DDL Backup lock +BACKUP STAGE BLOCK_COMMIT; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_WAIT_COMMIT Backup lock +BACKUP STAGE END; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +# +# testing BACKUP STAGE LOCK's +# +connect con1,localhost,root,,; +connect con2,localhost,root,,; +connection default; +# +# testing if BACKUP STAGE FLUSH causes deadlocks with ALTER TABLE +# +create table t1 (a int) engine=innodb; +start transaction; +insert into t1 values (1); +connection con1; +alter table t1 add column (j int), algorithm copy; +connection con2; +backup stage start; +backup stage flush; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_DDL Backup lock +MDL_BACKUP_FLUSH Backup lock +MDL_SHARED_WRITE Table metadata lock test t1 +MDL_SHARED_UPGRADABLE Table metadata lock test t1 +MDL_INTENTION_EXCLUSIVE Schema metadata lock test +SET STATEMENT max_statement_time=1 FOR backup stage block_ddl; +ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +backup stage block_ddl; +connection default; +commit; +SELECT * FROM t1; +a +1 +SET STATEMENT lock_wait_timeout=0 FOR INSERT INTO t1 values (2); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +INSERT INTO t1 values (2,0);; +connection con2; +backup stage end; +connection con1; +connection default; +select * from t1; +a j +1 NULL +2 0 +drop table t1; +# Test with inline alter table, which doesn't block block_commit +create table t1 (a int) engine=innodb; +start transaction; +insert into t1 values (1); +connection con1; +alter table t1 add column (j int); +connection con2; +backup stage start; +backup stage flush; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_ALTER_COPY Backup lock +MDL_BACKUP_FLUSH Backup lock +MDL_SHARED_WRITE Table metadata lock test t1 +MDL_SHARED_UPGRADABLE Table metadata lock test t1 +MDL_INTENTION_EXCLUSIVE Schema metadata lock test +backup stage block_ddl; +backup stage block_commit; +connection default; +SELECT * FROM t1; +a +1 +commit; +connection con2; +backup stage end; +connection con1; +connection default; +drop table t1; +# +# testing if BACKUP STAGE FLUSH causes deadlocks with DROP TABLE +# +create table t1 (a int) engine=innodb; +start transaction; +insert into t1 values (1); +connection con1; +SET STATEMENT lock_wait_timeout=0 FOR DROP TABLE t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +DROP TABLE t1; +connection con2; +backup stage start; +backup stage flush; +SET STATEMENT lock_wait_timeout=0 FOR SELECT * FROM t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +backup stage block_ddl; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_WAIT_DDL Backup lock +MDL_SHARED_WRITE Table metadata lock test t1 +MDL_INTENTION_EXCLUSIVE Schema metadata lock test +backup stage end; +connection default; +commit; +connection con1; +connection default; +# +# Check if backup stage block_dll + concurrent drop table blocks select +# +create table t1 (a int) engine=innodb; +backup stage start; +backup stage block_ddl; +connection con1; +DROP TABLE t1; +connection con2; +connection con2; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_WAIT_DDL Backup lock +SELECT * FROM t1; +a +connection default; +backup stage end; +connection con1; +connection default; +# +# Check if backup stage block_dll overrides ddl lock for drop table +# +create table t1 (a int) engine=innodb; +start transaction; +insert into t1 values (1); +connection con1; +SET STATEMENT lock_wait_timeout=0 FOR DROP TABLE t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +DROP TABLE t1; +connection con2; +backup stage start; +backup stage flush; +backup stage block_ddl; +connection default; +commit; +connection con2; +backup stage end; +connection con1; +connection default; +# +# Check if BACKUP STAGE BLOCK_COMMIT blocks commit +# +create table t1 (a int) engine=innodb; +start transaction; +insert into t1 values (1); +connection con1; +backup stage start; +backup stage block_commit; +connection default; +commit; +connection con1; +backup stage end; +connection default; +select * from t1; +a +1 +drop table t1; +disconnect con1; +disconnect con2; +# +# Test backup stage and flush tables +# +BACKUP STAGE START ; +BACKUP STAGE BLOCK_DDL ; +FLUSH TABLES; +CREATE TEMPORARY TABLE t12345678_tmp (col1 INT); +drop table t12345678_tmp; +BACKUP STAGE END; +# +# Test BACKUP STAGES with lock timeouts +# +SET GLOBAL lock_wait_timeout=0; +CREATE TABLE t_permanent_innodb (col1 INT) ENGINE = InnoDB; +CREATE TABLE t_permanent_myisam (col1 INT) ENGINE = MyISAM; +INSERT INTO t_permanent_innodb SET col1 = 1; +INSERT INTO t_permanent_myisam SET col1 = 1; +CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; +CREATE TABLE t_con1_myisam (col1 INT) ENGINE = MyISAM; +connect con1,localhost,root,,; +SET AUTOCOMMIT = 0; +connection default; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +connection con1; +UPDATE t_permanent_innodb SET col1 = 8; +UPDATE t_permanent_myisam SET col1 = 8; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +DROP TABLE t_con1_innodb; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +DROP TABLE t_con1_myisam; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +connection default; +BACKUP STAGE END; +DROP TABLE t_permanent_myisam, t_permanent_innodb; +DROP TABLE t_con1_innodb, t_con1_myisam; +disconnect con1; +set global lock_wait_timeout=default; diff --git a/mysql-test/main/backup_lock.test b/mysql-test/main/backup_lock.test new file mode 100644 index 00000000000..d6db7a6364e --- /dev/null +++ b/mysql-test/main/backup_lock.test @@ -0,0 +1,284 @@ +######################################################################## +# Tests BACKUP STAGE locking +######################################################################## + +--source include/have_innodb.inc +--source include/have_metadata_lock_info.inc +--source include/not_embedded.inc + +--echo # +--echo # Testing which locks we get from all stages +--echo # + +BACKUP STAGE START; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +BACKUP STAGE FLUSH; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +BACKUP STAGE BLOCK_DDL; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +BACKUP STAGE BLOCK_COMMIT; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +BACKUP STAGE END; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; + +--echo # +--echo # testing BACKUP STAGE LOCK's +--echo # + +# Following connections are used in a few of the following tests +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +connection default; + +--echo # +--echo # testing if BACKUP STAGE FLUSH causes deadlocks with ALTER TABLE +--echo # + +create table t1 (a int) engine=innodb; + +start transaction; +# Acquires MDL lock +insert into t1 values (1); + +connection con1; +# Waits on MDL +--send alter table t1 add column (j int), algorithm copy + +connection con2; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table metadata lock"; +--source include/wait_condition.inc +backup stage start; +backup stage flush; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +# +# Do first test with max_statement_time, other tests later are done with +# lock_wait_timeout. This is mostly to ensure that both methods works +# +--error ER_STATEMENT_TIMEOUT +SET STATEMENT max_statement_time=1 FOR backup stage block_ddl; +--send backup stage block_ddl + +connection default; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for backup lock"; +--source include/wait_condition.inc +commit; +# The following select works because alter table is waiting for DDL lock +SELECT * FROM t1; +--error ER_LOCK_WAIT_TIMEOUT +SET STATEMENT lock_wait_timeout=0 FOR INSERT INTO t1 values (2); +--send INSERT INTO t1 values (2,0); +connection con2; +--reap # BLOCK_DDL +backup stage end; +connection con1; +--reap # ALTER TABLE +connection default; +--reap # INSERT +select * from t1; +drop table t1; + +--echo # Test with inline alter table, which doesn't block block_commit + +create table t1 (a int) engine=innodb; + +start transaction; +# Acquires MDL lock +insert into t1 values (1); + +connection con1; +# Waits on MDL +--send alter table t1 add column (j int) + +connection con2; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table metadata lock"; +--source include/wait_condition.inc +backup stage start; +backup stage flush; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +backup stage block_ddl; +backup stage block_commit; +connection default; +SELECT * FROM t1; +--send commit +connection con2; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for backup lock"; +backup stage end; +connection con1; +--reap # ALTER TABLE +connection default; +--reap # commit +drop table t1; + +--echo # +--echo # testing if BACKUP STAGE FLUSH causes deadlocks with DROP TABLE +--echo # + +create table t1 (a int) engine=innodb; +start transaction; +# Acquires MDL lock +insert into t1 values (1); + +connection con1; +# Waits on MDL +--error ER_LOCK_WAIT_TIMEOUT +SET STATEMENT lock_wait_timeout=0 FOR DROP TABLE t1; +--send DROP TABLE t1 + +connection con2; +backup stage start; +backup stage flush; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table metadata lock"; +--source include/wait_condition.inc +--error ER_LOCK_WAIT_TIMEOUT +SET STATEMENT lock_wait_timeout=0 FOR SELECT * FROM t1; + +backup stage block_ddl; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +backup stage end; + +connection default; +commit; +connection con1; +--reap # DROP TABLE +connection default; + +--echo # +--echo # Check if backup stage block_dll + concurrent drop table blocks select +--echo # + +create table t1 (a int) engine=innodb; +backup stage start; +backup stage block_ddl; +connection con1; +--send DROP TABLE t1 +connection con2; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for backup lock"; +--source include/wait_condition.inc +connection con2; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +# Check that select's are not blocked +SELECT * FROM t1; +connection default; +backup stage end; +connection con1; +--reap +connection default; + +--echo # +--echo # Check if backup stage block_dll overrides ddl lock for drop table +--echo # + +create table t1 (a int) engine=innodb; +start transaction; +# Acquires MDL lock +insert into t1 values (1); + +connection con1; +# Waits on MDL +--error ER_LOCK_WAIT_TIMEOUT +SET STATEMENT lock_wait_timeout=0 FOR DROP TABLE t1; +--send DROP TABLE t1 + +connection con2; +backup stage start; +backup stage flush; +backup stage block_ddl; +connection default; +commit; +connection con2; +backup stage end; +connection con1; +--reap # DROP TABLE +connection default; + +--echo # +--echo # Check if BACKUP STAGE BLOCK_COMMIT blocks commit +--echo # + +create table t1 (a int) engine=innodb; +start transaction; +# Acquires MDL lock +insert into t1 values (1); + +connection con1; +backup stage start; +backup stage block_commit; +connection default; +--send commit +connection con1; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for backup lock"; +backup stage end; +connection default; +--reap # commit +select * from t1; +drop table t1; + +# +# End of tests using con1 and con2 +# +disconnect con1; +disconnect con2; + +--echo # +--echo # Test backup stage and flush tables +--echo # + +BACKUP STAGE START ; +BACKUP STAGE BLOCK_DDL ; +FLUSH TABLES; +CREATE TEMPORARY TABLE t12345678_tmp (col1 INT); +drop table t12345678_tmp; +BACKUP STAGE END; + +--echo # +--echo # Test BACKUP STAGES with lock timeouts +--echo # + +SET GLOBAL lock_wait_timeout=0; +CREATE TABLE t_permanent_innodb (col1 INT) ENGINE = InnoDB; +CREATE TABLE t_permanent_myisam (col1 INT) ENGINE = MyISAM; +INSERT INTO t_permanent_innodb SET col1 = 1; + +INSERT INTO t_permanent_myisam SET col1 = 1; +CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; +CREATE TABLE t_con1_myisam (col1 INT) ENGINE = MyISAM; + +--connect(con1,localhost,root,,) +SET AUTOCOMMIT = 0; + +--connection default +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; + +--connection con1 +UPDATE t_permanent_innodb SET col1 = 8; +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t_permanent_myisam SET col1 = 8; +--error ER_LOCK_WAIT_TIMEOUT +DROP TABLE t_con1_innodb; + +--error ER_LOCK_WAIT_TIMEOUT +DROP TABLE t_con1_myisam; + +--connection default +BACKUP STAGE END; +DROP TABLE t_permanent_myisam, t_permanent_innodb; +DROP TABLE t_con1_innodb, t_con1_myisam; +--disconnect con1 +set global lock_wait_timeout=default; diff --git a/mysql-test/main/backup_lock_debug.result b/mysql-test/main/backup_lock_debug.result new file mode 100644 index 00000000000..8832d9cd3e7 --- /dev/null +++ b/mysql-test/main/backup_lock_debug.result @@ -0,0 +1,28 @@ +# +# Make sure pending LOCK TABLES doesn't block BACKUP STAGE +# +CREATE TABLE t1(a INT); +LOCK TABLE t1 READ; +# +connect con1,localhost,root,,; +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL ready'; +LOCK TABLE t1 WRITE; +# +connect con2,localhost,root,,; +SET DEBUG_SYNC= 'now WAIT_FOR ready'; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; +disconnect con2; +# +connection default; +UNLOCK TABLES; +# +connection con1; +UNLOCK TABLES; +disconnect con1; +# +connection default; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/main/backup_lock_debug.test b/mysql-test/main/backup_lock_debug.test new file mode 100644 index 00000000000..8cf492b3404 --- /dev/null +++ b/mysql-test/main/backup_lock_debug.test @@ -0,0 +1,40 @@ +######################################################################## +# Tests for BACKUP STAGE locking that requires debug. +######################################################################## + +--source include/have_debug_sync.inc + +--echo # +--echo # Make sure pending LOCK TABLES doesn't block BACKUP STAGE +--echo # +CREATE TABLE t1(a INT); +LOCK TABLE t1 READ; + +--echo # +connect (con1,localhost,root,,); +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL ready'; +--send LOCK TABLE t1 WRITE + +--echo # +connect (con2,localhost,root,,); +SET DEBUG_SYNC= 'now WAIT_FOR ready'; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; +disconnect con2; + +--echo # +connection default; +UNLOCK TABLES; + +--echo # +connection con1; +reap; +UNLOCK TABLES; +disconnect con1; + +--echo # +connection default; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/main/backup_priv.result b/mysql-test/main/backup_priv.result new file mode 100644 index 00000000000..4169f58f40f --- /dev/null +++ b/mysql-test/main/backup_priv.result @@ -0,0 +1,40 @@ +# +# Test privileges for BACKUP STAGES +# +set sql_mode=""; +GRANT RELOAD ON *.* TO user1@localhost; +GRANT CREATE, DROP ON *.* TO user2@localhost; +connect con1, localhost, user1; +BACKUP STAGE START; +BACKUP STAGE END; +# change_user must release backup lock +BACKUP STAGE START; +BACKUP STAGE FLUSH; +SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock'; +lock_mode +MDL_BACKUP_FLUSH +SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock'; +lock_mode +disconnect con1; +connection default; +# A very low privileged user (-> con4) cannot acquire the backup lock +connect con1, localhost, user2; +BACKUP STAGE START; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +BACKUP STAGE FLUSH; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +BACKUP STAGE BLOCK_DDL; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +BACKUP STAGE BLOCK_COMMIT; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +BACKUP STAGE END; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +disconnect con1; +connection default; +DROP USER user1@localhost, user2@localhost; +# +# Test using BACKUP STAGES in a SP +# +create procedure foo42() +BACKUP STAGE START; +ERROR 0A000: BACKUP STAGE is not allowed in stored procedures diff --git a/mysql-test/main/backup_priv.test b/mysql-test/main/backup_priv.test new file mode 100644 index 00000000000..93b69af0b67 --- /dev/null +++ b/mysql-test/main/backup_priv.test @@ -0,0 +1,52 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc +--source include/have_metadata_lock_info.inc + +--echo # +--echo # Test privileges for BACKUP STAGES +--echo # + +set sql_mode=""; + +GRANT RELOAD ON *.* TO user1@localhost; +GRANT CREATE, DROP ON *.* TO user2@localhost; + +--connect(con1, localhost, user1) +BACKUP STAGE START; +BACKUP STAGE END; +--echo # change_user must release backup lock +BACKUP STAGE START; +BACKUP STAGE FLUSH; +SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock'; +change_user user2; +SELECT lock_mode FROM information_schema.metadata_lock_info WHERE lock_type='Backup lock'; +--disconnect con1 +--source include/wait_until_disconnected.inc +--connection default + +--echo # A very low privileged user (-> con4) cannot acquire the backup lock + +--connect(con1, localhost, user2) +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +BACKUP STAGE START; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +BACKUP STAGE FLUSH; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +BACKUP STAGE BLOCK_DDL; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +BACKUP STAGE BLOCK_COMMIT; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +BACKUP STAGE END; +--disconnect con1 +--source include/wait_until_disconnected.inc + +--connection default +DROP USER user1@localhost, user2@localhost; + +--echo # +--echo # Test using BACKUP STAGES in a SP +--echo # + +--error ER_SP_BADSTATEMENT +create procedure foo42() + BACKUP STAGE START; diff --git a/mysql-test/main/backup_stages.result b/mysql-test/main/backup_stages.result new file mode 100644 index 00000000000..caea1fda0b9 --- /dev/null +++ b/mysql-test/main/backup_stages.result @@ -0,0 +1,335 @@ +#----------------------------------------------------------------------- +# Multi-threaded tests +#----------------------------------------------------------------------- +# Show that only one connection can hold the backup lock. +connection default; +BACKUP STAGE START; +connect con1,localhost,root,,; +SET STATEMENT lock_wait_timeout=0 FOR BACKUP STAGE START; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +BACKUP STAGE START; +connection default; +# Show that the connection con1 has to wait for the backup lock and the +# corresponding representation within the processlist. +SET @con1_id = <con1_id>; +SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY +FROM information_schema.processlist WHERE id = @con1_id; +ID USER COMMAND STATE INFO STAGE MAX_STAGE INFO_BINARY +<con1_id> root Query Waiting for backup lock BACKUP STAGE START 0 0 BACKUP STAGE START +BACKUP STAGE END; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_START Backup lock +connection con1; +# The connection default has removed the backup lock. +# And so the current connection con1 can reap for its BACKUP STAGE START +connect con2,localhost,root,,; +# The connection con2 cannot continue the work of con1 by setting the +# next BACKUP STAGE FLUSH. +BACKUP STAGE FLUSH; +ERROR HY000: You must start backup with "BACKUP STAGE START" +BACKUP STAGE START; +connection default; +SET @con2_id = <con2_id>; +# Connection con2 waits for the backup lock held by con1. +SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY +FROM information_schema.processlist WHERE id = @con2_id; +ID USER COMMAND STATE INFO STAGE MAX_STAGE INFO_BINARY +<con2_id> root Query Waiting for backup lock BACKUP STAGE START 0 0 BACKUP STAGE START +disconnect con1; +connection con2; +# Connection con1 frees the backup lock held by disconnecting. +# So connection con2 gets the backup lock. +connect con3,localhost,root,,; +BACKUP STAGE START; +connection default; +SET @con3_id = <con3_id>; +# Connection con3 waits for the backup lock held by con2. +SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY +FROM information_schema.processlist WHERE id = @con3_id; +ID USER COMMAND STATE INFO STAGE MAX_STAGE INFO_BINARY +<con3_id> root Query Waiting for backup lock BACKUP STAGE START 0 0 BACKUP STAGE START +KILL CONNECTION @con2_id; +connection con3; +# Connection con2 frees the backup lock held by getting killed. +# So connection con3 gets the backup lock. +BACKUP STAGE END; +disconnect con3; +connection default; +CREATE TABLE t_permanent_innodb (col1 INT) ENGINE = InnoDB; +INSERT INTO t_permanent_innodb SET col1 = 1; +CREATE TABLE t_permanent_myisam (col1 INT) ENGINE = MyISAM; +INSERT INTO t_permanent_myisam SET col1 = 1; +connect backup,localhost,root,,; +connect con11,localhost,root,,; +SET AUTOCOMMIT = 0; +set session lock_wait_timeout=0; +connect con12,localhost,root,,; +SET AUTOCOMMIT = 1; +# Between (connection default) BACKUP STAGE START and FLUSH +# no restrictions for concurrent sessions regarding DDL or DML +# affecting transactional/non transactional permanent tables. +connection backup; +BACKUP STAGE START; +connection con11; +UPDATE t_permanent_innodb SET col1 = 2; +UPDATE t_permanent_myisam SET col1 = 2; +SELECT COUNT(*) FROM t_permanent_innodb; +COUNT(*) +1 +HANDLER t_permanent_innodb OPEN; +HANDLER t_permanent_innodb READ FIRST; +col1 +2 +HANDLER t_permanent_innodb CLOSE; +SELECT COUNT(*) FROM t_permanent_myisam; +COUNT(*) +1 +HANDLER t_permanent_myisam OPEN; +HANDLER t_permanent_myisam READ FIRST; +col1 +2 +HANDLER t_permanent_myisam CLOSE; +CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; +CREATE TABLE t_con1_myisam (col1 INT) ENGINE = InnoDB; +ALTER TABLE t_permanent_innodb ADD COLUMN col2 INT; +ALTER TABLE t_permanent_myisam ADD COLUMN col2 INT; +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; +connection con12; +UPDATE t_permanent_innodb SET col1 = 3; +UPDATE t_permanent_myisam SET col1 = 3; +# Between (connection default) BACKUP STAGE FLUSH and BLOCK_DDL +# concurrent sessions +# - can change transactional permanent tables with DDL and DML +# - can run DROP/CREATE transactional/non transactional TABLE +# - cannot modify non transactional permanent tables with DDL or DML +connection backup; +BACKUP STAGE FLUSH; +connection con11; +UPDATE t_permanent_innodb SET col1 = 4; +SET STATEMENT lock_wait_timeout=0 FOR UPDATE t_permanent_myisam SET col1 = 4; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT COUNT(*) FROM t_permanent_innodb; +COUNT(*) +1 +HANDLER t_permanent_innodb OPEN; +HANDLER t_permanent_innodb READ FIRST; +col1 col2 +4 NULL +HANDLER t_permanent_innodb CLOSE; +SELECT COUNT(*) FROM t_permanent_myisam; +COUNT(*) +1 +HANDLER t_permanent_myisam OPEN; +HANDLER t_permanent_myisam READ FIRST; +col1 col2 +3 NULL +HANDLER t_permanent_myisam CLOSE; +DROP TABLE t_con1_innodb; +DROP TABLE t_con1_myisam; +CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; +CREATE TABLE t_con1_myisam (col1 INT) ENGINE = InnoDB; +ALTER TABLE t_permanent_innodb ADD COLUMN col3 INT; +SET STATEMENT lock_wait_timeout=0 FOR ALTER TABLE t_permanent_myisam ADD COLUMN col3 INT; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; +connection con12; +UPDATE t_permanent_innodb SET col1 = 5; +# Between (connection default) BACKUP STAGE BLOCK_DDL and BLOCK_COMMIT +# concurrent sessions +# - can change transactional permanent tables with DML +# - cannot run DDL +# - cannot change non transactional permanent tables with DML +connection backup; +BACKUP STAGE BLOCK_DDL; +connection con11; +UPDATE t_permanent_innodb SET col1 = 6; +UPDATE t_permanent_myisam SET col1 = 6; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT COUNT(*) FROM t_permanent_innodb; +COUNT(*) +1 +HANDLER t_permanent_innodb OPEN; +HANDLER t_permanent_innodb READ FIRST; +col1 col2 col3 +6 NULL NULL +HANDLER t_permanent_innodb CLOSE; +SELECT COUNT(*) FROM t_permanent_myisam; +COUNT(*) +1 +HANDLER t_permanent_myisam OPEN; +HANDLER t_permanent_myisam READ FIRST; +col1 col2 +3 NULL +HANDLER t_permanent_myisam CLOSE; +DROP TABLE t_con1_innodb; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +CREATE TABLE throw_away (col1 INT) ENGINE = InnoDB; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +ALTER TABLE t_permanent_innodb ADD COLUMN col4 INT; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +connection con12; +UPDATE t_permanent_innodb SET col1 = 7; +# Between (connection default) BACKUP STAGE BLOCK_COMMIT and END +# concurrent sessions +# - can change transactional permanent tables with DML +# - cannot run DDL +# - cannot change non transactional permanent tables with DML +connection backup; +BACKUP STAGE BLOCK_COMMIT; +connection con11; +UPDATE t_permanent_innodb SET col1 = 8; +UPDATE t_permanent_myisam SET col1 = 8; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT COUNT(*) FROM t_permanent_innodb; +COUNT(*) +1 +HANDLER t_permanent_innodb OPEN; +HANDLER t_permanent_innodb READ FIRST; +col1 col2 col3 +8 NULL NULL +HANDLER t_permanent_innodb CLOSE; +SELECT COUNT(*) FROM t_permanent_myisam; +COUNT(*) +1 +HANDLER t_permanent_myisam OPEN; +HANDLER t_permanent_myisam READ FIRST; +col1 col2 +3 NULL +HANDLER t_permanent_myisam CLOSE; +DROP TABLE t_con1_innodb; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +DROP TABLE t_con1_myisam; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +connection con12; +SET STATEMENT lock_wait_timeout=0 FOR UPDATE t_permanent_innodb SET col1 = 9; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +connection backup; +BACKUP STAGE END; +connection con11; +COMMIT; +SELECT * FROM t_permanent_innodb ORDER BY col1; +col1 col2 col3 +7 NULL NULL +SELECT * FROM t_permanent_myisam ORDER BY col1; +col1 col2 +3 NULL +SET AUTOCOMMIT = 0; +SET GLOBAL tx_read_only = 1; +connection con12; +BACKUP STAGE START; +BACKUP STAGE END; +SET GLOBAL tx_read_only = 0; +DROP VIEW v_some_view; +DROP TABLE t_con1_innodb; +DROP TABLE t_con1_myisam; +# Connection backup holds the backup log and is on some stage. +# Connection con11 tries to LOCK TABLEs or to set read_only. +connection backup; +BACKUP STAGE START; +connection con11; +# Between BACKUP STAGE START and FLUSH: +# No restrictions for other connection around LOCK TABLES or read-only. +LOCK TABLES t_permanent_innodb READ; +LOCK TABLES t_permanent_myisam READ; +LOCK TABLES t_permanent_innodb WRITE; +LOCK TABLES t_permanent_myisam WRITE; +UNLOCK TABLES; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +connection backup; +BACKUP STAGE FLUSH; +connection con11; +# Between BACKUP STAGE FLUSH and BLOCK_COMMIT: +# Connection con11 not holding the backup lock cannot +# LOCK WRITE non transactional table. +LOCK TABLES t_permanent_innodb READ; +LOCK TABLES t_permanent_myisam READ; +LOCK TABLES t_permanent_innodb WRITE; +LOCK TABLES t_permanent_myisam WRITE; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +UNLOCK TABLES; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +connection backup; +BACKUP STAGE BLOCK_DDL; +connection con11; +# Between BACKUP STAGE FLUSH and BLOCK_COMMIT: +# Connection con11 not holding the backup lock cannot +# LOCK WRITE transactional or non transactional table. +LOCK TABLES t_permanent_innodb READ; +LOCK TABLES t_permanent_myisam READ; +LOCK TABLES t_permanent_innodb WRITE; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +LOCK TABLES t_permanent_myisam WRITE; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +UNLOCK TABLES; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +connection backup; +BACKUP STAGE BLOCK_COMMIT; +connection con11; +# Between BACKUP BLOCK_COMMIT FLUSH and END: +# Connection con11 not holding the backup lock cannot +# LOCK WRITE transactional or non transactional table. +LOCK TABLES t_permanent_innodb READ; +LOCK TABLES t_permanent_myisam READ; +LOCK TABLES t_permanent_innodb WRITE; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +LOCK TABLES t_permanent_myisam WRITE; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +UNLOCK TABLES; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +connection backup; +BACKUP STAGE END; +DROP TABLE t_permanent_innodb; +DROP TABLE t_permanent_myisam; +# +# Log tables +# +connection backup; +SET @old_general_log = @@general_log; +SET @old_slow_query_log = @@slow_query_log; +SET @old_log_output = @@log_output; +SET GLOBAL log_output = 'TABLE'; +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; +connection con11; +SET @old_long_query_time = @@SESSION.long_query_time; +SET SESSION long_query_time = 0; +connection backup; +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +connection con11; +SELECT 1; +1 +1 +connection backup; +SELECT 1; +1 +1 +connection con11; +SET SESSION long_query_time = @old_long_query_time; +connection backup; +BACKUP STAGE END; +SET GLOBAL log_output = @old_log_output; +SET GLOBAL slow_query_log = @old_slow_query_log; +SET GLOBAL general_log = @old_general_log; +#----------------------------------------------------------------------- +# Cleanup +#----------------------------------------------------------------------- +SET GLOBAL lock_wait_timeout = <old_lock_wait_timeout>; +disconnect con2; +disconnect con11; +disconnect con12; +disconnect backup; +connection default; diff --git a/mysql-test/main/backup_stages.test b/mysql-test/main/backup_stages.test new file mode 100644 index 00000000000..ba9c15a1d7e --- /dev/null +++ b/mysql-test/main/backup_stages.test @@ -0,0 +1,385 @@ +######################################################################## +# Test what is locked in each stage for LOCK FOR BACKUP (MDEV-5336) +######################################################################## + +--source include/not_embedded.inc +# A transactional engine +--source include/have_innodb.inc +--source include/have_metadata_lock_info.inc +# As non transactional engine we have MyISAM anyway. + +# Save the initial number of concurrent sessions. +--source include/count_sessions.inc + +let $old_lock_wait_timeout = `SELECT @@global.lock_wait_timeout`; + +--echo #----------------------------------------------------------------------- +--echo # Multi-threaded tests +--echo #----------------------------------------------------------------------- +--echo # Show that only one connection can hold the backup lock. + +--connection default +let $default_id= `SELECT CONNECTION_ID()`; +BACKUP STAGE START; + +# con1, root high privileged user +--connect(con1,localhost,root,,) +let $con1_id= `SELECT CONNECTION_ID()`; +--error ER_LOCK_WAIT_TIMEOUT +SET STATEMENT lock_wait_timeout=0 FOR BACKUP STAGE START; +send BACKUP STAGE START; +--connection default + +--echo # Show that the connection con1 has to wait for the backup lock and the +--echo # corresponding representation within the processlist. + +--replace_result $con1_id <con1_id> + +eval SET @con1_id = $con1_id; +# Output expected here is +# ID USER COMMAND STATE INFO INFO_BINARY +# <con1_id> root Query Waiting for backup lock BACKUP STAGE START BACKUP STAGE START +let $wait_condition= + SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE STATE = "Waiting for backup lock" and INFO = "BACKUP STAGE START"; +--source include/wait_condition.inc +--replace_column 1 <con1_id> +eval +SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY +FROM information_schema.processlist WHERE id = @con1_id; +# con1 uses @@global.lock_wait_timeout + +BACKUP STAGE END; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; + +--connection con1 +--echo # The connection default has removed the backup lock. +--echo # And so the current connection con1 can reap for its BACKUP STAGE START +--reap + +# con2, root high privileged user +--connect(con2,localhost,root,,) +let $con2_id= `SELECT CONNECTION_ID()`; +--echo # The connection con2 cannot continue the work of con1 by setting the +--echo # next BACKUP STAGE FLUSH. +--error ER_BACKUP_NOT_RUNNING +BACKUP STAGE FLUSH; +send +BACKUP STAGE START; + +--connection default +--replace_result $con2_id <con2_id> +eval SET @con2_id = $con2_id; +--echo # Connection con2 waits for the backup lock held by con1. +--source include/wait_condition.inc +--replace_column 1 <con2_id> +eval +SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY +FROM information_schema.processlist WHERE id = @con2_id; + +--disconnect con1 + +--connection con2 +--echo # Connection con1 frees the backup lock held by disconnecting. +--echo # So connection con2 gets the backup lock. +--reap + +--connect(con3,localhost,root,,) +let $con3_id= `SELECT CONNECTION_ID()`; +send +BACKUP STAGE START; + +--connection default +--replace_result $con3_id <con3_id> +eval SET @con3_id = $con3_id; +--echo # Connection con3 waits for the backup lock held by con2. +--source include/wait_condition.inc +--replace_column 1 <con3_id> +eval +SELECT ID, USER, COMMAND, STATE, INFO, STAGE, MAX_STAGE, INFO_BINARY +FROM information_schema.processlist WHERE id = @con3_id; +KILL CONNECTION @con2_id; + +--connection con3 +--echo # Connection con2 frees the backup lock held by getting killed. +--echo # So connection con3 gets the backup lock. +--reap +BACKUP STAGE END; +disconnect con3; +--connection default + +CREATE TABLE t_permanent_innodb (col1 INT) ENGINE = InnoDB; +INSERT INTO t_permanent_innodb SET col1 = 1; +CREATE TABLE t_permanent_myisam (col1 INT) ENGINE = MyISAM; +INSERT INTO t_permanent_myisam SET col1 = 1; + +# backup : Try the BACKUP STAGE sequence +# con11 : Try DDL + DML with AUTOCOMMIT = 0 +# con12 : Try DML with AUTOCOMMIT = 1 +--connect(backup,localhost,root,,) +--connect(con11,localhost,root,,) +SET AUTOCOMMIT = 0; +set session lock_wait_timeout=0; +--connect(con12,localhost,root,,) +SET AUTOCOMMIT = 1; + +--echo # Between (connection default) BACKUP STAGE START and FLUSH +--echo # no restrictions for concurrent sessions regarding DDL or DML +--echo # affecting transactional/non transactional permanent tables. + +--connection backup +BACKUP STAGE START; +--connection con11 +UPDATE t_permanent_innodb SET col1 = 2; +UPDATE t_permanent_myisam SET col1 = 2; +SELECT COUNT(*) FROM t_permanent_innodb; +HANDLER t_permanent_innodb OPEN; +HANDLER t_permanent_innodb READ FIRST; +HANDLER t_permanent_innodb CLOSE; +SELECT COUNT(*) FROM t_permanent_myisam; +HANDLER t_permanent_myisam OPEN; +HANDLER t_permanent_myisam READ FIRST; +HANDLER t_permanent_myisam CLOSE; +CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; +CREATE TABLE t_con1_myisam (col1 INT) ENGINE = InnoDB; +ALTER TABLE t_permanent_innodb ADD COLUMN col2 INT; +ALTER TABLE t_permanent_myisam ADD COLUMN col2 INT; +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; +--connection con12 +UPDATE t_permanent_innodb SET col1 = 3; +UPDATE t_permanent_myisam SET col1 = 3; + +--echo # Between (connection default) BACKUP STAGE FLUSH and BLOCK_DDL +--echo # concurrent sessions +--echo # - can change transactional permanent tables with DDL and DML +--echo # - can run DROP/CREATE transactional/non transactional TABLE +--echo # - cannot modify non transactional permanent tables with DDL or DML + +--connection backup +BACKUP STAGE FLUSH; +--connection con11 +UPDATE t_permanent_innodb SET col1 = 4; +--error ER_LOCK_WAIT_TIMEOUT +SET STATEMENT lock_wait_timeout=0 FOR UPDATE t_permanent_myisam SET col1 = 4; +SELECT COUNT(*) FROM t_permanent_innodb; +HANDLER t_permanent_innodb OPEN; +HANDLER t_permanent_innodb READ FIRST; +HANDLER t_permanent_innodb CLOSE; +SELECT COUNT(*) FROM t_permanent_myisam; +HANDLER t_permanent_myisam OPEN; +HANDLER t_permanent_myisam READ FIRST; +HANDLER t_permanent_myisam CLOSE; +DROP TABLE t_con1_innodb; +DROP TABLE t_con1_myisam; +CREATE TABLE t_con1_innodb (col1 INT) ENGINE = InnoDB; +CREATE TABLE t_con1_myisam (col1 INT) ENGINE = InnoDB; +ALTER TABLE t_permanent_innodb ADD COLUMN col3 INT; +--error ER_LOCK_WAIT_TIMEOUT +SET STATEMENT lock_wait_timeout=0 FOR ALTER TABLE t_permanent_myisam ADD COLUMN col3 INT; +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; +--connection con12 +UPDATE t_permanent_innodb SET col1 = 5; + + +--echo # Between (connection default) BACKUP STAGE BLOCK_DDL and BLOCK_COMMIT +--echo # concurrent sessions +--echo # - can change transactional permanent tables with DML +--echo # - cannot run DDL +--echo # - cannot change non transactional permanent tables with DML + +--connection backup +BACKUP STAGE BLOCK_DDL; +--connection con11 + +UPDATE t_permanent_innodb SET col1 = 6; +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t_permanent_myisam SET col1 = 6; +SELECT COUNT(*) FROM t_permanent_innodb; +HANDLER t_permanent_innodb OPEN; +HANDLER t_permanent_innodb READ FIRST; +HANDLER t_permanent_innodb CLOSE; +SELECT COUNT(*) FROM t_permanent_myisam; +HANDLER t_permanent_myisam OPEN; +HANDLER t_permanent_myisam READ FIRST; +HANDLER t_permanent_myisam CLOSE; +--error ER_LOCK_WAIT_TIMEOUT +DROP TABLE t_con1_innodb; +--error ER_LOCK_WAIT_TIMEOUT +CREATE TABLE throw_away (col1 INT) ENGINE = InnoDB; +--error ER_LOCK_WAIT_TIMEOUT +ALTER TABLE t_permanent_innodb ADD COLUMN col4 INT; +--error ER_LOCK_WAIT_TIMEOUT +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_innodb; +--error ER_LOCK_WAIT_TIMEOUT +CREATE OR REPLACE VIEW v_some_view AS SELECT * FROM t_permanent_myisam; +--connection con12 +UPDATE t_permanent_innodb SET col1 = 7; + + +--echo # Between (connection default) BACKUP STAGE BLOCK_COMMIT and END +--echo # concurrent sessions +--echo # - can change transactional permanent tables with DML +--echo # - cannot run DDL +--echo # - cannot change non transactional permanent tables with DML + +--connection backup +BACKUP STAGE BLOCK_COMMIT; +--connection con11 +UPDATE t_permanent_innodb SET col1 = 8; +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t_permanent_myisam SET col1 = 8; +SELECT COUNT(*) FROM t_permanent_innodb; +HANDLER t_permanent_innodb OPEN; +HANDLER t_permanent_innodb READ FIRST; +HANDLER t_permanent_innodb CLOSE; +SELECT COUNT(*) FROM t_permanent_myisam; +HANDLER t_permanent_myisam OPEN; +HANDLER t_permanent_myisam READ FIRST; +HANDLER t_permanent_myisam CLOSE; +--error ER_LOCK_WAIT_TIMEOUT +DROP TABLE t_con1_innodb; +--error ER_LOCK_WAIT_TIMEOUT +DROP TABLE t_con1_myisam; +--connection con12 +--error ER_LOCK_WAIT_TIMEOUT +SET STATEMENT lock_wait_timeout=0 FOR UPDATE t_permanent_innodb SET col1 = 9; + +--connection backup +BACKUP STAGE END; +--connection con11 +COMMIT; +SELECT * FROM t_permanent_innodb ORDER BY col1; +SELECT * FROM t_permanent_myisam ORDER BY col1; +SET AUTOCOMMIT = 0; +SET GLOBAL tx_read_only = 1; +--connection con12 +BACKUP STAGE START; +BACKUP STAGE END; +SET GLOBAL tx_read_only = 0; +DROP VIEW v_some_view; +DROP TABLE t_con1_innodb; +DROP TABLE t_con1_myisam; + +--echo # Connection backup holds the backup log and is on some stage. +--echo # Connection con11 tries to LOCK TABLEs or to set read_only. + +--connection backup +BACKUP STAGE START; +--connection con11 +--echo # Between BACKUP STAGE START and FLUSH: +--echo # No restrictions for other connection around LOCK TABLES or read-only. +LOCK TABLES t_permanent_innodb READ; +LOCK TABLES t_permanent_myisam READ; +LOCK TABLES t_permanent_innodb WRITE; +LOCK TABLES t_permanent_myisam WRITE; +UNLOCK TABLES; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +--connection backup +BACKUP STAGE FLUSH; +--connection con11 +--echo # Between BACKUP STAGE FLUSH and BLOCK_COMMIT: +--echo # Connection con11 not holding the backup lock cannot +--echo # LOCK WRITE non transactional table. +LOCK TABLES t_permanent_innodb READ; +LOCK TABLES t_permanent_myisam READ; +LOCK TABLES t_permanent_innodb WRITE; +--error ER_LOCK_WAIT_TIMEOUT +LOCK TABLES t_permanent_myisam WRITE; +UNLOCK TABLES; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +--connection backup +BACKUP STAGE BLOCK_DDL; +--connection con11 +--echo # Between BACKUP STAGE FLUSH and BLOCK_COMMIT: +--echo # Connection con11 not holding the backup lock cannot +--echo # LOCK WRITE transactional or non transactional table. +LOCK TABLES t_permanent_innodb READ; +LOCK TABLES t_permanent_myisam READ; +--error ER_LOCK_WAIT_TIMEOUT +LOCK TABLES t_permanent_innodb WRITE; +--error ER_LOCK_WAIT_TIMEOUT +LOCK TABLES t_permanent_myisam WRITE; +UNLOCK TABLES; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +--connection backup +BACKUP STAGE BLOCK_COMMIT; +--connection con11 +--echo # Between BACKUP BLOCK_COMMIT FLUSH and END: +--echo # Connection con11 not holding the backup lock cannot +--echo # LOCK WRITE transactional or non transactional table. +LOCK TABLES t_permanent_innodb READ; +LOCK TABLES t_permanent_myisam READ; +--error ER_LOCK_WAIT_TIMEOUT +LOCK TABLES t_permanent_innodb WRITE; +--error ER_LOCK_WAIT_TIMEOUT +LOCK TABLES t_permanent_myisam WRITE; +UNLOCK TABLES; +SET GLOBAL tx_read_only = 1; +SET GLOBAL tx_read_only = 0; +--connection backup +BACKUP STAGE END; + +DROP TABLE t_permanent_innodb; +DROP TABLE t_permanent_myisam; + +--echo # +--echo # Log tables +--echo # + +--connection backup + +SET @old_general_log = @@general_log; +SET @old_slow_query_log = @@slow_query_log; +SET @old_log_output = @@log_output; + +SET GLOBAL log_output = 'TABLE'; +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; + + +--connection con11 +SET @old_long_query_time = @@SESSION.long_query_time; +SET SESSION long_query_time = 0; + +--connection backup +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; + +--connection con11 +SELECT 1; + +--connection backup +SELECT 1; + +--connection con11 +SET SESSION long_query_time = @old_long_query_time; + +--connection backup +BACKUP STAGE END; + +SET GLOBAL log_output = @old_log_output; +SET GLOBAL slow_query_log = @old_slow_query_log; +SET GLOBAL general_log = @old_general_log; + +--echo #----------------------------------------------------------------------- +--echo # Cleanup +--echo #----------------------------------------------------------------------- + +--replace_result $old_lock_wait_timeout <old_lock_wait_timeout> +eval +SET GLOBAL lock_wait_timeout = $old_lock_wait_timeout; + +--disconnect con2 +--disconnect con11 +--disconnect con12 +--disconnect backup + +--connection default +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/main/backup_syntax.result b/mysql-test/main/backup_syntax.result new file mode 100644 index 00000000000..f8f623cda0c --- /dev/null +++ b/mysql-test/main/backup_syntax.result @@ -0,0 +1,163 @@ +#----------------------------------------------------------------------- +# Basic syntax checks +#----------------------------------------------------------------------- +# Check existing BACKUP STAGE statements in the sequence to be used. +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +# Check invalid variants of BACKUP .... syntax. +BACKUP LOG; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOG' at line 1 +BACKUP LOCK; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOCK' at line 1 +BACKUP STAGE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 +BACKUP STAGE LOCK; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LOCK' at line 1 +BACKUP STAGE not_existing; +ERROR HY000: Unknown backup stage: 'not_existing'. Stage should be one of START, FLUSH, BLOCK_DDL, BLOCK_COMMIT or END +#----------------------------------------------------------------------- +# BACKUP STAGE statements in various orders. +#----------------------------------------------------------------------- +# All BACKUP STAGE statements != 'BACKUP STAGE START' expect that a +# backup lock (generated by BACKUP STAGE START) already exists. +# +backup stage start; +backup stage flush; +backup stage start; +ERROR HY000: Backup stage 'START' is same or before current backup stage 'FLUSH' +backup stage start; +ERROR HY000: Backup stage 'START' is same or before current backup stage 'FLUSH' +backup stage block_commit; +backup stage flush; +ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'BLOCK_COMMIT' +backup stage flush; +ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'BLOCK_COMMIT' +backup stage end; +backup stage flush; +ERROR HY000: You must start backup with "BACKUP STAGE START" +BACKUP STAGE END; +ERROR HY000: You must start backup with "BACKUP STAGE START" +BACKUP STAGE BLOCK_COMMIT; +ERROR HY000: You must start backup with "BACKUP STAGE START" +BACKUP STAGE BLOCK_DDL; +ERROR HY000: You must start backup with "BACKUP STAGE START" +BACKUP STAGE FLUSH; +ERROR HY000: You must start backup with "BACKUP STAGE START" +# Ordered "give up" with 'BACKUP STAGE END' because of whatever reason. +# Some existing backup lock assumed a 'BACKUP STAGE END' is allowed in +# every situation. +BACKUP STAGE START; +BACKUP STAGE END; +#---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE END; +#---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; +# Orders with BACKUP STAGE FLUSH omitted. +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; +#---- +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +# Orders with BACKUP STAGE BLOCK_DDL omitted. +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +# Orders with BACKUP STAGE BLOCK_COMMIT omitted. +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; +# Orders with doubled BACKUP STAGE statements. +# We get an error but that seems to have no bad impact on the state. +# And so we are allowed to go on with BACKUP STAGE statements. +BACKUP STAGE START; +BACKUP STAGE START; +ERROR HY000: Backup stage 'START' is same or before current backup stage 'START' +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +#---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE FLUSH; +ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'FLUSH' +BACKUP STAGE END; +#---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_DDL; +ERROR HY000: Backup stage 'BLOCK_DDL' is same or before current backup stage 'BLOCK_DDL' +BACKUP STAGE END; +#---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE BLOCK_COMMIT; +ERROR HY000: Backup stage 'BLOCK_COMMIT' is same or before current backup stage 'BLOCK_COMMIT' +BACKUP STAGE END; +# Scrambled orders. +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE START; +ERROR HY000: Backup stage 'START' is same or before current backup stage 'FLUSH' +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE START; +ERROR HY000: Backup stage 'START' is same or before current backup stage 'BLOCK_DDL' +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE START; +ERROR HY000: Backup stage 'START' is same or before current backup stage 'BLOCK_COMMIT' +BACKUP STAGE END; +#---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE FLUSH; +ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'BLOCK_DDL' +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE FLUSH; +ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'BLOCK_COMMIT' +BACKUP STAGE END; +#---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE BLOCK_DDL; +ERROR HY000: Backup stage 'BLOCK_DDL' is same or before current backup stage 'BLOCK_COMMIT' +BACKUP STAGE END; +#---- +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE FLUSH; +ERROR HY000: Backup stage 'FLUSH' is same or before current backup stage 'BLOCK_DDL' +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +#---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE BLOCK_DDL; +ERROR HY000: Backup stage 'BLOCK_DDL' is same or before current backup stage 'BLOCK_COMMIT' +BACKUP STAGE END; +# +# Check Oracle syntax +# +set SQL_MODE=Oracle; +backup stage start; +backup stage end; +set SQL_MODE=default; diff --git a/mysql-test/main/backup_syntax.test b/mysql-test/main/backup_syntax.test new file mode 100644 index 00000000000..f02c69bdd85 --- /dev/null +++ b/mysql-test/main/backup_syntax.test @@ -0,0 +1,181 @@ +######################################################################## +# Tests things releated to syntax of BACKUP STAGE (MDEV-5336) +######################################################################## + +--source include/have_innodb.inc +--source include/have_metadata_lock_info.inc + +--echo #----------------------------------------------------------------------- +--echo # Basic syntax checks +--echo #----------------------------------------------------------------------- + +--echo # Check existing BACKUP STAGE statements in the sequence to be used. +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; + +--echo # Check invalid variants of BACKUP .... syntax. +--error ER_PARSE_ERROR +BACKUP LOG; +--error ER_PARSE_ERROR +BACKUP LOCK; +--error ER_PARSE_ERROR +BACKUP STAGE; +--error ER_PARSE_ERROR +BACKUP STAGE LOCK; +--error ER_BACKUP_UNKNOWN_STAGE +BACKUP STAGE not_existing; + +--echo #----------------------------------------------------------------------- +--echo # BACKUP STAGE statements in various orders. +--echo #----------------------------------------------------------------------- +--echo # All BACKUP STAGE statements != 'BACKUP STAGE START' expect that a +--echo # backup lock (generated by BACKUP STAGE START) already exists. +--echo # + +backup stage start; +backup stage flush; +--error ER_BACKUP_WRONG_STAGE +backup stage start; +--error ER_BACKUP_WRONG_STAGE +backup stage start; +backup stage block_commit; +--error ER_BACKUP_WRONG_STAGE +backup stage flush; +--error ER_BACKUP_WRONG_STAGE +backup stage flush; +backup stage end; +--error ER_BACKUP_NOT_RUNNING +backup stage flush; +--error ER_BACKUP_NOT_RUNNING +BACKUP STAGE END; +--error ER_BACKUP_NOT_RUNNING +BACKUP STAGE BLOCK_COMMIT; +--error ER_BACKUP_NOT_RUNNING +BACKUP STAGE BLOCK_DDL; +--error ER_BACKUP_NOT_RUNNING +BACKUP STAGE FLUSH; + +--echo # Ordered "give up" with 'BACKUP STAGE END' because of whatever reason. +--echo # Some existing backup lock assumed a 'BACKUP STAGE END' is allowed in +--echo # every situation. + +BACKUP STAGE START; +BACKUP STAGE END; +--echo #---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE END; +--echo #---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; +--echo # Orders with BACKUP STAGE FLUSH omitted. +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; +--echo #---- +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +--echo # Orders with BACKUP STAGE BLOCK_DDL omitted. +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +--echo # Orders with BACKUP STAGE BLOCK_COMMIT omitted. +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; + +--echo # Orders with doubled BACKUP STAGE statements. +--echo # We get an error but that seems to have no bad impact on the state. +--echo # And so we are allowed to go on with BACKUP STAGE statements. + +BACKUP STAGE START; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +--echo #---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE FLUSH; +BACKUP STAGE END; +--echo #---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; +--echo #---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; + +--echo # Scrambled orders. +BACKUP STAGE START; +BACKUP STAGE FLUSH; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE START; +BACKUP STAGE BLOCK_COMMIT; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE START; +BACKUP STAGE END; +--echo #---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_COMMIT; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE FLUSH; +BACKUP STAGE END; +--echo #---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE BLOCK_COMMIT; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; +--echo #---- +BACKUP STAGE START; +BACKUP STAGE BLOCK_DDL; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_COMMIT; +BACKUP STAGE END; +--echo #---- +BACKUP STAGE START; +BACKUP STAGE FLUSH; +BACKUP STAGE BLOCK_COMMIT; +--error ER_BACKUP_WRONG_STAGE +BACKUP STAGE BLOCK_DDL; +BACKUP STAGE END; + +--echo # +--echo # Check Oracle syntax +--echo # + +set SQL_MODE=Oracle; +backup stage start; +backup stage end; +set SQL_MODE=default; diff --git a/mysql-test/main/bootstrap.result b/mysql-test/main/bootstrap.result index 5cefc281996..eea0010b4e4 100644 --- a/mysql-test/main/bootstrap.result +++ b/mysql-test/main/bootstrap.result @@ -1,10 +1,10 @@ drop table if exists t1; +# Kill the server drop table t1; +# Kill the server drop table t1; ERROR 42S02: Unknown table 'test.t1' -set @my_max_allowed_packet= @@max_allowed_packet; -set global max_allowed_packet=64*@@max_allowed_packet; -set global max_allowed_packet=@my_max_allowed_packet; +# Kill the server drop table t1; End of 5.1 tests # @@ -14,7 +14,9 @@ End of 5.1 tests SELECT 'bug' as '' FROM INFORMATION_SCHEMA.ENGINES WHERE engine='innodb' and SUPPORT='YES'; +# Kill the server End of 5.5 tests +# Kill the server flush tables; show create table t1; Table Create Table @@ -26,3 +28,4 @@ select * from mysql.plugin; name dl EXAMPLE ha_example.so truncate table mysql.plugin; +# Kill the server diff --git a/mysql-test/main/bootstrap.test b/mysql-test/main/bootstrap.test index 414deede892..d75be403f13 100644 --- a/mysql-test/main/bootstrap.test +++ b/mysql-test/main/bootstrap.test @@ -1,3 +1,4 @@ +--source include/not_embedded.inc # # test mysqld in bootstrap mode # @@ -15,7 +16,9 @@ let $MYSQLD_BOOTSTRAP_CMD= $MYSQLD_BOOTSTRAP_CMD --datadir=$MYSQLD_DATADIR --def use test; CREATE TABLE t1(a int); EOF +--source include/kill_mysqld.inc --exec $MYSQLD_BOOTSTRAP_CMD < $MYSQLTEST_VARDIR/tmp/bootstrap_test.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1 +--source include/start_mysqld.inc drop table t1; remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_test.sql; # @@ -25,9 +28,11 @@ remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_test.sql; use test; CREATE TABLE t1; EOF +--source include/kill_mysqld.inc --error 1 --exec $MYSQLD_BOOTSTRAP_CMD < $MYSQLTEST_VARDIR/tmp/bootstrap_error.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1 # Table t1 should not exists +--source include/start_mysqld.inc --error 1051 drop table t1; remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_error.sql; @@ -35,17 +40,15 @@ remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_error.sql; # # Bootstrap with a query larger than 2*thd->net.max_packet # -set @my_max_allowed_packet= @@max_allowed_packet; -set global max_allowed_packet=64*@@max_allowed_packet; --disable_query_log create table t1 select 2 as a, concat(repeat('MySQL', @@max_allowed_packet/10), ';') as b; eval select * into outfile '$MYSQLTEST_VARDIR/tmp/long_query.sql' from t1; --enable_query_log +--source include/kill_mysqld.inc --error 1 --exec $MYSQLD_BOOTSTRAP_CMD < $MYSQLTEST_VARDIR/tmp/long_query.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1 remove_file $MYSQLTEST_VARDIR/tmp/long_query.sql; - -set global max_allowed_packet=@my_max_allowed_packet; +--source include/start_mysqld.inc drop table t1; --echo End of 5.1 tests @@ -62,8 +65,10 @@ SELECT 'bug' as '' FROM INFORMATION_SCHEMA.ENGINES WHERE engine='innodb' # # MDEV-13063 Server crashes in intern_plugin_lock or assertion `plugin_ptr->ref_count == 1' fails in plugin_init # +--source include/kill_mysqld.inc --error 1 --exec $MYSQLD_BOOTSTRAP_CMD --myisam_recover_options=NONE +--source include/start_mysqld.inc --echo End of 5.5 tests @@ -73,6 +78,7 @@ SELECT 'bug' as '' FROM INFORMATION_SCHEMA.ENGINES WHERE engine='innodb' # Check that --bootstrap can install and uninstall plugins # let $PLUGIN_DIR=`select @@plugin_dir`; +--source include/kill_mysqld.inc --write_file $MYSQLTEST_VARDIR/tmp/install_plugin.sql install soname 'ha_example'; uninstall plugin unusable; @@ -90,6 +96,7 @@ create table t1(a int) engine=example charset=latin1; EOF --exec $MYSQLD_BOOTSTRAP_CMD --plugin-dir=$PLUGIN_DIR < $MYSQLTEST_VARDIR/tmp/bootstrap_plugins.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1 --remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_plugins.sql +--source include/start_mysqld.inc flush tables; show create table t1; drop table t1; @@ -104,6 +111,7 @@ truncate table mysql.plugin; --write_file $MYSQLTEST_VARDIR/tmp/bootstrap_9969.sql use test; EOF +--source include/kill_mysqld.inc --exec $MYSQLD_BOOTSTRAP_CMD --ignore-db-dirs='some_dir' --ignore-db-dirs='some_dir' < $MYSQLTEST_VARDIR/tmp/bootstrap_9969.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1 --remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_9969.sql @@ -115,3 +123,5 @@ use test; EOF --exec $MYSQLD_BOOTSTRAP_CMD --default-time-zone=Europe/Moscow < $MYSQLTEST_VARDIR/tmp/bootstrap_9969.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1 --remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_9969.sql + +--source include/start_mysqld.inc diff --git a/mysql-test/main/brackets.result b/mysql-test/main/brackets.result new file mode 100644 index 00000000000..e789cdeff76 --- /dev/null +++ b/mysql-test/main/brackets.result @@ -0,0 +1,246 @@ +select 1 union ( select 2 union select 3); +1 +1 +2 +3 +explain extended +select 1 union ( select 2 union select 3); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +4 UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL +NULL UNION RESULT <union1,4> ALL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` union /* select#4 */ select `__4`.`2` AS `2` from (/* select#2 */ select 2 AS `2` union /* select#3 */ select 3 AS `3`) `__4` +select 1 union ( select 1 union select 1); +1 +1 +explain extended +select 1 union ( select 1 union select 1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +4 UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL +NULL UNION RESULT <union1,4> ALL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` union /* select#4 */ select `__4`.`1` AS `1` from (/* select#2 */ select 1 AS `1` union /* select#3 */ select 1 AS `1`) `__4` +select 1 union all ( select 1 union select 1); +1 +1 +1 +explain extended +select 1 union all ( select 1 union select 1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +4 UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` union all /* select#4 */ select `__4`.`1` AS `1` from (/* select#2 */ select 1 AS `1` union /* select#3 */ select 1 AS `1`) `__4` +select 1 union ( select 1 union all select 1); +1 +1 +explain extended +select 1 union ( select 1 union all select 1); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +4 UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT <union1,4> ALL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` union /* select#4 */ select `__4`.`1` AS `1` from (/* select#2 */ select 1 AS `1` union all /* select#3 */ select 1 AS `1`) `__4` +select 1 union select 1 union all select 1; +1 +1 +1 +explain extended +select 1 union select 1 union all select 1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +2 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +3 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT <union1,2,3> ALL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 /* select#1 */ select 1 AS `1` union /* select#2 */ select 1 AS `1` union all /* select#3 */ select 1 AS `1` +(select 1 as a) union (select 2) order by a; +a +1 +2 +explain extended +(select 1 as a) union (select 2) order by a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +2 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort +Warnings: +Note 1003 (/* select#1 */ select 1 AS `a`) union (/* select#2 */ select 2 AS `2`) order by `a` +/* select#1 */ select 1 AS `a` union /* select#2 */ select 2 AS `2` order by `a`; +a +1 +2 +explain extended +/* select#1 */ select 1 AS `a` union /* select#2 */ select 2 AS `2` order by `a`; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +2 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL NULL Using filesort +Warnings: +Note 1003 /* select#1 */ select 1 AS `a` union /* select#2 */ select 2 AS `2` order by `a` +select 1 union ( select 1 union (select 1 union (select 1 union select 1))); +1 +1 +explain extended all +select 1 union ( select 1 union (select 1 union (select 1 union select 1))); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +8 UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 +2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used +7 UNION <derived3> ALL NULL NULL NULL NULL 2 100.00 +3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used +6 UNION <derived4> ALL NULL NULL NULL NULL 2 100.00 +4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used +5 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL NULL +NULL UNION RESULT <union3,6> ALL NULL NULL NULL NULL NULL NULL +NULL UNION RESULT <union2,7> ALL NULL NULL NULL NULL NULL NULL +NULL UNION RESULT <union1,8> ALL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 /* select#1/0 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#8/0 */ select `__8`.`1` AS `1` from (/* select#2/1 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#7/1 */ select `__7`.`1` AS `1` from (/* select#3/2 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#6/2 */ select `__6`.`1` AS `1` from (/* select#4/3 Filter Select: select `1` AS `1` */ select 1 AS `1` union /* select#5/3 */ select 1 AS `1`) `__6`) `__7`) `__8` +# +# MDEV-6341: INSERT ... SELECT UNION with parenthesis +# +create table t1 (a int, b int); +insert into t1 (select 1,1 union select 2,2); +select * from t1 order by 1; +a b +1 1 +2 2 +delete from t1; +insert into t1 select 1,1 union select 2,2; +select * from t1 order by 1; +a b +1 1 +2 2 +drop table t1; +CREATE OR REPLACE TABLE t1 AS SELECT 1 AS a UNION SELECT 2; +select * from t1 order by 1; +a +1 +2 +drop table t1; +CREATE OR REPLACE TABLE t1 AS (SELECT 1 AS a UNION SELECT 2); +select * from t1 order by 1; +a +1 +2 +drop table t1; +CREATE OR REPLACE VIEW v1 AS (SELECT 1 AS a); +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select 1 AS `a`) latin1 latin1_swedish_ci +drop view v1; +CREATE OR REPLACE VIEW v1 AS SELECT 1 AS a UNION SELECT 2; +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `a` union select 2 AS `2` latin1 latin1_swedish_ci +drop view v1; +CREATE OR REPLACE VIEW v1 AS (SELECT 1 AS a UNION SELECT 2); +show create view v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `a` union select 2 AS `2` latin1 latin1_swedish_ci +drop view v1; +# +# MDEV-10028: Syntax error on ((SELECT ...) UNION (SELECT ...)) +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (20); +INSERT INTO t1 VALUES (30); +((SELECT a FROM t1) UNION (SELECT a FROM t1)); +a +10 +20 +30 +(SELECT * FROM t1 UNION SELECT * FROM t1); +a +10 +20 +30 +((SELECT a FROM t1) LIMIT 1); +a +10 +SELECT * FROM (SELECT 1 UNION (SELECT 2 UNION SELECT 3)) t1; +1 +1 +2 +3 +DROP TABLE t1; +# +# test of several levels of ORDER BY / LIMIT +# +create table t1 (a int, b int); +insert into t1 (a,b) values (1, 100), (2, 200), (3,30), (4,4); +select a,b from t1 order by 1 limit 3; +a b +1 100 +2 200 +3 30 +(select a,b from t1 order by 1 limit 3) order by 2 limit 2; +a b +3 30 +1 100 +(select 10,1000 union select a,b from t1 order by 1 limit 3) order by 2 limit 2; +10 1000 +3 30 +1 100 +((select a,b from t1 order by 1 limit 3) order by 2 limit 2) order by 1 limit 1; +a b +1 100 +((select a,b from t1 order by 1 limit 3) order by 2 limit 2) order by 1; +a b +1 100 +3 30 +drop table t1; +# +# MDEV-16359: union with 3 selects in brackets +# +select 1 union select 1 union select 1; +1 +1 +(select 1 union select 1 union select 1); +1 +1 +((select 1) union (select 1) union (select 1)); +1 +1 +# +# MDEV-16357: union in brackets with tail +# union with tail in brackets +# +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES(1),(2),(3),(4); +CREATE TABLE t2 (a int); +INSERT INTO t2 VALUES (4),(5),(6),(7); +(SELECT a FROM t1 UNION SELECT a FROM t2) LIMIT 1; +a +1 +(SELECT a FROM t1 UNION SELECT a FROM t2) ORDER BY a DESC; +a +7 +6 +5 +4 +3 +2 +1 +(SELECT a FROM t1 UNION SELECT a FROM t2 LIMIT 1); +a +1 +DROP TABLE t1,t2; +# End of 10.4 tests diff --git a/mysql-test/main/brackets.test b/mysql-test/main/brackets.test new file mode 100644 index 00000000000..0eaa3bfc0a2 --- /dev/null +++ b/mysql-test/main/brackets.test @@ -0,0 +1,110 @@ +select 1 union ( select 2 union select 3); +explain extended +select 1 union ( select 2 union select 3); +select 1 union ( select 1 union select 1); +explain extended +select 1 union ( select 1 union select 1); +select 1 union all ( select 1 union select 1); +explain extended +select 1 union all ( select 1 union select 1); +select 1 union ( select 1 union all select 1); +explain extended +select 1 union ( select 1 union all select 1); +select 1 union select 1 union all select 1; +explain extended +select 1 union select 1 union all select 1; + +(select 1 as a) union (select 2) order by a; +explain extended +(select 1 as a) union (select 2) order by a; +/* select#1 */ select 1 AS `a` union /* select#2 */ select 2 AS `2` order by `a`; +explain extended +/* select#1 */ select 1 AS `a` union /* select#2 */ select 2 AS `2` order by `a`; + +select 1 union ( select 1 union (select 1 union (select 1 union select 1))); +explain extended all +select 1 union ( select 1 union (select 1 union (select 1 union select 1))); + +--echo # +--echo # MDEV-6341: INSERT ... SELECT UNION with parenthesis +--echo # +create table t1 (a int, b int); +insert into t1 (select 1,1 union select 2,2); +select * from t1 order by 1; +delete from t1; +insert into t1 select 1,1 union select 2,2; +select * from t1 order by 1; +drop table t1; +CREATE OR REPLACE TABLE t1 AS SELECT 1 AS a UNION SELECT 2; +select * from t1 order by 1; +drop table t1; +CREATE OR REPLACE TABLE t1 AS (SELECT 1 AS a UNION SELECT 2); +select * from t1 order by 1; +drop table t1; +CREATE OR REPLACE VIEW v1 AS (SELECT 1 AS a); +show create view v1; +drop view v1; +CREATE OR REPLACE VIEW v1 AS SELECT 1 AS a UNION SELECT 2; +show create view v1; +drop view v1; +CREATE OR REPLACE VIEW v1 AS (SELECT 1 AS a UNION SELECT 2); +show create view v1; +drop view v1; + + +--echo # +--echo # MDEV-10028: Syntax error on ((SELECT ...) UNION (SELECT ...)) +--echo # +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (10); +INSERT INTO t1 VALUES (20); +INSERT INTO t1 VALUES (30); + +((SELECT a FROM t1) UNION (SELECT a FROM t1)); +(SELECT * FROM t1 UNION SELECT * FROM t1); +((SELECT a FROM t1) LIMIT 1); +SELECT * FROM (SELECT 1 UNION (SELECT 2 UNION SELECT 3)) t1; +DROP TABLE t1; + +--echo # +--echo # test of several levels of ORDER BY / LIMIT +--echo # +create table t1 (a int, b int); +insert into t1 (a,b) values (1, 100), (2, 200), (3,30), (4,4); + +select a,b from t1 order by 1 limit 3; +(select a,b from t1 order by 1 limit 3) order by 2 limit 2; +(select 10,1000 union select a,b from t1 order by 1 limit 3) order by 2 limit 2; +((select a,b from t1 order by 1 limit 3) order by 2 limit 2) order by 1 limit 1; +((select a,b from t1 order by 1 limit 3) order by 2 limit 2) order by 1; + +drop table t1; + +--echo # +--echo # MDEV-16359: union with 3 selects in brackets +--echo # + +select 1 union select 1 union select 1; +(select 1 union select 1 union select 1); +((select 1) union (select 1) union (select 1)); + +--echo # +--echo # MDEV-16357: union in brackets with tail +--echo # union with tail in brackets +--echo # + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES(1),(2),(3),(4); + +CREATE TABLE t2 (a int); +INSERT INTO t2 VALUES (4),(5),(6),(7); + +(SELECT a FROM t1 UNION SELECT a FROM t2) LIMIT 1; +(SELECT a FROM t1 UNION SELECT a FROM t2) ORDER BY a DESC; + +(SELECT a FROM t1 UNION SELECT a FROM t2 LIMIT 1); + +DROP TABLE t1,t2; + +--echo # End of 10.4 tests + diff --git a/mysql-test/main/bug12427262.result b/mysql-test/main/bug12427262.result index 8ec14efc45e..6e79ec3aa11 100644 --- a/mysql-test/main/bug12427262.result +++ b/mysql-test/main/bug12427262.result @@ -16,6 +16,8 @@ create table t10 (c1 int); select Sum(ALL(COUNT_READ)) from performance_schema.file_summary_by_instance where FILE_NAME like "%show_table_lw_db%" AND FILE_NAME like "%.frm%" AND EVENT_NAME='wait/io/file/sql/FRM' into @count_read_before; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead show tables; Tables_in_show_table_lw_db t1 @@ -31,6 +33,8 @@ t9 select Sum(ALL(COUNT_READ)) from performance_schema.file_summary_by_instance where FILE_NAME like "%show_table_lw_db%" AND FILE_NAME like "%.frm%" AND EVENT_NAME='wait/io/file/sql/FRM' into @count_read_after; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select @count_read_after-@count_read_before; @count_read_after-@count_read_before 0.00000000000000000000000000000000000000 @@ -49,6 +53,8 @@ t9 BASE TABLE select Sum(ALL(COUNT_READ)) from performance_schema.file_summary_by_instance where FILE_NAME like "%show_table_lw_db%" AND FILE_NAME like "%.frm%" AND EVENT_NAME='wait/io/file/sql/FRM' into @count_read_after; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select @count_read_after-@count_read_before; @count_read_after-@count_read_before 10.00000000000000000000000000000000000000 diff --git a/mysql-test/main/cast.result b/mysql-test/main/cast.result index ca314573581..f1e7eb7b502 100644 --- a/mysql-test/main/cast.result +++ b/mysql-test/main/cast.result @@ -313,7 +313,7 @@ select cast('' as time); cast('' as time) NULL Warnings: -Warning 1292 Truncated incorrect time value: '' +Warning 1292 Incorrect time value: '' select cast(NULL as DATE); cast(NULL as DATE) NULL diff --git a/mysql-test/main/column_compression_parts.result b/mysql-test/main/column_compression_parts.result index e0b54aec20c..bc3028826ee 100644 --- a/mysql-test/main/column_compression_parts.result +++ b/mysql-test/main/column_compression_parts.result @@ -12,6 +12,7 @@ INSERT INTO t1 VALUES (1,REPEAT('a',100)),(2,REPEAT('v',200)),(3,REPEAT('r',300) INSERT INTO t1 VALUES (5,REPEAT('k',500)),(6,'April'),(7,7),(8,""),(9,"M"),(10,DEFAULT); ALTER TABLE t1 ANALYZE PARTITION p1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK ALTER TABLE t1 CHECK PARTITION p2; Table Op Msg_type Msg_text diff --git a/mysql-test/main/column_compression_parts.test b/mysql-test/main/column_compression_parts.test index 9a6f63d0cde..4c77a7308f7 100644 --- a/mysql-test/main/column_compression_parts.test +++ b/mysql-test/main/column_compression_parts.test @@ -179,4 +179,4 @@ ALTER TABLE t1 REORGANIZE PARTITION p2 INTO (PARTITION p22 VALUES LESS THAN (MAX SHOW CREATE TABLE t1; ALTER TABLE t1 REBUILD PARTITION p22; -DROP TABLE t1;
\ No newline at end of file +DROP TABLE t1; diff --git a/mysql-test/main/connect-abstract.cnf b/mysql-test/main/connect-abstract.cnf new file mode 100644 index 00000000000..5798c4f2f2a --- /dev/null +++ b/mysql-test/main/connect-abstract.cnf @@ -0,0 +1,9 @@ + +!include include/default_my.cnf + +[mysqld.1] +socket= @ENV.ABSTRACT_SOCKET + +# Using @OPT.port here for uniqueness +[ENV] +ABSTRACT_SOCKET= @mtr-test-abstract-socket-@OPT.port diff --git a/mysql-test/main/connect-abstract.result b/mysql-test/main/connect-abstract.result new file mode 100644 index 00000000000..68a9674dfaa --- /dev/null +++ b/mysql-test/main/connect-abstract.result @@ -0,0 +1,5 @@ +connect con1,localhost,root,,test,,$ABSTRACT_SOCKET; +select 1; +1 +1 +disconnect con1; diff --git a/mysql-test/main/connect-abstract.test b/mysql-test/main/connect-abstract.test new file mode 100644 index 00000000000..0f212fe5a0d --- /dev/null +++ b/mysql-test/main/connect-abstract.test @@ -0,0 +1,6 @@ +--source include/linux.inc +--source include/not_embedded.inc + +connect(con1,localhost,root,,test,,$ABSTRACT_SOCKET); +select 1; +disconnect con1; diff --git a/mysql-test/main/connect.result b/mysql-test/main/connect.result index b05d0ea9fea..459ec286165 100644 --- a/mysql-test/main/connect.result +++ b/mysql-test/main/connect.result @@ -1,5 +1,4 @@ SET global secure_auth=0; -drop table if exists t1,t2; connect con1,localhost,root,,mysql; show tables; Tables_in_mysql @@ -9,12 +8,12 @@ db event func general_log +global_priv gtid_slave_pos help_category help_keyword help_relation help_topic -host index_stats innodb_index_stats innodb_table_stats @@ -57,12 +56,12 @@ db event func general_log +global_priv gtid_slave_pos help_category help_keyword help_relation help_topic -host index_stats innodb_index_stats innodb_table_stats @@ -100,11 +99,10 @@ ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) connect(localhost,test,zorro,test,MASTER_PORT,MASTER_SOCKET); connect fail_con,localhost,test,zorro,; ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) -update mysql.user set password=old_password("gambling2") where user=_binary"test"; +update mysql.user set plugin="", authentication_string="", password=old_password("gambling2") where user=_binary"test"; flush privileges; connect con10,localhost,test,gambling2,; connect con5,localhost,test,gambling2,mysql; -connection con5; set password=""; set password='gambling3'; ERROR HY000: Password hash should be a 41-digit hexadecimal number @@ -117,12 +115,12 @@ db event func general_log +global_priv_bak gtid_slave_pos help_category help_keyword help_relation help_topic -host index_stats innodb_index_stats innodb_table_stats @@ -142,6 +140,7 @@ time_zone_transition time_zone_transition_type transaction_registry user +user_bak connect con6,localhost,test,gambling3,test; show tables; Tables_in_test @@ -162,9 +161,7 @@ connect(localhost,test,zorro,test,MASTER_PORT,MASTER_SOCKET); connect fail_con,localhost,test,zorro,; ERROR 28000: Access denied for user 'test'@'localhost' (using password: YES) delete from mysql.user where user=_binary"test"; -flush privileges; connect con7,localhost,root,,test; -connection con7; create table t1 (id integer not null auto_increment primary key); create temporary table t2(id integer not null auto_increment primary key); set @id := 1; @@ -305,12 +302,10 @@ SET GLOBAL event_scheduler = OFF; # -- End of Bug#35074. connect extracon,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,; -connection extracon; SELECT 'Connection on extra port ok'; Connection on extra port ok Connection on extra port ok connect extracon2,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,; -connection extracon2; SELECT 'Connection on extra port 2 ok'; Connection on extra port 2 ok Connection on extra port 2 ok @@ -341,7 +336,6 @@ connect(localhost,mysqltest_up1,foo,test,MASTER_PORT,MASTER_SOCKET); connect pcon1,localhost,mysqltest_up1,foo,,$MASTER_MYPORT,; ERROR 28000: Access denied for user 'mysqltest_up1'@'localhost' (using password: YES) connect pcon2,localhost,mysqltest_up1,bar,,$MASTER_MYPORT,; -connection pcon2; select user(), current_user(); user() current_user() mysqltest_up1@localhost mysqltest_up1@% @@ -350,7 +344,6 @@ connect(localhost,mysqltest_up2,newpw,test,MASTER_PORT,MASTER_SOCKET); connect pcon3,localhost,mysqltest_up2,newpw,,$MASTER_MYPORT,; ERROR 28000: Access denied for user 'mysqltest_up2'@'localhost' (using password: YES) connect pcon4,localhost,mysqltest_up2,oldpw,,$MASTER_MYPORT,; -connection pcon4; select user(), current_user(); user() current_user() mysqltest_up2@localhost mysqltest_up2@% @@ -367,17 +360,15 @@ update mysql.user set plugin='mysql_old_password' where user = 'mysqltest_up2'; select user, password, plugin, authentication_string from mysql.user where user like 'mysqltest_up_'; user password plugin authentication_string -mysqltest_up1 *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB mysql_native_password -mysqltest_up2 09301740536db389 mysql_old_password +mysqltest_up1 *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB mysql_native_password *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB +mysqltest_up2 09301740536db389 mysql_old_password 09301740536db389 flush privileges; connect pcon6,localhost,mysqltest_up1,bar,,$MASTER_MYPORT,; -connection pcon6; select user(), current_user(); user() current_user() mysqltest_up1@localhost mysqltest_up1@% disconnect pcon6; connect pcon7,localhost,mysqltest_up2,oldpw,,$MASTER_MYPORT,; -connection pcon7; select user(), current_user(); user() current_user() mysqltest_up2@localhost mysqltest_up2@% @@ -386,7 +377,7 @@ connection default; DROP USER mysqltest_up1@'%'; DROP USER mysqltest_up2@'%'; # -# BUG#1010351: New "via" keyword in 5.2+ can't be used as identifier anymore +# BUG#1010351: New "via" keyword in 5.2+ can't be used as identifier anymore # create table t1 (via int); alter table t1 add key(via); @@ -394,7 +385,6 @@ drop table t1; create table t1 (col1 int); alter table t1 add via int not null; drop table t1; -drop procedure if exists p1; create procedure p1(x int) foo: loop if x = 0 then diff --git a/mysql-test/main/connect.test b/mysql-test/main/connect.test index 3a38ad88462..afc0fcc1259 100644 --- a/mysql-test/main/connect.test +++ b/mysql-test/main/connect.test @@ -14,10 +14,6 @@ SET global secure_auth=0; ---disable_warnings -drop table if exists t1,t2; ---enable_warnings - #connect (con1,localhost,root,,""); #show tables; connect (con1,localhost,root,,mysql); @@ -66,12 +62,12 @@ connect (fail_con,localhost,test,zorro,test2); connect (fail_con,localhost,test,zorro,); # check if old password version also works -update mysql.user set password=old_password("gambling2") where user=_binary"test"; +source include/switch_to_mysql_user.inc; +update mysql.user set plugin="", authentication_string="", password=old_password("gambling2") where user=_binary"test"; flush privileges; connect (con10,localhost,test,gambling2,); connect (con5,localhost,test,gambling2,mysql); -connection con5; set password=""; --error ER_PASSWD_LENGTH set password='gambling3'; @@ -98,17 +94,15 @@ connect (fail_con,localhost,test,zorro,test2); --error ER_ACCESS_DENIED_ERROR connect (fail_con,localhost,test,zorro,); - +source include/switch_to_mysql_global_priv.inc; # remove user 'test' so that other tests which may use 'test' # do not depend on this test. delete from mysql.user where user=_binary"test"; -flush privileges; # # Bug#12517 Clear user variables and replication events before # closing temp tables in thread cleanup. connect (con7,localhost,root,,test); -connection con7; let $connection_id= `select connection_id()`; create table t1 (id integer not null auto_increment primary key); create temporary table t2(id integer not null auto_increment primary key); @@ -311,11 +305,9 @@ SET GLOBAL event_scheduler = OFF; # Test connections to the extra port. connect(extracon,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,); -connection extracon; SELECT 'Connection on extra port ok'; connect(extracon2,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,); -connection extracon2; SELECT 'Connection on extra port 2 ok'; --disable_abort_on_error @@ -346,7 +338,6 @@ GRANT ALL ON test.* TO 'O1234567890123456789012345678901234567890123456789012345 FLUSH PRIVILEGES; ---replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT connect (con1,localhost,O1234567890123456789012345678901234567890123456789012345678901234567890123456789x,test123,test); disconnect con1; @@ -377,18 +368,14 @@ CREATE USER mysqltest_up2 IDENTIFIED VIA mysql_old_password using '09301740536db --replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT --error ER_ACCESS_DENIED_ERROR connect(pcon1,localhost,mysqltest_up1,foo,,$MASTER_MYPORT,); ---replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT connect(pcon2,localhost,mysqltest_up1,bar,,$MASTER_MYPORT,); -connection pcon2; select user(), current_user(); disconnect pcon2; --replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT --error ER_ACCESS_DENIED_ERROR connect(pcon3,localhost,mysqltest_up2,newpw,,$MASTER_MYPORT,); ---replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT connect(pcon4,localhost,mysqltest_up2,oldpw,,$MASTER_MYPORT,); -connection pcon4; select user(), current_user(); disconnect pcon4; @@ -412,34 +399,32 @@ connection default; # # cannot connect when password is set and plugin=mysql_native_password # +source include/switch_to_mysql_user.inc; update mysql.user set plugin='mysql_native_password' where user = 'mysqltest_up1'; update mysql.user set plugin='mysql_old_password' where user = 'mysqltest_up2'; select user, password, plugin, authentication_string from mysql.user where user like 'mysqltest_up_'; -flush privileges; +flush privileges; ---replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT connect(pcon6,localhost,mysqltest_up1,bar,,$MASTER_MYPORT,); -connection pcon6; select user(), current_user(); disconnect pcon6; ---replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT connect(pcon7,localhost,mysqltest_up2,oldpw,,$MASTER_MYPORT,); -connection pcon7; select user(), current_user(); disconnect pcon7; connection default; +source include/switch_to_mysql_global_priv.inc; + DROP USER mysqltest_up1@'%'; DROP USER mysqltest_up2@'%'; # Wait till all disconnects are completed --source include/wait_until_count_sessions.inc - --echo # ---echo # BUG#1010351: New "via" keyword in 5.2+ can't be used as identifier anymore +--echo # BUG#1010351: New "via" keyword in 5.2+ can't be used as identifier anymore --echo # create table t1 (via int); alter table t1 add key(via); @@ -449,10 +434,6 @@ create table t1 (col1 int); alter table t1 add via int not null; drop table t1; ---disable_warnings -drop procedure if exists p1; ---enable_warnings - delimiter |; create procedure p1(x int) foo: loop @@ -467,6 +448,4 @@ delimiter ;| call p1(2); drop procedure p1; - - SET global secure_auth=default; diff --git a/mysql-test/main/create-big.result b/mysql-test/main/create-big.result index d041419443e..fc29b08ffb8 100644 --- a/mysql-test/main/create-big.result +++ b/mysql-test/main/create-big.result @@ -237,11 +237,11 @@ select @a; @a 0 drop table t1; -set debug_sync='create_table_select_before_check_if_exists SIGNAL parked WAIT_FOR go'; -create table if not exists t1 select 1 as i;; +set debug_sync='create_table_before_check_if_exists SIGNAL parked WAIT_FOR go'; +create table if not exists t1 select 1 as i; connection addconroot1; set debug_sync='now WAIT_FOR parked'; -drop table t1;; +drop table t1; connection addconroot2; set debug_sync='now SIGNAL go'; connection default; @@ -249,11 +249,11 @@ connection addconroot1; connection default; create table t1 (i int); set @a:=0; -set debug_sync='create_table_select_before_check_if_exists SIGNAL parked WAIT_FOR go'; -create table if not exists t1 select 1 as i;; +set debug_sync='create_table_before_check_if_exists SIGNAL parked WAIT_FOR go'; +create table if not exists t1 select 1 as i; connection addconroot1; set debug_sync='now WAIT_FOR parked'; -create trigger t1_bi before insert on t1 for each row set @a:=1;; +create trigger t1_bi before insert on t1 for each row set @a:=1; connection addconroot2; set debug_sync='now SIGNAL go'; connection default; diff --git a/mysql-test/main/create-big.test b/mysql-test/main/create-big.test index 7f20a8b42af..82a4dd82a32 100644 --- a/mysql-test/main/create-big.test +++ b/mysql-test/main/create-big.test @@ -395,11 +395,11 @@ select @a; drop table t1; # Concurrent DROP TABLE -set debug_sync='create_table_select_before_check_if_exists SIGNAL parked WAIT_FOR go'; ---send create table if not exists t1 select 1 as i; +set debug_sync='create_table_before_check_if_exists SIGNAL parked WAIT_FOR go'; +--send create table if not exists t1 select 1 as i connection addconroot1; set debug_sync='now WAIT_FOR parked'; ---send drop table t1; +--send drop table t1 connection addconroot2; # Wait until the above DROP TABLE is blocked due to CREATE TABLE let $wait_condition= @@ -417,11 +417,11 @@ connection default; # Concurrent CREATE TRIGGER create table t1 (i int); set @a:=0; -set debug_sync='create_table_select_before_check_if_exists SIGNAL parked WAIT_FOR go'; ---send create table if not exists t1 select 1 as i; +set debug_sync='create_table_before_check_if_exists SIGNAL parked WAIT_FOR go'; +--send create table if not exists t1 select 1 as i connection addconroot1; set debug_sync='now WAIT_FOR parked'; ---send create trigger t1_bi before insert on t1 for each row set @a:=1; +--send create trigger t1_bi before insert on t1 for each row set @a:=1 connection addconroot2; # Wait until the above DROP TABLE is blocked due to CREATE TABLE let $wait_condition= diff --git a/mysql-test/main/create.result b/mysql-test/main/create.result index fd017c0967b..ea9014498e0 100644 --- a/mysql-test/main/create.result +++ b/mysql-test/main/create.result @@ -404,7 +404,7 @@ create table t3 like mysqltest.t3; ERROR 42S01: Table 't3' already exists create table non_existing_database.t1 like t1; ERROR 42000: Unknown database 'non_existing_database' -create table t3 like non_existing_table; +create table t4 like non_existing_table; ERROR 42S02: Table 'test.non_existing_table' doesn't exist create temporary table t3 like t1; ERROR 42S01: Table 't3' already exists @@ -914,8 +914,12 @@ unlock tables; lock table t1 read, t2 read; create table t2 select * from t1; ERROR HY000: Table 't2' was locked with a READ lock and can't be updated +create table t3 select * from t1; +ERROR HY000: Table 't3' was not locked with LOCK TABLES create table if not exists t2 select * from t1; ERROR HY000: Table 't2' was locked with a READ lock and can't be updated +create table if not exists t3 select * from t1; +ERROR HY000: Table 't3' was not locked with LOCK TABLES unlock tables; lock table t1 read, t2 write; create table t2 select * from t1; @@ -1053,95 +1057,6 @@ USE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' SHOW CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -set names utf8; -create database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; -use имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; -select database(); -database() -имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45 -use test; -select SCHEMA_NAME from information_schema.schemata -where schema_name='имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45'; -SCHEMA_NAME -имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45 -drop database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; -create table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 -( -имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 int, -index имÑ_индекÑа_в_кодировке_утф8_длиной_больше_чем_48 (имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45) -); -create view имÑ_вью_кодировке_утф8_длиной_больше_чем_42 as -select имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 -from имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; -select * from имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; -имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 -select TABLE_NAME from information_schema.tables where -table_schema='test'; -TABLE_NAME -имÑ_вью_кодировке_утф8_длиной_больше_чем_42 -имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 -select COLUMN_NAME from information_schema.columns where -table_schema='test'; -COLUMN_NAME -имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 -имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 -select INDEX_NAME from information_schema.statistics where -table_schema='test'; -INDEX_NAME -имÑ_индекÑа_в_кодировке_утф8_длиной_больше_чем_48 -select TABLE_NAME from information_schema.views where -table_schema='test'; -TABLE_NAME -имÑ_вью_кодировке_утф8_длиной_больше_чем_42 -show create table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; -Table Create Table -имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 CREATE TABLE `имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48` ( - `имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45` int(11) DEFAULT NULL, - KEY `имÑ_индекÑа_в_кодировке_утф8_длиной_больше_чем_48` (`имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -show create view имÑ_вью_кодировке_утф8_длиной_больше_чем_42; -View Create View character_set_client collation_connection -имÑ_вью_кодировке_утф8_длиной_больше_чем_42 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `имÑ_вью_кодировке_утф8_длиной_больше_чем_42` AS select `имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48`.`имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45` AS `имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45` from `имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48` utf8 utf8_general_ci -create trigger имÑ_триггера_в_кодировке_утф8_длиной_больше_чем_49 -before insert on имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 for each row set @a:=1; -select TRIGGER_NAME from information_schema.triggers where -trigger_schema='test'; -TRIGGER_NAME -имÑ_триггера_в_кодировке_утф8_длиной_больше_чем_49 -drop trigger имÑ_триггера_в_кодировке_утф8_длиной_больше_чем_49; -create trigger -очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66 -before insert on имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 for each row set @a:=1; -ERROR 42000: Identifier name 'очень_очень_очень_очень_очень_очень_очень_очень_длинна' is too long -drop trigger очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66; -ERROR 42000: Identifier name 'очень_очень_очень_очень_очень_очень_очень_очень_длинна' is too long -create procedure имÑ_процедуры_в_кодировке_утф8_длиной_больше_чем_50() -begin -end; -select ROUTINE_NAME from information_schema.routines where -routine_schema='test'; -ROUTINE_NAME -имÑ_процедуры_в_кодировке_утф8_длиной_больше_чем_50 -drop procedure имÑ_процедуры_в_кодировке_утф8_длиной_больше_чем_50; -create procedure очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66() -begin -end; -ERROR 42000: Identifier name 'очень_очень_очень_очень_очень_очень_очень_очень_длинна' is too long -create function имÑ_функции_в_кодировке_утф8_длиной_больше_чем_49() -returns int -return 0; -select ROUTINE_NAME from information_schema.routines where -routine_schema='test'; -ROUTINE_NAME -имÑ_функции_в_кодировке_утф8_длиной_больше_чем_49 -drop function имÑ_функции_в_кодировке_утф8_длиной_больше_чем_49; -create function очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66() -returns int -return 0; -ERROR 42000: Identifier name 'очень_очень_очень_очень_очень_очень_очень_очень_длинна' is too long -drop view имÑ_вью_кодировке_утф8_длиной_больше_чем_42; -drop table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; -set names default; drop table if exists t1,t2,t3; drop function if exists f1; create function f1() returns int diff --git a/mysql-test/main/create.test b/mysql-test/main/create.test index af5c427852c..4bf6ce99504 100644 --- a/mysql-test/main/create.test +++ b/mysql-test/main/create.test @@ -323,7 +323,7 @@ create table t3 like mysqltest.t3; --error 1049 create table non_existing_database.t1 like t1; --error ER_NO_SUCH_TABLE -create table t3 like non_existing_table; +create table t4 like non_existing_table; --error 1050 create temporary table t3 like t1; drop table t1, t2, t3; @@ -768,7 +768,6 @@ drop table t1; --error ER_CANT_AGGREGATE_2COLLATIONS create table t1 select coalesce('a' collate latin1_swedish_ci,'b' collate latin1_bin); - # Base vs temporary tables dillema (a.k.a. bug#24508 "Inconsistent # results of CREATE TABLE ... SELECT when temporary table exists"). # In this situation we either have to create non-temporary table and @@ -776,6 +775,7 @@ create table t1 select coalesce('a' collate latin1_swedish_ci,'b' collate latin1 # permanent table. After patch for Bug#47418, we create the base table and # instert data into it, even though a temporary table exists with the same # name. + create temporary table t1 (j int); create table if not exists t1 select 1; select * from t1; @@ -783,7 +783,6 @@ drop temporary table t1; select * from t1; drop table t1; - # # CREATE TABLE ... SELECT and LOCK TABLES # @@ -792,6 +791,7 @@ drop table t1; # the server doesn't crash, hang and produces sensible errors. # Includes test for bug #20662 "Infinite loop in CREATE TABLE # IF NOT EXISTS ... SELECT with locked tables". + create table t1 (i int); insert into t1 values (1), (2); lock tables t1 read; @@ -812,8 +812,12 @@ unlock tables; lock table t1 read, t2 read; --error ER_TABLE_NOT_LOCKED_FOR_WRITE create table t2 select * from t1; +--error ER_TABLE_NOT_LOCKED +create table t3 select * from t1; --error ER_TABLE_NOT_LOCKED_FOR_WRITE create table if not exists t2 select * from t1; +--error ER_TABLE_NOT_LOCKED +create table if not exists t3 select * from t1; unlock tables; lock table t1 read, t2 write; --error ER_TABLE_EXISTS_ERROR @@ -991,87 +995,6 @@ USE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa SHOW CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; # -# Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte -# -set names utf8; - -create database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; -use имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; -select database(); -use test; - -select SCHEMA_NAME from information_schema.schemata -where schema_name='имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45'; - -drop database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; -create table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 -( - имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 int, - index имÑ_индекÑа_в_кодировке_утф8_длиной_больше_чем_48 (имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45) -); - -create view имÑ_вью_кодировке_утф8_длиной_больше_чем_42 as -select имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 -from имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; - -# database, table, field, key, view -select * from имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; - ---sorted_result -select TABLE_NAME from information_schema.tables where -table_schema='test'; - -select COLUMN_NAME from information_schema.columns where -table_schema='test'; - -select INDEX_NAME from information_schema.statistics where -table_schema='test'; - -select TABLE_NAME from information_schema.views where -table_schema='test'; - -show create table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; -show create view имÑ_вью_кодировке_утф8_длиной_больше_чем_42; - -create trigger имÑ_триггера_в_кодировке_утф8_длиной_больше_чем_49 -before insert on имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 for each row set @a:=1; -select TRIGGER_NAME from information_schema.triggers where -trigger_schema='test'; -drop trigger имÑ_триггера_в_кодировке_утф8_длиной_больше_чем_49; ---error 1059 -create trigger -очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66 -before insert on имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 for each row set @a:=1; ---error 1059 -drop trigger очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66; - -create procedure имÑ_процедуры_в_кодировке_утф8_длиной_больше_чем_50() -begin -end; -select ROUTINE_NAME from information_schema.routines where -routine_schema='test'; -drop procedure имÑ_процедуры_в_кодировке_утф8_длиной_больше_чем_50; ---error 1059 -create procedure очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66() -begin -end; - -create function имÑ_функции_в_кодировке_утф8_длиной_больше_чем_49() - returns int -return 0; -select ROUTINE_NAME from information_schema.routines where -routine_schema='test'; -drop function имÑ_функции_в_кодировке_утф8_длиной_больше_чем_49; ---error 1059 -create function очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66() - returns int -return 0; - -drop view имÑ_вью_кодировке_утф8_длиной_больше_чем_42; -drop table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; -set names default; - -# # Bug#21136 CREATE TABLE SELECT within CREATE TABLE SELECT causes server crash # diff --git a/mysql-test/main/create_drop_binlog.result b/mysql-test/main/create_drop_binlog.result index be40fcc140a..b8f8b61c359 100644 --- a/mysql-test/main/create_drop_binlog.result +++ b/mysql-test/main/create_drop_binlog.result @@ -322,8 +322,6 @@ Log_name Pos Event_type Server_id End_log_pos Info # # Gtid 1 # GTID #-#-# # # Query 1 # use `test`; CREATE TABLE t1(a INT, b INT) # # Gtid 1 # GTID #-#-# -# # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS t1(a INT, b INT) -# # Gtid 1 # GTID #-#-# # # Query 1 # use `test`; CREATE OR REPLACE INDEX i1 ON t1(a) # # Gtid 1 # GTID #-#-# # # Query 1 # use `test`; CREATE OR REPLACE INDEX i1 ON t1(a) @@ -377,8 +375,6 @@ Log_name Pos Event_type Server_id End_log_pos Info # # Gtid 1 # GTID #-#-# # # Query 1 # use `test`; CREATE TABLE t1(a INT, b INT) # # Gtid 1 # GTID #-#-# -# # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS t1(a INT, b INT) -# # Gtid 1 # GTID #-#-# # # Query 1 # use `test`; CREATE INDEX IF NOT EXISTS i1 ON t1(a) # # Gtid 1 # GTID #-#-# # # Query 1 # use `test`; CREATE INDEX IF NOT EXISTS i1 ON t1(a) diff --git a/mysql-test/main/create_drop_user.result b/mysql-test/main/create_drop_user.result index dd75d1c257a..67717f3e4e0 100644 --- a/mysql-test/main/create_drop_user.result +++ b/mysql-test/main/create_drop_user.result @@ -1,22 +1,22 @@ CREATE USER IF NOT EXISTS u1@localhost IDENTIFIED BY 'pw1'; -SELECT password FROM mysql.user WHERE user='u1'; -password -*2B602296A79E0A8784ACC5C88D92E46588CCA3C3 +SELECT plugin,authentication_string FROM mysql.user WHERE user='u1'; +plugin authentication_string +mysql_native_password *2B602296A79E0A8784ACC5C88D92E46588CCA3C3 CREATE USER IF NOT EXISTS u1@localhost IDENTIFIED BY 'pw2'; Warnings: Note 1973 Can't create user 'u1'@'localhost'; it already exists -SELECT password FROM mysql.user WHERE user='u1'; -password -*2B602296A79E0A8784ACC5C88D92E46588CCA3C3 +SELECT plugin,authentication_string FROM mysql.user WHERE user='u1'; +plugin authentication_string +mysql_native_password *2B602296A79E0A8784ACC5C88D92E46588CCA3C3 CREATE OR REPLACE USER u1@localhost IDENTIFIED BY 'pw3'; -SELECT password FROM mysql.user WHERE user='u1'; -password -*77B4A70CEFD76DB9415F36D291E74C110D2738E0 +SELECT plugin,authentication_string FROM mysql.user WHERE user='u1'; +plugin authentication_string +mysql_native_password *77B4A70CEFD76DB9415F36D291E74C110D2738E0 CREATE OR REPLACE USER IF NOT EXISTS u1@localhost IDENTIFIED BY 'pw4'; ERROR HY000: Incorrect usage of OR REPLACE and IF NOT EXISTS -SELECT password FROM mysql.user WHERE user='u1'; -password -*77B4A70CEFD76DB9415F36D291E74C110D2738E0 +SELECT plugin,authentication_string FROM mysql.user WHERE user='u1'; +plugin authentication_string +mysql_native_password *77B4A70CEFD76DB9415F36D291E74C110D2738E0 DROP USER IF EXISTS u1@localhost; DROP USER IF EXISTS u1@localhost; Warnings: diff --git a/mysql-test/main/create_drop_user.test b/mysql-test/main/create_drop_user.test index 949782a2daf..234383fb4ca 100644 --- a/mysql-test/main/create_drop_user.test +++ b/mysql-test/main/create_drop_user.test @@ -1,17 +1,17 @@ --source include/not_embedded.inc CREATE USER IF NOT EXISTS u1@localhost IDENTIFIED BY 'pw1'; -SELECT password FROM mysql.user WHERE user='u1'; +SELECT plugin,authentication_string FROM mysql.user WHERE user='u1'; CREATE USER IF NOT EXISTS u1@localhost IDENTIFIED BY 'pw2'; -SELECT password FROM mysql.user WHERE user='u1'; +SELECT plugin,authentication_string FROM mysql.user WHERE user='u1'; CREATE OR REPLACE USER u1@localhost IDENTIFIED BY 'pw3'; -SELECT password FROM mysql.user WHERE user='u1'; +SELECT plugin,authentication_string FROM mysql.user WHERE user='u1'; --error ER_WRONG_USAGE CREATE OR REPLACE USER IF NOT EXISTS u1@localhost IDENTIFIED BY 'pw4'; -SELECT password FROM mysql.user WHERE user='u1'; +SELECT plugin,authentication_string FROM mysql.user WHERE user='u1'; DROP USER IF EXISTS u1@localhost; DROP USER IF EXISTS u1@localhost; diff --git a/mysql-test/main/create_or_replace.result b/mysql-test/main/create_or_replace.result index 54bec5c3f9d..485091e5810 100644 --- a/mysql-test/main/create_or_replace.result +++ b/mysql-test/main/create_or_replace.result @@ -257,12 +257,13 @@ drop table if exists test.t1,mysqltest2.t2; Warnings: Note 1051 Unknown table 'test.t1' Note 1051 Unknown table 'mysqltest2.t2' -create table test.t1 (i int); +create table test.t1 (i int) engine=myisam; create table mysqltest2.t2 like test.t1; lock table test.t1 write, mysqltest2.t2 write; select * from information_schema.metadata_lock_info; THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME -# MDL_INTENTION_EXCLUSIVE NULL Global read lock +# MDL_BACKUP_DDL NULL Backup lock +# MDL_BACKUP_DML NULL Backup lock # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock mysqltest2 # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test # MDL_SHARED_NO_READ_WRITE NULL Table metadata lock mysqltest2 t2 @@ -274,7 +275,8 @@ Tables_in_test t2 select * from information_schema.metadata_lock_info; THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME -# MDL_INTENTION_EXCLUSIVE NULL Global read lock +# MDL_BACKUP_DDL NULL Backup lock +# MDL_BACKUP_DML NULL Backup lock # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock mysqltest2 # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test # MDL_SHARED_NO_READ_WRITE NULL Table metadata lock mysqltest2 t2 @@ -289,7 +291,8 @@ create table mysqltest2.t2 like test.t1; lock table test.t1 write, mysqltest2.t2 write; select * from information_schema.metadata_lock_info; THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME -# MDL_INTENTION_EXCLUSIVE NULL Global read lock +# MDL_BACKUP_DDL NULL Backup lock +# MDL_BACKUP_DML NULL Backup lock # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock mysqltest2 # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test # MDL_SHARED_NO_READ_WRITE NULL Table metadata lock mysqltest2 t2 @@ -301,7 +304,8 @@ Tables_in_test t2 select * from information_schema.metadata_lock_info; THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME -# MDL_INTENTION_EXCLUSIVE NULL Global read lock +# MDL_BACKUP_DDL NULL Backup lock +# MDL_BACKUP_DML NULL Backup lock # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock mysqltest2 # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test # MDL_SHARED_NO_READ_WRITE NULL Table metadata lock mysqltest2 t2 @@ -311,6 +315,31 @@ select * from information_schema.metadata_lock_info; THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME create table t1 (i int); drop table t1; +create table test.t1 (i int) engine=innodb; +create table mysqltest2.t2 like test.t1; +lock table test.t1 write, mysqltest2.t2 write; +select * from information_schema.metadata_lock_info; +THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME +# MDL_BACKUP_DDL NULL Backup lock +# MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock mysqltest2 +# MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test +# MDL_SHARED_NO_READ_WRITE NULL Table metadata lock mysqltest2 t2 +# MDL_SHARED_NO_READ_WRITE NULL Table metadata lock test t1 +unlock tables; +drop table test.t1,mysqltest2.t2; +create table test.t1 (i int) engine=aria transactional=1 checksum=1; +create table mysqltest2.t2 like test.t1; +lock table test.t1 write, mysqltest2.t2 write; +select * from information_schema.metadata_lock_info; +THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME +# MDL_BACKUP_DDL NULL Backup lock +# MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock mysqltest2 +# MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test +# MDL_SHARED_NO_READ_WRITE NULL Table metadata lock mysqltest2 t2 +# MDL_SHARED_NO_READ_WRITE NULL Table metadata lock test t1 +unlock tables; +drop table t1; +create table test.t1 (i int); drop database mysqltest2; # # Testing CREATE .. LIKE @@ -398,28 +427,32 @@ create table t1 (a int); lock table t1 write, t2 read; select * from information_schema.metadata_lock_info; THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME -# MDL_INTENTION_EXCLUSIVE NULL Global read lock +# MDL_BACKUP_DDL NULL Backup lock +# MDL_BACKUP_DML NULL Backup lock # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test # MDL_SHARED_NO_READ_WRITE NULL Table metadata lock test t1 # MDL_SHARED_READ NULL Table metadata lock test t2 create or replace table t1 (i int); select * from information_schema.metadata_lock_info; THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME -# MDL_INTENTION_EXCLUSIVE NULL Global read lock +# MDL_BACKUP_DDL NULL Backup lock +# MDL_BACKUP_DML NULL Backup lock # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test # MDL_SHARED_NO_READ_WRITE NULL Table metadata lock test t1 # MDL_SHARED_READ NULL Table metadata lock test t2 create or replace table t1 like t2; select * from information_schema.metadata_lock_info; THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME -# MDL_INTENTION_EXCLUSIVE NULL Global read lock +# MDL_BACKUP_DDL NULL Backup lock +# MDL_BACKUP_DML NULL Backup lock # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test # MDL_SHARED_NO_READ_WRITE NULL Table metadata lock test t1 # MDL_SHARED_READ NULL Table metadata lock test t2 create or replace table t1 select 1 as f1; select * from information_schema.metadata_lock_info; THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME -# MDL_INTENTION_EXCLUSIVE NULL Global read lock +# MDL_BACKUP_DDL NULL Backup lock +# MDL_BACKUP_DML NULL Backup lock # MDL_INTENTION_EXCLUSIVE NULL Schema metadata lock test # MDL_SHARED_NO_READ_WRITE NULL Table metadata lock test t1 # MDL_SHARED_READ NULL Table metadata lock test t2 diff --git a/mysql-test/main/create_or_replace.test b/mysql-test/main/create_or_replace.test index 4b167663742..1b4994e811f 100644 --- a/mysql-test/main/create_or_replace.test +++ b/mysql-test/main/create_or_replace.test @@ -210,7 +210,7 @@ drop table t1,t3,t4; create database mysqltest2; drop table if exists test.t1,mysqltest2.t2; -create table test.t1 (i int); +create table test.t1 (i int) engine=myisam; create table mysqltest2.t2 like test.t1; lock table test.t1 write, mysqltest2.t2 write; --replace_column 1 # @@ -249,6 +249,26 @@ create or replace table mysqltest2.t2 (a int) select 1 as 'a', 2 as 'a'; select * from information_schema.metadata_lock_info; create table t1 (i int); drop table t1; + +create table test.t1 (i int) engine=innodb; +create table mysqltest2.t2 like test.t1; +lock table test.t1 write, mysqltest2.t2 write; +--replace_column 1 # +--sorted_result +select * from information_schema.metadata_lock_info; +unlock tables; +drop table test.t1,mysqltest2.t2; + +create table test.t1 (i int) engine=aria transactional=1 checksum=1; +create table mysqltest2.t2 like test.t1; +lock table test.t1 write, mysqltest2.t2 write; +--replace_column 1 # +--sorted_result +select * from information_schema.metadata_lock_info; +unlock tables; +drop table t1; + +create table test.t1 (i int); drop database mysqltest2; --echo # diff --git a/mysql-test/main/create_user.result b/mysql-test/main/create_user.result index 8001b43221b..8bd0ca88335 100644 --- a/mysql-test/main/create_user.result +++ b/mysql-test/main/create_user.result @@ -1,57 +1,57 @@ create user foo; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 mysql_native_password N N 0.000000 drop user foo; create user foo identified by 'password'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 mysql_native_password *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N 0.000000 drop user foo; create user foo identified by 'password' require SSL; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N ANY 0 0 0 0 N N 0.000000 +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N ANY 0 0 0 0 mysql_native_password *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N 0.000000 drop user foo; create user foo identified by 'password' require X509; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N X509 0 0 0 0 N N 0.000000 +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N X509 0 0 0 0 mysql_native_password *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N 0.000000 drop user foo; create user foo identified by 'password' require CIPHER 'cipher'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher 0 0 0 0 N N 0.000000 +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher 0 0 0 0 mysql_native_password *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N 0.000000 drop user foo; create user foo identified by 'password' require ISSUER 'issuer'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED issuer 0 0 0 0 N N 0.000000 +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED issuer 0 0 0 0 mysql_native_password *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N 0.000000 drop user foo; create user foo identified by 'password' require SUBJECT 'subject'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED subject 0 0 0 0 N N 0.000000 +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED subject 0 0 0 0 mysql_native_password *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N 0.000000 drop user foo; create user foo identified by 'password' require CIPHER 'cipher' SUBJECT 'subject'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher subject 0 0 0 0 N N 0.000000 +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher subject 0 0 0 0 mysql_native_password *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N 0.000000 drop user foo; create user foo identified by 'password' require CIPHER 'cipher' AND SUBJECT 'subject' AND ISSUER 'issuer'; select * from mysql.user where user = 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 mysql_native_password *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N 0.000000 drop user foo; create user foo, foo2 identified by 'password' require CIPHER 'cipher' AND SUBJECT 'subject' AND ISSUER 'issuer'; select * from mysql.user where user like 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 mysql_native_password N N 0.000000 #--warning ER_USER_CREATE_EXISTS create user if not exists foo, foo2 identified by 'password2' require CIPHER 'cipher2' AND SUBJECT 'subject2' AND ISSUER 'issuer2'; @@ -60,7 +60,7 @@ Note 1973 Can't create user 'foo'@'%'; it already exists Note 1973 Can't create user 'foo2'@'%'; it already exists select * from mysql.user where user like 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 mysql_native_password N N 0.000000 drop user foo, foo2; create user foo with MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 @@ -68,5 +68,5 @@ MAX_CONNECTIONS_PER_HOUR 30 MAX_USER_CONNECTIONS 40; select * from mysql.user where user like 'foo'; Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv Delete_history_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time -% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 40 N N 0.000000 +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 40 mysql_native_password N N 0.000000 drop user foo; diff --git a/mysql-test/main/create_utf8.result b/mysql-test/main/create_utf8.result new file mode 100644 index 00000000000..e1ccf7a08d7 --- /dev/null +++ b/mysql-test/main/create_utf8.result @@ -0,0 +1,89 @@ +set names utf8; +create database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +use имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +select database(); +database() +имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45 +use test; +select SCHEMA_NAME from information_schema.schemata +where schema_name='имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45'; +SCHEMA_NAME +имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45 +drop database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +create table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 +( +имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 int, +index имÑ_индекÑа_в_кодировке_утф8_длиной_больше_чем_48 (имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45) +); +create view имÑ_вью_кодировке_утф8_длиной_больше_чем_42 as +select имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 +from имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; +select * from имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; +имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 +select TABLE_NAME from information_schema.tables where +table_schema='test'; +TABLE_NAME +имÑ_вью_кодировке_утф8_длиной_больше_чем_42 +имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 +select COLUMN_NAME from information_schema.columns where +table_schema='test'; +COLUMN_NAME +имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 +имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 +select INDEX_NAME from information_schema.statistics where +table_schema='test'; +INDEX_NAME +имÑ_индекÑа_в_кодировке_утф8_длиной_больше_чем_48 +select TABLE_NAME from information_schema.views where +table_schema='test'; +TABLE_NAME +имÑ_вью_кодировке_утф8_длиной_больше_чем_42 +show create table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; +Table Create Table +имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 CREATE TABLE `имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48` ( + `имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45` int(11) DEFAULT NULL, + KEY `имÑ_индекÑа_в_кодировке_утф8_длиной_больше_чем_48` (`имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +show create view имÑ_вью_кодировке_утф8_длиной_больше_чем_42; +View Create View character_set_client collation_connection +имÑ_вью_кодировке_утф8_длиной_больше_чем_42 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `имÑ_вью_кодировке_утф8_длиной_больше_чем_42` AS select `имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48`.`имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45` AS `имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45` from `имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48` utf8 utf8_general_ci +create trigger имÑ_триггера_в_кодировке_утф8_длиной_больше_чем_49 +before insert on имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 for each row set @a:=1; +select TRIGGER_NAME from information_schema.triggers where +trigger_schema='test'; +TRIGGER_NAME +имÑ_триггера_в_кодировке_утф8_длиной_больше_чем_49 +drop trigger имÑ_триггера_в_кодировке_утф8_длиной_больше_чем_49; +create trigger +очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66 +before insert on имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 for each row set @a:=1; +ERROR 42000: Identifier name 'очень_очень_очень_очень_очень_очень_очень_очень_длинна' is too long +drop trigger очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66; +ERROR 42000: Identifier name 'очень_очень_очень_очень_очень_очень_очень_очень_длинна' is too long +create procedure имÑ_процедуры_в_кодировке_утф8_длиной_больше_чем_50() +begin +end; +select ROUTINE_NAME from information_schema.routines where +routine_schema='test'; +ROUTINE_NAME +имÑ_процедуры_в_кодировке_утф8_длиной_больше_чем_50 +drop procedure имÑ_процедуры_в_кодировке_утф8_длиной_больше_чем_50; +create procedure очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66() +begin +end; +ERROR 42000: Identifier name 'очень_очень_очень_очень_очень_очень_очень_очень_длинна' is too long +create function имÑ_функции_в_кодировке_утф8_длиной_больше_чем_49() +returns int +return 0; +select ROUTINE_NAME from information_schema.routines where +routine_schema='test'; +ROUTINE_NAME +имÑ_функции_в_кодировке_утф8_длиной_больше_чем_49 +drop function имÑ_функции_в_кодировке_утф8_длиной_больше_чем_49; +create function очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66() +returns int +return 0; +ERROR 42000: Identifier name 'очень_очень_очень_очень_очень_очень_очень_очень_длинна' is too long +drop view имÑ_вью_кодировке_утф8_длиной_больше_чем_42; +drop table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; +set names default; diff --git a/mysql-test/main/create_utf8.test b/mysql-test/main/create_utf8.test new file mode 100644 index 00000000000..40e814834bc --- /dev/null +++ b/mysql-test/main/create_utf8.test @@ -0,0 +1,80 @@ +# +# Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte +# +set names utf8; + +create database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +use имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +select database(); +use test; + +select SCHEMA_NAME from information_schema.schemata +where schema_name='имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45'; + +drop database имÑ_базы_в_кодировке_утф8_длиной_больше_чем_45; +create table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 +( + имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 int, + index имÑ_индекÑа_в_кодировке_утф8_длиной_больше_чем_48 (имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45) +); + +create view имÑ_вью_кодировке_утф8_длиной_больше_чем_42 as +select имÑ_полÑ_в_кодировке_утф8_длиной_больше_чем_45 +from имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; + +# database, table, field, key, view +select * from имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; + +--sorted_result +select TABLE_NAME from information_schema.tables where +table_schema='test'; + +select COLUMN_NAME from information_schema.columns where +table_schema='test'; + +select INDEX_NAME from information_schema.statistics where +table_schema='test'; + +select TABLE_NAME from information_schema.views where +table_schema='test'; + +show create table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; +show create view имÑ_вью_кодировке_утф8_длиной_больше_чем_42; + +create trigger имÑ_триггера_в_кодировке_утф8_длиной_больше_чем_49 +before insert on имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 for each row set @a:=1; +select TRIGGER_NAME from information_schema.triggers where +trigger_schema='test'; +drop trigger имÑ_триггера_в_кодировке_утф8_длиной_больше_чем_49; +--error 1059 +create trigger +очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66 +before insert on имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48 for each row set @a:=1; +--error 1059 +drop trigger очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66; + +create procedure имÑ_процедуры_в_кодировке_утф8_длиной_больше_чем_50() +begin +end; +select ROUTINE_NAME from information_schema.routines where +routine_schema='test'; +drop procedure имÑ_процедуры_в_кодировке_утф8_длиной_больше_чем_50; +--error 1059 +create procedure очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66() +begin +end; + +create function имÑ_функции_в_кодировке_утф8_длиной_больше_чем_49() + returns int +return 0; +select ROUTINE_NAME from information_schema.routines where +routine_schema='test'; +drop function имÑ_функции_в_кодировке_утф8_длиной_больше_чем_49; +--error 1059 +create function очень_очень_очень_очень_очень_очень_очень_очень_длиннаÑ_Ñтрока_66() + returns int +return 0; + +drop view имÑ_вью_кодировке_утф8_длиной_больше_чем_42; +drop table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; +set names default; diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result index 9bce4f0a9bd..eeae6d02476 100644 --- a/mysql-test/main/cte_nonrecursive.result +++ b/mysql-test/main/cte_nonrecursive.result @@ -418,10 +418,10 @@ t2.c in (with t as (select * from t1 where t1.a<5) select t2.c from t2,t where t2.c=t.a); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 4 -1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where -2 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +3 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) explain select t1.a,t1.b from t1,t2 where t1.a>t2.c and @@ -461,10 +461,10 @@ t.c in (with t as (select * from t1 where t1.a<5) select t2.c from t2,t where t2.c=t.a); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where -1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 +1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 func 1 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) -3 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where -3 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +4 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +4 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) explain select t1.a,t1.b from t1, (select c from t2 where c >= 4) as t where t1.a=t.c and @@ -507,9 +507,9 @@ select t.a, count(*) from t1,t where t1.a=t.a group by t.a; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) -1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 35 func 1 -3 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where -3 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 35 func 1 +4 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +4 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) explain select t.a, count(*) from t1, @@ -597,8 +597,8 @@ explain select * from v2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where -1 PRIMARY <derived3> ref key0 key0 5 test.t2.c 2 -3 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +1 PRIMARY <derived2> ref key0 key0 5 test.t2.c 2 +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort # with clause in the specification of a view that whose definition # table alias for a with table create view v3 as @@ -863,8 +863,8 @@ SELECT * FROM (WITH a AS (SELECT * FROM t1) SELECT 1) AS t1; 1 EXPLAIN SELECT * FROM (WITH a AS (SELECT * FROM t1) SELECT 1) AS t1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <derived2> system NULL NULL NULL NULL 1 -2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +1 PRIMARY <derived3> system NULL NULL NULL NULL 1 +3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used DROP TABLE t1; # # MDEV-10058: Suspicious EXPLAIN output for a derived table + WITH + joined table @@ -1116,17 +1116,17 @@ select * from cte_e as cte_e1 where a > 1 union select * from cte_e as cte_e2; id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY <derived2> ALL NULL NULL NULL NULL 14 100.00 Using where -2 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where +1 PRIMARY <derived4> ALL NULL NULL NULL NULL 14 100.00 Using where +4 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where 5 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where -NULL UNION RESULT <union2,5> ALL NULL NULL NULL NULL NULL NULL -6 UNION <derived9> ALL NULL NULL NULL NULL 14 100.00 -9 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where +NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL NULL +6 UNION <derived11> ALL NULL NULL NULL NULL 14 100.00 +11 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where 12 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where -NULL UNION RESULT <union9,12> ALL NULL NULL NULL NULL NULL NULL +NULL UNION RESULT <union11,12> ALL NULL NULL NULL NULL NULL NULL NULL UNION RESULT <union1,6> ALL NULL NULL NULL NULL NULL NULL Warnings: -Note 1003 with cte_e as (with cte_o as (with cte_i as (/* select#4 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)/* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1 union /* select#5 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1)/* select#1 */ select `cte_e1`.`a` AS `a` from `cte_e` `cte_e1` where `cte_e1`.`a` > 1 union /* select#6 */ select `cte_e2`.`a` AS `a` from (with cte_o as (with cte_i as (/* select#11 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)/* select#10 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)/* select#9 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 union /* select#12 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7) `cte_e2` +Note 1003 with cte_e as (with cte_o as (with cte_i as (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1 union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1)select `cte_e1`.`a` AS `a` from `cte_e` `cte_e1` where `cte_e1`.`a` > 1 union select `cte_e2`.`a` AS `a` from (with cte_o as (with cte_i as (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7) `cte_e2` drop table t1; # # MDEV-13753: embedded CTE in a VIEW created in prepared statement diff --git a/mysql-test/main/ctype_gbk.result b/mysql-test/main/ctype_gbk.result index de056dffe2a..9bf69584725 100644 --- a/mysql-test/main/ctype_gbk.result +++ b/mysql-test/main/ctype_gbk.result @@ -480,7 +480,11 @@ b MEDIUMTEXT CHARACTER SET big5); INSERT INTO t1 VALUES (REPEAT(0x1125,200000), REPEAT(0x1125,200000)), ('', ''), ('', ''); SELECT a FROM t1 GROUP BY 1 LIMIT 1 INTO @nullll; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT b FROM t1 GROUP BY 1 LIMIT 1 INTO @nullll; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead DROP TABLES t1; End of 5.0 tests # diff --git a/mysql-test/main/ctype_ucs.result b/mysql-test/main/ctype_ucs.result index dee9da3ce87..efd113e4847 100644 --- a/mysql-test/main/ctype_ucs.result +++ b/mysql-test/main/ctype_ucs.result @@ -207,6 +207,8 @@ DROP TABLE t1; # Problem # 1 (original report): wrong parsing of ucs2 data SET character_set_connection=ucs2; SELECT '00' UNION SELECT '10' INTO OUTFILE 'tmpp.txt'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE TABLE t1(a INT); LOAD DATA INFILE 'tmpp.txt' INTO TABLE t1 CHARACTER SET ucs2 (@b) SET a=REVERSE(@b); @@ -218,6 +220,8 @@ a DROP TABLE t1; # Problem # 2 : if you write and read ucs2 data to a file they're lost SELECT '00' UNION SELECT '10' INTO OUTFILE 'tmpp2.txt' CHARACTER SET ucs2; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE TABLE t1(a INT); LOAD DATA INFILE 'tmpp2.txt' INTO TABLE t1 CHARACTER SET ucs2 (@b) SET a=REVERSE(@b); @@ -4571,7 +4575,7 @@ SELECT SEC_TO_TIME(CONVERT(900*24*60*60 USING ucs2)); SEC_TO_TIME(CONVERT(900*24*60*60 USING ucs2)) 838:59:59.999999 Warnings: -Warning 1292 Truncated incorrect time value: '77760000' +Warning 1292 Truncated incorrect seconds value: '77760000' # # MDEV-13530 VARBINARY doesn't convert to to BLOB for sizes 65533, 65534 and 65535 # @@ -6379,3 +6383,15 @@ DEALLOCATE PREPARE stmt; # # End of 10.2 tests # +# +# Start of 10.4 tests +# +# +# MDEV-17995 INET6_NTOA(ucs2_input) erroneously returns NULL +# +SELECT HEX(INET6_ATON('1::1')), HEX(INET6_ATON(CONVERT('1::1' USING ucs2))); +HEX(INET6_ATON('1::1')) HEX(INET6_ATON(CONVERT('1::1' USING ucs2))) +00010000000000000000000000000001 00010000000000000000000000000001 +# +# End of 10.4 tests +# diff --git a/mysql-test/main/ctype_ucs.test b/mysql-test/main/ctype_ucs.test index d0d463c0340..983f48edbc5 100644 --- a/mysql-test/main/ctype_ucs.test +++ b/mysql-test/main/ctype_ucs.test @@ -1094,3 +1094,18 @@ DEALLOCATE PREPARE stmt; --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-17995 INET6_NTOA(ucs2_input) erroneously returns NULL +--echo # + +SELECT HEX(INET6_ATON('1::1')), HEX(INET6_ATON(CONVERT('1::1' USING ucs2))); + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/ctype_upgrade.result b/mysql-test/main/ctype_upgrade.result index 5f0be66f8fb..9d19c3b5203 100644 --- a/mysql-test/main/ctype_upgrade.result +++ b/mysql-test/main/ctype_upgrade.result @@ -235,12 +235,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -258,9 +258,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -294,12 +294,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -317,9 +317,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables diff --git a/mysql-test/main/date_formats.result b/mysql-test/main/date_formats.result index 16dbdf7969c..463cce39520 100644 --- a/mysql-test/main/date_formats.result +++ b/mysql-test/main/date_formats.result @@ -442,7 +442,7 @@ f1 f2 f3 Warnings: Warning 1292 Truncated incorrect datetime value: '2003-01-02 10:11:12.0012ABCD' Warning 1292 Truncated incorrect time value: '-01:01:01.01 GGG' -Warning 1292 Truncated incorrect time value: '1997-12-31 23:59:59.01XXXX' +Warning 1292 Truncated incorrect datetime value: '1997-12-31 23:59:59.01XXXX' select str_to_date("2003-04-05 g", "%Y-%m-%d") as f1, str_to_date("2003-04-05 10:11:12.101010234567", "%Y-%m-%d %H:%i:%S.%f") as f2; f1 f2 diff --git a/mysql-test/main/deadlock_innodb.result b/mysql-test/main/deadlock_innodb.result index af78a6aa9d5..fca0ff6be0c 100644 --- a/mysql-test/main/deadlock_innodb.result +++ b/mysql-test/main/deadlock_innodb.result @@ -72,7 +72,7 @@ insert into t1 values(0, 0), (300, 300); insert into t2 values(0, 0), (1, 20), (2, 30); commit; connection con1; -select a,b from t2 UNION SELECT id, x from t1 FOR UPDATE; +select a,b from t2 UNION (SELECT id, x from t1 FOR UPDATE); a b 0 0 20 1 diff --git a/mysql-test/main/delayed.result b/mysql-test/main/delayed.result index 613e214751e..ec36e3af46d 100644 --- a/mysql-test/main/delayed.result +++ b/mysql-test/main/delayed.result @@ -500,7 +500,8 @@ call mtr.add_suppression("Checking table"); insert delayed into t1 values (2,2); Warnings: Error 145 Table './test/t1' is marked as crashed and should be repaired -Error 1034 1 client is using or hasn't closed the table properly +Warning 1034 1 client is using or hasn't closed the table properly +Note 1034 Table is fixed insert delayed into t1 values (3,3); flush tables t1; select * from t1; diff --git a/mysql-test/main/delete_use_source.result b/mysql-test/main/delete_use_source.result index 08da8901528..a9a6df88077 100644 --- a/mysql-test/main/delete_use_source.result +++ b/mysql-test/main/delete_use_source.result @@ -6,6 +6,7 @@ insert t1 select 2,seq from seq_1_to_50; insert t1 select 3,seq from seq_1_to_20; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # # Delete with limit (quick select - range acces) @@ -47,8 +48,8 @@ rollback; start transaction; explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL c1 NULL NULL NULL 502 Using where -2 DEPENDENT SUBQUERY b ref c1 c1 4 test.t1.c1 58 Using index +1 PRIMARY t1 range c1 c1 4 NULL 600 Using where +2 DEPENDENT SUBQUERY b ref c1 c1 4 test.t1.c1 167 Using index delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1; affected rows: 1 delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 limit 1; @@ -63,8 +64,8 @@ rollback; start transaction; explain delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL c1 NULL NULL NULL 502 Using where -2 DEPENDENT SUBQUERY b ref c1 c1 4 test.t1.c1 58 Using index +1 PRIMARY t1 ALL c1 NULL NULL NULL 670 Using where +2 DEPENDENT SUBQUERY b ref c1 c1 4 test.t1.c1 167 Using index delete from v1 where (select count(*) from t1 b where b.c1=v1.c1) = 500 ; affected rows: 500 select count(*) from v1 where c1=0; diff --git a/mysql-test/main/deprecated_features.result b/mysql-test/main/deprecated_features.result index fc6c86d065d..2c77d745e2e 100644 --- a/mysql-test/main/deprecated_features.result +++ b/mysql-test/main/deprecated_features.result @@ -5,7 +5,7 @@ ERROR HY000: Unknown system variable 'table_type' select @@table_type='MyISAM'; ERROR HY000: Unknown system variable 'table_type' backup table t1 to 'data.txt'; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'backup table t1 to 'data.txt'' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'table t1 to 'data.txt'' at line 1 restore table t1 from 'data.txt'; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'restore table t1 from 'data.txt'' at line 1 show plugin; diff --git a/mysql-test/main/derived.result b/mysql-test/main/derived.result index f0d0289c1ce..9874f16aa8a 100644 --- a/mysql-test/main/derived.result +++ b/mysql-test/main/derived.result @@ -632,7 +632,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 DERIVED t1 system NULL NULL NULL NULL 1 100.00 Warnings: Note 1276 Field or reference 'sq.f2' of SELECT #3 was resolved in SELECT #1 -Note 1003 /* select#1 */ select 6 AS `f1` from <materialize> (/* select#4 */ select `test`.`t2`.`f3` from `test`.`t2` having `test`.`t2`.`f3` >= 8) semi join (`test`.`t2`) where `test`.`t2`.`f3` = 6 and `<subquery4>`.`f3` = 9 +Note 1003 /* select#1 */ select 6 AS `f1` from <materialize> (/* select#4 */ select `test`.`t2`.`f3` from `test`.`t2` having `test`.`t2`.`f3` >= 8) semi join (`test`.`t2`) where `<subquery4>`.`f3` = 9 and `test`.`t2`.`f3` = 6 DROP TABLE t2,t1; # # MDEV-9462: Out of memory using explain on 2 empty tables diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index ff6d94ab858..36a44ce6fba 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -10269,9 +10269,9 @@ EXPLAIN INSERT INTO t1 SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 144 Using where -2 DERIVED <derived3> ALL NULL NULL NULL NULL 12 +2 DERIVED <derived4> ALL NULL NULL NULL NULL 12 2 DERIVED t1 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join) -3 DERIVED t1 ALL NULL NULL NULL NULL 12 +4 DERIVED t1 ALL NULL NULL NULL NULL 12 EXPLAIN FORMAT=JSON INSERT INTO t1 SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL; EXPLAIN @@ -10288,13 +10288,13 @@ EXPLAIN "query_block": { "select_id": 2, "table": { - "table_name": "<derived3>", + "table_name": "<derived4>", "access_type": "ALL", "rows": 12, "filtered": 100, "materialized": { "query_block": { - "select_id": 3, + "select_id": 4, "table": { "table_name": "t1", "access_type": "ALL", @@ -10364,7 +10364,7 @@ EXPLAIN "attached_condition": "t1.f is not null" }, "table": { - "table_name": "<derived3>", + "table_name": "<derived4>", "access_type": "ref", "possible_keys": ["key0"], "key": "key0", @@ -10375,7 +10375,7 @@ EXPLAIN "filtered": 100, "materialized": { "query_block": { - "select_id": 3, + "select_id": 4, "table": { "table_name": "t1", "access_type": "ALL", @@ -12434,7 +12434,7 @@ EXPLAIN "access_type": "ALL", "rows": 18, "filtered": 100, - "attached_condition": "__3.a > 5 and __3.c > 200", + "attached_condition": "__5.a > 5 and __5.c > 200", "materialized": { "query_block": { "union_result": { @@ -13060,7 +13060,7 @@ EXPLAIN "access_type": "ALL", "rows": 18, "filtered": 100, - "attached_condition": "__3.a > 4 and __3.c < 130", + "attached_condition": "__5.a > 4 and __5.c < 130", "materialized": { "query_block": { "union_result": { @@ -13206,7 +13206,7 @@ EXPLAIN "access_type": "ALL", "rows": 18, "filtered": 100, - "attached_condition": "__3.a > 4 and __3.c < 130", + "attached_condition": "__6.a > 4 and __6.c < 130", "materialized": { "query_block": { "union_result": { @@ -13963,16 +13963,16 @@ a b max_c a b c 1 21 345 3 21 231 select * from v1,t2 where (v1.b=t2.b) and (v1.a<5); a b max_c a b c -1 21 345 3 21 231 2 33 7 5 33 207 -2 33 7 8 33 117 -3 21 500 3 21 231 4 33 123 5 33 207 +2 33 7 8 33 117 4 33 123 8 33 117 +1 21 345 3 21 231 +3 21 500 3 21 231 explain select * from v1,t2 where (v1.b=t2.b) and (v1.a<5); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 ALL NULL NULL NULL NULL 9 -1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 9 Using where; Using join buffer (flat, BNL join) 2 DERIVED t3 range i1 i1 5 NULL 5 Using index condition explain format=json select * from v1,t2 where (v1.b=t2.b) and (v1.a<5); EXPLAIN @@ -13980,23 +13980,11 @@ EXPLAIN "query_block": { "select_id": 1, "table": { - "table_name": "t2", + "table_name": "<derived2>", "access_type": "ALL", - "rows": 9, - "filtered": 100 - }, - "block-nl-join": { - "table": { - "table_name": "<derived2>", - "access_type": "ALL", - "rows": 5, - "filtered": 80, - "attached_condition": "v1.a < 5" - }, - "buffer_type": "flat", - "buffer_size": "256Kb", - "join_type": "BNL", - "attached_condition": "v1.b = t2.b", + "rows": 5, + "filtered": 100, + "attached_condition": "v1.a < 5", "materialized": { "query_block": { "select_id": 2, @@ -14013,6 +14001,18 @@ EXPLAIN } } } + }, + "block-nl-join": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 9, + "filtered": 100 + }, + "buffer_type": "flat", + "buffer_size": "256Kb", + "join_type": "BNL", + "attached_condition": "t2.b = v1.b" } } } @@ -14936,7 +14936,9 @@ insert into t2 values insert into t2 select a+10, b+10, concat(c,'f') from t2; analyze table t1,t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK set statement optimizer_switch='split_materialized=off' for select t1.a,t.s,t.m from t1 join @@ -14966,7 +14968,7 @@ where t1.b < 3; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 range idx_b idx_b 5 NULL 4 100.00 Using index condition; Using where 1 PRIMARY <derived2> ref key0 key0 5 test.t1.a 2 100.00 -2 LATERAL DERIVED t2 ref idx_a idx_a 5 test.t1.a 2 100.00 +2 LATERAL DERIVED t2 ref idx_a idx_a 5 test.t1.a 1 100.00 Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`t`.`s` AS `s`,`t`.`m` AS `m` from `test`.`t1` join (/* select#2 */ select `test`.`t2`.`a` AS `a`,sum(`test`.`t2`.`b`) AS `s`,min(`test`.`t2`.`c`) AS `m` from `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`a` group by `test`.`t2`.`a`) `t` where `t`.`a` = `test`.`t1`.`a` and `test`.`t1`.`b` < 3 explain format=json select t1.a,t.s,t.m @@ -15012,7 +15014,7 @@ EXPLAIN "key_length": "5", "used_key_parts": ["a"], "ref": ["test.t1.a"], - "rows": 2, + "rows": 1, "filtered": 100 } } @@ -15075,10 +15077,10 @@ on t1.a=t.a where t1.b <= 5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL idx_b NULL NULL NULL 12 75.00 Using where -1 PRIMARY <derived2> ref key0 key0 5 test.t1.a 9 100.00 -2 DERIVED t2 ALL idx_a NULL NULL NULL 90 100.00 Using temporary; Using filesort +1 PRIMARY <derived2> ref key0 key0 5 test.t1.a 2 100.00 +2 LATERAL DERIVED t2 ref idx_a idx_a 5 test.t1.a 1 100.00 Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`t`.`s` AS `s`,`t`.`m` AS `m` from `test`.`t1` join (/* select#2 */ select `test`.`t2`.`a` AS `a`,sum(`test`.`t2`.`b`) AS `s`,min(`test`.`t2`.`b`) AS `m` from `test`.`t2` group by `test`.`t2`.`a`) `t` where `t`.`a` = `test`.`t1`.`a` and `test`.`t1`.`b` <= 5 +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`t`.`s` AS `s`,`t`.`m` AS `m` from `test`.`t1` join (/* select#2 */ select `test`.`t2`.`a` AS `a`,sum(`test`.`t2`.`b`) AS `s`,min(`test`.`t2`.`b`) AS `m` from `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`a` group by `test`.`t2`.`a`) `t` where `t`.`a` = `test`.`t1`.`a` and `test`.`t1`.`b` <= 5 explain format=json select t1.a,t.s,t.m from t1 join (select a, sum(t2.b) as s, min(t2.b) as m from t2 group by t2.a) t @@ -15104,22 +15106,22 @@ EXPLAIN "key_length": "5", "used_key_parts": ["a"], "ref": ["test.t1.a"], - "rows": 9, + "rows": 2, "filtered": 100, "materialized": { "query_block": { "select_id": 2, - "filesort": { - "sort_key": "t2.a", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "possible_keys": ["idx_a"], - "rows": 90, - "filtered": 100 - } - } + "outer_ref_condition": "t1.a is not null", + "table": { + "table_name": "t2", + "access_type": "ref", + "possible_keys": ["idx_a"], + "key": "idx_a", + "key_length": "5", + "used_key_parts": ["a"], + "ref": ["test.t1.a"], + "rows": 1, + "filtered": 100 } } } @@ -15178,11 +15180,11 @@ from t1 left join (select a, max(t2.b) max, min(t2.b) min from t2 group by t2.a) t on t1.a=t.a; id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 4 100.00 -1 PRIMARY <derived2> ref key0 key0 5 test.t1.a 2 100.00 Using where -2 LATERAL DERIVED t2 ref idx_a idx_a 5 test.t1.a 2 100.00 +1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 +1 PRIMARY <derived2> ref key0 key0 5 test.t1.a 9 100.00 Using where +2 DERIVED t2 ALL idx_a NULL NULL NULL 90 100.00 Using temporary; Using filesort Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`t`.`max` AS `max`,`t`.`min` AS `min` from `test`.`t1` left join (/* select#2 */ select `test`.`t2`.`a` AS `a`,max(`test`.`t2`.`b`) AS `max`,min(`test`.`t2`.`b`) AS `min` from `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`a` group by `test`.`t2`.`a`) `t` on(`t`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` is not null) where 1 +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`t`.`max` AS `max`,`t`.`min` AS `min` from `test`.`t1` left join (/* select#2 */ select `test`.`t2`.`a` AS `a`,max(`test`.`t2`.`b`) AS `max`,min(`test`.`t2`.`b`) AS `min` from `test`.`t2` group by `test`.`t2`.`a`) `t` on(`t`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` is not null) where 1 explain format=json select t1.a,t.max,t.min from t1 left join (select a, max(t2.b) max, min(t2.b) min from t2 group by t2.a) t @@ -15195,7 +15197,7 @@ EXPLAIN "table": { "table_name": "t1", "access_type": "ALL", - "rows": 4, + "rows": 12, "filtered": 100 }, "table": { @@ -15206,23 +15208,23 @@ EXPLAIN "key_length": "5", "used_key_parts": ["a"], "ref": ["test.t1.a"], - "rows": 2, + "rows": 9, "filtered": 100, "attached_condition": "trigcond(trigcond(t1.a is not null))", "materialized": { "query_block": { "select_id": 2, - "outer_ref_condition": "t1.a is not null", - "table": { - "table_name": "t2", - "access_type": "ref", - "possible_keys": ["idx_a"], - "key": "idx_a", - "key_length": "5", - "used_key_parts": ["a"], - "ref": ["test.t1.a"], - "rows": 2, - "filtered": 100 + "filesort": { + "sort_key": "t2.a", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "possible_keys": ["idx_a"], + "rows": 90, + "filtered": 100 + } + } } } } @@ -15243,7 +15245,9 @@ insert into t4 values insert into t4 select a+10, b+10, concat(c,'f') from t4; analyze table t3,t4; Table Op Msg_type Msg_text +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK +test.t4 analyze status Engine-independent statistics collected test.t4 analyze status OK set statement optimizer_switch='split_materialized=off' for select t3.a,t3.c,t.max,t.min from t3 join @@ -15559,8 +15563,11 @@ insert into t4 select a+100, b+100, concat(c,'g') from t4; insert into t4 select a+1000, b+1000, concat(c,'h') from t4; analyze table t2,t3,t4; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK +test.t4 analyze status Engine-independent statistics collected test.t4 analyze status OK set statement optimizer_switch='split_materialized=off' for select t2.a,t2.b,t2.c,t.c as t_c,t.max,t.min from t2, t3, (select c, max(b) max, min(b) min from t4 group by c) t @@ -15581,9 +15588,9 @@ from t2, t3, (select c, max(b) max, min(b) min from t4 group by c) t where t2.b between 80 and 85 and t2.c in ('y','z') and t2.a=t3.a and t3.c=t.c; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 range idx idx 133 NULL 2 100.00 Using index condition; Using where -1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 2 100.00 Using where +1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 1 100.00 Using where 1 PRIMARY <derived2> ref key0 key0 128 test.t3.c 2 100.00 -2 LATERAL DERIVED t4 ref idx_c idx_c 128 test.t3.c 3 100.00 +2 LATERAL DERIVED t4 ref idx_c idx_c 128 test.t3.c 2 100.00 Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`t`.`c` AS `t_c`,`t`.`max` AS `max`,`t`.`min` AS `min` from `test`.`t2` join `test`.`t3` join (/* select#2 */ select `test`.`t4`.`c` AS `c`,max(`test`.`t4`.`b`) AS `max`,min(`test`.`t4`.`b`) AS `min` from `test`.`t4` where `test`.`t4`.`c` = `test`.`t3`.`c` group by `test`.`t4`.`c`) `t` where `test`.`t3`.`a` = `test`.`t2`.`a` and `t`.`c` = `test`.`t3`.`c` and `test`.`t2`.`b` between 80 and 85 and `test`.`t2`.`c` in ('y','z') explain format=json select t2.a,t2.b,t2.c,t.c as t_c,t.max,t.min @@ -15613,7 +15620,7 @@ EXPLAIN "key_length": "5", "used_key_parts": ["a"], "ref": ["test.t2.a"], - "rows": 2, + "rows": 1, "filtered": 100, "attached_condition": "t3.c is not null" }, @@ -15639,7 +15646,7 @@ EXPLAIN "key_length": "128", "used_key_parts": ["c"], "ref": ["test.t3.c"], - "rows": 3, + "rows": 2, "filtered": 100 } } @@ -15727,8 +15734,8 @@ explain extended select t2.a,t2.b,t2.c,t.c as t_c,t.max,t.min from t2, t3, (select c, max(b) max, min(b) min from t4 group by c) t where t2.b < 40 and t2.a=t3.a and t3.c=t.c; id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t2 ALL NULL NULL NULL NULL 90 100.00 Using where -1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 2 100.00 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 90 33.33 Using where +1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 1 100.00 Using where 1 PRIMARY <derived2> ref key0 key0 128 test.t3.c 10 100.00 2 DERIVED t4 ALL idx_c NULL NULL NULL 160 100.00 Using temporary; Using filesort Warnings: @@ -15744,7 +15751,7 @@ EXPLAIN "table_name": "t2", "access_type": "ALL", "rows": 90, - "filtered": 100, + "filtered": 33.333, "attached_condition": "t2.b < 40 and t2.a is not null" }, "table": { @@ -15755,7 +15762,7 @@ EXPLAIN "key_length": "5", "used_key_parts": ["a"], "ref": ["test.t2.a"], - "rows": 2, + "rows": 1, "filtered": 100, "attached_condition": "t3.c is not null" }, @@ -15828,9 +15835,9 @@ from t2, t3, (select c, b, sum(b) over (partition by c) from t4 ) t where t2.b between 80 and 85 and t2.c in ('y','z') and t2.a=t3.a and t3.c=t.c; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 range idx idx 133 NULL 2 100.00 Using index condition; Using where -1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 2 100.00 Using where +1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 1 100.00 Using where 1 PRIMARY <derived2> ref key0 key0 128 test.t3.c 2 100.00 -2 LATERAL DERIVED t4 ref idx_c idx_c 128 test.t3.c 3 100.00 Using temporary +2 LATERAL DERIVED t4 ref idx_c idx_c 128 test.t3.c 2 100.00 Using temporary Warnings: Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`t`.`c` AS `c`,`t`.`b` AS `b`,`t`.`sum(b) over (partition by c)` AS `sum(b) over (partition by c)` from `test`.`t2` join `test`.`t3` join (/* select#2 */ select `test`.`t4`.`c` AS `c`,`test`.`t4`.`b` AS `b`,sum(`test`.`t4`.`b`) over ( partition by `test`.`t4`.`c`) AS `sum(b) over (partition by c)` from `test`.`t4` where `test`.`t4`.`c` = `test`.`t3`.`c`) `t` where `test`.`t3`.`a` = `test`.`t2`.`a` and `t`.`c` = `test`.`t3`.`c` and `test`.`t2`.`b` between 80 and 85 and `test`.`t2`.`c` in ('y','z') explain format=json select * @@ -15860,7 +15867,7 @@ EXPLAIN "key_length": "5", "used_key_parts": ["a"], "ref": ["test.t2.a"], - "rows": 2, + "rows": 1, "filtered": 100, "attached_condition": "t3.c is not null" }, @@ -15893,7 +15900,7 @@ EXPLAIN "key_length": "128", "used_key_parts": ["c"], "ref": ["test.t3.c"], - "rows": 3, + "rows": 2, "filtered": 100 } } @@ -16223,8 +16230,8 @@ explain extended select * from t2, t3, (select c, b, sum(b) over (partition by c) from t4 ) t where t2.b < 40 and t2.a=t3.a and t3.c=t.c; id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t2 ALL NULL NULL NULL NULL 90 100.00 Using where -1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 2 100.00 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 90 33.33 Using where +1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 1 100.00 Using where 1 PRIMARY <derived2> ref key0 key0 128 test.t3.c 10 100.00 2 DERIVED t4 ALL idx_c NULL NULL NULL 160 100.00 Using temporary Warnings: @@ -16240,7 +16247,7 @@ EXPLAIN "table_name": "t2", "access_type": "ALL", "rows": 90, - "filtered": 100, + "filtered": 33.333, "attached_condition": "t2.b < 40 and t2.a is not null" }, "table": { @@ -16251,7 +16258,7 @@ EXPLAIN "key_length": "5", "used_key_parts": ["a"], "ref": ["test.t2.a"], - "rows": 2, + "rows": 1, "filtered": 100, "attached_condition": "t3.c is not null" }, @@ -16307,9 +16314,13 @@ INSERT INTO t4 VALUES (5,'zzz'),(9,'xyz'),(2,'yxz'),(5,'zxy'),(7,'zyx') ; ANALYZE TABLE t1,t2,t3,t4; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK +test.t4 analyze status Engine-independent statistics collected test.t4 analyze status OK CREATE VIEW v1 AS SELECT c FROM t3 @@ -16621,7 +16632,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 DERIVED a2 eq_ref PRIMARY PRIMARY 4 a1.f 1 100.00 Using index 4 DERIVED t1 index PRIMARY PRIMARY 4 NULL 7 100.00 Using index; Using temporary; Using filesort Warnings: -Note 1003 /* select#1 */ select `s`.`f` AS `f`,`s`.`c` AS `c` from (/* select#2 */ select straight_join `a2`.`f` AS `f`,count(0) AS `c` from ((/* select#4 */ select `test`.`t1`.`f` AS `f`,count(0) AS `c` from `test`.`t1` group by `test`.`t1`.`f`)) `a1` join `test`.`t1` `a2` where `a2`.`f` = `a1`.`f` group by `a2`.`f`) `s` +Note 1003 /* select#1 */ select `s`.`f` AS `f`,`s`.`c` AS `c` from (/* select#2 */ select straight_join `a2`.`f` AS `f`,count(0) AS `c` from (/* select#4 */ select `test`.`t1`.`f` AS `f`,count(0) AS `c` from `test`.`t1` group by `test`.`t1`.`f`) `a1` join `test`.`t1` `a2` where `a2`.`f` = `a1`.`f` group by `a2`.`f`) `s` SELECT * FROM ( SELECT STRAIGHT_JOIN f, COUNT(*) as c FROM v1 GROUP BY f ) AS s; f c 1 1 @@ -16651,8 +16662,11 @@ INSERT INTO t3 VALUES (3), (4), (1), (8), (3); ANALYZE tables t1,t2,t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK SELECT * FROM t3, @@ -16682,7 +16696,7 @@ WHERE t3.d = dt.b; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 5 100.00 Using where 1 PRIMARY <derived2> ref key0 key0 5 test.t3.d 2 100.00 -2 LATERAL DERIVED t1 ref idx_b idx_b 5 test.t3.d 2 100.00 Using index; Using temporary; Using filesort +2 LATERAL DERIVED t1 ref idx_b idx_b 5 test.t3.d 1 100.00 Using index; Using temporary; Using filesort 2 LATERAL DERIVED t2 ALL NULL NULL NULL NULL 5 100.00 Using join buffer (flat, BNL join) Warnings: Note 1003 /* select#1 */ select `test`.`t3`.`d` AS `d`,`dt`.`b` AS `b`,`dt`.`c` AS `c` from `test`.`t3` join (/* select#2 */ select `test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`b` = `test`.`t3`.`d` group by `test`.`t1`.`b`,`test`.`t2`.`c`) `dt` where `dt`.`b` = `test`.`t3`.`d` diff --git a/mysql-test/main/derived_split_innodb.result b/mysql-test/main/derived_split_innodb.result index 21dbd494e4b..5073aa84c13 100644 --- a/mysql-test/main/derived_split_innodb.result +++ b/mysql-test/main/derived_split_innodb.result @@ -11,6 +11,7 @@ KEY n1_c1_n2 (n1,c1,n2) INSERT INTO t1 VALUES (0, 2, 'a'), (1, 3, 'a'); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN SELECT t1.n1 FROM t1, (SELECT n1, n2 FROM t1 WHERE c1 = 'a' GROUP BY n1) as t WHERE t.n1 = t1.n1 AND t.n2 = t1.n2 AND c1 = 'a' GROUP BY n1; diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result index 86dd73f5733..45de32d1ee1 100644 --- a/mysql-test/main/derived_view.result +++ b/mysql-test/main/derived_view.result @@ -2939,21 +2939,23 @@ insert into t2 select b+10 from t2; insert into t2 select b+10 from t2; analyze table t1,t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK explain select a from t1 where a in (select b from t2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where -1 PRIMARY t2 ref idx idx 5 test.t1.a 140 Using index; FirstMatch(t1) +1 PRIMARY t2 ref idx idx 5 test.t1.a 139 Using index; FirstMatch(t1) explain select * from (select a from t1 where a in (select b from t2)) t; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where -1 PRIMARY t2 ref idx idx 5 test.t1.a 140 Using index; FirstMatch(t1) +1 PRIMARY t2 ref idx idx 5 test.t1.a 139 Using index; FirstMatch(t1) create view v1 as select a from t1 where a in (select b from t2); explain select * from v1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 7 Using where -1 PRIMARY t2 ref idx idx 5 test.t1.a 140 Using index; FirstMatch(t1) +1 PRIMARY t2 ref idx idx 5 test.t1.a 139 Using index; FirstMatch(t1) drop view v1; drop table t1,t2; # diff --git a/mysql-test/main/disabled.def b/mysql-test/main/disabled.def index b489139a59f..86bd3a14492 100644 --- a/mysql-test/main/disabled.def +++ b/mysql-test/main/disabled.def @@ -21,3 +21,6 @@ innodb-wl5522-debug-zip : broken upstream innodb_bug12902967 : broken upstream file_contents : MDEV-6526 these files are not installed anymore max_statement_time : cannot possibly work, depends on timing +mysqlcheck : special tables like proxy , host specific to a system are shown +flush_read_lock : special tables like proxy , host specific to a system are shown +join_cache : enable after MDEV-17752 is fixed diff --git a/mysql-test/main/distinct.result b/mysql-test/main/distinct.result index 237638468fa..8fcc45e740a 100644 --- a/mysql-test/main/distinct.result +++ b/mysql-test/main/distinct.result @@ -173,9 +173,9 @@ INSERT INTO t2 values (1),(2),(3); INSERT INTO t3 VALUES (1,'1'),(2,'2'),(1,'1'),(2,'2'); explain SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 4 Using where; Using temporary +1 SIMPLE t2 index a a 4 NULL 5 Using index; Using temporary +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where 1 SIMPLE t3 ref a a 5 test.t1.b 2 Using index -1 SIMPLE t2 index a a 4 NULL 5 Using where; Using index; Using join buffer (flat, BNL join) SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a; a 1 @@ -1061,7 +1061,7 @@ UNION ( SELECT DISTINCT 1 FROM t1 ORDER BY BENCHMARK(1, MIN(pk)) ); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL PRIMARY 4 NULL 2 Using index; Using temporary -2 UNION t1 index NULL PRIMARY 4 NULL 2 Using index; Using temporary +2 UNCACHEABLE UNION t1 index NULL PRIMARY 4 NULL 2 Using index; Using temporary NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL ( SELECT DISTINCT 1 FROM t1 ORDER BY BENCHMARK(1, MIN(pk)) ) UNION diff --git a/mysql-test/main/drop.test b/mysql-test/main/drop.test index 6f506dd7215..fe8d39c0d7e 100644 --- a/mysql-test/main/drop.test +++ b/mysql-test/main/drop.test @@ -190,28 +190,28 @@ CREATE DATABASE mysql_test; let $MYSQLD_DATADIR= `select @@datadir`; --let $proc_frm = $MYSQLD_DATADIR/mysql/proc.frm ---let $proc_MYD = $MYSQLD_DATADIR/mysql/proc.MYD ---let $proc_MYI = $MYSQLD_DATADIR/mysql/proc.MYI +--let $proc_MAD = $MYSQLD_DATADIR/mysql/proc.MAD +--let $proc_MAI = $MYSQLD_DATADIR/mysql/proc.MAI --let $copy_of_proc_frm = $MYSQLTEST_VARDIR/tmp/bug29958.copy.frm ---let $copy_of_proc_MYD = $MYSQLTEST_VARDIR/tmp/bug29958.copy.MYD ---let $copy_of_proc_MYI = $MYSQLTEST_VARDIR/tmp/bug29958.copy.MYI +--let $copy_of_proc_MAD = $MYSQLTEST_VARDIR/tmp/bug29958.copy.MAD +--let $copy_of_proc_MAI = $MYSQLTEST_VARDIR/tmp/bug29958.copy.MAI --copy_file $proc_frm $copy_of_proc_frm ---copy_file $proc_MYD $copy_of_proc_MYD ---copy_file $proc_MYI $copy_of_proc_MYI +--copy_file $proc_MAD $copy_of_proc_MAD +--copy_file $proc_MAI $copy_of_proc_MAI DROP TABLE mysql.proc; DROP DATABASE mysql_test; --copy_file $copy_of_proc_frm $proc_frm ---copy_file $copy_of_proc_MYD $proc_MYD ---copy_file $copy_of_proc_MYI $proc_MYI +--copy_file $copy_of_proc_MAD $proc_MAD +--copy_file $copy_of_proc_MAI $proc_MAI --remove_file $copy_of_proc_frm ---remove_file $copy_of_proc_MYD ---remove_file $copy_of_proc_MYI +--remove_file $copy_of_proc_MAD +--remove_file $copy_of_proc_MAI --echo --echo # -- diff --git a/mysql-test/main/dyncol.result b/mysql-test/main/dyncol.result index 7a5eeac67cc..cc9a94e74be 100644 --- a/mysql-test/main/dyncol.result +++ b/mysql-test/main/dyncol.result @@ -1028,12 +1028,12 @@ select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as tim column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time) NULL Warnings: -Warning 1292 Truncated incorrect time value: '2011-02-32 8:46:06.23434' +Warning 1292 Incorrect time value: '2011-02-32 8:46:06.23434' select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as time); column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as time) NULL Warnings: -Warning 1292 Truncated incorrect time value: '2011-13-01 8:46:06.23434' +Warning 1292 Incorrect time value: '2011-13-01 8:46:06.23434' select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as time); column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as time) 08:46:06 diff --git a/mysql-test/main/empty_user_table.result b/mysql-test/main/empty_user_table.result index 54a7fd4907b..924e4cd8ea5 100644 --- a/mysql-test/main/empty_user_table.result +++ b/mysql-test/main/empty_user_table.result @@ -1,9 +1,14 @@ -create table t1 as select * from mysql.user; -truncate table mysql.user; +create table t1 as select * from mysql.global_priv; +truncate table mysql.global_priv; flush privileges; connect(localhost,u1,,test,MASTER_PORT,MASTER_SOCKET); connect fail,localhost,u1; Got one of the listed errors -insert mysql.user select * from t1; +insert mysql.global_priv select * from t1; drop table t1; flush privileges; +truncate table mysql.user; +flush privileges; +connect(localhost,u1,,test,MASTER_PORT,MASTER_SOCKET); +connect fail,localhost,u1; +Got one of the listed errors diff --git a/mysql-test/main/empty_user_table.test b/mysql-test/main/empty_user_table.test index b54f2109e30..8a544fece83 100644 --- a/mysql-test/main/empty_user_table.test +++ b/mysql-test/main/empty_user_table.test @@ -4,8 +4,8 @@ source include/not_embedded.inc; -create table t1 as select * from mysql.user; -truncate table mysql.user; +create table t1 as select * from mysql.global_priv; +truncate table mysql.global_priv; flush privileges; # connecting via unix socket gives ER_ACCESS_DENIED_ERROR @@ -14,7 +14,23 @@ flush privileges; --error ER_ACCESS_DENIED_ERROR,ER_HOST_NOT_PRIVILEGED connect (fail,localhost,u1); -insert mysql.user select * from t1; +insert mysql.global_priv select * from t1; drop table t1; flush privileges; +# +# same with mysql.user +# + +source include/switch_to_mysql_user.inc; +truncate table mysql.user; + +flush privileges; + +# connecting via unix socket gives ER_ACCESS_DENIED_ERROR +# connecting via tcp/ip gives ER_HOST_NOT_PRIVILEGED +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error ER_ACCESS_DENIED_ERROR,ER_HOST_NOT_PRIVILEGED +connect (fail,localhost,u1); + +source include/switch_to_mysql_global_priv.inc; diff --git a/mysql-test/main/except.result b/mysql-test/main/except.result index 594bb7118eb..b9959a3f520 100644 --- a/mysql-test/main/except.result +++ b/mysql-test/main/except.result @@ -24,7 +24,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 3 EXCEPT t2 ALL NULL NULL NULL NULL 2 100.00 NULL EXCEPT RESULT <except2,3> ALL NULL NULL NULL NULL NULL NULL Warnings: -Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`)) `a` +Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`)) `a` EXPLAIN format=json (select a,b from t1) except (select c,d from t2); EXPLAIN { @@ -229,7 +229,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 3 EXCEPT t4 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join) NULL EXCEPT RESULT <except2,3> ALL NULL NULL NULL NULL NULL NULL Warnings: -Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b`,`a`.`e` AS `e`,`a`.`f` AS `f` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t1` join `test`.`t3`) except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t4`.`g` AS `g`,`test`.`t4`.`h` AS `h` from `test`.`t2` join `test`.`t4`)) `a` +Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b`,`a`.`e` AS `e`,`a`.`f` AS `f` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t1` join `test`.`t3` except (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t4`.`g` AS `g`,`test`.`t4`.`h` AS `h` from `test`.`t2` join `test`.`t4`)) `a` EXPLAIN format=json (select a,b,e,f from t1,t3) except (select c,d,g,h from t2,t4); EXPLAIN { @@ -500,7 +500,7 @@ a (select 1 from dual) except (select 1 from dual); 1 (select 1 from dual into @v) except (select 1 from dual); -ERROR HY000: Incorrect usage of EXCEPT and INTO +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'into @v) except (select 1 from dual)' at line 1 select 1 from dual ORDER BY 1 except select 1 from dual; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'except select 1 from dual' at line 1 select 1 as a from dual union all select 1 from dual; @@ -508,7 +508,7 @@ a 1 1 select 1 from dual except all select 1 from dual; -ERROR HY000: Incorrect usage of EXCEPT and ALL +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'all select 1 from dual' at line 1 create table t1 (a int, b blob, a1 int, b1 blob) engine=MyISAM; create table t2 (c int, d blob, c1 int, d1 blob) engine=MyISAM; insert into t1 values (1,"ddd", 1, "sdfrrwwww"),(2, "fgh", 2, "dffggtt"); diff --git a/mysql-test/main/except.test b/mysql-test/main/except.test index f88d9b29e35..32aa0b90544 100644 --- a/mysql-test/main/except.test +++ b/mysql-test/main/except.test @@ -60,13 +60,13 @@ drop tables t1,t2,t3,t4; select 1 as a from dual except select 1 from dual; (select 1 from dual) except (select 1 from dual); ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR (select 1 from dual into @v) except (select 1 from dual); --error ER_PARSE_ERROR select 1 from dual ORDER BY 1 except select 1 from dual; select 1 as a from dual union all select 1 from dual; ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR select 1 from dual except all select 1 from dual; diff --git a/mysql-test/main/explain_json.result b/mysql-test/main/explain_json.result index ef6b70aff71..3ca3ac200af 100644 --- a/mysql-test/main/explain_json.result +++ b/mysql-test/main/explain_json.result @@ -1029,6 +1029,7 @@ create index idx_t1_1 on t1 (a1,a2,b,c); create index idx_t1_2 on t1 (a1,a2,b); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a'); id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/main/explain_non_select.result b/mysql-test/main/explain_non_select.result index 5a6b9f841c2..51414d0c196 100644 --- a/mysql-test/main/explain_non_select.result +++ b/mysql-test/main/explain_non_select.result @@ -229,7 +229,7 @@ INSERT INTO t1 VALUES (1),(2); EXPLAIN UPDATE v1, mysql.user SET v1.a = v1.a + 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 -1 SIMPLE user index NULL PRIMARY 420 NULL 4 Using index +1 SIMPLE global_priv index NULL PRIMARY 420 NULL 4 Using index DROP TABLE t1; DROP VIEW v1; # diff --git a/mysql-test/main/failed_auth_3909.result b/mysql-test/main/failed_auth_3909.result index d0fd2c41221..19951415585 100644 --- a/mysql-test/main/failed_auth_3909.result +++ b/mysql-test/main/failed_auth_3909.result @@ -1,24 +1,17 @@ -optimize table mysql.user; -Table Op Msg_type Msg_text -mysql.user optimize status OK -insert ignore mysql.user (user,plugin) values ('foo','bar'),('bar','bar'),('baz','bar'); -Warnings: -Warning 1364 Field 'ssl_cipher' doesn't have a default value -Warning 1364 Field 'x509_issuer' doesn't have a default value -Warning 1364 Field 'x509_subject' doesn't have a default value -Warning 1364 Field 'authentication_string' doesn't have a default value -flush privileges; +create user foo identified via mysql_old_password; +create user bar identified via mysql_old_password; +create user baz identified via mysql_old_password; connect(localhost,u1,,test,MASTER_PORT,MASTER_SOCKET); connect fail,localhost,u1; -ERROR HY000: Plugin 'bar' is not loaded +ERROR 28000: Access denied for user 'u1'@'localhost' (using password: NO) connect(localhost,u2,,test,MASTER_PORT,MASTER_SOCKET); connect fail,localhost,u2; -ERROR 28000: Access denied for user 'u2'@'localhost' (using password: NO) +ERROR HY000: Server is running in --secure-auth mode, but 'u2'@'localhost' has a password in the old format; please change the password to the new format connect(localhost,u2,password,test,MASTER_PORT,MASTER_SOCKET); connect fail,localhost,u2,password; -ERROR 28000: Access denied for user 'u2'@'localhost' (using password: YES) -ERROR HY000: Plugin 'bar' is not loaded -ERROR 28000: Access denied for user 'u2'@'localhost' (using password: NO) -ERROR 28000: Access denied for user 'u2'@'localhost' (using password: YES) -delete from mysql.user where plugin = 'bar'; +ERROR HY000: Server is running in --secure-auth mode, but 'u2'@'localhost' has a password in the old format; please change the password to the new format +ERROR 28000: Access denied for user 'u1'@'localhost' (using password: NO) +ERROR HY000: Server is running in --secure-auth mode, but 'u2'@'localhost' has a password in the old format; please change the password to the new format +ERROR HY000: Server is running in --secure-auth mode, but 'u2'@'localhost' has a password in the old format; please change the password to the new format +delete from mysql.user where plugin = 'mysql_old_password'; flush privileges; diff --git a/mysql-test/main/failed_auth_3909.test b/mysql-test/main/failed_auth_3909.test index f72460691ea..25e45e49a0e 100644 --- a/mysql-test/main/failed_auth_3909.test +++ b/mysql-test/main/failed_auth_3909.test @@ -6,32 +6,32 @@ source include/not_embedded.inc; # verify that for some failed login attemps (with wrong user names) # the server requests a plugin # -optimize table mysql.user; -insert ignore mysql.user (user,plugin) values ('foo','bar'),('bar','bar'),('baz','bar'); -flush privileges; +create user foo identified via mysql_old_password; +create user bar identified via mysql_old_password; +create user baz identified via mysql_old_password; --replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT ---error ER_PLUGIN_IS_NOT_LOADED +--error ER_ACCESS_DENIED_ERROR connect (fail,localhost,u1); --replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT ---error ER_ACCESS_DENIED_ERROR +--error ER_SERVER_IS_IN_SECURE_AUTH_MODE connect (fail,localhost,u2); --replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT ---error ER_ACCESS_DENIED_ERROR +--error ER_SERVER_IS_IN_SECURE_AUTH_MODE connect (fail,localhost,u2,password); ---error ER_PLUGIN_IS_NOT_LOADED +--error ER_ACCESS_DENIED_ERROR change_user u1; ---error ER_ACCESS_DENIED_ERROR +--error ER_SERVER_IS_IN_SECURE_AUTH_MODE change_user u2; ---error ER_ACCESS_DENIED_ERROR +--error ER_SERVER_IS_IN_SECURE_AUTH_MODE change_user u2,password; -delete from mysql.user where plugin = 'bar'; +delete from mysql.user where plugin = 'mysql_old_password'; flush privileges; diff --git a/mysql-test/main/failed_auth_unixsocket.result b/mysql-test/main/failed_auth_unixsocket.result index 680d3b48a33..b2081c9ba84 100644 --- a/mysql-test/main/failed_auth_unixsocket.result +++ b/mysql-test/main/failed_auth_unixsocket.result @@ -1,13 +1,18 @@ -update mysql.user set plugin='unix_socket'; +update mysql.global_priv set priv=json_insert(priv, '$.plugin', 'unix_socket'); flush privileges; +Warnings: +Warning 1524 Plugin 'unix_socket' is not loaded +Warning 1524 Plugin 'unix_socket' is not loaded +Warning 1524 Plugin 'unix_socket' is not loaded +Warning 1524 Plugin 'unix_socket' is not loaded connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); -connect fail,localhost,$USER; -ERROR HY000: Plugin 'unix_socket' is not loaded -ERROR HY000: Plugin 'unix_socket' is not loaded +ERROR 28000: Access denied for user 'USER'@'localhost' (using password: NO) +ERROR 28000: Access denied for user 'USER'@'localhost' (using password: NO) install plugin unix_socket soname 'auth_socket.so'; +flush privileges; connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); ERROR 28000: Access denied for user 'USER'@'localhost' ERROR 28000: Access denied for user 'USER'@'localhost' -update mysql.user set plugin=''; +update mysql.global_priv set priv=json_remove(priv, '$.plugin'); flush privileges; uninstall plugin unix_socket; diff --git a/mysql-test/main/failed_auth_unixsocket.test b/mysql-test/main/failed_auth_unixsocket.test index f7345f44698..179e561e9ed 100644 --- a/mysql-test/main/failed_auth_unixsocket.test +++ b/mysql-test/main/failed_auth_unixsocket.test @@ -4,23 +4,29 @@ # MDEV-3909 remote user enumeration # unix_socket tests # -update mysql.user set plugin='unix_socket'; +update mysql.global_priv set priv=json_insert(priv, '$.plugin', 'unix_socket'); flush privileges; ---replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT $USER USER ---error ER_PLUGIN_IS_NOT_LOADED +# Make sure that the replace works, even if $USER is 'user' or something else +# that matches other parts of the error message. +let $replace=Access denied for user '$USER'; + +--echo connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); +--replace_result $replace "Access denied for user 'USER'" +--disable_query_log +--error ER_ACCESS_DENIED_ERROR connect (fail,localhost,$USER); +--enable_query_log ---error ER_PLUGIN_IS_NOT_LOADED +--replace_result $replace "Access denied for user 'USER'" +--error ER_ACCESS_DENIED_ERROR change_user $USER; eval install plugin unix_socket soname '$AUTH_SOCKET_SO'; +flush privileges; -# Make sure that the replace works, even if $USER is 'user' or something else -# that matches other parts of the error message. --echo connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); ---let $replace=Access denied for user '$USER' ---replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT $replace "Access denied for user 'USER'" +--replace_result $replace "Access denied for user 'USER'" --disable_query_log --error ER_ACCESS_DENIED_NO_PASSWORD_ERROR connect (fail,localhost,$USER); @@ -30,7 +36,7 @@ connect (fail,localhost,$USER); --error ER_ACCESS_DENIED_NO_PASSWORD_ERROR change_user $USER; -update mysql.user set plugin=''; +update mysql.global_priv set priv=json_remove(priv, '$.plugin'); flush privileges; uninstall plugin unix_socket; diff --git a/mysql-test/main/flush.result b/mysql-test/main/flush.result index af8e327657b..8149ce29dec 100644 --- a/mysql-test/main/flush.result +++ b/mysql-test/main/flush.result @@ -364,16 +364,19 @@ flush table t1; connection default; # Let flush table sync in. select * from t1; +a connection con1; select * from t1; a unlock tables; +connection default; +select count(*) from information_schema.processlist where state = "Waiting for table metadata lock"; +count(*) +1 +commit; connection con2; # Reaping 'flush table t1'... connection default; -# Reaping 'select * from t1'... -a -commit; # # Repeat the same test but with FLUSH TABLES # @@ -386,13 +389,10 @@ connection con1; # lock table t1 read; connection con2; -# -# FLUSH TABLES expels the table definition from the cache. -# Sending 'flush tables'... flush tables; connection default; -# Let flush table sync in. select * from t1; +a connection con1; select * from t1; a @@ -400,8 +400,6 @@ unlock tables; connection con2; # Reaping 'flush tables'... connection default; -# Reaping 'select * from t1'... -a commit; # Cleanup connection con1; @@ -472,10 +470,7 @@ create table t1 (i int); create table t2 (i int); handler t1 open; connection con1; -# Sending: flush tables with read lock; -connection con2; -# Wait until FTWRL starts waiting for 't1' to be closed. connection default; # The below statement should not cause deadlock. # Sending: @@ -483,8 +478,6 @@ insert into t2 values (1); connection con2; # Wait until INSERT starts to wait for FTWRL to go away. connection con1; -# FTWRL should be able to continue now. -# Reap FTWRL. unlock tables; connection default; # Reap INSERT. diff --git a/mysql-test/main/flush.test b/mysql-test/main/flush.test index 51b5c48c137..17f9241a122 100644 --- a/mysql-test/main/flush.test +++ b/mysql-test/main/flush.test @@ -449,24 +449,20 @@ connection default; --echo # Let flush table sync in. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" + where state = "Waiting for table metadata lock" and info = "flush table t1"; --source include/wait_condition.inc -send select * from t1; +select * from t1; connection con1; -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" - and info = "select * from t1"; select * from t1; unlock tables; +connection default; +select count(*) from information_schema.processlist where state = "Waiting for table metadata lock"; +commit; connection con2; --echo # Reaping 'flush table t1'... reap; connection default; ---echo # Reaping 'select * from t1'... -reap; -commit; --echo # --echo # Repeat the same test but with FLUSH TABLES @@ -480,31 +476,16 @@ connection con1; --echo # lock table t1 read; connection con2; ---echo # ---echo # FLUSH TABLES expels the table definition from the cache. ---echo # Sending 'flush tables'... send flush tables; connection default; ---echo # Let flush table sync in. -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" - and info = "flush tables"; ---source include/wait_condition.inc -send select * from t1; +select * from t1; connection con1; -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" - and info = "select * from t1"; select * from t1; unlock tables; connection con2; --echo # Reaping 'flush tables'... reap; connection default; ---echo # Reaping 'select * from t1'... -reap; commit; --echo # Cleanup @@ -566,17 +547,7 @@ create table t2 (i int); handler t1 open; connection con1; ---echo # Sending: ---send flush tables with read lock - -connection con2; ---echo # Wait until FTWRL starts waiting for 't1' to be closed. -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" - and info = "flush tables with read lock"; ---source include/wait_condition.inc - +flush tables with read lock; connection default; --echo # The below statement should not cause deadlock. --echo # Sending: @@ -586,14 +557,11 @@ connection con2; --echo # Wait until INSERT starts to wait for FTWRL to go away. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" + where state = "Waiting for backup lock" and info = "insert into t2 values (1)"; --source include/wait_condition.inc connection con1; ---echo # FTWRL should be able to continue now. ---echo # Reap FTWRL. ---reap unlock tables; connection default; diff --git a/mysql-test/main/flush_block_commit.test b/mysql-test/main/flush_block_commit.test index 6a6120ce63f..0280aedf2ca 100644 --- a/mysql-test/main/flush_block_commit.test +++ b/mysql-test/main/flush_block_commit.test @@ -32,7 +32,7 @@ connection con2; --echo # Wait until COMMIT gets blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" and info = "COMMIT"; + where state = "Waiting for backup lock" and info = "COMMIT"; --source include/wait_condition.inc --echo # Verify that 'con1' was blocked and data did not move. SELECT * FROM t1; diff --git a/mysql-test/main/flush_block_commit_notembedded.test b/mysql-test/main/flush_block_commit_notembedded.test index 3d894c5f16c..5be9e50e58b 100644 --- a/mysql-test/main/flush_block_commit_notembedded.test +++ b/mysql-test/main/flush_block_commit_notembedded.test @@ -46,7 +46,7 @@ begin; connection con1; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "insert into t1 values (1)"; --source include/wait_condition.inc unlock tables; diff --git a/mysql-test/main/flush_read_lock.result b/mysql-test/main/flush_read_lock.result index 55c31ae8d12..33dc1092190 100644 --- a/mysql-test/main/flush_read_lock.result +++ b/mysql-test/main/flush_read_lock.result @@ -652,6 +652,7 @@ connection default; # 14.2) FLUSH TABLES <list> WITH READ LOCK is not blocked by # active FTWRL. But since the latter keeps tables open # FTWRL is blocked by FLUSH TABLES <list> WITH READ LOCK. +# Fixed by MDEV-5336 flush tables with read lock; # FT <list> WRL is allowed under FTWRL at the moment. # It does not make much sense though. @@ -668,12 +669,9 @@ connection default; flush tables t1_base, t2_base with read lock; connection con1; flush tables with read lock; -connection con2; -# Wait until FTWRL is blocked. connection default; unlock tables; connection con1; -# Reap FTWRL. unlock tables; connection default; # @@ -1677,3 +1675,57 @@ disconnect con1; disconnect con2; disconnect con3; set global sql_mode=default; +# +# Deadlock between FTWRL under open handler and DDL/LOCK TABLES +# +CREATE TABLE t1(a INT); +HANDLER t1 OPEN; +# +connect con1,localhost,root,,; +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL ready'; +LOCK TABLE t1 WRITE; +# +# we need to do it in a separate connection, +# because SET DEBUG_SYNC call open_tables()/mysql_ha_flush() :( +connect con2,localhost,root,,; +SET DEBUG_SYNC= 'now WAIT_FOR ready'; +disconnect con2; +# +connection default; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +HANDLER t1 CLOSE; +# +connection con1; +UNLOCK TABLES; +disconnect con1; +# +connection default; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; +# +# Make sure pending LOCK TABLES doesn't block FTWRL +# +CREATE TABLE t1(a INT); +LOCK TABLE t1 READ; +# +connect con1,localhost,root,,; +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL ready'; +LOCK TABLE t1 WRITE; +# +connect con2,localhost,root,,; +SET DEBUG_SYNC= 'now WAIT_FOR ready'; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +disconnect con2; +# +connection default; +UNLOCK TABLES; +# +connection con1; +UNLOCK TABLES; +disconnect con1; +# +connection default; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/main/flush_read_lock.test b/mysql-test/main/flush_read_lock.test index 4a9752ae9f1..f39dbecf4a9 100644 --- a/mysql-test/main/flush_read_lock.test +++ b/mysql-test/main/flush_read_lock.test @@ -259,7 +259,7 @@ connection $con_aux1; --echo # Wait until COMMIT is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" and + where state = "Waiting for backup lock" and info = "commit"; --source include/wait_condition.inc unlock tables; @@ -281,7 +281,7 @@ connection $con_aux2; --echo # Wait until FTWRL is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" and + where state = "Waiting for backup lock" and info = "flush tables with read lock"; --source include/wait_condition.inc set debug_sync='now SIGNAL go'; @@ -565,7 +565,7 @@ connection $con_aux1; --echo # Check that EXECUTE is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "insert into t1_base values (1)"; --source include/wait_condition.inc unlock tables; @@ -582,7 +582,7 @@ connection $con_aux2; --echo # Wait until FTWRL is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "flush tables with read lock"; --source include/wait_condition.inc set debug_sync='now SIGNAL go'; @@ -800,6 +800,8 @@ connection default; --echo # 14.2) FLUSH TABLES <list> WITH READ LOCK is not blocked by --echo # active FTWRL. But since the latter keeps tables open --echo # FTWRL is blocked by FLUSH TABLES <list> WITH READ LOCK. +--echo # Fixed by MDEV-5336 + flush tables with read lock; --echo # FT <list> WRL is allowed under FTWRL at the moment. --echo # It does not make much sense though. @@ -815,19 +817,10 @@ unlock tables; connection default; flush tables t1_base, t2_base with read lock; connection $con_aux1; ---send flush tables with read lock -connection $con_aux2; ---echo # Wait until FTWRL is blocked. -let $wait_condition= - select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" and - info = "flush tables with read lock"; ---source include/wait_condition.inc +flush tables with read lock; connection default; unlock tables; connection $con_aux1; ---echo # Reap FTWRL. ---reap unlock tables; connection default; @@ -1018,7 +1011,7 @@ connection $con_aux1; --echo # Check that LOCK TABLES WRITE is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "lock tables t1_base write"; --source include/wait_condition.inc unlock tables; @@ -1062,7 +1055,7 @@ connection $con_aux1; --echo # Check that OPTIMIZE TABLE is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "optimize table t1_base"; --source include/wait_condition.inc unlock tables; @@ -1228,7 +1221,7 @@ connection $con_aux1; --echo # Check that REPAIR TABLE is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "repair table t1_base"; --source include/wait_condition.inc unlock tables; @@ -1427,7 +1420,7 @@ connection $con_aux1; --echo # Wait until SET AUTOCOMMIT=1 is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" and + where state = "Waiting for backup lock" and info = "set autocommit= 1"; --source include/wait_condition.inc unlock tables; @@ -1449,7 +1442,7 @@ connection $con_aux2; --echo # Wait until FTWRL is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" and + where state = "Waiting for backup lock" and info = "flush tables with read lock"; --source include/wait_condition.inc set debug_sync='now SIGNAL go'; @@ -1628,7 +1621,7 @@ connection $con_aux1; --echo # Wait until XA COMMIT is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" and + where state = "Waiting for backup lock" and info = "xa commit 'test1'"; --source include/wait_condition.inc unlock tables; @@ -1652,7 +1645,7 @@ connection $con_aux2; --echo # Wait until FTWRL is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" and + where state = "Waiting for backup lock" and info = "flush tables with read lock"; --source include/wait_condition.inc set debug_sync='now SIGNAL go'; @@ -1731,7 +1724,7 @@ connection $con_aux1; --echo # Check that ANALYZE TABLE is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" and + where state = "Waiting for backup lock" and info = "analyze table t3_trans"; --source include/wait_condition.inc unlock tables; @@ -1806,7 +1799,7 @@ connection $con_aux1; --echo # Check that CHECK TABLE is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" and + where state = "Waiting for backup lock" and info = "check table t1_base"; --source include/wait_condition.inc unlock tables; @@ -1824,7 +1817,7 @@ connection $con_aux1; --echo # Check that ALTER TABLE is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" and + where state = "Waiting for backup lock" and info = "alter table t1_temp add column c1 int"; --source include/wait_condition.inc unlock tables; @@ -1877,7 +1870,7 @@ connection $con_aux2; --echo # Wait until FTWRL is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "flush tables with read lock"; --source include/wait_condition.inc --echo # Try to run another INSERT and see that it is blocked. @@ -1886,7 +1879,7 @@ connection con3; --echo # Wait until new INSERT is blocked. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "insert into t2_base values (1)"; --echo # Unblock INSERT in the first connection. set debug_sync='now SIGNAL go'; @@ -2022,3 +2015,73 @@ set global sql_mode=default; # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc + + +--echo # +--echo # Deadlock between FTWRL under open handler and DDL/LOCK TABLES +--echo # +CREATE TABLE t1(a INT); +HANDLER t1 OPEN; + +--echo # +connect (con1,localhost,root,,); +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL ready'; +--send LOCK TABLE t1 WRITE + +--echo # +--echo # we need to do it in a separate connection, +--echo # because SET DEBUG_SYNC call open_tables()/mysql_ha_flush() :( +connect (con2,localhost,root,,); +SET DEBUG_SYNC= 'now WAIT_FOR ready'; +disconnect con2; + +--echo # +connection default; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +HANDLER t1 CLOSE; + +--echo # +connection con1; +reap; +UNLOCK TABLES; +disconnect con1; + +--echo # +connection default; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; + + +--echo # +--echo # Make sure pending LOCK TABLES doesn't block FTWRL +--echo # +CREATE TABLE t1(a INT); +LOCK TABLE t1 READ; + +--echo # +connect (con1,localhost,root,,); +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL ready'; +--send LOCK TABLE t1 WRITE + +--echo # +connect (con2,localhost,root,,); +SET DEBUG_SYNC= 'now WAIT_FOR ready'; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +disconnect con2; + +--echo # +connection default; +UNLOCK TABLES; + +--echo # +connection con1; +reap; +UNLOCK TABLES; +disconnect con1; + +--echo # +connection default; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; diff --git a/mysql-test/main/flush_read_lock_kill.test b/mysql-test/main/flush_read_lock_kill.test index d83e5b3f1df..bd3efd7bdc4 100644 --- a/mysql-test/main/flush_read_lock_kill.test +++ b/mysql-test/main/flush_read_lock_kill.test @@ -51,7 +51,7 @@ SELECT ((@id := kill_id) - kill_id) FROM t1 LIMIT 1; --echo # to active COMMIT let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for commit lock" + where state = "Waiting for backup lock" and info = "flush tables with read lock"; --source include/wait_condition.inc diff --git a/mysql-test/main/flush_ssl.result b/mysql-test/main/flush_ssl.result new file mode 100644 index 00000000000..e2941db9f95 --- /dev/null +++ b/mysql-test/main/flush_ssl.result @@ -0,0 +1,26 @@ +# Kill the server +connect ssl_con,localhost,root,,,,,SSL; +SELECT VARIABLE_VALUE INTO @ssl_not_after FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_server_not_after'; +# Use a different certificate ("Not after" certificate field changed) +FLUSH SSL; +# Check new certificate used by new connection +Result +OK +# Check that existing SSL connection still works, and uses old certificate, even if new one is loaded in FLUSH SSL +connection ssl_con; +SELECT IF(VARIABLE_VALUE=@ssl_not_after,'OK','FAIL') as Result FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_server_not_after'; +Result +OK +disconnect ssl_con; +connection default; +SELECT VARIABLE_NAME NAME, VARIABLE_VALUE VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME in ('Ssl_accepts', 'Ssl_finished_accepts'); +NAME VALUE +SSL_ACCEPTS 1 +SSL_FINISHED_ACCEPTS 1 +FLUSH SSL; +SELECT VARIABLE_NAME NAME, VARIABLE_VALUE VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME in ('Ssl_accepts', 'Ssl_finished_accepts'); +NAME VALUE +SSL_ACCEPTS 0 +SSL_FINISHED_ACCEPTS 0 +# Cleanup +# Kill the server diff --git a/mysql-test/main/flush_ssl.test b/mysql-test/main/flush_ssl.test new file mode 100644 index 00000000000..e7bd57b156a --- /dev/null +++ b/mysql-test/main/flush_ssl.test @@ -0,0 +1,61 @@ +# MDEV-16266 Reload SSL certificate +# This test reloads server SSL certs FLUSH SSL, and checks that +# 1. old SSL connections (that existed before FLUSH) still work and use old certificate +# 2. new SSL connection use new certificate +# 3. if FLUSH SSL runs into error, SSL is still functioning +# SWtatus variable Ssl_server_not_after is used to tell the old certificate from new. + + +source include/have_ssl_communication.inc; + +# Restart server with cert. files located in temp directory +# We are going to remove / replace them within the test, +# so we can't use the ones in std_data directly. + +let $ssl_cert=$MYSQLTEST_VARDIR/tmp/ssl_cert.pem; +let $ssl_key=$MYSQLTEST_VARDIR/tmp/ssl_key.pem; + +copy_file $MYSQL_TEST_DIR/std_data/server-key.pem $ssl_key; +copy_file $MYSQL_TEST_DIR/std_data/server-cert.pem $ssl_cert; + +let $restart_parameters=--ssl-key=$ssl_key --ssl-cert=$ssl_cert; +--source include/kill_mysqld.inc +--source include/start_mysqld.inc + +connect ssl_con,localhost,root,,,,,SSL; +SELECT VARIABLE_VALUE INTO @ssl_not_after FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_server_not_after'; +let $ssl_not_after=`SELECT @ssl_not_after`; + +remove_file $ssl_cert; +remove_file $ssl_key; + +--echo # Use a different certificate ("Not after" certificate field changed) +copy_file $MYSQL_TEST_DIR/std_data/server-new-key.pem $ssl_key; +copy_file $MYSQL_TEST_DIR/std_data/server-new-cert.pem $ssl_cert; + +FLUSH SSL; + +--echo # Check new certificate used by new connection +exec $MYSQL --ssl -e "SELECT IF(VARIABLE_VALUE <> '$ssl_not_after', 'OK', 'FAIL') as Result FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_server_not_after'"; + +--echo # Check that existing SSL connection still works, and uses old certificate, even if new one is loaded in FLUSH SSL +connection ssl_con; +SELECT IF(VARIABLE_VALUE=@ssl_not_after,'OK','FAIL') as Result FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='Ssl_server_not_after'; + +disconnect ssl_con; +connection default; + +SELECT VARIABLE_NAME NAME, VARIABLE_VALUE VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME in ('Ssl_accepts', 'Ssl_finished_accepts'); +FLUSH SSL; +#Check that accepts are zeroed by FLUSH SSL. +SELECT VARIABLE_NAME NAME, VARIABLE_VALUE VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME in ('Ssl_accepts', 'Ssl_finished_accepts'); + +--echo # Cleanup +remove_file $ssl_cert; +remove_file $ssl_key; +# restart with usuall SSL +let $restart_parameters=; +--source include/kill_mysqld.inc +--source include/start_mysqld.inc + + diff --git a/mysql-test/main/fulltext_order_by.result b/mysql-test/main/fulltext_order_by.result index c2f57c6f9c2..a350a55c75d 100644 --- a/mysql-test/main/fulltext_order_by.result +++ b/mysql-test/main/fulltext_order_by.result @@ -126,7 +126,7 @@ group by a.text, b.id, b.betreff order by match(b.betreff) against ('+abc' in boolean mode) desc; -ERROR 42000: Table 'b' from one of the SELECTs cannot be used in field list +ERROR 42000: Table 'b' from one of the SELECTs cannot be used in ORDER clause select a.text, b.id, b.betreff from t2 a inner join t3 b on a.id = b.forum inner join @@ -142,7 +142,7 @@ where match(c.beitrag) against ('+abc' in boolean mode) order by match(b.betreff) against ('+abc' in boolean mode) desc; -ERROR 42000: Table 'b' from one of the SELECTs cannot be used in field list +ERROR 42000: Table 'b' from one of the SELECTs cannot be used in ORDER clause select a.text, b.id, b.betreff from t2 a inner join t3 b on a.id = b.forum inner join diff --git a/mysql-test/main/func_analyse.result b/mysql-test/main/func_analyse.result index 1e78e603bca..1cb9e3c9ad8 100644 --- a/mysql-test/main/func_analyse.result +++ b/mysql-test/main/func_analyse.result @@ -153,13 +153,19 @@ End of 5.1 tests # Start of 10.2 tests # (SELECT 1 FROM DUAL PROCEDURE ANALYSE()); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE())' at line 1 +((SELECT 1 FROM DUAL PROCEDURE ANALYSE())); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE()))' at line 1 +(SELECT 1 FROM DUAL) PROCEDURE ANALYSE(); Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype 1 1 1 1 1 0 0 1.0000 0.0000 ENUM('1') NOT NULL -((SELECT 1 FROM DUAL PROCEDURE ANALYSE())); +((SELECT 1 FROM DUAL)) PROCEDURE ANALYSE(); Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype 1 1 1 1 1 0 0 1.0000 0.0000 ENUM('1') NOT NULL +create table t1 (a int); SELECT * FROM t1 UNION SELECT * FROM t1 PROCEDURE analyse(); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE analyse()' at line 1 +ERROR 42000: Incorrect usage/placement of 'PROCEDURE' +drop table t1; # # MDEV-10030 sql_yacc.yy: Split table_expression and remove PROCEDURE from create_select, select_paren_derived, select_derived2, query_specification # @@ -171,3 +177,48 @@ SELECT (SELECT 1 FROM t1 PROCEDURE ANALYSE()) FROM t2; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE()) FROM t2' at line 1 SELECT ((SELECT 1 FROM t1 PROCEDURE ANALYSE())) FROM t2; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE())) FROM t2' at line 1 +# +# Start of 10.4 tests +# +# +# MDEV-16309 Split ::create_tmp_field() into virtual methods in Item +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +BEGIN NOT ATOMIC +DECLARE rec ROW(Field_name TEXT, +Min_value TEXT, +Max_value TEXT, +Min_length TEXT, +Max_length TEXT, +Empties_or_zeros TEXT, +Nulls TEXT, +Avg_value_or_avg_length TEXT, +Std TEXT, +Optimal_fieldtype TEXT); +DECLARE c CURSOR FOR SELECT * FROM t1 PROCEDURE analyse(); +OPEN c; +FETCH c INTO rec; +CLOSE c; +SELECT rec.field_name, +rec.Min_value, rec.Max_value, +rec.Min_length, rec. Max_length, +rec.Empties_or_zeros, rec.Nulls, +rec.Avg_value_or_avg_length, rec.Std, +rec.Optimal_fieldtype; +END; +$$ +rec.field_name test.t1.a +rec.Min_value 1 +rec.Max_value 3 +rec.Min_length 1 +rec. Max_length 1 +rec.Empties_or_zeros 0 +rec.Nulls 0 +rec.Avg_value_or_avg_length 2.0000 +rec.Std 0.8165 +rec.Optimal_fieldtype ENUM('1','2','3') NOT NULL +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/func_analyse.test b/mysql-test/main/func_analyse.test index d99f5c0fa9a..3c8be90d6e2 100644 --- a/mysql-test/main/func_analyse.test +++ b/mysql-test/main/func_analyse.test @@ -161,12 +161,17 @@ DROP TABLE t1, t2; --echo # --echo # Start of 10.2 tests --echo # +--error ER_PARSE_ERROR (SELECT 1 FROM DUAL PROCEDURE ANALYSE()); +--error ER_PARSE_ERROR ((SELECT 1 FROM DUAL PROCEDURE ANALYSE())); +(SELECT 1 FROM DUAL) PROCEDURE ANALYSE(); +((SELECT 1 FROM DUAL)) PROCEDURE ANALYSE(); -# TODO: ---error ER_PARSE_ERROR +create table t1 (a int); +--error ER_CANT_USE_OPTION_HERE SELECT * FROM t1 UNION SELECT * FROM t1 PROCEDURE analyse(); +drop table t1; --echo # --echo # MDEV-10030 sql_yacc.yy: Split table_expression and remove PROCEDURE from create_select, select_paren_derived, select_derived2, query_specification @@ -181,3 +186,47 @@ SELECT * FROM t1 NATURAL JOIN (SELECT * FROM t2 PROCEDURE ANALYSE()); SELECT (SELECT 1 FROM t1 PROCEDURE ANALYSE()) FROM t2; --error ER_PARSE_ERROR SELECT ((SELECT 1 FROM t1 PROCEDURE ANALYSE())) FROM t2; + + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-16309 Split ::create_tmp_field() into virtual methods in Item +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +--vertical_results +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE rec ROW(Field_name TEXT, + Min_value TEXT, + Max_value TEXT, + Min_length TEXT, + Max_length TEXT, + Empties_or_zeros TEXT, + Nulls TEXT, + Avg_value_or_avg_length TEXT, + Std TEXT, + Optimal_fieldtype TEXT); + DECLARE c CURSOR FOR SELECT * FROM t1 PROCEDURE analyse(); + OPEN c; + FETCH c INTO rec; + CLOSE c; + SELECT rec.field_name, + rec.Min_value, rec.Max_value, + rec.Min_length, rec. Max_length, + rec.Empties_or_zeros, rec.Nulls, + rec.Avg_value_or_avg_length, rec.Std, + rec.Optimal_fieldtype; +END; +$$ +DELIMITER ;$$ +--horizontal_results +DROP TABLE t1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/func_debug.result b/mysql-test/main/func_debug.result index 7fcf522abba..c0c6e8c6a7e 100644 --- a/mysql-test/main/func_debug.result +++ b/mysql-test/main/func_debug.result @@ -1655,3 +1655,283 @@ Note 1105 DBUG: [1] arg=2 handler=0 (time) Note 1105 DBUG: [2] arg=3 handler=2 (datetime) SET SESSION debug_dbug="-d,Predicant_to_list_comparator"; SET SESSION debug_dbug="-d,Item_func_in"; +# +# MDEV-16408 Remove tests for Item::type() in Item_basic_value::eq() +# +SET SESSION debug_dbug="+d,Item_basic_value"; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT * FROM t1 WHERE a BETWEEN 1 AND 1.0; +a +1 +Warnings: +Note 1105 bin_eq=0 a=(int)1 b=(decimal)1.0 +SELECT * FROM t1 WHERE a BETWEEN 1 AND 1; +a +1 +Warnings: +Note 1105 bin_eq=1 a=(int)1 b=(int)1 +SELECT * FROM t1 WHERE a BETWEEN 0 AND 1; +a +1 +Warnings: +Note 1105 bin_eq=0 a=(int)0 b=(int)1 +SELECT * FROM t1 WHERE a BETWEEN 0 AND -1; +a +Warnings: +Note 1105 bin_eq=0 a=(int)0 b=(int)-1 +SELECT * FROM t1 WHERE a BETWEEN -1 AND -1; +a +Warnings: +Note 1105 bin_eq=1 a=(int)-1 b=(int)-1 +SELECT * FROM t1 WHERE a BETWEEN -0000000000000001 AND -1; +a +Warnings: +Note 1105 bin_eq=1 a=(bigint)-1 b=(int)-1 +SELECT * FROM t1 WHERE a BETWEEN -1 AND 18446744073709551615; +a +1 +2 +3 +Warnings: +Note 1105 bin_eq=0 a=(int)-1 b=(bigint)18446744073709551615 +SELECT * FROM t1 WHERE a BETWEEN -1 AND 18446744073709551616; +a +1 +2 +3 +Warnings: +Note 1105 bin_eq=0 a=(int)-1 b=(decimal)18446744073709551616 +SELECT * FROM t1 WHERE a BETWEEN 1e2 AND 100e0; +a +Warnings: +Note 1105 bin_eq=1 a=(double)1e2 b=(double)100e0 +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN 1 AND ?' USING 1; +a +1 +Warnings: +Note 1105 bin_eq=1 a=(int)1 b=(int)1 +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551615; +a +1 +2 +3 +Warnings: +Note 1105 bin_eq=0 a=(int)-1 b=(bigint)18446744073709551615 +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551616; +a +1 +2 +3 +Warnings: +Note 1105 bin_eq=0 a=(int)-1 b=(decimal)18446744073709551616 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(10)); +INSERT INTO t1 VALUES ('0'),('1'),('2'); +SELECT * FROM t1 WHERE a BETWEEN '0' AND '0'; +a +0 +Warnings: +Note 1105 eq=1 a=(varchar)'0' b=(varchar)'0' +SELECT * FROM t1 WHERE a BETWEEN '0' AND ' 0'; +a +Warnings: +Note 1105 eq=0 a=(varchar)'0' b=(varchar)' 0' +SELECT * FROM t1 WHERE a BETWEEN '0' AND '0 '; +a +0 +Warnings: +Note 1105 eq=1 a=(varchar)'0' b=(varchar)'0 ' +DROP TABLE t1; +SET SESSION debug_dbug="-d,Item_basic_value"; +# +# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +# +SET SESSION debug_dbug="+d,Item_basic_value"; +CREATE TABLE t1 (a DECIMAL(10,3)); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT * FROM t1 WHERE a BETWEEN 1.0 AND 1.0; +a +1.000 +Warnings: +Note 1105 bin_eq=1 a=(decimal)1.0 b=(decimal)1.0 +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN 1.0 AND ?' USING 1.0; +a +1.000 +Warnings: +Note 1105 bin_eq=1 a=(decimal)1.0 b=(decimal)1.0 +DROP TABLE t1; +CREATE TABLE t1 (a TIME); +INSERT INTO t1 VALUES ('00:00:00'),('00:00:01'); +SELECT * FROM t1 WHERE a BETWEEN TIME'00:00:00' AND TIME'00:00:00'; +a +00:00:00 +Warnings: +Note 1105 bin_eq=1 a=(time)TIME'00:00:00' b=(time)TIME'00:00:00' +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN TIME''00:00:00'' AND ?' USING TIME'00:00:00'; +a +00:00:00 +Warnings: +Note 1105 bin_eq=1 a=(time)TIME'00:00:00' b=(time)TIME'00:00:00' +DROP TABLE t1; +CREATE TABLE t1 (a DATE); +INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1 WHERE a BETWEEN DATE'2001-01-01' AND DATE'2001-01-01'; +a +2001-01-01 +Warnings: +Note 1105 bin_eq=1 a=(date)DATE'2001-01-01' b=(date)DATE'2001-01-01' +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN DATE''2001-01-01'' AND ?' USING DATE'2001-01-01'; +a +2001-01-01 +Warnings: +Note 1105 bin_eq=1 a=(date)DATE'2001-01-01' b=(date)DATE'2001-01-01' +DROP TABLE t1; +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:00'); +SELECT * FROM t1 WHERE a BETWEEN TIMESTAMP'2001-01-01 00:00:00' AND TIMESTAMP'2001-01-01 00:00:00'; +a +2001-01-01 00:00:00 +2001-01-01 00:00:00 +Warnings: +Note 1105 bin_eq=1 a=(datetime)TIMESTAMP'2001-01-01 00:00:00' b=(datetime)TIMESTAMP'2001-01-01 00:00:00' +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN TIMESTAMP''2001-01-01 00:00:00'' AND ?' USING TIMESTAMP'2001-01-01 00:00:00'; +a +2001-01-01 00:00:00 +2001-01-01 00:00:00 +Warnings: +Note 1105 bin_eq=1 a=(datetime)TIMESTAMP'2001-01-01 00:00:00' b=(datetime)TIMESTAMP'2001-01-01 00:00:00' +DROP TABLE t1; +SET SESSION debug_dbug="-d,Item_basic_value"; +# +# MDEV-16426 Optimizer erroneously treats equal constants of different formats as same +# +SET SESSION debug_dbug="+d,Item_basic_value"; +CREATE TABLE t1 (a VARCHAR(10)); +INSERT INTO t1 VALUES ('a'),('b'),('c'); +SELECT * FROM t1 WHERE a BETWEEN 'a' AND 0x61; +a +a +Warnings: +Note 1105 eq=0 a=(varchar)'a' b=(hex_hybrid)0x61 +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN ''a'' AND ?' USING 0x61; +a +a +Warnings: +Note 1105 eq=0 a=(varchar)'a' b=(hex_hybrid)'a' +DROP TABLE t1; +SET SESSION debug_dbug="-d,Item_basic_value"; +# +# MDEV-16454 Bad results for IN with ROW +# +SET SESSION debug_dbug="+d,cmp_item"; +SET SESSION debug_dbug="+d,Item_func_in"; +SET SESSION debug_dbug="+d,Predicant_to_list_comparator"; +SELECT (18446744073709551615,0) IN ((18446744073709551614,0),(-1,0)); +(18446744073709551615,0) IN ((18446744073709551614,0),(-1,0)) +0 +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (row) +Note 1105 DBUG: [1] arg=2 handler=0 (row) +Note 1105 DBUG: ROW(3 args) level=0 +Note 1105 DBUG: [0,0] handler=bigint +Note 1105 DBUG: [0,1] handler=bigint +Note 1105 DBUG: [0,2] handler=int +Note 1105 DBUG: => handler=decimal +Note 1105 DBUG: [1,0] handler=int +Note 1105 DBUG: [1,1] handler=int +Note 1105 DBUG: [1,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: types_compatible=yes bisect=yes +SELECT (1,(0,0)) IN ((1,(1,0)),(0,(0,0))); +(1,(0,0)) IN ((1,(1,0)),(0,(0,0))) +0 +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (row) +Note 1105 DBUG: [1] arg=2 handler=0 (row) +Note 1105 DBUG: ROW(3 args) level=0 +Note 1105 DBUG: [0,0] handler=int +Note 1105 DBUG: [0,1] handler=int +Note 1105 DBUG: [0,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: [1,0] handler=row +Note 1105 DBUG: [1,1] handler=row +Note 1105 DBUG: [1,2] handler=row +Note 1105 DBUG: => handler=row +Note 1105 DBUG: ROW(3 args) level=1 +Note 1105 DBUG: [0,0] handler=int +Note 1105 DBUG: [0,1] handler=int +Note 1105 DBUG: [0,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: [1,0] handler=int +Note 1105 DBUG: [1,1] handler=int +Note 1105 DBUG: [1,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: types_compatible=yes bisect=yes +SELECT (1,(0,0),3) IN ((1,(1,0),3),(0,(0,0),3)); +(1,(0,0),3) IN ((1,(1,0),3),(0,(0,0),3)) +0 +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (row) +Note 1105 DBUG: [1] arg=2 handler=0 (row) +Note 1105 DBUG: ROW(3 args) level=0 +Note 1105 DBUG: [0,0] handler=int +Note 1105 DBUG: [0,1] handler=int +Note 1105 DBUG: [0,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: [1,0] handler=row +Note 1105 DBUG: [1,1] handler=row +Note 1105 DBUG: [1,2] handler=row +Note 1105 DBUG: => handler=row +Note 1105 DBUG: ROW(3 args) level=1 +Note 1105 DBUG: [0,0] handler=int +Note 1105 DBUG: [0,1] handler=int +Note 1105 DBUG: [0,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: [1,0] handler=int +Note 1105 DBUG: [1,1] handler=int +Note 1105 DBUG: [1,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: [2,0] handler=int +Note 1105 DBUG: [2,1] handler=int +Note 1105 DBUG: [2,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: types_compatible=yes bisect=yes +SELECT '0x' IN (0); +'0x' IN (0) +1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '0x' +SELECT '0x' IN (0,1); +'0x' IN (0,1) +1 +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (double) +Note 1105 DBUG: [1] arg=2 handler=0 (double) +Note 1105 DBUG: types_compatible=yes bisect=yes +Warning 1292 Truncated incorrect DOUBLE value: '0x' +SELECT ('0x',1) IN ((0,1)); +('0x',1) IN ((0,1)) +1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '0x' +SELECT ('0x',1) IN ((0,1),(1,1)); +('0x',1) IN ((0,1),(1,1)) +1 +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (row) +Note 1105 DBUG: [1] arg=2 handler=0 (row) +Note 1105 DBUG: ROW(3 args) level=0 +Note 1105 DBUG: [0,0] handler=varchar +Note 1105 DBUG: [0,1] handler=int +Note 1105 DBUG: [0,2] handler=int +Note 1105 DBUG: => handler=double +Note 1105 DBUG: [1,0] handler=int +Note 1105 DBUG: [1,1] handler=int +Note 1105 DBUG: [1,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: types_compatible=yes bisect=yes +Warning 1292 Truncated incorrect DOUBLE value: '0x' +SET SESSION debug_dbug="-d,Predicant_to_list_comparator"; +SET SESSION debug_dbug="-d,Item_func_in"; +SET SESSION debug_dbug="-d,cmp_item"; diff --git a/mysql-test/main/func_debug.test b/mysql-test/main/func_debug.test index e0960f736cb..f3ae0c67181 100644 --- a/mysql-test/main/func_debug.test +++ b/mysql-test/main/func_debug.test @@ -475,3 +475,105 @@ SELECT SET SESSION debug_dbug="-d,Predicant_to_list_comparator"; SET SESSION debug_dbug="-d,Item_func_in"; + + +--echo # +--echo # MDEV-16408 Remove tests for Item::type() in Item_basic_value::eq() +--echo # + +SET SESSION debug_dbug="+d,Item_basic_value"; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT * FROM t1 WHERE a BETWEEN 1 AND 1.0; +SELECT * FROM t1 WHERE a BETWEEN 1 AND 1; +SELECT * FROM t1 WHERE a BETWEEN 0 AND 1; +SELECT * FROM t1 WHERE a BETWEEN 0 AND -1; +SELECT * FROM t1 WHERE a BETWEEN -1 AND -1; +SELECT * FROM t1 WHERE a BETWEEN -0000000000000001 AND -1; +SELECT * FROM t1 WHERE a BETWEEN -1 AND 18446744073709551615; +SELECT * FROM t1 WHERE a BETWEEN -1 AND 18446744073709551616; +SELECT * FROM t1 WHERE a BETWEEN 1e2 AND 100e0; + +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN 1 AND ?' USING 1; +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551615; +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551616; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(10)); +INSERT INTO t1 VALUES ('0'),('1'),('2'); +SELECT * FROM t1 WHERE a BETWEEN '0' AND '0'; +SELECT * FROM t1 WHERE a BETWEEN '0' AND ' 0'; +SELECT * FROM t1 WHERE a BETWEEN '0' AND '0 '; +DROP TABLE t1; + +SET SESSION debug_dbug="-d,Item_basic_value"; + + +--echo # +--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +--echo # + +SET SESSION debug_dbug="+d,Item_basic_value"; + +CREATE TABLE t1 (a DECIMAL(10,3)); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT * FROM t1 WHERE a BETWEEN 1.0 AND 1.0; +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN 1.0 AND ?' USING 1.0; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME); +INSERT INTO t1 VALUES ('00:00:00'),('00:00:01'); +SELECT * FROM t1 WHERE a BETWEEN TIME'00:00:00' AND TIME'00:00:00'; +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN TIME''00:00:00'' AND ?' USING TIME'00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1 (a DATE); +INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02'); +SELECT * FROM t1 WHERE a BETWEEN DATE'2001-01-01' AND DATE'2001-01-01'; +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN DATE''2001-01-01'' AND ?' USING DATE'2001-01-01'; +DROP TABLE t1; + +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:00'); +SELECT * FROM t1 WHERE a BETWEEN TIMESTAMP'2001-01-01 00:00:00' AND TIMESTAMP'2001-01-01 00:00:00'; +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN TIMESTAMP''2001-01-01 00:00:00'' AND ?' USING TIMESTAMP'2001-01-01 00:00:00'; +DROP TABLE t1; + +SET SESSION debug_dbug="-d,Item_basic_value"; + + +--echo # +--echo # MDEV-16426 Optimizer erroneously treats equal constants of different formats as same +--echo # + +SET SESSION debug_dbug="+d,Item_basic_value"; + +CREATE TABLE t1 (a VARCHAR(10)); +INSERT INTO t1 VALUES ('a'),('b'),('c'); +SELECT * FROM t1 WHERE a BETWEEN 'a' AND 0x61; +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN ''a'' AND ?' USING 0x61; +DROP TABLE t1; + +SET SESSION debug_dbug="-d,Item_basic_value"; + + +--echo # +--echo # MDEV-16454 Bad results for IN with ROW +--echo # + +SET SESSION debug_dbug="+d,cmp_item"; +SET SESSION debug_dbug="+d,Item_func_in"; +SET SESSION debug_dbug="+d,Predicant_to_list_comparator"; + +SELECT (18446744073709551615,0) IN ((18446744073709551614,0),(-1,0)); +SELECT (1,(0,0)) IN ((1,(1,0)),(0,(0,0))); +SELECT (1,(0,0),3) IN ((1,(1,0),3),(0,(0,0),3)); + +SELECT '0x' IN (0); +SELECT '0x' IN (0,1); +SELECT ('0x',1) IN ((0,1)); +SELECT ('0x',1) IN ((0,1),(1,1)); + +SET SESSION debug_dbug="-d,Predicant_to_list_comparator"; +SET SESSION debug_dbug="-d,Item_func_in"; +SET SESSION debug_dbug="-d,cmp_item"; diff --git a/mysql-test/main/func_extract.result b/mysql-test/main/func_extract.result new file mode 100644 index 00000000000..30ec0460d61 --- /dev/null +++ b/mysql-test/main/func_extract.result @@ -0,0 +1,592 @@ +# +# MDEV-17385 MICROSECOND() returns confusing results with an out-of-range TIME-alike argument +# +CREATE TABLE t1 (v VARCHAR(64), ll BIGINT, t TIME, dt DATETIME, d DATE); +CREATE TABLE t2 AS SELECT +EXTRACT(DAY FROM t), +EXTRACT(DAY_HOUR FROM t), +EXTRACT(DAY_MINUTE FROM t), +EXTRACT(DAY_SECOND FROM t), +EXTRACT(DAY_MICROSECOND FROM t), +EXTRACT(DAY FROM d), +EXTRACT(DAY_HOUR FROM d), +EXTRACT(DAY_MINUTE FROM d), +EXTRACT(DAY_SECOND FROM d), +EXTRACT(DAY_MICROSECOND FROM d), +EXTRACT(DAY FROM v), +EXTRACT(DAY_HOUR FROM v), +EXTRACT(DAY_MINUTE FROM v), +EXTRACT(DAY_SECOND FROM v), +EXTRACT(DAY_MICROSECOND FROM v), +EXTRACT(DAY FROM ll), +EXTRACT(DAY_HOUR FROM ll), +EXTRACT(DAY_MINUTE FROM ll), +EXTRACT(DAY_SECOND FROM ll), +EXTRACT(DAY_MICROSECOND FROM ll) +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `EXTRACT(DAY FROM t)` int(3) DEFAULT NULL, + `EXTRACT(DAY_HOUR FROM t)` int(5) DEFAULT NULL, + `EXTRACT(DAY_MINUTE FROM t)` int(7) DEFAULT NULL, + `EXTRACT(DAY_SECOND FROM t)` int(9) DEFAULT NULL, + `EXTRACT(DAY_MICROSECOND FROM t)` bigint(15) DEFAULT NULL, + `EXTRACT(DAY FROM d)` int(3) DEFAULT NULL, + `EXTRACT(DAY_HOUR FROM d)` int(5) DEFAULT NULL, + `EXTRACT(DAY_MINUTE FROM d)` int(7) DEFAULT NULL, + `EXTRACT(DAY_SECOND FROM d)` int(9) DEFAULT NULL, + `EXTRACT(DAY_MICROSECOND FROM d)` bigint(15) DEFAULT NULL, + `EXTRACT(DAY FROM v)` int(8) DEFAULT NULL, + `EXTRACT(DAY_HOUR FROM v)` int(10) DEFAULT NULL, + `EXTRACT(DAY_MINUTE FROM v)` bigint(12) DEFAULT NULL, + `EXTRACT(DAY_SECOND FROM v)` bigint(14) DEFAULT NULL, + `EXTRACT(DAY_MICROSECOND FROM v)` bigint(20) DEFAULT NULL, + `EXTRACT(DAY FROM ll)` int(8) DEFAULT NULL, + `EXTRACT(DAY_HOUR FROM ll)` int(10) DEFAULT NULL, + `EXTRACT(DAY_MINUTE FROM ll)` bigint(12) DEFAULT NULL, + `EXTRACT(DAY_SECOND FROM ll)` bigint(14) DEFAULT NULL, + `EXTRACT(DAY_MICROSECOND FROM ll)` bigint(20) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64), b DECIMAL(32,9)); +INSERT INTO t1 VALUES +('9999-12-31 23:59:59.123456', 99991231235959.123456), +('2001-01-01 10:20:30.123456', 20010101102030.123456), +('4294967296:59:59.123456', 42949672965959.123456), +('4294967295:59:59.123456', 42949672955959.123456), +('87649416:59:59.123456', 876494165959.123456), +('87649415:59:59.123456', 876494155959.123456), +('87649414:59:59.123456', 876494145959.123456), +('9999:59:59.123456', 99995959.123456), +('9999:01:01.123456', 99990101.123456), +('9999:01:01', 99990101), +('0.999999', 0.999999), +('0.99999', 0.99999), +('0.9999', 0.9999), +('0.999', 0.999), +('0.99', 0.99), +('0.9', 0.9), +('000000',0); +# Summary: +# Check that FUNC(varchar) and FUNC(decimal) give equal results +# Expect empty sets +SELECT a, b, EXTRACT(DAY_HOUR FROM a), EXTRACT(DAY_HOUR FROM b) FROM t1 WHERE NOT (EXTRACT(DAY_HOUR FROM a)<=>EXTRACT(DAY_HOUR FROM b)); +a b EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY_HOUR FROM b) +SELECT a, b, EXTRACT(DAY FROM a), EXTRACT(DAY FROM b) FROM t1 WHERE NOT (EXTRACT(DAY FROM a)<=>EXTRACT(DAY FROM b)); +a b EXTRACT(DAY FROM a) EXTRACT(DAY FROM b) +SELECT a, b, EXTRACT(HOUR FROM a), EXTRACT(HOUR FROM b) FROM t1 WHERE NOT (EXTRACT(HOUR FROM a)<=>EXTRACT(HOUR FROM b)); +a b EXTRACT(HOUR FROM a) EXTRACT(HOUR FROM b) +SELECT a, b, EXTRACT(MINUTE FROM a), EXTRACT(MINUTE FROM b) FROM t1 WHERE NOT (EXTRACT(MINUTE FROM a)<=>EXTRACT(MINUTE FROM b)); +a b EXTRACT(MINUTE FROM a) EXTRACT(MINUTE FROM b) +SELECT a, b, EXTRACT(SECOND FROM a), EXTRACT(SECOND FROM b) FROM t1 WHERE NOT (EXTRACT(SECOND FROM a)<=>EXTRACT(SECOND FROM b)); +a b EXTRACT(SECOND FROM a) EXTRACT(SECOND FROM b) +SELECT a, b, EXTRACT(MICROSECOND FROM a), EXTRACT(MICROSECOND FROM b) FROM t1 WHERE NOT (EXTRACT(MICROSECOND FROM a)<=>EXTRACT(MICROSECOND FROM b)); +a b EXTRACT(MICROSECOND FROM a) EXTRACT(MICROSECOND FROM b) +# Detailed results +SELECT +a, +CAST(a AS INTERVAL DAY_SECOND(6)) AS cidm, +EXTRACT(DAY FROM a) * 24 + EXTRACT(HOUR FROM a) AS dh, +EXTRACT(DAY_HOUR FROM a), +EXTRACT(DAY FROM a), +EXTRACT(HOUR FROM a), +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a) +FROM t1; +a cidm dh EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY FROM a) EXTRACT(HOUR FROM a) EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a) +9999-12-31 23:59:59.123456 NULL 767 3123 31 23 59 59 123456 +2001-01-01 10:20:30.123456 NULL 34 110 1 10 20 30 123456 +4294967296:59:59.123456 NULL NULL NULL NULL NULL NULL NULL NULL +4294967295:59:59.123456 NULL NULL NULL NULL NULL NULL NULL NULL +87649416:59:59.123456 NULL NULL NULL NULL NULL NULL NULL NULL +87649415:59:59.123456 3652058 23:59:59.123456 87649415 365205823 3652058 23 59 59 123456 +87649414:59:59.123456 3652058 22:59:59.123456 87649414 365205822 3652058 22 59 59 123456 +9999:59:59.123456 416 15:59:59.123456 9999 41615 416 15 59 59 123456 +9999:01:01.123456 416 15:01:01.123456 9999 41615 416 15 1 1 123456 +9999:01:01 416 15:01:01.000000 9999 41615 416 15 1 1 0 +0.999999 00:00:00.999999 0 0 0 0 0 0 999999 +0.99999 00:00:00.999990 0 0 0 0 0 0 999990 +0.9999 00:00:00.999900 0 0 0 0 0 0 999900 +0.999 00:00:00.999000 0 0 0 0 0 0 999000 +0.99 00:00:00.990000 0 0 0 0 0 0 990000 +0.9 00:00:00.900000 0 0 0 0 0 0 900000 +000000 00:00:00.000000 0 0 0 0 0 0 0 +Warnings: +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '9999-12-31 23:59:59.123456' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '2001-01-01 10:20:30.123456' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59.123456' +Warning 1292 Incorrect interval value: '4294967296:59:59.123456' +Warning 1292 Incorrect interval value: '4294967296:59:59.123456' +Warning 1292 Incorrect interval value: '4294967296:59:59.123456' +Warning 1292 Incorrect interval value: '4294967296:59:59.123456' +Warning 1292 Incorrect interval value: '4294967296:59:59.123456' +Warning 1292 Incorrect interval value: '4294967296:59:59.123456' +Warning 1292 Incorrect interval value: '4294967296:59:59.123456' +Warning 1292 Incorrect interval value: '4294967296:59:59.123456' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59.123456' +Warning 1292 Incorrect interval value: '4294967295:59:59.123456' +Warning 1292 Incorrect interval value: '4294967295:59:59.123456' +Warning 1292 Incorrect interval value: '4294967295:59:59.123456' +Warning 1292 Incorrect interval value: '4294967295:59:59.123456' +Warning 1292 Incorrect interval value: '4294967295:59:59.123456' +Warning 1292 Incorrect interval value: '4294967295:59:59.123456' +Warning 1292 Incorrect interval value: '4294967295:59:59.123456' +Warning 1292 Incorrect interval value: '4294967295:59:59.123456' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59.123456' +Warning 1292 Incorrect interval value: '87649416:59:59.123456' +Warning 1292 Incorrect interval value: '87649416:59:59.123456' +Warning 1292 Incorrect interval value: '87649416:59:59.123456' +Warning 1292 Incorrect interval value: '87649416:59:59.123456' +Warning 1292 Incorrect interval value: '87649416:59:59.123456' +Warning 1292 Incorrect interval value: '87649416:59:59.123456' +Warning 1292 Incorrect interval value: '87649416:59:59.123456' +Warning 1292 Incorrect interval value: '87649416:59:59.123456' +SELECT +b, +CAST(b AS INTERVAL DAY_SECOND(6)) AS cidm, +EXTRACT(DAY FROM b) * 24 + EXTRACT(HOUR FROM b) AS dh, +EXTRACT(DAY_HOUR FROM b), +EXTRACT(DAY FROM b), +EXTRACT(HOUR FROM b), +EXTRACT(MINUTE FROM b), +EXTRACT(SECOND FROM b), +EXTRACT(MICROSECOND FROM b) +FROM t1; +b cidm dh EXTRACT(DAY_HOUR FROM b) EXTRACT(DAY FROM b) EXTRACT(HOUR FROM b) EXTRACT(MINUTE FROM b) EXTRACT(SECOND FROM b) EXTRACT(MICROSECOND FROM b) +99991231235959.123456000 NULL 767 3123 31 23 59 59 123456 +20010101102030.123456000 NULL 34 110 1 10 20 30 123456 +42949672965959.123456000 NULL NULL NULL NULL NULL NULL NULL NULL +42949672955959.123456000 NULL NULL NULL NULL NULL NULL NULL NULL +876494165959.123456000 NULL NULL NULL NULL NULL NULL NULL NULL +876494155959.123456000 3652058 23:59:59.123456 87649415 365205823 3652058 23 59 59 123456 +876494145959.123456000 3652058 22:59:59.123456 87649414 365205822 3652058 22 59 59 123456 +99995959.123456000 416 15:59:59.123456 9999 41615 416 15 59 59 123456 +99990101.123456000 416 15:01:01.123456 9999 41615 416 15 1 1 123456 +99990101.000000000 416 15:01:01.000000 9999 41615 416 15 1 1 0 +0.999999000 00:00:00.999999 0 0 0 0 0 0 999999 +0.999990000 00:00:00.999990 0 0 0 0 0 0 999990 +0.999900000 00:00:00.999900 0 0 0 0 0 0 999900 +0.999000000 00:00:00.999000 0 0 0 0 0 0 999000 +0.990000000 00:00:00.990000 0 0 0 0 0 0 990000 +0.900000000 00:00:00.900000 0 0 0 0 0 0 900000 +0.000000000 00:00:00.000000 0 0 0 0 0 0 0 +Warnings: +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '99991231235959.123456000' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '20010101102030.123456000' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '42949672965959.123456000' +Warning 1292 Incorrect interval value: '42949672965959.123456000' for column `test`.`t1`.`b` at row 3 +Warning 1292 Incorrect interval value: '42949672965959.123456000' for column `test`.`t1`.`b` at row 3 +Warning 1292 Incorrect interval value: '42949672965959.123456000' for column `test`.`t1`.`b` at row 3 +Warning 1292 Incorrect interval value: '42949672965959.123456000' for column `test`.`t1`.`b` at row 3 +Warning 1292 Incorrect interval value: '42949672965959.123456000' for column `test`.`t1`.`b` at row 3 +Warning 1292 Incorrect interval value: '42949672965959.123456000' for column `test`.`t1`.`b` at row 3 +Warning 1292 Incorrect interval value: '42949672965959.123456000' for column `test`.`t1`.`b` at row 3 +Warning 1292 Incorrect interval value: '42949672965959.123456000' for column `test`.`t1`.`b` at row 3 +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '42949672955959.123456000' +Warning 1292 Incorrect interval value: '42949672955959.123456000' for column `test`.`t1`.`b` at row 4 +Warning 1292 Incorrect interval value: '42949672955959.123456000' for column `test`.`t1`.`b` at row 4 +Warning 1292 Incorrect interval value: '42949672955959.123456000' for column `test`.`t1`.`b` at row 4 +Warning 1292 Incorrect interval value: '42949672955959.123456000' for column `test`.`t1`.`b` at row 4 +Warning 1292 Incorrect interval value: '42949672955959.123456000' for column `test`.`t1`.`b` at row 4 +Warning 1292 Incorrect interval value: '42949672955959.123456000' for column `test`.`t1`.`b` at row 4 +Warning 1292 Incorrect interval value: '42949672955959.123456000' for column `test`.`t1`.`b` at row 4 +Warning 1292 Incorrect interval value: '42949672955959.123456000' for column `test`.`t1`.`b` at row 4 +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '876494165959.123456000' +Warning 1292 Incorrect interval value: '876494165959.123456000' for column `test`.`t1`.`b` at row 5 +Warning 1292 Incorrect interval value: '876494165959.123456000' for column `test`.`t1`.`b` at row 5 +Warning 1292 Incorrect interval value: '876494165959.123456000' for column `test`.`t1`.`b` at row 5 +Warning 1292 Incorrect interval value: '876494165959.123456000' for column `test`.`t1`.`b` at row 5 +Warning 1292 Incorrect interval value: '876494165959.123456000' for column `test`.`t1`.`b` at row 5 +Warning 1292 Incorrect interval value: '876494165959.123456000' for column `test`.`t1`.`b` at row 5 +Warning 1292 Incorrect interval value: '876494165959.123456000' for column `test`.`t1`.`b` at row 5 +Warning 1292 Incorrect interval value: '876494165959.123456000' for column `test`.`t1`.`b` at row 5 +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '876494155959.123456000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '876494145959.123456000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '99995959.123456000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '99990101.123456000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '99990101.000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.999990000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.999900000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.999000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.990000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.900000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.000000000' +DROP TABLE t1; +# Special case: DAY + TIME +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES ('9999-01-01'); +SELECT a, +EXTRACT(DAY_HOUR FROM a), +EXTRACT(DAY_MINUTE FROM a), +EXTRACT(DAY_SECOND FROM a), +EXTRACT(DAY_MICROSECOND FROM a), +EXTRACT(DAY FROM a), +EXTRACT(HOUR FROM a), +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a) +FROM t1; +a EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY_MINUTE FROM a) EXTRACT(DAY_SECOND FROM a) EXTRACT(DAY_MICROSECOND FROM a) EXTRACT(DAY FROM a) EXTRACT(HOUR FROM a) EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a) +9999-01-01 100 10000 1000000 1000000000000 1 0 0 0 0 +DROP TABLE t1; +# Bad values +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES (''); +SELECT a, +CAST(a AS INTERVAL DAY_SECOND(6)) AS cidm, +EXTRACT(DAY_HOUR FROM a), +EXTRACT(DAY_MINUTE FROM a), +EXTRACT(DAY_SECOND FROM a), +EXTRACT(DAY_MICROSECOND FROM a), +EXTRACT(DAY FROM a), +EXTRACT(HOUR FROM a), +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a) +FROM t1; +a cidm EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY_MINUTE FROM a) EXTRACT(DAY_SECOND FROM a) EXTRACT(DAY_MICROSECOND FROM a) EXTRACT(DAY FROM a) EXTRACT(HOUR FROM a) EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a) + NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '' +Warning 1292 Incorrect interval value: '' +Warning 1292 Incorrect interval value: '' +Warning 1292 Incorrect interval value: '' +Warning 1292 Incorrect interval value: '' +Warning 1292 Incorrect interval value: '' +Warning 1292 Incorrect interval value: '' +Warning 1292 Incorrect interval value: '' +Warning 1292 Incorrect interval value: '' +Warning 1292 Incorrect interval value: '' +DROP TABLE t1; +# Backward compatibility +# This still parses as DATETIME +SELECT EXTRACT(YEAR FROM '2001/02/03 10:20:30'); +EXTRACT(YEAR FROM '2001/02/03 10:20:30') +2001 +SELECT EXTRACT(MONTH FROM '2001/02/03 10:20:30'); +EXTRACT(MONTH FROM '2001/02/03 10:20:30') +2 +SELECT EXTRACT(DAY FROM '2001/02/03 10:20:30'); +EXTRACT(DAY FROM '2001/02/03 10:20:30') +3 +SELECT EXTRACT(YEAR FROM '01/02/03 10:20:30'); +EXTRACT(YEAR FROM '01/02/03 10:20:30') +2001 +SELECT EXTRACT(MONTH FROM '01/02/03 10:20:30'); +EXTRACT(MONTH FROM '01/02/03 10:20:30') +2 +SELECT EXTRACT(DAY FROM '01/02/03 10:20:30'); +EXTRACT(DAY FROM '01/02/03 10:20:30') +3 +SELECT EXTRACT(YEAR FROM '01:02:03 10:20:30'); +EXTRACT(YEAR FROM '01:02:03 10:20:30') +2001 +SELECT EXTRACT(MONTH FROM '01:02:03 10:20:30'); +EXTRACT(MONTH FROM '01:02:03 10:20:30') +2 +SELECT EXTRACT(DAY FROM '01:02:03 10:20:30'); +EXTRACT(DAY FROM '01:02:03 10:20:30') +3 +# This still parses as DATETIME and returns NULL +SELECT EXTRACT(YEAR FROM "2011-02-32 8:46:06.23434"); +EXTRACT(YEAR FROM "2011-02-32 8:46:06.23434") +NULL +Warnings: +Warning 1292 Incorrect datetime value: '2011-02-32 8:46:06.23434' +SELECT EXTRACT(MONTH FROM "2011-02-32 8:46:06.23434"); +EXTRACT(MONTH FROM "2011-02-32 8:46:06.23434") +NULL +Warnings: +Warning 1292 Incorrect datetime value: '2011-02-32 8:46:06.23434' +SELECT EXTRACT(DAY FROM "2011-02-32 8:46:06.23434"); +EXTRACT(DAY FROM "2011-02-32 8:46:06.23434") +NULL +Warnings: +Warning 1292 Incorrect interval value: '2011-02-32 8:46:06.23434' +SELECT EXTRACT(HOUR FROM "2011-02-32 8:46:06.23434"); +EXTRACT(HOUR FROM "2011-02-32 8:46:06.23434") +NULL +Warnings: +Warning 1292 Incorrect interval value: '2011-02-32 8:46:06.23434' +# This still parses as DATE +SELECT EXTRACT(YEAR FROM '2001/02/03'); +EXTRACT(YEAR FROM '2001/02/03') +2001 +SELECT EXTRACT(MONTH FROM '2001/02/03'); +EXTRACT(MONTH FROM '2001/02/03') +2 +SELECT EXTRACT(DAY FROM '2001/02/03'); +EXTRACT(DAY FROM '2001/02/03') +3 +SELECT EXTRACT(YEAR FROM '01/02/03'); +EXTRACT(YEAR FROM '01/02/03') +2001 +SELECT EXTRACT(MONTH FROM '01/02/03'); +EXTRACT(MONTH FROM '01/02/03') +2 +SELECT EXTRACT(DAY FROM '01/02/03'); +EXTRACT(DAY FROM '01/02/03') +3 +SELECT EXTRACT(YEAR FROM '01-02-03'); +EXTRACT(YEAR FROM '01-02-03') +2001 +SELECT EXTRACT(MONTH FROM '01-02-03'); +EXTRACT(MONTH FROM '01-02-03') +2 +SELECT EXTRACT(DAY FROM '01-02-03'); +EXTRACT(DAY FROM '01-02-03') +3 +SELECT EXTRACT(YEAR FROM '1-2-3'); +EXTRACT(YEAR FROM '1-2-3') +1 +SELECT EXTRACT(MONTH FROM '1-2-3'); +EXTRACT(MONTH FROM '1-2-3') +2 +SELECT EXTRACT(DAY FROM '1-2-3'); +EXTRACT(DAY FROM '1-2-3') +3 +SELECT EXTRACT(HOUR FROM '1-2-3'); +EXTRACT(HOUR FROM '1-2-3') +0 +SELECT EXTRACT(DAY FROM '2024-01-03 garbage /////'); +EXTRACT(DAY FROM '2024-01-03 garbage /////') +3 +Warnings: +Warning 1292 Truncated incorrect date value: '2024-01-03 garbage /////' +SELECT EXTRACT(DAY FROM '24-01-03 garbage /////'); +EXTRACT(DAY FROM '24-01-03 garbage /////') +3 +Warnings: +Warning 1292 Truncated incorrect date value: '24-01-03 garbage /////' +SELECT EXTRACT(DAY FROM '01-02-03'); +EXTRACT(DAY FROM '01-02-03') +3 +SELECT EXTRACT(DAY FROM '24:02:03T'); +EXTRACT(DAY FROM '24:02:03T') +3 +SELECT EXTRACT(DAY FROM '24-02-03'); +EXTRACT(DAY FROM '24-02-03') +3 +SELECT EXTRACT(DAY FROM '24/02/03'); +EXTRACT(DAY FROM '24/02/03') +3 +SELECT EXTRACT(DAY FROM '11111'); +EXTRACT(DAY FROM '11111') +1 +SELECT TIME('2001-01-01T'), TIME('2001-01-01T '); +TIME('2001-01-01T') TIME('2001-01-01T ') +00:00:00 00:00:00 +SELECT TIME('2001/01/01T'), TIME('2001/01/01T '); +TIME('2001/01/01T') TIME('2001/01/01T ') +00:00:00 00:00:00 +SELECT TIME('2001:01:01T'), TIME('2001:01:01T '); +TIME('2001:01:01T') TIME('2001:01:01T ') +00:00:00 00:00:00 +SELECT EXTRACT(DAY FROM '2001-01-01T'), EXTRACT(DAY FROM '2001-01-01T '); +EXTRACT(DAY FROM '2001-01-01T') EXTRACT(DAY FROM '2001-01-01T ') +1 1 +SELECT EXTRACT(DAY FROM '2001/01/01T'), EXTRACT(DAY FROM '2001/01/01T '); +EXTRACT(DAY FROM '2001/01/01T') EXTRACT(DAY FROM '2001/01/01T ') +1 1 +SELECT EXTRACT(DAY FROM '2001:01:01T'), EXTRACT(DAY FROM '2001:01:01T '); +EXTRACT(DAY FROM '2001:01:01T') EXTRACT(DAY FROM '2001:01:01T ') +1 1 +SELECT TIME('2001:01:01T'), TIME('2001:01:01T '); +TIME('2001:01:01T') TIME('2001:01:01T ') +00:00:00 00:00:00 +SELECT EXTRACT(HOUR FROM '2001-01-01T'), EXTRACT(HOUR FROM '2001-01-01T '); +EXTRACT(HOUR FROM '2001-01-01T') EXTRACT(HOUR FROM '2001-01-01T ') +0 0 +SELECT EXTRACT(HOUR FROM '2001/01/01T'), EXTRACT(HOUR FROM '2001/01/01T '); +EXTRACT(HOUR FROM '2001/01/01T') EXTRACT(HOUR FROM '2001/01/01T ') +0 0 +SELECT EXTRACT(HOUR FROM '2001:01:01T'), EXTRACT(HOUR FROM '2001:01:01T '); +EXTRACT(HOUR FROM '2001:01:01T') EXTRACT(HOUR FROM '2001:01:01T ') +0 0 +# This still parses as DATE and returns NULL (without trying TIME) +SELECT EXTRACT(DAY FROM '100000:02:03T'); +EXTRACT(DAY FROM '100000:02:03T') +NULL +Warnings: +Warning 1292 Incorrect interval value: '100000:02:03T' +SELECT EXTRACT(DAY FROM '100000/02/03'); +EXTRACT(DAY FROM '100000/02/03') +NULL +Warnings: +Warning 1292 Incorrect interval value: '100000/02/03' +SELECT EXTRACT(DAY FROM '100000-02-03'); +EXTRACT(DAY FROM '100000-02-03') +NULL +Warnings: +Warning 1292 Incorrect interval value: '100000-02-03' +SELECT EXTRACT(DAY FROM '1111'); +EXTRACT(DAY FROM '1111') +NULL +Warnings: +Warning 1292 Incorrect interval value: '1111' +SELECT EXTRACT(DAY FROM '111'); +EXTRACT(DAY FROM '111') +NULL +Warnings: +Warning 1292 Incorrect interval value: '111' +SELECT EXTRACT(DAY FROM '11'); +EXTRACT(DAY FROM '11') +NULL +Warnings: +Warning 1292 Incorrect interval value: '11' +SELECT EXTRACT(DAY FROM '1'); +EXTRACT(DAY FROM '1') +NULL +Warnings: +Warning 1292 Incorrect interval value: '1' +# This still parses as TIME +SELECT EXTRACT(HOUR FROM '11111'); +EXTRACT(HOUR FROM '11111') +1 +SELECT EXTRACT(HOUR FROM '1111'); +EXTRACT(HOUR FROM '1111') +0 +SELECT EXTRACT(HOUR FROM '111'); +EXTRACT(HOUR FROM '111') +0 +SELECT EXTRACT(HOUR FROM '11'); +EXTRACT(HOUR FROM '11') +0 +SELECT EXTRACT(HOUR FROM '1'); +EXTRACT(HOUR FROM '1') +0 +SELECT TIME('01:02:03:'); +TIME('01:02:03:') +01:02:03 +Warnings: +Warning 1292 Truncated incorrect time value: '01:02:03:' +SELECT TIME('01:02:03-'); +TIME('01:02:03-') +01:02:03 +Warnings: +Warning 1292 Truncated incorrect time value: '01:02:03-' +SELECT TIME('01:02:03;'); +TIME('01:02:03;') +01:02:03 +Warnings: +Warning 1292 Truncated incorrect time value: '01:02:03;' +SELECT TIME('01:02:03/'); +TIME('01:02:03/') +01:02:03 +Warnings: +Warning 1292 Truncated incorrect time value: '01:02:03/' +SELECT EXTRACT(HOUR FROM '01:02:03:'); +EXTRACT(HOUR FROM '01:02:03:') +1 +Warnings: +Warning 1292 Truncated incorrect time value: '01:02:03:' +SELECT EXTRACT(HOUR FROM '01:02:03-'); +EXTRACT(HOUR FROM '01:02:03-') +1 +Warnings: +Warning 1292 Truncated incorrect time value: '01:02:03-' +SELECT EXTRACT(HOUR FROM '01:02:03;'); +EXTRACT(HOUR FROM '01:02:03;') +1 +Warnings: +Warning 1292 Truncated incorrect time value: '01:02:03;' +SELECT EXTRACT(HOUR FROM '01:02:03/'); +EXTRACT(HOUR FROM '01:02:03/') +1 +Warnings: +Warning 1292 Truncated incorrect time value: '01:02:03/' +# Backward compatibility preserved for YEAR and MONTH only +# (behavior has changed for DAY, see below) +SELECT EXTRACT(YEAR FROM '01:02:03'); +EXTRACT(YEAR FROM '01:02:03') +2001 +SELECT EXTRACT(MONTH FROM '01:02:03'); +EXTRACT(MONTH FROM '01:02:03') +2 +SELECT EXTRACT(YEAR FROM '24:01:03 garbage /////'); +EXTRACT(YEAR FROM '24:01:03 garbage /////') +2024 +Warnings: +Warning 1292 Truncated incorrect date value: '24:01:03 garbage /////' +SELECT EXTRACT(MONTH FROM '24:01:03 garbage /////'); +EXTRACT(MONTH FROM '24:01:03 garbage /////') +1 +Warnings: +Warning 1292 Truncated incorrect date value: '24:01:03 garbage /////' +# This still parses as TIME 00:20:01 +SELECT TIME('2001/01/01'); +TIME('2001/01/01') +00:20:01 +Warnings: +Warning 1292 Truncated incorrect time value: '2001/01/01' +SELECT TIME('2001-01-01'); +TIME('2001-01-01') +00:20:01 +Warnings: +Warning 1292 Truncated incorrect time value: '2001-01-01' +# This still parses as TIME and overflows to '838:59:59' +SELECT TIME('2001:01:01'); +TIME('2001:01:01') +838:59:59 +Warnings: +Warning 1292 Truncated incorrect time value: '2001:01:01' +# This used to parse as DATE, now parses as TIME interval +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2024:01:03 garbage /////'), +('24:01:03 garbage /////'), +('01:01:03 garbage /////'), +('2024:02:03'), +('100000:02:03'), +('24:02:03'), +('01:02:03'), +('01:02:03:'), +('01:02:03-'), +('01:02:03;'), +('01:02:03/'), +('20 10:20:30'); +SELECT +EXTRACT(DAY FROM a), +EXTRACT(DAY_SECOND FROM a), a, +CAST(a AS INTERVAL DAY_SECOND(6)) AS cidm +FROM t1; +EXTRACT(DAY FROM a) EXTRACT(DAY_SECOND FROM a) a cidm +84 84080103 2024:01:03 garbage ///// NULL +1 1000103 24:01:03 garbage ///// NULL +0 10103 01:01:03 garbage ///// NULL +84 84080203 2024:02:03 84 08:02:03.000000 +4166 4166160203 100000:02:03 4166 16:02:03.000000 +1 1000203 24:02:03 1 00:02:03.000000 +0 10203 01:02:03 01:02:03.000000 +0 10203 01:02:03: 01:02:03.000000 +0 10203 01:02:03- NULL +0 10203 01:02:03; 01:02:03.000000 +0 10203 01:02:03/ 01:02:03.000000 +20 20102030 20 10:20:30 20 10:20:30.000000 +Warnings: +Warning 1292 Truncated incorrect time value: '2024:01:03 garbage /////' +Warning 1292 Truncated incorrect time value: '2024:01:03 garbage /////' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '2024:01:03 garbage /////' +Warning 1292 Truncated incorrect time value: '24:01:03 garbage /////' +Warning 1292 Truncated incorrect time value: '24:01:03 garbage /////' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '24:01:03 garbage /////' +Warning 1292 Truncated incorrect time value: '01:01:03 garbage /////' +Warning 1292 Truncated incorrect time value: '01:01:03 garbage /////' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '01:01:03 garbage /////' +Warning 1292 Truncated incorrect time value: '01:02:03:' +Warning 1292 Truncated incorrect time value: '01:02:03:' +Warning 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '01:02:03:' +Warning 1292 Truncated incorrect time value: '01:02:03-' +Warning 1292 Truncated incorrect time value: '01:02:03-' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '01:02:03-' +Warning 1292 Truncated incorrect time value: '01:02:03;' +Warning 1292 Truncated incorrect time value: '01:02:03;' +Warning 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '01:02:03;' +Warning 1292 Truncated incorrect time value: '01:02:03/' +Warning 1292 Truncated incorrect time value: '01:02:03/' +Warning 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '01:02:03/' +DROP TABLE t1; diff --git a/mysql-test/main/func_extract.test b/mysql-test/main/func_extract.test new file mode 100644 index 00000000000..edc99b9c00c --- /dev/null +++ b/mysql-test/main/func_extract.test @@ -0,0 +1,257 @@ +--echo # +--echo # MDEV-17385 MICROSECOND() returns confusing results with an out-of-range TIME-alike argument +--echo # + +CREATE TABLE t1 (v VARCHAR(64), ll BIGINT, t TIME, dt DATETIME, d DATE); +CREATE TABLE t2 AS SELECT + EXTRACT(DAY FROM t), + EXTRACT(DAY_HOUR FROM t), + EXTRACT(DAY_MINUTE FROM t), + EXTRACT(DAY_SECOND FROM t), + EXTRACT(DAY_MICROSECOND FROM t), + EXTRACT(DAY FROM d), + EXTRACT(DAY_HOUR FROM d), + EXTRACT(DAY_MINUTE FROM d), + EXTRACT(DAY_SECOND FROM d), + EXTRACT(DAY_MICROSECOND FROM d), + EXTRACT(DAY FROM v), + EXTRACT(DAY_HOUR FROM v), + EXTRACT(DAY_MINUTE FROM v), + EXTRACT(DAY_SECOND FROM v), + EXTRACT(DAY_MICROSECOND FROM v), + EXTRACT(DAY FROM ll), + EXTRACT(DAY_HOUR FROM ll), + EXTRACT(DAY_MINUTE FROM ll), + EXTRACT(DAY_SECOND FROM ll), + EXTRACT(DAY_MICROSECOND FROM ll) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; +DROP TABLE t1; + + +CREATE TABLE t1 (a VARCHAR(64), b DECIMAL(32,9)); +INSERT INTO t1 VALUES +('9999-12-31 23:59:59.123456', 99991231235959.123456), +('2001-01-01 10:20:30.123456', 20010101102030.123456), +('4294967296:59:59.123456', 42949672965959.123456), +('4294967295:59:59.123456', 42949672955959.123456), +('87649416:59:59.123456', 876494165959.123456), +('87649415:59:59.123456', 876494155959.123456), +('87649414:59:59.123456', 876494145959.123456), +('9999:59:59.123456', 99995959.123456), +('9999:01:01.123456', 99990101.123456), +('9999:01:01', 99990101), +('0.999999', 0.999999), +('0.99999', 0.99999), +('0.9999', 0.9999), +('0.999', 0.999), +('0.99', 0.99), +('0.9', 0.9), +('000000',0); + +--echo # Summary: +--echo # Check that FUNC(varchar) and FUNC(decimal) give equal results +--echo # Expect empty sets +--disable_warnings +SELECT a, b, EXTRACT(DAY_HOUR FROM a), EXTRACT(DAY_HOUR FROM b) FROM t1 WHERE NOT (EXTRACT(DAY_HOUR FROM a)<=>EXTRACT(DAY_HOUR FROM b)); +SELECT a, b, EXTRACT(DAY FROM a), EXTRACT(DAY FROM b) FROM t1 WHERE NOT (EXTRACT(DAY FROM a)<=>EXTRACT(DAY FROM b)); +SELECT a, b, EXTRACT(HOUR FROM a), EXTRACT(HOUR FROM b) FROM t1 WHERE NOT (EXTRACT(HOUR FROM a)<=>EXTRACT(HOUR FROM b)); +SELECT a, b, EXTRACT(MINUTE FROM a), EXTRACT(MINUTE FROM b) FROM t1 WHERE NOT (EXTRACT(MINUTE FROM a)<=>EXTRACT(MINUTE FROM b)); +SELECT a, b, EXTRACT(SECOND FROM a), EXTRACT(SECOND FROM b) FROM t1 WHERE NOT (EXTRACT(SECOND FROM a)<=>EXTRACT(SECOND FROM b)); +SELECT a, b, EXTRACT(MICROSECOND FROM a), EXTRACT(MICROSECOND FROM b) FROM t1 WHERE NOT (EXTRACT(MICROSECOND FROM a)<=>EXTRACT(MICROSECOND FROM b)); +--enable_warnings + +--echo # Detailed results +SELECT + a, + CAST(a AS INTERVAL DAY_SECOND(6)) AS cidm, + EXTRACT(DAY FROM a) * 24 + EXTRACT(HOUR FROM a) AS dh, + EXTRACT(DAY_HOUR FROM a), + EXTRACT(DAY FROM a), + EXTRACT(HOUR FROM a), + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a) +FROM t1; +SELECT + b, + CAST(b AS INTERVAL DAY_SECOND(6)) AS cidm, + EXTRACT(DAY FROM b) * 24 + EXTRACT(HOUR FROM b) AS dh, + EXTRACT(DAY_HOUR FROM b), + EXTRACT(DAY FROM b), + EXTRACT(HOUR FROM b), + EXTRACT(MINUTE FROM b), + EXTRACT(SECOND FROM b), + EXTRACT(MICROSECOND FROM b) +FROM t1; +DROP TABLE t1; + +--echo # Special case: DAY + TIME +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES ('9999-01-01'); +SELECT a, + EXTRACT(DAY_HOUR FROM a), + EXTRACT(DAY_MINUTE FROM a), + EXTRACT(DAY_SECOND FROM a), + EXTRACT(DAY_MICROSECOND FROM a), + EXTRACT(DAY FROM a), + EXTRACT(HOUR FROM a), + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a) +FROM t1; +DROP TABLE t1; + +--echo # Bad values +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES (''); +SELECT a, + CAST(a AS INTERVAL DAY_SECOND(6)) AS cidm, + EXTRACT(DAY_HOUR FROM a), + EXTRACT(DAY_MINUTE FROM a), + EXTRACT(DAY_SECOND FROM a), + EXTRACT(DAY_MICROSECOND FROM a), + EXTRACT(DAY FROM a), + EXTRACT(HOUR FROM a), + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a) +FROM t1; +DROP TABLE t1; + + +--echo # Backward compatibility + +--echo # This still parses as DATETIME +SELECT EXTRACT(YEAR FROM '2001/02/03 10:20:30'); +SELECT EXTRACT(MONTH FROM '2001/02/03 10:20:30'); +SELECT EXTRACT(DAY FROM '2001/02/03 10:20:30'); + +SELECT EXTRACT(YEAR FROM '01/02/03 10:20:30'); +SELECT EXTRACT(MONTH FROM '01/02/03 10:20:30'); +SELECT EXTRACT(DAY FROM '01/02/03 10:20:30'); + +SELECT EXTRACT(YEAR FROM '01:02:03 10:20:30'); +SELECT EXTRACT(MONTH FROM '01:02:03 10:20:30'); +SELECT EXTRACT(DAY FROM '01:02:03 10:20:30'); + +--echo # This still parses as DATETIME and returns NULL + +SELECT EXTRACT(YEAR FROM "2011-02-32 8:46:06.23434"); +SELECT EXTRACT(MONTH FROM "2011-02-32 8:46:06.23434"); +SELECT EXTRACT(DAY FROM "2011-02-32 8:46:06.23434"); +SELECT EXTRACT(HOUR FROM "2011-02-32 8:46:06.23434"); + +--echo # This still parses as DATE + +SELECT EXTRACT(YEAR FROM '2001/02/03'); +SELECT EXTRACT(MONTH FROM '2001/02/03'); +SELECT EXTRACT(DAY FROM '2001/02/03'); + +SELECT EXTRACT(YEAR FROM '01/02/03'); +SELECT EXTRACT(MONTH FROM '01/02/03'); +SELECT EXTRACT(DAY FROM '01/02/03'); + +SELECT EXTRACT(YEAR FROM '01-02-03'); +SELECT EXTRACT(MONTH FROM '01-02-03'); +SELECT EXTRACT(DAY FROM '01-02-03'); + +SELECT EXTRACT(YEAR FROM '1-2-3'); +SELECT EXTRACT(MONTH FROM '1-2-3'); +SELECT EXTRACT(DAY FROM '1-2-3'); +SELECT EXTRACT(HOUR FROM '1-2-3'); + +SELECT EXTRACT(DAY FROM '2024-01-03 garbage /////'); +SELECT EXTRACT(DAY FROM '24-01-03 garbage /////'); +SELECT EXTRACT(DAY FROM '01-02-03'); + +SELECT EXTRACT(DAY FROM '24:02:03T'); +SELECT EXTRACT(DAY FROM '24-02-03'); +SELECT EXTRACT(DAY FROM '24/02/03'); + +SELECT EXTRACT(DAY FROM '11111'); + +SELECT TIME('2001-01-01T'), TIME('2001-01-01T '); +SELECT TIME('2001/01/01T'), TIME('2001/01/01T '); +SELECT TIME('2001:01:01T'), TIME('2001:01:01T '); + +SELECT EXTRACT(DAY FROM '2001-01-01T'), EXTRACT(DAY FROM '2001-01-01T '); +SELECT EXTRACT(DAY FROM '2001/01/01T'), EXTRACT(DAY FROM '2001/01/01T '); +SELECT EXTRACT(DAY FROM '2001:01:01T'), EXTRACT(DAY FROM '2001:01:01T '); + + +SELECT TIME('2001:01:01T'), TIME('2001:01:01T '); +SELECT EXTRACT(HOUR FROM '2001-01-01T'), EXTRACT(HOUR FROM '2001-01-01T '); +SELECT EXTRACT(HOUR FROM '2001/01/01T'), EXTRACT(HOUR FROM '2001/01/01T '); +SELECT EXTRACT(HOUR FROM '2001:01:01T'), EXTRACT(HOUR FROM '2001:01:01T '); + +--echo # This still parses as DATE and returns NULL (without trying TIME) +SELECT EXTRACT(DAY FROM '100000:02:03T'); +SELECT EXTRACT(DAY FROM '100000/02/03'); +SELECT EXTRACT(DAY FROM '100000-02-03'); + +SELECT EXTRACT(DAY FROM '1111'); +SELECT EXTRACT(DAY FROM '111'); +SELECT EXTRACT(DAY FROM '11'); +SELECT EXTRACT(DAY FROM '1'); + + +--echo # This still parses as TIME + +SELECT EXTRACT(HOUR FROM '11111'); +SELECT EXTRACT(HOUR FROM '1111'); +SELECT EXTRACT(HOUR FROM '111'); +SELECT EXTRACT(HOUR FROM '11'); +SELECT EXTRACT(HOUR FROM '1'); + +SELECT TIME('01:02:03:'); +SELECT TIME('01:02:03-'); +SELECT TIME('01:02:03;'); +SELECT TIME('01:02:03/'); + +SELECT EXTRACT(HOUR FROM '01:02:03:'); +SELECT EXTRACT(HOUR FROM '01:02:03-'); +SELECT EXTRACT(HOUR FROM '01:02:03;'); +SELECT EXTRACT(HOUR FROM '01:02:03/'); + +--echo # Backward compatibility preserved for YEAR and MONTH only +--echo # (behavior has changed for DAY, see below) +SELECT EXTRACT(YEAR FROM '01:02:03'); +SELECT EXTRACT(MONTH FROM '01:02:03'); + +SELECT EXTRACT(YEAR FROM '24:01:03 garbage /////'); +SELECT EXTRACT(MONTH FROM '24:01:03 garbage /////'); + +--echo # This still parses as TIME 00:20:01 + +SELECT TIME('2001/01/01'); +SELECT TIME('2001-01-01'); + +--echo # This still parses as TIME and overflows to '838:59:59' +SELECT TIME('2001:01:01'); + + +--echo # This used to parse as DATE, now parses as TIME interval + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2024:01:03 garbage /////'), +('24:01:03 garbage /////'), +('01:01:03 garbage /////'), +('2024:02:03'), +('100000:02:03'), +('24:02:03'), +('01:02:03'), +('01:02:03:'), +('01:02:03-'), +('01:02:03;'), +('01:02:03/'), +('20 10:20:30'); + +SELECT + EXTRACT(DAY FROM a), + EXTRACT(DAY_SECOND FROM a), a, + CAST(a AS INTERVAL DAY_SECOND(6)) AS cidm +FROM t1; +DROP TABLE t1; diff --git a/mysql-test/main/func_group_innodb.result b/mysql-test/main/func_group_innodb.result index 27493ae710b..a2251f2b348 100644 --- a/mysql-test/main/func_group_innodb.result +++ b/mysql-test/main/func_group_innodb.result @@ -244,6 +244,6 @@ MIN(c) 0 EXPLAIN SELECT MIN(c) FROM t1 GROUP BY b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range NULL b 263 NULL 3 Using index for group-by +1 SIMPLE t1 range NULL b 263 NULL 2 Using index for group-by DROP TABLE t1; End of 5.5 tests diff --git a/mysql-test/main/func_hybrid_type.result b/mysql-test/main/func_hybrid_type.result index ebf7191a3f7..a86fd8d1d6f 100644 --- a/mysql-test/main/func_hybrid_type.result +++ b/mysql-test/main/func_hybrid_type.result @@ -3755,3 +3755,193 @@ DROP TABLE t1; # # End of 10.3 tests # +# +# Start of 10.4 tests +# +# +# MDEV-17325 NULL-ability problems with LEAST() in combination with NO_ZERO_DATE and NO_ZERO_IN_DATE +# +SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE'; +SELECT +LEAST('0000-00-00',DATE'2001-01-01') AS s1, +LEAST('0001-00-01',DATE'2001-01-01') AS s2, +LEAST('0000-00-00',TIMESTAMP'2001-01-01 00:00:00') AS s3, +LEAST('0001-00-01',TIMESTAMP'2001-01-01 00:00:00') AS s4, +LEAST(0,DATE'2001-01-01') AS i1, +LEAST(20010001,DATE'2001-01-01') AS i2, +LEAST(0,TIMESTAMP'2001-01-01 00:00:00') AS i3, +LEAST(20010001,TIMESTAMP'2001-01-01 00:00:00') AS i4; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def s1 10 10 0 Y 128 0 63 +def s2 10 10 0 Y 128 0 63 +def s3 12 26 0 Y 128 0 63 +def s4 12 26 0 Y 128 0 63 +def i1 10 10 0 Y 128 0 63 +def i2 10 10 0 Y 128 0 63 +def i3 12 19 0 Y 128 0 63 +def i4 12 19 0 Y 128 0 63 +s1 s2 s3 s4 i1 i2 i3 i4 +NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0001-00-01' +Warning 1292 Incorrect datetime value: '0000-00-00 00:00:00' +Warning 1292 Incorrect datetime value: '0001-00-01 00:00:00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '2001-00-01' +Warning 1292 Incorrect datetime value: '0000-00-00 00:00:00' +Warning 1292 Incorrect datetime value: '2001-00-01 00:00:00' +SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE'; +CREATE TABLE t1 AS SELECT +LEAST('0000-00-00',DATE'2001-01-01') AS s1, +LEAST('0001-00-01',DATE'2001-01-01') AS s2, +LEAST('0000-00-00',TIMESTAMP'2001-01-01 00:00:00') AS s3, +LEAST('0001-00-01',TIMESTAMP'2001-01-01 00:00:00') AS s4, +LEAST(0,DATE'2001-01-01') AS i1, +LEAST(20010001,DATE'2001-01-01') AS i2, +LEAST(0,TIMESTAMP'2001-01-01 00:00:00') AS i3, +LEAST(20010001,TIMESTAMP'2001-01-01 00:00:00') AS i4; +Warnings: +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0001-00-01' +Warning 1292 Incorrect datetime value: '0000-00-00 00:00:00' +Warning 1292 Incorrect datetime value: '0001-00-01 00:00:00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '2001-00-01' +Warning 1292 Incorrect datetime value: '0000-00-00 00:00:00' +Warning 1292 Incorrect datetime value: '2001-00-01 00:00:00' +SELECT * FROM t1; +s1 s2 s3 s4 i1 i2 i3 i4 +NULL NULL NULL NULL NULL NULL NULL NULL +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `s1` date DEFAULT NULL, + `s2` date DEFAULT NULL, + `s3` datetime DEFAULT NULL, + `s4` datetime DEFAULT NULL, + `i1` date DEFAULT NULL, + `i2` date DEFAULT NULL, + `i3` datetime DEFAULT NULL, + `i4` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30'); +CREATE TABLE t1 AS SELECT LEAST(CURRENT_DATE,CURRENT_TIME) AS c1; +SELECT * FROM t1; +c1 +2001-01-01 00:00:00 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` datetime NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET old_mode=ZERO_DATE_TIME_CAST; +CREATE TABLE t1 AS SELECT LEAST(CURRENT_DATE,CURRENT_TIME) AS c1; +Warnings: +Warning 1292 Incorrect datetime value: '0000-00-00 10:20:30' +SELECT * FROM t1; +c1 +NULL +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` datetime DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET old_mode=DEFAULT; +SET timestamp=DEFAULT; +SET sql_mode=DEFAULT; +SET sql_mode=''; +SELECT LEAST(999,TIME'10:20:30') AS c1; +c1 +NULL +Warnings: +Warning 1292 Incorrect time value: '999' +CREATE TABLE t1 AS SELECT LEAST(999,TIME'10:20:30') AS c1; +Warnings: +Warning 1292 Incorrect time value: '999' +SELECT * FROM t1; +c1 +NULL +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` time DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET sql_mode=DEFAULT; +# +# MDEV-17318 CAST(LEAST(zero_date,non_zero_date) AS numeric_data_type) returns a wrong result +# +SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE'; +SELECT +LEAST('0000-00-00',DATE'2001-01-01') AS c0, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS CHAR) AS string, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATE) AS date, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATETIME) AS datetime, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS TIME) AS time, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DECIMAL) AS dc, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DOUBLE) AS dbl, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS SIGNED) AS sint, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS UNSIGNED) AS uint; +c0 string date datetime time dc dbl sint uint +NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +CREATE TABLE t1 AS SELECT +LEAST('0000-00-00',DATE'2001-01-01') AS c0, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS CHAR) AS string, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATE) AS date, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATETIME) AS datetime, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS TIME) AS time, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DECIMAL) AS dc, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DOUBLE) AS dbl, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS SIGNED) AS sint, +CAST(LEAST('0000-00-00',DATE'2001-01-01') AS UNSIGNED) AS uint; +Warnings: +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' +SELECT * FROM t1; +c0 string date datetime time dc dbl sint uint +NULL NULL NULL NULL NULL NULL NULL NULL NULL +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c0` date DEFAULT NULL, + `string` varchar(10) DEFAULT NULL, + `date` date DEFAULT NULL, + `datetime` datetime DEFAULT NULL, + `time` time DEFAULT NULL, + `dc` decimal(10,0) DEFAULT NULL, + `dbl` double DEFAULT NULL, + `sint` bigint(10) DEFAULT NULL, + `uint` bigint(20) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET sql_mode=DEFAULT; +# +# MDEV-17330 Wrong result for 0 + LEAST(TIME'-10:00:00',TIME'10:00:00') +# +SELECT 0 + LEAST(TIME'-10:00:00',TIME'10:00:00') AS c; +c +-100000 +# +# End of 10.4 tests +# diff --git a/mysql-test/main/func_hybrid_type.test b/mysql-test/main/func_hybrid_type.test index 954c7de53fa..6b32f331d34 100644 --- a/mysql-test/main/func_hybrid_type.test +++ b/mysql-test/main/func_hybrid_type.test @@ -615,3 +615,108 @@ DROP TABLE t1; --echo # End of 10.3 tests --echo # +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-17325 NULL-ability problems with LEAST() in combination with NO_ZERO_DATE and NO_ZERO_IN_DATE +--echo # + +SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE'; + +--disable_ps_protocol +--enable_metadata +SELECT + LEAST('0000-00-00',DATE'2001-01-01') AS s1, + LEAST('0001-00-01',DATE'2001-01-01') AS s2, + LEAST('0000-00-00',TIMESTAMP'2001-01-01 00:00:00') AS s3, + LEAST('0001-00-01',TIMESTAMP'2001-01-01 00:00:00') AS s4, + LEAST(0,DATE'2001-01-01') AS i1, + LEAST(20010001,DATE'2001-01-01') AS i2, + LEAST(0,TIMESTAMP'2001-01-01 00:00:00') AS i3, + LEAST(20010001,TIMESTAMP'2001-01-01 00:00:00') AS i4; +--disable_metadata +--enable_ps_protocol + +SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE'; +CREATE TABLE t1 AS SELECT + LEAST('0000-00-00',DATE'2001-01-01') AS s1, + LEAST('0001-00-01',DATE'2001-01-01') AS s2, + LEAST('0000-00-00',TIMESTAMP'2001-01-01 00:00:00') AS s3, + LEAST('0001-00-01',TIMESTAMP'2001-01-01 00:00:00') AS s4, + LEAST(0,DATE'2001-01-01') AS i1, + LEAST(20010001,DATE'2001-01-01') AS i2, + LEAST(0,TIMESTAMP'2001-01-01 00:00:00') AS i3, + LEAST(20010001,TIMESTAMP'2001-01-01 00:00:00') AS i4; +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30'); + +# A TIME always converts to a non-NULL DATETIME with the new CAST style +# Expect a NOT NULL column +CREATE TABLE t1 AS SELECT LEAST(CURRENT_DATE,CURRENT_TIME) AS c1; +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +# A TIME can convert to a NULL DATETIME with old CAST style +# Expect a NULL-able column +SET old_mode=ZERO_DATE_TIME_CAST; +CREATE TABLE t1 AS SELECT LEAST(CURRENT_DATE,CURRENT_TIME) AS c1; +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET old_mode=DEFAULT; +SET timestamp=DEFAULT; + +SET sql_mode=DEFAULT; + +SET sql_mode=''; +SELECT LEAST(999,TIME'10:20:30') AS c1; +CREATE TABLE t1 AS SELECT LEAST(999,TIME'10:20:30') AS c1; +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET sql_mode=DEFAULT; + +--echo # +--echo # MDEV-17318 CAST(LEAST(zero_date,non_zero_date) AS numeric_data_type) returns a wrong result +--echo # +SET sql_mode='NO_ZERO_DATE,NO_ZERO_IN_DATE'; +SELECT + LEAST('0000-00-00',DATE'2001-01-01') AS c0, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS CHAR) AS string, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATE) AS date, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATETIME) AS datetime, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS TIME) AS time, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DECIMAL) AS dc, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DOUBLE) AS dbl, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS SIGNED) AS sint, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS UNSIGNED) AS uint; +CREATE TABLE t1 AS SELECT + LEAST('0000-00-00',DATE'2001-01-01') AS c0, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS CHAR) AS string, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATE) AS date, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DATETIME) AS datetime, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS TIME) AS time, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DECIMAL) AS dc, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS DOUBLE) AS dbl, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS SIGNED) AS sint, + CAST(LEAST('0000-00-00',DATE'2001-01-01') AS UNSIGNED) AS uint; +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET sql_mode=DEFAULT; + +--echo # +--echo # MDEV-17330 Wrong result for 0 + LEAST(TIME'-10:00:00',TIME'10:00:00') +--echo # +SELECT 0 + LEAST(TIME'-10:00:00',TIME'10:00:00') AS c; + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/func_in.result b/mysql-test/main/func_in.result index 65313148bf8..acf718c453e 100644 --- a/mysql-test/main/func_in.result +++ b/mysql-test/main/func_in.result @@ -481,7 +481,7 @@ SELECT * FROM t4 WHERE a IN ('1972-02-06','19772-07-29'); a 1972-02-06 Warnings: -Warning 1292 Incorrect datetime value: '19772-07-29' +Warning 1292 Truncated incorrect datetime value: '19772-07-29' DROP TABLE t1,t2,t3,t4; CREATE TABLE t1 (id int not null); INSERT INTO t1 VALUES (1),(2); @@ -909,3 +909,38 @@ Warnings: Warning 1292 Truncated incorrect time value: '' Warning 1292 Truncated incorrect time value: '' Warning 1292 Truncated incorrect time value: '' +# +# End of 10.3 tests +# +# +# Start of 10.4 tests +# +# +# MDEV-16454 Bad results for IN with ROW +# +SELECT (18446744073709551615,0) IN ((18446744073709551614,0),(-1,0)); +(18446744073709551615,0) IN ((18446744073709551614,0),(-1,0)) +0 +SELECT '0x' IN (0); +'0x' IN (0) +1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '0x' +SELECT '0x' IN (0,1); +'0x' IN (0,1) +1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '0x' +SELECT ('0x',1) IN ((0,1)); +('0x',1) IN ((0,1)) +1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '0x' +SELECT ('0x',1) IN ((0,1),(1,1)); +('0x',1) IN ((0,1),(1,1)) +1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '0x' +# +# End of 10.4 tests +# diff --git a/mysql-test/main/func_in.test b/mysql-test/main/func_in.test index b99fad159c2..fb6f2036f20 100644 --- a/mysql-test/main/func_in.test +++ b/mysql-test/main/func_in.test @@ -690,3 +690,27 @@ SELECT TIME'00:00:00'='' AS c1_true, TIME'00:00:00' IN ('', TIME'10:20:30') AS c2_true, TIME'00:00:00' NOT IN ('', TIME'10:20:30') AS c3_false; + + +--echo # +--echo # End of 10.3 tests +--echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-16454 Bad results for IN with ROW +--echo # +SELECT (18446744073709551615,0) IN ((18446744073709551614,0),(-1,0)); + +SELECT '0x' IN (0); +SELECT '0x' IN (0,1); +SELECT ('0x',1) IN ((0,1)); +SELECT ('0x',1) IN ((0,1),(1,1)); + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 61dd55850ac..3eae5be2492 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -859,3 +859,91 @@ json_length json_depnth # # End of 10.3 tests # +# +# Start of 10.4 tests +# +# +# MDEV-16351 JSON_OBJECT() treats hybrid functions with boolean arguments as numbers +# +SELECT +JSON_OBJECT("cond", true) AS j1, +JSON_OBJECT("cond", COALESCE(true, false)) j2, +JSON_OBJECT("cond", COALESCE(COALESCE(true, false))) j3; +j1 {"cond": true} +j2 {"cond": true} +j3 {"cond": true} +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT JSON_OBJECT('x',(SELECT MAX(a)=4 FROM t1)); +JSON_OBJECT('x',(SELECT MAX(a)=4 FROM t1)) +{"x": false} +SELECT JSON_OBJECT('x',(SELECT MAX(a)=3 FROM t1)); +JSON_OBJECT('x',(SELECT MAX(a)=3 FROM t1)) +{"x": true} +SELECT JSON_OBJECT('x',(SELECT MAX(a)=2 FROM t1)); +JSON_OBJECT('x',(SELECT MAX(a)=2 FROM t1)) +{"x": false} +SELECT JSON_OBJECT('x',MAX(a=4)) FROM t1; +JSON_OBJECT('x',MAX(a=4)) +{"x": false} +SELECT JSON_OBJECT('x',MAX(a=3)) FROM t1; +JSON_OBJECT('x',MAX(a=3)) +{"x": true} +SELECT JSON_OBJECT('x',MAX(a=2)) FROM t1; +JSON_OBJECT('x',MAX(a=2)) +{"x": true} +SELECT JSON_OBJECT('x',(SELECT MAX(a=4) FROM t1)); +JSON_OBJECT('x',(SELECT MAX(a=4) FROM t1)) +{"x": false} +SELECT JSON_OBJECT('x',(SELECT MAX(a=3) FROM t1)); +JSON_OBJECT('x',(SELECT MAX(a=3) FROM t1)) +{"x": true} +SELECT JSON_OBJECT('x',(SELECT MAX(a=2) FROM t1)); +JSON_OBJECT('x',(SELECT MAX(a=2) FROM t1)) +{"x": true} +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=4 FROM t1))='{"x": true}' THEN a END; +a +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=4 FROM t1))='{"x": false}' THEN a END; +a +1 +2 +3 +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=3 FROM t1))='{"x": true}' THEN a END; +a +1 +2 +3 +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=3 FROM t1))='{"x": false}' THEN a END; +a +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=2 FROM t1))='{"x": true}' THEN a END; +a +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=2 FROM t1))='{"x": false}' THEN a END; +a +1 +2 +3 +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=4) FROM t1))='{"x": true}' THEN a END; +a +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=4) FROM t1))='{"x": false}' THEN a END; +a +1 +2 +3 +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=3) FROM t1))='{"x": true}' THEN a END; +a +1 +2 +3 +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=3) FROM t1))='{"x": false}' THEN a END; +a +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=2) FROM t1))='{"x": true}' THEN a END; +a +1 +2 +3 +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=2) FROM t1))='{"x": false}' THEN a END; +a +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index fabca504530..09ae35ad653 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -511,3 +511,53 @@ SELECT --echo # --echo # End of 10.3 tests --echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-16351 JSON_OBJECT() treats hybrid functions with boolean arguments as numbers +--echo # + +--vertical_results +SELECT + JSON_OBJECT("cond", true) AS j1, + JSON_OBJECT("cond", COALESCE(true, false)) j2, + JSON_OBJECT("cond", COALESCE(COALESCE(true, false))) j3; +--horizontal_results + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT JSON_OBJECT('x',(SELECT MAX(a)=4 FROM t1)); +SELECT JSON_OBJECT('x',(SELECT MAX(a)=3 FROM t1)); +SELECT JSON_OBJECT('x',(SELECT MAX(a)=2 FROM t1)); + +SELECT JSON_OBJECT('x',MAX(a=4)) FROM t1; +SELECT JSON_OBJECT('x',MAX(a=3)) FROM t1; +SELECT JSON_OBJECT('x',MAX(a=2)) FROM t1; + +SELECT JSON_OBJECT('x',(SELECT MAX(a=4) FROM t1)); +SELECT JSON_OBJECT('x',(SELECT MAX(a=3) FROM t1)); +SELECT JSON_OBJECT('x',(SELECT MAX(a=2) FROM t1)); + +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=4 FROM t1))='{"x": true}' THEN a END; +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=4 FROM t1))='{"x": false}' THEN a END; +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=3 FROM t1))='{"x": true}' THEN a END; +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=3 FROM t1))='{"x": false}' THEN a END; +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=2 FROM t1))='{"x": true}' THEN a END; +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a)=2 FROM t1))='{"x": false}' THEN a END; + +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=4) FROM t1))='{"x": true}' THEN a END; +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=4) FROM t1))='{"x": false}' THEN a END; +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=3) FROM t1))='{"x": true}' THEN a END; +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=3) FROM t1))='{"x": false}' THEN a END; +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=2) FROM t1))='{"x": true}' THEN a END; +SELECT * FROM t1 WHERE CASE WHEN JSON_OBJECT('x', (SELECT MAX(a=2) FROM t1))='{"x": false}' THEN a END; + + +DROP TABLE t1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/func_misc.result b/mysql-test/main/func_misc.result index 0ab07664e6c..2aa305191bd 100644 --- a/mysql-test/main/func_misc.result +++ b/mysql-test/main/func_misc.result @@ -1582,3 +1582,29 @@ SELECT * FROM t1; c1 c2 18446744073709551615 18446744073709551615 DROP TABLE t1; +# +# End of 10.3 tests +# +# +# Start of 10.4 tests +# +# +# MDEV-16309 Split ::create_tmp_field() into virtual methods in Item +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +BEGIN NOT ATOMIC +DECLARE a TEXT; +DECLARE c CURSOR FOR SELECT NAME_CONST('x','y') FROM t1; +OPEN c; +FETCH c INTO a; +CLOSE c; +SELECT a; +END; +$$ +a +y +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/func_misc.test b/mysql-test/main/func_misc.test index f8f2147e182..1301b172910 100644 --- a/mysql-test/main/func_misc.test +++ b/mysql-test/main/func_misc.test @@ -1218,3 +1218,33 @@ CREATE TABLE t1 AS SELECT 18446744073709551615 AS c1, name_const('a',18446744073 SHOW CREATE TABLE t1; SELECT * FROM t1; DROP TABLE t1; +--echo # +--echo # End of 10.3 tests +--echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-16309 Split ::create_tmp_field() into virtual methods in Item +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE a TEXT; + DECLARE c CURSOR FOR SELECT NAME_CONST('x','y') FROM t1; + OPEN c; + FETCH c INTO a; + CLOSE c; + SELECT a; +END; +$$ +DELIMITER ;$$ +DROP TABLE t1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/func_sapdb.result b/mysql-test/main/func_sapdb.result index 5b9743fb33f..27f1d74bc41 100644 --- a/mysql-test/main/func_sapdb.result +++ b/mysql-test/main/func_sapdb.result @@ -107,9 +107,13 @@ subtime("1997-12-31 23:59:59.000001", "1 1:1:1.000002") select addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999"); addtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999") NULL +Warnings: +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '1998-01-01 01:01:01.999999' select subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999"); subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999") NULL +Warnings: +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '1998-01-01 01:01:01.999999' select subtime("01:00:00.999999", "02:00:00.999998"); subtime("01:00:00.999999", "02:00:00.999998") -00:59:59.999999 @@ -180,7 +184,7 @@ select time("1997-12-31 25:59:59.000001"); time("1997-12-31 25:59:59.000001") NULL Warnings: -Warning 1292 Truncated incorrect time value: '1997-12-31 25:59:59.000001' +Warning 1292 Incorrect time value: '1997-12-31 25:59:59.000001' select microsecond("1997-12-31 23:59:59.000001"); microsecond("1997-12-31 23:59:59.000001") 1 diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result index 9a60f3e2718..007f5585c27 100644 --- a/mysql-test/main/func_time.result +++ b/mysql-test/main/func_time.result @@ -26,7 +26,7 @@ select sec_to_time('9001.1'), sec_to_time('1234567890123.123'); sec_to_time('9001.1') sec_to_time('1234567890123.123') 02:30:01.100000 838:59:59.999999 Warnings: -Warning 1292 Truncated incorrect time value: '1234567890123.123' +Warning 1292 Truncated incorrect seconds value: '1234567890123.123000' select sec_to_time(-9001.1), sec_to_time(-9001.1) / 1, sec_to_time(-9001.1) / 1e0, sec_to_time(-9001) div 1; sec_to_time(-9001.1) sec_to_time(-9001.1) / 1 sec_to_time(-9001.1) / 1e0 sec_to_time(-9001) div 1 @@ -35,13 +35,13 @@ select sec_to_time(90011e-1), sec_to_time(1234567890123e30); sec_to_time(90011e-1) sec_to_time(1234567890123e30) 02:30:01.100000 838:59:59.999999 Warnings: -Warning 1292 Truncated incorrect time value: '1.234567890123e42' +Warning 1292 Truncated incorrect seconds value: '1.234567890123e42' select sec_to_time(1234567890123), sec_to_time('99999999999999999999999999999'); sec_to_time(1234567890123) sec_to_time('99999999999999999999999999999') 838:59:59 838:59:59.999999 Warnings: -Warning 1292 Truncated incorrect time value: '1234567890123' -Warning 1292 Truncated incorrect time value: '99999999999999999999999999999' +Warning 1292 Truncated incorrect seconds value: '1234567890123' +Warning 1292 Truncated incorrect seconds value: '99999999999999999999999999999' select now()-curdate()*1000000-curtime(); now()-curdate()*1000000-curtime() 0 @@ -367,9 +367,7 @@ extract(DAY_MINUTE FROM "02 10:11:12") 21011 select extract(DAY_SECOND FROM "225 10:11:12"); extract(DAY_SECOND FROM "225 10:11:12") -34225959 -Warnings: -Warning 1292 Truncated incorrect time value: '225 10:11:12' +225101112 select extract(HOUR FROM "1999-01-02 10:11:12"); extract(HOUR FROM "1999-01-02 10:11:12") 10 @@ -584,6 +582,8 @@ from_unixtime(2147483647) select from_unixtime(2147483648); from_unixtime(2147483648) NULL +Warnings: +Warning 1292 Truncated incorrect unixtime value: '2147483648' select from_unixtime(0); from_unixtime(0) 1970-01-01 03:00:00 @@ -593,6 +593,8 @@ unix_timestamp(from_unixtime(2147483647)) select unix_timestamp(from_unixtime(2147483648)); unix_timestamp(from_unixtime(2147483648)) NULL +Warnings: +Warning 1292 Truncated incorrect unixtime value: '2147483648' select unix_timestamp('2039-01-20 01:00:00'); unix_timestamp('2039-01-20 01:00:00') NULL @@ -937,7 +939,7 @@ f1 select f1 from t1 where cast("2006-1-1" as date) between f1 and cast('zzz' as date); f1 Warnings: -Warning 1292 Incorrect datetime value: 'zzz' +Warning 1292 Truncated incorrect datetime value: 'zzz' select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); f1 2006-01-01 @@ -960,17 +962,17 @@ SELECT SEC_TO_TIME(3300000); SEC_TO_TIME(3300000) 838:59:59 Warnings: -Warning 1292 Truncated incorrect time value: '3300000' +Warning 1292 Truncated incorrect seconds value: '3300000' SELECT SEC_TO_TIME(3300000)+0; SEC_TO_TIME(3300000)+0 8385959 Warnings: -Warning 1292 Truncated incorrect time value: '3300000' +Warning 1292 Truncated incorrect seconds value: '3300000' SELECT SEC_TO_TIME(3600 * 4294967296); SEC_TO_TIME(3600 * 4294967296) 838:59:59 Warnings: -Warning 1292 Truncated incorrect time value: '15461882265600' +Warning 1292 Truncated incorrect seconds value: '15461882265600' SELECT TIME_TO_SEC('916:40:00'); TIME_TO_SEC('916:40:00') 3020399 @@ -1019,6 +1021,8 @@ NULL SELECT MAKETIME(0, 0, 4294967296); MAKETIME(0, 0, 4294967296) NULL +Warnings: +Warning 1292 Truncated incorrect seconds value: '4294967296' SELECT MAKETIME(CAST(-1 AS UNSIGNED), 0, 0); MAKETIME(CAST(-1 AS UNSIGNED), 0, 0) 838:59:59 @@ -1027,9 +1031,7 @@ Note 1105 Cast to unsigned converted negative integer to it's positive complemen Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00' SELECT EXTRACT(HOUR FROM '10000:02:03'); EXTRACT(HOUR FROM '10000:02:03') -22 -Warnings: -Warning 1292 Truncated incorrect time value: '10000:02:03' +16 CREATE TABLE t1(f1 TIME); INSERT IGNORE INTO t1 VALUES('916:00:00 a'); Warnings: @@ -1044,8 +1046,7 @@ SEC_TO_TIME(CAST(-1 AS UNSIGNED)) 838:59:59 Warnings: Note 1105 Cast to unsigned converted negative integer to it's positive complement -Note 1105 Cast to unsigned converted negative integer to it's positive complement -Warning 1292 Truncated incorrect time value: '18446744073709551615' +Warning 1292 Truncated incorrect seconds value: '18446744073709551615' SET NAMES latin1; SET character_set_results = NULL; SHOW VARIABLES LIKE 'character_set_results'; @@ -1058,6 +1059,7 @@ fmtddate field2 Sep-4 12:00AM abcd DROP TABLE testBug8868; SET NAMES DEFAULT; +SET TIMESTAMP=UNIX_TIMESTAMP('2001-01-01 11:22:33'); CREATE TABLE t1 ( a TIMESTAMP ); @@ -1066,7 +1068,11 @@ SELECT 1 FROM t1 ORDER BY MAKETIME(1, 1, a); 1 1 1 +Warnings: +Warning 1292 Truncated incorrect seconds value: '20010101112233' +Warning 1292 Truncated incorrect seconds value: '20010101112233' DROP TABLE t1; +SET TIMESTAMP=DEFAULT; (select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H) union (select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H); @@ -1095,7 +1101,7 @@ week(20061108), week(20061108.01), week(20061108085411.000002); isnull(week(now() + 0)) isnull(week(now() + 0.2)) week(20061108) week(20061108.01) week(20061108085411.000002) 0 0 45 45 45 Warnings: -Warning 1292 Truncated incorrect datetime value: '20061108.01' +Note 1292 Truncated incorrect date value: '20061108.01' End of 4.1 tests select time_format('100:00:00', '%H %k %h %I %l'); time_format('100:00:00', '%H %k %h %I %l') @@ -1230,7 +1236,7 @@ str_to_date("1997-00-04 22:23:00","%Y-%m-%D") + interval 10 minute NULL Warnings: Warning 1292 Truncated incorrect date value: '1997-00-04 22:23:00' -Warning 1292 Incorrect datetime value: '1997-00-04' +Warning 1292 Incorrect datetime value: '1997-00-04 00:00:00' create table t1 (field DATE); insert into t1 values ('2006-11-06'); select * from t1 where field < '2006-11-06 04:08:36.0'; @@ -1372,9 +1378,9 @@ SELECT COUNT(*) FROM t1 GROUP BY TIME_TO_SEC(a); COUNT(*) 2 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '' DROP TABLE t1; # # Bug#11766112 59151:UNINITIALIZED VALUES IN EXTRACT_DATE_TIME WITH STR_TO_DATE(SPACE(..) ... @@ -1716,7 +1722,6 @@ min(timestampadd(month, 1>'', from_days('%Z'))) NULL Warnings: Warning 1292 Truncated incorrect INTEGER value: '%Z' -Warning 1292 Truncated incorrect DOUBLE value: '' Warning 1292 Incorrect datetime value: '0000-00-00' SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:00'); create table t1(a time); @@ -1726,7 +1731,7 @@ select 1 from t1 where 1 < some (select cast(a as datetime) from t1); 1 1 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' drop table t1; SET timestamp=DEFAULT; # @@ -1833,7 +1838,7 @@ select cast('131415.123e0' as time); cast('131415.123e0' as time) NULL Warnings: -Warning 1292 Truncated incorrect time value: '131415.123e0' +Warning 1292 Incorrect time value: '131415.123e0' select cast('2010-01-02 03:04:05' as datetime) between null and '2010-01-02 03:04:04'; cast('2010-01-02 03:04:05' as datetime) between null and '2010-01-02 03:04:04' 0 @@ -1909,7 +1914,7 @@ select least(1, f1) from t1; least(1, f1) 0000-00-00 00:00:00 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' drop table t1; SET timestamp=UNIX_TIMESTAMP('2014-04-14 10:10:10'); select now() > coalesce(time('21:43:24'), date('2010-05-03')); @@ -2510,7 +2515,7 @@ TIMESTAMP('2001-01-01','10:10:10.12345'), TIMESTAMP('2001-01-01','10:10:10.123456'), TIMESTAMP('2001-01-01','10:10:10.1234567'); Warnings: -Note 1292 Truncated incorrect time value: '10:10:10.1234567' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '10:10:10.1234567' SHOW COLUMNS FROM t1; Field Type Null Key Default Extra TIMESTAMP('2001-01-01','10:10:10') datetime YES NULL @@ -2631,7 +2636,7 @@ SELECT DATE_ADD('2001-01-01 10:20:30',INTERVAL 250000000000.0 SECOND) AS c1, DAT c1 c2 9923-03-10 22:47:10.0 NULL Warnings: -Warning 1292 Truncated incorrect DECIMAL value: '2000000000000000000.0' +Warning 1292 Truncated incorrect seconds value: '2000000000000000000.0' # # MDEV-4838 Wrong metadata for DATE_ADD('string', INVERVAL) # @@ -2790,13 +2795,12 @@ DO TO_DAYS(SEC_TO_TIME(MAKEDATE('',RAND(~(''))))); Warnings: Warning 1292 Truncated incorrect INTEGER value: '' Warning 1292 Truncated incorrect INTEGER value: '' -Warning 1292 Truncated incorrect INTEGER value: '' -Warning 1292 Truncated incorrect time value: '20000101' +Warning 1292 Truncated incorrect seconds value: '20000101' SELECT SEC_TO_TIME(MAKEDATE(0,RAND(~0))); SEC_TO_TIME(MAKEDATE(0,RAND(~0))) 838:59:59 Warnings: -Warning 1292 Truncated incorrect time value: '20000101' +Warning 1292 Truncated incorrect seconds value: '20000101' SELECT PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')); PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')) 24257 @@ -3132,7 +3136,7 @@ def EXTRACT(YEAR_MONTH FROM a) 3 6 6 Y 32896 0 63 def EXTRACT(QUARTER FROM a) 3 2 1 Y 32896 0 63 def EXTRACT(MONTH FROM a) 3 2 2 Y 32896 0 63 def EXTRACT(WEEK FROM a) 3 2 2 Y 32896 0 63 -def EXTRACT(DAY FROM a) 3 2 2 Y 32896 0 63 +def EXTRACT(DAY FROM a) 3 3 2 Y 32896 0 63 def EXTRACT(DAY_HOUR FROM a) 3 5 4 Y 32896 0 63 def EXTRACT(DAY_MINUTE FROM a) 3 7 6 Y 32896 0 63 def EXTRACT(DAY_SECOND FROM a) 3 9 8 Y 32896 0 63 @@ -3222,7 +3226,7 @@ t2 CREATE TABLE `t2` ( `EXTRACT(QUARTER FROM a)` int(2) DEFAULT NULL, `EXTRACT(MONTH FROM a)` int(2) DEFAULT NULL, `EXTRACT(WEEK FROM a)` int(2) DEFAULT NULL, - `EXTRACT(DAY FROM a)` int(2) DEFAULT NULL, + `EXTRACT(DAY FROM a)` int(3) DEFAULT NULL, `EXTRACT(DAY_HOUR FROM a)` int(5) DEFAULT NULL, `EXTRACT(DAY_MINUTE FROM a)` int(7) DEFAULT NULL, `EXTRACT(DAY_SECOND FROM a)` int(9) DEFAULT NULL, @@ -3271,7 +3275,7 @@ def EXTRACT(YEAR_MONTH FROM a) 3 6 1 Y 32896 0 63 def EXTRACT(QUARTER FROM a) 3 2 1 Y 32896 0 63 def EXTRACT(MONTH FROM a) 3 2 1 Y 32896 0 63 def EXTRACT(WEEK FROM a) 3 2 9 Y 32896 0 63 -def EXTRACT(DAY FROM a) 3 2 2 Y 32896 0 63 +def EXTRACT(DAY FROM a) 3 3 3 Y 32896 0 63 def EXTRACT(DAY_HOUR FROM a) 3 5 5 Y 32896 0 63 def EXTRACT(DAY_MINUTE FROM a) 3 7 7 Y 32896 0 63 def EXTRACT(DAY_SECOND FROM a) 3 9 9 Y 32896 0 63 @@ -3292,7 +3296,7 @@ EXTRACT(YEAR_MONTH FROM a) 0 EXTRACT(QUARTER FROM a) 0 EXTRACT(MONTH FROM a) 0 EXTRACT(WEEK FROM a) 613566757 -EXTRACT(DAY FROM a) 34 +EXTRACT(DAY FROM a) -34 EXTRACT(DAY_HOUR FROM a) -3422 EXTRACT(DAY_MINUTE FROM a) -342259 EXTRACT(DAY_SECOND FROM a) -34225959 @@ -3358,7 +3362,7 @@ EXTRACT(YEAR_MONTH FROM a) 0 EXTRACT(QUARTER FROM a) 0 EXTRACT(MONTH FROM a) 0 EXTRACT(WEEK FROM a) 613566757 -EXTRACT(DAY FROM a) 34 +EXTRACT(DAY FROM a) -34 EXTRACT(DAY_HOUR FROM a) -3422 EXTRACT(DAY_MINUTE FROM a) -342259 EXTRACT(DAY_SECOND FROM a) -34225959 @@ -3403,7 +3407,7 @@ t2 CREATE TABLE `t2` ( `EXTRACT(QUARTER FROM a)` int(2) DEFAULT NULL, `EXTRACT(MONTH FROM a)` int(2) DEFAULT NULL, `EXTRACT(WEEK FROM a)` int(2) DEFAULT NULL, - `EXTRACT(DAY FROM a)` int(2) DEFAULT NULL, + `EXTRACT(DAY FROM a)` int(3) DEFAULT NULL, `EXTRACT(DAY_HOUR FROM a)` int(5) DEFAULT NULL, `EXTRACT(DAY_MINUTE FROM a)` int(7) DEFAULT NULL, `EXTRACT(DAY_SECOND FROM a)` int(9) DEFAULT NULL, @@ -3445,7 +3449,7 @@ NULL NULL NULL Warnings: -Warning 1292 Incorrect datetime value: '18446744073709551615' +Warning 1292 Truncated incorrect datetime value: '18446744073709551615' CREATE TABLE t2 (pk int default 1, a1 date); INSERT INTO t2 VALUES (4,NULL); CREATE view v2 as SELECT default(t1.pk), default(t2.pk), t1.pk from t1,t2; @@ -3623,6 +3627,11 @@ ADDTIME(TIME'10:20:30', DATE'2001-01-01') AS c3, ADDTIME(TIME'10:20:30', COALESCE(DATE'2001-01-01',TIMESTAMP'2001-01-01 00:00:00')) AS c4; c1 c2 c3 c4 NULL NULL NULL NULL +Warnings: +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '2001-01-01 00:00:00' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '2001-01-01 00:00:00' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '2001-01-01' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '2001-01-01 00:00:00' SELECT HOUR(TIMESTAMP'0000-00-01 10:00:00') AS h0, TIME_TO_SEC(TIMESTAMP'0000-00-01 10:00:00') AS tts0, @@ -3743,13 +3752,21 @@ SET @sav_slow_query_log= @@session.slow_query_log; SET @@session.slow_query_log= ON; SELECT current_timestamp(6),fn_sleep_before_now() INTO @ts_cur, @ts_func; SELECT a FROM t_ts LIMIT 1 into @ts_func; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT a FROM t_trig LIMIT 1 into @ts_trig; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead DELETE FROM t_ts; DELETE FROM t_trig; SET @@session.slow_query_log= OFF; SELECT current_timestamp(6),fn_sleep_before_now() INTO @ts_cur, @func_ts; SELECT a FROM t_ts LIMIT 1 into @ts_func; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT a FROM t_trig LIMIT 1 into @ts_trig; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SET @@session.slow_query_log= @sav_slow_query_log; DROP FUNCTION fn_sleep_before_now; DROP TRIGGER trg_insert_t_ts; @@ -3789,3 +3806,2503 @@ c1 c2 c3 # # End of 10.3 tests # +# +# MDEV-14032 SEC_TO_TIME executes side effect two times +# +SET @a=10000000; +SELECT SEC_TO_TIME(@a:=@a+1); +SEC_TO_TIME(@a:=@a+1) +838:59:59 +Warnings: +Warning 1292 Truncated incorrect seconds value: '10000001' +SELECT @a; +@a +10000001 +CREATE TABLE t1 (a TEXT); +CREATE FUNCTION f1() RETURNS INT +BEGIN +INSERT INTO t1 VALUES ('f1 was called'); +RETURN 10000000; +END; +$$ +SELECT SEC_TO_TIME(f1()); +SEC_TO_TIME(f1()) +838:59:59 +Warnings: +Warning 1292 Truncated incorrect seconds value: '10000000' +SELECT * FROM t1; +a +f1 was called +DROP TABLE t1; +DROP FUNCTION f1; +# +# MDEV-17351 MICROSECOND(XXX(int_number_out_of_range)) erroneously returns 999999 +# +# Reject anything that's parsed as DATETIME or DATE +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2001-01-01 10:20:30'), +('01-01-01 10:20:30'), +('2001-01-01 '), +('20010101102030'), +('010101102030'); +SELECT ADDTIME(DATE'2001-01-01',a), a FROM t1; +ADDTIME(DATE'2001-01-01',a) a +NULL 2001-01-01 10:20:30 +NULL 01-01-01 10:20:30 +NULL 2001-01-01 +NULL 20010101102030 +NULL 010101102030 +Warnings: +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '2001-01-01 10:20:30' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '01-01-01 10:20:30' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '2001-01-01 ' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '20010101102030' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '010101102030' +DROP TABLE t1; +# GREATEST(decimal, time) +SELECT +GREATEST(8395959, TIME'00:00:00') AS c0, +GREATEST(8395959.0, TIME'00:00:00') AS c1, +GREATEST(8395959.00, TIME'00:00:00') AS c2, +GREATEST(8395959.000, TIME'00:00:00') AS c3, +GREATEST(8395959.0000, TIME'00:00:00') AS c4, +GREATEST(8395959.00000, TIME'00:00:00') AS c5, +GREATEST(8395959.000000, TIME'00:00:00') AS c6, +GREATEST(8395959.0000000, TIME'00:00:00') AS c7; +c0 838:59:59 +c1 838:59:59.9 +c2 838:59:59.99 +c3 838:59:59.999 +c4 838:59:59.9999 +c5 838:59:59.99999 +c6 838:59:59.999999 +c7 838:59:59.999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.0' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.0000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.00000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.000000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.0000000' +SELECT +MICROSECOND(GREATEST(8395959, TIME'00:00:00')) AS c0, +MICROSECOND(GREATEST(8395959.0, TIME'00:00:00')) AS c1, +MICROSECOND(GREATEST(8395959.00, TIME'00:00:00')) AS c2, +MICROSECOND(GREATEST(8395959.000, TIME'00:00:00')) AS c3, +MICROSECOND(GREATEST(8395959.0000, TIME'00:00:00')) AS c4, +MICROSECOND(GREATEST(8395959.00000, TIME'00:00:00')) AS c5, +MICROSECOND(GREATEST(8395959.000000, TIME'00:00:00')) AS c6, +MICROSECOND(GREATEST(8395959.0000000, TIME'00:00:00')) AS c7; +c0 0 +c1 900000 +c2 990000 +c3 999000 +c4 999900 +c5 999990 +c6 999999 +c7 999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.0' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.0000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.00000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.000000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959.0000000' +SELECT +CAST(GREATEST(8395959, TIME'00:00:00') AS SIGNED) AS ci, +CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,0)) AS c0, +CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,1)) AS c1, +CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,2)) AS c2, +CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,3)) AS c3, +CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,4)) AS c4, +CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,5)) AS c5, +CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,6)) AS c6, +CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,7)) AS c7; +ci 8385959 +c0 8385959 +c1 8385959.0 +c2 8385959.00 +c3 8385959.000 +c4 8385959.0000 +c5 8385959.00000 +c6 8385959.000000 +c7 8385959.0000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +SELECT +GREATEST(8395959, TIME'00:00:00') AS ci, +GREATEST(8395959, TIME'00:00:00')+0 AS c0, +GREATEST(8395959, TIME'00:00:00')+0.0 AS c1, +GREATEST(8395959, TIME'00:00:00')+0.00 AS c2, +GREATEST(8395959, TIME'00:00:00')+0.000 AS c3, +GREATEST(8395959, TIME'00:00:00')+0.0000 AS c4, +GREATEST(8395959, TIME'00:00:00')+0.00000 AS c5, +GREATEST(8395959, TIME'00:00:00')+0.000000 AS c6, +GREATEST(8395959, TIME'00:00:00')+0.0000000 AS c7; +ci 838:59:59 +c0 8385959 +c1 8385959.0 +c2 8385959.00 +c3 8385959.000 +c4 8385959.0000 +c5 8385959.00000 +c6 8385959.000000 +c7 8385959.0000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +Level Warning +Code 1292 +Message Truncated incorrect time value: '8395959' +# GREATEST(string, time) +SELECT +GREATEST('839:59:59', TIME'00:00:00') AS ci, +GREATEST('839:59:59.0', TIME'00:00:00') AS c1, +GREATEST('839:59:59.00', TIME'00:00:00') AS c2, +GREATEST('839:59:59.000', TIME'00:00:00') AS c3, +GREATEST('839:59:59.0000', TIME'00:00:00') AS c4, +GREATEST('839:59:59.00000', TIME'00:00:00') AS c5, +GREATEST('839:59:59.000000', TIME'00:00:00') AS c6, +GREATEST('839:59:59.0000000', TIME'00:00:00') AS c7; +ci 838:59:59 +c1 838:59:59.9 +c2 838:59:59.99 +c3 838:59:59.999 +c4 838:59:59.9999 +c5 838:59:59.99999 +c6 838:59:59.999999 +c7 838:59:59.999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.0' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.0000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.00000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.000000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.0000000' +SELECT +MICROSECOND(GREATEST('839:59:59', TIME'00:00:00')) AS ci, +MICROSECOND(GREATEST('839:59:59.0', TIME'00:00:00')) AS c1, +MICROSECOND(GREATEST('839:59:59.00', TIME'00:00:00')) AS c2, +MICROSECOND(GREATEST('839:59:59.000', TIME'00:00:00')) AS c3, +MICROSECOND(GREATEST('839:59:59.0000', TIME'00:00:00')) AS c4, +MICROSECOND(GREATEST('839:59:59.00000', TIME'00:00:00')) AS c5, +MICROSECOND(GREATEST('839:59:59.000000', TIME'00:00:00')) AS c6, +MICROSECOND(GREATEST('839:59:59.0000000', TIME'00:00:00')) AS c7; +ci 0 +c1 900000 +c2 990000 +c3 999000 +c4 999900 +c5 999990 +c6 999999 +c7 999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.0' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.0000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.00000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.000000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59.0000000' +SELECT +CAST(GREATEST('839:59:59', TIME'00:00:00') AS SIGNED) AS ci, +CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,0)) AS c0, +CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,1)) AS c1, +CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,2)) AS c2, +CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,3)) AS c3, +CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,4)) AS c4, +CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,5)) AS c5, +CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,6)) AS c6, +CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,7)) AS c7; +ci 8385959 +c0 8385959 +c1 8385959.0 +c2 8385959.00 +c3 8385959.000 +c4 8385959.0000 +c5 8385959.00000 +c6 8385959.000000 +c7 8385959.0000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +GREATEST('839:59:59', TIME'00:00:00') AS ci, +GREATEST('839:59:59', TIME'00:00:00')+0 AS c0, +GREATEST('839:59:59', TIME'00:00:00')+0.0 AS c1, +GREATEST('839:59:59', TIME'00:00:00')+0.00 AS c2, +GREATEST('839:59:59', TIME'00:00:00')+0.000 AS c3, +GREATEST('839:59:59', TIME'00:00:00')+0.0000 AS c4, +GREATEST('839:59:59', TIME'00:00:00')+0.00000 AS c5, +GREATEST('839:59:59', TIME'00:00:00')+0.000000 AS c6, +GREATEST('839:59:59', TIME'00:00:00')+0.0000000 AS c7; +ci 838:59:59 +c0 8385959 +c1 8385959.0 +c2 8385959.00 +c3 8385959.000 +c4 8385959.0000 +c5 8385959.00000 +c6 8385959.000000 +c7 8385959.0000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +# ADDTIME(datetime, decimal) +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0) AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.00) AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.000) AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0000) AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.00000) AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.000000) AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0000000) AS c7; +c0 2001-02-04 23:59:59 +c1 2001-02-04 23:59:59.0 +c2 2001-02-04 23:59:59.00 +c3 2001-02-04 23:59:59.000 +c4 2001-02-04 23:59:59.0000 +c5 2001-02-04 23:59:59.00000 +c6 2001-02-04 23:59:59.000000 +c7 2001-02-04 23:59:59.000000 +Warnings: +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '8395959.0000000' +SELECT +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)) AS c0, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0)) AS c1, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.00)) AS c2, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.000)) AS c3, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0000)) AS c4, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.00000)) AS c5, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.000000)) AS c6, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0000000)) AS c7; +c0 0 +c1 0 +c2 0 +c3 0 +c4 0 +c5 0 +c6 0 +c7 0 +Warnings: +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '8395959.0000000' +SELECT +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS SIGNED) AS ci, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,0)) AS c0, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,1)) AS c1, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,2)) AS c2, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,3)) AS c3, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,4)) AS c4, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,5)) AS c5, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,6)) AS c6, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,7)) AS c7; +ci 20010204235959 +c0 20010204235959 +c1 20010204235959.0 +c2 20010204235959.00 +c3 20010204235959.000 +c4 20010204235959.0000 +c5 20010204235959.00000 +c6 20010204235959.000000 +c7 20010204235959.0000000 +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS ci, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0 AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.0 AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.00 AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.000 AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.0000 AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.00000 AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.000000 AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.0000000 AS c7; +ci 2001-02-04 23:59:59 +c0 20010204235959 +c1 20010204235959.0 +c2 20010204235959.00 +c3 20010204235959.000 +c4 20010204235959.0000 +c5 20010204235959.00000 +c6 20010204235959.000000 +c7 20010204235959.0000000 +# ADDTIME(datetime, string) +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0') AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.00') AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.000') AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0000') AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.00000') AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.000000') AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0000000') AS c7; +c0 2001-02-04 23:59:59 +c1 2001-02-04 23:59:59.0 +c2 2001-02-04 23:59:59.00 +c3 2001-02-04 23:59:59.000 +c4 2001-02-04 23:59:59.0000 +c5 2001-02-04 23:59:59.00000 +c6 2001-02-04 23:59:59.000000 +c7 2001-02-04 23:59:59.000000 +Warnings: +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '839:59:59.0000000' +SELECT +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')) AS c0, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0')) AS c1, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.00')) AS c2, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.000')) AS c3, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0000')) AS c4, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.00000')) AS c5, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.000000')) AS c6, +MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0000000')) AS c7; +c0 0 +c1 0 +c2 0 +c3 0 +c4 0 +c5 0 +c6 0 +c7 0 +Warnings: +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '839:59:59.0000000' +SELECT +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS SIGNED) AS ci, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,0)) AS c0, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,1)) AS c1, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,2)) AS c2, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,3)) AS c3, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,4)) AS c4, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,5)) AS c5, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,6)) AS c6, +CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,7)) AS c7; +ci 20010204235959 +c0 20010204235959 +c1 20010204235959.0 +c2 20010204235959.00 +c3 20010204235959.000 +c4 20010204235959.0000 +c5 20010204235959.00000 +c6 20010204235959.000000 +c7 20010204235959.0000000 +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS ci, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0 AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.0 AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.00 AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.000 AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.0000 AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.00000 AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.000000 AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.0000000 AS c7; +ci 2001-02-04 23:59:59 +c0 20010204235959 +c1 20010204235959.0 +c2 20010204235959.00 +c3 20010204235959.000 +c4 20010204235959.0000 +c5 20010204235959.00000 +c6 20010204235959.000000 +c7 20010204235959.0000000 +# ADDTIME(time, decimal) +SELECT +ADDTIME(TIME'00:00:00', 8395959) AS c0, +ADDTIME(TIME'00:00:00', 8395959.0) AS c1, +ADDTIME(TIME'00:00:00', 8395959.00) AS c2, +ADDTIME(TIME'00:00:00', 8395959.000) AS c3, +ADDTIME(TIME'00:00:00', 8395959.0000) AS c4, +ADDTIME(TIME'00:00:00', 8395959.00000) AS c5, +ADDTIME(TIME'00:00:00', 8395959.000000) AS c6, +ADDTIME(TIME'00:00:00', 8395959.0000000) AS c7; +c0 838:59:59 +c1 838:59:59.9 +c2 838:59:59.99 +c3 838:59:59.999 +c4 838:59:59.9999 +c5 838:59:59.99999 +c6 838:59:59.999999 +c7 838:59:59.999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '8395959.0000000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +MICROSECOND(ADDTIME(TIME'00:00:00', 8395959)) AS c0, +MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.0)) AS c1, +MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.00)) AS c2, +MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.000)) AS c3, +MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.0000)) AS c4, +MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.00000)) AS c5, +MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.000000)) AS c6, +MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.0000000)) AS c7; +c0 0 +c1 900000 +c2 990000 +c3 999000 +c4 999900 +c5 999990 +c6 999999 +c7 999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '8395959.0000000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +CAST(ADDTIME(TIME'00:00:00', 8395959) AS SIGNED) AS ci, +CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,0)) AS c0, +CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,1)) AS c1, +CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,2)) AS c2, +CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,3)) AS c3, +CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,4)) AS c4, +CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,5)) AS c5, +CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,6)) AS c6, +CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,7)) AS c7; +ci 8385959 +c0 8385959 +c1 8385959.0 +c2 8385959.00 +c3 8385959.000 +c4 8385959.0000 +c5 8385959.00000 +c6 8385959.000000 +c7 8385959.0000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +ADDTIME(TIME'00:00:00', 8395959) AS ci, +ADDTIME(TIME'00:00:00', 8395959)+0 AS c0, +ADDTIME(TIME'00:00:00', 8395959)+0.0 AS c1, +ADDTIME(TIME'00:00:00', 8395959)+0.00 AS c2, +ADDTIME(TIME'00:00:00', 8395959)+0.000 AS c3, +ADDTIME(TIME'00:00:00', 8395959)+0.0000 AS c4, +ADDTIME(TIME'00:00:00', 8395959)+0.00000 AS c5, +ADDTIME(TIME'00:00:00', 8395959)+0.000000 AS c6, +ADDTIME(TIME'00:00:00', 8395959)+0.0000000 AS c7; +ci 838:59:59 +c0 8385959 +c1 8385959.0 +c2 8385959.00 +c3 8385959.000 +c4 8385959.0000 +c5 8385959.00000 +c6 8385959.000000 +c7 8385959.0000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +# ADDTIME(time,string) +SELECT +ADDTIME(TIME'00:00:00', '839:59:59') AS c0, +ADDTIME(TIME'00:00:00', '839:59:59.0') AS c1, +ADDTIME(TIME'00:00:00', '839:59:59.00') AS c2, +ADDTIME(TIME'00:00:00', '839:59:59.000') AS c3, +ADDTIME(TIME'00:00:00', '839:59:59.0000') AS c4, +ADDTIME(TIME'00:00:00', '839:59:59.00000') AS c5, +ADDTIME(TIME'00:00:00', '839:59:59.000000') AS c6, +ADDTIME(TIME'00:00:00', '839:59:59.0000000') AS c7; +c0 838:59:59 +c1 838:59:59.9 +c2 838:59:59.99 +c3 838:59:59.999 +c4 838:59:59.9999 +c5 838:59:59.99999 +c6 838:59:59.999999 +c7 838:59:59.999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '839:59:59.0000000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59')) AS c0, +MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.0')) AS c1, +MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.00')) AS c2, +MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.000')) AS c3, +MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.0000')) AS c4, +MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.00000')) AS c5, +MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.000000')) AS c6, +MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.0000000')) AS c7; +c0 0 +c1 900000 +c2 990000 +c3 999000 +c4 999900 +c5 999990 +c6 999999 +c7 999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '839:59:59.0000000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS SIGNED) AS ci, +CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,0)) AS c0, +CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,1)) AS c1, +CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,2)) AS c2, +CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,3)) AS c3, +CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,4)) AS c4, +CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,5)) AS c5, +CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,6)) AS c6, +CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,7)) AS c7; +ci 8385959 +c0 8385959 +c1 8385959.0 +c2 8385959.00 +c3 8385959.000 +c4 8385959.0000 +c5 8385959.00000 +c6 8385959.000000 +c7 8385959.0000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +ADDTIME(TIME'00:00:00', '839:59:59') AS ci, +ADDTIME(TIME'00:00:00', '839:59:59')+0 AS c0, +ADDTIME(TIME'00:00:00', '839:59:59')+0.0 AS c1, +ADDTIME(TIME'00:00:00', '839:59:59')+0.00 AS c2, +ADDTIME(TIME'00:00:00', '839:59:59')+0.000 AS c3, +ADDTIME(TIME'00:00:00', '839:59:59')+0.0000 AS c4, +ADDTIME(TIME'00:00:00', '839:59:59')+0.00000 AS c5, +ADDTIME(TIME'00:00:00', '839:59:59')+0.000000 AS c6, +ADDTIME(TIME'00:00:00', '839:59:59')+0.0000000 AS c7; +ci 838:59:59 +c0 8385959 +c1 8385959.0 +c2 8385959.00 +c3 8385959.000 +c4 8385959.0000 +c5 8385959.00000 +c6 8385959.000000 +c7 8385959.0000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +# ADDTIME(int,int) +SELECT +ADDTIME(0, 8395959) AS c, +MICROSECOND(ADDTIME(0, 8395959)) AS cm, +CAST(ADDTIME(0, 8395959) AS SIGNED) AS cs_fixme_mdev_17384, +CAST(ADDTIME(0, 8395959) AS DECIMAL(30,0)) AS cd300; +c 838:59:59 +cm 0 +cs_fixme_mdev_17384 838 +cd300 8385959 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect INTEGER value: '838:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +ADDTIME(20010101000000, 8395959) AS c, +MICROSECOND(ADDTIME(20010101000000, 8395959)) AS cm, +CAST(ADDTIME(20010101000000, 8395959) AS SIGNED) AS cs_fixme_mdev_17384, +CAST(ADDTIME(20010101000000, 8395959) AS DECIMAL(30,0)) AS cd300; +c 2001-02-04 23:59:59 +cm 0 +cs_fixme_mdev_17384 2001 +cd300 20010204235959 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect INTEGER value: '2001-02-04 23:59:59' +# ADDTIME(decimal,int) +# 8385960 in cd300 is correct: addtime returns '838:59:59.9' +# which is further *rounded* to a decimals(30,0) +SELECT +ADDTIME(0.0, 8395959) AS c, +MICROSECOND(ADDTIME(0.0, 8395959)) AS cm, +CAST(ADDTIME(0.0, 8395959) AS SIGNED) AS cs_fixme_mdev_17384, +CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,0)) AS cd300; +c 838:59:59.9 +cm 900000 +cs_fixme_mdev_17384 838 +cd300 8385960 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect INTEGER value: '838:59:59.9' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +ADDTIME(20010101000000.0, 8395959) AS c, +MICROSECOND(ADDTIME(20010101000000.0, 8395959)) AS cm, +CAST(ADDTIME(20010101000000.0, 8395959) AS SIGNED) AS cs_fixme_mdev_17384, +CAST(ADDTIME(20010101000000.0, 8395959) AS DECIMAL(30,0)) AS cd300; +c 2001-02-04 23:59:59.0 +cm 0 +cs_fixme_mdev_17384 2001 +cd300 20010204235959 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect INTEGER value: '2001-02-04 23:59:59.0' +# ADDTIME(decimal,decimal) +SELECT +ADDTIME(0.0, 8395959.0) AS c1, +ADDTIME(0.0, 8395959.00) AS c2, +ADDTIME(0.0, 8395959.000) AS c3, +ADDTIME(0.0, 8395959.0000) AS c4, +ADDTIME(0.0, 8395959.00000) AS c5, +ADDTIME(0.0, 8395959.000000) AS c6, +ADDTIME(0.0, 8395959.0000000) AS c7; +c1 838:59:59.9 +c2 838:59:59.99 +c3 838:59:59.999 +c4 838:59:59.9999 +c5 838:59:59.99999 +c6 838:59:59.999999 +c7 838:59:59.999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '8395959.0000000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +MICROSECOND(ADDTIME(0.0, 8395959.0)) AS c1, +MICROSECOND(ADDTIME(0.0, 8395959.00)) AS c2, +MICROSECOND(ADDTIME(0.0, 8395959.000)) AS c3, +MICROSECOND(ADDTIME(0.0, 8395959.0000)) AS c4, +MICROSECOND(ADDTIME(0.0, 8395959.00000)) AS c5, +MICROSECOND(ADDTIME(0.0, 8395959.000000)) AS c6, +MICROSECOND(ADDTIME(0.0, 8395959.0000000)) AS c7; +c1 900000 +c2 990000 +c3 999000 +c4 999900 +c5 999990 +c6 999999 +c7 999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '8395959.0000000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +# 8385960 in c1 is correct: addtime returns '838:59:59.9' +# which is further *rounded* to a decimals(30,0) +SELECT +CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,0)) AS c0, +CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,1)) AS c1, +CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,2)) AS c2, +CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,3)) AS c3, +CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,4)) AS c4, +CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,5)) AS c5, +CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,6)) AS c6, +CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,7)) AS c7; +c0 8385960 +c1 8385959.9 +c2 8385959.90 +c3 8385959.900 +c4 8385959.9000 +c5 8385959.90000 +c6 8385959.900000 +c7 8385959.9000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +SELECT +ADDTIME(0.0, 8395959)+0 AS c0, +ADDTIME(0.0, 8395959)+0.0 AS c1, +ADDTIME(0.0, 8395959)+0.00 AS c2, +ADDTIME(0.0, 8395959)+0.000 AS c3, +ADDTIME(0.0, 8395959)+0.0000 AS c4, +ADDTIME(0.0, 8395959)+0.00000 AS c5, +ADDTIME(0.0, 8395959)+0.000000 AS c6, +ADDTIME(0.0, 8395959)+0.0000000 AS c7; +c0 8385959.9 +c1 8385959.9 +c2 8385959.90 +c3 8385959.900 +c4 8385959.9000 +c5 8385959.90000 +c6 8385959.900000 +c7 8385959.9000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '839:59:59' +# TIMESTAMP(string,decimal) +SELECT +TIMESTAMP('2001-01-01', 8395959) AS ci, +TIMESTAMP('2001-01-01', 8395959.0) AS c1, +TIMESTAMP('2001-01-01', 8395959.00) AS c2, +TIMESTAMP('2001-01-01', 8395959.000) AS c3, +TIMESTAMP('2001-01-01', 8395959.0000) AS c4, +TIMESTAMP('2001-01-01', 8395959.00000) AS c5, +TIMESTAMP('2001-01-01', 8395959.000000) AS c6, +TIMESTAMP('2001-01-01', 8395959.0000000) AS c7; +ci 2001-02-04 23:59:59 +c1 2001-02-04 23:59:59.0 +c2 2001-02-04 23:59:59.00 +c3 2001-02-04 23:59:59.000 +c4 2001-02-04 23:59:59.0000 +c5 2001-02-04 23:59:59.00000 +c6 2001-02-04 23:59:59.000000 +c7 2001-02-04 23:59:59.000000 +Warnings: +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '8395959.0000000' +SELECT +MICROSECOND(TIMESTAMP('2001-01-01', 8395959)) AS ci, +MICROSECOND(TIMESTAMP('2001-01-01', 8395959.0)) AS c1, +MICROSECOND(TIMESTAMP('2001-01-01', 8395959.00)) AS c2, +MICROSECOND(TIMESTAMP('2001-01-01', 8395959.000)) AS c3, +MICROSECOND(TIMESTAMP('2001-01-01', 8395959.0000)) AS c4, +MICROSECOND(TIMESTAMP('2001-01-01', 8395959.00000)) AS c5, +MICROSECOND(TIMESTAMP('2001-01-01', 8395959.000000)) AS c6, +MICROSECOND(TIMESTAMP('2001-01-01', 8395959.0000000)) AS c7; +ci 0 +c1 0 +c2 0 +c3 0 +c4 0 +c5 0 +c6 0 +c7 0 +Warnings: +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '8395959.0000000' +SELECT +CAST(TIMESTAMP('2001-01-01', 8395959) AS SIGNED) AS ci, +CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,0)) AS c0, +CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,1)) AS c1, +CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,2)) AS c2, +CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,3)) AS c3, +CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,4)) AS c4, +CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,5)) AS c5, +CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,6)) AS c6; +ci 20010204235959 +c0 20010204235959 +c1 20010204235959.0 +c2 20010204235959.00 +c3 20010204235959.000 +c4 20010204235959.0000 +c5 20010204235959.00000 +c6 20010204235959.000000 +SELECT +TIMESTAMP('2001-01-01', 8395959) AS ci, +TIMESTAMP('2001-01-01', 8395959)+0 AS c0, +TIMESTAMP('2001-01-01', 8395959)+0.0 AS c1, +TIMESTAMP('2001-01-01', 8395959)+0.00 AS c2, +TIMESTAMP('2001-01-01', 8395959)+0.000 AS c3, +TIMESTAMP('2001-01-01', 8395959)+0.0000 AS c4, +TIMESTAMP('2001-01-01', 8395959)+0.00000 AS c5, +TIMESTAMP('2001-01-01', 8395959)+0.000000 AS c6, +TIMESTAMP('2001-01-01', 8395959)+0.0000000 AS c7; +ci 2001-02-04 23:59:59 +c0 20010204235959 +c1 20010204235959.0 +c2 20010204235959.00 +c3 20010204235959.000 +c4 20010204235959.0000 +c5 20010204235959.00000 +c6 20010204235959.000000 +c7 20010204235959.0000000 +# TIMESTAMP(string,string) +SELECT +TIMESTAMP('2001-01-01', '839:59:59') AS ci, +TIMESTAMP('2001-01-01', '839:59:59.0') AS c1, +TIMESTAMP('2001-01-01', '839:59:59.00') AS c2, +TIMESTAMP('2001-01-01', '839:59:59.000') AS c3, +TIMESTAMP('2001-01-01', '839:59:59.0000') AS c4, +TIMESTAMP('2001-01-01', '839:59:59.00000') AS c5, +TIMESTAMP('2001-01-01', '839:59:59.000000') AS c6, +TIMESTAMP('2001-01-01', '839:59:59.0000000') AS c7; +ci 2001-02-04 23:59:59 +c1 2001-02-04 23:59:59.0 +c2 2001-02-04 23:59:59.00 +c3 2001-02-04 23:59:59.000 +c4 2001-02-04 23:59:59.0000 +c5 2001-02-04 23:59:59.00000 +c6 2001-02-04 23:59:59.000000 +c7 2001-02-04 23:59:59.000000 +Warnings: +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '839:59:59.0000000' +SELECT +MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59')) AS ci, +MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.0')) AS c1, +MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.00')) AS c2, +MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.000')) AS c3, +MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.0000')) AS c4, +MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.00000')) AS c5, +MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.000000')) AS c6, +MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.0000000')) AS c7; +ci 0 +c1 0 +c2 0 +c3 0 +c4 0 +c5 0 +c6 0 +c7 0 +Warnings: +Level Note +Code 1292 +Message Truncated incorrect INTERVAL DAY TO SECOND value: '839:59:59.0000000' +SELECT +CAST(TIMESTAMP('2001-01-01', '839:59:59') AS SIGNED) AS ci, +CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,0)) AS c0, +CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,1)) AS c1, +CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,2)) AS c2, +CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,3)) AS c3, +CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,4)) AS c4, +CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,5)) AS c5, +CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,6)) AS c6; +ci 20010204235959 +c0 20010204235959 +c1 20010204235959.0 +c2 20010204235959.00 +c3 20010204235959.000 +c4 20010204235959.0000 +c5 20010204235959.00000 +c6 20010204235959.000000 +SELECT +TIMESTAMP('2001-01-01', '839:59:59') AS ci, +TIMESTAMP('2001-01-01', '839:59:59')+0 AS c0, +TIMESTAMP('2001-01-01', '839:59:59')+0.0 AS c1, +TIMESTAMP('2001-01-01', '839:59:59')+0.00 AS c2, +TIMESTAMP('2001-01-01', '839:59:59')+0.000 AS c3, +TIMESTAMP('2001-01-01', '839:59:59')+0.0000 AS c4, +TIMESTAMP('2001-01-01', '839:59:59')+0.00000 AS c5, +TIMESTAMP('2001-01-01', '839:59:59')+0.000000 AS c6, +TIMESTAMP('2001-01-01', '839:59:59')+0.0000000 AS c7; +ci 2001-02-04 23:59:59 +c0 20010204235959 +c1 20010204235959.0 +c2 20010204235959.00 +c3 20010204235959.000 +c4 20010204235959.0000 +c5 20010204235959.00000 +c6 20010204235959.000000 +c7 20010204235959.0000000 +# Corner cases for TIMESTAMP(timestamp,xxx) +# HOUR is outside of supported INTERVAL DAYS TO SECONDS range +# Expect NULL with INTERVAL warnings +CREATE TABLE t1 (a VARCHAR(64), b VARCHAR(64)); +INSERT INTO t1 VALUES ('4294967296:00:00', '178956970 16:00:00'); +INSERT INTO t1 VALUES ('4294967295:59:59', '178956970 15:59:59'); +INSERT INTO t1 VALUES ('4294967294:59:59', '178956970 14:59:59'); +INSERT INTO t1 VALUES ('87649416:00:00', '3652059 00:00:00'); +SELECT TIMESTAMP('0001-01-01 00:00:00', a) AS ta, TIMESTAMP('0001-01-01 00:00:00', b) AS tb FROM t1; +ta tb +NULL NULL +NULL NULL +NULL NULL +NULL NULL +Warnings: +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '4294967296:00:00' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '178956970 16:00:00' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '178956970 15:59:59' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '4294967294:59:59' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '178956970 14:59:59' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '87649416:00:00' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '3652059 00:00:00' +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64), b VARCHAR(64)); +INSERT INTO t1 VALUES ('-4294967296:00:00', '-178956970 16:00:00'); +INSERT INTO t1 VALUES ('-4294967295:59:59', '-178956970 15:59:59'); +INSERT INTO t1 VALUES ('-4294967294:59:59', '-178956970 14:59:59'); +INSERT INTO t1 VALUES ('-87649416:00:00', '-3652059 00:00:00'); +SELECT TIMESTAMP('9999-12-31 23:59:59', a) AS ta, TIMESTAMP('9999-12-31 23:59:59.999999', b) AS tb FROM t1; +ta tb +NULL NULL +NULL NULL +NULL NULL +NULL NULL +Warnings: +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '-4294967296:00:00' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '-178956970 16:00:00' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '-4294967295:59:59' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '-178956970 15:59:59' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '-4294967294:59:59' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '-178956970 14:59:59' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '-87649416:00:00' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '-3652059 00:00:00' +DROP TABLE t1; +# HOUR is OK +# Expect max or near-max DATETIME value + no INTERVAL warnings +CREATE TABLE t1 (a VARCHAR(64), b VARCHAR(64)); +INSERT INTO t1 VALUES ('87649415:59:59.999999', '3652058 23:59:59.999999'); +INSERT INTO t1 VALUES ('87649415:59:59', '3652058 23:59:59'); +SELECT TIMESTAMP('0001-01-01 00:00:00', a) AS ta, TIMESTAMP('0001-01-01 00:00:00', b) AS tb FROM t1; +ta tb +9999-12-31 23:59:59.999999 9999-12-31 23:59:59.999999 +9999-12-31 23:59:59.000000 9999-12-31 23:59:59.000000 +DROP TABLE t1; +# HOUR is OK +# Expect near '0001-01-01 00:00:00' DATETIME value + no INTERVAL warnings +CREATE TABLE t1 (a VARCHAR(64), b VARCHAR(64)); +INSERT INTO t1 VALUES ('-87649415:59:59.999999', '-3652058 23:59:59.999999'); +INSERT INTO t1 VALUES ('-87649415:59:59', '-3652058 23:59:59'); +SELECT TIMESTAMP('9999-12-31 23:59:59', a) AS ta, TIMESTAMP('9999-12-31 23:59:59.999999', b) AS tb FROM t1; +ta tb +NULL 0001-01-01 00:00:00.000000 +0001-01-01 00:00:00.000000 0001-01-01 00:00:00.999999 +DROP TABLE t1; +# HOUR is OK +# Expect NULL on datetime arithmetic overflow + no INTERVAL warnings +CREATE TABLE t1 (a VARCHAR(64), b VARCHAR(64)); +INSERT INTO t1 VALUES ('-00:00:00.000001', '-0 00:00:00.000001'); +SELECT TIMESTAMP('0001-01-01 00:00:00', a) AS ta, TIMESTAMP('0001-01-01 00:00:00', b) AS tb FROM t1; +ta tb +NULL NULL +DROP TABLE t1; +# Corner cases for ADDTIME(timestamp,xxx) +# HOUR is outside of UINT_MAX32 range +# Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959) AS ci, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0 AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.0 AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.00 AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.000 AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.0000 AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.00000 AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.000000 AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59') AS ci, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0 AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.0 AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.00 AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.000 AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.0000 AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.00000 AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.000000 AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +# HOUR UINT_MAX32 +# Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959) AS ci, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0 AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.0 AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.00 AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.000 AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.0000 AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.00000 AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.000000 AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59') AS ci, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0 AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.0 AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.00 AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.000 AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.0000 AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.00000 AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.000000 AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +# HOUR is max_useful_hour()+1 +# Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959) AS ci, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0 AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.0 AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.00 AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.000 AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.0000 AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.00000 AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.000000 AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59') AS ci, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0 AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.0 AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.00 AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.000 AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.0000 AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.00000 AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.000000 AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +# HOUR is max_useful_hour() +# Expect NULL (calc_time_diff overflows ) + no INTERVAL warnings +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959) AS ci, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0 AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.0 AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.00 AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.000 AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.0000 AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.00000 AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.000000 AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +SELECT +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59') AS ci, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0 AS c0, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.0 AS c1, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.00 AS c2, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.000 AS c3, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.0000 AS c4, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.00000 AS c5, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.000000 AS c6, +ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +# HOUR is max_useful_hour() +# Expect non-NULL + no warnings +SELECT +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959) AS ci, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0 AS c0, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.0 AS c1, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.00 AS c2, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.000 AS c3, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.0000 AS c4, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.00000 AS c5, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.000000 AS c6, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.0000000 AS c7; +ci 9999-12-31 23:59:59 +c0 99991231235959 +c1 99991231235959.0 +c2 99991231235959.00 +c3 99991231235959.000 +c4 99991231235959.0000 +c5 99991231235959.00000 +c6 99991231235959.000000 +c7 99991231235959.0000000 +SELECT +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59') AS ci, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0 AS c0, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.0 AS c1, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.00 AS c2, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.000 AS c3, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.0000 AS c4, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.00000 AS c5, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.000000 AS c6, +ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.0000000 AS c7; +ci 9999-12-31 23:59:59 +c0 99991231235959 +c1 99991231235959.0 +c2 99991231235959.00 +c3 99991231235959.000 +c4 99991231235959.0000 +c5 99991231235959.00000 +c6 99991231235959.000000 +c7 99991231235959.0000000 +# Corner cases for ADDTIME(time,xxx) +# HOUR outside of UINT32 range +# Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT +ADDTIME(TIME'00:00:00', 42949672965959) AS ci, +ADDTIME(TIME'00:00:00', 42949672965959)+0 AS c0, +ADDTIME(TIME'00:00:00', 42949672965959)+0.0 AS c1, +ADDTIME(TIME'00:00:00', 42949672965959)+0.00 AS c2, +ADDTIME(TIME'00:00:00', 42949672965959)+0.000 AS c3, +ADDTIME(TIME'00:00:00', 42949672965959)+0.0000 AS c4, +ADDTIME(TIME'00:00:00', 42949672965959)+0.00000 AS c5, +ADDTIME(TIME'00:00:00', 42949672965959)+0.000000 AS c6, +ADDTIME(TIME'00:00:00', 42949672965959)+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672965959' +SELECT +ADDTIME(TIME'00:00:00', '4294967296:59:59') AS ci, +ADDTIME(TIME'00:00:00', '4294967296:59:59')+0 AS c0, +ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.0 AS c1, +ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.00 AS c2, +ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.000 AS c3, +ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.0000 AS c4, +ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.00000 AS c5, +ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.000000 AS c6, +ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967296:59:59' +# HOUR is UINT_MAX32 (outside of INTERVAL DAY TO SECOND range) +# Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT +ADDTIME(TIME'00:00:00', 42949672955959) AS ci, +ADDTIME(TIME'00:00:00', 42949672955959)+0 AS c0, +ADDTIME(TIME'00:00:00', 42949672955959)+0.0 AS c1, +ADDTIME(TIME'00:00:00', 42949672955959)+0.00 AS c2, +ADDTIME(TIME'00:00:00', 42949672955959)+0.000 AS c3, +ADDTIME(TIME'00:00:00', 42949672955959)+0.0000 AS c4, +ADDTIME(TIME'00:00:00', 42949672955959)+0.00000 AS c5, +ADDTIME(TIME'00:00:00', 42949672955959)+0.000000 AS c6, +ADDTIME(TIME'00:00:00', 42949672955959)+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '42949672955959' +SELECT +ADDTIME(TIME'00:00:00', '4294967295:59:59') AS ci, +ADDTIME(TIME'00:00:00', '4294967295:59:59')+0 AS c0, +ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.0 AS c1, +ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.00 AS c2, +ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.000 AS c3, +ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.0000 AS c4, +ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.00000 AS c5, +ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.000000 AS c6, +ADDTIME(TIME'00:00:00', '4294967295;00:00')+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '4294967295;00:00' +# HOUR is max_useful_hour()+1 (outside of INTERVAL DAY TO SECOND range) +# Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT +ADDTIME(TIME'00:00:00', 876494165959) AS ci, +ADDTIME(TIME'00:00:00', 876494165959)+0 AS c0, +ADDTIME(TIME'00:00:00', 876494165959)+0.0 AS c1, +ADDTIME(TIME'00:00:00', 876494165959)+0.00 AS c2, +ADDTIME(TIME'00:00:00', 876494165959)+0.000 AS c3, +ADDTIME(TIME'00:00:00', 876494165959)+0.0000 AS c4, +ADDTIME(TIME'00:00:00', 876494165959)+0.00000 AS c5, +ADDTIME(TIME'00:00:00', 876494165959)+0.000000 AS c6, +ADDTIME(TIME'00:00:00', 876494165959)+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +SELECT +ADDTIME(TIME'00:00:00', '87649416:59:59') AS ci, +ADDTIME(TIME'00:00:00', '87649416:59:59')+0 AS c0, +ADDTIME(TIME'00:00:00', '87649416:59:59')+0.0 AS c1, +ADDTIME(TIME'00:00:00', '87649416:59:59')+0.00 AS c2, +ADDTIME(TIME'00:00:00', '87649416:59:59')+0.000 AS c3, +ADDTIME(TIME'00:00:00', '87649416:59:59')+0.0000 AS c4, +ADDTIME(TIME'00:00:00', '87649416:59:59')+0.00000 AS c5, +ADDTIME(TIME'00:00:00', '87649416:59:59')+0.000000 AS c6, +ADDTIME(TIME'00:00:00', '87649416:59:59')+0.0000000 AS c7; +ci NULL +c0 NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +c7 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +# HOUR is max_useful_hour()+1 (outside of INTERVAL DAY TO SECOND range) +# Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT +ADDTIME(TIME'-838:59:59', 876494165959) AS ci, +ADDTIME(TIME'-838:59:59.9', 876494165959) AS c1, +ADDTIME(TIME'-838:59:59.99', 876494165959) AS c2, +ADDTIME(TIME'-838:59:59.999', 876494165959) AS c3, +ADDTIME(TIME'-838:59:59.9999', 876494165959) AS c4, +ADDTIME(TIME'-838:59:59.99999', 876494165959) AS c5, +ADDTIME(TIME'-838:59:59.999999', 876494165959) AS c6; +ci NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '876494165959' +SELECT +ADDTIME(TIME'-838:59:59', '87649416:59:59') AS ci, +ADDTIME(TIME'-838:59:59.9', '87649416:59:59') AS c1, +ADDTIME(TIME'-838:59:59.99', '87649416:59:59') AS c2, +ADDTIME(TIME'-838:59:59.999', '87649416:59:59') AS c3, +ADDTIME(TIME'-838:59:59.9999', '87649416:59:59') AS c4, +ADDTIME(TIME'-838:59:59.99999', '87649416:59:59') AS c5, +ADDTIME(TIME'-838:59:59.999999', '87649416:59:59') AS c6; +ci NULL +c1 NULL +c2 NULL +c3 NULL +c4 NULL +c5 NULL +c6 NULL +Warnings: +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +Level Warning +Code 1292 +Message Incorrect INTERVAL DAY TO SECOND value: '87649416:59:59' +SELECT +ADDTIME(TIME'-838:59:59.9999999', '87649416:59:59') AS c7; +c7 NULL +# HOUR is max_useful_hour() (inside INTERVAL DAY TO SECOND range) +# Expect max TIME(0) + zero fraction + TIME warnings + no INTEVAL warnings +SELECT +ADDTIME(TIME'00:00:00', 876494155959) AS ci, +ADDTIME(TIME'00:00:00', 876494155959)+0 AS c0, +ADDTIME(TIME'00:00:00', 876494155959)+0.0 AS c1, +ADDTIME(TIME'00:00:00', 876494155959)+0.00 AS c2, +ADDTIME(TIME'00:00:00', 876494155959)+0.000 AS c3, +ADDTIME(TIME'00:00:00', 876494155959)+0.0000 AS c4, +ADDTIME(TIME'00:00:00', 876494155959)+0.00000 AS c5, +ADDTIME(TIME'00:00:00', 876494155959)+0.000000 AS c6, +ADDTIME(TIME'00:00:00', 876494155959)+0.0000000 AS c7; +ci 838:59:59 +c0 8385959 +c1 8385959.0 +c2 8385959.00 +c3 8385959.000 +c4 8385959.0000 +c5 8385959.00000 +c6 8385959.000000 +c7 8385959.0000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +SELECT +ADDTIME(TIME'00:00:00', '87649415:59:59') AS ci, +ADDTIME(TIME'00:00:00', '87649415:59:59')+0 AS c0, +ADDTIME(TIME'00:00:00', '87649415:59:59')+0.0 AS c1, +ADDTIME(TIME'00:00:00', '87649415:59:59')+0.00 AS c2, +ADDTIME(TIME'00:00:00', '87649415:59:59')+0.000 AS c3, +ADDTIME(TIME'00:00:00', '87649415:59:59')+0.0000 AS c4, +ADDTIME(TIME'00:00:00', '87649415:59:59')+0.00000 AS c5, +ADDTIME(TIME'00:00:00', '87649415:59:59')+0.000000 AS c6, +ADDTIME(TIME'00:00:00', '87649415:59:59')+0.0000000 AS c7; +ci 838:59:59 +c0 8385959 +c1 8385959.0 +c2 8385959.00 +c3 8385959.000 +c4 8385959.0000 +c5 8385959.00000 +c6 8385959.000000 +c7 8385959.0000000 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87649415:59:59' +# HOUR is max_useful_hour() (inside INTERVAL DAY TO SECOND range) +# Expect max TIME(N) + TIME warnings + no INTERVAL warnings +SELECT +ADDTIME(TIME'-838:59:59', 876494155959) AS ci, +ADDTIME(TIME'-838:59:59.9', 876494155959) AS c1, +ADDTIME(TIME'-838:59:59.99', 876494155959) AS c2, +ADDTIME(TIME'-838:59:59.999', 876494155959) AS c3, +ADDTIME(TIME'-838:59:59.9999', 876494155959) AS c4, +ADDTIME(TIME'-838:59:59.99999', 876494155959) AS c5, +ADDTIME(TIME'-838:59:59.999999', 876494155959) AS c6; +ci 838:59:59 +c1 838:59:59.9 +c2 838:59:59.99 +c3 838:59:59.999 +c4 838:59:59.9999 +c5 838:59:59.99999 +c6 838:59:59.999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648577:00:00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.100000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.010000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.001000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.000100' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.000010' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.000001' +SELECT +ADDTIME(TIME'-838:59:59', '87649415:59:59') AS ci, +ADDTIME(TIME'-838:59:59.9', '87649415:59:59') AS c1, +ADDTIME(TIME'-838:59:59.99', '87649415:59:59') AS c2, +ADDTIME(TIME'-838:59:59.999', '87649415:59:59') AS c3, +ADDTIME(TIME'-838:59:59.9999', '87649415:59:59') AS c4, +ADDTIME(TIME'-838:59:59.99999', '87649415:59:59') AS c5, +ADDTIME(TIME'-838:59:59.999999', '87649415:59:59') AS c6; +ci 838:59:59 +c1 838:59:59.9 +c2 838:59:59.99 +c3 838:59:59.999 +c4 838:59:59.9999 +c5 838:59:59.99999 +c6 838:59:59.999999 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648577:00:00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.100000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.010000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.001000' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.000100' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.000010' +Level Warning +Code 1292 +Message Truncated incorrect time value: '87648576:59:59.000001' +SELECT +ADDTIME(TIME'-838:59:59.9999999', '87649415:59:59') AS c7; +c7 838:59:59.999999 +# +# MDEV-17400 The result of TIME('42949672965959-01') depends on architecture +# +SELECT TIME('42949672955959-01'), TIME('42949672965959-01'); +TIME('42949672955959-01') TIME('42949672965959-01') +NULL NULL +Warnings: +Warning 1292 Incorrect time value: '42949672955959-01' +Warning 1292 Incorrect time value: '42949672965959-01' +SELECT TIME('18446744073709551615-01'), TIME('18446744073709551616-01'); +TIME('18446744073709551615-01') TIME('18446744073709551616-01') +NULL NULL +Warnings: +Warning 1292 Incorrect time value: '18446744073709551615-01' +Warning 1292 Incorrect time value: '18446744073709551616-01' +# +# MDEV-17434 EXTRACT(DAY FROM negative_time) returns wrong result +# +CREATE TABLE t1 (a TIME(6)); +INSERT INTO t1 VALUES ('-24:10:10.10'); +SELECT +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a), +EXTRACT(DAY FROM a), +EXTRACT(DAY_HOUR FROM a), +EXTRACT(DAY_MINUTE FROM a), +EXTRACT(DAY_SECOND FROM a), +EXTRACT(DAY_MICROSECOND FROM a) +FROM t1; +EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a) EXTRACT(DAY FROM a) EXTRACT(DAY_HOUR FROM a) EXTRACT(DAY_MINUTE FROM a) EXTRACT(DAY_SECOND FROM a) EXTRACT(DAY_MICROSECOND FROM a) +-10 -10 -100000 -1 -100 -10010 -1001010 -1001010100000 +CREATE TABLE t2 AS +SELECT +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a), +EXTRACT(DAY FROM a), +EXTRACT(DAY_HOUR FROM a), +EXTRACT(DAY_MINUTE FROM a), +EXTRACT(DAY_SECOND FROM a), +EXTRACT(DAY_MICROSECOND FROM a) +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `EXTRACT(MINUTE FROM a)` int(3) DEFAULT NULL, + `EXTRACT(SECOND FROM a)` int(3) DEFAULT NULL, + `EXTRACT(MICROSECOND FROM a)` int(7) DEFAULT NULL, + `EXTRACT(DAY FROM a)` int(3) DEFAULT NULL, + `EXTRACT(DAY_HOUR FROM a)` int(5) DEFAULT NULL, + `EXTRACT(DAY_MINUTE FROM a)` int(7) DEFAULT NULL, + `EXTRACT(DAY_SECOND FROM a)` int(9) DEFAULT NULL, + `EXTRACT(DAY_MICROSECOND FROM a)` bigint(15) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +DROP TABLE t1; +# +# MDEV-17478 Wrong result for TIME('+100:20:30') +# +SELECT TIME('+100:20:30'); +TIME('+100:20:30') +100:20:30 +# +# MDEV-17477 Wrong result for TIME('-2001-01-01 10:20:30') +# +SELECT TIME('-2001-01-01 10:20:30'); +TIME('-2001-01-01 10:20:30') +NULL +Warnings: +Warning 1292 Incorrect time value: '-2001-01-01 10:20:30' +SELECT TIME('2001-01-01') AS c1, TIME('2001-01-01 ') AS c2; +c1 c2 +00:20:01 00:20:01 +Warnings: +Warning 1292 Truncated incorrect time value: '2001-01-01' +Warning 1292 Truncated incorrect time value: '2001-01-01 ' +SELECT TIME('0001:01:01 '), TIME('0001:01:01 '); +TIME('0001:01:01 ') TIME('0001:01:01 ') +01:01:01 01:01:01 +SELECT TIME('1 2'), TIME('1 2 '); +TIME('1 2') TIME('1 2 ') +00:00:01 00:00:01 +Warnings: +Warning 1292 Truncated incorrect time value: '1 2' +Warning 1292 Truncated incorrect time value: '1 2 ' +SELECT TIME('2001-01-01T'), TIME('2001-01-01T '); +TIME('2001-01-01T') TIME('2001-01-01T ') +00:00:00 00:00:00 +SELECT TIME('901-01-01T1'), TIME('901-01-01T10'); +TIME('901-01-01T1') TIME('901-01-01T10') +01:00:00 10:00:00 +SELECT TIME('091-01-01T1'), TIME('091-01-01T10'); +TIME('091-01-01T1') TIME('091-01-01T10') +01:00:00 10:00:00 +SELECT TIME('0001:01:01x'), TIME('0001:01:01xx'); +TIME('0001:01:01x') TIME('0001:01:01xx') +01:01:01 01:01:01 +Warnings: +Warning 1292 Truncated incorrect time value: '0001:01:01x' +Warning 1292 Truncated incorrect time value: '0001:01:01xx' +SELECT TIME('0001:01:01.'), TIME('0001:01:01..'); +TIME('0001:01:01.') TIME('0001:01:01..') +01:01:01 01:01:01 +Warnings: +Warning 1292 Truncated incorrect time value: '0001:01:01..' +SELECT TIME('0001:01:01-'), TIME('0001:01:01--'); +TIME('0001:01:01-') TIME('0001:01:01--') +01:01:01 01:01:01 +Warnings: +Warning 1292 Truncated incorrect time value: '0001:01:01-' +Warning 1292 Truncated incorrect time value: '0001:01:01--' +SELECT TIME('0001:01:01-'), TIME('0001:01:01--'); +TIME('0001:01:01-') TIME('0001:01:01--') +01:01:01 01:01:01 +Warnings: +Warning 1292 Truncated incorrect time value: '0001:01:01-' +Warning 1292 Truncated incorrect time value: '0001:01:01--' +SELECT TIME('-xxx'), TIME('-xxxxxxxxxxxxxxxxxxxx'); +TIME('-xxx') TIME('-xxxxxxxxxxxxxxxxxxxx') +NULL NULL +Warnings: +Warning 1292 Incorrect time value: '-xxx' +Warning 1292 Incorrect time value: '-xxxxxxxxxxxxxxxxxxxx' +SELECT TIME('- '), TIME('- '); +TIME('- ') TIME('- ') +NULL NULL +Warnings: +Warning 1292 Incorrect time value: '- ' +Warning 1292 Incorrect time value: '- ' +SELECT TIME('-'), TIME('-'); +TIME('-') TIME('-') +NULL NULL +Warnings: +Warning 1292 Incorrect time value: '-' +Warning 1292 Incorrect time value: '-' +SELECT TIME('1-1-1 1:1:1'), TIME('1-1-1 1:1:1.0'); +TIME('1-1-1 1:1:1') TIME('1-1-1 1:1:1.0') +01:01:01 01:01:01.0 +SELECT TIME('1-1-1 1:2:3'), TIME('1-1-1 1:2:3.0'); +TIME('1-1-1 1:2:3') TIME('1-1-1 1:2:3.0') +01:02:03 01:02:03.0 +SELECT +CAST('20050326112233 garbage' as datetime), +CAST('20050326 garbage' as date), +CAST('50326 garbage' as time); +CAST('20050326112233 garbage' as datetime) CAST('20050326 garbage' as date) CAST('50326 garbage' as time) +2005-03-26 11:22:33 2005-03-26 05:03:26 +Warnings: +Warning 1292 Truncated incorrect datetime value: '20050326112233 garbage' +Warning 1292 Truncated incorrect date value: '20050326 garbage' +Warning 1292 Truncated incorrect time value: '50326 garbage' +SELECT TIME('- 01:00:00'), TIME('- 1 01:00:00'); +TIME('- 01:00:00') TIME('- 1 01:00:00') +-01:00:00 -25:00:00 +# +# MDEV-17854 Assertion `decimals <= 6' failed in my_time_fraction_remainder on SELECT with NULLIF and FROM_UNIXTIME on incorrect time +# +SET time_zone='+00:00'; +SELECT NULLIF(FROM_UNIXTIME('foo'), '2012-12-12 21:10:14'); +NULLIF(FROM_UNIXTIME('foo'), '2012-12-12 21:10:14') +1970-01-01 00:00:00 +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: 'foo' +Warning 1292 Truncated incorrect DECIMAL value: 'foo' +SET time_zone=DEFAULT; diff --git a/mysql-test/main/func_time.test b/mysql-test/main/func_time.test index be203c99c69..630083ef97e 100644 --- a/mysql-test/main/func_time.test +++ b/mysql-test/main/func_time.test @@ -564,12 +564,15 @@ SET NAMES DEFAULT; # Bug #31160: MAKETIME() crashes server when returning NULL in ORDER BY using # filesort # +SET TIMESTAMP=UNIX_TIMESTAMP('2001-01-01 11:22:33'); CREATE TABLE t1 ( a TIMESTAMP ); INSERT INTO t1 VALUES (now()), (now()); SELECT 1 FROM t1 ORDER BY MAKETIME(1, 1, a); DROP TABLE t1; +SET TIMESTAMP=DEFAULT; + # # Bug #19844 time_format in Union truncates values # @@ -2244,3 +2247,888 @@ SELECT --echo # --echo # End of 10.3 tests --echo # + +--echo # +--echo # MDEV-14032 SEC_TO_TIME executes side effect two times +--echo # + +SET @a=10000000; +SELECT SEC_TO_TIME(@a:=@a+1); +SELECT @a; + +CREATE TABLE t1 (a TEXT); +DELIMITER $$; +CREATE FUNCTION f1() RETURNS INT +BEGIN + INSERT INTO t1 VALUES ('f1 was called'); + RETURN 10000000; +END; +$$ +DELIMITER ;$$ +SELECT SEC_TO_TIME(f1()); +SELECT * FROM t1; +DROP TABLE t1; +DROP FUNCTION f1; + +--echo # +--echo # MDEV-17351 MICROSECOND(XXX(int_number_out_of_range)) erroneously returns 999999 +--echo # + +--echo # Reject anything that's parsed as DATETIME or DATE + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2001-01-01 10:20:30'), +('01-01-01 10:20:30'), +('2001-01-01 '), +('20010101102030'), +('010101102030'); +SELECT ADDTIME(DATE'2001-01-01',a), a FROM t1; +DROP TABLE t1; + + +--vertical_results + +--echo # GREATEST(decimal, time) + +SELECT + GREATEST(8395959, TIME'00:00:00') AS c0, + GREATEST(8395959.0, TIME'00:00:00') AS c1, + GREATEST(8395959.00, TIME'00:00:00') AS c2, + GREATEST(8395959.000, TIME'00:00:00') AS c3, + GREATEST(8395959.0000, TIME'00:00:00') AS c4, + GREATEST(8395959.00000, TIME'00:00:00') AS c5, + GREATEST(8395959.000000, TIME'00:00:00') AS c6, + GREATEST(8395959.0000000, TIME'00:00:00') AS c7; + +SELECT + MICROSECOND(GREATEST(8395959, TIME'00:00:00')) AS c0, + MICROSECOND(GREATEST(8395959.0, TIME'00:00:00')) AS c1, + MICROSECOND(GREATEST(8395959.00, TIME'00:00:00')) AS c2, + MICROSECOND(GREATEST(8395959.000, TIME'00:00:00')) AS c3, + MICROSECOND(GREATEST(8395959.0000, TIME'00:00:00')) AS c4, + MICROSECOND(GREATEST(8395959.00000, TIME'00:00:00')) AS c5, + MICROSECOND(GREATEST(8395959.000000, TIME'00:00:00')) AS c6, + MICROSECOND(GREATEST(8395959.0000000, TIME'00:00:00')) AS c7; + +SELECT + CAST(GREATEST(8395959, TIME'00:00:00') AS SIGNED) AS ci, + CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,0)) AS c0, + CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,1)) AS c1, + CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,2)) AS c2, + CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,3)) AS c3, + CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,4)) AS c4, + CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,5)) AS c5, + CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,6)) AS c6, + CAST(GREATEST(8395959, TIME'00:00:00') AS DECIMAL(30,7)) AS c7; + +SELECT + GREATEST(8395959, TIME'00:00:00') AS ci, + GREATEST(8395959, TIME'00:00:00')+0 AS c0, + GREATEST(8395959, TIME'00:00:00')+0.0 AS c1, + GREATEST(8395959, TIME'00:00:00')+0.00 AS c2, + GREATEST(8395959, TIME'00:00:00')+0.000 AS c3, + GREATEST(8395959, TIME'00:00:00')+0.0000 AS c4, + GREATEST(8395959, TIME'00:00:00')+0.00000 AS c5, + GREATEST(8395959, TIME'00:00:00')+0.000000 AS c6, + GREATEST(8395959, TIME'00:00:00')+0.0000000 AS c7; + + + +--echo # GREATEST(string, time) + +SELECT + GREATEST('839:59:59', TIME'00:00:00') AS ci, + GREATEST('839:59:59.0', TIME'00:00:00') AS c1, + GREATEST('839:59:59.00', TIME'00:00:00') AS c2, + GREATEST('839:59:59.000', TIME'00:00:00') AS c3, + GREATEST('839:59:59.0000', TIME'00:00:00') AS c4, + GREATEST('839:59:59.00000', TIME'00:00:00') AS c5, + GREATEST('839:59:59.000000', TIME'00:00:00') AS c6, + GREATEST('839:59:59.0000000', TIME'00:00:00') AS c7; + +SELECT + MICROSECOND(GREATEST('839:59:59', TIME'00:00:00')) AS ci, + MICROSECOND(GREATEST('839:59:59.0', TIME'00:00:00')) AS c1, + MICROSECOND(GREATEST('839:59:59.00', TIME'00:00:00')) AS c2, + MICROSECOND(GREATEST('839:59:59.000', TIME'00:00:00')) AS c3, + MICROSECOND(GREATEST('839:59:59.0000', TIME'00:00:00')) AS c4, + MICROSECOND(GREATEST('839:59:59.00000', TIME'00:00:00')) AS c5, + MICROSECOND(GREATEST('839:59:59.000000', TIME'00:00:00')) AS c6, + MICROSECOND(GREATEST('839:59:59.0000000', TIME'00:00:00')) AS c7; + +SELECT + CAST(GREATEST('839:59:59', TIME'00:00:00') AS SIGNED) AS ci, + CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,0)) AS c0, + CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,1)) AS c1, + CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,2)) AS c2, + CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,3)) AS c3, + CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,4)) AS c4, + CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,5)) AS c5, + CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,6)) AS c6, + CAST(GREATEST('839:59:59', TIME'00:00:00') AS DECIMAL(30,7)) AS c7; + +SELECT + GREATEST('839:59:59', TIME'00:00:00') AS ci, + GREATEST('839:59:59', TIME'00:00:00')+0 AS c0, + GREATEST('839:59:59', TIME'00:00:00')+0.0 AS c1, + GREATEST('839:59:59', TIME'00:00:00')+0.00 AS c2, + GREATEST('839:59:59', TIME'00:00:00')+0.000 AS c3, + GREATEST('839:59:59', TIME'00:00:00')+0.0000 AS c4, + GREATEST('839:59:59', TIME'00:00:00')+0.00000 AS c5, + GREATEST('839:59:59', TIME'00:00:00')+0.000000 AS c6, + GREATEST('839:59:59', TIME'00:00:00')+0.0000000 AS c7; + + +--echo # ADDTIME(datetime, decimal) + +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0) AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.00) AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.000) AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0000) AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.00000) AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.000000) AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0000000) AS c7; + +SELECT + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)) AS c0, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0)) AS c1, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.00)) AS c2, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.000)) AS c3, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0000)) AS c4, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.00000)) AS c5, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.000000)) AS c6, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959.0000000)) AS c7; + +SELECT + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS SIGNED) AS ci, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,0)) AS c0, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,1)) AS c1, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,2)) AS c2, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,3)) AS c3, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,4)) AS c4, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,5)) AS c5, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,6)) AS c6, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS DECIMAL(30,7)) AS c7; + +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959) AS ci, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0 AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.0 AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.00 AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.000 AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.0000 AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.00000 AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.000000 AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 8395959)+0.0000000 AS c7; + +--echo # ADDTIME(datetime, string) + +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0') AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.00') AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.000') AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0000') AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.00000') AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.000000') AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0000000') AS c7; + +SELECT + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')) AS c0, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0')) AS c1, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.00')) AS c2, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.000')) AS c3, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0000')) AS c4, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.00000')) AS c5, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.000000')) AS c6, + MICROSECOND(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59.0000000')) AS c7; + +SELECT + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS SIGNED) AS ci, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,0)) AS c0, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,1)) AS c1, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,2)) AS c2, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,3)) AS c3, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,4)) AS c4, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,5)) AS c5, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,6)) AS c6, + CAST(ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS DECIMAL(30,7)) AS c7; + +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59') AS ci, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0 AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.0 AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.00 AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.000 AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.0000 AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.00000 AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.000000 AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '839:59:59')+0.0000000 AS c7; + +--echo # ADDTIME(time, decimal) + +SELECT + ADDTIME(TIME'00:00:00', 8395959) AS c0, + ADDTIME(TIME'00:00:00', 8395959.0) AS c1, + ADDTIME(TIME'00:00:00', 8395959.00) AS c2, + ADDTIME(TIME'00:00:00', 8395959.000) AS c3, + ADDTIME(TIME'00:00:00', 8395959.0000) AS c4, + ADDTIME(TIME'00:00:00', 8395959.00000) AS c5, + ADDTIME(TIME'00:00:00', 8395959.000000) AS c6, + ADDTIME(TIME'00:00:00', 8395959.0000000) AS c7; + +SELECT + MICROSECOND(ADDTIME(TIME'00:00:00', 8395959)) AS c0, + MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.0)) AS c1, + MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.00)) AS c2, + MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.000)) AS c3, + MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.0000)) AS c4, + MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.00000)) AS c5, + MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.000000)) AS c6, + MICROSECOND(ADDTIME(TIME'00:00:00', 8395959.0000000)) AS c7; + +SELECT + CAST(ADDTIME(TIME'00:00:00', 8395959) AS SIGNED) AS ci, + CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,0)) AS c0, + CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,1)) AS c1, + CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,2)) AS c2, + CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,3)) AS c3, + CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,4)) AS c4, + CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,5)) AS c5, + CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,6)) AS c6, + CAST(ADDTIME(TIME'00:00:00', 8395959) AS DECIMAL(30,7)) AS c7; + +SELECT + ADDTIME(TIME'00:00:00', 8395959) AS ci, + ADDTIME(TIME'00:00:00', 8395959)+0 AS c0, + ADDTIME(TIME'00:00:00', 8395959)+0.0 AS c1, + ADDTIME(TIME'00:00:00', 8395959)+0.00 AS c2, + ADDTIME(TIME'00:00:00', 8395959)+0.000 AS c3, + ADDTIME(TIME'00:00:00', 8395959)+0.0000 AS c4, + ADDTIME(TIME'00:00:00', 8395959)+0.00000 AS c5, + ADDTIME(TIME'00:00:00', 8395959)+0.000000 AS c6, + ADDTIME(TIME'00:00:00', 8395959)+0.0000000 AS c7; + +--echo # ADDTIME(time,string) + +SELECT + ADDTIME(TIME'00:00:00', '839:59:59') AS c0, + ADDTIME(TIME'00:00:00', '839:59:59.0') AS c1, + ADDTIME(TIME'00:00:00', '839:59:59.00') AS c2, + ADDTIME(TIME'00:00:00', '839:59:59.000') AS c3, + ADDTIME(TIME'00:00:00', '839:59:59.0000') AS c4, + ADDTIME(TIME'00:00:00', '839:59:59.00000') AS c5, + ADDTIME(TIME'00:00:00', '839:59:59.000000') AS c6, + ADDTIME(TIME'00:00:00', '839:59:59.0000000') AS c7; + +SELECT + MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59')) AS c0, + MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.0')) AS c1, + MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.00')) AS c2, + MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.000')) AS c3, + MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.0000')) AS c4, + MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.00000')) AS c5, + MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.000000')) AS c6, + MICROSECOND(ADDTIME(TIME'00:00:00', '839:59:59.0000000')) AS c7; + +SELECT + CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS SIGNED) AS ci, + CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,0)) AS c0, + CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,1)) AS c1, + CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,2)) AS c2, + CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,3)) AS c3, + CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,4)) AS c4, + CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,5)) AS c5, + CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,6)) AS c6, + CAST(ADDTIME(TIME'00:00:00', '839:59:59') AS DECIMAL(30,7)) AS c7; + +SELECT + ADDTIME(TIME'00:00:00', '839:59:59') AS ci, + ADDTIME(TIME'00:00:00', '839:59:59')+0 AS c0, + ADDTIME(TIME'00:00:00', '839:59:59')+0.0 AS c1, + ADDTIME(TIME'00:00:00', '839:59:59')+0.00 AS c2, + ADDTIME(TIME'00:00:00', '839:59:59')+0.000 AS c3, + ADDTIME(TIME'00:00:00', '839:59:59')+0.0000 AS c4, + ADDTIME(TIME'00:00:00', '839:59:59')+0.00000 AS c5, + ADDTIME(TIME'00:00:00', '839:59:59')+0.000000 AS c6, + ADDTIME(TIME'00:00:00', '839:59:59')+0.0000000 AS c7; + +--echo # ADDTIME(int,int) +SELECT + ADDTIME(0, 8395959) AS c, + MICROSECOND(ADDTIME(0, 8395959)) AS cm, + CAST(ADDTIME(0, 8395959) AS SIGNED) AS cs_fixme_mdev_17384, + CAST(ADDTIME(0, 8395959) AS DECIMAL(30,0)) AS cd300; + +SELECT + ADDTIME(20010101000000, 8395959) AS c, + MICROSECOND(ADDTIME(20010101000000, 8395959)) AS cm, + CAST(ADDTIME(20010101000000, 8395959) AS SIGNED) AS cs_fixme_mdev_17384, + CAST(ADDTIME(20010101000000, 8395959) AS DECIMAL(30,0)) AS cd300; + +--echo # ADDTIME(decimal,int) +--echo # 8385960 in cd300 is correct: addtime returns '838:59:59.9' +--echo # which is further *rounded* to a decimals(30,0) +SELECT + ADDTIME(0.0, 8395959) AS c, + MICROSECOND(ADDTIME(0.0, 8395959)) AS cm, + CAST(ADDTIME(0.0, 8395959) AS SIGNED) AS cs_fixme_mdev_17384, + CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,0)) AS cd300; + +SELECT + ADDTIME(20010101000000.0, 8395959) AS c, + MICROSECOND(ADDTIME(20010101000000.0, 8395959)) AS cm, + CAST(ADDTIME(20010101000000.0, 8395959) AS SIGNED) AS cs_fixme_mdev_17384, + CAST(ADDTIME(20010101000000.0, 8395959) AS DECIMAL(30,0)) AS cd300; + + +--echo # ADDTIME(decimal,decimal) + +SELECT + ADDTIME(0.0, 8395959.0) AS c1, + ADDTIME(0.0, 8395959.00) AS c2, + ADDTIME(0.0, 8395959.000) AS c3, + ADDTIME(0.0, 8395959.0000) AS c4, + ADDTIME(0.0, 8395959.00000) AS c5, + ADDTIME(0.0, 8395959.000000) AS c6, + ADDTIME(0.0, 8395959.0000000) AS c7; + +SELECT + MICROSECOND(ADDTIME(0.0, 8395959.0)) AS c1, + MICROSECOND(ADDTIME(0.0, 8395959.00)) AS c2, + MICROSECOND(ADDTIME(0.0, 8395959.000)) AS c3, + MICROSECOND(ADDTIME(0.0, 8395959.0000)) AS c4, + MICROSECOND(ADDTIME(0.0, 8395959.00000)) AS c5, + MICROSECOND(ADDTIME(0.0, 8395959.000000)) AS c6, + MICROSECOND(ADDTIME(0.0, 8395959.0000000)) AS c7; + +--echo # 8385960 in c1 is correct: addtime returns '838:59:59.9' +--echo # which is further *rounded* to a decimals(30,0) +SELECT + CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,0)) AS c0, + CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,1)) AS c1, + CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,2)) AS c2, + CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,3)) AS c3, + CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,4)) AS c4, + CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,5)) AS c5, + CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,6)) AS c6, + CAST(ADDTIME(0.0, 8395959) AS DECIMAL(30,7)) AS c7; + +SELECT + ADDTIME(0.0, 8395959)+0 AS c0, + ADDTIME(0.0, 8395959)+0.0 AS c1, + ADDTIME(0.0, 8395959)+0.00 AS c2, + ADDTIME(0.0, 8395959)+0.000 AS c3, + ADDTIME(0.0, 8395959)+0.0000 AS c4, + ADDTIME(0.0, 8395959)+0.00000 AS c5, + ADDTIME(0.0, 8395959)+0.000000 AS c6, + ADDTIME(0.0, 8395959)+0.0000000 AS c7; + + +--echo # TIMESTAMP(string,decimal) + +SELECT + TIMESTAMP('2001-01-01', 8395959) AS ci, + TIMESTAMP('2001-01-01', 8395959.0) AS c1, + TIMESTAMP('2001-01-01', 8395959.00) AS c2, + TIMESTAMP('2001-01-01', 8395959.000) AS c3, + TIMESTAMP('2001-01-01', 8395959.0000) AS c4, + TIMESTAMP('2001-01-01', 8395959.00000) AS c5, + TIMESTAMP('2001-01-01', 8395959.000000) AS c6, + TIMESTAMP('2001-01-01', 8395959.0000000) AS c7; + +SELECT + MICROSECOND(TIMESTAMP('2001-01-01', 8395959)) AS ci, + MICROSECOND(TIMESTAMP('2001-01-01', 8395959.0)) AS c1, + MICROSECOND(TIMESTAMP('2001-01-01', 8395959.00)) AS c2, + MICROSECOND(TIMESTAMP('2001-01-01', 8395959.000)) AS c3, + MICROSECOND(TIMESTAMP('2001-01-01', 8395959.0000)) AS c4, + MICROSECOND(TIMESTAMP('2001-01-01', 8395959.00000)) AS c5, + MICROSECOND(TIMESTAMP('2001-01-01', 8395959.000000)) AS c6, + MICROSECOND(TIMESTAMP('2001-01-01', 8395959.0000000)) AS c7; + +SELECT + CAST(TIMESTAMP('2001-01-01', 8395959) AS SIGNED) AS ci, + CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,0)) AS c0, + CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,1)) AS c1, + CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,2)) AS c2, + CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,3)) AS c3, + CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,4)) AS c4, + CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,5)) AS c5, + CAST(TIMESTAMP('2001-01-01', 8395959) AS DECIMAL(30,6)) AS c6; + +SELECT + TIMESTAMP('2001-01-01', 8395959) AS ci, + TIMESTAMP('2001-01-01', 8395959)+0 AS c0, + TIMESTAMP('2001-01-01', 8395959)+0.0 AS c1, + TIMESTAMP('2001-01-01', 8395959)+0.00 AS c2, + TIMESTAMP('2001-01-01', 8395959)+0.000 AS c3, + TIMESTAMP('2001-01-01', 8395959)+0.0000 AS c4, + TIMESTAMP('2001-01-01', 8395959)+0.00000 AS c5, + TIMESTAMP('2001-01-01', 8395959)+0.000000 AS c6, + TIMESTAMP('2001-01-01', 8395959)+0.0000000 AS c7; + +--echo # TIMESTAMP(string,string) + +SELECT + TIMESTAMP('2001-01-01', '839:59:59') AS ci, + TIMESTAMP('2001-01-01', '839:59:59.0') AS c1, + TIMESTAMP('2001-01-01', '839:59:59.00') AS c2, + TIMESTAMP('2001-01-01', '839:59:59.000') AS c3, + TIMESTAMP('2001-01-01', '839:59:59.0000') AS c4, + TIMESTAMP('2001-01-01', '839:59:59.00000') AS c5, + TIMESTAMP('2001-01-01', '839:59:59.000000') AS c6, + TIMESTAMP('2001-01-01', '839:59:59.0000000') AS c7; + +SELECT + MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59')) AS ci, + MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.0')) AS c1, + MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.00')) AS c2, + MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.000')) AS c3, + MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.0000')) AS c4, + MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.00000')) AS c5, + MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.000000')) AS c6, + MICROSECOND(TIMESTAMP('2001-01-01', '839:59:59.0000000')) AS c7; + +SELECT + CAST(TIMESTAMP('2001-01-01', '839:59:59') AS SIGNED) AS ci, + CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,0)) AS c0, + CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,1)) AS c1, + CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,2)) AS c2, + CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,3)) AS c3, + CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,4)) AS c4, + CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,5)) AS c5, + CAST(TIMESTAMP('2001-01-01', '839:59:59') AS DECIMAL(30,6)) AS c6; + +SELECT + TIMESTAMP('2001-01-01', '839:59:59') AS ci, + TIMESTAMP('2001-01-01', '839:59:59')+0 AS c0, + TIMESTAMP('2001-01-01', '839:59:59')+0.0 AS c1, + TIMESTAMP('2001-01-01', '839:59:59')+0.00 AS c2, + TIMESTAMP('2001-01-01', '839:59:59')+0.000 AS c3, + TIMESTAMP('2001-01-01', '839:59:59')+0.0000 AS c4, + TIMESTAMP('2001-01-01', '839:59:59')+0.00000 AS c5, + TIMESTAMP('2001-01-01', '839:59:59')+0.000000 AS c6, + TIMESTAMP('2001-01-01', '839:59:59')+0.0000000 AS c7; + +--horizontal_results + +--echo # Corner cases for TIMESTAMP(timestamp,xxx) + +--echo # HOUR is outside of supported INTERVAL DAYS TO SECONDS range +--echo # Expect NULL with INTERVAL warnings +CREATE TABLE t1 (a VARCHAR(64), b VARCHAR(64)); +INSERT INTO t1 VALUES ('4294967296:00:00', '178956970 16:00:00'); +INSERT INTO t1 VALUES ('4294967295:59:59', '178956970 15:59:59'); +INSERT INTO t1 VALUES ('4294967294:59:59', '178956970 14:59:59'); +INSERT INTO t1 VALUES ('87649416:00:00', '3652059 00:00:00'); +SELECT TIMESTAMP('0001-01-01 00:00:00', a) AS ta, TIMESTAMP('0001-01-01 00:00:00', b) AS tb FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64), b VARCHAR(64)); +INSERT INTO t1 VALUES ('-4294967296:00:00', '-178956970 16:00:00'); +INSERT INTO t1 VALUES ('-4294967295:59:59', '-178956970 15:59:59'); +INSERT INTO t1 VALUES ('-4294967294:59:59', '-178956970 14:59:59'); +INSERT INTO t1 VALUES ('-87649416:00:00', '-3652059 00:00:00'); +SELECT TIMESTAMP('9999-12-31 23:59:59', a) AS ta, TIMESTAMP('9999-12-31 23:59:59.999999', b) AS tb FROM t1; +DROP TABLE t1; + +--echo # HOUR is OK +--echo # Expect max or near-max DATETIME value + no INTERVAL warnings +CREATE TABLE t1 (a VARCHAR(64), b VARCHAR(64)); +INSERT INTO t1 VALUES ('87649415:59:59.999999', '3652058 23:59:59.999999'); +INSERT INTO t1 VALUES ('87649415:59:59', '3652058 23:59:59'); +SELECT TIMESTAMP('0001-01-01 00:00:00', a) AS ta, TIMESTAMP('0001-01-01 00:00:00', b) AS tb FROM t1; +DROP TABLE t1; + +--echo # HOUR is OK +--echo # Expect near '0001-01-01 00:00:00' DATETIME value + no INTERVAL warnings +CREATE TABLE t1 (a VARCHAR(64), b VARCHAR(64)); +INSERT INTO t1 VALUES ('-87649415:59:59.999999', '-3652058 23:59:59.999999'); +INSERT INTO t1 VALUES ('-87649415:59:59', '-3652058 23:59:59'); +SELECT TIMESTAMP('9999-12-31 23:59:59', a) AS ta, TIMESTAMP('9999-12-31 23:59:59.999999', b) AS tb FROM t1; +DROP TABLE t1; + +--echo # HOUR is OK +--echo # Expect NULL on datetime arithmetic overflow + no INTERVAL warnings +CREATE TABLE t1 (a VARCHAR(64), b VARCHAR(64)); +INSERT INTO t1 VALUES ('-00:00:00.000001', '-0 00:00:00.000001'); +SELECT TIMESTAMP('0001-01-01 00:00:00', a) AS ta, TIMESTAMP('0001-01-01 00:00:00', b) AS tb FROM t1; +DROP TABLE t1; + + +--echo # Corner cases for ADDTIME(timestamp,xxx) +--vertical_results + +--echo # HOUR is outside of UINT_MAX32 range +--echo # Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" + +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959) AS ci, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0 AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.0 AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.00 AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.000 AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.0000 AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.00000 AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.000000 AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672965959)+0.0000000 AS c7; + +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59') AS ci, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0 AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.0 AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.00 AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.000 AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.0000 AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.00000 AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.000000 AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967296:59:59')+0.0000000 AS c7; + +## TODO: add '0001-01-01 00:00:00' + +--echo # HOUR UINT_MAX32 +--echo # Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959) AS ci, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0 AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.0 AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.00 AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.000 AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.0000 AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.00000 AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.000000 AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 42949672955959)+0.0000000 AS c7; + +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59') AS ci, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0 AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.0 AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.00 AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.000 AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.0000 AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.00000 AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.000000 AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '4294967295:59:59')+0.0000000 AS c7; + +--echo # HOUR is max_useful_hour()+1 +--echo # Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959) AS ci, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0 AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.0 AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.00 AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.000 AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.0000 AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.00000 AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.000000 AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494165959)+0.0000000 AS c7; + +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59') AS ci, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0 AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.0 AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.00 AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.000 AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.0000 AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.00000 AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.000000 AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649416:59:59')+0.0000000 AS c7; + +--echo # HOUR is max_useful_hour() +--echo # Expect NULL (calc_time_diff overflows ) + no INTERVAL warnings +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959) AS ci, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0 AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.0 AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.00 AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.000 AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.0000 AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.00000 AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.000000 AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', 876494155959)+0.0000000 AS c7; + +SELECT + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59') AS ci, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0 AS c0, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.0 AS c1, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.00 AS c2, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.000 AS c3, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.0000 AS c4, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.00000 AS c5, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.000000 AS c6, + ADDTIME(TIMESTAMP'2001-01-01 00:00:00', '87649415:59:59')+0.0000000 AS c7; + +--echo # HOUR is max_useful_hour() +--echo # Expect non-NULL + no warnings +SELECT + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959) AS ci, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0 AS c0, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.0 AS c1, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.00 AS c2, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.000 AS c3, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.0000 AS c4, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.00000 AS c5, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.000000 AS c6, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', 876494155959)+0.0000000 AS c7; + +SELECT + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59') AS ci, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0 AS c0, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.0 AS c1, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.00 AS c2, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.000 AS c3, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.0000 AS c4, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.00000 AS c5, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.000000 AS c6, + ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59')+0.0000000 AS c7; +--horizontal_results + + +--echo # Corner cases for ADDTIME(time,xxx) +--vertical_results + +--echo # HOUR outside of UINT32 range +--echo # Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT + ADDTIME(TIME'00:00:00', 42949672965959) AS ci, + ADDTIME(TIME'00:00:00', 42949672965959)+0 AS c0, + ADDTIME(TIME'00:00:00', 42949672965959)+0.0 AS c1, + ADDTIME(TIME'00:00:00', 42949672965959)+0.00 AS c2, + ADDTIME(TIME'00:00:00', 42949672965959)+0.000 AS c3, + ADDTIME(TIME'00:00:00', 42949672965959)+0.0000 AS c4, + ADDTIME(TIME'00:00:00', 42949672965959)+0.00000 AS c5, + ADDTIME(TIME'00:00:00', 42949672965959)+0.000000 AS c6, + ADDTIME(TIME'00:00:00', 42949672965959)+0.0000000 AS c7; + +SELECT + ADDTIME(TIME'00:00:00', '4294967296:59:59') AS ci, + ADDTIME(TIME'00:00:00', '4294967296:59:59')+0 AS c0, + ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.0 AS c1, + ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.00 AS c2, + ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.000 AS c3, + ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.0000 AS c4, + ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.00000 AS c5, + ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.000000 AS c6, + ADDTIME(TIME'00:00:00', '4294967296:59:59')+0.0000000 AS c7; + +--echo # HOUR is UINT_MAX32 (outside of INTERVAL DAY TO SECOND range) +--echo # Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" +SELECT + ADDTIME(TIME'00:00:00', 42949672955959) AS ci, + ADDTIME(TIME'00:00:00', 42949672955959)+0 AS c0, + ADDTIME(TIME'00:00:00', 42949672955959)+0.0 AS c1, + ADDTIME(TIME'00:00:00', 42949672955959)+0.00 AS c2, + ADDTIME(TIME'00:00:00', 42949672955959)+0.000 AS c3, + ADDTIME(TIME'00:00:00', 42949672955959)+0.0000 AS c4, + ADDTIME(TIME'00:00:00', 42949672955959)+0.00000 AS c5, + ADDTIME(TIME'00:00:00', 42949672955959)+0.000000 AS c6, + ADDTIME(TIME'00:00:00', 42949672955959)+0.0000000 AS c7; + +SELECT + ADDTIME(TIME'00:00:00', '4294967295:59:59') AS ci, + ADDTIME(TIME'00:00:00', '4294967295:59:59')+0 AS c0, + ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.0 AS c1, + ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.00 AS c2, + ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.000 AS c3, + ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.0000 AS c4, + ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.00000 AS c5, + ADDTIME(TIME'00:00:00', '4294967295:59:59')+0.000000 AS c6, + ADDTIME(TIME'00:00:00', '4294967295;00:00')+0.0000000 AS c7; + +--echo # HOUR is max_useful_hour()+1 (outside of INTERVAL DAY TO SECOND range) +--echo # Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" + +SELECT + ADDTIME(TIME'00:00:00', 876494165959) AS ci, + ADDTIME(TIME'00:00:00', 876494165959)+0 AS c0, + ADDTIME(TIME'00:00:00', 876494165959)+0.0 AS c1, + ADDTIME(TIME'00:00:00', 876494165959)+0.00 AS c2, + ADDTIME(TIME'00:00:00', 876494165959)+0.000 AS c3, + ADDTIME(TIME'00:00:00', 876494165959)+0.0000 AS c4, + ADDTIME(TIME'00:00:00', 876494165959)+0.00000 AS c5, + ADDTIME(TIME'00:00:00', 876494165959)+0.000000 AS c6, + ADDTIME(TIME'00:00:00', 876494165959)+0.0000000 AS c7; + +SELECT + ADDTIME(TIME'00:00:00', '87649416:59:59') AS ci, + ADDTIME(TIME'00:00:00', '87649416:59:59')+0 AS c0, + ADDTIME(TIME'00:00:00', '87649416:59:59')+0.0 AS c1, + ADDTIME(TIME'00:00:00', '87649416:59:59')+0.00 AS c2, + ADDTIME(TIME'00:00:00', '87649416:59:59')+0.000 AS c3, + ADDTIME(TIME'00:00:00', '87649416:59:59')+0.0000 AS c4, + ADDTIME(TIME'00:00:00', '87649416:59:59')+0.00000 AS c5, + ADDTIME(TIME'00:00:00', '87649416:59:59')+0.000000 AS c6, + ADDTIME(TIME'00:00:00', '87649416:59:59')+0.0000000 AS c7; + +--echo # HOUR is max_useful_hour()+1 (outside of INTERVAL DAY TO SECOND range) +--echo # Expect NULL + "Incorrect INTERVAL DAY TO SECOND value" + +SELECT + ADDTIME(TIME'-838:59:59', 876494165959) AS ci, + ADDTIME(TIME'-838:59:59.9', 876494165959) AS c1, + ADDTIME(TIME'-838:59:59.99', 876494165959) AS c2, + ADDTIME(TIME'-838:59:59.999', 876494165959) AS c3, + ADDTIME(TIME'-838:59:59.9999', 876494165959) AS c4, + ADDTIME(TIME'-838:59:59.99999', 876494165959) AS c5, + ADDTIME(TIME'-838:59:59.999999', 876494165959) AS c6; + +SELECT + ADDTIME(TIME'-838:59:59', '87649416:59:59') AS ci, + ADDTIME(TIME'-838:59:59.9', '87649416:59:59') AS c1, + ADDTIME(TIME'-838:59:59.99', '87649416:59:59') AS c2, + ADDTIME(TIME'-838:59:59.999', '87649416:59:59') AS c3, + ADDTIME(TIME'-838:59:59.9999', '87649416:59:59') AS c4, + ADDTIME(TIME'-838:59:59.99999', '87649416:59:59') AS c5, + ADDTIME(TIME'-838:59:59.999999', '87649416:59:59') AS c6; + +# This does not give a warning about nanosecond truncation in --ps runs +# so disable warnings +--disable_warnings +SELECT + ADDTIME(TIME'-838:59:59.9999999', '87649416:59:59') AS c7; +--enable_warnings + +--echo # HOUR is max_useful_hour() (inside INTERVAL DAY TO SECOND range) +--echo # Expect max TIME(0) + zero fraction + TIME warnings + no INTEVAL warnings +SELECT + ADDTIME(TIME'00:00:00', 876494155959) AS ci, + ADDTIME(TIME'00:00:00', 876494155959)+0 AS c0, + ADDTIME(TIME'00:00:00', 876494155959)+0.0 AS c1, + ADDTIME(TIME'00:00:00', 876494155959)+0.00 AS c2, + ADDTIME(TIME'00:00:00', 876494155959)+0.000 AS c3, + ADDTIME(TIME'00:00:00', 876494155959)+0.0000 AS c4, + ADDTIME(TIME'00:00:00', 876494155959)+0.00000 AS c5, + ADDTIME(TIME'00:00:00', 876494155959)+0.000000 AS c6, + ADDTIME(TIME'00:00:00', 876494155959)+0.0000000 AS c7; + +SELECT + ADDTIME(TIME'00:00:00', '87649415:59:59') AS ci, + ADDTIME(TIME'00:00:00', '87649415:59:59')+0 AS c0, + ADDTIME(TIME'00:00:00', '87649415:59:59')+0.0 AS c1, + ADDTIME(TIME'00:00:00', '87649415:59:59')+0.00 AS c2, + ADDTIME(TIME'00:00:00', '87649415:59:59')+0.000 AS c3, + ADDTIME(TIME'00:00:00', '87649415:59:59')+0.0000 AS c4, + ADDTIME(TIME'00:00:00', '87649415:59:59')+0.00000 AS c5, + ADDTIME(TIME'00:00:00', '87649415:59:59')+0.000000 AS c6, + ADDTIME(TIME'00:00:00', '87649415:59:59')+0.0000000 AS c7; + + +--echo # HOUR is max_useful_hour() (inside INTERVAL DAY TO SECOND range) +--echo # Expect max TIME(N) + TIME warnings + no INTERVAL warnings + +SELECT + ADDTIME(TIME'-838:59:59', 876494155959) AS ci, + ADDTIME(TIME'-838:59:59.9', 876494155959) AS c1, + ADDTIME(TIME'-838:59:59.99', 876494155959) AS c2, + ADDTIME(TIME'-838:59:59.999', 876494155959) AS c3, + ADDTIME(TIME'-838:59:59.9999', 876494155959) AS c4, + ADDTIME(TIME'-838:59:59.99999', 876494155959) AS c5, + ADDTIME(TIME'-838:59:59.999999', 876494155959) AS c6; + +SELECT + ADDTIME(TIME'-838:59:59', '87649415:59:59') AS ci, + ADDTIME(TIME'-838:59:59.9', '87649415:59:59') AS c1, + ADDTIME(TIME'-838:59:59.99', '87649415:59:59') AS c2, + ADDTIME(TIME'-838:59:59.999', '87649415:59:59') AS c3, + ADDTIME(TIME'-838:59:59.9999', '87649415:59:59') AS c4, + ADDTIME(TIME'-838:59:59.99999', '87649415:59:59') AS c5, + ADDTIME(TIME'-838:59:59.999999', '87649415:59:59') AS c6; + +# This does not give a warning about nanosecond truncation in --ps runs +# so disable warnings +--disable_warnings +SELECT + ADDTIME(TIME'-838:59:59.9999999', '87649415:59:59') AS c7; +--enable_warnings + +--horizontal_results + + +--echo # +--echo # MDEV-17400 The result of TIME('42949672965959-01') depends on architecture +--echo # + +SELECT TIME('42949672955959-01'), TIME('42949672965959-01'); +SELECT TIME('18446744073709551615-01'), TIME('18446744073709551616-01'); + +--echo # +--echo # MDEV-17434 EXTRACT(DAY FROM negative_time) returns wrong result +--echo # + +CREATE TABLE t1 (a TIME(6)); +INSERT INTO t1 VALUES ('-24:10:10.10'); +SELECT + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a), + EXTRACT(DAY FROM a), + EXTRACT(DAY_HOUR FROM a), + EXTRACT(DAY_MINUTE FROM a), + EXTRACT(DAY_SECOND FROM a), + EXTRACT(DAY_MICROSECOND FROM a) +FROM t1; +CREATE TABLE t2 AS +SELECT + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a), + EXTRACT(DAY FROM a), + EXTRACT(DAY_HOUR FROM a), + EXTRACT(DAY_MINUTE FROM a), + EXTRACT(DAY_SECOND FROM a), + EXTRACT(DAY_MICROSECOND FROM a) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; +DROP TABLE t1; + + +--echo # +--echo # MDEV-17478 Wrong result for TIME('+100:20:30') +--echo # + +SELECT TIME('+100:20:30'); + +--echo # +--echo # MDEV-17477 Wrong result for TIME('-2001-01-01 10:20:30') +--echo # + +SELECT TIME('-2001-01-01 10:20:30'); +SELECT TIME('2001-01-01') AS c1, TIME('2001-01-01 ') AS c2; +SELECT TIME('0001:01:01 '), TIME('0001:01:01 '); +SELECT TIME('1 2'), TIME('1 2 '); + +SELECT TIME('2001-01-01T'), TIME('2001-01-01T '); +SELECT TIME('901-01-01T1'), TIME('901-01-01T10'); +SELECT TIME('091-01-01T1'), TIME('091-01-01T10'); + +SELECT TIME('0001:01:01x'), TIME('0001:01:01xx'); +SELECT TIME('0001:01:01.'), TIME('0001:01:01..'); +SELECT TIME('0001:01:01-'), TIME('0001:01:01--'); +SELECT TIME('0001:01:01-'), TIME('0001:01:01--'); + +SELECT TIME('-xxx'), TIME('-xxxxxxxxxxxxxxxxxxxx'); +SELECT TIME('- '), TIME('- '); +SELECT TIME('-'), TIME('-'); +SELECT TIME('1-1-1 1:1:1'), TIME('1-1-1 1:1:1.0'); +SELECT TIME('1-1-1 1:2:3'), TIME('1-1-1 1:2:3.0'); + +SELECT + CAST('20050326112233 garbage' as datetime), + CAST('20050326 garbage' as date), + CAST('50326 garbage' as time); + +SELECT TIME('- 01:00:00'), TIME('- 1 01:00:00'); + + +--echo # +--echo # MDEV-17854 Assertion `decimals <= 6' failed in my_time_fraction_remainder on SELECT with NULLIF and FROM_UNIXTIME on incorrect time +--echo # + +SET time_zone='+00:00'; +SELECT NULLIF(FROM_UNIXTIME('foo'), '2012-12-12 21:10:14'); +SET time_zone=DEFAULT; diff --git a/mysql-test/main/func_time_round.result b/mysql-test/main/func_time_round.result new file mode 100644 index 00000000000..b335cf393ba --- /dev/null +++ b/mysql-test/main/func_time_round.result @@ -0,0 +1,1374 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; +CREATE TABLE t1_datetime_in_varchar (id SERIAL, a VARCHAR(64)); +INSERT INTO t1_datetime_in_varchar (a) VALUES +('2000-12-31 23:59:59'), +('2000-12-31 23:59:59.9'), +('2000-12-31 23:59:59.99'), +('2000-12-31 23:59:59.999'), +('2000-12-31 23:59:59.9999'), +('2000-12-31 23:59:59.99999'), +('2000-12-31 23:59:59.999999'), +('2000-12-31 23:59:59.9999999'); +CREATE TABLE t1_datetime_in_decimal (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_datetime_in_decimal (a) VALUES +(20001231235959), +(20001231235959.9), +(20001231235959.99), +(20001231235959.999), +(20001231235959.9999), +(20001231235959.99999), +(20001231235959.999999), +(20001231235959.9999999); +CREATE TABLE t1_time_in_varchar (id SERIAL, a VARCHAR(64)); +INSERT INTO t1_time_in_varchar (a) VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.99'), +('00:00:00.999'), +('00:00:00.9999'), +('00:00:00.99999'), +('00:00:00.999999'), +('00:00:00.9999999'); +INSERT INTO t1_time_in_varchar (a) VALUES +('837:59:59.9999999'), +('838:59:59'), +('838:59:59.9'), +('838:59:59.99'), +('838:59:59.999'), +('838:59:59.9999'), +('838:59:59.99999'), +('838:59:59.999999'), +('838:59:59.9999999'), +('839:59:59.9999999'), +('87649414:59:59.999999'), +('87649414:59:59.9999999'), +('87649415:59:59.999999'), +('87649415:59:59.9999999'); +CREATE TABLE t1_time_in_decimal (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_time_in_decimal (a) VALUES +(0), +(0.9), +(0.99), +(0.999), +(0.9999), +(0.99999), +(0.999999), +(0.9999999); +INSERT INTO t1_time_in_decimal (a) VALUES +(8375959.9999999), +(8385959), +(8385959.9), +(8385959.99), +(8385959.999), +(8385959.9999), +(8385959.99999), +(8385959.999999), +(8385959.9999999), +(8395959.9999999), +(876494145959.999999), +(876494145959.9999999), +(876494155959.999999), +(876494155959.9999999); +# +# TIME: LEAST/GREATEST +# +SELECT GREATEST(TIME'00:00:00', a) FROM t1_time_in_varchar; +GREATEST(TIME'00:00:00', a) +00:00:00.000000 +00:00:00.900000 +00:00:00.990000 +00:00:00.999000 +00:00:00.999900 +00:00:00.999990 +00:00:00.999999 +00:00:01.000000 +838:00:00.000000 +838:59:59.000000 +838:59:59.900000 +838:59:59.990000 +838:59:59.999000 +838:59:59.999900 +838:59:59.999990 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Warning 1292 Truncated incorrect time value: '838:59:59.9999999' +Warning 1292 Truncated incorrect time value: '839:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +SELECT GREATEST(TIME'00:00:00', a) FROM t1_time_in_decimal; +GREATEST(TIME'00:00:00', a) +00:00:00.000000 +00:00:00.900000 +00:00:00.990000 +00:00:00.999000 +00:00:00.999900 +00:00:00.999990 +00:00:00.999999 +00:00:01.000000 +838:00:00.000000 +838:59:59.000000 +838:59:59.900000 +838:59:59.990000 +838:59:59.999000 +838:59:59.999900 +838:59:59.999990 +838:59:59.999999 +838:59:59.999999 +838:59:59.999999 +NULL +NULL +NULL +NULL +Warnings: +Warning 1292 Incorrect time value: '8385959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 17 +Warning 1292 Incorrect time value: '8395959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 18 +Warning 1292 Incorrect time value: '876494145959.9999990000' for column `test`.`t1_time_in_decimal`.`a` at row 19 +Warning 1292 Incorrect time value: '876494145959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 20 +Warning 1292 Incorrect time value: '876494155959.9999990000' for column `test`.`t1_time_in_decimal`.`a` at row 21 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 22 +SELECT GREATEST(TIME'00:00:00', '00:00:00.0000004'); +GREATEST(TIME'00:00:00', '00:00:00.0000004') +00:00:00.000000 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.0000004' +SELECT GREATEST(TIME'00:00:00', 0.0000004); +GREATEST(TIME'00:00:00', 0.0000004) +00:00:00.000000 +SELECT GREATEST(TIME'00:00:00', '00:00:00.0000005'); +GREATEST(TIME'00:00:00', '00:00:00.0000005') +00:00:00.000001 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.0000005' +SELECT GREATEST(TIME'00:00:00', 0.0000005); +GREATEST(TIME'00:00:00', 0.0000005) +00:00:00.000001 +# +# Functions with a single TIME input, conversion from DATETIME-in-VARCHAR +# +SELECT SECOND(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SECOND(a) CAST(a AS TIME(6)) a +59 23:59:59.000000 2000-12-31 23:59:59 +59 23:59:59.900000 2000-12-31 23:59:59.9 +59 23:59:59.990000 2000-12-31 23:59:59.99 +59 23:59:59.999000 2000-12-31 23:59:59.999 +59 23:59:59.999900 2000-12-31 23:59:59.9999 +59 23:59:59.999990 2000-12-31 23:59:59.99999 +59 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT MINUTE(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +MINUTE(a) CAST(a AS TIME(6)) a +59 23:59:59.000000 2000-12-31 23:59:59 +59 23:59:59.900000 2000-12-31 23:59:59.9 +59 23:59:59.990000 2000-12-31 23:59:59.99 +59 23:59:59.999000 2000-12-31 23:59:59.999 +59 23:59:59.999900 2000-12-31 23:59:59.9999 +59 23:59:59.999990 2000-12-31 23:59:59.99999 +59 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT HOUR(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +HOUR(a) CAST(a AS TIME(6)) a +23 23:59:59.000000 2000-12-31 23:59:59 +23 23:59:59.900000 2000-12-31 23:59:59.9 +23 23:59:59.990000 2000-12-31 23:59:59.99 +23 23:59:59.999000 2000-12-31 23:59:59.999 +23 23:59:59.999900 2000-12-31 23:59:59.9999 +23 23:59:59.999990 2000-12-31 23:59:59.99999 +23 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT EXTRACT(SECOND FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +EXTRACT(SECOND FROM a) CAST(a AS TIME(6)) a +59 23:59:59.000000 2000-12-31 23:59:59 +59 23:59:59.900000 2000-12-31 23:59:59.9 +59 23:59:59.990000 2000-12-31 23:59:59.99 +59 23:59:59.999000 2000-12-31 23:59:59.999 +59 23:59:59.999900 2000-12-31 23:59:59.9999 +59 23:59:59.999990 2000-12-31 23:59:59.99999 +59 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT EXTRACT(MINUTE FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +EXTRACT(MINUTE FROM a) CAST(a AS TIME(6)) a +59 23:59:59.000000 2000-12-31 23:59:59 +59 23:59:59.900000 2000-12-31 23:59:59.9 +59 23:59:59.990000 2000-12-31 23:59:59.99 +59 23:59:59.999000 2000-12-31 23:59:59.999 +59 23:59:59.999900 2000-12-31 23:59:59.9999 +59 23:59:59.999990 2000-12-31 23:59:59.99999 +59 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT EXTRACT(HOUR FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +EXTRACT(HOUR FROM a) CAST(a AS TIME(6)) a +23 23:59:59.000000 2000-12-31 23:59:59 +23 23:59:59.900000 2000-12-31 23:59:59.9 +23 23:59:59.990000 2000-12-31 23:59:59.99 +23 23:59:59.999000 2000-12-31 23:59:59.999 +23 23:59:59.999900 2000-12-31 23:59:59.9999 +23 23:59:59.999990 2000-12-31 23:59:59.99999 +23 23:59:59.999999 2000-12-31 23:59:59.999999 +0 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT TIME_TO_SEC(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +TIME_TO_SEC(a) CAST(a AS TIME(6)) a +86399.000000 23:59:59.000000 2000-12-31 23:59:59 +86399.900000 23:59:59.900000 2000-12-31 23:59:59.9 +86399.990000 23:59:59.990000 2000-12-31 23:59:59.99 +86399.999000 23:59:59.999000 2000-12-31 23:59:59.999 +86399.999900 23:59:59.999900 2000-12-31 23:59:59.9999 +86399.999990 23:59:59.999990 2000-12-31 23:59:59.99999 +86399.999999 23:59:59.999999 2000-12-31 23:59:59.999999 +0.000000 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +# +# Functions with a single TIME input, conversion from DATETIME-in-DECIMAL +# +SELECT SECOND(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SECOND(a) CAST(a AS TIME(6)) a +59 23:59:59.000000 20001231235959.0000000000 +59 23:59:59.900000 20001231235959.9000000000 +59 23:59:59.990000 20001231235959.9900000000 +59 23:59:59.999000 20001231235959.9990000000 +59 23:59:59.999900 20001231235959.9999000000 +59 23:59:59.999990 20001231235959.9999900000 +59 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT MINUTE(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +MINUTE(a) CAST(a AS TIME(6)) a +59 23:59:59.000000 20001231235959.0000000000 +59 23:59:59.900000 20001231235959.9000000000 +59 23:59:59.990000 20001231235959.9900000000 +59 23:59:59.999000 20001231235959.9990000000 +59 23:59:59.999900 20001231235959.9999000000 +59 23:59:59.999990 20001231235959.9999900000 +59 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT HOUR(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +HOUR(a) CAST(a AS TIME(6)) a +23 23:59:59.000000 20001231235959.0000000000 +23 23:59:59.900000 20001231235959.9000000000 +23 23:59:59.990000 20001231235959.9900000000 +23 23:59:59.999000 20001231235959.9990000000 +23 23:59:59.999900 20001231235959.9999000000 +23 23:59:59.999990 20001231235959.9999900000 +23 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT EXTRACT(SECOND FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +EXTRACT(SECOND FROM a) CAST(a AS TIME(6)) a +59 23:59:59.000000 20001231235959.0000000000 +59 23:59:59.900000 20001231235959.9000000000 +59 23:59:59.990000 20001231235959.9900000000 +59 23:59:59.999000 20001231235959.9990000000 +59 23:59:59.999900 20001231235959.9999000000 +59 23:59:59.999990 20001231235959.9999900000 +59 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT EXTRACT(MINUTE FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +EXTRACT(MINUTE FROM a) CAST(a AS TIME(6)) a +59 23:59:59.000000 20001231235959.0000000000 +59 23:59:59.900000 20001231235959.9000000000 +59 23:59:59.990000 20001231235959.9900000000 +59 23:59:59.999000 20001231235959.9990000000 +59 23:59:59.999900 20001231235959.9999000000 +59 23:59:59.999990 20001231235959.9999900000 +59 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT EXTRACT(HOUR FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +EXTRACT(HOUR FROM a) CAST(a AS TIME(6)) a +23 23:59:59.000000 20001231235959.0000000000 +23 23:59:59.900000 20001231235959.9000000000 +23 23:59:59.990000 20001231235959.9900000000 +23 23:59:59.999000 20001231235959.9990000000 +23 23:59:59.999900 20001231235959.9999000000 +23 23:59:59.999990 20001231235959.9999900000 +23 23:59:59.999999 20001231235959.9999990000 +0 00:00:00.000000 20001231235959.9999999000 +SELECT TIME_TO_SEC(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +TIME_TO_SEC(a) CAST(a AS TIME(6)) a +86399.000000 23:59:59.000000 20001231235959.0000000000 +86399.900000 23:59:59.900000 20001231235959.9000000000 +86399.990000 23:59:59.990000 20001231235959.9900000000 +86399.999000 23:59:59.999000 20001231235959.9990000000 +86399.999900 23:59:59.999900 20001231235959.9999000000 +86399.999990 23:59:59.999990 20001231235959.9999900000 +86399.999999 23:59:59.999999 20001231235959.9999990000 +0.000000 00:00:00.000000 20001231235959.9999999000 +# +# Functions with a single TIME interval input, conversion from TIME-interval-in-VARCHAR +# +SELECT +EXTRACT(DAY FROM a), +EXTRACT(HOUR FROM a), +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a), +CAST(a AS INTERVAL DAY_SECOND(6)), +a +FROM t1_time_in_varchar ORDER BY id; +EXTRACT(DAY FROM a) EXTRACT(HOUR FROM a) EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a) CAST(a AS INTERVAL DAY_SECOND(6)) a +0 0 0 0 0 00:00:00.000000 00:00:00 +0 0 0 0 900000 00:00:00.900000 00:00:00.9 +0 0 0 0 990000 00:00:00.990000 00:00:00.99 +0 0 0 0 999000 00:00:00.999000 00:00:00.999 +0 0 0 0 999900 00:00:00.999900 00:00:00.9999 +0 0 0 0 999990 00:00:00.999990 00:00:00.99999 +0 0 0 0 999999 00:00:00.999999 00:00:00.999999 +0 0 0 1 0 00:00:01.000000 00:00:00.9999999 +34 22 0 0 0 34 22:00:00.000000 837:59:59.9999999 +34 22 59 59 0 34 22:59:59.000000 838:59:59 +34 22 59 59 900000 34 22:59:59.900000 838:59:59.9 +34 22 59 59 990000 34 22:59:59.990000 838:59:59.99 +34 22 59 59 999000 34 22:59:59.999000 838:59:59.999 +34 22 59 59 999900 34 22:59:59.999900 838:59:59.9999 +34 22 59 59 999990 34 22:59:59.999990 838:59:59.99999 +34 22 59 59 999999 34 22:59:59.999999 838:59:59.999999 +34 23 0 0 0 34 23:00:00.000000 838:59:59.9999999 +35 0 0 0 0 35 00:00:00.000000 839:59:59.9999999 +3652058 22 59 59 999999 3652058 22:59:59.999999 87649414:59:59.999999 +3652058 23 0 0 0 3652058 23:00:00.000000 87649414:59:59.9999999 +3652058 23 59 59 999999 3652058 23:59:59.999999 87649415:59:59.999999 +3652058 23 59 59 999999 3652058 23:59:59.999999 87649415:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '838:59:59.9999999' +Note 1292 Truncated incorrect time value: '838:59:59.9999999' +Note 1292 Truncated incorrect time value: '838:59:59.9999999' +Note 1292 Truncated incorrect time value: '838:59:59.9999999' +Note 1292 Truncated incorrect time value: '838:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '838:59:59.9999999' +Note 1292 Truncated incorrect time value: '839:59:59.9999999' +Note 1292 Truncated incorrect time value: '839:59:59.9999999' +Note 1292 Truncated incorrect time value: '839:59:59.9999999' +Note 1292 Truncated incorrect time value: '839:59:59.9999999' +Note 1292 Truncated incorrect time value: '839:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '839:59:59.9999999' +Note 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Note 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Note 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Note 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Note 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '87649414:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '87649415:59:59.9999999' +SELECT +TIME_TO_SEC(a), +CAST(a AS TIME(6)), +a +FROM t1_time_in_varchar ORDER BY id; +TIME_TO_SEC(a) CAST(a AS TIME(6)) a +0.000000 00:00:00.000000 00:00:00 +0.900000 00:00:00.900000 00:00:00.9 +0.990000 00:00:00.990000 00:00:00.99 +0.999000 00:00:00.999000 00:00:00.999 +0.999900 00:00:00.999900 00:00:00.9999 +0.999990 00:00:00.999990 00:00:00.99999 +0.999999 00:00:00.999999 00:00:00.999999 +1.000000 00:00:01.000000 00:00:00.9999999 +3016800.000000 838:00:00.000000 837:59:59.9999999 +3020399.000000 838:59:59.000000 838:59:59 +3020399.900000 838:59:59.900000 838:59:59.9 +3020399.990000 838:59:59.990000 838:59:59.99 +3020399.999000 838:59:59.999000 838:59:59.999 +3020399.999900 838:59:59.999900 838:59:59.9999 +3020399.999990 838:59:59.999990 838:59:59.99999 +3020399.999999 838:59:59.999999 838:59:59.999999 +3020399.999999 838:59:59.999999 838:59:59.9999999 +3020399.999999 838:59:59.999999 839:59:59.9999999 +3020399.999999 838:59:59.999999 87649414:59:59.999999 +3020399.999999 838:59:59.999999 87649414:59:59.9999999 +3020399.999999 838:59:59.999999 87649415:59:59.999999 +3020399.999999 838:59:59.999999 87649415:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Note 1292 Truncated incorrect time value: '837:59:59.9999999' +Warning 1292 Truncated incorrect time value: '838:59:59.9999999' +Warning 1292 Truncated incorrect time value: '838:59:59.9999999' +Warning 1292 Truncated incorrect time value: '839:59:59.9999999' +Warning 1292 Truncated incorrect time value: '839:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649414:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +Warning 1292 Truncated incorrect time value: '87649415:59:59.9999999' +# +# Functions with a single TIME interval input, conversion from TIME-interval-in-DECIMAL +# +SELECT +EXTRACT(DAY FROM a), +EXTRACT(HOUR FROM a), +EXTRACT(MINUTE FROM a), +EXTRACT(SECOND FROM a), +EXTRACT(MICROSECOND FROM a), +CAST(a AS INTERVAL DAY_SECOND(6)), +a +FROM t1_time_in_decimal ORDER BY id; +EXTRACT(DAY FROM a) EXTRACT(HOUR FROM a) EXTRACT(MINUTE FROM a) EXTRACT(SECOND FROM a) EXTRACT(MICROSECOND FROM a) CAST(a AS INTERVAL DAY_SECOND(6)) a +0 0 0 0 0 00:00:00.000000 0.0000000000 +0 0 0 0 900000 00:00:00.900000 0.9000000000 +0 0 0 0 990000 00:00:00.990000 0.9900000000 +0 0 0 0 999000 00:00:00.999000 0.9990000000 +0 0 0 0 999900 00:00:00.999900 0.9999000000 +0 0 0 0 999990 00:00:00.999990 0.9999900000 +0 0 0 0 999999 00:00:00.999999 0.9999990000 +0 0 0 1 0 00:00:01.000000 0.9999999000 +34 22 0 0 0 34 22:00:00.000000 8375959.9999999000 +34 22 59 59 0 34 22:59:59.000000 8385959.0000000000 +34 22 59 59 900000 34 22:59:59.900000 8385959.9000000000 +34 22 59 59 990000 34 22:59:59.990000 8385959.9900000000 +34 22 59 59 999000 34 22:59:59.999000 8385959.9990000000 +34 22 59 59 999900 34 22:59:59.999900 8385959.9999000000 +34 22 59 59 999990 34 22:59:59.999990 8385959.9999900000 +34 22 59 59 999999 34 22:59:59.999999 8385959.9999990000 +34 23 0 0 0 34 23:00:00.000000 8385959.9999999000 +35 0 0 0 0 35 00:00:00.000000 8395959.9999999000 +3652058 22 59 59 999999 3652058 22:59:59.999999 876494145959.9999990000 +3652058 23 0 0 0 3652058 23:00:00.000000 876494145959.9999999000 +3652058 23 59 59 999999 3652058 23:59:59.999999 876494155959.9999990000 +3652058 23 59 59 999999 3652058 23:59:59.999999 876494155959.9999999000 +Warnings: +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.0000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9900000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9990000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9999000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9999900000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9999990000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.9999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8375959.9999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.0000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9900000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9990000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9999000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9999900000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9999990000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.9999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8395959.9999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '876494145959.9999990000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '876494145959.9999999000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '876494155959.9999990000' +Warning 1292 Incorrect time value: '876494155959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 22 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 22 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 22 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 22 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 22 +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '876494155959.9999999000' +SELECT +TIME_TO_SEC(a), +CAST(a AS TIME(6)), +a +FROM t1_time_in_decimal ORDER BY id; +TIME_TO_SEC(a) CAST(a AS TIME(6)) a +0.000000 00:00:00.000000 0.0000000000 +0.900000 00:00:00.900000 0.9000000000 +0.990000 00:00:00.990000 0.9900000000 +0.999000 00:00:00.999000 0.9990000000 +0.999900 00:00:00.999900 0.9999000000 +0.999990 00:00:00.999990 0.9999900000 +0.999999 00:00:00.999999 0.9999990000 +1.000000 00:00:01.000000 0.9999999000 +3016800.000000 838:00:00.000000 8375959.9999999000 +3020399.000000 838:59:59.000000 8385959.0000000000 +3020399.900000 838:59:59.900000 8385959.9000000000 +3020399.990000 838:59:59.990000 8385959.9900000000 +3020399.999000 838:59:59.999000 8385959.9990000000 +3020399.999900 838:59:59.999900 8385959.9999000000 +3020399.999990 838:59:59.999990 8385959.9999900000 +3020399.999999 838:59:59.999999 8385959.9999990000 +3020399.999999 838:59:59.999999 8385959.9999999000 +3020399.999999 838:59:59.999999 8395959.9999999000 +NULL NULL 876494145959.9999990000 +NULL NULL 876494145959.9999999000 +NULL NULL 876494155959.9999990000 +NULL NULL 876494155959.9999999000 +Warnings: +Warning 1292 Incorrect time value: '8385959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 17 +Warning 1292 Incorrect time value: '8385959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 17 +Warning 1292 Incorrect time value: '8395959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 18 +Warning 1292 Incorrect time value: '8395959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 18 +Warning 1292 Incorrect time value: '876494145959.9999990000' for column `test`.`t1_time_in_decimal`.`a` at row 19 +Warning 1292 Incorrect time value: '876494145959.9999990000' for column `test`.`t1_time_in_decimal`.`a` at row 19 +Warning 1292 Incorrect time value: '876494145959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 20 +Warning 1292 Incorrect time value: '876494145959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 20 +Warning 1292 Incorrect time value: '876494155959.9999990000' for column `test`.`t1_time_in_decimal`.`a` at row 21 +Warning 1292 Incorrect time value: '876494155959.9999990000' for column `test`.`t1_time_in_decimal`.`a` at row 21 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 22 +Warning 1292 Incorrect time value: '876494155959.9999999000' for column `test`.`t1_time_in_decimal`.`a` at row 22 +# +# Functions with a single DATE input, conversion from DATETIME-in-VARCHAR +# +SELECT QUARTER(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +QUARTER(a) CAST(a AS DATE) a +4 2000-12-31 2000-12-31 23:59:59 +4 2000-12-31 2000-12-31 23:59:59.9 +4 2000-12-31 2000-12-31 23:59:59.99 +4 2000-12-31 2000-12-31 23:59:59.999 +4 2000-12-31 2000-12-31 23:59:59.9999 +4 2000-12-31 2000-12-31 23:59:59.99999 +4 2000-12-31 2000-12-31 23:59:59.999999 +1 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +DAY(a) CAST(a AS DATE) a +31 2000-12-31 2000-12-31 23:59:59 +31 2000-12-31 2000-12-31 23:59:59.9 +31 2000-12-31 2000-12-31 23:59:59.99 +31 2000-12-31 2000-12-31 23:59:59.999 +31 2000-12-31 2000-12-31 23:59:59.9999 +31 2000-12-31 2000-12-31 23:59:59.99999 +31 2000-12-31 2000-12-31 23:59:59.999999 +1 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT MONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +MONTH(a) CAST(a AS DATE) a +12 2000-12-31 2000-12-31 23:59:59 +12 2000-12-31 2000-12-31 23:59:59.9 +12 2000-12-31 2000-12-31 23:59:59.99 +12 2000-12-31 2000-12-31 23:59:59.999 +12 2000-12-31 2000-12-31 23:59:59.9999 +12 2000-12-31 2000-12-31 23:59:59.99999 +12 2000-12-31 2000-12-31 23:59:59.999999 +1 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT YEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +YEAR(a) CAST(a AS DATE) a +2000 2000-12-31 2000-12-31 23:59:59 +2000 2000-12-31 2000-12-31 23:59:59.9 +2000 2000-12-31 2000-12-31 23:59:59.99 +2000 2000-12-31 2000-12-31 23:59:59.999 +2000 2000-12-31 2000-12-31 23:59:59.9999 +2000 2000-12-31 2000-12-31 23:59:59.99999 +2000 2000-12-31 2000-12-31 23:59:59.999999 +2001 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT DAYNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +DAYNAME(a) CAST(a AS DATE) a +Sunday 2000-12-31 2000-12-31 23:59:59 +Sunday 2000-12-31 2000-12-31 23:59:59.9 +Sunday 2000-12-31 2000-12-31 23:59:59.99 +Sunday 2000-12-31 2000-12-31 23:59:59.999 +Sunday 2000-12-31 2000-12-31 23:59:59.9999 +Sunday 2000-12-31 2000-12-31 23:59:59.99999 +Sunday 2000-12-31 2000-12-31 23:59:59.999999 +Monday 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT MONTHNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +MONTHNAME(a) CAST(a AS DATE) a +December 2000-12-31 2000-12-31 23:59:59 +December 2000-12-31 2000-12-31 23:59:59.9 +December 2000-12-31 2000-12-31 23:59:59.99 +December 2000-12-31 2000-12-31 23:59:59.999 +December 2000-12-31 2000-12-31 23:59:59.9999 +December 2000-12-31 2000-12-31 23:59:59.99999 +December 2000-12-31 2000-12-31 23:59:59.999999 +January 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT LAST_DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +LAST_DAY(a) CAST(a AS DATE) a +2000-12-31 2000-12-31 2000-12-31 23:59:59 +2000-12-31 2000-12-31 2000-12-31 23:59:59.9 +2000-12-31 2000-12-31 2000-12-31 23:59:59.99 +2000-12-31 2000-12-31 2000-12-31 23:59:59.999 +2000-12-31 2000-12-31 2000-12-31 23:59:59.9999 +2000-12-31 2000-12-31 2000-12-31 23:59:59.99999 +2000-12-31 2000-12-31 2000-12-31 23:59:59.999999 +2000-12-31 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT TO_DAYS(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +TO_DAYS(a) CAST(a AS DATE) a +730850 2000-12-31 2000-12-31 23:59:59 +730850 2000-12-31 2000-12-31 23:59:59.9 +730850 2000-12-31 2000-12-31 23:59:59.99 +730850 2000-12-31 2000-12-31 23:59:59.999 +730850 2000-12-31 2000-12-31 23:59:59.9999 +730850 2000-12-31 2000-12-31 23:59:59.99999 +730850 2000-12-31 2000-12-31 23:59:59.999999 +730851 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT DAYOFYEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +DAYOFYEAR(a) CAST(a AS DATE) a +366 2000-12-31 2000-12-31 23:59:59 +366 2000-12-31 2000-12-31 23:59:59.9 +366 2000-12-31 2000-12-31 23:59:59.99 +366 2000-12-31 2000-12-31 23:59:59.999 +366 2000-12-31 2000-12-31 23:59:59.9999 +366 2000-12-31 2000-12-31 23:59:59.99999 +366 2000-12-31 2000-12-31 23:59:59.999999 +1 2000-12-31 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +CREATE TABLE t1 (a VARCHAR(32)); +INSERT INTO t1 VALUES +('2002-01-05 23:59:59'), +('2002-01-05 23:59:59.999999'), +('2002-01-05 23:59:59.9999999'); +SELECT YEARWEEK(a), a FROM t1; +YEARWEEK(a) a +200152 2002-01-05 23:59:59 +200152 2002-01-05 23:59:59.999999 +200201 2002-01-05 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2002-01-05 23:59:59.9999999' +SELECT WEEK(a), a FROM t1; +WEEK(a) a +0 2002-01-05 23:59:59 +0 2002-01-05 23:59:59.999999 +1 2002-01-05 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2002-01-05 23:59:59.9999999' +SELECT WEEKDAY(a), a FROM t1; +WEEKDAY(a) a +5 2002-01-05 23:59:59 +5 2002-01-05 23:59:59.999999 +6 2002-01-05 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2002-01-05 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,9)); +INSERT INTO t1 VALUES +(20020105235959), +(20020105235959.999999), +(20020105235959.9999999); +SELECT YEARWEEK(a), a FROM t1; +YEARWEEK(a) a +200152 20020105235959.000000000 +200152 20020105235959.999999000 +200201 20020105235959.999999900 +SELECT WEEK(a), a FROM t1; +WEEK(a) a +0 20020105235959.000000000 +0 20020105235959.999999000 +1 20020105235959.999999900 +SELECT WEEKDAY(a), a FROM t1; +WEEKDAY(a) a +5 20020105235959.000000000 +5 20020105235959.999999000 +6 20020105235959.999999900 +DROP TABLE t1; +# +# Functions with a single DATE input, conversion from DATETIME-in-DECIMAL +# +SELECT QUARTER(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +QUARTER(a) CAST(a AS DATE) a +4 2000-12-31 20001231235959.0000000000 +4 2000-12-31 20001231235959.9000000000 +4 2000-12-31 20001231235959.9900000000 +4 2000-12-31 20001231235959.9990000000 +4 2000-12-31 20001231235959.9999000000 +4 2000-12-31 20001231235959.9999900000 +4 2000-12-31 20001231235959.9999990000 +1 2000-12-31 20001231235959.9999999000 +SELECT DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +DAY(a) CAST(a AS DATE) a +31 2000-12-31 20001231235959.0000000000 +31 2000-12-31 20001231235959.9000000000 +31 2000-12-31 20001231235959.9900000000 +31 2000-12-31 20001231235959.9990000000 +31 2000-12-31 20001231235959.9999000000 +31 2000-12-31 20001231235959.9999900000 +31 2000-12-31 20001231235959.9999990000 +1 2000-12-31 20001231235959.9999999000 +SELECT MONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +MONTH(a) CAST(a AS DATE) a +12 2000-12-31 20001231235959.0000000000 +12 2000-12-31 20001231235959.9000000000 +12 2000-12-31 20001231235959.9900000000 +12 2000-12-31 20001231235959.9990000000 +12 2000-12-31 20001231235959.9999000000 +12 2000-12-31 20001231235959.9999900000 +12 2000-12-31 20001231235959.9999990000 +1 2000-12-31 20001231235959.9999999000 +SELECT YEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +YEAR(a) CAST(a AS DATE) a +2000 2000-12-31 20001231235959.0000000000 +2000 2000-12-31 20001231235959.9000000000 +2000 2000-12-31 20001231235959.9900000000 +2000 2000-12-31 20001231235959.9990000000 +2000 2000-12-31 20001231235959.9999000000 +2000 2000-12-31 20001231235959.9999900000 +2000 2000-12-31 20001231235959.9999990000 +2001 2000-12-31 20001231235959.9999999000 +SELECT DAYNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +DAYNAME(a) CAST(a AS DATE) a +Sunday 2000-12-31 20001231235959.0000000000 +Sunday 2000-12-31 20001231235959.9000000000 +Sunday 2000-12-31 20001231235959.9900000000 +Sunday 2000-12-31 20001231235959.9990000000 +Sunday 2000-12-31 20001231235959.9999000000 +Sunday 2000-12-31 20001231235959.9999900000 +Sunday 2000-12-31 20001231235959.9999990000 +Monday 2000-12-31 20001231235959.9999999000 +SELECT MONTHNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +MONTHNAME(a) CAST(a AS DATE) a +December 2000-12-31 20001231235959.0000000000 +December 2000-12-31 20001231235959.9000000000 +December 2000-12-31 20001231235959.9900000000 +December 2000-12-31 20001231235959.9990000000 +December 2000-12-31 20001231235959.9999000000 +December 2000-12-31 20001231235959.9999900000 +December 2000-12-31 20001231235959.9999990000 +January 2000-12-31 20001231235959.9999999000 +SELECT YEARWEEK(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +YEARWEEK(a) CAST(a AS DATE) a +200053 2000-12-31 20001231235959.0000000000 +200053 2000-12-31 20001231235959.9000000000 +200053 2000-12-31 20001231235959.9900000000 +200053 2000-12-31 20001231235959.9990000000 +200053 2000-12-31 20001231235959.9999000000 +200053 2000-12-31 20001231235959.9999900000 +200053 2000-12-31 20001231235959.9999990000 +200053 2000-12-31 20001231235959.9999999000 +SELECT LAST_DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +LAST_DAY(a) CAST(a AS DATE) a +2000-12-31 2000-12-31 20001231235959.0000000000 +2000-12-31 2000-12-31 20001231235959.9000000000 +2000-12-31 2000-12-31 20001231235959.9900000000 +2000-12-31 2000-12-31 20001231235959.9990000000 +2000-12-31 2000-12-31 20001231235959.9999000000 +2000-12-31 2000-12-31 20001231235959.9999900000 +2000-12-31 2000-12-31 20001231235959.9999990000 +2000-12-31 2000-12-31 20001231235959.9999999000 +SELECT TO_DAYS(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +TO_DAYS(a) CAST(a AS DATE) a +730850 2000-12-31 20001231235959.0000000000 +730850 2000-12-31 20001231235959.9000000000 +730850 2000-12-31 20001231235959.9900000000 +730850 2000-12-31 20001231235959.9990000000 +730850 2000-12-31 20001231235959.9999000000 +730850 2000-12-31 20001231235959.9999900000 +730850 2000-12-31 20001231235959.9999990000 +730851 2000-12-31 20001231235959.9999999000 +SELECT DAYOFYEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +DAYOFYEAR(a) CAST(a AS DATE) a +366 2000-12-31 20001231235959.0000000000 +366 2000-12-31 20001231235959.9000000000 +366 2000-12-31 20001231235959.9900000000 +366 2000-12-31 20001231235959.9990000000 +366 2000-12-31 20001231235959.9999000000 +366 2000-12-31 20001231235959.9999900000 +366 2000-12-31 20001231235959.9999990000 +1 2000-12-31 20001231235959.9999999000 +SELECT DAYOFMONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +DAYOFMONTH(a) CAST(a AS DATE) a +31 2000-12-31 20001231235959.0000000000 +31 2000-12-31 20001231235959.9000000000 +31 2000-12-31 20001231235959.9900000000 +31 2000-12-31 20001231235959.9990000000 +31 2000-12-31 20001231235959.9999000000 +31 2000-12-31 20001231235959.9999900000 +31 2000-12-31 20001231235959.9999990000 +1 2000-12-31 20001231235959.9999999000 +# +# Functions with a single DATETIME input, conversion from DATETIME-in-VARCHAR +# +SELECT TO_SECONDS(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +TO_SECONDS(a) CAST(a AS DATETIME(6)) a +63145526399 2000-12-31 23:59:59.000000 2000-12-31 23:59:59 +63145526399 2000-12-31 23:59:59.900000 2000-12-31 23:59:59.9 +63145526399 2000-12-31 23:59:59.990000 2000-12-31 23:59:59.99 +63145526399 2000-12-31 23:59:59.999000 2000-12-31 23:59:59.999 +63145526399 2000-12-31 23:59:59.999900 2000-12-31 23:59:59.9999 +63145526399 2000-12-31 23:59:59.999990 2000-12-31 23:59:59.99999 +63145526399 2000-12-31 23:59:59.999999 2000-12-31 23:59:59.999999 +63145526400 2001-01-01 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SET time_zone='+00:00'; +SELECT UNIX_TIMESTAMP(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +UNIX_TIMESTAMP(a) CAST(a AS DATETIME(6)) a +978307199.000000 2000-12-31 23:59:59.000000 2000-12-31 23:59:59 +978307199.900000 2000-12-31 23:59:59.900000 2000-12-31 23:59:59.9 +978307199.990000 2000-12-31 23:59:59.990000 2000-12-31 23:59:59.99 +978307199.999000 2000-12-31 23:59:59.999000 2000-12-31 23:59:59.999 +978307199.999900 2000-12-31 23:59:59.999900 2000-12-31 23:59:59.9999 +978307199.999990 2000-12-31 23:59:59.999990 2000-12-31 23:59:59.99999 +978307199.999999 2000-12-31 23:59:59.999999 2000-12-31 23:59:59.999999 +978307200.000000 2001-01-01 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SET time_zone=DEFAULT; +SELECT CONVERT_TZ(a, '+00:00','+00:00'), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +CONVERT_TZ(a, '+00:00','+00:00') CAST(a AS DATETIME(6)) a +2000-12-31 23:59:59.000000 2000-12-31 23:59:59.000000 2000-12-31 23:59:59 +2000-12-31 23:59:59.900000 2000-12-31 23:59:59.900000 2000-12-31 23:59:59.9 +2000-12-31 23:59:59.990000 2000-12-31 23:59:59.990000 2000-12-31 23:59:59.99 +2000-12-31 23:59:59.999000 2000-12-31 23:59:59.999000 2000-12-31 23:59:59.999 +2000-12-31 23:59:59.999900 2000-12-31 23:59:59.999900 2000-12-31 23:59:59.9999 +2000-12-31 23:59:59.999990 2000-12-31 23:59:59.999990 2000-12-31 23:59:59.99999 +2000-12-31 23:59:59.999999 2000-12-31 23:59:59.999999 2000-12-31 23:59:59.999999 +2001-01-01 00:00:00.000000 2001-01-01 00:00:00.000000 2000-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +# +# Functions with a single DATETIME input, conversion from DATETIME-in-DECIMAL +# +SELECT TO_SECONDS(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +TO_SECONDS(a) CAST(a AS DATETIME(6)) a +63145526399 2000-12-31 23:59:59.000000 20001231235959.0000000000 +63145526399 2000-12-31 23:59:59.900000 20001231235959.9000000000 +63145526399 2000-12-31 23:59:59.990000 20001231235959.9900000000 +63145526399 2000-12-31 23:59:59.999000 20001231235959.9990000000 +63145526399 2000-12-31 23:59:59.999900 20001231235959.9999000000 +63145526399 2000-12-31 23:59:59.999990 20001231235959.9999900000 +63145526399 2000-12-31 23:59:59.999999 20001231235959.9999990000 +63145526400 2001-01-01 00:00:00.000000 20001231235959.9999999000 +SET time_zone='+00:00'; +SELECT UNIX_TIMESTAMP(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +UNIX_TIMESTAMP(a) CAST(a AS DATETIME(6)) a +978307199.000000 2000-12-31 23:59:59.000000 20001231235959.0000000000 +978307199.900000 2000-12-31 23:59:59.900000 20001231235959.9000000000 +978307199.990000 2000-12-31 23:59:59.990000 20001231235959.9900000000 +978307199.999000 2000-12-31 23:59:59.999000 20001231235959.9990000000 +978307199.999900 2000-12-31 23:59:59.999900 20001231235959.9999000000 +978307199.999990 2000-12-31 23:59:59.999990 20001231235959.9999900000 +978307199.999999 2000-12-31 23:59:59.999999 20001231235959.9999990000 +978307200.000000 2001-01-01 00:00:00.000000 20001231235959.9999999000 +SET time_zone=DEFAULT; +SELECT CONVERT_TZ(a, '+00:00','+00:00'), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +CONVERT_TZ(a, '+00:00','+00:00') CAST(a AS DATETIME(6)) a +2000-12-31 23:59:59.000000 2000-12-31 23:59:59.000000 20001231235959.0000000000 +2000-12-31 23:59:59.900000 2000-12-31 23:59:59.900000 20001231235959.9000000000 +2000-12-31 23:59:59.990000 2000-12-31 23:59:59.990000 20001231235959.9900000000 +2000-12-31 23:59:59.999000 2000-12-31 23:59:59.999000 20001231235959.9990000000 +2000-12-31 23:59:59.999900 2000-12-31 23:59:59.999900 20001231235959.9999000000 +2000-12-31 23:59:59.999990 2000-12-31 23:59:59.999990 20001231235959.9999900000 +2000-12-31 23:59:59.999999 2000-12-31 23:59:59.999999 20001231235959.9999990000 +2001-01-01 00:00:00.000000 2001-01-01 00:00:00.000000 20001231235959.9999999000 +DROP TABLE t1_datetime_in_varchar; +DROP TABLE t1_datetime_in_decimal; +DROP TABLE t1_time_in_varchar; +DROP TABLE t1_time_in_decimal; +# +# Functions that construct DATETIME +# +SET time_zone='+00:00'; +CREATE TABLE t1_unix_timestamp (id SERIAL, a DECIMAL(30,10)); +INSERT INTO t1_unix_timestamp (a) VALUES +(980639999), +(980639999.9), +(980639999.999999), +(980639999.9999999), +(2147483647), +(2147483647.9), +(2147483647.999999), +(2147483647.9999999); +SELECT a, FROM_UNIXTIME(a) FROM t1_unix_timestamp ORDER BY id; +a FROM_UNIXTIME(a) +980639999.0000000000 2001-01-27 23:59:59.000000 +980639999.9000000000 2001-01-27 23:59:59.900000 +980639999.9999990000 2001-01-27 23:59:59.999999 +980639999.9999999000 2001-01-28 00:00:00.000000 +2147483647.0000000000 2038-01-19 03:14:07.000000 +2147483647.9000000000 2038-01-19 03:14:07.900000 +2147483647.9999990000 2038-01-19 03:14:07.999999 +2147483647.9999999000 NULL +DROP TABLE t1_unix_timestamp; +SET time_zone=DEFAULT; +# +# Functions that construct TIME +# +CREATE TABLE t1_sec (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_sec (a) VALUES +(59), +(59.9), +(59.999999), +(59.9999999), +(3020398), +(3020398.999999), +(3020398.9999999), +(3020399), +(3020399.999999), +(3020399.9999999), +(9223372036854775807), +(9223372036854775807.9), +(9223372036854775807.999999), +(9223372036854775807.9999999), +(18446744073709551615), +(18446744073709551615.9), +(18446744073709551615.999999), +(18446744073709551615.9999999); +SELECT a, SEC_TO_TIME(a) FROM t1_sec ORDER BY id; +a SEC_TO_TIME(a) +59.0000000000 00:00:59.000000 +59.9000000000 00:00:59.900000 +59.9999990000 00:00:59.999999 +59.9999999000 00:01:00.000000 +3020398.0000000000 838:59:58.000000 +3020398.9999990000 838:59:58.999999 +3020398.9999999000 838:59:59.000000 +3020399.0000000000 838:59:59.000000 +3020399.9999990000 838:59:59.999999 +3020399.9999999000 838:59:59.999999 +9223372036854775807.0000000000 838:59:59.999999 +9223372036854775807.9000000000 838:59:59.999999 +9223372036854775807.9999990000 838:59:59.999999 +9223372036854775807.9999999000 838:59:59.999999 +18446744073709551615.0000000000 838:59:59.999999 +18446744073709551615.9000000000 838:59:59.999999 +18446744073709551615.9999990000 838:59:59.999999 +18446744073709551615.9999999000 838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect seconds value: '3020400' +Warning 1292 Truncated incorrect seconds value: '9223372036854775807.0000000000' +Warning 1292 Truncated incorrect seconds value: '9223372036854775807.9000000000' +Warning 1292 Truncated incorrect seconds value: '9223372036854775807.9999990000' +Warning 1292 Truncated incorrect seconds value: '9223372036854775807.9999999000' +Warning 1292 Truncated incorrect seconds value: '18446744073709551615.0000000000' +Warning 1292 Truncated incorrect seconds value: '18446744073709551615.9000000000' +Warning 1292 Truncated incorrect seconds value: '18446744073709551615.9999990000' +Warning 1292 Truncated incorrect seconds value: '18446744073709551615.9999999000' +DROP TABLE t1_sec; +CREATE TABLE t1_sec (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_sec (a) VALUES +(0), +(0.9), +(0.999999), +(0.9999999); +SELECT a, MAKETIME(0, 0, a) FROM t1_sec ORDER BY id; +a MAKETIME(0, 0, a) +0.0000000000 00:00:00.000000 +0.9000000000 00:00:00.900000 +0.9999990000 00:00:00.999999 +0.9999999000 00:00:01.000000 +DROP TABLE t1_sec; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +SELECT +'----', +a, +DATE_FORMAT(a, '%Y') AS yyyy, +DATE_FORMAT(a, '%Y-%m-%d') AS d, +DATE_FORMAT(a, '%H:%i:%s') AS t0, +DATE_FORMAT(a, '%H:%i:%s.%f') AS t6, +DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s') AS dt0, +DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s.%f') AS dt6 +FROM t1; +---- ---- +a 2017-12-31 23:59:59 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.000000 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.000000 +---- ---- +a 2017-12-31 23:59:59.9 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.900000 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.900000 +---- ---- +a 2017-12-31 23:59:59.999999 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.999999 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.999999 +---- ---- +a 2017-12-31 23:59:59.9999999 +yyyy 2018 +d 2018-01-01 +t0 00:00:00 +t6 00:00:00.000000 +dt0 2018-01-01 00:00:00 +dt6 2018-01-01 00:00:00.000000 +Warnings: +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Level Note +Code 1292 +Message Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,9)); +INSERT INTO t1 VALUES +(20171231235959), +(20171231235959.9), +(20171231235959.999999), +(20171231235959.9999999); +SELECT +'----', +a, +DATE_FORMAT(a, '%Y') AS yyyy, +DATE_FORMAT(a, '%Y-%m-%d') AS d, +DATE_FORMAT(a, '%H:%i:%s') AS t0, +DATE_FORMAT(a, '%H:%i:%s.%f') AS t6, +DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s') AS dt0, +DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s.%f') AS dt6 +FROM t1; +---- ---- +a 20171231235959.000000000 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.000000 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.000000 +---- ---- +a 20171231235959.900000000 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.900000 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.900000 +---- ---- +a 20171231235959.999999000 +yyyy 2017 +d 2017-12-31 +t0 23:59:59 +t6 23:59:59.999999 +dt0 2017-12-31 23:59:59 +dt6 2017-12-31 23:59:59.999999 +---- ---- +a 20171231235959.999999900 +yyyy 2018 +d 2018-01-01 +t0 00:00:00 +t6 00:00:00.000000 +dt0 2018-01-01 00:00:00 +dt6 2018-01-01 00:00:00.000000 +DROP TABLE t1; +# +# Functions with two temporal parameters that round nanoseconds in both parameters in MySQL +# +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); +SELECT TIMESTAMP(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +TIMESTAMP(t1.a, t2.a) a a +2017-12-31 23:59:59.000000 2017-12-31 23:59:59 00:00:00 +2017-12-31 23:59:59.900000 2017-12-31 23:59:59 00:00:00.9 +2017-12-31 23:59:59.999999 2017-12-31 23:59:59 00:00:00.999999 +2018-01-01 00:00:00.000000 2017-12-31 23:59:59 00:00:00.9999999 +2017-12-31 23:59:59.900000 2017-12-31 23:59:59.9 00:00:00 +2018-01-01 00:00:00.800000 2017-12-31 23:59:59.9 00:00:00.9 +2018-01-01 00:00:00.899999 2017-12-31 23:59:59.9 00:00:00.999999 +2018-01-01 00:00:00.900000 2017-12-31 23:59:59.9 00:00:00.9999999 +2017-12-31 23:59:59.999999 2017-12-31 23:59:59.999999 00:00:00 +2018-01-01 00:00:00.899999 2017-12-31 23:59:59.999999 00:00:00.9 +2018-01-01 00:00:00.999998 2017-12-31 23:59:59.999999 00:00:00.999999 +2018-01-01 00:00:00.999999 2017-12-31 23:59:59.999999 00:00:00.9999999 +2018-01-01 00:00:00.000000 2017-12-31 23:59:59.9999999 00:00:00 +2018-01-01 00:00:00.900000 2017-12-31 23:59:59.9999999 00:00:00.9 +2018-01-01 00:00:00.999999 2017-12-31 23:59:59.9999999 00:00:00.999999 +2018-01-01 00:00:01.000000 2017-12-31 23:59:59.9999999 00:00:00.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +SELECT ADDTIME(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +ADDTIME(t1.a, t2.a) a a +2017-12-31 23:59:59 2017-12-31 23:59:59 00:00:00 +2017-12-31 23:59:59.900000 2017-12-31 23:59:59 00:00:00.9 +2017-12-31 23:59:59.999999 2017-12-31 23:59:59 00:00:00.999999 +2018-01-01 00:00:00 2017-12-31 23:59:59 00:00:00.9999999 +2017-12-31 23:59:59.900000 2017-12-31 23:59:59.9 00:00:00 +2018-01-01 00:00:00.800000 2017-12-31 23:59:59.9 00:00:00.9 +2018-01-01 00:00:00.899999 2017-12-31 23:59:59.9 00:00:00.999999 +2018-01-01 00:00:00.900000 2017-12-31 23:59:59.9 00:00:00.9999999 +2017-12-31 23:59:59.999999 2017-12-31 23:59:59.999999 00:00:00 +2018-01-01 00:00:00.899999 2017-12-31 23:59:59.999999 00:00:00.9 +2018-01-01 00:00:00.999998 2017-12-31 23:59:59.999999 00:00:00.999999 +2018-01-01 00:00:00.999999 2017-12-31 23:59:59.999999 00:00:00.9999999 +2018-01-01 00:00:00 2017-12-31 23:59:59.9999999 00:00:00 +2018-01-01 00:00:00.900000 2017-12-31 23:59:59.9999999 00:00:00.9 +2018-01-01 00:00:00.999999 2017-12-31 23:59:59.9999999 00:00:00.999999 +2018-01-01 00:00:01 2017-12-31 23:59:59.9999999 00:00:00.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '00:00:00.9999999' +DROP TABLE t1, t2; +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('23:59:59'), +('23:59:59.9'), +('23:59:59.999999'), +('23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); +SELECT TIMEDIFF(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +TIMEDIFF(t1.a, t2.a) a a +23:59:59.000000 23:59:59 00:00:00 +23:59:58.100000 23:59:59 00:00:00.9 +23:59:58.000001 23:59:59 00:00:00.999999 +23:59:58.000000 23:59:59 00:00:00.9999999 +23:59:59.900000 23:59:59.9 00:00:00 +23:59:59.000000 23:59:59.9 00:00:00.9 +23:59:58.900001 23:59:59.9 00:00:00.999999 +23:59:58.900000 23:59:59.9 00:00:00.9999999 +23:59:59.999999 23:59:59.999999 00:00:00 +23:59:59.099999 23:59:59.999999 00:00:00.9 +23:59:59.000000 23:59:59.999999 00:00:00.999999 +23:59:58.999999 23:59:59.999999 00:00:00.9999999 +24:00:00.000000 23:59:59.9999999 00:00:00 +23:59:59.100000 23:59:59.9999999 00:00:00.9 +23:59:59.000001 23:59:59.9999999 00:00:00.999999 +23:59:59.000000 23:59:59.9999999 00:00:00.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +DROP TABLE t1, t2; +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2001-12-31 23:59:59'), +('2001-12-31 23:59:59.9'), +('2001-12-31 23:59:59.999999'), +('2001-12-31 23:59:59.9999999'); +INSERT INTO t2 VALUES +('2001-12-31 23:59:59'), +('2001-12-31 23:59:59.9'), +('2001-12-31 23:59:59.999999'), +('2001-12-31 23:59:59.9999999'); +SELECT TIMESTAMPDIFF(MICROSECOND,t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +TIMESTAMPDIFF(MICROSECOND,t1.a, t2.a) a a +0 2001-12-31 23:59:59 2001-12-31 23:59:59 +900000 2001-12-31 23:59:59 2001-12-31 23:59:59.9 +999999 2001-12-31 23:59:59 2001-12-31 23:59:59.999999 +1000000 2001-12-31 23:59:59 2001-12-31 23:59:59.9999999 +-900000 2001-12-31 23:59:59.9 2001-12-31 23:59:59 +0 2001-12-31 23:59:59.9 2001-12-31 23:59:59.9 +99999 2001-12-31 23:59:59.9 2001-12-31 23:59:59.999999 +100000 2001-12-31 23:59:59.9 2001-12-31 23:59:59.9999999 +-999999 2001-12-31 23:59:59.999999 2001-12-31 23:59:59 +-99999 2001-12-31 23:59:59.999999 2001-12-31 23:59:59.9 +0 2001-12-31 23:59:59.999999 2001-12-31 23:59:59.999999 +1 2001-12-31 23:59:59.999999 2001-12-31 23:59:59.9999999 +-1000000 2001-12-31 23:59:59.9999999 2001-12-31 23:59:59 +-100000 2001-12-31 23:59:59.9999999 2001-12-31 23:59:59.9 +-1 2001-12-31 23:59:59.9999999 2001-12-31 23:59:59.999999 +0 2001-12-31 23:59:59.9999999 2001-12-31 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-12-31 23:59:59.9999999' +DROP TABLE t1, t2; +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('23:59:59'), +('23:59:59.9'), +('23:59:59.999999'), +('23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); +SELECT TIMEDIFF(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +TIMEDIFF(t1.a, t2.a) a a +23:59:59.000000 23:59:59 00:00:00 +23:59:58.100000 23:59:59 00:00:00.9 +23:59:58.000001 23:59:59 00:00:00.999999 +23:59:58.000000 23:59:59 00:00:00.9999999 +23:59:59.900000 23:59:59.9 00:00:00 +23:59:59.000000 23:59:59.9 00:00:00.9 +23:59:58.900001 23:59:59.9 00:00:00.999999 +23:59:58.900000 23:59:59.9 00:00:00.9999999 +23:59:59.999999 23:59:59.999999 00:00:00 +23:59:59.099999 23:59:59.999999 00:00:00.9 +23:59:59.000000 23:59:59.999999 00:00:00.999999 +23:59:58.999999 23:59:59.999999 00:00:00.9999999 +24:00:00.000000 23:59:59.9999999 00:00:00 +23:59:59.100000 23:59:59.9999999 00:00:00.9 +23:59:59.000001 23:59:59.9999999 00:00:00.999999 +23:59:59.000000 23:59:59.9999999 00:00:00.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +Note 1292 Truncated incorrect time value: '23:59:59.9999999' +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +DROP TABLE t1, t2; +# +# STR_TO_DATE behaviour is questionable in MySQL 5.6 (MySQL Bug #92474) +# +# It truncates nanoseconds, but this may change in the future. +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +SELECT +a, +STR_TO_DATE(a, '%Y-%m-%d %H:%i:%s') AS c0, +STR_TO_DATE(a, '%Y-%m-%d %H:%i:%s.%f') AS c6 +FROM t1; +a c0 c6 +2017-12-31 23:59:59 2017-12-31 23:59:59 2017-12-31 23:59:59.000000 +2017-12-31 23:59:59.9 2017-12-31 23:59:59 2017-12-31 23:59:59.900000 +2017-12-31 23:59:59.999999 2017-12-31 23:59:59 2017-12-31 23:59:59.999999 +2017-12-31 23:59:59.9999999 2017-12-31 23:59:59 2017-12-31 23:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9' +Warning 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.999999' +Warning 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Warning 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +DROP TABLE t1; +# +# DATE_ADD behaviour is questionable in MySQL 5.6 (MySQL Bug#92473) +# It rounds nanoseconds in the first argument, but truncates nanoseconds in the second argument. +# This may change in the future, to round both arguments. +# +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +CREATE TABLE t2 (b DECIMAL(32,9)); +INSERT INTO t2 VALUES +(0), +(0.9), +(0.999999), +(0.9999999); +SELECT a, b, DATE_ADD(a, INTERVAL b SECOND) FROM t1,t2 ORDER BY a,b; +a b DATE_ADD(a, INTERVAL b SECOND) +2017-12-31 23:59:59 0.000000000 2017-12-31 23:59:59.000000 +2017-12-31 23:59:59 0.900000000 2017-12-31 23:59:59.900000 +2017-12-31 23:59:59 0.999999000 2017-12-31 23:59:59.999999 +2017-12-31 23:59:59 0.999999900 2017-12-31 23:59:59.999999 +2017-12-31 23:59:59.9 0.000000000 2017-12-31 23:59:59.900000 +2017-12-31 23:59:59.9 0.900000000 2018-01-01 00:00:00.800000 +2017-12-31 23:59:59.9 0.999999000 2018-01-01 00:00:00.899999 +2017-12-31 23:59:59.9 0.999999900 2018-01-01 00:00:00.899999 +2017-12-31 23:59:59.999999 0.000000000 2017-12-31 23:59:59.999999 +2017-12-31 23:59:59.999999 0.900000000 2018-01-01 00:00:00.899999 +2017-12-31 23:59:59.999999 0.999999000 2018-01-01 00:00:00.999998 +2017-12-31 23:59:59.999999 0.999999900 2018-01-01 00:00:00.999998 +2017-12-31 23:59:59.9999999 0.000000000 2018-01-01 00:00:00.000000 +2017-12-31 23:59:59.9999999 0.900000000 2018-01-01 00:00:00.900000 +2017-12-31 23:59:59.9999999 0.999999000 2018-01-01 00:00:00.999999 +2017-12-31 23:59:59.9999999 0.999999900 2018-01-01 00:00:00.999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2017-12-31 23:59:59.9999999' +DROP TABLE t1, t2; diff --git a/mysql-test/main/func_time_round.test b/mysql-test/main/func_time_round.test new file mode 100644 index 00000000000..12d3a50a10f --- /dev/null +++ b/mysql-test/main/func_time_round.test @@ -0,0 +1,461 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; + +CREATE TABLE t1_datetime_in_varchar (id SERIAL, a VARCHAR(64)); +INSERT INTO t1_datetime_in_varchar (a) VALUES +('2000-12-31 23:59:59'), +('2000-12-31 23:59:59.9'), +('2000-12-31 23:59:59.99'), +('2000-12-31 23:59:59.999'), +('2000-12-31 23:59:59.9999'), +('2000-12-31 23:59:59.99999'), +('2000-12-31 23:59:59.999999'), +('2000-12-31 23:59:59.9999999'); + +CREATE TABLE t1_datetime_in_decimal (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_datetime_in_decimal (a) VALUES +(20001231235959), +(20001231235959.9), +(20001231235959.99), +(20001231235959.999), +(20001231235959.9999), +(20001231235959.99999), +(20001231235959.999999), +(20001231235959.9999999); + + +CREATE TABLE t1_time_in_varchar (id SERIAL, a VARCHAR(64)); +INSERT INTO t1_time_in_varchar (a) VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.99'), +('00:00:00.999'), +('00:00:00.9999'), +('00:00:00.99999'), +('00:00:00.999999'), +('00:00:00.9999999'); +INSERT INTO t1_time_in_varchar (a) VALUES +('837:59:59.9999999'), +('838:59:59'), +('838:59:59.9'), +('838:59:59.99'), +('838:59:59.999'), +('838:59:59.9999'), +('838:59:59.99999'), +('838:59:59.999999'), +('838:59:59.9999999'), +('839:59:59.9999999'), +('87649414:59:59.999999'), +('87649414:59:59.9999999'), +('87649415:59:59.999999'), +('87649415:59:59.9999999'); + + +CREATE TABLE t1_time_in_decimal (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_time_in_decimal (a) VALUES +(0), +(0.9), +(0.99), +(0.999), +(0.9999), +(0.99999), +(0.999999), +(0.9999999); +INSERT INTO t1_time_in_decimal (a) VALUES +(8375959.9999999), +(8385959), +(8385959.9), +(8385959.99), +(8385959.999), +(8385959.9999), +(8385959.99999), +(8385959.999999), +(8385959.9999999), +(8395959.9999999), +(876494145959.999999), +(876494145959.9999999), +(876494155959.999999), +(876494155959.9999999); + +--echo # +--echo # TIME: LEAST/GREATEST +--echo # + +SELECT GREATEST(TIME'00:00:00', a) FROM t1_time_in_varchar; +SELECT GREATEST(TIME'00:00:00', a) FROM t1_time_in_decimal; + +SELECT GREATEST(TIME'00:00:00', '00:00:00.0000004'); +SELECT GREATEST(TIME'00:00:00', 0.0000004); + +SELECT GREATEST(TIME'00:00:00', '00:00:00.0000005'); +SELECT GREATEST(TIME'00:00:00', 0.0000005); + + +--echo # +--echo # Functions with a single TIME input, conversion from DATETIME-in-VARCHAR +--echo # + +SELECT SECOND(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT MINUTE(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT HOUR(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; + +SELECT EXTRACT(SECOND FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT EXTRACT(MINUTE FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT EXTRACT(HOUR FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; + +SELECT TIME_TO_SEC(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; + + +--echo # +--echo # Functions with a single TIME input, conversion from DATETIME-in-DECIMAL +--echo # + + +SELECT SECOND(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT MINUTE(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT HOUR(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; + +SELECT EXTRACT(SECOND FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT EXTRACT(MINUTE FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT EXTRACT(HOUR FROM a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; + +SELECT TIME_TO_SEC(a), CAST(a AS TIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; + + +--echo # +--echo # Functions with a single TIME interval input, conversion from TIME-interval-in-VARCHAR +--echo # + +SELECT + EXTRACT(DAY FROM a), + EXTRACT(HOUR FROM a), + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a), + CAST(a AS INTERVAL DAY_SECOND(6)), + a +FROM t1_time_in_varchar ORDER BY id; + +SELECT + TIME_TO_SEC(a), + CAST(a AS TIME(6)), + a +FROM t1_time_in_varchar ORDER BY id; + +--echo # +--echo # Functions with a single TIME interval input, conversion from TIME-interval-in-DECIMAL +--echo # + +SELECT + EXTRACT(DAY FROM a), + EXTRACT(HOUR FROM a), + EXTRACT(MINUTE FROM a), + EXTRACT(SECOND FROM a), + EXTRACT(MICROSECOND FROM a), + CAST(a AS INTERVAL DAY_SECOND(6)), + a +FROM t1_time_in_decimal ORDER BY id; + +SELECT + TIME_TO_SEC(a), + CAST(a AS TIME(6)), + a +FROM t1_time_in_decimal ORDER BY id; + + +--echo # +--echo # Functions with a single DATE input, conversion from DATETIME-in-VARCHAR +--echo # + +SELECT QUARTER(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT MONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT YEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; + +SELECT DAYNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT MONTHNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; + +SELECT LAST_DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT TO_DAYS(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; +SELECT DAYOFYEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_varchar ORDER BY id; + + +CREATE TABLE t1 (a VARCHAR(32)); +INSERT INTO t1 VALUES +('2002-01-05 23:59:59'), +('2002-01-05 23:59:59.999999'), +('2002-01-05 23:59:59.9999999'); +SELECT YEARWEEK(a), a FROM t1; +SELECT WEEK(a), a FROM t1; +SELECT WEEKDAY(a), a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(32,9)); +INSERT INTO t1 VALUES +(20020105235959), +(20020105235959.999999), +(20020105235959.9999999); +SELECT YEARWEEK(a), a FROM t1; +SELECT WEEK(a), a FROM t1; +SELECT WEEKDAY(a), a FROM t1; +DROP TABLE t1; + +--echo # +--echo # Functions with a single DATE input, conversion from DATETIME-in-DECIMAL +--echo # + +SELECT QUARTER(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT MONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT YEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; + +SELECT DAYNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT MONTHNAME(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT YEARWEEK(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; + +SELECT LAST_DAY(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT TO_DAYS(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT DAYOFYEAR(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; +SELECT DAYOFMONTH(a), CAST(a AS DATE), a FROM t1_datetime_in_decimal ORDER BY id; + + +--echo # +--echo # Functions with a single DATETIME input, conversion from DATETIME-in-VARCHAR +--echo # + +SELECT TO_SECONDS(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; + +SET time_zone='+00:00'; +SELECT UNIX_TIMESTAMP(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; +SET time_zone=DEFAULT; + +SELECT CONVERT_TZ(a, '+00:00','+00:00'), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_varchar ORDER BY id; + + +--echo # +--echo # Functions with a single DATETIME input, conversion from DATETIME-in-DECIMAL +--echo # + +SELECT TO_SECONDS(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; + +SET time_zone='+00:00'; +SELECT UNIX_TIMESTAMP(a), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; +SET time_zone=DEFAULT; + +SELECT CONVERT_TZ(a, '+00:00','+00:00'), CAST(a AS DATETIME(6)), a FROM t1_datetime_in_decimal ORDER BY id; + +DROP TABLE t1_datetime_in_varchar; +DROP TABLE t1_datetime_in_decimal; +DROP TABLE t1_time_in_varchar; +DROP TABLE t1_time_in_decimal; + + +--echo # +--echo # Functions that construct DATETIME +--echo # + +SET time_zone='+00:00'; +CREATE TABLE t1_unix_timestamp (id SERIAL, a DECIMAL(30,10)); +INSERT INTO t1_unix_timestamp (a) VALUES +(980639999), +(980639999.9), +(980639999.999999), +(980639999.9999999), +(2147483647), +(2147483647.9), +(2147483647.999999), +(2147483647.9999999); +SELECT a, FROM_UNIXTIME(a) FROM t1_unix_timestamp ORDER BY id; +DROP TABLE t1_unix_timestamp; +SET time_zone=DEFAULT; + + +--echo # +--echo # Functions that construct TIME +--echo # + +CREATE TABLE t1_sec (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_sec (a) VALUES +(59), +(59.9), +(59.999999), +(59.9999999), +(3020398), +(3020398.999999), +(3020398.9999999), +(3020399), +(3020399.999999), +(3020399.9999999), +(9223372036854775807), +(9223372036854775807.9), +(9223372036854775807.999999), +(9223372036854775807.9999999), +(18446744073709551615), +(18446744073709551615.9), +(18446744073709551615.999999), +(18446744073709551615.9999999); +SELECT a, SEC_TO_TIME(a) FROM t1_sec ORDER BY id; +DROP TABLE t1_sec; + + +CREATE TABLE t1_sec (id SERIAL, a DECIMAL(38,10)); +INSERT INTO t1_sec (a) VALUES +(0), +(0.9), +(0.999999), +(0.9999999); +SELECT a, MAKETIME(0, 0, a) FROM t1_sec ORDER BY id; +DROP TABLE t1_sec; + + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +--vertical_results +SELECT + '----', + a, + DATE_FORMAT(a, '%Y') AS yyyy, + DATE_FORMAT(a, '%Y-%m-%d') AS d, + DATE_FORMAT(a, '%H:%i:%s') AS t0, + DATE_FORMAT(a, '%H:%i:%s.%f') AS t6, + DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s') AS dt0, + DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s.%f') AS dt6 +FROM t1; +--horizontal_results +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(32,9)); +INSERT INTO t1 VALUES +(20171231235959), +(20171231235959.9), +(20171231235959.999999), +(20171231235959.9999999); +--vertical_results +SELECT + '----', + a, + DATE_FORMAT(a, '%Y') AS yyyy, + DATE_FORMAT(a, '%Y-%m-%d') AS d, + DATE_FORMAT(a, '%H:%i:%s') AS t0, + DATE_FORMAT(a, '%H:%i:%s.%f') AS t6, + DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s') AS dt0, + DATE_FORMAT(a, '%Y-%m-%d %H:%i:%s.%f') AS dt6 +FROM t1; +--horizontal_results +DROP TABLE t1; + + +--echo # +--echo # Functions with two temporal parameters that round nanoseconds in both parameters in MySQL +--echo # + +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); + +SELECT TIMESTAMP(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +SELECT ADDTIME(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; + +DROP TABLE t1, t2; + + +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('23:59:59'), +('23:59:59.9'), +('23:59:59.999999'), +('23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); +SELECT TIMEDIFF(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +DROP TABLE t1, t2; + + +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2001-12-31 23:59:59'), +('2001-12-31 23:59:59.9'), +('2001-12-31 23:59:59.999999'), +('2001-12-31 23:59:59.9999999'); +INSERT INTO t2 VALUES +('2001-12-31 23:59:59'), +('2001-12-31 23:59:59.9'), +('2001-12-31 23:59:59.999999'), +('2001-12-31 23:59:59.9999999'); +SELECT TIMESTAMPDIFF(MICROSECOND,t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +DROP TABLE t1, t2; + +CREATE TABLE t1 (a VARCHAR(64)); +CREATE TABLE t2 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('23:59:59'), +('23:59:59.9'), +('23:59:59.999999'), +('23:59:59.9999999'); +INSERT INTO t2 VALUES +('00:00:00'), +('00:00:00.9'), +('00:00:00.999999'), +('00:00:00.9999999'); +SELECT TIMEDIFF(t1.a, t2.a), t1.a, t2.a FROM t1,t2 ORDER BY t1.a, t2.a; +DROP TABLE t1, t2; + + +--echo # +--echo # STR_TO_DATE behaviour is questionable in MySQL 5.6 (MySQL Bug #92474) +--echo # + +--echo # It truncates nanoseconds, but this may change in the future. +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); + +SELECT + a, + STR_TO_DATE(a, '%Y-%m-%d %H:%i:%s') AS c0, + STR_TO_DATE(a, '%Y-%m-%d %H:%i:%s.%f') AS c6 +FROM t1; +DROP TABLE t1; + + +--echo # +--echo # DATE_ADD behaviour is questionable in MySQL 5.6 (MySQL Bug#92473) +--echo # It rounds nanoseconds in the first argument, but truncates nanoseconds in the second argument. +--echo # This may change in the future, to round both arguments. +--echo # + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES +('2017-12-31 23:59:59'), +('2017-12-31 23:59:59.9'), +('2017-12-31 23:59:59.999999'), +('2017-12-31 23:59:59.9999999'); +CREATE TABLE t2 (b DECIMAL(32,9)); +INSERT INTO t2 VALUES +(0), +(0.9), +(0.999999), +(0.9999999); +SELECT a, b, DATE_ADD(a, INTERVAL b SECOND) FROM t1,t2 ORDER BY a,b; +DROP TABLE t1, t2; diff --git a/mysql-test/main/get_diagnostics.result b/mysql-test/main/get_diagnostics.result index 732be7c0283..6944103c805 100644 --- a/mysql-test/main/get_diagnostics.result +++ b/mysql-test/main/get_diagnostics.result @@ -133,7 +133,7 @@ DROP PROCEDURE p1; GET DIAGNOSTICS CONDITION; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 GET DIAGNOSTICS CONDITION a; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 +ERROR 42S22: Unknown column 'a' in 'field list' GET DIAGNOSTICS CONDITION 1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 GET DIAGNOSTICS CONDITION 1 @var; @@ -212,9 +212,9 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp GET DIAGNOSTICS CONDITION (1) @var = CLASS_ORIGIN; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(1) @var = CLASS_ORIGIN' at line 1 GET DIAGNOSTICS CONDITION p1() @var = CLASS_ORIGIN; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '() @var = CLASS_ORIGIN' at line 1 +ERROR 42S22: Unknown column 'p1' in 'field list' GET DIAGNOSTICS CONDITION ABS(2) @var = CLASS_ORIGIN; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(2) @var = CLASS_ORIGIN' at line 1 +ERROR 42S22: Unknown column 'ABS' in 'field list' GET DIAGNOSTICS CONDITION 1.1 @var = CLASS_ORIGIN; GET DIAGNOSTICS CONDITION "1" @var = CLASS_ORIGIN; SELECT COUNT(max_questions) INTO @var FROM mysql.user; @@ -226,10 +226,7 @@ Warnings: Error 1758 Invalid condition number Error 1758 Invalid condition number GET DIAGNOSTICS CONDITION a @var = CLASS_ORIGIN; -Warnings: -Error 1758 Invalid condition number -Error 1758 Invalid condition number -Error 1054 Unknown column 'a' in 'field list' +ERROR 42S22: Unknown column 'a' in 'field list' SELECT COUNT(max_questions) INTO @var FROM mysql.user; SET @cond = 1; GET DIAGNOSTICS CONDITION @cond @var1 = CLASS_ORIGIN; diff --git a/mysql-test/main/get_diagnostics.test b/mysql-test/main/get_diagnostics.test index a30bad72136..1553eb500b7 100644 --- a/mysql-test/main/get_diagnostics.test +++ b/mysql-test/main/get_diagnostics.test @@ -169,7 +169,7 @@ DROP PROCEDURE p1; --error ER_PARSE_ERROR GET DIAGNOSTICS CONDITION; ---error ER_PARSE_ERROR +--error ER_BAD_FIELD_ERROR GET DIAGNOSTICS CONDITION a; --error ER_PARSE_ERROR GET DIAGNOSTICS CONDITION 1; @@ -271,9 +271,9 @@ GET DIAGNOSTICS CONDITION 1+1 @var = CLASS_ORIGIN; GET DIAGNOSTICS CONDITION ? @var = CLASS_ORIGIN; --error ER_PARSE_ERROR GET DIAGNOSTICS CONDITION (1) @var = CLASS_ORIGIN; ---error ER_PARSE_ERROR +--error ER_BAD_FIELD_ERROR GET DIAGNOSTICS CONDITION p1() @var = CLASS_ORIGIN; ---error ER_PARSE_ERROR +--error ER_BAD_FIELD_ERROR GET DIAGNOSTICS CONDITION ABS(2) @var = CLASS_ORIGIN; # Unfortunate side effects... @@ -285,6 +285,7 @@ SELECT COUNT(max_questions) INTO @var FROM mysql.user; GET DIAGNOSTICS CONDITION 9999 @var = CLASS_ORIGIN; GET DIAGNOSTICS CONDITION NULL @var = CLASS_ORIGIN; +--error ER_BAD_FIELD_ERROR GET DIAGNOSTICS CONDITION a @var = CLASS_ORIGIN; # Reset warnings diff --git a/mysql-test/main/gis-debug.result b/mysql-test/main/gis-debug.result index be4145f2236..2daa810db0d 100644 --- a/mysql-test/main/gis-debug.result +++ b/mysql-test/main/gis-debug.result @@ -405,3 +405,93 @@ ERROR HY000: Illegal parameter data types varchar and geometry for operation '/' CREATE TABLE t1 AS SELECT '0' MOD POINT(0,0) LIMIT 0; ERROR HY000: Illegal parameter data types varchar and geometry for operation 'MOD' SET debug_dbug='-d,num_op'; +# +# End of 10.3 tests +# +# +# Start of 10.4 tests +# +# +# MDEV-16454 Bad results for IN with ROW +# +SET SESSION debug_dbug="+d,cmp_item"; +SET SESSION debug_dbug="+d,Item_func_in"; +SET SESSION debug_dbug="+d,Predicant_to_list_comparator"; +SELECT (POINT(1,1),0) IN ((POINT(1,1),0),((POINT(1,1)),1)); +(POINT(1,1),0) IN ((POINT(1,1),0),((POINT(1,1)),1)) +1 +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (row) +Note 1105 DBUG: [1] arg=2 handler=0 (row) +Note 1105 DBUG: ROW(3 args) level=0 +Note 1105 DBUG: [0,0] handler=geometry +Note 1105 DBUG: [0,1] handler=geometry +Note 1105 DBUG: [0,2] handler=geometry +Note 1105 DBUG: => handler=geometry +Note 1105 DBUG: [1,0] handler=int +Note 1105 DBUG: [1,1] handler=int +Note 1105 DBUG: [1,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: types_compatible=yes bisect=no +SELECT (1,(POINT(1,1),0)) IN ((1,(POINT(1,1),0)),(0,(POINT(1,1),0))); +(1,(POINT(1,1),0)) IN ((1,(POINT(1,1),0)),(0,(POINT(1,1),0))) +1 +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (row) +Note 1105 DBUG: [1] arg=2 handler=0 (row) +Note 1105 DBUG: ROW(3 args) level=0 +Note 1105 DBUG: [0,0] handler=int +Note 1105 DBUG: [0,1] handler=int +Note 1105 DBUG: [0,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: [1,0] handler=row +Note 1105 DBUG: [1,1] handler=row +Note 1105 DBUG: [1,2] handler=row +Note 1105 DBUG: => handler=row +Note 1105 DBUG: ROW(3 args) level=1 +Note 1105 DBUG: [0,0] handler=geometry +Note 1105 DBUG: [0,1] handler=geometry +Note 1105 DBUG: [0,2] handler=geometry +Note 1105 DBUG: => handler=geometry +Note 1105 DBUG: [1,0] handler=int +Note 1105 DBUG: [1,1] handler=int +Note 1105 DBUG: [1,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: types_compatible=yes bisect=no +SELECT (1,0) IN ((POINT(1,1),0),(0,0)); +ERROR HY000: Illegal parameter data types int and geometry for operation 'in' +SHOW WARNINGS; +Level Code Message +Note 1105 DBUG: [0] arg=1 handler=0 (row) +Note 1105 DBUG: [1] arg=2 handler=0 (row) +Note 1105 DBUG: ROW(3 args) level=0 +Note 1105 DBUG: [0,0] handler=int +Note 1105 DBUG: [0,1] handler=geometry +Note 1105 DBUG: [0,2] handler=int +Error 4078 Illegal parameter data types int and geometry for operation 'in' +SELECT (1,(0,0)) IN ((1,(POINT(1,1),0)),(0,(0,0))); +ERROR HY000: Illegal parameter data types int and geometry for operation 'in' +SHOW WARNINGS; +Level Code Message +Note 1105 DBUG: [0] arg=1 handler=0 (row) +Note 1105 DBUG: [1] arg=2 handler=0 (row) +Note 1105 DBUG: ROW(3 args) level=0 +Note 1105 DBUG: [0,0] handler=int +Note 1105 DBUG: [0,1] handler=int +Note 1105 DBUG: [0,2] handler=int +Note 1105 DBUG: => handler=bigint +Note 1105 DBUG: [1,0] handler=row +Note 1105 DBUG: [1,1] handler=row +Note 1105 DBUG: [1,2] handler=row +Note 1105 DBUG: => handler=row +Note 1105 DBUG: ROW(3 args) level=1 +Note 1105 DBUG: [0,0] handler=int +Note 1105 DBUG: [0,1] handler=geometry +Note 1105 DBUG: [0,2] handler=int +Error 4078 Illegal parameter data types int and geometry for operation 'in' +SET SESSION debug_dbug="-d,Predicant_to_list_comparator"; +SET SESSION debug_dbug="-d,Item_func_in"; +SET SESSION debug_dbug="-d,cmp_item"; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/gis-debug.test b/mysql-test/main/gis-debug.test index 588bc706370..dd64ce0f04c 100644 --- a/mysql-test/main/gis-debug.test +++ b/mysql-test/main/gis-debug.test @@ -111,3 +111,39 @@ CREATE TABLE t1 AS SELECT '0'/POINT(0,0) LIMIT 0; CREATE TABLE t1 AS SELECT '0' MOD POINT(0,0) LIMIT 0; SET debug_dbug='-d,num_op'; + +--echo # +--echo # End of 10.3 tests +--echo # + + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-16454 Bad results for IN with ROW +--echo # + +SET SESSION debug_dbug="+d,cmp_item"; +SET SESSION debug_dbug="+d,Item_func_in"; +SET SESSION debug_dbug="+d,Predicant_to_list_comparator"; + +SELECT (POINT(1,1),0) IN ((POINT(1,1),0),((POINT(1,1)),1)); +SELECT (1,(POINT(1,1),0)) IN ((1,(POINT(1,1),0)),(0,(POINT(1,1),0))); + +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT (1,0) IN ((POINT(1,1),0),(0,0)); +SHOW WARNINGS; + +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT (1,(0,0)) IN ((1,(POINT(1,1),0)),(0,(0,0))); +SHOW WARNINGS; + +SET SESSION debug_dbug="-d,Predicant_to_list_comparator"; +SET SESSION debug_dbug="-d,Item_func_in"; +SET SESSION debug_dbug="-d,cmp_item"; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/gis-precise.result b/mysql-test/main/gis-precise.result index 2d78b6e53de..8382a94e358 100644 --- a/mysql-test/main/gis-precise.result +++ b/mysql-test/main/gis-precise.result @@ -223,7 +223,7 @@ st_u MULTIPOLYGON(((525400 18370,525000.9677614468 183300,525400 183300,525400 18370)),((525000 183300,525000 183700,525000.9677614468 183300,525000 183300)),((525265.58 183481.95,525263.95 183484.75,525260.7 183491.55,525276.79 183500,525278.39 183500.84,525278.63 183500.97,525280.98 183502.26,525283.17 183503.47,525289.11 183506.62,525296.42 183510.31,525296.57 183510.39,525298.67 183511.53,525302.81 183513.8,525304.5 183510.83,525307.85 183504.95,525304.45 183504.25,525301.75 183509.35,525283.55 183500,525282.2 183499.3,525282.3 183499.1,525280.35 183498.2,525275.5 183495.7,525276.5 183493.45,525278.97 183488.73,525265.58 183481.95),(525266.99 183484.33,525263.26 183491.55,525266.15 183493.04,525269.88 183485.82,525266.99 183484.33),(525272.06 183488.37,525268.94 183494.51,525271.94 183496.03,525275.06 183489.89,525272.06 183488.37))) SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F; SELECT ASTEXT(TOUCHES(@a, GEOMFROMTEXT('point(0 0)'))) t; -ERROR HY000: Illegal parameter data type int for operation 'st_astext' +ERROR HY000: Illegal parameter data type boolean for operation 'st_astext' SELECT astext(ST_UNION ( PolyFromText('POLYGON(( 2 2 ,3 2,2 7,2 2),( 0 0,8 2,1 9,0 0))'), ExteriorRing( Envelope( MultiLineStringFromText('MULTILINESTRING((3 4,5 3),(3 0,0 5))'))))); diff --git a/mysql-test/main/gis-rtree.result b/mysql-test/main/gis-rtree.result index 5d4708dd111..2ef8757339e 100644 --- a/mysql-test/main/gis-rtree.result +++ b/mysql-test/main/gis-rtree.result @@ -744,6 +744,7 @@ Table Op Msg_type Msg_text test.t1 check status OK analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK drop table t1; CREATE TABLE t1 ( diff --git a/mysql-test/main/gis.result b/mysql-test/main/gis.result index 0ee502d8f87..7695cef15c5 100644 --- a/mysql-test/main/gis.result +++ b/mysql-test/main/gis.result @@ -4936,3 +4936,56 @@ ERROR HY000: Illegal parameter data type geometry for operation 'is_used_lock' # # End of 10.3 tests # +# +# Start of 10.4 tests +# +# +# MDEV-16351 JSON_OBJECT() treats hybrid functions with boolean arguments as numbers +# +SELECT ST_SRID(TRUE); +ERROR HY000: Illegal parameter data type boolean for operation 'srid' +SELECT ST_SRID(COALESCE(TRUE,TRUE)); +ERROR HY000: Illegal parameter data type boolean for operation 'srid' +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT ST_SRID((SELECT MAX(a)>3 FROM t1)); +ERROR HY000: Illegal parameter data type boolean for operation 'srid' +SELECT ST_SRID(MAX(a>3)) FROM t1; +ERROR HY000: Illegal parameter data type boolean for operation 'srid' +SELECT ST_SRID((SELECT MAX(a>3) FROM t1)); +ERROR HY000: Illegal parameter data type boolean for operation 'srid' +DROP TABLE t1; +# +# Mixing GEOMETRY with HEX hybrid +# +SELECT 0x60=POINT(1,1), POINT(1,1)=0x60; +0x60=POINT(1,1) POINT(1,1)=0x60 +0 0 +CREATE TABLE t1 AS SELECT +COALESCE(0x60,POINT(1,1)), +COALESCE(POINT(1,1),0x60), +LEAST(0x60,POINT(1,1)), +LEAST(POINT(1,1),0x60); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `COALESCE(0x60,POINT(1,1))` longblob DEFAULT NULL, + `COALESCE(POINT(1,1),0x60)` longblob DEFAULT NULL, + `LEAST(0x60,POINT(1,1))` longblob DEFAULT NULL, + `LEAST(POINT(1,1),0x60)` longblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SELECT 0x60+POINT(1,1); +ERROR HY000: Illegal parameter data types bigint and geometry for operation '+' +SELECT POINT(1,1)+0x60; +ERROR HY000: Illegal parameter data types geometry and bigint for operation '+' +# +# MDEV-16454 Bad results for IN with ROW +# +SELECT (1,0) IN ((POINT(1,1),0),(0,0)); +ERROR HY000: Illegal parameter data types int and geometry for operation 'in' +SELECT (1,(0,0)) IN ((1,(POINT(1,1),0)),(0,(0,0))); +ERROR HY000: Illegal parameter data types int and geometry for operation 'in' +# +# End of 10.4 tests +# diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index d22591bbe69..c3d0fb43520 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -2610,7 +2610,6 @@ SELECT ST_SRID(1); --error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION SELECT ST_SRID('test'); - --echo # Item_bool_func_args_geometry --error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION @@ -3005,3 +3004,58 @@ SELECT IS_USED_LOCK(POINT(1,1)); --echo # --echo # End of 10.3 tests --echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-16351 JSON_OBJECT() treats hybrid functions with boolean arguments as numbers +--echo # + +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT ST_SRID(TRUE); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT ST_SRID(COALESCE(TRUE,TRUE)); + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT ST_SRID((SELECT MAX(a)>3 FROM t1)); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT ST_SRID(MAX(a>3)) FROM t1; +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT ST_SRID((SELECT MAX(a>3) FROM t1)); +DROP TABLE t1; + +--echo # +--echo # Mixing GEOMETRY with HEX hybrid +--echo # + +SELECT 0x60=POINT(1,1), POINT(1,1)=0x60; + +CREATE TABLE t1 AS SELECT + COALESCE(0x60,POINT(1,1)), + COALESCE(POINT(1,1),0x60), + LEAST(0x60,POINT(1,1)), + LEAST(POINT(1,1),0x60); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT 0x60+POINT(1,1); +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT POINT(1,1)+0x60; + +--echo # +--echo # MDEV-16454 Bad results for IN with ROW +--echo # + +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT (1,0) IN ((POINT(1,1),0),(0,0)); +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT (1,(0,0)) IN ((1,(POINT(1,1),0)),(0,(0,0))); + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/grant.result b/mysql-test/main/grant.result index b2f6bafd291..46d87a4777f 100644 --- a/mysql-test/main/grant.result +++ b/mysql-test/main/grant.result @@ -2,6 +2,7 @@ set GLOBAL sql_mode=""; set LOCAL sql_mode=""; SET @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; SET GLOBAL log_bin_trust_function_creators = 1; +select priv into @root_priv from mysql.global_priv where user='root' and host='localhost'; drop table if exists t1; drop database if exists mysqltest; connect master,localhost,root,,; @@ -58,7 +59,7 @@ max_questions 0 max_updates 0 max_connections 0 max_user_connections 0 -plugin +plugin mysql_native_password authentication_string password_expired N is_role N @@ -134,7 +135,7 @@ max_questions 10 max_updates 0 max_connections 0 max_user_connections 0 -plugin +plugin mysql_native_password authentication_string password_expired N is_role N @@ -186,7 +187,7 @@ max_questions 10 max_updates 20 max_connections 30 max_user_connections 0 -plugin +plugin mysql_native_password authentication_string password_expired N is_role N @@ -298,12 +299,7 @@ ERROR HY000: Incorrect usage of DB GRANT and GLOBAL PRIVILEGES select 1; 1 1 -insert into mysql.user (host, user) values ('localhost', 'test11'); -Warnings: -Warning 1364 Field 'ssl_cipher' doesn't have a default value -Warning 1364 Field 'x509_issuer' doesn't have a default value -Warning 1364 Field 'x509_subject' doesn't have a default value -Warning 1364 Field 'authentication_string' doesn't have a default value +insert into mysql.global_priv (host, user) values ('localhost', 'test11'); insert into mysql.db (host, db, user, select_priv) values ('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y'); alter table mysql.db order by db asc; @@ -842,9 +838,6 @@ drop database db27515; End of 4.1 tests use test; create table t1 (a int); -create table t2 as select * from mysql.user where user=''; -delete from mysql.user where user=''; -flush privileges; create user mysqltest_8@''; create user mysqltest_8@host8; create user mysqltest_8@''; @@ -854,7 +847,7 @@ ERROR HY000: Operation CREATE USER failed for 'mysqltest_8'@'%' create user mysqltest_8@host8; ERROR HY000: Operation CREATE USER failed for 'mysqltest_8'@'host8' select user, QUOTE(host) from mysql.user where user="mysqltest_8"; -user QUOTE(host) +User QUOTE(host) mysqltest_8 '%' mysqltest_8 'host8' Schema privileges @@ -1044,9 +1037,6 @@ ERROR 42000: There is no such grant defined for user 'mysqltest_8' on host '%' drop user mysqltest_8@host8; show grants for mysqltest_8@host8; ERROR 42000: There is no such grant defined for user 'mysqltest_8' on host 'host8' -insert into mysql.user select * from t2; -flush privileges; -drop table t2; drop table t1; connection master; CREATE DATABASE mysqltest3; @@ -1440,6 +1430,8 @@ declare tmp varchar(30); select col1 from test limit 1 into tmp; return '1'; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create view v1 as select test.* from test where test.col1=test_function(); grant update (col1) on v1 to 'greg'@'localhost'; drop user 'greg'@'localhost'; @@ -1451,7 +1443,6 @@ CURRENT_USER() root@localhost SET PASSWORD FOR CURRENT_USER() = PASSWORD("admin"); SET PASSWORD FOR CURRENT_USER() = PASSWORD(""); -update mysql.user set plugin=''; # Bug#57952 @@ -1923,7 +1914,7 @@ DROP DATABASE db2; grant usage on Foo.* to myuser@Localhost identified by 'foo'; grant select on Foo.* to myuser@localhost; select host,user from mysql.user where User='myuser'; -host user +Host User localhost myuser revoke select on Foo.* from myuser@localhost; delete from mysql.user where User='myuser'; @@ -2731,7 +2722,7 @@ DROP USER untrusted@localhost; DROP DATABASE secret; set GLOBAL sql_mode=default; # -# Start of 10.2 tests +# End of 10.1 tests # # # MDEV-10134 Add full support for DEFAULT @@ -2760,3 +2751,24 @@ DROP USER dummy@localhost; # # End of 10.2 tests # +# +# MDEV-17932 : Assertion upon double RENAME USER +# +CREATE USER foo@localhost; +CREATE USER bar2@localhost; +RENAME USER foo@localhost TO bar1@localhost, bar1@localhost TO bar3@localhost; +DROP USER bar2@localhost; +DROP USER bar3@localhost; +# +# MDEV-17946 : Unsorted acl_dbs after RENAME USER +# +CREATE USER foo; +GRANT SELECT ON test.* TO foo; +RENAME USER '' TO 'name'; +GRANT UPDATE ON test.* TO foo; +RENAME USER 'name' to ''; +DROP USER foo; +# +# End of 10.4 tests +# +update mysql.global_priv set priv=@root_priv where user='root' and host='localhost'; diff --git a/mysql-test/main/grant.test b/mysql-test/main/grant.test index f54c4bd981d..8ae64c9ad4d 100644 --- a/mysql-test/main/grant.test +++ b/mysql-test/main/grant.test @@ -10,6 +10,7 @@ set GLOBAL sql_mode=""; set LOCAL sql_mode=""; SET @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; SET GLOBAL log_bin_trust_function_creators = 1; +select priv into @root_priv from mysql.global_priv where user='root' and host='localhost'; # Cleanup --disable_warnings @@ -131,7 +132,7 @@ select 1; # To test that the previous command didn't cause problems # # Bug#4898 User privileges depending on ORDER BY Settings of table db # -insert into mysql.user (host, user) values ('localhost', 'test11'); +insert into mysql.global_priv (host, user) values ('localhost', 'test11'); insert into mysql.db (host, db, user, select_priv) values ('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y'); alter table mysql.db order by db asc; @@ -581,12 +582,6 @@ drop database db27515; use test; create table t1 (a int); -# Backup anonymous users and remove them. (They get in the way of -# the one we test with here otherwise.) -create table t2 as select * from mysql.user where user=''; -delete from mysql.user where user=''; -flush privileges; - # Create some users with different hostnames create user mysqltest_8@''; create user mysqltest_8@host8; @@ -700,10 +695,6 @@ drop user mysqltest_8@host8; --error ER_NONEXISTING_GRANT show grants for mysqltest_8@host8; -# Restore the anonymous users. -insert into mysql.user select * from t2; -flush privileges; -drop table t2; drop table t1; # @@ -1265,9 +1256,6 @@ SELECT CURRENT_USER(); SET PASSWORD FOR CURRENT_USER() = PASSWORD("admin"); SET PASSWORD FOR CURRENT_USER() = PASSWORD(""); -#cleanup after MDEV-16238 -update mysql.user set plugin=''; - # # Bug#57952: privilege change is not taken into account by EXECUTE. # @@ -2233,7 +2221,7 @@ set GLOBAL sql_mode=default; --source include/wait_until_count_sessions.inc --echo # ---echo # Start of 10.2 tests +--echo # End of 10.1 tests --echo # --echo # @@ -2258,3 +2246,28 @@ DROP USER dummy@localhost; --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # MDEV-17932 : Assertion upon double RENAME USER +--echo # +CREATE USER foo@localhost; +CREATE USER bar2@localhost; +RENAME USER foo@localhost TO bar1@localhost, bar1@localhost TO bar3@localhost; +DROP USER bar2@localhost; +DROP USER bar3@localhost; + +--echo # +--echo # MDEV-17946 : Unsorted acl_dbs after RENAME USER +--echo # +CREATE USER foo; +GRANT SELECT ON test.* TO foo; +RENAME USER '' TO 'name'; +GRANT UPDATE ON test.* TO foo; +RENAME USER 'name' to ''; +DROP USER foo; + +--echo # +--echo # End of 10.4 tests +--echo # + +update mysql.global_priv set priv=@root_priv where user='root' and host='localhost'; diff --git a/mysql-test/main/grant2.result b/mysql-test/main/grant2.result index ffb41c1b5f8..5d168a04455 100644 --- a/mysql-test/main/grant2.result +++ b/mysql-test/main/grant2.result @@ -1,3 +1,4 @@ +select priv into @root_priv from mysql.global_priv where user='root' and host='localhost'; set GLOBAL sql_mode=""; set LOCAL sql_mode=""; SET NAMES binary; @@ -181,19 +182,19 @@ grant select on *.* to 'mysqltest_2'; grant insert on test.* to 'mysqltest_2'; grant update on test.t1 to 'mysqltest_2'; grant update (c2) on test.t2 to 'mysqltest_2'; -select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; -host user password -% mysqltest_1 -% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 -% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff -select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +select host,user,password,plugin,authentication_string from mysql.user where user like 'mysqltest_%'; +Host User Password plugin authentication_string +% mysqltest_1 mysql_native_password +% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 mysql_native_password *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff mysql_native_password fffffffffffffffffffffffffffffffffffffffff +select host,db,user from mysql.db where user like 'mysqltest_%'; host db user % test mysqltest_2 -select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%'; host db user table_name % test mysqltest_2 t1 % test mysqltest_2 t2 -select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%'; host db user table_name column_name % test mysqltest_2 t2 c2 show grants for 'mysqltest_1'; @@ -206,35 +207,35 @@ GRANT INSERT ON "test".* TO 'mysqltest_2'@'%' GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_2'@'%' GRANT UPDATE ON "test"."t1" TO 'mysqltest_2'@'%' drop user 'mysqltest_1'; -select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; -host user password -% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 -% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff -select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +select host,user,password,plugin,authentication_string from mysql.user where user like 'mysqltest_%'; +Host User Password plugin authentication_string +% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 mysql_native_password *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff mysql_native_password fffffffffffffffffffffffffffffffffffffffff +select host,db,user from mysql.db where user like 'mysqltest_%'; host db user % test mysqltest_2 -select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%'; host db user table_name % test mysqltest_2 t1 % test mysqltest_2 t2 -select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%'; host db user table_name column_name % test mysqltest_2 t2 c2 show grants for 'mysqltest_1'; ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' rename user 'mysqltest_2' to 'mysqltest_1'; -select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; -host user password -% mysqltest_1 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 -% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff -select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +select host,user,password,plugin,authentication_string from mysql.user where user like 'mysqltest_%' ; +Host User Password plugin authentication_string +% mysqltest_1 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 mysql_native_password *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff mysql_native_password fffffffffffffffffffffffffffffffffffffffff +select host,db,user from mysql.db where user like 'mysqltest_%' ; host db user % test mysqltest_1 -select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' ; host db user table_name % test mysqltest_1 t1 % test mysqltest_1 t2 -select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' ; host db user table_name column_name % test mysqltest_1 t2 c2 show grants for 'mysqltest_1'; @@ -254,21 +255,21 @@ ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' revoke all privileges, grant option from 'mysqltest_1'; ERROR HY000: Can't revoke all privileges for one or more of the requested users drop user 'mysqltest_1'; -select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user; +select host,db,user from mysql.db where user = 'mysqltest_1' ; host db user insert into mysql.tables_priv set host='%', db='test', user='mysqltest_1', table_name='t1'; flush privileges; show grants for 'mysqltest_1'; ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' drop user 'mysqltest_1'; -select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' order by host,db,user,table_name; +select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' ; host db user table_name insert into mysql.columns_priv set host='%', db='test', user='mysqltest_1', table_name='t1', column_name='c1'; flush privileges; show grants for 'mysqltest_1'; ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' drop user 'mysqltest_1'; -select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' order by host,db,user,table_name,column_name; +select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' ; host db user table_name column_name create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; @@ -310,7 +311,7 @@ create user mysqltest_2@localhost; grant create user on *.* to mysqltest_2@localhost; connect user3,localhost,mysqltest_2,,; connection user3; -select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +select host,user,password,plugin,authentication_string from mysql.user where user like 'mysqltest_%' ; ERROR 42000: SELECT command denied to user 'mysqltest_2'@'localhost' for table 'user' create user mysqltest_A@'%'; rename user mysqltest_A@'%' to mysqltest_B@'%'; @@ -326,14 +327,9 @@ show grants; Grants for mysqltest_3@localhost GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost' GRANT INSERT, UPDATE, DELETE ON `mysql`.* TO 'mysqltest_3'@'localhost' -select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +select host,user,password,plugin,authentication_string from mysql.user where user like 'mysqltest_%' ; ERROR 42000: SELECT command denied to user 'mysqltest_3'@'localhost' for table 'user' -insert into mysql.user set host='%', user='mysqltest_B'; -Warnings: -Warning 1364 Field 'ssl_cipher' doesn't have a default value -Warning 1364 Field 'x509_issuer' doesn't have a default value -Warning 1364 Field 'x509_subject' doesn't have a default value -Warning 1364 Field 'authentication_string' doesn't have a default value +insert into mysql.global_priv set host='%', user='mysqltest_B'; create user mysqltest_A@'%'; rename user mysqltest_B@'%' to mysqltest_C@'%'; drop user mysqltest_C@'%'; @@ -373,7 +369,7 @@ set password = password('changed'); disconnect b12302; connection default; select host, length(authentication_string) from mysql.user where user like 'mysqltest\_1'; -host length(authentication_string) +Host length(authentication_string) 127.0.0.1 41 revoke all on mysqltest_1.* from mysqltest_1@'127.0.0.1'; delete from mysql.user where user like 'mysqltest\_1'; @@ -388,7 +384,7 @@ set password = password('changed'); disconnect b12302_2; connection default; select host, length(authentication_string) from mysql.user where user like 'mysqltest\_1'; -host length(authentication_string) +Host length(authentication_string) 127.0.0.0/255.0.0.0 41 revoke all on mysqltest_1.* from mysqltest_1@'127.0.0.0/255.0.0.0'; delete from mysql.user where user like 'mysqltest\_1'; @@ -428,15 +424,10 @@ disconnect con2root; disconnect con3root; create database TESTDB; create table t2(a int); -create temporary table t1 as select * from mysql.user; -delete from mysql.user where host='localhost'; -INSERT INTO mysql.user (host, user, password) VALUES -('%','mysqltest_1',password('password')); -Warnings: -Warning 1364 Field 'ssl_cipher' doesn't have a default value -Warning 1364 Field 'x509_issuer' doesn't have a default value -Warning 1364 Field 'x509_subject' doesn't have a default value -Warning 1364 Field 'authentication_string' doesn't have a default value +create temporary table t1 as select * from mysql.global_priv; +delete from mysql.global_priv where host='localhost'; +INSERT INTO mysql.global_priv (host, user, priv) VALUES +('%','mysqltest_1',json_object('authentication_string', password('password'))); INSERT INTO mysql.db (host, db, user, select_priv) VALUES ('%','TESTDB','mysqltest_1','Y'); FLUSH PRIVILEGES; @@ -445,9 +436,9 @@ create database TEStdb; Got one of the listed errors connection default; disconnect con1; -delete from mysql.user; +delete from mysql.global_priv; delete from mysql.db where host='%' and user='mysqltest_1' and db='TESTDB'; -insert into mysql.user select * from t1; +insert into mysql.global_priv select * from t1; drop table t1, t2; drop database TESTDB; flush privileges; @@ -462,6 +453,8 @@ INSERT INTO t2 VALUES (1); DROP FUNCTION IF EXISTS f2; CREATE FUNCTION f2 () RETURNS INT BEGIN DECLARE v INT; SELECT s1 FROM t2 INTO v; RETURN v; END// +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT f2(); f2() 1 @@ -553,27 +546,18 @@ End of 5.0 tests USE mysql; SELECT LEFT(CURRENT_USER(),INSTR(CURRENT_USER(),'@')-1) INTO @u; SELECT MID(CURRENT_USER(),INSTR(CURRENT_USER(),'@')+1) INTO @h; -SELECT password FROM user WHERE user=@u AND host=@h INTO @pwd; -SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; -user host password insert_priv -root localhost Y -UPDATE user SET insert_priv='N' WHERE user=@u AND host=@h; -SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; -user host password insert_priv -root localhost N +SELECT user,host,password,plugin,authentication_string,insert_priv FROM user WHERE user=@u AND host=@h; +User Host Password plugin authentication_string Insert_priv +root localhost Y GRANT INSERT ON *.* TO CURRENT_USER(); -SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; -user host password insert_priv -root localhost Y -UPDATE user SET insert_priv='N' WHERE user=@u AND host=@h; +SELECT user,host,password,plugin,authentication_string,insert_priv FROM user WHERE user=@u AND host=@h; +User Host Password plugin authentication_string Insert_priv +root localhost mysql_native_password Y GRANT INSERT ON *.* TO CURRENT_USER() IDENTIFIED BY 'keksdose'; -SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; -user host password insert_priv -root localhost *0BB7188CF0DE9B403BA66E9DD810D82652D002EB Y -UPDATE user SET password=@pwd WHERE user=@u AND host=@h; -SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; -user host password insert_priv -root localhost Y +SELECT user,host,password,plugin,authentication_string,insert_priv FROM user WHERE user=@u AND host=@h; +User Host Password plugin authentication_string Insert_priv +root localhost *0BB7188CF0DE9B403BA66E9DD810D82652D002EB mysql_native_password *0BB7188CF0DE9B403BA66E9DD810D82652D002EB Y +UPDATE global_priv SET priv=@root_priv; FLUSH PRIVILEGES; USE test; End of 5.1 tests diff --git a/mysql-test/main/grant2.test b/mysql-test/main/grant2.test index 1f7450df6c1..b33d7d63992 100644 --- a/mysql-test/main/grant2.test +++ b/mysql-test/main/grant2.test @@ -4,7 +4,7 @@ # Save the initial number of concurrent sessions --source include/count_sessions.inc - +select priv into @root_priv from mysql.global_priv where user='root' and host='localhost'; set GLOBAL sql_mode=""; set LOCAL sql_mode=""; SET NAMES binary; @@ -231,28 +231,40 @@ grant select on *.* to 'mysqltest_2'; grant insert on test.* to 'mysqltest_2'; grant update on test.t1 to 'mysqltest_2'; grant update (c2) on test.t2 to 'mysqltest_2'; -select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; -select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; -select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; -select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +--sorted_result +select host,user,password,plugin,authentication_string from mysql.user where user like 'mysqltest_%'; +--sorted_result +select host,db,user from mysql.db where user like 'mysqltest_%'; +--sorted_result +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%'; +--sorted_result +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%'; show grants for 'mysqltest_1'; show grants for 'mysqltest_2'; # # Drop drop user 'mysqltest_1'; -select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; -select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; -select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; -select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +--sorted_result +select host,user,password,plugin,authentication_string from mysql.user where user like 'mysqltest_%'; +--sorted_result +select host,db,user from mysql.db where user like 'mysqltest_%'; +--sorted_result +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%'; +--sorted_result +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%'; --error ER_NONEXISTING_GRANT show grants for 'mysqltest_1'; # # Rename rename user 'mysqltest_2' to 'mysqltest_1'; -select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; -select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; -select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; -select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +--sorted_result +select host,user,password,plugin,authentication_string from mysql.user where user like 'mysqltest_%' ; +--sorted_result +select host,db,user from mysql.db where user like 'mysqltest_%' ; +--sorted_result +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' ; +--sorted_result +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' ; show grants for 'mysqltest_1'; drop user 'mysqltest_1', 'mysqltest_3'; --error ER_CANNOT_USER @@ -269,7 +281,8 @@ show grants for 'mysqltest_1'; --error ER_REVOKE_GRANTS revoke all privileges, grant option from 'mysqltest_1'; drop user 'mysqltest_1'; -select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user; +--sorted_result +select host,db,user from mysql.db where user = 'mysqltest_1' ; # # Add a stray record insert into mysql.tables_priv set host='%', db='test', user='mysqltest_1', table_name='t1'; @@ -277,7 +290,8 @@ flush privileges; --error ER_NONEXISTING_GRANT show grants for 'mysqltest_1'; drop user 'mysqltest_1'; -select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' order by host,db,user,table_name; +--sorted_result +select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' ; # # Add a stray record insert into mysql.columns_priv set host='%', db='test', user='mysqltest_1', table_name='t1', column_name='c1'; @@ -285,7 +299,8 @@ flush privileges; --error ER_NONEXISTING_GRANT show grants for 'mysqltest_1'; drop user 'mysqltest_1'; -select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' order by host,db,user,table_name,column_name; +--sorted_result +select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' ; # # Handle multi user lists create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; @@ -330,7 +345,7 @@ grant create user on *.* to mysqltest_2@localhost; connect (user3,localhost,mysqltest_2,,); connection user3; --error ER_TABLEACCESS_DENIED_ERROR -select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +select host,user,password,plugin,authentication_string from mysql.user where user like 'mysqltest_%' ; create user mysqltest_A@'%'; rename user mysqltest_A@'%' to mysqltest_B@'%'; drop user mysqltest_B@'%'; @@ -345,8 +360,8 @@ connect (user4,localhost,mysqltest_3,,); connection user4; show grants; --error ER_TABLEACCESS_DENIED_ERROR -select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; -insert into mysql.user set host='%', user='mysqltest_B'; +select host,user,password,plugin,authentication_string from mysql.user where user like 'mysqltest_%' ; +insert into mysql.global_priv set host='%', user='mysqltest_B'; create user mysqltest_A@'%'; rename user mysqltest_B@'%' to mysqltest_C@'%'; drop user mysqltest_C@'%'; @@ -466,10 +481,10 @@ disconnect con3root; create database TESTDB; create table t2(a int); -create temporary table t1 as select * from mysql.user; -delete from mysql.user where host='localhost'; -INSERT INTO mysql.user (host, user, password) VALUES -('%','mysqltest_1',password('password')); +create temporary table t1 as select * from mysql.global_priv; +delete from mysql.global_priv where host='localhost'; +INSERT INTO mysql.global_priv (host, user, priv) VALUES +('%','mysqltest_1',json_object('authentication_string', password('password'))); INSERT INTO mysql.db (host, db, user, select_priv) VALUES ('%','TESTDB','mysqltest_1','Y'); FLUSH PRIVILEGES; @@ -485,9 +500,9 @@ create database TEStdb; # Clean-up connection default; disconnect con1; -delete from mysql.user; +delete from mysql.global_priv; delete from mysql.db where host='%' and user='mysqltest_1' and db='TESTDB'; -insert into mysql.user select * from t1; +insert into mysql.global_priv select * from t1; drop table t1, t2; drop database TESTDB; flush privileges; @@ -642,27 +657,19 @@ DROP DATABASE db1; USE mysql; SELECT LEFT(CURRENT_USER(),INSTR(CURRENT_USER(),'@')-1) INTO @u; SELECT MID(CURRENT_USER(),INSTR(CURRENT_USER(),'@')+1) INTO @h; -SELECT password FROM user WHERE user=@u AND host=@h INTO @pwd; # show current privs. -SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; - -# toggle INSERT -UPDATE user SET insert_priv='N' WHERE user=@u AND host=@h; -SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; +SELECT user,host,password,plugin,authentication_string,insert_priv FROM user WHERE user=@u AND host=@h; # show that GRANT ... TO CURRENT_USER() no longer crashes GRANT INSERT ON *.* TO CURRENT_USER(); -SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; -UPDATE user SET insert_priv='N' WHERE user=@u AND host=@h; +SELECT user,host,password,plugin,authentication_string,insert_priv FROM user WHERE user=@u AND host=@h; # show that GRANT ... TO CURRENT_USER() IDENTIFIED BY ... works now GRANT INSERT ON *.* TO CURRENT_USER() IDENTIFIED BY 'keksdose'; -SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; - -UPDATE user SET password=@pwd WHERE user=@u AND host=@h; -SELECT user,host,password,insert_priv FROM user WHERE user=@u AND host=@h; +SELECT user,host,password,plugin,authentication_string,insert_priv FROM user WHERE user=@u AND host=@h; +UPDATE global_priv SET priv=@root_priv; FLUSH PRIVILEGES; USE test; diff --git a/mysql-test/main/grant3.result b/mysql-test/main/grant3.result index 4c99fb02f19..1bc6e7572c5 100644 --- a/mysql-test/main/grant3.result +++ b/mysql-test/main/grant3.result @@ -29,7 +29,7 @@ grant select on test.* to CUser@localhost; grant select on test.* to CUser@LOCALHOST; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser' order by 1,2; -user host +User Host CUser localhost SELECT user, host, db, select_priv FROM mysql.db where user = 'CUser' order by 1,2; user host db select_priv @@ -37,14 +37,14 @@ CUser localhost test Y REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'CUser'@'LOCALHOST'; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser' order by 1,2; -user host +User Host CUser localhost SELECT user, host, db, select_priv FROM mysql.db where user = 'CUser' order by 1,2; user host db select_priv REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'CUser'@'localhost'; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser' order by 1,2; -user host +User Host CUser localhost SELECT user, host, db, select_priv FROM mysql.db where user = 'CUser' order by 1,2; user host db select_priv @@ -56,7 +56,7 @@ grant select on test.t1 to CUser@localhost; grant select on test.t1 to CUser@LOCALHOST; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser' order by 1,2; -user host +User Host CUser localhost SELECT user, host, db, Table_name, Table_priv, Column_priv FROM mysql.tables_priv where user = 'CUser' order by 1,2; user host db Table_name Table_priv Column_priv @@ -64,14 +64,14 @@ CUser localhost test t1 Select REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'CUser'@'LOCALHOST'; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser' order by 1,2; -user host +User Host CUser localhost SELECT user, host, db, Table_name, Table_priv, Column_priv FROM mysql.tables_priv where user = 'CUser' order by 1,2; user host db Table_name Table_priv Column_priv REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'CUser'@'localhost'; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser' order by 1,2; -user host +User Host CUser localhost SELECT user, host, db, Table_name, Table_priv, Column_priv FROM mysql.tables_priv where user = 'CUser' order by 1,2; user host db Table_name Table_priv Column_priv @@ -82,7 +82,7 @@ grant select(a) on test.t1 to CUser@localhost; grant select(a) on test.t1 to CUser@LOCALHOST; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser' order by 1,2; -user host +User Host CUser localhost SELECT user, host, db, Table_name, Table_priv, Column_priv FROM mysql.tables_priv where user = 'CUser' order by 1,2; user host db Table_name Table_priv Column_priv @@ -90,14 +90,14 @@ CUser localhost test t1 Select REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'CUser'@'LOCALHOST'; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser' order by 1,2; -user host +User Host CUser localhost SELECT user, host, db, Table_name, Table_priv, Column_priv FROM mysql.tables_priv where user = 'CUser' order by 1,2; user host db Table_name Table_priv Column_priv REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'CUser'@'localhost'; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser' order by 1,2; -user host +User Host CUser localhost SELECT user, host, db, Table_name, Table_priv, Column_priv FROM mysql.tables_priv where user = 'CUser' order by 1,2; user host db Table_name Table_priv Column_priv @@ -109,7 +109,7 @@ grant select on test.* to CUser2@localhost; grant select on test.* to CUser2@LOCALHOST; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser2' order by 1,2; -user host +User Host CUser2 localhost SELECT user, host, db, select_priv FROM mysql.db where user = 'CUser2' order by 1,2; user host db select_priv @@ -117,7 +117,7 @@ CUser2 localhost test Y REVOKE SELECT ON test.* FROM 'CUser2'@'LOCALHOST'; flush privileges; SELECT user, host FROM mysql.user where user = 'CUser2' order by 1,2; -user host +User Host CUser2 localhost SELECT user, host, db, select_priv FROM mysql.db where user = 'CUser2' order by 1,2; user host db select_priv @@ -125,7 +125,7 @@ REVOKE SELECT ON test.* FROM 'CUser2'@'localhost'; ERROR 42000: There is no such grant defined for user 'CUser2' on host 'localhost' flush privileges; SELECT user, host FROM mysql.user where user = 'CUser2' order by 1,2; -user host +User Host CUser2 localhost SELECT user, host, db, select_priv FROM mysql.db where user = 'CUser2' order by 1,2; user host db select_priv diff --git a/mysql-test/main/grant4.result b/mysql-test/main/grant4.result index c3db2e03e3e..9aad70205ec 100644 --- a/mysql-test/main/grant4.result +++ b/mysql-test/main/grant4.result @@ -198,15 +198,15 @@ grant select on test.* to foo6 identified by password '2222222222222222'; grant select on test.* to foo7 identified via mysql_native_password using '11111111111111111111111111111111111111111'; grant select on test.* to foo8 identified via mysql_old_password using '2222222222222222'; select user,password,plugin,authentication_string from mysql.user where user like 'foo%'; -user password plugin authentication_string -foo1 11111111111111111111111111111111111111111 -foo2 2222222222222222 -foo3 11111111111111111111111111111111111111111 -foo4 2222222222222222 -foo5 11111111111111111111111111111111111111111 -foo6 2222222222222222 -foo7 11111111111111111111111111111111111111111 -foo8 2222222222222222 +User Password plugin authentication_string +foo1 11111111111111111111111111111111111111111 mysql_native_password 11111111111111111111111111111111111111111 +foo2 2222222222222222 mysql_old_password 2222222222222222 +foo3 11111111111111111111111111111111111111111 mysql_native_password 11111111111111111111111111111111111111111 +foo4 2222222222222222 mysql_old_password 2222222222222222 +foo5 11111111111111111111111111111111111111111 mysql_native_password 11111111111111111111111111111111111111111 +foo6 2222222222222222 mysql_old_password 2222222222222222 +foo7 11111111111111111111111111111111111111111 mysql_native_password 11111111111111111111111111111111111111111 +foo8 2222222222222222 mysql_old_password 2222222222222222 drop user foo1; drop user foo2; drop user foo3; diff --git a/mysql-test/main/grant5.result b/mysql-test/main/grant5.result index 24abc61a348..5df4a669a0c 100644 --- a/mysql-test/main/grant5.result +++ b/mysql-test/main/grant5.result @@ -18,3 +18,84 @@ ERROR 42000: Access denied for user 'test'@'%' to database 'mysql' connection default; drop user test, foo; drop role foo; +create user u1@h identified with 'mysql_native_password' using 'pwd'; +ERROR HY000: Password hash should be a 41-digit hexadecimal number +create user u1@h identified with 'mysql_native_password' using password('pwd'); +create user u2@h identified with 'mysql_native_password' using '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD'; +create user u3@h identified with 'mysql_native_password'; +set password for u3@h = 'pwd'; +ERROR HY000: Password hash should be a 41-digit hexadecimal number +set password for u3@h = password('pwd'); +create user u4@h identified with 'mysql_native_password'; +set password for u4@h = '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD'; +create user u5@h identified with 'mysql_old_password' using 'pwd'; +ERROR HY000: Password hash should be a 16-digit hexadecimal number +create user u5@h identified with 'mysql_old_password' using password('pwd'); +create user u6@h identified with 'mysql_old_password' using '78a302dd267f6044'; +create user u7@h identified with 'mysql_old_password'; +set password for u7@h = 'pwd'; +ERROR HY000: Password hash should be a 41-digit hexadecimal number +set password for u7@h = old_password('pwd'); +create user u8@h identified with 'mysql_old_password'; +set password for u8@h = '78a302dd267f6044'; +select user,host,plugin,authentication_string from mysql.user where host='h'; +User Host plugin authentication_string +u1 h mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD +u2 h mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD +u3 h mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD +u4 h mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD +u5 h mysql_old_password 78a302dd267f6044 +u6 h mysql_old_password 78a302dd267f6044 +u7 h mysql_old_password 78a302dd267f6044 +u8 h mysql_old_password 78a302dd267f6044 +update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad') where user='u1'; +update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad') where user='u5'; +update mysql.global_priv set priv=json_set(priv, '$.plugin', 'nonexistent') where user='u8'; +flush privileges; +Warnings: +Error 1372 Password hash should be a 41-digit hexadecimal number +Error 1372 Password hash should be a 16-digit hexadecimal number +Warning 1524 Plugin 'nonexistent' is not loaded +show create user u1@h; +ERROR 28000: Can't find any matching row in the user table +show create user u2@h; +CREATE USER for u2@h +CREATE USER 'u2'@'h' IDENTIFIED BY PASSWORD '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD' +show create user u3@h; +CREATE USER for u3@h +CREATE USER 'u3'@'h' IDENTIFIED BY PASSWORD '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD' +show create user u4@h; +CREATE USER for u4@h +CREATE USER 'u4'@'h' IDENTIFIED BY PASSWORD '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD' +show create user u5@h; +ERROR 28000: Can't find any matching row in the user table +show create user u6@h; +CREATE USER for u6@h +CREATE USER 'u6'@'h' IDENTIFIED BY PASSWORD '78a302dd267f6044' +show create user u7@h; +CREATE USER for u7@h +CREATE USER 'u7'@'h' IDENTIFIED BY PASSWORD '78a302dd267f6044' +show create user u8@h; +ERROR 28000: Can't find any matching row in the user table +grant select on *.* to u1@h; +ERROR 28000: Can't find any matching row in the user table +grant select on *.* to u2@h; +grant select on *.* to u3@h; +grant select on *.* to u4@h; +grant select on *.* to u5@h; +ERROR 28000: Can't find any matching row in the user table +grant select on *.* to u6@h; +grant select on *.* to u7@h; +grant select on *.* to u8@h; +ERROR 28000: Can't find any matching row in the user table +select user,select_priv,plugin,authentication_string from mysql.user where user like 'u_'; +User Select_priv plugin authentication_string +u1 N mysql_native_password bad +u2 Y mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD +u3 Y mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD +u4 Y mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD +u5 N mysql_old_password bad +u6 Y mysql_old_password 78a302dd267f6044 +u7 Y mysql_old_password 78a302dd267f6044 +u8 N nonexistent 78a302dd267f6044 +drop user u1@h, u2@h, u3@h, u4@h, u5@h, u6@h, u7@h, u8@h; diff --git a/mysql-test/main/grant5.test b/mysql-test/main/grant5.test index 14f2fd65020..4e89bad9775 100644 --- a/mysql-test/main/grant5.test +++ b/mysql-test/main/grant5.test @@ -23,3 +23,63 @@ show grants for foo@'%'; # user drop user test, foo; drop role foo; +# +# MDEV-12321 authentication plugin: SET PASSWORD support +# +error ER_PASSWD_LENGTH; +create user u1@h identified with 'mysql_native_password' using 'pwd'; +create user u1@h identified with 'mysql_native_password' using password('pwd'); +let p=`select password('pwd')`; +eval create user u2@h identified with 'mysql_native_password' using '$p'; +create user u3@h identified with 'mysql_native_password'; +error ER_PASSWD_LENGTH; +set password for u3@h = 'pwd'; +set password for u3@h = password('pwd'); +create user u4@h identified with 'mysql_native_password'; +eval set password for u4@h = '$p'; +error ER_PASSWD_LENGTH; +create user u5@h identified with 'mysql_old_password' using 'pwd'; +create user u5@h identified with 'mysql_old_password' using password('pwd'); +let p=`select old_password('pwd')`; +eval create user u6@h identified with 'mysql_old_password' using '$p'; +create user u7@h identified with 'mysql_old_password'; +error ER_PASSWD_LENGTH; +set password for u7@h = 'pwd'; +set password for u7@h = old_password('pwd'); +create user u8@h identified with 'mysql_old_password'; +eval set password for u8@h = '$p'; +sorted_result; +select user,host,plugin,authentication_string from mysql.user where host='h'; +# test with invalid entries +update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad') where user='u1'; +update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad') where user='u5'; +update mysql.global_priv set priv=json_set(priv, '$.plugin', 'nonexistent') where user='u8'; +flush privileges; +# invalid entries are skipped, users don't exist +error ER_PASSWORD_NO_MATCH; +show create user u1@h; +show create user u2@h; +show create user u3@h; +show create user u4@h; +error ER_PASSWORD_NO_MATCH; +show create user u5@h; +show create user u6@h; +show create user u7@h; +error ER_PASSWORD_NO_MATCH; +show create user u8@h; +#grants don't work either +error ER_PASSWORD_NO_MATCH; +grant select on *.* to u1@h; +grant select on *.* to u2@h; +grant select on *.* to u3@h; +grant select on *.* to u4@h; +error ER_PASSWORD_NO_MATCH; +grant select on *.* to u5@h; +grant select on *.* to u6@h; +grant select on *.* to u7@h; +error ER_PASSWORD_NO_MATCH; +grant select on *.* to u8@h; +select user,select_priv,plugin,authentication_string from mysql.user where user like 'u_'; + +# but they still can be dropped +drop user u1@h, u2@h, u3@h, u4@h, u5@h, u6@h, u7@h, u8@h; diff --git a/mysql-test/main/grant_4332.result b/mysql-test/main/grant_4332.result index b62ca1a20cc..af6b23088f5 100644 --- a/mysql-test/main/grant_4332.result +++ b/mysql-test/main/grant_4332.result @@ -1,5 +1,5 @@ -set GLOBAL sql_mode=""; -set LOCAL sql_mode=""; +set global sql_mode=""; +set local sql_mode=""; alter table mysql.user modify User char(16) binary not null default ''; alter table mysql.db modify User char(16) binary not null default ''; alter table mysql.tables_priv modify User char(16) binary not null default ''; @@ -32,4 +32,4 @@ Catalog Database Table Table_alias Column Column_alias Type Length Max length Is def user() 253 141 14 N 1 39 8 user() root@localhost -set GLOBAL sql_mode=default; +set global sql_mode=default; diff --git a/mysql-test/main/grant_4332.test b/mysql-test/main/grant_4332.test index 41e0b822f98..f723e4afe44 100644 --- a/mysql-test/main/grant_4332.test +++ b/mysql-test/main/grant_4332.test @@ -6,8 +6,9 @@ # --source include/not_embedded.inc -set GLOBAL sql_mode=""; -set LOCAL sql_mode=""; +--source include/switch_to_mysql_user.inc +set global sql_mode=""; +set local sql_mode=""; alter table mysql.user modify User char(16) binary not null default ''; alter table mysql.db modify User char(16) binary not null default ''; @@ -42,4 +43,5 @@ flush privileges; select user(); --disable_metadata -set GLOBAL sql_mode=default; +set global sql_mode=default; +--source include/switch_to_mysql_global_priv.inc diff --git a/mysql-test/main/grant_lowercase.result b/mysql-test/main/grant_lowercase.result index d4a1667595e..a87f74721bc 100644 --- a/mysql-test/main/grant_lowercase.result +++ b/mysql-test/main/grant_lowercase.result @@ -9,17 +9,11 @@ connection default; disconnect conn1; drop user user1@localhost; call mtr.add_suppression("Incorrect database name"); -alter table mysql.host modify Db varchar(200); alter table mysql.db modify User char(16) default "", modify Db varchar(200) default ""; -insert mysql.host set db=concat('=>', repeat(_utf8 'й', 200)); -Warnings: -Warning 1265 Data truncated for column 'Db' at row 1 insert mysql.db set db=concat('=>', repeat(_utf8 'й', 200)); Warnings: Warning 1265 Data truncated for column 'Db' at row 1 flush privileges; -delete from mysql.host where db like '=>%'; delete from mysql.db where db like '=>%'; -alter table mysql.host modify Db char(64) default ""; alter table mysql.db modify Db char(64) default "", modify User char(80) default ""; flush privileges; diff --git a/mysql-test/main/grant_lowercase.test b/mysql-test/main/grant_lowercase.test index e31a72b890e..ffd1d4682a0 100644 --- a/mysql-test/main/grant_lowercase.test +++ b/mysql-test/main/grant_lowercase.test @@ -18,13 +18,9 @@ drop user user1@localhost; # in acl_load() call mtr.add_suppression("Incorrect database name"); -alter table mysql.host modify Db varchar(200); alter table mysql.db modify User char(16) default "", modify Db varchar(200) default ""; -insert mysql.host set db=concat('=>', repeat(_utf8 'й', 200)); insert mysql.db set db=concat('=>', repeat(_utf8 'й', 200)); flush privileges; # shouldn't crash here -delete from mysql.host where db like '=>%'; delete from mysql.db where db like '=>%'; -alter table mysql.host modify Db char(64) default ""; alter table mysql.db modify Db char(64) default "", modify User char(80) default ""; flush privileges; diff --git a/mysql-test/main/group_by.result b/mysql-test/main/group_by.result index a6da0e70247..f28068cc29a 100644 --- a/mysql-test/main/group_by.result +++ b/mysql-test/main/group_by.result @@ -536,17 +536,17 @@ a b select t1.a,t2.b from t1,t2 where t1.a=t2.a group by t1.a,t2.b ORDER BY NULL; a b 1 3 +1 1 3 1 2 2 -1 1 explain select t1.a,t2.b from t1,t2 where t1.a=t2.a group by t1.a,t2.b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort -1 SIMPLE t2 ALL a NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t2 ALL a NULL NULL NULL 4 Using temporary; Using filesort +1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join) explain select t1.a,t2.b from t1,t2 where t1.a=t2.a group by t1.a,t2.b ORDER BY NULL; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary -1 SIMPLE t2 ALL a NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t2 ALL a NULL NULL NULL 4 Using temporary +1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join) drop table t1,t2; create table t1 (a int, b int); insert into t1 values (1, 4),(10, 40),(1, 4),(10, 43),(1, 4),(10, 41),(1, 4),(10, 43),(1, 4); @@ -1330,6 +1330,7 @@ INSERT INTO t1 SELECT a + 64,b FROM t1; INSERT INTO t1 SELECT a + 128,b FROM t1 limit 16; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN SELECT a FROM t1 WHERE a < 2; id select_type table type possible_keys key key_len ref rows Extra @@ -2749,6 +2750,7 @@ create table t2 (c int, col1 int, key(c)); insert into t2 select t1.a, 100000 from t1; analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date explain select diff --git a/mysql-test/main/group_by_innodb.result b/mysql-test/main/group_by_innodb.result index 034866b63d5..f935d4da45b 100644 --- a/mysql-test/main/group_by_innodb.result +++ b/mysql-test/main/group_by_innodb.result @@ -151,6 +151,7 @@ KEY idx3 (a, b) INSERT INTO t1 (a, b) SELECT t01.a, t02.a FROM t0 t01, t0 t02; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN SELECT DISTINCT a, MAX(b) FROM t1 WHERE a >= 0 GROUP BY a,a; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result index cfdf9ef9865..a8e0762a823 100644 --- a/mysql-test/main/group_min_max.result +++ b/mysql-test/main/group_min_max.result @@ -40,6 +40,7 @@ create index idx_t1_1 on t1 (a1,a2,b,c); create index idx_t1_2 on t1 (a1,a2,b); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date drop table if exists t2; create table t2 ( @@ -68,6 +69,7 @@ create index idx_t2_1 on t2 (a1,a2,b,c); create index idx_t2_2 on t2 (a1,a2,b); analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date drop table if exists t3; create table t3 ( @@ -130,6 +132,7 @@ create index idx_t3_1 on t3 (a1,a2,b,c); create index idx_t3_2 on t3 (a1,a2,b); analyze table t3; Table Op Msg_type Msg_text +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status Table is already up to date explain select a1, min(a2) from t1 group by a1; id select_type table type possible_keys key key_len ref rows Extra @@ -684,10 +687,10 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range NULL idx_t1_1 147 NULL 9 Using where; Using index for group-by explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL idx_t2_1 163 NULL 5 Using where; Using index for group-by +1 SIMPLE t2 range NULL idx_t2_1 163 NULL 6 Using where; Using index for group-by explain select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL idx_t2_1 163 NULL 5 Using where; Using index for group-by +1 SIMPLE t2 range NULL idx_t2_1 163 NULL 6 Using where; Using index for group-by explain select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range NULL idx_t2_1 146 NULL 10 Using where; Using index for group-by @@ -804,10 +807,10 @@ b h212 e212 c h312 e312 explain select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL idx_t2_1 163 NULL 5 Using where; Using index for group-by +1 SIMPLE t2 range NULL idx_t2_1 163 NULL 6 Using where; Using index for group-by explain select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range NULL idx_t2_1 146 NULL 5 Using where; Using index for group-by +1 SIMPLE t2 range NULL idx_t2_1 146 NULL 6 Using where; Using index for group-by explain select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range NULL idx_t2_1 163 NULL 10 Using where; Using index for group-by @@ -1662,7 +1665,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by explain select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index NULL idx_t2_1 163 NULL # Using where; Using index +1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by explain select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by @@ -1713,7 +1716,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by explain extended select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 50.78 Using where; Using index +1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 0.39 Using where; Using index Warnings: Note 1003 select distinct `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`b` = 'a' and `test`.`t1`.`c` = 'i121' and `test`.`t1`.`a2` >= 'b' explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c'); @@ -1730,7 +1733,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by explain extended select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121'); id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 50.61 Using where; Using index +1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 0.28 Using where; Using index Warnings: Note 1003 select distinct `test`.`t2`.`a1` AS `a1`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where `test`.`t2`.`b` = 'a' and `test`.`t2`.`c` = 'i121' and `test`.`t2`.`a2` >= 'b' explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c'); @@ -1876,7 +1879,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by explain select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index NULL idx_t2_1 163 NULL # Using where; Using index +1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by @@ -2075,19 +2078,19 @@ id select_type table type possible_keys key key_len ref rows Extra explain extended select a1,a2,min(b),max(b) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 76 85.53 Using where; Using index +1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 76 100.00 Using where; Using index Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,min(`test`.`t1`.`b`) AS `min(b)`,max(`test`.`t1`.`b`) AS `max(b)` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`c` > 'a111' group by `test`.`t1`.`a1`,`test`.`t1`.`a2` explain extended select a1,a2,b,min(c),max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 50.78 Using where; Using temporary; Using filesort +1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 39.58 Using where; Using temporary; Using filesort Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,min(`test`.`t1`.`c`) AS `min(c)`,max(`test`.`t1`.`c`) AS `max(c)` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`d` > 'xy2' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b` explain extended select a1,a2,b,c from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 50.78 Using where; Using temporary; Using filesort +1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 128 39.58 Using where; Using temporary; Using filesort Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`d` > 'xy2' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`,`test`.`t1`.`c` explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1; @@ -2095,7 +2098,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index explain extended select a1,a2,b from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 76 85.53 Using where; Using index +1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 76 100.00 Using where; Using index Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`c` > 'a111' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b` explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1; @@ -2464,7 +2467,7 @@ FLUSH STATUS; INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a; SHOW STATUS LIKE 'handler_read__e%'; Variable_name Value -Handler_read_key 8 +Handler_read_key 13 Handler_read_next 0 Handler_read_retry 0 DELETE FROM t3; @@ -2634,7 +2637,7 @@ a b 3 13 explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ref a,index a 5 const 15 100.00 Using index; Using temporary +1 SIMPLE t1 ref a,index a 5 const 15 20.00 Using index; Using temporary Warnings: Note 1003 select sql_buffer_result `test`.`t1`.`a` AS `a`,max(`test`.`t1`.`b`) + 1 AS `max(b)+1` from `test`.`t1` where `test`.`t1`.`a` = 0 group by `test`.`t1`.`a` drop table t1; @@ -2719,6 +2722,7 @@ CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL, KEY (b)); INSERT INTO t1 VALUES(1,1),(2,1); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT 1 AS c, b FROM t1 WHERE b IN (1,2) GROUP BY c, b; c b @@ -3609,6 +3613,7 @@ CREATE TABLE t (a INT, b INT, KEY(a,b)); INSERT INTO t VALUES (1,1), (2,2), (3,3), (4,4), (1,0), (3,2), (4,5); ANALYZE TABLE t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK SELECT a, SUM(DISTINCT a), MIN(b) FROM t GROUP BY a; a SUM(DISTINCT a) MIN(b) diff --git a/mysql-test/main/group_min_max_innodb.result b/mysql-test/main/group_min_max_innodb.result index 311032bc453..02262d5649a 100644 --- a/mysql-test/main/group_min_max_innodb.result +++ b/mysql-test/main/group_min_max_innodb.result @@ -41,6 +41,7 @@ create index idx12672_1 on t4 (a1,a2,b,c); create index idx12672_2 on t4 (a1,a2,b); analyze table t4; Table Op Msg_type Msg_text +test.t4 analyze status Engine-independent statistics collected test.t4 analyze status OK select distinct a1 from t4 where pk_col not in (1,2,3,4); a1 diff --git a/mysql-test/main/handlersocket.result b/mysql-test/main/handlersocket.result index 1b3fc573548..8ef9b289cd0 100644 --- a/mysql-test/main/handlersocket.result +++ b/mysql-test/main/handlersocket.result @@ -5,7 +5,7 @@ plugin_version 1.0 plugin_status ACTIVE plugin_type DAEMON plugin_library handlersocket.so -plugin_library_version 1.13 +plugin_library_version 1.14 plugin_author higuchi dot akira at dena dot jp plugin_description Direct access into InnoDB plugin_license BSD diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result index f37cc48772e..a220068bc38 100644 --- a/mysql-test/main/having.result +++ b/mysql-test/main/having.result @@ -835,6 +835,7 @@ INSERT INTO t1 VALUES(10, 10), (11, 11), (12, 12), (12, 13),(14, 15), (15, 16), (16, 17), (17, 17); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT t, next_seq_value() r FROM t1 FORCE INDEX(t) GROUP BY t HAVING r = 1 ORDER BY t1.u; diff --git a/mysql-test/main/help.result b/mysql-test/main/help.result index 66850e75dc1..130aacf6644 100644 --- a/mysql-test/main/help.result +++ b/mysql-test/main/help.result @@ -255,10 +255,10 @@ help 'impossible_category_1'; source_category_name name is_it_category impossible_category_1 impossible_function_1 N impossible_category_1 impossible_function_2 N -alter table mysql.help_relation engine=myisam; -alter table mysql.help_keyword engine=myisam; -alter table mysql.help_topic engine=myisam; -alter table mysql.help_category engine=myisam; +alter table mysql.help_relation engine=aria; +alter table mysql.help_keyword engine=aria; +alter table mysql.help_topic engine=aria; +alter table mysql.help_category engine=aria; delete from mysql.help_topic where help_topic_id=@topic1_id; delete from mysql.help_topic where help_topic_id=@topic2_id; delete from mysql.help_topic where help_topic_id=@topic3_id; diff --git a/mysql-test/main/help.test b/mysql-test/main/help.test index 802f24f80a9..725eec2771f 100644 --- a/mysql-test/main/help.test +++ b/mysql-test/main/help.test @@ -98,10 +98,10 @@ help 'impossible_function_1'; help 'impossible_category_1'; ############## -alter table mysql.help_relation engine=myisam; -alter table mysql.help_keyword engine=myisam; -alter table mysql.help_topic engine=myisam; -alter table mysql.help_category engine=myisam; +alter table mysql.help_relation engine=aria; +alter table mysql.help_keyword engine=aria; +alter table mysql.help_topic engine=aria; +alter table mysql.help_category engine=aria; delete from mysql.help_topic where help_topic_id=@topic1_id; delete from mysql.help_topic where help_topic_id=@topic2_id; diff --git a/mysql-test/main/in_subq_cond_pushdown.result b/mysql-test/main/in_subq_cond_pushdown.result new file mode 100644 index 00000000000..06248895bd3 --- /dev/null +++ b/mysql-test/main/in_subq_cond_pushdown.result @@ -0,0 +1,3889 @@ +CREATE TABLE t1 (a INT, b INT, c INT, d INT); +CREATE TABLE t2 (e INT, f INT, g INT); +CREATE TABLE t3 (x INT, y INT); +INSERT INTO t1 VALUES +(1,1,18,1), (2,1,25,1), (1,3,40,1), (2,3,40,4), +(4,2,24,4), (3,2,23,1), (1,2,40,2), (3,4,17,2), +(5,5,65,1), (2,3,70,3), (1,4,35,3), (2,3,25,3), +(2,2,40,4), (1,4,55,1), (5,3,72,4), (1,2,70,5); +INSERT INTO t2 VALUES +(1,2,38), (2,3,15), (1,3,40), (1,4,35), +(2,2,70), (3,4,23), (5,5,12), (5,4,17), +(3,3,17), (4,2,24), (2,5,25), (5,1,65); +INSERT INTO t3 VALUES +(1,25), (1,18), (2,15), (4,24), +(1,35), (3,23), (3,17), (2,15); +CREATE VIEW v1 AS +( +SELECT t3.x AS v1_x, t3.y AS v1_y FROM t3 WHERE t3.x<=3 +); +CREATE VIEW v2 AS +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.e +HAVING max_g>25 +); +# conjunctive subformula : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.c<25 AND +(t1.a,t1.c) IN (SELECT t2.e,MAX(t2.g) FROM t2 WHERE t2.e<5 GROUP BY t2.e); +a b c d +4 2 24 4 +3 2 23 1 +SELECT * FROM t1 +WHERE t1.c<25 AND +(t1.a,t1.c) IN (SELECT t2.e,MAX(t2.g) FROM t2 WHERE t2.e<5 GROUP BY t2.e); +a b c d +4 2 24 4 +3 2 23 1 +EXPLAIN SELECT * FROM t1 +WHERE t1.c<25 AND +(t1.a,t1.c) IN (SELECT t2.e,MAX(t2.g) FROM t2 WHERE t2.e<5 GROUP BY t2.e); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.c<25 AND +(t1.a,t1.c) IN (SELECT t2.e,MAX(t2.g) FROM t2 WHERE t2.e<5 GROUP BY t2.e); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.c < 25 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` < 25", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# extracted AND formula : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.c>55 AND t1.b<4 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +2 3 70 3 +SELECT * FROM t1 +WHERE t1.c>55 AND t1.b<4 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE t1.c>55 AND t1.b<4 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.c>55 AND t1.b<4 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.c > 55 and t1.b < 4 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` > 55 and t2.f < 4", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# extracted OR formula : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.c>60 OR t1.c<25) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +4 2 24 4 +2 3 70 3 +SELECT * FROM t1 +WHERE (t1.c>60 OR t1.c<25) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +4 2 24 4 +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE (t1.c>60 OR t1.c<25) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.c>60 OR t1.c<25) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "(t1.c > 60 or t1.c < 25) and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` > 60 or `MAX(t2.g)` < 25", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# extracted AND-OR formula : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE ((t1.c>60 OR t1.c<25) AND t1.b>2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +2 3 70 3 +SELECT * FROM t1 +WHERE ((t1.c>60 OR t1.c<25) AND t1.b>2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE ((t1.c>60 OR t1.c<25) AND t1.b>2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE ((t1.c>60 OR t1.c<25) AND t1.b>2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "(t1.c > 60 or t1.c < 25) and t1.b > 2 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "(`MAX(t2.g)` > 60 or `MAX(t2.g)` < 25) and t2.f > 2", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# conjunctive subformula : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.d>3) AND t1.b>1) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +4 2 24 4 +1 2 40 2 +SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.d>3) AND t1.b>1) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +4 2 24 4 +1 2 40 2 +EXPLAIN SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.d>3) AND t1.b>1) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.d>3) AND t1.b>1) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "(t1.a < 2 or t1.d > 3) and t1.b > 1 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "t2.f > 1", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# using view IN subquery defINition : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.c>20 AND +(t1.a,t1.c) IN +( +SELECT v1_x,MAX(v1_y) +FROM v1 +WHERE v1_x>1 +GROUP BY v1_x +) +; +a b c d +3 2 23 1 +SELECT * FROM t1 +WHERE t1.c>20 AND +(t1.a,t1.c) IN +( +SELECT v1_x,MAX(v1_y) +FROM v1 +WHERE v1_x>1 +GROUP BY v1_x +) +; +a b c d +3 2 23 1 +EXPLAIN SELECT * FROM t1 +WHERE t1.c>20 AND +(t1.a,t1.c) IN +( +SELECT v1_x,MAX(v1_y) +FROM v1 +WHERE v1_x>1 +GROUP BY v1_x +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t3 ALL NULL NULL NULL NULL 8 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.c>20 AND +(t1.a,t1.c) IN +( +SELECT v1_x,MAX(v1_y) +FROM v1 +WHERE v1_x>1 +GROUP BY v1_x +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.c > 20 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["v1_x", "MAX(v1_y)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "`MAX(v1_y)` > 20", + "temporary_table": { + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows": 8, + "filtered": 100, + "attached_condition": "t3.x > 1 and t3.x <= 3" + } + } + } + } + } + } +} +# using equality : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1,v1 +WHERE t1.c>20 AND t1.c=v1_y AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d v1_x v1_y +3 2 23 1 3 23 +SELECT * FROM t1,v1 +WHERE t1.c>20 AND t1.c=v1_y AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d v1_x v1_y +3 2 23 1 3 23 +EXPLAIN SELECT * FROM t1,v1 +WHERE t1.c>20 AND t1.c=v1_y AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where; Using join buffer (flat, BNL join) +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t3.y 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1,v1 +WHERE t1.c>20 AND t1.c=v1_y AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows": 8, + "filtered": 100, + "attached_condition": "t3.y > 20 and t3.x <= 3 and t3.y is not null" + }, + "block-nl-join": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100 + }, + "buffer_type": "flat", + "buffer_size": "256Kb", + "join_type": "BNL", + "attached_condition": "t1.c = t3.y and t1.a is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t3.y"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` > 20", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.a<2 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 3 40 1 +1 2 40 2 +SELECT * FROM t1 +WHERE t1.a<2 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 3 40 1 +1 2 40 2 +EXPLAIN SELECT * FROM t1 +WHERE t1.a<2 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.a<2 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a < 2 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e < 2" + } + } + } + } + } + } +} +# extracted AND formula : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.a>2 AND t1.a<5 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +4 2 24 4 +3 2 23 1 +SELECT * FROM t1 +WHERE t1.a>2 AND t1.a<5 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +4 2 24 4 +3 2 23 1 +EXPLAIN SELECT * FROM t1 +WHERE t1.a>2 AND t1.a<5 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.a>2 AND t1.a<5 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a > 2 and t1.a < 5 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e > 2 and t2.e < 5" + } + } + } + } + } + } +} +# extracted OR formula : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.a<2 OR t1.a>=4) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 3 40 1 +4 2 24 4 +1 2 40 2 +SELECT * FROM t1 +WHERE (t1.a<2 OR t1.a>=4) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 3 40 1 +4 2 24 4 +1 2 40 2 +EXPLAIN SELECT * FROM t1 +WHERE (t1.a<2 OR t1.a>=4) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.a<2 OR t1.a>=4) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "(t1.a < 2 or t1.a >= 4) and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and (t2.e < 2 or t2.e >= 4)" + } + } + } + } + } + } +} +# extracted AND-OR formula : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +1 4 35 3 +SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +1 4 35 3 +EXPLAIN SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "(t1.a < 2 or t1.a = 5) and t1.b > 3 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and (t2.e < 2 or t2.e = 5) and t2.f > 3" + } + } + } + } + } + } +} +# extracted AND-OR formula : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +1 4 35 3 +SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +1 4 35 3 +EXPLAIN SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "(t1.a < 2 or t1.a = 5) and t1.b > 3 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and (t2.e < 2 or t2.e = 5) and t2.f > 3" + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE ((t1.b<3 OR t1.d>2) AND t1.a<2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 2 40 2 +SELECT * FROM t1 +WHERE ((t1.b<3 OR t1.d>2) AND t1.a<2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 2 40 2 +EXPLAIN SELECT * FROM t1 +WHERE ((t1.b<3 OR t1.d>2) AND t1.a<2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE ((t1.b<3 OR t1.d>2) AND t1.a<2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "(t1.b < 3 or t1.d > 2) and t1.a < 2 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e < 2" + } + } + } + } + } + } +} +# using equalities : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.d=1 AND t1.a=t1.d AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 3 40 1 +SELECT * FROM t1 +WHERE t1.d=1 AND t1.a=t1.d AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 3 40 1 +EXPLAIN SELECT * FROM t1 +WHERE t1.d=1 AND t1.a=t1.d AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 const,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.d=1 AND t1.a=t1.d AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a = 1 and t1.d = 1 and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["const", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e = 1" + } + } + } + } + } +} +# using equality : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.d>1 AND t1.a=t1.d AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +4 2 24 4 +SELECT * FROM t1 +WHERE t1.d>1 AND t1.a=t1.d AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +4 2 24 4 +EXPLAIN SELECT * FROM t1 +WHERE t1.d>1 AND t1.a=t1.d AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.d>1 AND t1.a=t1.d AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.d = t1.a and t1.a > 1 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e > 1" + } + } + } + } + } + } +} +# using view IN subquery definition : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.a<3 AND +(t1.a,t1.c) IN +( +SELECT v1_x,MAX(v1_y) +FROM v1 +WHERE v1_x>1 +GROUP BY v1_x +) +; +a b c d +SELECT * FROM t1 +WHERE t1.a<3 AND +(t1.a,t1.c) IN +( +SELECT v1_x,MAX(v1_y) +FROM v1 +WHERE v1_x>1 +GROUP BY v1_x +) +; +a b c d +EXPLAIN SELECT * FROM t1 +WHERE t1.a<3 AND +(t1.a,t1.c) IN +( +SELECT v1_x,MAX(v1_y) +FROM v1 +WHERE v1_x>1 +GROUP BY v1_x +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t3 ALL NULL NULL NULL NULL 8 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.a<3 AND +(t1.a,t1.c) IN +( +SELECT v1_x,MAX(v1_y) +FROM v1 +WHERE v1_x>1 +GROUP BY v1_x +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a < 3 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["v1_x", "MAX(v1_y)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows": 8, + "filtered": 100, + "attached_condition": "t3.x > 1 and t3.x <= 3 and t3.x < 3" + } + } + } + } + } + } +} +# using equality : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1,v1 +WHERE t1.a=v1_x AND v1_x<2 AND v1_y>30 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d v1_x v1_y +1 3 40 1 1 35 +1 2 40 2 1 35 +SELECT * FROM t1,v1 +WHERE t1.a=v1_x AND v1_x<2 AND v1_y>30 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d v1_x v1_y +1 3 40 1 1 35 +1 2 40 2 1 35 +EXPLAIN SELECT * FROM t1,v1 +WHERE t1.a=v1_x AND v1_x<2 AND v1_y>30 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where; Using join buffer (flat, BNL join) +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t3.x,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1,v1 +WHERE t1.a=v1_x AND v1_x<2 AND v1_y>30 AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows": 8, + "filtered": 100, + "attached_condition": "t3.x < 2 and t3.y > 30 and t3.x <= 3 and t3.x is not null" + }, + "block-nl-join": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100 + }, + "buffer_type": "flat", + "buffer_size": "256Kb", + "join_type": "BNL", + "attached_condition": "t1.a = t3.x and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t3.x", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e <= 3" + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE +# extracted OR formula : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE ((t1.b<3 OR t1.b=4) AND t1.a<3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 2 40 2 +SELECT * FROM t1 +WHERE ((t1.b<3 OR t1.b=4) AND t1.a<3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 2 40 2 +EXPLAIN SELECT * FROM t1 +WHERE ((t1.b<3 OR t1.b=4) AND t1.a<3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE ((t1.b<3 OR t1.b=4) AND t1.a<3) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "(t1.b < 3 or t1.b = 4) and t1.a < 3 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "t2.f < 3 or t2.f = 4", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e < 3" + } + } + } + } + } + } +} +# conjunctive subformula using addition : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.a+t1.c>41) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +2 3 70 3 +SELECT * FROM t1 +WHERE (t1.a+t1.c>41) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE (t1.a+t1.c>41) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.a+t1.c>41) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a + t1.c > 41 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "t2.e + `MAX(t2.g)` > 41", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# conjunctive subformula using substitution : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.c-t1.a<35) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +4 2 24 4 +3 2 23 1 +SELECT * FROM t1 +WHERE (t1.c-t1.a<35) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +4 2 24 4 +3 2 23 1 +EXPLAIN SELECT * FROM t1 +WHERE (t1.c-t1.a<35) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.c-t1.a<35) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.c - t1.a < 35 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` - t2.e < 35", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# conjunctive subformula using multiplication : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.c*t1.a>100) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +2 3 70 3 +SELECT * FROM t1 +WHERE (t1.c*t1.a>100) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE (t1.c*t1.a>100) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.c*t1.a>100) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.c * t1.a > 100 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` * t2.e > 100", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# conjunctive subformula using division : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.c/t1.a>30) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 3 40 1 +1 2 40 2 +2 3 70 3 +SELECT * FROM t1 +WHERE (t1.c/t1.a>30) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 3 40 1 +1 2 40 2 +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE (t1.c/t1.a>30) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.c/t1.a>30) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.c / t1.a > 30 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` / t2.e > 30", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# conjunctive subformula using BETWEEN : pushing into HAVING +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.c BETWEEN 50 AND 100) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +2 3 70 3 +SELECT * FROM t1 +WHERE (t1.c BETWEEN 50 AND 100) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE (t1.c BETWEEN 50 AND 100) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.c BETWEEN 50 AND 100) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.c between 50 and 100 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` between 50 and 100", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } +} +# conjunctive subformula using addition : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.a+t1.b > 5) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +4 2 24 4 +SELECT * FROM t1 +WHERE (t1.a+t1.b > 5) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +4 2 24 4 +EXPLAIN SELECT * FROM t1 +WHERE (t1.a+t1.b > 5) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.a+t1.b > 5) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a + t1.b > 5 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e + t2.f > 5" + } + } + } + } + } + } +} +# conjunctive subformula using substitution : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.a-t1.b > 0) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +4 2 24 4 +SELECT * FROM t1 +WHERE (t1.a-t1.b > 0) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +4 2 24 4 +EXPLAIN SELECT * FROM t1 +WHERE (t1.a-t1.b > 0) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.a-t1.b > 0) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a - t1.b > 0 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e - t2.f > 0" + } + } + } + } + } + } +} +# conjunctive subformula using multiplication : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.a*t1.b > 6) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +4 2 24 4 +SELECT * FROM t1 +WHERE (t1.a*t1.b > 6) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +4 2 24 4 +EXPLAIN SELECT * FROM t1 +WHERE (t1.a*t1.b > 6) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.a*t1.b > 6) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a * t1.b > 6 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e * t2.f > 6" + } + } + } + } + } + } +} +# conjunctive subformula using division : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.b/t1.a > 2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +1 3 40 1 +1 4 35 3 +SELECT * FROM t1 +WHERE (t1.b/t1.a > 2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +a b c d +1 3 40 1 +1 4 35 3 +EXPLAIN SELECT * FROM t1 +WHERE (t1.b/t1.a > 2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.b/t1.a > 2) AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e,t2.f +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.b / t1.a > 2 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.f / t2.e > 2" + } + } + } + } + } + } +} +# conjunctive subformula using BETWEEN : pushing into WHERE +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.a BETWEEN 1 AND 3) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 3 40 1 +3 2 23 1 +1 2 40 2 +2 3 70 3 +SELECT * FROM t1 +WHERE (t1.a BETWEEN 1 AND 3) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +a b c d +1 3 40 1 +3 2 23 1 +1 2 40 2 +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE (t1.a BETWEEN 1 AND 3) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.a BETWEEN 1 AND 3) AND +(t1.a,t1.c) IN +( +SELECT t2.e,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a between 1 and 3 and t1.a is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["e", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e between 1 and 3" + } + } + } + } + } + } +} +# conjunctive subformula : pushing into HAVING of the IN subquery +# conjunctive subformula : pushing into WHERE of the view from the IN subquery +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.c>3 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +a b c d +1 2 40 2 +2 3 70 3 +SELECT * FROM t1 +WHERE t1.c>3 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +a b c d +1 2 40 2 +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE t1.c>3 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 12 Using where; Using temporary +3 DERIVED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary; Using filesort +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.c>3 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.c > 3 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "MAX(v2.f)", "max_g"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "v2.max_g > 3", + "temporary_table": { + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "v2.e < 5", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25", + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } + } + } + } + } + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE of the IN subquery +# conjunctive subformula : pushing into WHERE of the view +# from the IN subquery +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +a b c d +2 3 70 3 +SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +a b c d +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 12 Using where; Using temporary +3 DERIVED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary; Using filesort +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a > 1 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "MAX(v2.f)", "max_g"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "v2.e < 5 and v2.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25", + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e > 1" + } + } + } + } + } + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE and HAVING +# of the IN subquery +# conjunctive subformula : pushing into WHERE of the view +# from the IN subquery +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.a>1 AND t1.c<100 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +a b c d +2 3 70 3 +SELECT * FROM t1 +WHERE t1.a>1 AND t1.c<100 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +a b c d +2 3 70 3 +EXPLAIN SELECT * FROM t1 +WHERE t1.a>1 AND t1.c<100 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 12 Using where; Using temporary +3 DERIVED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary; Using filesort +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.a>1 AND t1.c<100 AND +(t1.a,t1.b,t1.c) IN +( +SELECT v2.e,MAX(v2.f),v2.max_g +FROM v2 +WHERE v2.e<5 +GROUP BY v2.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a > 1 and t1.c < 100 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "MAX(v2.f)", "max_g"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "having_condition": "v2.max_g < 100", + "temporary_table": { + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "v2.e < 5 and v2.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25", + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e > 1" + } + } + } + } + } + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE of the IN subquery +# extracted AND formula : pushing into HAVING of the derived table +# from the IN subquery +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +a b c d +2 3 40 4 +SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +a b c d +2 3 40 4 +EXPLAIN SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 12 Using where; Using temporary +3 DERIVED t2 ALL NULL NULL NULL NULL 12 Using temporary; Using filesort +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a > 1 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "MAX(d_tab.f)", "max_g"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "d_tab.e < 5 and d_tab.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25 and t2.e < 5 and t2.e > 1", + "filesort": { + "sort_key": "t2.f", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100 + } + } + } + } + } + } + } + } + } + } + } +} +# conjunctive subformula : pushing into HAVING of the derived table +# conjunctive subformula : pushing into WHERE of the IN subquery from +# the derived table +SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.e<5 +GROUP BY t2.e +) +GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.b>2; +x y a b max_c +2 15 2 3 70 +2 15 2 3 70 +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +a b c d +2 3 40 4 +SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +a b c d +2 3 40 4 +EXPLAIN SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 12 Using where; Using temporary +3 DERIVED t2 ALL NULL NULL NULL NULL 12 Using temporary; Using filesort +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a > 1 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "MAX(d_tab.f)", "max_g"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "d_tab.e < 5 and d_tab.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25 and t2.e < 5 and t2.e > 1", + "filesort": { + "sort_key": "t2.f", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100 + } + } + } + } + } + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE of the derived table +# extracted AND formula : pushing into WHERE of the IN subquery from +# the derived table +SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +GROUP BY t2.e +HAVING t2.f<5 +) +GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5; +x y a b max_c +2 15 2 3 70 +4 24 4 2 24 +2 15 2 3 70 +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +a b c d +2 3 40 4 +SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +a b c d +2 3 40 4 +EXPLAIN SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 12 Using where; Using temporary +3 DERIVED t2 ALL NULL NULL NULL NULL 12 Using temporary; Using filesort +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g +FROM +( +SELECT t2.e, t2.f, MAX(t2.g) AS max_g +FROM t2 +GROUP BY t2.f +HAVING max_g>25 +) as d_tab +WHERE d_tab.e<5 +GROUP BY d_tab.e +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a > 1 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "MAX(d_tab.f)", "max_g"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "<derived3>", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "d_tab.e < 5 and d_tab.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25 and t2.e < 5 and t2.e > 1", + "filesort": { + "sort_key": "t2.f", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100 + } + } + } + } + } + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE and HAVING +# of the derived table +# extracted AND formula : pushing into WHERE of the IN subquery +# from the derived table +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +GROUP BY t2.e +HAVING t2.f<5 +) +GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70; +x y a b max_c +4 24 4 2 24 +SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +GROUP BY t2.e +HAVING t2.f<5 +) +GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70; +x y a b max_c +4 24 4 2 24 +EXPLAIN SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +GROUP BY t2.e +HAVING t2.f<5 +) +GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where +1 PRIMARY <derived2> ref key0 key0 5 test.t3.x 2 Using where +2 DERIVED t1 ALL NULL NULL NULL NULL 16 Using where; Using temporary; Using filesort +2 DERIVED <subquery3> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +GROUP BY t2.e +HAVING t2.f<5 +) +GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows": 8, + "filtered": 100, + "attached_condition": "t3.x < 5 and t3.x is not null" + }, + "table": { + "table_name": "<derived2>", + "access_type": "ref", + "possible_keys": ["key0"], + "key": "key0", + "key_length": "5", + "used_key_parts": ["a"], + "ref": ["test.t3.x"], + "rows": 2, + "filtered": 100, + "attached_condition": "d_tab.max_c < 70", + "materialized": { + "query_block": { + "select_id": 2, + "having_condition": "max_c < 70", + "filesort": { + "sort_key": "t1.a", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a > 1 and t1.a < 5 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery3>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 3, + "having_condition": "t2.f < 5", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e > 1 and t2.e < 5" + } + } + } + } + } + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE of the derived table +# conjunctive subformula : pushing into HAVING of the IN subquery from +# the derived table +SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE (t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +WHERE t2.f<4 +GROUP BY t2.f +) +GROUP BY t1.a +HAVING t1.b<5 +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5; +x y a b max_c +1 25 1 2 70 +1 18 1 2 70 +2 15 2 3 40 +1 35 1 2 70 +2 15 2 3 40 +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +GROUP BY t2.e +HAVING t2.f<5 +) +GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70; +x y a b max_c +4 24 4 2 24 +SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +GROUP BY t2.e +HAVING t2.f<5 +) +GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70; +x y a b max_c +4 24 4 2 24 +EXPLAIN SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +GROUP BY t2.e +HAVING t2.f<5 +) +GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where +1 PRIMARY <derived2> ref key0 key0 5 test.t3.x 2 Using where +2 DERIVED t1 ALL NULL NULL NULL NULL 16 Using where; Using temporary; Using filesort +2 DERIVED <subquery3> eq_ref distinct_key distinct_key 12 test.t1.a,test.t1.b,test.t1.c 1 +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * +FROM t3, +( +SELECT t1.a,t1.b,max(t1.c) as max_c +FROM t1 +WHERE t1.a>1 AND +(t1.a,t1.b,t1.c) IN +( +SELECT t2.e,t2.f,MAX(t2.g) +FROM t2 +GROUP BY t2.e +HAVING t2.f<5 +) +GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows": 8, + "filtered": 100, + "attached_condition": "t3.x < 5 and t3.x is not null" + }, + "table": { + "table_name": "<derived2>", + "access_type": "ref", + "possible_keys": ["key0"], + "key": "key0", + "key_length": "5", + "used_key_parts": ["a"], + "ref": ["test.t3.x"], + "rows": 2, + "filtered": 100, + "attached_condition": "d_tab.max_c < 70", + "materialized": { + "query_block": { + "select_id": 2, + "having_condition": "max_c < 70", + "filesort": { + "sort_key": "t1.a", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.a > 1 and t1.a < 5 and t1.a is not null and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery3>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["e", "f", "MAX(t2.g)"], + "ref": ["test.t1.a", "test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 3, + "having_condition": "t2.f < 5", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e > 1 and t2.e < 5" + } + } + } + } + } + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE +# using WINDOW FUNCTIONS : using MAX function +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.b>1) AND +(t1.b, t1.c) IN +( +SELECT t2.f, MAX(t2.g) OVER (PARTITION BY t2.f) +FROM t2 +WHERE t2.e<5 +) +; +a b c d +1 3 40 1 +2 3 40 4 +1 4 35 3 +1 2 70 5 +SELECT * FROM t1 +WHERE (t1.b>1) AND +(t1.b, t1.c) IN +( +SELECT t2.f, MAX(t2.g) OVER (PARTITION BY t2.f) +FROM t2 +WHERE t2.e<5 +) +; +a b c d +1 3 40 1 +2 3 40 4 +1 4 35 3 +1 2 70 5 +EXPLAIN SELECT * FROM t1 +WHERE (t1.b>1) AND +(t1.b, t1.c) IN +( +SELECT t2.f, MAX(t2.g) OVER (PARTITION BY t2.f) +FROM t2 +WHERE t2.e<5 +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.b,test.t1.c 1 +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.b>1) AND +(t1.b, t1.c) IN +( +SELECT t2.f, MAX(t2.g) OVER (PARTITION BY t2.f) +FROM t2 +WHERE t2.e<5 +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.b > 1 and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "8", + "used_key_parts": ["f", "MAX(t2.g) OVER (PARTITION BY t2.f)"], + "ref": ["test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "window_functions_computation": { + "sorts": { + "filesort": { + "sort_key": "t2.f" + } + }, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.f > 1" + } + } + } + } + } + } + } +} +# conjunctive subformula : pushing into WHERE +# using WINDOW FUNCTIONS : using SUM function +SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR SELECT * FROM t1 +WHERE (t1.b>1) AND +(t1.b, t1.c) IN +( +SELECT t2.f, CAST(SUM(t2.g) OVER (PARTITION BY t2.f) AS INT) +FROM t2 +WHERE t2.e<5 +) +; +a b c d +5 3 72 4 +SELECT * FROM t1 +WHERE (t1.b>1) AND +(t1.b, t1.c) IN +( +SELECT t2.f, CAST(SUM(t2.g) OVER (PARTITION BY t2.f) AS INT) +FROM t2 +WHERE t2.e<5 +) +; +a b c d +5 3 72 4 +EXPLAIN SELECT * FROM t1 +WHERE (t1.b>1) AND +(t1.b, t1.c) IN +( +SELECT t2.f, CAST(SUM(t2.g) OVER (PARTITION BY t2.f) AS INT) +FROM t2 +WHERE t2.e<5 +) +; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 16 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 12 test.t1.b,test.t1.c 1 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 12 Using where; Using temporary +EXPLAIN FORMAT=JSON SELECT * FROM t1 +WHERE (t1.b>1) AND +(t1.b, t1.c) IN +( +SELECT t2.f, CAST(SUM(t2.g) OVER (PARTITION BY t2.f) AS INT) +FROM t2 +WHERE t2.e<5 +) +; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 16, + "filtered": 100, + "attached_condition": "t1.b > 1 and t1.b is not null and t1.c is not null" + }, + "table": { + "table_name": "<subquery2>", + "access_type": "eq_ref", + "possible_keys": ["distinct_key"], + "key": "distinct_key", + "key_length": "12", + "used_key_parts": ["f", "CAST(SUM(t2.g) OVER (PARTITION BY t2.f) AS INT)"], + "ref": ["test.t1.b", "test.t1.c"], + "rows": 1, + "filtered": 100, + "attached_condition": "t1.c = `<subquery2>`.`CAST(SUM(t2.g) OVER (PARTITION BY t2.f) AS INT)`", + "materialized": { + "unique": 1, + "query_block": { + "select_id": 2, + "window_functions_computation": { + "sorts": { + "filesort": { + "sort_key": "t2.f" + } + }, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.f > 1" + } + } + } + } + } + } + } +} +DROP TABLE t1,t2,t3; +DROP VIEW v1,v2; +# +# MDEV-16721: IN-subquery defined with the AUTO-INCREMENT column +# and used with the ZEROFILL column +# +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY); +CREATE TABLE t2 (b INT ZEROFILL); +INSERT INTO t2 VALUES (2), (3); +SELECT * +FROM t2 +WHERE t2.b IN (SELECT MIN(t1.a) from t1); +b +DROP TABLE t1, t2; +# +# MDEV-16730: server fault caused by pushdown into the derived table +# condition that joins IN subquery and parent select +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2), (3); +SELECT * +FROM (SELECT DISTINCT * FROM t1) AS tbl +WHERE tbl.a IN +( +SELECT COUNT(t1.a) +FROM t1 +WHERE (t1.a!=1) +); +a +2 +DROP TABLE t1; +# +# MDEV-16727: failure assertion caused by the lamely saved list +# of multiple equalities +# +CREATE TABLE t1 (a varchar(1)); +INSERT INTO `t1` VALUES ('x'), ('y'), ('z'); +CREATE TABLE t2 (b varchar(1)); +INSERT INTO t2 VALUES ('x'); +CREATE TABLE t3 (c varchar(1)); +INSERT INTO t3 VALUES ('y'); +CREATE TABLE t4 (d varchar(1)); +INSERT INTO t4 VALUES ('x'), ('z'); +SELECT * FROM t1 +JOIN t2 ON (t1.a=t2.b) +LEFT JOIN t3 ON (t1.a=t3.c) +WHERE (t1.a) IN +( +SELECT t4.d +FROM t4 +ORDER BY t4.d +); +a b c +x x NULL +DROP TABLE t1,t2,t3,t4; +# +# MDEV-17360: IN subquery predicate with outer reference in the left part +# that refers to a field of a mergeable derived table +# +CREATE TABLE t1 (id1 int) ENGINE=MYISAM; +INSERT INTO t1 VALUES (1814),(0),(NULL),(1); +CREATE TABLE t2 (id2 int) ENGINE=MYISAM; +SELECT 1 AS r FROM t2,t1,(SELECT * FROM t1) dt1 +WHERE NOT EXISTS (SELECT id2 FROM t2 +WHERE dt1.id1 IN (SELECT t2.id2 FROM t2 +HAVING t2.id2 >= 1)); +r +DROP TABLE t1,t2; +# +# MDEV-17027: IN subquery predicate with outer reference in the left part +# conjuncted with equality predicate +# +CREATE TABLE t1 (pk int, i1 int, v1 varchar(1)); +INSERT INTO t1 VALUES (3,2,'x'), (1,1,'y'), (4,2,'z'); +CREATE TABLE t2 (pk int, i1 int, v1 varchar(1)); +INSERT INTO t2 VALUES (5,2,'x'), (7,1,'x'); +CREATE TABLE t3 (pk int, i1 int, v1 varchar(1)); +INSERT INTO t3 VALUES (8,2,'x'), (7,1,'z'); +SELECT t3.i1 FROM t3 +WHERE EXISTS ( SELECT t2.v1 FROM t1,t2 +WHERE t1.v1 = t2.v1 AND +t3.i1 IN (SELECT t.i1 FROM t1 as t +GROUP BY i1 HAVING t.i1 < 3)); +i1 +2 +1 +DROP TABLE t1,t2,t3; diff --git a/mysql-test/main/in_subq_cond_pushdown.test b/mysql-test/main/in_subq_cond_pushdown.test new file mode 100644 index 00000000000..2482fd91103 --- /dev/null +++ b/mysql-test/main/in_subq_cond_pushdown.test @@ -0,0 +1,862 @@ +LET $no_pushdown= + SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR; + +CREATE TABLE t1 (a INT, b INT, c INT, d INT); +CREATE TABLE t2 (e INT, f INT, g INT); +CREATE TABLE t3 (x INT, y INT); + +INSERT INTO t1 VALUES +(1,1,18,1), (2,1,25,1), (1,3,40,1), (2,3,40,4), +(4,2,24,4), (3,2,23,1), (1,2,40,2), (3,4,17,2), +(5,5,65,1), (2,3,70,3), (1,4,35,3), (2,3,25,3), +(2,2,40,4), (1,4,55,1), (5,3,72,4), (1,2,70,5); + +INSERT INTO t2 VALUES +(1,2,38), (2,3,15), (1,3,40), (1,4,35), +(2,2,70), (3,4,23), (5,5,12), (5,4,17), +(3,3,17), (4,2,24), (2,5,25), (5,1,65); + +INSERT INTO t3 VALUES +(1,25), (1,18), (2,15), (4,24), +(1,35), (3,23), (3,17), (2,15); + +CREATE VIEW v1 AS +( + SELECT t3.x AS v1_x, t3.y AS v1_y FROM t3 WHERE t3.x<=3 +); + +CREATE VIEW v2 AS +( + SELECT t2.e, t2.f, MAX(t2.g) AS max_g + FROM t2 + GROUP BY t2.e + HAVING max_g>25 +); + +--echo # conjunctive subformula : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE t1.c<25 AND + (t1.a,t1.c) IN (SELECT t2.e,MAX(t2.g) FROM t2 WHERE t2.e<5 GROUP BY t2.e); + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # extracted AND formula : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE t1.c>55 AND t1.b<4 AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # extracted OR formula : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE (t1.c>60 OR t1.c<25) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # extracted AND-OR formula : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE ((t1.c>60 OR t1.c<25) AND t1.b>2) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.d>3) AND t1.b>1) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # using view IN subquery defINition : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE t1.c>20 AND + (t1.a,t1.c) IN + ( + SELECT v1_x,MAX(v1_y) + FROM v1 + WHERE v1_x>1 + GROUP BY v1_x + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # using equality : pushing into WHERE +LET $query= +SELECT * FROM t1,v1 +WHERE t1.c>20 AND t1.c=v1_y AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE t1.a<2 AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # extracted AND formula : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE t1.a>2 AND t1.a<5 AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # extracted OR formula : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE (t1.a<2 OR t1.a>=4) AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # extracted AND-OR formula : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e,t2.f + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # extracted AND-OR formula : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e,t2.f + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE ((t1.b<3 OR t1.d>2) AND t1.a<2) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # using equalities : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE t1.d=1 AND t1.a=t1.d AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # using equality : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE t1.d>1 AND t1.a=t1.d AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # using view IN subquery definition : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE t1.a<3 AND + (t1.a,t1.c) IN + ( + SELECT v1_x,MAX(v1_y) + FROM v1 + WHERE v1_x>1 + GROUP BY v1_x + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # using equality : pushing into WHERE +LET $query= +SELECT * FROM t1,v1 +WHERE t1.a=v1_x AND v1_x<2 AND v1_y>30 AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE +--echo # extracted OR formula : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE ((t1.b<3 OR t1.b=4) AND t1.a<3) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula using addition : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE (t1.a+t1.c>41) AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula using substitution : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE (t1.c-t1.a<35) AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula using multiplication : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE (t1.c*t1.a>100) AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula using division : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE (t1.c/t1.a>30) AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula using BETWEEN : pushing into HAVING +LET $query= +SELECT * FROM t1 +WHERE (t1.c BETWEEN 50 AND 100) AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula using addition : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE (t1.a+t1.b > 5) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e,t2.f + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula using substitution : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE (t1.a-t1.b > 0) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e,t2.f + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula using multiplication : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE (t1.a*t1.b > 6) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e,t2.f + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula using division : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE (t1.b/t1.a > 2) AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e,t2.f + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula using BETWEEN : pushing into WHERE +LET $query= +SELECT * FROM t1 +WHERE (t1.a BETWEEN 1 AND 3) AND + (t1.a,t1.c) IN + ( + SELECT t2.e,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into HAVING of the IN subquery +--echo # conjunctive subformula : pushing into WHERE of the view from the IN subquery +LET $query= +SELECT * FROM t1 +WHERE t1.c>3 AND + (t1.a,t1.b,t1.c) IN + ( + SELECT v2.e,MAX(v2.f),v2.max_g + FROM v2 + WHERE v2.e<5 + GROUP BY v2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE of the IN subquery +--echo # conjunctive subformula : pushing into WHERE of the view +--echo # from the IN subquery +LET $query= +SELECT * FROM t1 +WHERE t1.a>1 AND + (t1.a,t1.b,t1.c) IN + ( + SELECT v2.e,MAX(v2.f),v2.max_g + FROM v2 + WHERE v2.e<5 + GROUP BY v2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE and HAVING +--echo # of the IN subquery +--echo # conjunctive subformula : pushing into WHERE of the view +--echo # from the IN subquery +LET $query= +SELECT * FROM t1 +WHERE t1.a>1 AND t1.c<100 AND + (t1.a,t1.b,t1.c) IN + ( + SELECT v2.e,MAX(v2.f),v2.max_g + FROM v2 + WHERE v2.e<5 + GROUP BY v2.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE of the IN subquery +--echo # extracted AND formula : pushing into HAVING of the derived table +--echo # from the IN subquery +LET $query= +SELECT * FROM t1 +WHERE t1.a>1 AND + (t1.a,t1.b,t1.c) IN + ( + SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g + FROM + ( + SELECT t2.e, t2.f, MAX(t2.g) AS max_g + FROM t2 + GROUP BY t2.f + HAVING max_g>25 + ) as d_tab + WHERE d_tab.e<5 + GROUP BY d_tab.e + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into HAVING of the derived table +--echo # conjunctive subformula : pushing into WHERE of the IN subquery from +--echo # the derived table +SELECT * +FROM t3, +( + SELECT t1.a,t1.b,max(t1.c) as max_c + FROM t1 + WHERE t1.a>1 AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.e<5 + GROUP BY t2.e + ) + GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.b>2; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE of the derived table +--echo # extracted AND formula : pushing into WHERE of the IN subquery from +--echo # the derived table +SELECT * +FROM t3, +( + SELECT t1.a,t1.b,max(t1.c) as max_c + FROM t1 + WHERE t1.a>1 AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + GROUP BY t2.e + HAVING t2.f<5 + ) + GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE and HAVING +--echo # of the derived table +--echo # extracted AND formula : pushing into WHERE of the IN subquery +--echo # from the derived table +LET $query= +SELECT * +FROM t3, +( + SELECT t1.a,t1.b,max(t1.c) as max_c + FROM t1 + WHERE t1.a>1 AND + (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + GROUP BY t2.e + HAVING t2.f<5 + ) + GROUP BY t1.a +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE of the derived table +--echo # conjunctive subformula : pushing into HAVING of the IN subquery from +--echo # the derived table +SELECT * +FROM t3, +( + SELECT t1.a,t1.b,max(t1.c) as max_c + FROM t1 + WHERE (t1.a,t1.b,t1.c) IN + ( + SELECT t2.e,t2.f,MAX(t2.g) + FROM t2 + WHERE t2.f<4 + GROUP BY t2.f + ) + GROUP BY t1.a + HAVING t1.b<5 +) AS d_tab +WHERE d_tab.a=t3.x AND d_tab.a<5; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE +--echo # using WINDOW FUNCTIONS : using MAX function +LET $query= +SELECT * FROM t1 +WHERE (t1.b>1) AND + (t1.b, t1.c) IN + ( + SELECT t2.f, MAX(t2.g) OVER (PARTITION BY t2.f) + FROM t2 + WHERE t2.e<5 + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +--echo # conjunctive subformula : pushing into WHERE +--echo # using WINDOW FUNCTIONS : using SUM function +LET $query= +SELECT * FROM t1 +WHERE (t1.b>1) AND + (t1.b, t1.c) IN + ( + SELECT t2.f, CAST(SUM(t2.g) OVER (PARTITION BY t2.f) AS INT) + FROM t2 + WHERE t2.e<5 + ) +; + +EVAL $no_pushdown $query; +EVAL $query; +EVAL EXPLAIN $query; +EVAL EXPLAIN FORMAT=JSON $query; + +DROP TABLE t1,t2,t3; +DROP VIEW v1,v2; + +--echo # +--echo # MDEV-16721: IN-subquery defined with the AUTO-INCREMENT column +--echo # and used with the ZEROFILL column +--echo # + +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY); +CREATE TABLE t2 (b INT ZEROFILL); + +INSERT INTO t2 VALUES (2), (3); + +SELECT * +FROM t2 +WHERE t2.b IN (SELECT MIN(t1.a) from t1); + +DROP TABLE t1, t2; + +--echo # +--echo # MDEV-16730: server fault caused by pushdown into the derived table +--echo # condition that joins IN subquery and parent select +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2), (3); + +SELECT * +FROM (SELECT DISTINCT * FROM t1) AS tbl +WHERE tbl.a IN +( + SELECT COUNT(t1.a) + FROM t1 + WHERE (t1.a!=1) +); + +DROP TABLE t1; + +--echo # +--echo # MDEV-16727: failure assertion caused by the lamely saved list +--echo # of multiple equalities +--echo # + +CREATE TABLE t1 (a varchar(1)); +INSERT INTO `t1` VALUES ('x'), ('y'), ('z'); + +CREATE TABLE t2 (b varchar(1)); +INSERT INTO t2 VALUES ('x'); + +CREATE TABLE t3 (c varchar(1)); +INSERT INTO t3 VALUES ('y'); + +CREATE TABLE t4 (d varchar(1)); +INSERT INTO t4 VALUES ('x'), ('z'); + +SELECT * FROM t1 +JOIN t2 ON (t1.a=t2.b) +LEFT JOIN t3 ON (t1.a=t3.c) +WHERE (t1.a) IN +( + SELECT t4.d + FROM t4 + ORDER BY t4.d +); + +DROP TABLE t1,t2,t3,t4; + +--echo # +--echo # MDEV-17360: IN subquery predicate with outer reference in the left part +--echo # that refers to a field of a mergeable derived table +--echo # + +CREATE TABLE t1 (id1 int) ENGINE=MYISAM; +INSERT INTO t1 VALUES (1814),(0),(NULL),(1); + +CREATE TABLE t2 (id2 int) ENGINE=MYISAM; + +SELECT 1 AS r FROM t2,t1,(SELECT * FROM t1) dt1 + WHERE NOT EXISTS (SELECT id2 FROM t2 + WHERE dt1.id1 IN (SELECT t2.id2 FROM t2 + HAVING t2.id2 >= 1)); + +DROP TABLE t1,t2; + +--echo # +--echo # MDEV-17027: IN subquery predicate with outer reference in the left part +--echo # conjuncted with equality predicate +--echo # + +CREATE TABLE t1 (pk int, i1 int, v1 varchar(1)); +INSERT INTO t1 VALUES (3,2,'x'), (1,1,'y'), (4,2,'z'); + +CREATE TABLE t2 (pk int, i1 int, v1 varchar(1)); +INSERT INTO t2 VALUES (5,2,'x'), (7,1,'x'); + +CREATE TABLE t3 (pk int, i1 int, v1 varchar(1)); +INSERT INTO t3 VALUES (8,2,'x'), (7,1,'z'); + +SELECT t3.i1 FROM t3 + WHERE EXISTS ( SELECT t2.v1 FROM t1,t2 + WHERE t1.v1 = t2.v1 AND + t3.i1 IN (SELECT t.i1 FROM t1 as t + GROUP BY i1 HAVING t.i1 < 3)); + +DROP TABLE t1,t2,t3; diff --git a/mysql-test/main/index_merge_innodb.result b/mysql-test/main/index_merge_innodb.result index 6a3ea839535..3ba21b5fb85 100644 --- a/mysql-test/main/index_merge_innodb.result +++ b/mysql-test/main/index_merge_innodb.result @@ -106,6 +106,7 @@ insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b) select key1a, key1b, key2a, key2b, key3a, key3b from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select count(*) from t1; count(*) @@ -313,6 +314,7 @@ alter table t1 add index i3(key3); update t1 set key2=key1,key3=key1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select * from t1 where (key3 > 30 and key3<35) or (key2 >32 and key2 < 40); id select_type table type possible_keys key key_len ref rows Extra @@ -699,8 +701,8 @@ SELECT COUNT(*) FROM (SELECT * FROM t1 FORCE INDEX(primary,idx) WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6145 -2 DERIVED t1 index_merge PRIMARY,idx idx,PRIMARY 5,4 NULL 6145 Using sort_union(idx,PRIMARY); Using where +1 PRIMARY <derived2> ALL NULL NULL NULL NULL # +2 DERIVED t1 index_merge PRIMARY,idx idx,PRIMARY 5,4 NULL # Using sort_union(idx,PRIMARY); Using where SELECT COUNT(*) FROM (SELECT * FROM t1 FORCE INDEX(primary,idx) WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t; diff --git a/mysql-test/main/index_merge_innodb.test b/mysql-test/main/index_merge_innodb.test index 53ce3114b49..4b75ddaa0f2 100644 --- a/mysql-test/main/index_merge_innodb.test +++ b/mysql-test/main/index_merge_innodb.test @@ -72,6 +72,7 @@ set optimizer_switch='derived_merge=off,derived_with_keys=off'; # We have to use FORCE INDEX here as Innodb gives inconsistent estimates # which causes different query plans. +--replace_column 9 # EXPLAIN SELECT COUNT(*) FROM (SELECT * FROM t1 FORCE INDEX(primary,idx) diff --git a/mysql-test/main/index_merge_myisam.result b/mysql-test/main/index_merge_myisam.result index 725a888c914..0438d0e564c 100644 --- a/mysql-test/main/index_merge_myisam.result +++ b/mysql-test/main/index_merge_myisam.result @@ -18,6 +18,7 @@ alter table t0 add key8 int not null, add index i8(key8); update t0 set key2=key1,key3=key1,key4=key1,key5=key1,key6=key1,key7=key1,key8=1024-key1; analyze table t0; Table Op Msg_type Msg_text +test.t0 analyze status Engine-independent statistics collected test.t0 analyze status OK explain select * from t0 where key1 < 3 or key1 > 1020; id select_type table type possible_keys key key_len ref rows Extra @@ -944,6 +945,7 @@ insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b) select key1a, key1b, key2a, key2b, key3a, key3b from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select count(*) from t1; count(*) @@ -1151,6 +1153,7 @@ alter table t1 add index i3(key3); update t1 set key2=key1,key3=key1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select * from t1 where (key3 > 30 and key3<35) or (key2 >32 and key2 < 40); id select_type table type possible_keys key key_len ref rows Extra @@ -1745,6 +1748,7 @@ alter table t0 add key8 int not null, add index i8(key8); update t0 set key2=key1,key3=key1,key8=1024-key1; analyze table t0; Table Op Msg_type Msg_text +test.t0 analyze status Engine-independent statistics collected test.t0 analyze status OK set @optimizer_switch_save=@@optimizer_switch; set optimizer_switch='derived_merge=off,derived_with_keys=off'; diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result index 83f987b78db..b76d9f64a9f 100644 --- a/mysql-test/main/information_schema.result +++ b/mysql-test/main/information_schema.result @@ -96,12 +96,12 @@ db event func general_log +global_priv gtid_slave_pos help_category help_keyword help_relation help_topic -host index_stats plugin proc @@ -564,6 +564,7 @@ create view v2 (c) as select a from t1 WITH LOCAL CHECK OPTION; create view v3 (c) as select a from t1 WITH CASCADED CHECK OPTION; select * from information_schema.views; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME VIEW_DEFINITION CHECK_OPTION IS_UPDATABLE DEFINER SECURITY_TYPE CHARACTER_SET_CLIENT COLLATION_CONNECTION ALGORITHM +def mysql user select `mysql`.`global_priv`.`Host` AS `Host`,`mysql`.`global_priv`.`User` AS `User`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.plugin') in ('mysql_native_password','mysql_old_password'),ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.authentication_string'),''),'') AS `Password`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 1,'Y','N') AS `Select_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 2,'Y','N') AS `Insert_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 4,'Y','N') AS `Update_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 8,'Y','N') AS `Delete_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 16,'Y','N') AS `Create_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 32,'Y','N') AS `Drop_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 64,'Y','N') AS `Reload_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 128,'Y','N') AS `Shutdown_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 256,'Y','N') AS `Process_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 512,'Y','N') AS `File_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 1024,'Y','N') AS `Grant_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 2048,'Y','N') AS `References_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 4096,'Y','N') AS `Index_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 8192,'Y','N') AS `Alter_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 16384,'Y','N') AS `Show_db_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 32768,'Y','N') AS `Super_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 65536,'Y','N') AS `Create_tmp_table_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 131072,'Y','N') AS `Lock_tables_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 262144,'Y','N') AS `Execute_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 524288,'Y','N') AS `Repl_slave_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 1048576,'Y','N') AS `Repl_client_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 2097152,'Y','N') AS `Create_view_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 4194304,'Y','N') AS `Show_view_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 8388608,'Y','N') AS `Create_routine_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 16777216,'Y','N') AS `Alter_routine_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 33554432,'Y','N') AS `Create_user_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 67108864,'Y','N') AS `Event_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 134217728,'Y','N') AS `Trigger_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 268435456,'Y','N') AS `Create_tablespace_priv`,if(json_value(`mysql`.`global_priv`.`Priv`,'$.access') & 536870912,'Y','N') AS `Delete_history_priv`,elt(ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.ssl_type'),0) + 1,'','ANY','X509','SPECIFIED') AS `ssl_type`,ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.ssl_cipher'),'') AS `ssl_cipher`,ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.x509_issuer'),'') AS `x509_issuer`,ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.x509_subject'),'') AS `x509_subject`,cast(ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.max_questions'),0) as unsigned) AS `max_questions`,cast(ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.max_updates'),0) as unsigned) AS `max_updates`,cast(ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.max_connections'),0) as unsigned) AS `max_connections`,cast(ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.max_user_connections'),0) as signed) AS `max_user_connections`,ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.plugin'),'') AS `plugin`,ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.authentication_string'),'') AS `authentication_string`,'N' AS `password_expired`,elt(ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.is_role'),0) + 1,'N','Y') AS `is_role`,ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.default_role'),'') AS `default_role`,cast(ifnull(json_value(`mysql`.`global_priv`.`Priv`,'$.max_statement_time'),0.0) as decimal(12,6)) AS `max_statement_time` from `mysql`.`global_priv` NONE YES root@localhost DEFINER latin1 latin1_swedish_ci UNDEFINED def test v1 select `test`.`t1`.`a` AS `c` from `test`.`t1` CASCADED YES root@localhost DEFINER latin1 latin1_swedish_ci UNDEFINED def test v2 select `test`.`t1`.`a` AS `c` from `test`.`t1` LOCAL YES root@localhost DEFINER latin1 latin1_swedish_ci UNDEFINED def test v3 select `test`.`t1`.`a` AS `c` from `test`.`t1` CASCADED YES root@localhost DEFINER latin1 latin1_swedish_ci UNDEFINED @@ -594,6 +595,7 @@ information_schema.tables; s1 10 11 +NULL drop table t1; SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets; Table Create Table @@ -665,7 +667,7 @@ proc body longblob proc definer char(141) proc created timestamp proc modified timestamp -proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') +proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') proc comment text proc character_set_client char(32) proc collation_connection char(32) @@ -825,7 +827,7 @@ NULL select table_type from information_schema.tables where table_schema="mysql" and table_name="user"; table_type -BASE TABLE +VIEW show open tables where `table` like "user"; Database Table In_use Name_locked mysql user 0 0 @@ -875,6 +877,14 @@ information_schema SYSTEM_VARIABLES ENUM_VALUE_LIST information_schema TRIGGERS ACTION_CONDITION information_schema TRIGGERS ACTION_STATEMENT information_schema VIEWS VIEW_DEFINITION +mysql global_priv Priv +mysql user Password +mysql user ssl_cipher +mysql user x509_issuer +mysql user x509_subject +mysql user plugin +mysql user authentication_string +mysql user default_role select table_name, column_name, data_type from information_schema.columns where data_type = 'datetime' and table_name not like 'innodb_%' order by binary table_name, ordinal_position; @@ -1254,7 +1264,7 @@ CREATE VIEW v1 AS SELECT 1 FROM t1 WHERE f3 = (SELECT func2 ()); SELECT func1(); func1() -1 +2 DROP TABLE t1; DROP VIEW v1; DROP FUNCTION func1; @@ -1405,6 +1415,7 @@ create table t2 (f1 int, f2 int); create view v2 as select f1+1 as a, f2 as b from t2; select table_name, is_updatable from information_schema.views order by table_name; table_name is_updatable +user YES v1 NO v2 YES delete from v1; @@ -1958,8 +1969,9 @@ lock table t1 read; connect con1, localhost, root,,; connection con1; flush tables; +flush tables t1; connection default; -select * from information_schema.views; +select * from information_schema.views where table_schema='test'; TABLE_CATALOG def TABLE_SCHEMA test TABLE_NAME v1 diff --git a/mysql-test/main/information_schema.test b/mysql-test/main/information_schema.test index 2b318f5f1aa..95b6f253058 100644 --- a/mysql-test/main/information_schema.test +++ b/mysql-test/main/information_schema.test @@ -1622,15 +1622,16 @@ alter table t1 change b c int; lock table t1 read; connect(con1, localhost, root,,); connection con1; -send flush tables; +flush tables; +send flush tables t1; connection default; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" and - info = "flush tables"; + where state = "Waiting for table metadata lock" and + info = "flush tables t1"; --source include/wait_condition.inc --vertical_results -select * from information_schema.views; +select * from information_schema.views where table_schema='test'; --horizontal_results unlock tables; diff --git a/mysql-test/main/information_schema_db.result b/mysql-test/main/information_schema_db.result index 45ade65c502..0d98a10050d 100644 --- a/mysql-test/main/information_schema_db.result +++ b/mysql-test/main/information_schema_db.result @@ -26,6 +26,8 @@ declare ret_val int; select max(f1) from t1 into ret_val; return ret_val; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create view v1 as select f1 from t1 where f1 = func1(f1); create function func2() returns int return 1; use mbase; diff --git a/mysql-test/main/init_file_set_password-7656.result b/mysql-test/main/init_file_set_password-7656.result index e5b3fc75706..fba65b036fd 100644 --- a/mysql-test/main/init_file_set_password-7656.result +++ b/mysql-test/main/init_file_set_password-7656.result @@ -1,8 +1,8 @@ create user foo@localhost; select user,host,password from mysql.user where user='foo'; -user host password +User Host Password foo localhost -select user,host,password from mysql.user where user='foo'; -user host password -foo localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 +select user,host,password,plugin,authentication_string from mysql.user where user='foo'; +User Host Password plugin authentication_string +foo localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 mysql_native_password *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 drop user foo@localhost; diff --git a/mysql-test/main/init_file_set_password-7656.test b/mysql-test/main/init_file_set_password-7656.test index ecee3924355..c695d01b675 100644 --- a/mysql-test/main/init_file_set_password-7656.test +++ b/mysql-test/main/init_file_set_password-7656.test @@ -21,6 +21,6 @@ EOF --exec echo "restart:--init-file=$MYSQLTEST_VARDIR/init.file " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --source include/wait_until_connected_again.inc -select user,host,password from mysql.user where user='foo'; +select user,host,password,plugin,authentication_string from mysql.user where user='foo'; drop user foo@localhost; diff --git a/mysql-test/main/innodb_ext_key.result b/mysql-test/main/innodb_ext_key.result index c55e8d138f8..f9210bd168c 100644 --- a/mysql-test/main/innodb_ext_key.result +++ b/mysql-test/main/innodb_ext_key.result @@ -872,7 +872,9 @@ alter table t3 add primary key (pk1, pk2); alter table t3 add key (col1, col2); analyze table t1,t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK set optimizer_switch='extended_keys=off'; explain @@ -1171,7 +1173,7 @@ EXPLAIN "key_length": "3070", "used_key_parts": ["f2", "pk1"], "rows": 1, - "filtered": 100, + "filtered": 50, "index_condition": "t1.pk1 <= 5 and t1.pk2 <= 5 and t1.f2 = 'abc'", "attached_condition": "t1.f1 <= '3'" } @@ -1201,7 +1203,7 @@ EXPLAIN "key_length": "3011", "used_key_parts": ["pk1", "f2", "pk2"], "rows": 1, - "filtered": 100, + "filtered": 50, "index_condition": "t1.f2 <= 5 and t1.pk2 <= 5 and t1.pk1 = 'abc'", "attached_condition": "t1.f1 <= '3'" } diff --git a/mysql-test/main/innodb_icp.result b/mysql-test/main/innodb_icp.result index 9ba98ba5b13..00ca6b144ad 100644 --- a/mysql-test/main/innodb_icp.result +++ b/mysql-test/main/innodb_icp.result @@ -679,8 +679,8 @@ EXPLAIN SELECT t1.b, t1.c FROM t1, t2 WHERE t1.a = t2.a AND t1.b != 0 HAVING t1.c != 5 ORDER BY t1.c; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where; Using filesort -1 SIMPLE t2 ref a a 515 test.t1.a 1 Using where +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where; Using temporary; Using filesort +1 SIMPLE t2 ALL a NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join) SELECT t1.b, t1.c FROM t1, t2 WHERE t1.a = t2.a AND t1.b != 0 HAVING t1.c != 5 ORDER BY t1.c; b c @@ -690,8 +690,8 @@ EXPLAIN SELECT t1.b, t1.c FROM t1, t2 WHERE t1.a = t2.a AND t1.b != 0 HAVING t1.c != 5 ORDER BY t1.c; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where; Using filesort -1 SIMPLE t2 ref a a 515 test.t1.a 1 Using where +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where; Using temporary; Using filesort +1 SIMPLE t2 ALL a NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join) SELECT t1.b, t1.c FROM t1, t2 WHERE t1.a = t2.a AND t1.b != 0 HAVING t1.c != 5 ORDER BY t1.c; b c diff --git a/mysql-test/main/innodb_mysql_lock2.result b/mysql-test/main/innodb_mysql_lock2.result index df97b32a41c..608cbec88c5 100644 --- a/mysql-test/main/innodb_mysql_lock2.result +++ b/mysql-test/main/innodb_mysql_lock2.result @@ -57,6 +57,8 @@ declare j int; select i from t1 where i = 1 into j; return j; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f2() returns int begin declare k int; @@ -64,6 +66,8 @@ select i from t1 where i = 1 into k; insert into t2 values (k + 5); return 0; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f3() returns int begin return (select i from t1 where i = 3); @@ -87,12 +91,16 @@ declare k int; select i from v1 where i = 1 into k; return k; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f7() returns int begin declare k int; select j from v2 where j = 1 into k; return k; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f8() returns int begin declare k int; @@ -100,6 +108,8 @@ select i from v1 where i = 1 into k; insert into t2 values (k+5); return k; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f9() returns int begin update v2 set j=j+10 where j=1; @@ -129,6 +139,8 @@ create procedure p2(inout p int) begin select i from t1 where i = 1 into p; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f14() returns int begin declare k int; @@ -148,6 +160,8 @@ declare k int; select i from t1 where i=1 into k; set new.l= k+1; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create trigger t4_bu before update on t4 for each row begin if (select i from t1 where i=1) then diff --git a/mysql-test/main/intersect.result b/mysql-test/main/intersect.result index 66c7addfd36..5c7e9dfc6f6 100644 --- a/mysql-test/main/intersect.result +++ b/mysql-test/main/intersect.result @@ -37,7 +37,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 4 INTERSECT t3 ALL NULL NULL NULL NULL 3 100.00 NULL INTERSECT RESULT <intersect2,3,4> ALL NULL NULL NULL NULL NULL NULL Warnings: -Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `a` +Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `a` EXPLAIN format=json (select a,b from t1) intersect (select c,d from t2) intersect (select e,f from t3); EXPLAIN { @@ -278,7 +278,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 3 INTERSECT t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join) NULL INTERSECT RESULT <intersect2,3> ALL NULL NULL NULL NULL NULL NULL Warnings: -Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from ((/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t3`.`e` AS `e` from `test`.`t2` join `test`.`t3`)) `a` +Note 1003 /* select#1 */ select `a`.`a` AS `a`,`a`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` intersect (/* select#3 */ select `test`.`t2`.`c` AS `c`,`test`.`t3`.`e` AS `e` from `test`.`t2` join `test`.`t3`)) `a` EXPLAIN format=json (select a,b from t1) intersect (select c,e from t2,t3); EXPLAIN { @@ -497,7 +497,7 @@ a 1 1 (select 1 from dual into @v) intersect (select 1 from dual); -ERROR HY000: Incorrect usage of INTERSECT and INTO +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'into @v) intersect (select 1 from dual)' at line 1 select 1 from dual ORDER BY 1 intersect select 1 from dual; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'intersect select 1 from dual' at line 1 select 1 as a from dual union all select 1 from dual; @@ -505,7 +505,7 @@ a 1 1 select 1 from dual intersect all select 1 from dual; -ERROR HY000: Incorrect usage of INTERSECT and ALL +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'all select 1 from dual' at line 1 create table t1 (a int, b blob, a1 int, b1 blob); create table t2 (c int, d blob, c1 int, d1 blob); insert into t1 values (1,"ddd", 1, "sdfrrwwww"),(2, "fgh", 2, "dffggtt"); @@ -599,14 +599,14 @@ explain extended (select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 -3 UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 +5 UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 -4 INTERSECT t3 ALL NULL NULL NULL NULL 2 100.00 -NULL INTERSECT RESULT <intersect2,4> ALL NULL NULL NULL NULL NULL NULL -5 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used -NULL UNION RESULT <union1,3,5> ALL NULL NULL NULL NULL NULL NULL +3 INTERSECT t3 ALL NULL NULL NULL NULL 2 100.00 +NULL INTERSECT RESULT <intersect2,3> ALL NULL NULL NULL NULL NULL NULL +4 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used +NULL UNION RESULT <union1,5,4> ALL NULL NULL NULL NULL NULL NULL Warnings: -Note 1003 (/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union /* select#3 */ select `__3`.`c` AS `c`,`__3`.`d` AS `d` from ((/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#4 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__3` union (/* select#5 */ select 4 AS `4`,4 AS `4`) +Note 1003 (/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union /* select#5 */ select `__5`.`c` AS `c`,`__5`.`d` AS `d` from ((/* select#2 */ select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (/* select#3 */ select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__5` union (/* select#4 */ select 4 AS `4`,4 AS `4`) set SQL_MODE=ORACLE; (select a,b from t1) union (select c,d from t2) intersect (select e,f from t3) union (select 4,4); a b @@ -720,7 +720,7 @@ a b drop procedure p1; show create view v1; View Create View character_set_client collation_connection -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union select `__3`.`c` AS `c`,`__3`.`d` AS `d` from ((select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2`) intersect (select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__3` union (select 4 AS `4`,4 AS `4`) latin1 latin1_swedish_ci +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS (select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) union select `__6`.`c` AS `c`,`__6`.`d` AS `d` from (select `test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` intersect (select `test`.`t3`.`e` AS `e`,`test`.`t3`.`f` AS `f` from `test`.`t3`)) `__6` union (select 4 AS `4`,4 AS `4`) latin1 latin1_swedish_ci drop view v1; drop tables t1,t2,t3; # diff --git a/mysql-test/main/intersect.test b/mysql-test/main/intersect.test index fb5e991a24c..0a68cab21f0 100644 --- a/mysql-test/main/intersect.test +++ b/mysql-test/main/intersect.test @@ -59,13 +59,13 @@ drop tables t1,t2,t3; select 1 as a from dual intersect select 1 from dual; (select 1 from dual) intersect (select 1 from dual); ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR (select 1 from dual into @v) intersect (select 1 from dual); --error ER_PARSE_ERROR select 1 from dual ORDER BY 1 intersect select 1 from dual; select 1 as a from dual union all select 1 from dual; ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR select 1 from dual intersect all select 1 from dual; diff --git a/mysql-test/main/invisible_field.result b/mysql-test/main/invisible_field.result index 876a80814e5..36e62645ef2 100644 --- a/mysql-test/main/invisible_field.result +++ b/mysql-test/main/invisible_field.result @@ -404,8 +404,8 @@ b int(11) YES NULL c int(11) YES NULL explain select * from t1,t2 where t1.b = t2.c and t1.c = t2.b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 10 -1 SIMPLE t1 ALL b,c NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t1 ALL b,c NULL NULL NULL 10 +1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) select * from t1,t2 where t1.b = t2.c and t1.c = t2.b; a a b c 1 1 1 1 @@ -559,6 +559,8 @@ DROP TABLE t1; create or replace table t1 (a int, b int invisible); insert into t1 values (1),(2); select * from t1 into outfile 'f'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead load data infile 'f' into table t1; select a,b from t1; a b @@ -589,6 +591,8 @@ a b truncate table t1; insert into t1(a,b) values (1,1),(2,2); select a,b from t1 into outfile 'a'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead load data infile 'a' into table t1(a,b); select a,b from t1; a b diff --git a/mysql-test/main/join.result b/mysql-test/main/join.result index cc8e174c8e6..7918cb173e9 100644 --- a/mysql-test/main/join.result +++ b/mysql-test/main/join.result @@ -260,8 +260,8 @@ PRIMARY KEY (id) INSERT INTO t2 VALUES (1,'s1'),(2,'s2'),(3,'s3'),(4,'s4'),(5,'s5'); select t1.*, t2.* from t1, t2 where t2.id=t1.t2_id limit 2; t1_id t2_id type cost_unit min_value max_value t3_id item_id id name -22 1 Percent Cost 100 -1 6 291 1 s1 -23 1 Percent Cost 100 -1 21 291 1 s1 +12 5 Percent Cost -1 0 -1 -1 5 s5 +14 4 Percent Cost -1 0 -1 -1 4 s4 drop table t1,t2; CREATE TABLE t1 ( siteid varchar(25) NOT NULL default '', @@ -755,10 +755,10 @@ ERROR 42S22: Unknown column 't1.b' in 'on clause' select statistics.TABLE_NAME, statistics.COLUMN_NAME, statistics.TABLE_CATALOG, statistics.TABLE_SCHEMA, statistics.NON_UNIQUE, statistics.INDEX_SCHEMA, statistics.INDEX_NAME, statistics.SEQ_IN_INDEX, statistics.COLLATION, statistics.SUB_PART, statistics.PACKED, statistics.NULLABLE, statistics.INDEX_TYPE, statistics.COMMENT, columns.TABLE_CATALOG, columns.TABLE_SCHEMA, columns.COLUMN_DEFAULT, columns.IS_NULLABLE, columns.DATA_TYPE, columns.CHARACTER_MAXIMUM_LENGTH, columns.CHARACTER_OCTET_LENGTH, columns.NUMERIC_PRECISION, columns.NUMERIC_SCALE, columns.CHARACTER_SET_NAME, columns.COLLATION_NAME, columns.COLUMN_TYPE, columns.COLUMN_KEY, columns.EXTRA, columns.COLUMN_COMMENT -from information_schema.statistics join information_schema.columns using(table_name,column_name) where table_name='user'; +from information_schema.statistics join information_schema.columns using(table_name,column_name) where table_name='global_priv'; TABLE_NAME COLUMN_NAME TABLE_CATALOG TABLE_SCHEMA NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLLATION SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT TABLE_CATALOG TABLE_SCHEMA COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA COLUMN_COMMENT -user Host def mysql 0 mysql PRIMARY 1 A NULL NULL BTREE def mysql '' NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI -user User def mysql 0 mysql PRIMARY 2 A NULL NULL BTREE def mysql '' NO char 80 240 NULL NULL utf8 utf8_bin char(80) PRI +global_priv Host def mysql 0 mysql PRIMARY 1 A NULL NULL BTREE def mysql '' NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI +global_priv User def mysql 0 mysql PRIMARY 2 A NULL NULL BTREE def mysql '' NO char 80 240 NULL NULL utf8 utf8_bin char(80) PRI Warnings: Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' @@ -1484,7 +1484,7 @@ DROP TABLE t1,t2,t3,t4,t5; # MDEV-4752: Segfault during parsing of illegal query # SELECT * FROM t5 JOIN (t1 JOIN t2 UNION SELECT * FROM t3 JOIN t4); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM t3 JOIN t4)' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT * FROM t3 JOIN t4)' at line 1 # # MDEV-4959: join of const table with NULL fields # diff --git a/mysql-test/main/join.test b/mysql-test/main/join.test index 3d2a02e2346..a6cf2dcc217 100644 --- a/mysql-test/main/join.test +++ b/mysql-test/main/join.test @@ -555,7 +555,7 @@ select * from v1a join v1b on t1.b = t2.b; select statistics.TABLE_NAME, statistics.COLUMN_NAME, statistics.TABLE_CATALOG, statistics.TABLE_SCHEMA, statistics.NON_UNIQUE, statistics.INDEX_SCHEMA, statistics.INDEX_NAME, statistics.SEQ_IN_INDEX, statistics.COLLATION, statistics.SUB_PART, statistics.PACKED, statistics.NULLABLE, statistics.INDEX_TYPE, statistics.COMMENT, columns.TABLE_CATALOG, columns.TABLE_SCHEMA, columns.COLUMN_DEFAULT, columns.IS_NULLABLE, columns.DATA_TYPE, columns.CHARACTER_MAXIMUM_LENGTH, columns.CHARACTER_OCTET_LENGTH, columns.NUMERIC_PRECISION, columns.NUMERIC_SCALE, columns.CHARACTER_SET_NAME, columns.COLLATION_NAME, columns.COLUMN_TYPE, columns.COLUMN_KEY, columns.EXTRA, columns.COLUMN_COMMENT - from information_schema.statistics join information_schema.columns using(table_name,column_name) where table_name='user'; + from information_schema.statistics join information_schema.columns using(table_name,column_name) where table_name='global_priv'; drop table t1; drop table t2; diff --git a/mysql-test/main/join_cache.result b/mysql-test/main/join_cache.result index fde6e0fec6b..dcada9b60e2 100644 --- a/mysql-test/main/join_cache.result +++ b/mysql-test/main/join_cache.result @@ -79,9 +79,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where +1 SIMPLE City ALL NULL NULL NULL NULL 4079 Using where +1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where; Using join buffer (flat, BNL join) 1 SIMPLE CountryLanguage ALL NULL NULL NULL NULL 984 Using where; Using join buffer (flat, BNL join) -1 SIMPLE City ALL NULL NULL NULL NULL 4079 Using where; Using join buffer (flat, BNL join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -157,9 +157,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where -1 SIMPLE CountryLanguage ALL NULL NULL NULL NULL 984 Using where; Using join buffer (flat, BNL join) -1 SIMPLE City ALL NULL NULL NULL NULL 4079 Using where; Using join buffer (incremental, BNL join) +1 SIMPLE City ALL NULL NULL NULL NULL 4079 Using where +1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where; Using join buffer (flat, BNL join) +1 SIMPLE CountryLanguage ALL NULL NULL NULL NULL 984 Using where; Using join buffer (incremental, BNL join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -236,8 +236,8 @@ CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where -1 SIMPLE CountryLanguage hash_ALL NULL #hash#$hj 3 world.Country.Code 984 Using where; Using join buffer (flat, BNLH join) 1 SIMPLE City hash_ALL NULL #hash#$hj 3 world.Country.Code 4079 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE CountryLanguage hash_ALL NULL #hash#$hj 3 world.Country.Code 984 Using where; Using join buffer (flat, BNLH join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -314,8 +314,8 @@ CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where -1 SIMPLE CountryLanguage hash_ALL NULL #hash#$hj 3 world.Country.Code 984 Using where; Using join buffer (flat, BNLH join) -1 SIMPLE City hash_ALL NULL #hash#$hj 3 world.Country.Code 4079 Using where; Using join buffer (incremental, BNLH join) +1 SIMPLE City hash_ALL NULL #hash#$hj 3 world.Country.Code 4079 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE CountryLanguage hash_ALL NULL #hash#$hj 3 world.Country.Code 984 Using where; Using join buffer (incremental, BNLH join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -402,7 +402,7 @@ ON City.Country=Country.Code AND City.Population > 5000000 WHERE Country.Name LIKE 'C%' AND Country.Population > 10000000; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where -1 SIMPLE City hash_range City_Population #hash#$hj:City_Population 3:4 world.Country.Code 25 Using where; Rowid-ordered scan; Using join buffer (flat, BNLH join) +1 SIMPLE City range City_Population City_Population 4 NULL 25 Using where; Rowid-ordered scan; Using join buffer (flat, BNL join) SELECT Country.Name, Country.Population, City.Name, City.Population FROM Country LEFT JOIN City ON City.Country=Country.Code AND City.Population > 5000000 @@ -497,9 +497,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where +1 SIMPLE City ALL NULL NULL NULL NULL 4079 Using where 1 SIMPLE CountryLanguage ALL NULL NULL NULL NULL 984 Using where; Using join buffer (flat, BNL join) -1 SIMPLE City ALL NULL NULL NULL NULL 4079 Using where; Using join buffer (flat, BNL join) +1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where; Using join buffer (flat, BNL join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -575,9 +575,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where +1 SIMPLE City ALL NULL NULL NULL NULL 4079 Using where 1 SIMPLE CountryLanguage ALL NULL NULL NULL NULL 984 Using where; Using join buffer (flat, BNL join) -1 SIMPLE City ALL NULL NULL NULL NULL 4079 Using where; Using join buffer (incremental, BNL join) +1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where; Using join buffer (incremental, BNL join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -653,9 +653,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where -1 SIMPLE CountryLanguage hash_ALL NULL #hash#$hj 3 world.Country.Code 984 Using where; Using join buffer (flat, BNLH join) -1 SIMPLE City hash_ALL NULL #hash#$hj 3 world.Country.Code 4079 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE City ALL NULL NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage hash_ALL NULL #hash#$hj 3 world.City.Country 984 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE Country hash_ALL NULL #hash#$hj 3 world.City.Country 239 Using where; Using join buffer (flat, BNLH join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -731,9 +731,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE Country ALL NULL NULL NULL NULL 239 Using where -1 SIMPLE CountryLanguage hash_ALL NULL #hash#$hj 3 world.Country.Code 984 Using where; Using join buffer (flat, BNLH join) -1 SIMPLE City hash_ALL NULL #hash#$hj 3 world.Country.Code 4079 Using where; Using join buffer (incremental, BNLH join) +1 SIMPLE City ALL NULL NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage hash_ALL NULL #hash#$hj 3 world.City.Country 984 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE Country hash_ALL NULL #hash#$hj 3 world.City.Country 239 Using where; Using join buffer (incremental, BNLH join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -848,9 +848,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country hash_ALL PRIMARY #hash#PRIMARY 3 world.CountryLanguage.Country 239 Using where; Using join buffer (flat, BNLH join) -1 SIMPLE City hash_ALL Country #hash#Country 3 world.CountryLanguage.Country 4079 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage hash_ALL PRIMARY,Percentage #hash#PRIMARY 3 world.City.Country 984 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE Country hash_ALL PRIMARY #hash#PRIMARY 3 world.City.Country 239 Using where; Using join buffer (flat, BNLH join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -1048,9 +1048,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country hash_ALL PRIMARY #hash#PRIMARY 3 world.CountryLanguage.Country 239 Using where; Using join buffer (flat, BNLH join) -1 SIMPLE City hash_ALL Country #hash#Country 3 world.CountryLanguage.Country 4079 Using where; Using join buffer (incremental, BNLH join) +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage hash_ALL PRIMARY,Percentage #hash#PRIMARY 3 world.City.Country 984 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE Country hash_ALL PRIMARY #hash#PRIMARY 3 world.City.Country 239 Using where; Using join buffer (incremental, BNLH join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -1278,7 +1278,7 @@ WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 SIMPLE City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name FROM City,Country WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; @@ -1307,9 +1307,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.CountryLanguage.Country 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -1 SIMPLE City ref Country Country 3 world.CountryLanguage.Country 18 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage ref PRIMARY,Percentage PRIMARY 3 world.City.Country 4 Using index condition(BKA); Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.City.Country 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -1318,41 +1318,41 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; Name Name Language -La Matanza Argentina Spanish Lomas de Zamora Argentina Spanish +La Matanza Argentina Spanish Lauro de Freitas Brazil Portuguese Los Angeles Chile Spanish Las Palmas de Gran Canaria Spain Spanish -L´Hospitalet de Llobregat Spain Spanish Lleida (Lérida) Spain Spanish +L´Hospitalet de Llobregat Spain Spanish Liupanshui China Chinese -Lianyungang China Chinese Liangcheng China Chinese +Lianyungang China Chinese Lengshuijiang China Chinese Lázaro Cárdenas Mexico Spanish Lagos de Moreno Mexico Spanish Las Margaritas Mexico Spanish Lashio (Lasho) Myanmar Burmese Lalitapur Nepal Nepali -Ludwigshafen am Rhein Germany German Leverkusen Germany German +Ludwigshafen am Rhein Germany German Luchou Taiwan Min Lungtan Taiwan Min Lower Hutt New Zealand English Los Teques Venezuela Spanish Leninsk-Kuznetski Russian Federation Russian -Los Angeles United States English Long Beach United States English Lexington-Fayette United States English Louisville United States English Little Rock United States English +Los Angeles United States English EXPLAIN SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 PRIMARY City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 PRIMARY City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; @@ -1475,7 +1475,7 @@ WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 SIMPLE City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name FROM City,Country WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; @@ -1504,9 +1504,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.CountryLanguage.Country 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -1 SIMPLE City ref Country Country 3 world.CountryLanguage.Country 18 Using where; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage ref PRIMARY,Percentage PRIMARY 3 world.City.Country 4 Using index condition(BKA); Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.City.Country 1 Using where; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -1515,41 +1515,41 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; Name Name Language -La Matanza Argentina Spanish Lomas de Zamora Argentina Spanish +La Matanza Argentina Spanish Lauro de Freitas Brazil Portuguese Los Angeles Chile Spanish Las Palmas de Gran Canaria Spain Spanish -L´Hospitalet de Llobregat Spain Spanish Lleida (Lérida) Spain Spanish +L´Hospitalet de Llobregat Spain Spanish Liupanshui China Chinese -Lianyungang China Chinese Liangcheng China Chinese Lengshuijiang China Chinese -Lázaro Cárdenas Mexico Spanish -Lagos de Moreno Mexico Spanish +Lianyungang China Chinese Las Margaritas Mexico Spanish +Lagos de Moreno Mexico Spanish +Lázaro Cárdenas Mexico Spanish Lashio (Lasho) Myanmar Burmese Lalitapur Nepal Nepali -Ludwigshafen am Rhein Germany German Leverkusen Germany German +Ludwigshafen am Rhein Germany German Luchou Taiwan Min Lungtan Taiwan Min Lower Hutt New Zealand English Los Teques Venezuela Spanish Leninsk-Kuznetski Russian Federation Russian -Los Angeles United States English -Long Beach United States English -Lexington-Fayette United States English -Louisville United States English Little Rock United States English +Louisville United States English +Lexington-Fayette United States English +Long Beach United States English +Los Angeles United States English EXPLAIN SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 PRIMARY City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 PRIMARY City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; @@ -1672,7 +1672,7 @@ WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 SIMPLE City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name FROM City,Country WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; @@ -1701,9 +1701,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.CountryLanguage.Country 1 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan -1 SIMPLE City ref Country Country 3 world.CountryLanguage.Country 18 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage ref PRIMARY,Percentage PRIMARY 3 world.City.Country 4 Using index condition(BKA); Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.City.Country 1 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -1716,37 +1716,37 @@ La Matanza Argentina Spanish Lomas de Zamora Argentina Spanish Lauro de Freitas Brazil Portuguese Los Angeles Chile Spanish +Lleida (Lérida) Spain Spanish Las Palmas de Gran Canaria Spain Spanish L´Hospitalet de Llobregat Spain Spanish -Lleida (Lérida) Spain Spanish -Liupanshui China Chinese Lianyungang China Chinese Liangcheng China Chinese Lengshuijiang China Chinese -Lázaro Cárdenas Mexico Spanish +Liupanshui China Chinese Lagos de Moreno Mexico Spanish Las Margaritas Mexico Spanish +Lázaro Cárdenas Mexico Spanish Lashio (Lasho) Myanmar Burmese Lalitapur Nepal Nepali -Ludwigshafen am Rhein Germany German Leverkusen Germany German +Ludwigshafen am Rhein Germany German Luchou Taiwan Min Lungtan Taiwan Min Lower Hutt New Zealand English Los Teques Venezuela Spanish Leninsk-Kuznetski Russian Federation Russian -Los Angeles United States English -Long Beach United States English Lexington-Fayette United States English Louisville United States English +Los Angeles United States English Little Rock United States English +Long Beach United States English EXPLAIN SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 PRIMARY City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 PRIMARY City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; @@ -1869,7 +1869,7 @@ WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 SIMPLE City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name FROM City,Country WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; @@ -1898,9 +1898,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.CountryLanguage.Country 1 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan -1 SIMPLE City ref Country Country 3 world.CountryLanguage.Country 18 Using where; Using join buffer (incremental, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage ref PRIMARY,Percentage PRIMARY 3 world.City.Country 4 Using index condition(BKA); Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.City.Country 1 Using where; Using join buffer (incremental, BKAH join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -1913,28 +1913,28 @@ La Matanza Argentina Spanish Lomas de Zamora Argentina Spanish Lauro de Freitas Brazil Portuguese Los Angeles Chile Spanish +Lleida (Lérida) Spain Spanish Las Palmas de Gran Canaria Spain Spanish L´Hospitalet de Llobregat Spain Spanish -Lleida (Lérida) Spain Spanish -Liupanshui China Chinese Lianyungang China Chinese Liangcheng China Chinese Lengshuijiang China Chinese -Lázaro Cárdenas Mexico Spanish +Liupanshui China Chinese Lagos de Moreno Mexico Spanish +Lázaro Cárdenas Mexico Spanish Las Margaritas Mexico Spanish Lashio (Lasho) Myanmar Burmese Lalitapur Nepal Nepali -Ludwigshafen am Rhein Germany German Leverkusen Germany German +Ludwigshafen am Rhein Germany German Luchou Taiwan Min Lungtan Taiwan Min Lower Hutt New Zealand English Los Teques Venezuela Spanish Leninsk-Kuznetski Russian Federation Russian +Lexington-Fayette United States English Los Angeles United States English Long Beach United States English -Lexington-Fayette United States English Louisville United States English Little Rock United States English EXPLAIN @@ -1943,7 +1943,7 @@ WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AN City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 PRIMARY City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 PRIMARY City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; @@ -2099,9 +2099,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country hash_ALL PRIMARY #hash#PRIMARY 3 world.CountryLanguage.Country 239 Using where; Using join buffer (flat, BNLH join) -1 SIMPLE City hash_ALL Country #hash#Country 3 world.CountryLanguage.Country 4079 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage hash_ALL PRIMARY,Percentage #hash#PRIMARY 3 world.City.Country 984 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE Country hash_ALL PRIMARY #hash#PRIMARY 3 world.City.Country 239 Using where; Using join buffer (flat, BNLH join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -2203,9 +2203,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country hash_ALL PRIMARY #hash#PRIMARY 3 world.CountryLanguage.Country 239 Using where; Using join buffer (flat, BNLH join) -1 SIMPLE City hash_ALL Country #hash#Country 3 world.CountryLanguage.Country 4079 Using where; Using join buffer (incremental, BNLH join) +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage hash_ALL PRIMARY,Percentage #hash#PRIMARY 3 world.City.Country 984 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE Country hash_ALL PRIMARY #hash#PRIMARY 3 world.City.Country 239 Using where; Using join buffer (incremental, BNLH join) SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -2278,7 +2278,7 @@ WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 SIMPLE City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name FROM City,Country WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; @@ -2307,9 +2307,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.CountryLanguage.Country 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -1 SIMPLE City ref Country Country 3 world.CountryLanguage.Country 18 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage ref PRIMARY,Percentage PRIMARY 3 world.City.Country 4 Using index condition(BKA); Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.City.Country 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -2352,7 +2352,7 @@ WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AN City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 PRIMARY City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 PRIMARY City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; @@ -2382,7 +2382,7 @@ WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 SIMPLE City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name FROM City,Country WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; @@ -2411,9 +2411,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.CountryLanguage.Country 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -1 SIMPLE City ref Country Country 3 world.CountryLanguage.Country 18 Using where; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage ref PRIMARY,Percentage PRIMARY 3 world.City.Country 4 Using index condition(BKA); Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.City.Country 1 Using where; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -2456,7 +2456,7 @@ WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AN City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 PRIMARY City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +1 PRIMARY City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; @@ -2486,7 +2486,7 @@ WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 SIMPLE City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name FROM City,Country WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; @@ -2515,9 +2515,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.CountryLanguage.Country 1 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan -1 SIMPLE City ref Country Country 3 world.CountryLanguage.Country 18 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage ref PRIMARY,Percentage PRIMARY 3 world.City.Country 4 Using index condition(BKA); Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.City.Country 1 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -2534,12 +2534,12 @@ Las Palmas de Gran Canaria Spain Spanish L´Hospitalet de Llobregat Spain Spanish Lleida (Lérida) Spain Spanish Liupanshui China Chinese -Lianyungang China Chinese Liangcheng China Chinese +Lianyungang China Chinese Lengshuijiang China Chinese Lázaro Cárdenas Mexico Spanish -Lagos de Moreno Mexico Spanish Las Margaritas Mexico Spanish +Lagos de Moreno Mexico Spanish Lashio (Lasho) Myanmar Burmese Lalitapur Nepal Nepali Ludwigshafen am Rhein Germany German @@ -2549,9 +2549,9 @@ Lungtan Taiwan Min Lower Hutt New Zealand English Los Teques Venezuela Spanish Leninsk-Kuznetski Russian Federation Russian +Lexington-Fayette United States English Los Angeles United States English Long Beach United States English -Lexington-Fayette United States English Louisville United States English Little Rock United States English EXPLAIN @@ -2560,7 +2560,7 @@ WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AN City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 PRIMARY City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 PRIMARY City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; @@ -2590,7 +2590,7 @@ WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 SIMPLE City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name FROM City,Country WHERE City.Country=Country.Code AND Country.Name LIKE 'L%' AND City.Population > 100000; @@ -2619,9 +2619,9 @@ City.Name LIKE 'L%' AND Country.Population > 3000000 AND CountryLanguage.Percentage > 50 AND LENGTH(Language) < LENGTH(City.Name) - 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE CountryLanguage ALL PRIMARY,Percentage NULL NULL NULL 984 Using where -1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.CountryLanguage.Country 1 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan -1 SIMPLE City ref Country Country 3 world.CountryLanguage.Country 18 Using where; Using join buffer (incremental, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE City ALL Country NULL NULL NULL 4079 Using where +1 SIMPLE CountryLanguage ref PRIMARY,Percentage PRIMARY 3 world.City.Country 4 Using index condition(BKA); Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 SIMPLE Country eq_ref PRIMARY PRIMARY 3 world.City.Country 1 Using where; Using join buffer (incremental, BKAH join); Key-ordered Rowid-ordered scan SELECT City.Name, Country.Name, CountryLanguage.Language FROM City,Country,CountryLanguage WHERE City.Country=Country.Code AND @@ -2664,7 +2664,7 @@ WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AN City.Population > 100000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country range PRIMARY,Name Name 52 NULL 10 Using index condition; Rowid-ordered scan -1 PRIMARY City ref Population,Country Country 3 world.Country.Code 18 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan +1 PRIMARY City ref Population,Country Country 3 world.Country.Code 17 Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan SELECT Name FROM City WHERE City.Country IN (SELECT Code FROM Country WHERE Country.Name LIKE 'L%') AND City.Population > 100000; @@ -3044,7 +3044,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 ref t3_metaid,t3_formatid,t3_metaidformatid t3_metaidformatid 4 test.t1.metaid 1 Using index condition; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan 1 SIMPLE t4 eq_ref PRIMARY,t4_formatclassid,t4_formats_idx PRIMARY 4 test.t3.formatid 1 Using where; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan 1 SIMPLE t5 eq_ref PRIMARY,t5_formattypeid PRIMARY 4 test.t4.formatclassid 1 Using where; Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan -1 SIMPLE t9 index PRIMARY,t9_subgenreid,t9_metaid PRIMARY 8 NULL 2 Using where; Using index; Using join buffer (incremental, BNL join) +1 SIMPLE t9 ref PRIMARY,t9_subgenreid,t9_metaid t9_metaid 4 test.t1.metaid 2 Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan 1 SIMPLE t10 eq_ref PRIMARY,t10_genreid PRIMARY 4 test.t9.subgenreid 1 Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan 1 SIMPLE t11 eq_ref PRIMARY PRIMARY 4 test.t10.genreid 1 Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan SELECT t1.uniquekey, t1.xml AS affiliateXml, @@ -3665,8 +3665,8 @@ where t2.b=t1.b and t3.d=t1.d and t4.c=t1.c; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 7 Using where 1 SIMPLE t2 ref idx idx 5 test.t1.b 1 -1 SIMPLE t3 ref idx idx 5 test.t1.d 1 1 SIMPLE t4 ref idx idx 5 test.t1.c 1 +1 SIMPLE t3 ref idx idx 5 test.t1.d 1 select t1.a, t1.b, t1.c, t1.d, t2.e, t3.f, t4.g from t1,t2,t3,t4 where t2.b=t1.b and t3.d=t1.d and t4.c=t1.c; a b c d e f g @@ -3678,8 +3678,8 @@ where t2.b=t1.b and t3.d=t1.d and t4.c=t1.c; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 7 Using where 1 SIMPLE t2 ref idx idx 5 test.t1.b 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -1 SIMPLE t3 ref idx idx 5 test.t1.d 1 Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan 1 SIMPLE t4 ref idx idx 5 test.t1.c 1 Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan +1 SIMPLE t3 ref idx idx 5 test.t1.d 1 Using join buffer (incremental, BKA join); Key-ordered Rowid-ordered scan select t1.a, t1.b, t1.c, t1.d, t2.e, t3.f, t4.g from t1,t2,t3,t4 where t2.b=t1.b and t3.d=t1.d and t4.c=t1.c; a b c d e f g @@ -6033,12 +6033,12 @@ drop table t1; SET join_cache_level = 3; # The following should have # - table order PROFILING,user, -# - table user accessed with hash_ALL: +# - table db accessed with hash_ALL: explain -SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user WHERE password_expired = PAGE_FAULTS_MINOR; +SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.db WHERE Select_priv = PAGE_FAULTS_MINOR; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE PROFILING ALL NULL NULL NULL NULL NULL Using where -1 SIMPLE user hash_ALL NULL #hash#$hj 1 information_schema.PROFILING.PAGE_FAULTS_MINOR 4 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE db hash_ALL NULL #hash#$hj 1 information_schema.PROFILING.PAGE_FAULTS_MINOR 2 Using where; Using join buffer (flat, BNLH join) set join_cache_level=default; create table t1 (c1 date not null, key (c1)) engine=innodb; insert t1 values ('2017-12-27'); diff --git a/mysql-test/main/join_cache.test b/mysql-test/main/join_cache.test index df89fc30dee..046dcfcf3cb 100644 --- a/mysql-test/main/join_cache.test +++ b/mysql-test/main/join_cache.test @@ -3970,9 +3970,9 @@ drop table t1; SET join_cache_level = 3; --echo # The following should have --echo # - table order PROFILING,user, ---echo # - table user accessed with hash_ALL: +--echo # - table db accessed with hash_ALL: explain -SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user WHERE password_expired = PAGE_FAULTS_MINOR; +SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.db WHERE Select_priv = PAGE_FAULTS_MINOR; set join_cache_level=default; diff --git a/mysql-test/main/join_nested.result b/mysql-test/main/join_nested.result index 708c72fffb5..b6b4716d8b1 100644 --- a/mysql-test/main/join_nested.result +++ b/mysql-test/main/join_nested.result @@ -1150,7 +1150,7 @@ a b a b 4 2 2 2 5 3 NULL NULL SELECT t2.a,t2.b,t3.a,t3.b -FROM t2 LEFT JOIN (t3) ON t2.b=t3.b +FROM t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL); a b a b 4 2 1 2 diff --git a/mysql-test/main/join_nested.test b/mysql-test/main/join_nested.test index e60b7827f75..77d0e4154c1 100644 --- a/mysql-test/main/join_nested.test +++ b/mysql-test/main/join_nested.test @@ -683,7 +683,7 @@ SELECT t2.a,t2.b,t3.a,t3.b WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL); SELECT t2.a,t2.b,t3.a,t3.b - FROM t2 LEFT JOIN (t3) ON t2.b=t3.b + FROM t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL); ALTER TABLE t3 diff --git a/mysql-test/main/join_nested_jcl6.result b/mysql-test/main/join_nested_jcl6.result index 2f8e1712672..6b1901d8642 100644 --- a/mysql-test/main/join_nested_jcl6.result +++ b/mysql-test/main/join_nested_jcl6.result @@ -1161,7 +1161,7 @@ a b a b 4 2 2 2 5 3 NULL NULL SELECT t2.a,t2.b,t3.a,t3.b -FROM t2 LEFT JOIN (t3) ON t2.b=t3.b +FROM t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t2.a = 4 OR (t2.a > 4 AND t3.a IS NULL); a b a b 4 2 1 2 diff --git a/mysql-test/main/join_outer.result b/mysql-test/main/join_outer.result index 6b671a0759f..bda5d266f98 100644 --- a/mysql-test/main/join_outer.result +++ b/mysql-test/main/join_outer.result @@ -1790,8 +1790,11 @@ insert into t3 values (11, 100), (33, 301), (44, 402), (11, 102), (11, 101); insert into t3 values (22, 100), (53, 301), (64, 402), (22, 102), (22, 101); analyze table t1,t2,t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK flush status; select sum(t3.b) from t1 left join t3 on t3.a=t1.a and t1.a is not null; @@ -1800,7 +1803,7 @@ sum(t3.b) show status like "handler_read%"; Variable_name Value Handler_read_first 0 -Handler_read_key 4 +Handler_read_key 10 Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 @@ -1815,7 +1818,7 @@ sum(t3.b) show status like "handler_read%"; Variable_name Value Handler_read_first 0 -Handler_read_key 4 +Handler_read_key 6 Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 diff --git a/mysql-test/main/join_outer_innodb.result b/mysql-test/main/join_outer_innodb.result index 6f3fb09329d..9ab8bde1236 100644 --- a/mysql-test/main/join_outer_innodb.result +++ b/mysql-test/main/join_outer_innodb.result @@ -440,18 +440,18 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t6 eq_ref PRIMARY PRIMARY 4 test.t1.a3 1 Using where; Using index 1 SIMPLE t8 eq_ref PRIMARY PRIMARY 1 test.t1.a4 1 Using index 1 SIMPLE t7 eq_ref PRIMARY PRIMARY 1 test.t1.a7 1 -1 SIMPLE t9 ref PRIMARY PRIMARY 1 test.t1.a4 1 1 SIMPLE t11 eq_ref PRIMARY PRIMARY 4 test.t1.a5 1 1 SIMPLE t12 eq_ref PRIMARY PRIMARY 4 test.t11.k3 1 Using where 1 SIMPLE l2 eq_ref PRIMARY PRIMARY 4 test.t11.k4 1 Using where 1 SIMPLE t13 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where; Using index +1 SIMPLE t9 ref PRIMARY PRIMARY 1 test.t1.a4 1 1 SIMPLE l4 eq_ref PRIMARY PRIMARY 4 test.t13.m2 1 Using where; Using index 1 SIMPLE m2 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where; Using index -1 SIMPLE l3 eq_ref PRIMARY PRIMARY 4 test.m2.m2 1 Using where +1 SIMPLE l3 ALL PRIMARY NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t10 ALL PRIMARY NULL NULL NULL 3 Using where; Using join buffer (incremental, BNL join) 1 SIMPLE t14 eq_ref PRIMARY PRIMARY 2 test.t1.a8 1 Using where 1 SIMPLE t15 eq_ref PRIMARY PRIMARY 2 test.t1.a9 1 Using where; Using index 1 SIMPLE t16 ref PRIMARY PRIMARY 2 test.t15.o1 1 Using where -1 SIMPLE t10 ALL PRIMARY NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) explain select * from v1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL a4,a6,a5,a7 NULL NULL NULL 3 Using where @@ -462,18 +462,18 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t6 eq_ref PRIMARY PRIMARY 4 test.t1.a3 1 Using where; Using index 1 SIMPLE t8 eq_ref PRIMARY PRIMARY 1 test.t1.a4 1 Using index 1 SIMPLE t7 eq_ref PRIMARY PRIMARY 1 test.t1.a7 1 -1 SIMPLE t9 ref PRIMARY PRIMARY 1 test.t1.a4 1 1 SIMPLE t11 eq_ref PRIMARY PRIMARY 4 test.t1.a5 1 1 SIMPLE t12 eq_ref PRIMARY PRIMARY 4 test.t11.k3 1 Using where 1 SIMPLE l2 eq_ref PRIMARY PRIMARY 4 test.t11.k4 1 Using where 1 SIMPLE t13 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where; Using index +1 SIMPLE t9 ref PRIMARY PRIMARY 1 test.t1.a4 1 1 SIMPLE l4 eq_ref PRIMARY PRIMARY 4 test.t13.m2 1 Using where; Using index 1 SIMPLE m2 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where; Using index -1 SIMPLE l3 eq_ref PRIMARY PRIMARY 4 test.m2.m2 1 Using where +1 SIMPLE l3 ALL PRIMARY NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t10 ALL PRIMARY NULL NULL NULL 3 Using where; Using join buffer (incremental, BNL join) 1 SIMPLE t14 eq_ref PRIMARY PRIMARY 2 test.t1.a8 1 Using where 1 SIMPLE t15 eq_ref PRIMARY PRIMARY 2 test.t1.a9 1 Using where; Using index 1 SIMPLE t16 ref PRIMARY PRIMARY 2 test.t15.o1 1 Using where -1 SIMPLE t10 ALL PRIMARY NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) drop view v1; drop table t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16; # diff --git a/mysql-test/main/join_outer_jcl6.result b/mysql-test/main/join_outer_jcl6.result index f46f3e2df21..01e7ec9d42f 100644 --- a/mysql-test/main/join_outer_jcl6.result +++ b/mysql-test/main/join_outer_jcl6.result @@ -1801,8 +1801,11 @@ insert into t3 values (11, 100), (33, 301), (44, 402), (11, 102), (11, 101); insert into t3 values (22, 100), (53, 301), (64, 402), (22, 102), (22, 101); analyze table t1,t2,t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK flush status; select sum(t3.b) from t1 left join t3 on t3.a=t1.a and t1.a is not null; @@ -1811,7 +1814,7 @@ sum(t3.b) show status like "handler_read%"; Variable_name Value Handler_read_first 0 -Handler_read_key 4 +Handler_read_key 10 Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 @@ -1826,7 +1829,7 @@ sum(t3.b) show status like "handler_read%"; Variable_name Value Handler_read_first 0 -Handler_read_key 4 +Handler_read_key 6 Handler_read_last 0 Handler_read_next 5 Handler_read_prev 0 diff --git a/mysql-test/main/kill.result b/mysql-test/main/kill.result index dc1cb9252da..4775d111b79 100644 --- a/mysql-test/main/kill.result +++ b/mysql-test/main/kill.result @@ -324,7 +324,7 @@ connection blocker; lock tables t1 read; connection ddl; # Let us mark locked table t1 as old -flush tables; +flush tables t1; connection dml; select * from t1; connection default; diff --git a/mysql-test/main/kill.test b/mysql-test/main/kill.test index b6000ffced1..059d8d40b11 100644 --- a/mysql-test/main/kill.test +++ b/mysql-test/main/kill.test @@ -538,18 +538,18 @@ connection blocker; lock tables t1 read; connection ddl; --echo # Let us mark locked table t1 as old ---send flush tables +--send flush tables t1 connection dml; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" and - info = "flush tables"; + where state = "Waiting for table metadata lock" and + info = "flush tables t1"; --source include/wait_condition.inc --send select * from t1 connection default; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" and + where state = "Waiting for table metadata lock" and info = "select * from t1"; --source include/wait_condition.inc --replace_result $ID2 ID2 diff --git a/mysql-test/main/limit_rows_examined.result b/mysql-test/main/limit_rows_examined.result index 8458e063d97..71b99d066ff 100644 --- a/mysql-test/main/limit_rows_examined.result +++ b/mysql-test/main/limit_rows_examined.result @@ -49,10 +49,11 @@ explain select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1i index PRIMARY PRIMARY 2 NULL 4 Using index -1 SIMPLE t2i index PRIMARY PRIMARY 2 NULL 4 Using where; Using index; Using join buffer (flat, BNL join) +1 SIMPLE t2i eq_ref PRIMARY PRIMARY 2 test.t1i.c1 1 Using index select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; c1 c2 bb bb +cc cc Warnings: Warning 1931 Query execution was interrupted. The query examined at least 7 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete set @@join_cache_level=6; @@ -69,10 +70,11 @@ explain select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1i index PRIMARY PRIMARY 2 NULL 4 Using index -1 SIMPLE t2i index PRIMARY PRIMARY 2 NULL 4 Using where; Using index; Using join buffer (flat, BNL join) +1 SIMPLE t2i eq_ref PRIMARY PRIMARY 2 test.t1i.c1 1 Using index select * from t1i, t2i where c1 = c2 LIMIT ROWS EXAMINED 6; c1 c2 bb bb +cc cc Warnings: Warning 1931 Query execution was interrupted. The query examined at least 7 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete Mix LIMIT ROWS EXAMINED with LIMIT @@ -254,12 +256,13 @@ where c1 IN (select * from t2i where c2 > ' ') LIMIT ROWS EXAMINED 6; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1i index PRIMARY PRIMARY 2 NULL 4 Using where; Using index -1 PRIMARY t2i index PRIMARY PRIMARY 2 NULL 4 Using where; Using index; Using join buffer (flat, BNL join) +1 PRIMARY t2i eq_ref PRIMARY PRIMARY 2 test.t1i.c1 1 Using index select * from t1i where c1 IN (select * from t2i where c2 > ' ') LIMIT ROWS EXAMINED 6; c1 bb +cc Warnings: Warning 1931 Query execution was interrupted. The query examined at least 7 rows, which exceeds LIMIT ROWS EXAMINED (6). The query result may be incomplete Subqueries with IN-TO-EXISTS @@ -836,7 +839,7 @@ WHERE c = (SELECT MAX(b) FROM t2) LIMIT ROWS EXAMINED 3; (SELECT MAX(c) FROM t1, t2) Warnings: -Warning 1931 Query execution was interrupted. The query examined at least 10 rows, which exceeds LIMIT ROWS EXAMINED (3). The query result may be incomplete +Warning 1931 Query execution was interrupted. The query examined at least 12 rows, which exceeds LIMIT ROWS EXAMINED (3). The query result may be incomplete drop table t1, t2; MDEV-178: LIMIT ROWS EXAMINED: Assertion `0' failed in net_end_statement(THD*) on the diff --git a/mysql-test/main/lock.result b/mysql-test/main/lock.result index 339cfcaa441..6edb86bfa3f 100644 --- a/mysql-test/main/lock.result +++ b/mysql-test/main/lock.result @@ -457,6 +457,7 @@ connection default; LOCK TABLE t1 WRITE; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date connection con2; LOCK TABLE t2 WRITE; @@ -499,7 +500,7 @@ connect con1,localhost,root,,test; LOCK TABLE t2 WRITE; SET lock_wait_timeout= 1; FLUSH TABLES; -ERROR HY000: Lock wait timeout exceeded; try restarting transaction +FLUSH TABLES t2; UNLOCK TABLES; disconnect con1; connection default; diff --git a/mysql-test/main/lock.test b/mysql-test/main/lock.test index ff77b4991c0..8a59f4082b1 100644 --- a/mysql-test/main/lock.test +++ b/mysql-test/main/lock.test @@ -609,8 +609,8 @@ LOCK TABLE t1 READ; --connect (con1,localhost,root,,test) LOCK TABLE t2 WRITE; SET lock_wait_timeout= 1; ---error ER_LOCK_WAIT_TIMEOUT FLUSH TABLES; +FLUSH TABLES t2; # Cleanup UNLOCK TABLES; diff --git a/mysql-test/main/lock_multi.result b/mysql-test/main/lock_multi.result index e702c458c0c..30cd63e60ed 100644 --- a/mysql-test/main/lock_multi.result +++ b/mysql-test/main/lock_multi.result @@ -114,22 +114,21 @@ unlock tables; drop table t1; connection locker; USE mysql; -LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE; +LOCK TABLES columns_priv WRITE, db WRITE, user WRITE; FLUSH TABLES; connection reader; USE mysql; -SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1; +SELECT global_priv.host FROM global_priv, db WHERE global_priv.user = db.user LIMIT 1; connection locker; -OPTIMIZE TABLES columns_priv, db, host, user; +OPTIMIZE TABLES columns_priv, db, global_priv; Table Op Msg_type Msg_text mysql.columns_priv optimize status OK mysql.db optimize status OK -mysql.host optimize status OK -mysql.user optimize status OK +mysql.global_priv optimize status OK UNLOCK TABLES; connection reader; -Select_priv -N +host +localhost USE test; connection locker; use test; @@ -219,6 +218,7 @@ connection con2; unlock tables; connection con3; a +connection con4; connection default; disconnect con5; disconnect con4; @@ -248,6 +248,7 @@ flush table t2; connection default; unlock tables; connection con1; +connection con2; # # LOCK TABLES .. WRITE # @@ -300,7 +301,7 @@ connection default; alter table t1 add column j int; connect insert,localhost,root,,test,,; connection insert; -insert into t1 values (1,2);; +insert into t1 values (1,2); connection default; unlock tables; connection flush; @@ -532,8 +533,9 @@ connect con3, localhost, root; connection default; LOCK TABLE t1 READ; connection con3; -# Sending: FLUSH TABLES; +# Sending: +FLUSH TABLES t1; connection con2; SELECT * FROM t1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction diff --git a/mysql-test/main/lock_multi.test b/mysql-test/main/lock_multi.test index a945bcdbb74..5cc7219b01d 100644 --- a/mysql-test/main/lock_multi.test +++ b/mysql-test/main/lock_multi.test @@ -184,25 +184,25 @@ drop table t1; connection locker; USE mysql; -LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE; +LOCK TABLES columns_priv WRITE, db WRITE, user WRITE; FLUSH TABLES; # connection reader; USE mysql; # Note: This must be a multi-table select, otherwise the deadlock will not occur send -SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1; +SELECT global_priv.host FROM global_priv, db WHERE global_priv.user = db.user LIMIT 1; # connection locker; # Sleep a bit till the select of connection reader is in work and hangs let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = "Waiting for table metadata lock" AND info = - "SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1"; + "SELECT global_priv.host FROM global_priv, db WHERE global_priv.user = db.user LIMIT 1"; --source include/wait_condition.inc # Make test case independent from earlier grants. --replace_result "Table is already up to date" "OK" -OPTIMIZE TABLES columns_priv, db, host, user; +OPTIMIZE TABLES columns_priv, db, global_priv; UNLOCK TABLES; # connection reader; @@ -229,7 +229,7 @@ connection writer; # Sleep a bit till the flush of connection locker is in work and hangs let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "FLUSH TABLES WITH READ LOCK"; --source include/wait_condition.inc # This must not block. @@ -261,7 +261,7 @@ connection writer; # Sleep a bit till the flush of connection locker is in work and hangs let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "FLUSH TABLES WITH READ LOCK"; --source include/wait_condition.inc --error ER_TABLE_NOT_LOCKED @@ -298,10 +298,10 @@ DROP DATABASE mysqltest_1; # When fixed: Reject dropping db because of the read lock. connection con1; # Wait a bit so that the session con2 is in state -# "Waiting for global read lock" +# "Waiting for backup lock" let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" + where state = "Waiting for backup lock" and info = "DROP DATABASE mysqltest_1"; --source include/wait_condition.inc --error ER_CANT_UPDATE_WITH_READLOCK @@ -377,7 +377,7 @@ send flush tables with read lock; connection con5; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "flush tables with read lock"; --source include/wait_condition.inc --echo # global read lock is taken @@ -386,14 +386,19 @@ send select * from t2 for update; connection con5; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "select * from t2 for update"; --source include/wait_condition.inc --echo # waiting for release of read lock connection con4; --echo # would hang and later cause a deadlock -flush tables t2; +--send flush tables t2 connection con1; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table metadata lock" and + info = "flush tables t2"; +--source include/wait_condition.inc --echo # clean up unlock tables; connection con2; @@ -401,6 +406,8 @@ connection con2; unlock tables; connection con3; --reap +connection con4; +--reap connection default; disconnect con5; disconnect con4; @@ -432,16 +439,23 @@ send update t2 set a = 1; connection default; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "update t2 set a = 1"; --source include/wait_condition.inc --echo # statement is waiting for release of read lock connection con2; -flush table t2; +--send flush table t2 connection default; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table metadata lock" and + info = "flush table t2"; +--source include/wait_condition.inc unlock tables; connection con1; --reap +connection con2; +--reap --echo # --echo # LOCK TABLES .. WRITE @@ -454,7 +468,7 @@ send lock tables t2 write; connection default; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "lock tables t2 write"; --source include/wait_condition.inc --echo # statement is waiting for release of read lock @@ -542,7 +556,7 @@ connection flush; connection default; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "flush tables with read lock"; --source include/wait_condition.inc alter table t1 add column j int; @@ -550,14 +564,14 @@ connect (insert,localhost,root,,test,,); connection insert; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "flush tables with read lock"; --source include/wait_condition.inc ---send insert into t1 values (1,2); +--send insert into t1 values (1,2) connection default; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for table metadata lock" and info = "insert into t1 values (1,2)"; --source include/wait_condition.inc unlock tables; @@ -565,7 +579,7 @@ connection flush; --reap let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock" and + where state = "Waiting for backup lock" and info = "insert into t1 values (1,2)"; --source include/wait_condition.inc select * from t1; @@ -598,12 +612,12 @@ connection flush; connection default; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock"; + where state = "Waiting for backup lock"; --source include/wait_condition.inc flush tables; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock"; + where state = "Waiting for backup lock"; --source include/wait_condition.inc unlock tables; connection flush; @@ -664,12 +678,12 @@ connection flush; connection default; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock"; + where state = "Waiting for backup lock"; --source include/wait_condition.inc flush tables; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock"; + where state = "Waiting for backup lock"; --source include/wait_condition.inc drop table t1; connection flush; @@ -931,13 +945,19 @@ connection default; LOCK TABLE t1 READ; connection con3; + +# first test that flush tables doesn't block +FLUSH TABLES; + +# Check the FLUSH TABLES t1 waits until table lock is released + --echo # Sending: ---send FLUSH TABLES +--send FLUSH TABLES t1 connection con2; let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist - WHERE state = "Waiting for table flush" AND info = "FLUSH TABLES"; + WHERE state = "Waiting for table metadata lock" AND info = "FLUSH TABLES t1"; --source include/wait_condition.inc --error ER_LOCK_WAIT_TIMEOUT SELECT * FROM t1; diff --git a/mysql-test/main/lock_sync.result b/mysql-test/main/lock_sync.result index 7b61c5994b6..bbdc1d43ba5 100644 --- a/mysql-test/main/lock_sync.result +++ b/mysql-test/main/lock_sync.result @@ -67,6 +67,8 @@ declare j int; select i from t1 where i = 1 into j; return j; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f2() returns int begin declare k int; @@ -74,6 +76,8 @@ select i from t1 where i = 1 into k; insert into t2 values (k + 5); return 0; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f3() returns int begin return (select i from t1 where i = 3); @@ -97,12 +101,16 @@ declare k int; select i from v1 where i = 1 into k; return k; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f7() returns int begin declare k int; select j from v2 where j = 1 into k; return k; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f8() returns int begin declare k int; @@ -110,6 +118,8 @@ select i from v1 where i = 1 into k; insert into t2 values (k+5); return k; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f9() returns int begin update v2 set j=j+10 where j=1; @@ -139,6 +149,8 @@ create procedure p2(inout p int) begin select i from t1 where i = 1 into p; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function f14() returns int begin declare k int; @@ -166,6 +178,8 @@ select i from t1 where i = 1 into j; call p3; return 1; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create procedure p3() begin create temporary table if not exists temp1 (a int); @@ -178,6 +192,8 @@ declare k int; select i from t1 where i=1 into k; set new.l= k+1; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create trigger t4_bu before update on t4 for each row begin if (select i from t1 where i=1) then @@ -766,7 +782,7 @@ SET DEBUG_SYNC= 'now WAIT_FOR opened'; SET DEBUG_SYNC= 'now SIGNAL dropped'; SET DEBUG_SYNC= 'now WAIT_FOR opened'; # Sending: -FLUSH TABLES; +FLUSH TABLES t1; connection default; # Waiting for FLUSH TABLES to be blocked. SET DEBUG_SYNC= 'now SIGNAL dropped'; diff --git a/mysql-test/main/lock_sync.test b/mysql-test/main/lock_sync.test index af8435f7fbb..1a8cd7bdbd3 100644 --- a/mysql-test/main/lock_sync.test +++ b/mysql-test/main/lock_sync.test @@ -974,12 +974,12 @@ SET DEBUG_SYNC= 'now WAIT_FOR opened'; SET DEBUG_SYNC= 'now SIGNAL dropped'; SET DEBUG_SYNC= 'now WAIT_FOR opened'; --echo # Sending: ---send FLUSH TABLES +--send FLUSH TABLES t1 connection default; --echo # Waiting for FLUSH TABLES to be blocked. let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.processlist - WHERE state= 'Waiting for table flush' AND info= 'FLUSH TABLES'; + WHERE state= 'Waiting for table metadata lock' AND info= 'FLUSH TABLES t1'; --source include/wait_condition.inc SET DEBUG_SYNC= 'now SIGNAL dropped'; diff --git a/mysql-test/main/log_tables_upgrade.result b/mysql-test/main/log_tables_upgrade.result index 8f822d56020..8d7b08a11bd 100644 --- a/mysql-test/main/log_tables_upgrade.result +++ b/mysql-test/main/log_tables_upgrade.result @@ -19,12 +19,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -43,9 +43,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables diff --git a/mysql-test/main/lowercase_fs_off.result b/mysql-test/main/lowercase_fs_off.result index f2a8ec14641..6ff8c1b7f93 100644 --- a/mysql-test/main/lowercase_fs_off.result +++ b/mysql-test/main/lowercase_fs_off.result @@ -94,12 +94,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats Error : Unknown storage engine 'InnoDB' @@ -123,7 +123,6 @@ mysql.time_zone_transition_type OK mysql.transaction_registry Error : Unknown storage engine 'InnoDB' error : Corrupt -mysql.user OK Repairing tables mysql.innodb_index_stats @@ -137,6 +136,7 @@ Error : Unknown storage engine 'InnoDB' error : Corrupt Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables diff --git a/mysql-test/main/mdev-504.result b/mysql-test/main/mdev-504.result index 9b8b6795e0f..e34e57be6ed 100644 --- a/mysql-test/main/mdev-504.result +++ b/mysql-test/main/mdev-504.result @@ -1,3 +1,4 @@ +set @save_use_stat_tables=@@global.use_stat_tables; SET GLOBAL net_write_timeout = 900; CREATE TABLE A ( pk INTEGER AUTO_INCREMENT PRIMARY KEY, @@ -20,5 +21,5 @@ connection default; DROP TABLE A; DROP PROCEDURE p_analyze; DROP FUNCTION rnd3; -SET GLOBAL use_stat_tables = DEFAULT; +SET GLOBAL use_stat_tables = @save_use_stat_tables; SET GLOBAL net_write_timeout = DEFAULT; diff --git a/mysql-test/main/mdev-504.test b/mysql-test/main/mdev-504.test index 551c21c37d0..277b5a038a0 100644 --- a/mysql-test/main/mdev-504.test +++ b/mysql-test/main/mdev-504.test @@ -1,6 +1,8 @@ --source include/not_valgrind.inc --source include/no_protocol.inc +set @save_use_stat_tables=@@global.use_stat_tables; + SET GLOBAL net_write_timeout = 900; CREATE TABLE A ( @@ -76,5 +78,5 @@ while ($trial) DROP TABLE A; DROP PROCEDURE p_analyze; DROP FUNCTION rnd3; -SET GLOBAL use_stat_tables = DEFAULT; +SET GLOBAL use_stat_tables = @save_use_stat_tables; SET GLOBAL net_write_timeout = DEFAULT; diff --git a/mysql-test/main/mdev13607.result b/mysql-test/main/mdev13607.result index 08848bc645b..4d8f252478c 100644 --- a/mysql-test/main/mdev13607.result +++ b/mysql-test/main/mdev13607.result @@ -14,8 +14,11 @@ CREATE TABLE t3 (id INT) ENGINE=InnoDB; INSERT INTO t3 VALUES (1),(2); ANALYZE TABLE t1, t2, t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK explain SELECT * FROM (SELECT p1.* FROM t1 p1 NATURAL JOIN t2 r1 NATURAL JOIN t3 d1 NATURAL JOIN t1 p2 NATURAL JOIN t2 r2 NATURAL JOIN t3 d2 NATURAL JOIN t1 p3 NATURAL JOIN t2 r3 NATURAL JOIN t3 d3 NATURAL JOIN t1 p4 NATURAL JOIN t2 r4 NATURAL JOIN t3 d4 NATURAL JOIN t1 p5 NATURAL JOIN t2 r5 NATURAL JOIN t3 d5 NATURAL JOIN t1 p6 NATURAL JOIN t2 r6 NATURAL JOIN t3 d6 NATURAL JOIN t1 p7 NATURAL JOIN t2 r7 NATURAL JOIN t3 d7 NATURAL JOIN t1 p8 NATURAL JOIN t2 r8 NATURAL JOIN t3 d8 NATURAL JOIN t1 p9 ) gp_1 diff --git a/mysql-test/main/mdl.result b/mysql-test/main/mdl.result index d93bfd5c729..883f35674c0 100644 --- a/mysql-test/main/mdl.result +++ b/mysql-test/main/mdl.result @@ -6,17 +6,85 @@ # failed in MDL_context::upgrade_shared_lock # CREATE TABLE t1(a INT) ENGINE=InnoDB; +CREATE TABLE t3(a INT) ENGINE=myisam; LOCK TABLES t1 WRITE CONCURRENT, t1 AS t2 READ; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME -MDL_INTENTION_EXCLUSIVE Global read lock +MDL_BACKUP_TRANS_DML Backup lock MDL_SHARED_NO_READ_WRITE Table metadata lock test t1 UNLOCK TABLES; LOCK TABLES t1 AS t2 READ, t1 WRITE CONCURRENT; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME -MDL_INTENTION_EXCLUSIVE Global read lock +MDL_BACKUP_TRANS_DML Backup lock MDL_SHARED_WRITE Table metadata lock test t1 MDL_SHARED_READ_ONLY Table metadata lock test t1 UNLOCK TABLES; -DROP TABLE t1; +LOCK TABLES t1 WRITE CONCURRENT, t3 WRITE; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_DDL Backup lock +MDL_BACKUP_DML Backup lock +MDL_SHARED_WRITE Table metadata lock test t1 +MDL_SHARED_NO_READ_WRITE Table metadata lock test t3 +MDL_INTENTION_EXCLUSIVE Schema metadata lock test +UNLOCK TABLES; +LOCK TABLES t3 WRITE, t1 WRITE CONCURRENT; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_DDL Backup lock +MDL_BACKUP_DML Backup lock +MDL_SHARED_WRITE Table metadata lock test t1 +MDL_SHARED_NO_READ_WRITE Table metadata lock test t3 +MDL_INTENTION_EXCLUSIVE Schema metadata lock test +UNLOCK TABLES; +LOCK TABLES t1 WRITE, mysql.user WRITE; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_DDL Backup lock +MDL_SHARED_NO_READ_WRITE Table metadata lock mysql user +MDL_SHARED_NO_READ_WRITE Table metadata lock test t1 +MDL_INTENTION_EXCLUSIVE Schema metadata lock mysql +MDL_SHARED_NO_READ_WRITE Table metadata lock mysql global_priv +MDL_INTENTION_EXCLUSIVE Schema metadata lock test +UNLOCK TABLES; +LOCK TABLES mysql.general_log WRITE; +ERROR HY000: You can't use locks with log tables +LOCK TABLES t1 WRITE,information_schema.tables READ; +UNLOCK TABLES; +DROP TABLE t1,t3; +# +# Check MDL locks taken for different kind of tables by open +# +CREATE TABLE t1(a INT) ENGINE=InnoDB; +CREATE TABLE t3(a INT) ENGINE=myisam; +connect locker,localhost,root,,; +connection default; +FLUSH TABLES WITH READ LOCK; +connection locker; +insert into t1 values (1); +connection default; +connection default; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_FTWRL2 Backup lock +MDL_SHARED_WRITE Table metadata lock test t1 +unlock tables; +connection locker; +unlock tables; +connection default; +FLUSH TABLES WITH READ LOCK; +connection locker; +insert into t3 values (2); +connection default; +connection default; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_FTWRL2 Backup lock +MDL_SHARED_WRITE Table metadata lock test t3 +unlock tables; +connection locker; +unlock tables; +connection default; +disconnect locker; +DROP TABLE t1,t3; diff --git a/mysql-test/main/mdl.test b/mysql-test/main/mdl.test index b90c74a8f7f..23a862f5212 100644 --- a/mysql-test/main/mdl.test +++ b/mysql-test/main/mdl.test @@ -10,10 +10,72 @@ --echo # CREATE TABLE t1(a INT) ENGINE=InnoDB; +CREATE TABLE t3(a INT) ENGINE=myisam; LOCK TABLES t1 WRITE CONCURRENT, t1 AS t2 READ; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; UNLOCK TABLES; LOCK TABLES t1 AS t2 READ, t1 WRITE CONCURRENT; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; UNLOCK TABLES; -DROP TABLE t1; +LOCK TABLES t1 WRITE CONCURRENT, t3 WRITE; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +UNLOCK TABLES; +LOCK TABLES t3 WRITE, t1 WRITE CONCURRENT; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +UNLOCK TABLES; +LOCK TABLES t1 WRITE, mysql.user WRITE; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +UNLOCK TABLES; +--error ER_CANT_LOCK_LOG_TABLE +LOCK TABLES mysql.general_log WRITE; +# The following may work in embedded server +--error 0,ER_DBACCESS_DENIED_ERROR +LOCK TABLES t1 WRITE,information_schema.tables READ; +UNLOCK TABLES; +DROP TABLE t1,t3; + +--echo # +--echo # Check MDL locks taken for different kind of tables by open +--echo # + +CREATE TABLE t1(a INT) ENGINE=InnoDB; +CREATE TABLE t3(a INT) ENGINE=myisam; +connect (locker,localhost,root,,); +connection default; + +FLUSH TABLES WITH READ LOCK; +connection locker; +--send insert into t1 values (1) +connection default; +# Wait till above update gets blocked on a user lock. +let $wait_condition= + select count(*) > 0 from information_schema.processlist + where state = "Waiting for backup lock"; +--source include/wait_condition.inc +connection default; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +unlock tables; +connection locker; +--reap +unlock tables; +connection default; + +FLUSH TABLES WITH READ LOCK; +connection locker; +--send insert into t3 values (2) +connection default; +# Wait till above update gets blocked on a user lock. +let $wait_condition= + select count(*) > 0 from information_schema.processlist + where state = "Waiting for backup lock"; +--source include/wait_condition.inc +connection default; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +unlock tables; +connection locker; +--reap +unlock tables; +connection default; + +disconnect locker; +DROP TABLE t1,t3; diff --git a/mysql-test/main/mdl_sync.result b/mysql-test/main/mdl_sync.result index 3880fc5ef91..5203fdddb2d 100644 --- a/mysql-test/main/mdl_sync.result +++ b/mysql-test/main/mdl_sync.result @@ -2146,10 +2146,11 @@ flush tables t1, t2 with read lock; connection con1; # Wait till FLUSH TABLES <list> WITH READ LOCK stops. set debug_sync='now WAIT_FOR parked'; +flush tables; # Start a statement which will flush all tables and thus # invalidate table t1 open by FLUSH TABLES <list> WITH READ LOCK. # Sending: -flush tables; +flush tables t1; connection default; # Wait till the above FLUSH TABLES blocks. # Resume FLUSH TABLES <list> WITH READ LOCK, so it tries to open t2 @@ -2513,6 +2514,12 @@ connection con2; SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; # Check that FLUSH must wait to get the GRL # and let DROP PROCEDURE continue +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_DDL Backup lock +MDL_EXCLUSIVE Stored procedure metadata lock test p1 +MDL_INTENTION_EXCLUSIVE Schema metadata lock test +MDL_SHARED_WRITE Table metadata lock mysql proc SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL grlwait'; FLUSH TABLES WITH READ LOCK; connection default; @@ -2527,6 +2534,43 @@ connection con2; UNLOCK TABLES; connection default; SET DEBUG_SYNC= 'RESET'; +# +# UPDATE should wait for FTWRL with non transactional table second +# +create table t1 (a int) engine=myisam; +create table t2 (a int) engine=innodb; +insert into t1 values (1); +insert into t2 values (1); +SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait execute 2'; +update t1,t2 set t1.a=2,t2.a=3; +connection con2; +SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; +SET DEBUG_SYNC= 'now SIGNAL grlwait'; +SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL grlwait'; +FLUSH TABLES WITH READ LOCK; +connection default; +# Reaping UPDATE +connection con2; +UNLOCK TABLES; +connection default; +SET DEBUG_SYNC= 'RESET'; +SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait execute 2'; +update t2,t1 set t1.a=2,t2.a=3; +connection con2; +SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; +SET DEBUG_SYNC= 'now SIGNAL grlwait'; +SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL grlwait'; +FLUSH TABLES WITH READ LOCK; +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; +LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME +MDL_BACKUP_FTWRL2 Backup lock +unlock tables; +connection default; +# Reaping UPDATE +SET DEBUG_SYNC= 'RESET'; +drop table t1,t2; disconnect con2; # # Bug#50786 Assertion `thd->mdl_context.trans_sentinel() == __null' @@ -2534,7 +2578,6 @@ disconnect con2; # # Supress warnings written to the log file call mtr.add_suppression("Wait on a lock was aborted due to a pending exclusive lock"); -DROP TABLE IF EXISTS t1, t2; connect con1,localhost,root; connect con2,localhost,root; connect con3,localhost,root; @@ -3055,7 +3098,7 @@ disconnect con3; # CREATE TABLE t1(a INT) ENGINE=InnoDB; SET debug_sync='open_tables_after_open_and_process_table SIGNAL ready WAIT_FOR go'; -SELECT * FROM t1; +INSERT INTO t1 values (1); connect con1,localhost,root,,; SET debug_sync='now WAIT_FOR ready'; SET lock_wait_timeout=1; @@ -3063,7 +3106,21 @@ FLUSH TABLES WITH READ LOCK; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET debug_sync='now SIGNAL go'; connection default; +# After MDEV-5536, SELECT will not block FLUSH TABLES +SET debug_sync='RESET'; +SET debug_sync='open_tables_after_open_and_process_table SIGNAL ready WAIT_FOR go'; +SELECT * FROM t1; +connection con1; +SET debug_sync='now WAIT_FOR ready'; +SET lock_wait_timeout=1; +FLUSH TABLES WITH READ LOCK; +SET debug_sync='now SIGNAL go'; +connection default; a +1 +connection con1; +unlock tables; +connection default; SET debug_sync='RESET'; DROP TABLE t1; disconnect con1; diff --git a/mysql-test/main/mdl_sync.test b/mysql-test/main/mdl_sync.test index fbecd6bf547..2a1e488ab44 100644 --- a/mysql-test/main/mdl_sync.test +++ b/mysql-test/main/mdl_sync.test @@ -2,6 +2,7 @@ # We need the Debug Sync Facility. # --source include/have_debug_sync.inc +--source include/have_metadata_lock_info.inc # We need InnoDB tables for some of the tests. --source include/have_innodb.inc @@ -2690,17 +2691,20 @@ connection con1; --echo # Wait till FLUSH TABLES <list> WITH READ LOCK stops. set debug_sync='now WAIT_FOR parked'; +# Simple flush tables should not block +flush tables; + --echo # Start a statement which will flush all tables and thus --echo # invalidate table t1 open by FLUSH TABLES <list> WITH READ LOCK. --echo # Sending: -send flush tables; +send flush tables t1; connection default; --echo # Wait till the above FLUSH TABLES blocks. let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush" and - info = "flush tables"; + where state = "Waiting for table metadata lock" and + info = "flush tables t1"; --source include/wait_condition.inc --echo # Resume FLUSH TABLES <list> WITH READ LOCK, so it tries to open t2 @@ -3245,6 +3249,7 @@ connection con2; SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; --echo # Check that FLUSH must wait to get the GRL --echo # and let DROP PROCEDURE continue +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL grlwait'; --send FLUSH TABLES WITH READ LOCK @@ -3261,12 +3266,63 @@ connection con2; --echo # Reaping FTWRL. --reap UNLOCK TABLES; +connection default; +SET DEBUG_SYNC= 'RESET'; + +--echo # +--echo # UPDATE should wait for FTWRL with non transactional table second +--echo # + +create table t1 (a int) engine=myisam; +create table t2 (a int) engine=innodb; +insert into t1 values (1); +insert into t2 values (1); + +SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait execute 2'; +--send update t1,t2 set t1.a=2,t2.a=3 + +connection con2; +SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; +SET DEBUG_SYNC= 'now SIGNAL grlwait'; +SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL grlwait'; +FLUSH TABLES WITH READ LOCK; + +connection default; +--echo # Reaping UPDATE +--reap + +connection con2; +UNLOCK TABLES; connection default; SET DEBUG_SYNC= 'RESET'; -disconnect con2; +# This will cause a wait as we first get lock for innodb table t2 but FTWRL +# will cause lock for t1 to wait + +SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL table_opened WAIT_FOR grlwait execute 2'; +--send update t2,t1 set t1.a=2,t2.a=3 + +connection con2; +SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; +SET DEBUG_SYNC= 'now SIGNAL grlwait'; +SET DEBUG_SYNC= 'now WAIT_FOR table_opened'; +SET DEBUG_SYNC= 'mdl_acquire_lock_wait SIGNAL grlwait'; +FLUSH TABLES WITH READ LOCK; +let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.metadata_lock_info; +--source include/wait_condition.inc +SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; + +unlock tables; + +connection default; +--echo # Reaping UPDATE +--reap +SET DEBUG_SYNC= 'RESET'; +drop table t1,t2; +disconnect con2; --echo # --echo # Bug#50786 Assertion `thd->mdl_context.trans_sentinel() == __null' @@ -3275,9 +3331,6 @@ disconnect con2; --echo # Supress warnings written to the log file call mtr.add_suppression("Wait on a lock was aborted due to a pending exclusive lock"); ---disable_warnings -DROP TABLE IF EXISTS t1, t2; ---enable_warnings connect (con1,localhost,root); connect (con2,localhost,root); @@ -3966,7 +4019,7 @@ connection con2; connection default; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist - WHERE state='Waiting for global read lock' + WHERE state='Waiting for backup lock' AND info='CREATE TABLE db1.t2(a INT)'; --source include/wait_condition.inc UNLOCK TABLES; @@ -3984,7 +4037,7 @@ connection con2; connection default; let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist - WHERE state='Waiting for global read lock' + WHERE state='Waiting for backup lock' AND info='ALTER DATABASE db1 DEFAULT CHARACTER SET utf8'; --source include/wait_condition.inc UNLOCK TABLES; @@ -4079,9 +4132,10 @@ disconnect con3; --echo # MDEV-12620 - set lock_wait_timeout = 1;flush tables with read lock; --echo # lock not released after timeout --echo # + CREATE TABLE t1(a INT) ENGINE=InnoDB; SET debug_sync='open_tables_after_open_and_process_table SIGNAL ready WAIT_FOR go'; -send SELECT * FROM t1; +send INSERT INTO t1 values (1); connect (con1,localhost,root,,); SET debug_sync='now WAIT_FOR ready'; @@ -4093,12 +4147,31 @@ SET debug_sync='now SIGNAL go'; connection default; reap; + +--echo # After MDEV-5536, SELECT will not block FLUSH TABLES + +SET debug_sync='RESET'; +SET debug_sync='open_tables_after_open_and_process_table SIGNAL ready WAIT_FOR go'; +send SELECT * FROM t1; + +connection con1; +SET debug_sync='now WAIT_FOR ready'; +# lock_wait_timeout should be 0 in 10.3, so that we don't have to wait at all +SET lock_wait_timeout=1; +FLUSH TABLES WITH READ LOCK; +SET debug_sync='now SIGNAL go'; + +connection default; +reap; +connection con1; +unlock tables; +connection default; + SET debug_sync='RESET'; DROP TABLE t1; disconnect con1; - # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc diff --git a/mysql-test/main/merge.result b/mysql-test/main/merge.result index ff6bdf4a07e..4a3ca3d767e 100644 --- a/mysql-test/main/merge.result +++ b/mysql-test/main/merge.result @@ -2117,6 +2117,7 @@ CREATE TABLE t1(a INT, KEY(a)); INSERT INTO t1 VALUES(0),(1),(2),(3),(4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CREATE TABLE m1(a INT, KEY(a)) ENGINE=MERGE UNION=(t1); SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='m1'; @@ -2811,6 +2812,8 @@ CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST; CREATE TRIGGER tm1_ai AFTER INSERT ON tm1 FOR EACH ROW SELECT max(c1) FROM t1 INTO @var; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead LOCK TABLE tm1 WRITE, t1 WRITE; INSERT INTO tm1 VALUES (1); SELECT * FROM tm1; @@ -2835,6 +2838,8 @@ CREATE TABLE tm1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2,t3,t4,t5) INSERT_METHOD=LAST; CREATE TRIGGER t2_au AFTER UPDATE ON t2 FOR EACH ROW SELECT MAX(c1) FROM t1 INTO @var; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE FUNCTION f1() RETURNS INT RETURN (SELECT MAX(c1) FROM t4); LOCK TABLE tm1 WRITE, t1 WRITE, t2 WRITE, t3 WRITE, t4 WRITE, t5 WRITE; @@ -3814,11 +3819,15 @@ CREATE TABLE tmerge (f1 INT) ENGINE=MERGE UNION=(t1); PREPARE stmt FROM "ANALYZE TABLE tmerge, t1"; EXECUTE stmt; Table Op Msg_type Msg_text +test.tmerge analyze status Engine-independent statistics collected test.tmerge analyze note The storage engine for the table doesn't support analyze +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date EXECUTE stmt; Table Op Msg_type Msg_text +test.tmerge analyze status Engine-independent statistics collected test.tmerge analyze note The storage engine for the table doesn't support analyze +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date DEALLOCATE PREPARE stmt; DROP TABLE t1, tmerge; diff --git a/mysql-test/main/mix2_myisam.result b/mysql-test/main/mix2_myisam.result index 34764466d2a..5acec2616fa 100644 --- a/mysql-test/main/mix2_myisam.result +++ b/mysql-test/main/mix2_myisam.result @@ -211,6 +211,7 @@ create index skr on t1 (a); insert into t1 values (3,""), (4,"testing"); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/mysql-test/main/multi_update.result b/mysql-test/main/multi_update.result index c40de47668a..d2a33619900 100644 --- a/mysql-test/main/multi_update.result +++ b/mysql-test/main/multi_update.result @@ -603,11 +603,11 @@ CREATE TABLE t1 (f1 DATE); INSERT INTO t1 VALUES('2001-01-01'); UPDATE IGNORE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1; Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' CREATE view v1 as SELECT f1() FROM t1; UPDATE IGNORE (SELECT 1 FROM t1 WHERE f1 = (select * from v1)) x, t1 SET f1 = 1; Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' DROP VIEW v1; DROP FUNCTION f1; DROP TABLE t1; @@ -998,8 +998,8 @@ a b c a b c set optimizer_switch='firstmatch=off'; explain update t1, t2 set t2.c=1 where t1.a=t2.a and t1.b in (select b from t3 where t3.c< t2.c) order by t2.c, t1.c limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using temporary; Using filesort -1 PRIMARY t1 ALL a NULL NULL NULL 10 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 10 Using where; Using temporary; Using filesort +1 PRIMARY t1 ref a a 5 test.t2.a 1 1 PRIMARY t3 ALL NULL NULL NULL NULL 10 Using where; Start temporary; End temporary update t1, t2 set t2.c=1 where t1.a=t2.a and t1.b in (select b from t3 where t3.c<=t2.c) order by t2.c, t1.c limit 5; select * from t2; diff --git a/mysql-test/main/myisam.result b/mysql-test/main/myisam.result index 4864ef0bb13..c0e44d71abc 100644 --- a/mysql-test/main/myisam.result +++ b/mysql-test/main/myisam.result @@ -676,6 +676,7 @@ insert into t1 values (0),(1),(2),(3),(4); insert into t1 select NULL from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -696,6 +697,7 @@ insert into t1 values (11); delete from t1 where a=11; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -707,7 +709,7 @@ Table Op Msg_type Msg_text test.t1 check status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment -t1 1 a 1 a A 5 NULL NULL YES BTREE +t1 1 a 1 a A 10 NULL NULL YES BTREE set myisam_stats_method=DEFAULT; show variables like 'myisam_stats_method'; Variable_name Value @@ -716,6 +718,7 @@ insert into t1 values (11); delete from t1 where a=11; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -743,6 +746,7 @@ insert into t1 values ('bce','def1', 'yuu', NULL); insert into t1 values ('bce','def2', NULL, 'quux'); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -753,6 +757,7 @@ t1 1 a 4 d A 4 NULL NULL YES BTREE delete from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -1801,6 +1806,7 @@ create table t1 (a int, key(a)); insert into t1 values (1),(2),(3),(4),(NULL),(NULL),(NULL),(NULL); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -2545,7 +2551,7 @@ INSERT INTO t1 VALUES ('0'),('0'),('0'),('0'),('0'),('0'),('0'); Warnings: Error 1034 myisam_sort_buffer_size is too small. X -Error 1034 Number of rows changed from 0 to 157 +Warning 1034 Number of rows changed from 0 to 157 SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; INSERT INTO t1 VALUES('1'); SELECT * FROM t1, t1 AS a1 WHERE t1.a=1 AND a1.a=1; diff --git a/mysql-test/main/myisam_debug.result b/mysql-test/main/myisam_debug.result index 6232e3eac0e..9cba8968116 100644 --- a/mysql-test/main/myisam_debug.result +++ b/mysql-test/main/myisam_debug.result @@ -23,6 +23,8 @@ SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'wait_in_enable_indexes' AND INFO = "INSERT INTO t1(id) SELECT id FROM t2" INTO @thread_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead KILL QUERY @thread_id; CHECK TABLE t1; Table Op Msg_type Msg_text diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result index 09e662f5d6a..d238b0d9901 100644 --- a/mysql-test/main/myisam_explain_non_select_all.result +++ b/mysql-test/main/myisam_explain_non_select_all.result @@ -7,6 +7,8 @@ INSERT INTO t1 VALUES (1), (2), (3); # query: UPDATE t1 SET a = 10 WHERE a < 10 # select: SELECT * FROM t1 WHERE a < 10 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET a = 10 WHERE a < 10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where @@ -26,8 +28,12 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 10 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 4 # Status of testing query execution: Variable_name Value @@ -42,6 +48,8 @@ INSERT INTO t1 VALUES (1), (2), (3); # query: DELETE FROM t1 WHERE a < 10 # select: SELECT * FROM t1 WHERE a < 10 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE a < 10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where @@ -52,6 +60,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 2 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE a < 10; @@ -61,12 +70,17 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 10 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 4 # Status of testing query execution: Variable_name Value Handler_delete 3 +Handler_read_key 2 Handler_read_rnd_next 4 DROP TABLE t1; @@ -77,6 +91,8 @@ INSERT INTO t1 VALUES (1), (2), (3); # query: DELETE FROM t1 USING t1 WHERE a = 1 # select: SELECT * FROM t1 WHERE a = 1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 USING t1 WHERE a = 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where @@ -87,6 +103,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 2 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = 1; @@ -96,12 +113,17 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 4 # Status of testing query execution: Variable_name Value Handler_delete 1 +Handler_read_key 2 Handler_read_rnd_next 4 DROP TABLE t1; @@ -114,6 +136,8 @@ INSERT INTO t2 VALUES (1), (2), (3); # query: UPDATE t1, t2 SET t1.a = 10 WHERE t1.a = 1 # select: SELECT * FROM t1, t2 WHERE t1.a = 1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1, t2 SET t1.a = 10 WHERE t1.a = 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where @@ -136,8 +160,12 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 8 # Status of testing query execution: Variable_name Value @@ -154,6 +182,8 @@ INSERT INTO t2 VALUES (1), (2), (3); # query: UPDATE t1 t11, (SELECT * FROM t2) t12 SET t11.a = 10 WHERE t11.a = 1 # select: SELECT * FROM t1 t11, (SELECT * FROM t2) t12 WHERE t11.a = 1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 t11, (SELECT * FROM t2) t12 SET t11.a = 10 WHERE t11.a = 1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t11 ALL NULL NULL NULL NULL 3 Using where @@ -178,8 +208,12 @@ Warnings: Note 1003 select `test`.`t11`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` `t11` join `test`.`t2` where `test`.`t11`.`a` = 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 8 # Status of testing query execution: Variable_name Value @@ -196,6 +230,8 @@ INSERT INTO t2 VALUES (1), (2), (3); # query: UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3) # select: SELECT * FROM t1 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3) # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 @@ -220,9 +256,12 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`b` < 3 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 5 Handler_read_rnd_next 8 # Status of testing query execution: Variable_name Value @@ -239,6 +278,8 @@ INSERT INTO t2 VALUES (1), (2), (3); # query: UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3) # select: SELECT * FROM t1 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3) # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where @@ -264,8 +305,12 @@ Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`b` = `test`.`t1`.`a` and `test`.`t1`.`a` < 3 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 8 # Status of testing query execution: Variable_name Value @@ -282,6 +327,8 @@ INSERT INTO t2 VALUES (1), (2), (3); # query: UPDATE t1, t2 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t2.b < 3) # select: SELECT * FROM t1, t2 WHERE a IN (SELECT b FROM t2 WHERE t2.b < 3) # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1, t2 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t2.b < 3); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 @@ -310,9 +357,12 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` semi join (`test`.`t2`) join `test`.`t2` where `test`.`t2`.`b` < 3 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 3 +Handler_read_key 7 Handler_read_rnd_next 12 # Status of testing query execution: Variable_name Value @@ -330,6 +380,8 @@ INSERT INTO t2 VALUES (1), (2), (3); # query: UPDATE t1 t11, (SELECT * FROM t2) t12 SET t11.a = t11.a + 10 # select: SELECT * FROM t1 t11, (SELECT * FROM t2) t12 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 t11, (SELECT * FROM t2) t12 SET t11.a = t11.a + 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t11 ALL NULL NULL NULL NULL 3 @@ -354,8 +406,12 @@ Warnings: Note 1003 select `test`.`t11`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` `t11` join `test`.`t2` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 8 # Status of testing query execution: Variable_name Value @@ -374,6 +430,8 @@ INSERT INTO t2 VALUES (1), (2), (3); # query: UPDATE t1 t11, (SELECT 1 FROM DUAL) t12 SET t11.a = t11.a + 10 # select: SELECT * FROM t1 t11, (SELECT 1 FROM DUAL) t12 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 t11, (SELECT 1 FROM DUAL) t12 SET t11.a = t11.a + 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY <derived2> system NULL NULL NULL NULL 1 @@ -400,9 +458,13 @@ Warnings: Note 1003 /* select#1 */ select `test`.`t11`.`a` AS `a`,1 AS `1` from `test`.`t1` `t11` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 1 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 5 # Status of testing query execution: Variable_name Value @@ -420,6 +482,8 @@ INSERT INTO t2 VALUES (1), (2), (3); # query: UPDATE t1 t11, (SELECT * FROM t2) t12 SET t11.a = 10 WHERE t11.a > 1 # select: SELECT * FROM t1 t11, (SELECT * FROM t2) t12 WHERE t11.a > 1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 t11, (SELECT * FROM t2) t12 SET t11.a = 10 WHERE t11.a > 1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t11 ALL NULL NULL NULL NULL 3 Using where @@ -444,8 +508,12 @@ Warnings: Note 1003 select `test`.`t11`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` `t11` join `test`.`t2` where `test`.`t11`.`a` > 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 8 # Status of testing query execution: Variable_name Value @@ -460,6 +528,8 @@ INSERT INTO t1 VALUES (1), (2), (3); # query: DELETE FROM t1 WHERE a > 1 LIMIT 1 # select: SELECT * FROM t1 WHERE a > 1 LIMIT 1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE a > 1 LIMIT 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where @@ -470,6 +540,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 2 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE a > 1 LIMIT 1; @@ -479,12 +550,17 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1 limit 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 2 # Status of testing query execution: Variable_name Value Handler_delete 1 +Handler_read_key 2 Handler_read_rnd_next 2 DROP TABLE t1; @@ -495,6 +571,8 @@ INSERT INTO t1 VALUES (1), (2), (3); # query: DELETE FROM t1 WHERE 0 # select: SELECT * FROM t1 WHERE 0 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE 0; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE @@ -505,6 +583,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 2 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE 0; @@ -514,10 +593,15 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 # Status of testing query execution: Variable_name Value +Handler_read_key 2 DROP TABLE t1; #13 @@ -527,6 +611,8 @@ INSERT INTO t1 VALUES (1), (2), (3); # query: DELETE FROM t1 USING t1 WHERE 0 # select: SELECT * FROM t1 WHERE 0 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 USING t1 WHERE 0; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE @@ -537,6 +623,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 2 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE 0; @@ -546,10 +633,15 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 # Status of testing query execution: Variable_name Value +Handler_read_key 2 DROP TABLE t1; #14 @@ -559,6 +651,8 @@ INSERT INTO t1 VALUES (3, 3), (7, 7); # query: DELETE FROM t1 WHERE a = 3 # select: SELECT * FROM t1 WHERE a = 3 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE a = 3; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range a a 5 NULL 1 Using where @@ -569,6 +663,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 5 NULL 1 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 5 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE a = 3; @@ -578,14 +673,16 @@ Warnings: Note 1003 select 3 AS `a`,3 AS `b` from `test`.`t1` where 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value -Handler_read_key 1 +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 6 # Status of testing query execution: Variable_name Value Handler_delete 1 -Handler_read_key 1 +Handler_read_key 6 DROP TABLE t1; #15 @@ -595,6 +692,8 @@ INSERT INTO t1 VALUES (3, 3), (7, 7); # query: DELETE FROM t1 WHERE a < 3 # select: SELECT * FROM t1 WHERE a < 3 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE a < 3; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range a a 5 NULL 1 Using where @@ -605,6 +704,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 5 NULL 1 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 5 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE a < 3; @@ -614,12 +714,15 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` < 3 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 5 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 6 # Status of testing query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 6 DROP TABLE t1; #16 @@ -628,6 +731,8 @@ CREATE TABLE t1 ( a int PRIMARY KEY ); # query: DELETE FROM t1 WHERE t1.a > 0 ORDER BY t1.a # select: SELECT * FROM t1 WHERE t1.a > 0 ORDER BY t1.a # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE t1.a > 0 ORDER BY t1.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 Using where @@ -638,6 +743,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 3 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a > 0 ORDER BY t1.a; @@ -647,19 +753,25 @@ Warnings: Note 1003 select NULL AS `a` from `test`.`t1` where 0 order by NULL # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 3 Handler_read_rnd_next 1 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 3 Handler_read_rnd_next 1 # Status of testing query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 4 INSERT INTO t1 VALUES (1), (2), (3); # # query: DELETE FROM t1 WHERE t1.a > 0 ORDER BY t1.a # select: SELECT * FROM t1 WHERE t1.a > 0 ORDER BY t1.a # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE t1.a > 0 ORDER BY t1.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where @@ -670,6 +782,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 3 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE t1.a > 0 ORDER BY t1.a; @@ -679,14 +792,17 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 0 order by `test`.`t1`.`a` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 3 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 4 Handler_read_next 3 # Status of testing query execution: Variable_name Value Handler_delete 3 -Handler_read_key 1 +Handler_read_key 4 Handler_read_next 3 DROP TABLE t1; @@ -697,6 +813,8 @@ INSERT INTO t1 VALUES (4),(3),(1),(2); # query: DELETE FROM t1 WHERE (@a:= a) ORDER BY a LIMIT 1 # select: SELECT * FROM t1 WHERE (@a:= a) ORDER BY a LIMIT 1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE (@a:= a) ORDER BY a LIMIT 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 1 Using where @@ -707,6 +825,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 1 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 3 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE (@a:= a) ORDER BY a LIMIT 1; @@ -716,13 +835,18 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where @a:=`test`.`t1`.`a` order by `test`.`t1`.`a` limit 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 3 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value Handler_read_first 1 +Handler_read_key 3 # Status of testing query execution: Variable_name Value Handler_delete 1 Handler_read_first 1 +Handler_read_key 3 DROP TABLE t1; #18 @@ -733,6 +857,8 @@ UPDATE t1 SET a = c, b = c; # query: DELETE FROM t1 ORDER BY a ASC, b ASC LIMIT 1 # select: SELECT * FROM t1 ORDER BY a ASC, b ASC LIMIT 1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 ORDER BY a ASC, b ASC LIMIT 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using filesort @@ -743,6 +869,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 Using filesort # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 7 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 ORDER BY a ASC, b ASC LIMIT 1; @@ -752,8 +879,12 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` order by `test`.`t1`.`a`,`test`.`t1`.`b` limit 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 7 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 7 Handler_read_rnd_next 11 Sort_priority_queue_sorts 1 Sort_rows 1 @@ -761,6 +892,7 @@ Sort_scan 1 # Status of testing query execution: Variable_name Value Handler_delete 1 +Handler_read_key 7 Handler_read_rnd 1 Handler_read_rnd_next 11 Sort_rows 10 @@ -778,6 +910,8 @@ INSERT INTO t3 VALUES (1,1), (2,1), (1,3); # query: DELETE t1,t2,t3 FROM t1,t2,t3 WHERE a1=a2 AND b2=a3 AND b1=b3 # select: SELECT * FROM t1,t2,t3 WHERE a1=a2 AND b2=a3 AND b1=b3 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE t1,t2,t3 FROM t1,t2,t3 WHERE a1=a2 AND b2=a3 AND b1=b3; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 @@ -792,6 +926,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t3 eq_ref PRIMARY PRIMARY 8 test.t2.b2,test.t1.b1 1 100.00 # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 13 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1,t2,t3 WHERE a1=a2 AND b2=a3 AND b1=b3; @@ -803,15 +938,18 @@ Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b2` AS `b2`,`test`.`t3`.`a3` AS `a3`,`test`.`t3`.`b3` AS `b3` from `test`.`t1` join `test`.`t2` join `test`.`t3` where `test`.`t2`.`a2` = `test`.`t1`.`a1` and `test`.`t3`.`a3` = `test`.`t2`.`b2` and `test`.`t3`.`b3` = `test`.`t1`.`b1` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 13 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 6 +Handler_read_key 19 Handler_read_next 3 Handler_read_rnd_next 4 # Status of testing query execution: Variable_name Value Handler_delete 8 -Handler_read_key 6 +Handler_read_key 19 Handler_read_next 3 Handler_read_rnd 5 Handler_read_rnd_next 4 @@ -826,6 +964,8 @@ INSERT INTO t2 VALUES (1), (2), (3); # query: UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2) # select: SELECT * FROM t1 WHERE a IN (SELECT a FROM t2) # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where @@ -849,9 +989,12 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 3 +Handler_read_key 7 Handler_read_rnd_next 8 # Status of testing query execution: Variable_name Value @@ -869,6 +1012,8 @@ SET @save_optimizer_switch= @@optimizer_switch; # query: DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2) # select: SELECT * FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2) # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where @@ -881,6 +1026,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 4 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2); @@ -891,13 +1037,17 @@ Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(/* select#2 */ select `test`.`t2`.`a2` from `test`.`t2` where `test`.`t2`.`a2` > 2 and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`a2`))) # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 5 +Handler_read_key 9 Handler_read_rnd_next 30 # Status of testing query execution: Variable_name Value Handler_delete 3 +Handler_read_key 4 Handler_read_rnd_next 30 SET @@optimizer_switch= @save_optimizer_switch; @@ -907,6 +1057,8 @@ INSERT INTO t1 VALUES (1), (2), (3), (4), (5); # query: DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2) # select: SELECT * FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2) # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where @@ -919,6 +1071,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 4 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2); @@ -929,12 +1082,17 @@ Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`a2` > 2 and `test`.`t1`.`a1` = `test`.`t2`.`a2` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 12 # Status of testing query execution: Variable_name Value Handler_delete 3 +Handler_read_key 4 Handler_read_rnd_next 30 DROP TABLE t1, t2; @@ -945,6 +1103,8 @@ INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5); # query: UPDATE t1 SET i = 10 # select: SELECT * FROM t1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET i = 10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 5 @@ -964,8 +1124,12 @@ Warnings: Note 1003 select `test`.`t1`.`i` AS `i`,`test`.`t1`.`j` AS `j` from `test`.`t1` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 3 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 3 Handler_read_rnd_next 6 # Status of testing query execution: Variable_name Value @@ -980,6 +1144,8 @@ INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5); # query: DELETE FROM t1 # select: SELECT * FROM t1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL 5 Deleting all rows @@ -990,6 +1156,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL 5 NULL Deleting all rows # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 3 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1; @@ -999,11 +1166,16 @@ Warnings: Note 1003 select `test`.`t1`.`i` AS `i`,`test`.`t1`.`j` AS `j` from `test`.`t1` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 3 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 3 Handler_read_rnd_next 6 # Status of testing query execution: Variable_name Value +Handler_read_key 3 DROP TABLE t1; #24 @@ -1018,6 +1190,8 @@ INSERT INTO t2 (a, b, c) SELECT t1.i, t1.i, t1.i FROM t1, t1 x1, t1 x2; # query: DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # select: SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index NULL a 15 NULL 5 Using where @@ -1028,6 +1202,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 index NULL a 15 NULL 5 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 8 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -1037,14 +1212,19 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 8 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value Handler_read_first 1 +Handler_read_key 8 Handler_read_next 4 # Status of testing query execution: Variable_name Value Handler_delete 5 Handler_read_first 1 +Handler_read_key 8 Handler_read_next 4 DROP TABLE t1, t2; @@ -1056,6 +1236,8 @@ CREATE TABLE t2 (i INT); # query: INSERT INTO t2 SELECT * FROM t1 # select: SELECT * FROM t1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN INSERT INTO t2 SELECT * FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 @@ -1066,6 +1248,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 4 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1; @@ -1075,11 +1258,16 @@ Warnings: Note 1003 select `test`.`t1`.`i` AS `i` from `test`.`t1` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 4 # Status of testing query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 4 Handler_write 3 @@ -1092,6 +1280,8 @@ CREATE TABLE t2 (i INT); # query: REPLACE INTO t2 SELECT * FROM t1 # select: SELECT * FROM t1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN REPLACE INTO t2 SELECT * FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 @@ -1102,6 +1292,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 4 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1; @@ -1111,11 +1302,16 @@ Warnings: Note 1003 select `test`.`t1`.`i` AS `i` from `test`.`t1` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 4 # Status of testing query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 4 Handler_write 3 @@ -1136,8 +1332,10 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 INSERT t1 ALL NULL NULL NULL NULL NULL 100.00 NULL # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 2 # Status of testing query execution: Variable_name Value +Handler_read_key 2 Handler_write 1 DROP TABLE t1; @@ -1157,8 +1355,10 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 INSERT t1 ALL NULL NULL NULL NULL NULL 100.00 NULL # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 2 # Status of testing query execution: Variable_name Value +Handler_read_key 2 Handler_write 1 DROP TABLE t1; @@ -1171,6 +1371,8 @@ INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), # query: DELETE FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5 # select: SELECT * FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 5 Using where @@ -1181,6 +1383,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 5 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 4 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; @@ -1190,14 +1393,17 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 5 Handler_read_next 4 # Status of testing query execution: Variable_name Value Handler_delete 5 -Handler_read_key 1 +Handler_read_key 5 Handler_read_next 4 DROP TABLE t1; @@ -1210,6 +1416,8 @@ INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), # query: DELETE FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5 # select: SELECT * FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort @@ -1220,6 +1428,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 4 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; @@ -1229,8 +1438,12 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 27 Sort_priority_queue_sorts 1 Sort_rows 5 @@ -1238,6 +1451,7 @@ Sort_scan 1 # Status of testing query execution: Variable_name Value Handler_delete 5 +Handler_read_key 4 Handler_read_rnd 5 Handler_read_rnd_next 27 Sort_rows 8 @@ -1255,6 +1469,8 @@ INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1; # query: DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # select: SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort @@ -1265,6 +1481,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 8 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -1274,8 +1491,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 8 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 8 Handler_read_rnd_next 27 Sort_priority_queue_sorts 1 Sort_rows 1 @@ -1283,6 +1504,7 @@ Sort_scan 1 # Status of testing query execution: Variable_name Value Handler_delete 1 +Handler_read_key 8 Handler_read_rnd 1 Handler_read_rnd_next 27 Sort_rows 1 @@ -1301,6 +1523,8 @@ INSERT INTO t2 (a, b, c) SELECT t1.i, t1.i, t1.i FROM t1, t1 x1, t1 x2; # query: DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # select: SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index NULL a 15 NULL 5 Using where @@ -1311,6 +1535,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 index NULL a 15 NULL 5 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 8 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -1320,14 +1545,19 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 8 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value Handler_read_first 1 +Handler_read_key 8 Handler_read_next 4 # Status of testing query execution: Variable_name Value Handler_delete 5 Handler_read_first 1 +Handler_read_key 8 Handler_read_next 4 DROP TABLE t1, t2; @@ -1342,6 +1572,8 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1; # query: DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # select: SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort @@ -1352,6 +1584,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 8 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -1361,8 +1594,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 8 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 8 Handler_read_rnd_next 27 Sort_priority_queue_sorts 1 Sort_rows 1 @@ -1370,6 +1607,7 @@ Sort_scan 1 # Status of testing query execution: Variable_name Value Handler_delete 1 +Handler_read_key 8 Handler_read_rnd 1 Handler_read_rnd_next 27 Sort_rows 1 @@ -1388,6 +1626,8 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1; # query: DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # select: SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort @@ -1398,6 +1638,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using where; Using filesort # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 8 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5; @@ -1407,8 +1648,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 8 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 8 Handler_read_rnd 1 Handler_read_rnd_next 27 Sort_priority_queue_sorts 1 @@ -1417,6 +1662,7 @@ Sort_scan 1 # Status of testing query execution: Variable_name Value Handler_delete 1 +Handler_read_key 8 Handler_read_rnd 1 Handler_read_rnd_next 27 Sort_rows 1 @@ -1435,6 +1681,8 @@ INSERT INTO t2 (key1, key2) SELECT i, i FROM t1; # query: DELETE FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1 # select: SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index_merge key1,key2 key1,key2 5,5 NULL 7 Using sort_union(key1,key2); Using where; Using filesort @@ -1445,6 +1693,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 index_merge key1,key2 key1,key2 5,5 NULL 7 100.00 Using sort_union(key1,key2); Using where; Using filesort # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 6 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1; @@ -1454,9 +1703,12 @@ Warnings: Note 1003 select `test`.`t2`.`i` AS `i`,`test`.`t2`.`key1` AS `key1`,`test`.`t2`.`key2` AS `key2` from `test`.`t2` where `test`.`t2`.`key1` < 13 or `test`.`t2`.`key2` < 14 order by `test`.`t2`.`key1` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 2 +Handler_read_key 8 Handler_read_next 7 Handler_read_rnd 4 Sort_range 1 @@ -1464,7 +1716,7 @@ Sort_rows 4 # Status of testing query execution: Variable_name Value Handler_delete 4 -Handler_read_key 2 +Handler_read_key 8 Handler_read_next 7 Handler_read_rnd 8 Sort_range 1 @@ -1482,6 +1734,8 @@ INSERT INTO t2 (i) SELECT i FROM t1; # query: DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5 # select: SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 5 Using where @@ -1492,6 +1746,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 5 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 4 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; @@ -1501,14 +1756,17 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` desc limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 5 Handler_read_prev 4 # Status of testing query execution: Variable_name Value Handler_delete 5 -Handler_read_key 1 +Handler_read_key 5 Handler_read_prev 4 DROP TABLE t1, t2; @@ -1523,6 +1781,8 @@ INSERT INTO t2 SELECT i, i, i FROM t1; # query: DELETE FROM t2 ORDER BY a, b DESC LIMIT 5 # select: SELECT * FROM t2 ORDER BY a, b DESC LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t2 ORDER BY a, b DESC LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using filesort @@ -1533,6 +1793,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 100.00 Using filesort # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 6 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2 ORDER BY a, b DESC LIMIT 5; @@ -1542,8 +1803,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` order by `test`.`t2`.`a`,`test`.`t2`.`b` desc limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 6 Handler_read_rnd_next 27 Sort_priority_queue_sorts 1 Sort_rows 5 @@ -1551,6 +1816,7 @@ Sort_scan 1 # Status of testing query execution: Variable_name Value Handler_delete 5 +Handler_read_key 6 Handler_read_rnd 5 Handler_read_rnd_next 27 Sort_rows 26 @@ -1569,6 +1835,8 @@ INSERT INTO t2 (a, b) SELECT t1.i, t1.i FROM t1, t1 x1, t1 x2; # query: DELETE FROM t2 ORDER BY a DESC, b DESC LIMIT 5 # select: SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t2 ORDER BY a DESC, b DESC LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index NULL a 6 NULL 5 @@ -1579,6 +1847,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 index NULL a 6 NULL 5 100.00 # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 6 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5; @@ -1588,13 +1857,18 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` order by `test`.`t2`.`a` desc,`test`.`t2`.`b` desc limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 6 Handler_read_last 1 Handler_read_prev 4 # Status of testing query execution: Variable_name Value Handler_delete 5 +Handler_read_key 6 Handler_read_last 1 Handler_read_prev 4 @@ -1610,6 +1884,8 @@ INSERT INTO t2 (i) SELECT i FROM t1; # query: UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5 # select: SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 5 Using where; Using buffer @@ -1629,9 +1905,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 5 Handler_read_next 4 # Status of testing query execution: Variable_name Value @@ -1652,6 +1931,8 @@ INSERT INTO t2 (i) SELECT i FROM t1; # query: UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5 # select: SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort @@ -1671,8 +1952,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 27 Sort_priority_queue_sorts 1 Sort_rows 5 @@ -1698,6 +1983,8 @@ INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1; # query: UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5 # select: SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort @@ -1717,8 +2004,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 8 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 8 Handler_read_rnd_next 27 Sort_priority_queue_sorts 1 Sort_rows 1 @@ -1745,6 +2036,8 @@ INSERT INTO t2 (a, b, c) SELECT t1.i, t1.i, t1.i FROM t1, t1 x1, t1 x2; # query: UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5 # select: SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index NULL a 15 NULL 5 Using where; Using buffer @@ -1764,9 +2057,13 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 8 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value Handler_read_first 1 +Handler_read_key 8 Handler_read_next 4 # Status of testing query execution: Variable_name Value @@ -1787,6 +2084,8 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1; # query: UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5 # select: SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort @@ -1806,8 +2105,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 8 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 8 Handler_read_rnd_next 27 Sort_priority_queue_sorts 1 Sort_rows 1 @@ -1833,6 +2136,8 @@ INSERT INTO t2 SELECT i, i, i, i FROM t1; # query: UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5 # select: SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using where; Using filesort @@ -1852,8 +2157,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d` from `test`.`t2` where `test`.`t2`.`b` = 10 order by `test`.`t2`.`a`,`test`.`t2`.`c` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 8 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 8 Handler_read_rnd 1 Handler_read_rnd_next 27 Sort_priority_queue_sorts 1 @@ -1880,6 +2189,8 @@ INSERT INTO t2 (key1, key2) SELECT i, i FROM t1; # query: UPDATE t2 SET i = 123 WHERE key1 < 13 or key2 < 14 ORDER BY key1 # select: SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t2 SET i = 123 WHERE key1 < 13 or key2 < 14 ORDER BY key1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index_merge key1,key2 key1,key2 5,5 NULL 7 Using sort_union(key1,key2); Using where; Using filesort @@ -1899,9 +2210,12 @@ Warnings: Note 1003 select `test`.`t2`.`i` AS `i`,`test`.`t2`.`key1` AS `key1`,`test`.`t2`.`key2` AS `key2` from `test`.`t2` where `test`.`t2`.`key1` < 13 or `test`.`t2`.`key2` < 14 order by `test`.`t2`.`key1` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 2 +Handler_read_key 8 Handler_read_next 7 Handler_read_rnd 4 Sort_range 1 @@ -1927,6 +2241,8 @@ INSERT INTO t2 (i) SELECT i FROM t1; # query: UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5 # select: SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 5 Using where; Using buffer @@ -1946,9 +2262,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` desc limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 5 Handler_read_prev 4 # Status of testing query execution: Variable_name Value @@ -1969,6 +2288,8 @@ INSERT INTO t2 SELECT i, i, i FROM t1; # query: UPDATE t2 SET c = 10 ORDER BY a, b DESC LIMIT 5 # select: SELECT * FROM t2 ORDER BY a, b DESC LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t2 SET c = 10 ORDER BY a, b DESC LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 26 Using filesort @@ -1988,8 +2309,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` order by `test`.`t2`.`a`,`test`.`t2`.`b` desc limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 6 Handler_read_rnd_next 27 Sort_priority_queue_sorts 1 Sort_rows 5 @@ -2016,6 +2341,8 @@ INSERT INTO t2 (a, b) SELECT t1.i, t1.i FROM t1, t1 x1, t1 x2; # query: UPDATE t2 SET c = 10 ORDER BY a DESC, b DESC LIMIT 5 # select: SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t2 SET c = 10 ORDER BY a DESC, b DESC LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index NULL a 6 NULL 5 Using buffer @@ -2035,8 +2362,12 @@ Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` order by `test`.`t2`.`a` desc,`test`.`t2`.`b` desc limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 6 Handler_read_last 1 Handler_read_prev 4 # Status of testing query execution: @@ -2060,6 +2391,8 @@ INSERT INTO t1 VALUES (1,'y',1), (2,'n',2), (3,'y',3), (4,'n',4); # query: UPDATE t1 SET c2 = 0 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2 # select: SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET c2 = 0 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 Using where; Using filesort @@ -2079,9 +2412,12 @@ Warnings: Note 1003 select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where `test`.`t1`.`c1_idx` = 'y' order by `test`.`t1`.`pk` desc limit 2 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 7 Handler_read_next 2 Sort_priority_queue_sorts 1 Sort_range 1 @@ -2100,6 +2436,8 @@ Sort_rows 2 # query: DELETE FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2 # select: SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 Using where; Using filesort @@ -2110,6 +2448,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range c1_idx c1_idx 2 NULL 2 100.00 Using where; Using filesort # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 6 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1_idx = 'y' ORDER BY pk DESC LIMIT 2; @@ -2119,9 +2458,12 @@ Warnings: Note 1003 select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`c1_idx` AS `c1_idx`,`test`.`t1`.`c2` AS `c2` from `test`.`t1` where `test`.`t1`.`c1_idx` = 'y' order by `test`.`t1`.`pk` desc limit 2 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 7 Handler_read_next 2 Sort_priority_queue_sorts 1 Sort_range 1 @@ -2129,7 +2471,7 @@ Sort_rows 2 # Status of testing query execution: Variable_name Value Handler_delete 2 -Handler_read_key 1 +Handler_read_key 7 Handler_read_next 2 Handler_read_rnd 2 Sort_range 1 @@ -2143,6 +2485,8 @@ INSERT INTO t1 VALUES (),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),(),( # query: UPDATE t1 SET a=a+10 WHERE a > 34 # select: SELECT * FROM t1 WHERE a > 34 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET a=a+10 WHERE a > 34; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where; Using buffer @@ -2162,9 +2506,12 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 34 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 3 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 1 +Handler_read_key 4 Handler_read_next 2 # Status of testing query execution: Variable_name Value @@ -2182,6 +2529,8 @@ INSERT INTO t1 VALUES (1, 1, 10), (2, 2, 20); # query: UPDATE t1 LEFT JOIN t2 ON t1.c1 = t2.c1 SET t2.c2 = 10 # select: SELECT * FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 LEFT JOIN t2 ON t1.c1 = t2.c1 SET t2.c2 = 10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 system NULL NULL NULL NULL 0 Const row not found @@ -2205,9 +2554,13 @@ Warnings: Note 1003 select `test`.`t1`.`c1` AS `c1`,`test`.`t1`.`c2` AS `c2`,`test`.`t1`.`c3` AS `c3`,NULL AS `c1`,NULL AS `c2` from `test`.`t1` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 7 Handler_read_rnd_next 1 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 7 Handler_read_rnd_next 4 # Status of testing query execution: Variable_name Value @@ -2217,6 +2570,8 @@ Handler_read_rnd_next 4 # query: UPDATE t1 LEFT JOIN t2 ON t1.c1 = t2.c1 SET t2.c2 = 10 WHERE t1.c3 = 10 # select: SELECT * FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1 WHERE t1.c3 = 10 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 LEFT JOIN t2 ON t1.c1 = t2.c1 SET t2.c2 = 10 WHERE t1.c3 = 10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 system NULL NULL NULL NULL 0 Const row not found @@ -2240,9 +2595,13 @@ Warnings: Note 1003 select `test`.`t1`.`c1` AS `c1`,`test`.`t1`.`c2` AS `c2`,`test`.`t1`.`c3` AS `c3`,NULL AS `c1`,NULL AS `c2` from `test`.`t1` where `test`.`t1`.`c3` = 10 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 7 Handler_read_rnd_next 1 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 7 Handler_read_rnd_next 4 # Status of testing query execution: Variable_name Value @@ -2259,6 +2618,8 @@ INSERT INTO t2 VALUES(1,1),(2,2); # query: UPDATE t1 SET t1.f2=(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1) # select: SELECT (SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1) FROM t1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET t1.f2=(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 @@ -2284,9 +2645,12 @@ Note 1276 Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select <expr_cache><`test`.`t1`.`f1`>((/* select#2 */ select max(`test`.`t2`.`f4`) from `test`.`t2` where `test`.`t2`.`f3` = `test`.`t1`.`f1`)) AS `(SELECT MAX(t2.f4) FROM t2 WHERE t2.f3=t1.f1)` from `test`.`t1` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 7 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 2 +Handler_read_key 9 Handler_read_rnd_next 9 # Status of testing query execution: Variable_name Value @@ -2325,6 +2689,8 @@ CREATE VIEW v1 AS SELECT t11.a, t12.a AS b FROM t1 t11, t1 t12; # query: UPDATE v1 SET a = 1 WHERE a > 0 # select: SELECT * FROM v1 WHERE a > 0 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE v1 SET a = 1 WHERE a > 0; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t11 ALL NULL NULL NULL NULL 2 Using where @@ -2347,8 +2713,12 @@ Warnings: Note 1003 select `test`.`t11`.`a` AS `a`,`test`.`t12`.`a` AS `b` from `test`.`t1` `t11` join `test`.`t1` `t12` where `test`.`t11`.`a` > 0 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 6 # Status of testing query execution: Variable_name Value @@ -2360,6 +2730,8 @@ Handler_read_rnd_next 8 # query: UPDATE t1, v1 SET v1.a = 1 WHERE t1.a = v1.a # select: SELECT * FROM t1, v1 WHERE t1.a = v1.a # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1, v1 SET v1.a = 1 WHERE t1.a = v1.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 @@ -2385,8 +2757,12 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t11`.`a` AS `a`,`test`.`t12`.`a` AS `b` from `test`.`t1` join `test`.`t1` `t11` join `test`.`t1` `t12` where `test`.`t11`.`a` = `test`.`t1`.`a` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 9 # Status of testing query execution: Variable_name Value @@ -2405,6 +2781,8 @@ CREATE VIEW v1 (a) AS SELECT a FROM t1; # query: DELETE FROM v1 WHERE a < 4 # select: SELECT * FROM v1 WHERE a < 4 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE FROM v1 WHERE a < 4; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where @@ -2415,6 +2793,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 3 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM v1 WHERE a < 4; @@ -2424,14 +2803,19 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 4 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 3 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value Handler_read_first 1 +Handler_read_key 3 Handler_read_next 3 # Status of testing query execution: Variable_name Value Handler_delete 3 Handler_read_first 1 +Handler_read_key 3 Handler_read_next 3 DROP TABLE t1; @@ -2446,6 +2830,8 @@ CREATE VIEW v1 (a,c) AS SELECT a, b+1 FROM t1; # query: DELETE v1 FROM t2, v1 WHERE t2.x = v1.a # select: SELECT * FROM t2, v1 WHERE t2.x = v1.a # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE v1 FROM t2, v1 WHERE t2.x = v1.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 4 Using where @@ -2458,6 +2844,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.x 1 100.00 # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 6 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2, v1 WHERE t2.x = v1.a; @@ -2468,14 +2855,17 @@ Warnings: Note 1003 select `test`.`t2`.`x` AS `x`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` + 1 AS `c` from `test`.`t2` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t2`.`x` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 4 +Handler_read_key 10 Handler_read_rnd_next 5 # Status of testing query execution: Variable_name Value Handler_delete 4 -Handler_read_key 4 +Handler_read_key 10 Handler_read_rnd 4 Handler_read_rnd_next 5 @@ -2491,6 +2881,8 @@ CREATE VIEW v1 (a,c) AS SELECT a, b+1 FROM t1; # query: DELETE v1 FROM t2, v1 WHERE t2.x = v1.a # select: SELECT * FROM t2, v1 WHERE t2.x = v1.a # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN DELETE v1 FROM t2, v1 WHERE t2.x = v1.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 4 Using where @@ -2503,6 +2895,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.x 1 100.00 # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 6 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT * FROM t2, v1 WHERE t2.x = v1.a; @@ -2513,14 +2906,17 @@ Warnings: Note 1003 select `test`.`t2`.`x` AS `x`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` + 1 AS `c` from `test`.`t2` join `test`.`t1` where `test`.`t1`.`a` = `test`.`t2`.`x` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 6 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 4 +Handler_read_key 10 Handler_read_rnd_next 5 # Status of testing query execution: Variable_name Value Handler_delete 4 -Handler_read_key 4 +Handler_read_key 10 Handler_read_rnd 4 Handler_read_rnd_next 5 @@ -2543,6 +2939,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 INSERT t1 ALL NULL NULL NULL NULL NULL 100.00 NULL # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 2 FLUSH STATUS; FLUSH TABLES; EXPLAIN EXTENDED SELECT NULL; @@ -2556,6 +2953,7 @@ Variable_name Value Variable_name Value # Status of testing query execution: Variable_name Value +Handler_read_key 2 Handler_write 1 DROP TABLE t1; @@ -2569,6 +2967,8 @@ CREATE VIEW v1 (x) AS SELECT b FROM t2; # query: INSERT INTO v1 SELECT * FROM t1 # select: SELECT * FROM t1 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN INSERT INTO v1 SELECT * FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 0 Const row not found @@ -2579,6 +2979,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 Const row not found # Status of EXPLAIN EXTENDED query Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 1 FLUSH STATUS; FLUSH TABLES; @@ -2589,12 +2990,17 @@ Warnings: Note 1003 select NULL AS `a` from `test`.`t1` # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 1 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 2 Handler_read_rnd_next 1 # Status of testing query execution: Variable_name Value +Handler_read_key 4 Handler_read_rnd_next 1 DROP TABLE t1, t2; @@ -2614,6 +3020,8 @@ INSERT INTO t2 VALUES (1), (2), (3); # query: UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x) # select: SELECT * FROM t1 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x) # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where @@ -2640,9 +3048,12 @@ Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join ((/* select#3 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) where 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 3 +Handler_read_key 7 Handler_read_rnd_next 10 Sort_priority_queue_sorts 1 Sort_rows 3 @@ -2660,6 +3071,8 @@ Sort_scan 1 # query: UPDATE t1, t2 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x) # select: SELECT * FROM t1, t2 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x) # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1, t2 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 @@ -2691,9 +3104,12 @@ Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` semi join ((/* select#3 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) join `test`.`t2` where 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 3 +Handler_read_key 7 Handler_read_rnd_next 10 Sort_priority_queue_sorts 1 Sort_rows 3 @@ -2710,6 +3126,8 @@ Sort_scan 1 # query: UPDATE t1, (SELECT * FROM t2) y SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x) # select: SELECT * FROM t1, (SELECT * FROM t2) y WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x) # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1, (SELECT * FROM t2) y SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 @@ -2743,9 +3161,12 @@ Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` semi join ((/* select#4 */ select `test`.`t2`.`b` AS `b` from `test`.`t2` order by `test`.`t2`.`b` limit 2,2) `x`) join `test`.`t2` where 1 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 4 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value -Handler_read_key 3 +Handler_read_key 7 Handler_read_rnd_next 10 Sort_priority_queue_sorts 1 Sort_rows 3 @@ -2792,6 +3213,8 @@ INSERT INTO t1 VALUES (1), (2), (3), (4), (5); # query: UPDATE t1 SET a=a+1 WHERE a>10 # select: SELECT a t1 FROM t1 WHERE a>10 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET a=a+1 WHERE a>10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 Using where; Using buffer @@ -2811,9 +3234,13 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `t1` from `test`.`t1` where `test`.`t1`.`a` > 10 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 3 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value Handler_read_first 1 +Handler_read_key 3 Handler_read_next 5 # Status of testing query execution: Variable_name Value @@ -2824,6 +3251,8 @@ Handler_read_key 1 # query: UPDATE t1 SET a=a+1 WHERE a>10 ORDER BY a+20 # select: SELECT a t1 FROM t1 WHERE a>10 ORDER BY a+20 # +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead EXPLAIN UPDATE t1 SET a=a+1 WHERE a>10 ORDER BY a+20; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 Using where; Using filesort @@ -2843,8 +3272,12 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `t1` from `test`.`t1` where `test`.`t1`.`a` > 10 order by `test`.`t1`.`a` + 20 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value +Handler_read_key 3 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Status of "equivalent" SELECT query execution: Variable_name Value +Handler_read_key 3 Handler_read_rnd_next 6 Sort_scan 1 # Status of testing query execution: diff --git a/mysql-test/main/myisam_recover.result b/mysql-test/main/myisam_recover.result index 92df67b42d1..3a2c424c8b2 100644 --- a/mysql-test/main/myisam_recover.result +++ b/mysql-test/main/myisam_recover.result @@ -87,7 +87,7 @@ a 6 Warnings: Error 145 Table 't1' is marked as crashed and should be repaired -Error 1034 Number of rows changed from 3 to 6 +Warning 1034 Number of rows changed from 3 to 6 # # Cleanup # @@ -139,7 +139,7 @@ a 4 Warnings: Error 145 Table 't1' is marked as crashed and should be repaired -Error 1034 Number of rows changed from 1 to 2 +Warning 1034 Number of rows changed from 1 to 2 connect con2, localhost, root; ALTER TABLE t2 ADD val INT; connection default; diff --git a/mysql-test/main/mysql_install_db_win.result b/mysql-test/main/mysql_install_db_win.result new file mode 100644 index 00000000000..63c922a9184 --- /dev/null +++ b/mysql-test/main/mysql_install_db_win.result @@ -0,0 +1,13 @@ +Running bootstrap +Removing default user +Allowing remote access for user root +Setting root password +Creating my.ini file +Creation of the database was successful +# Kill the server +connect root,localhost,root,foo; +SELECT @@datadir; +@@datadir +DATADIR/ +# Kill the server +connection default; diff --git a/mysql-test/main/mysql_install_db_win.test b/mysql-test/main/mysql_install_db_win.test new file mode 100644 index 00000000000..7bf62903219 --- /dev/null +++ b/mysql-test/main/mysql_install_db_win.test @@ -0,0 +1,24 @@ +--source include/windows.inc + +# Create database in tmp directory using mysql_install_db.exe, +# and start server from this directory. +let $ddir= $MYSQLTEST_VARDIR/tmp/ddir; +exec $MYSQL_INSTALL_DB_EXE --datadir=$ddir --password=foo -R; + +--source include/kill_mysqld.inc +let $restart_parameters=--datadir=$ddir --loose-innodb; +--source include/start_mysqld.inc + +connect root,localhost,root,foo; +# Smoke test - check that we're actually using datadir +# we've created (i.e restart_parameters worked) +--replace_result $ddir DATADIR +SELECT @@datadir; + +# restart in the original datadir again +--source include/kill_mysqld.inc +rmdir $ddir; +let $restart_parameters=; +connection default; +--source include/start_mysqld.inc + diff --git a/mysql-test/main/mysql_protocols.result b/mysql-test/main/mysql_protocols.result index c6207c4f4f5..746e4a46100 100644 --- a/mysql-test/main/mysql_protocols.result +++ b/mysql-test/main/mysql_protocols.result @@ -5,6 +5,7 @@ TCP SOCKET ok ERROR 2047 (HY000): Wrong or unknown protocol -ERROR 2047 (HY000): Wrong or unknown protocol +Unknown option to protocol: MEMORY +Alternatives are: 'TCP','SOCKET','PIPE' Unknown option to protocol: NullS -Alternatives are: 'TCP','SOCKET','PIPE','MEMORY' +Alternatives are: 'TCP','SOCKET','PIPE' diff --git a/mysql-test/main/mysql_upgrade-6984.result b/mysql-test/main/mysql_upgrade-6984.result index 6c711b4847f..87f3c1a5359 100644 --- a/mysql-test/main/mysql_upgrade-6984.result +++ b/mysql-test/main/mysql_upgrade-6984.result @@ -1,4 +1,4 @@ -update mysql.user set password=password("foo") where user='root'; +update mysql.global_priv set priv=json_set(priv, '$.plugin', 'mysql_native_password', '$.authentication_string', password('foo')); Phase 1/7: Checking and upgrading mysql database Processing databases mysql @@ -7,12 +7,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats Error : Unknown storage engine 'InnoDB' @@ -36,7 +36,6 @@ mysql.time_zone_transition_type OK mysql.transaction_registry Error : Unknown storage engine 'InnoDB' error : Corrupt -mysql.user OK Repairing tables mysql.innodb_index_stats @@ -50,6 +49,7 @@ Error : Unknown storage engine 'InnoDB' error : Corrupt Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -63,6 +63,6 @@ test Phase 7/7: Running 'FLUSH PRIVILEGES' OK connect con1,localhost,root,foo,,,; -update mysql.user set password='' where user='root'; +update mysql.global_priv set priv=json_remove(priv, '$.plugin', '$.authentication_string'); flush privileges; set global event_scheduler=OFF; diff --git a/mysql-test/main/mysql_upgrade-6984.test b/mysql-test/main/mysql_upgrade-6984.test index 9bbfbeb3f87..a036b7a08a0 100644 --- a/mysql-test/main/mysql_upgrade-6984.test +++ b/mysql-test/main/mysql_upgrade-6984.test @@ -11,13 +11,13 @@ # In this setup MYSQL_UPGRADE cannot continue after issuing FLUSH PRIVILEGES # -update mysql.user set password=password("foo") where user='root'; +update mysql.global_priv set priv=json_set(priv, '$.plugin', 'mysql_native_password', '$.authentication_string', password('foo')); --exec $MYSQL_UPGRADE connect(con1,localhost,root,foo,,,); -update mysql.user set password='' where user='root'; +update mysql.global_priv set priv=json_remove(priv, '$.plugin', '$.authentication_string'); flush privileges; # Load event table set global event_scheduler=OFF; diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result index 08efe0e8bc8..a99895f53d7 100644 --- a/mysql-test/main/mysql_upgrade.result +++ b/mysql-test/main/mysql_upgrade.result @@ -8,12 +8,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -31,9 +31,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -47,7 +47,7 @@ test Phase 7/7: Running 'FLUSH PRIVILEGES' OK Run it again - should say already completed -This installation of MySQL is already upgraded to VERSION, use --force if you still need to run mysql_upgrade +This installation of MariaDB is already upgraded to VERSION, use --force if you still need to run mysql_upgrade Force should run it regardless of whether it has been run before Phase 1/7: Checking and upgrading mysql database Processing databases @@ -57,12 +57,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -80,9 +80,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -106,12 +106,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -129,9 +129,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -160,12 +160,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -183,9 +183,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -215,12 +215,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -238,9 +238,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -273,12 +273,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -296,9 +296,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -326,12 +326,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -349,7 +349,6 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views... Skipped Phase 4/7: Running 'mysql_fix_privilege_tables' @@ -371,12 +370,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -394,9 +393,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -437,12 +436,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -460,9 +459,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -520,12 +519,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -543,9 +542,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables @@ -576,7 +575,7 @@ Start of 10.3 tests # Ensure that mysql_upgrade correctly sets truncate_versioning_priv # on upgrade from 10.2 # -flush privileges; +drop view mysql.user_bak; CREATE USER 'user3'@'%'; GRANT USAGE ON *.* TO 'user3'@'%'; GRANT ALL PRIVILEGES ON `roelt`.`test2` TO 'user3'@'%'; @@ -590,3 +589,5 @@ GRANT USAGE ON *.* TO 'user3'@'%' GRANT ALL PRIVILEGES ON `roelt`.`test2` TO 'user3'@'%' DROP USER 'user3'@'%'; update mysql.db set Delete_history_priv='Y' where db like 'test%'; +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; diff --git a/mysql-test/main/mysql_upgrade.test b/mysql-test/main/mysql_upgrade.test index 0171fe6c7ba..d4a3d864c21 100644 --- a/mysql-test/main/mysql_upgrade.test +++ b/mysql-test/main/mysql_upgrade.test @@ -227,7 +227,8 @@ SET GLOBAL enforce_storage_engine=NULL; --echo # on upgrade from 10.2 --echo # -flush privileges; +--source include/switch_to_mysql_user.inc +drop view mysql.user_bak; CREATE USER 'user3'@'%'; GRANT USAGE ON *.* TO 'user3'@'%'; GRANT ALL PRIVILEGES ON `roelt`.`test2` TO 'user3'@'%'; @@ -241,3 +242,5 @@ flush privileges; SHOW GRANTS FOR 'user3'@'%'; DROP USER 'user3'@'%'; update mysql.db set Delete_history_priv='Y' where db like 'test%'; +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; diff --git a/mysql-test/main/mysql_upgrade_no_innodb.result b/mysql-test/main/mysql_upgrade_no_innodb.result index 8e051bb7c16..35b55bb45e0 100644 --- a/mysql-test/main/mysql_upgrade_no_innodb.result +++ b/mysql-test/main/mysql_upgrade_no_innodb.result @@ -7,12 +7,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats Error : Unknown storage engine 'InnoDB' @@ -36,7 +36,6 @@ mysql.time_zone_transition_type OK mysql.transaction_registry Error : Unknown storage engine 'InnoDB' error : Corrupt -mysql.user OK Repairing tables mysql.innodb_index_stats diff --git a/mysql-test/main/mysql_upgrade_noengine.result b/mysql-test/main/mysql_upgrade_noengine.result index 7b3b1610ee0..79ad04e1849 100644 --- a/mysql-test/main/mysql_upgrade_noengine.result +++ b/mysql-test/main/mysql_upgrade_noengine.result @@ -1,3 +1,4 @@ +drop view mysql.user_bak; install soname 'ha_blackhole'; install soname 'ha_archive'; create table t1 (a int) engine=blackhole; @@ -61,12 +62,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv_bak OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -141,6 +142,9 @@ Warnings: Level Warning Code 1286 Message Unknown storage engine 'ARCHIVE' +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; +drop view mysql.user_bak; alter table mysql.user drop column default_role, drop column max_statement_time; Phase 1/7: Checking and upgrading mysql database Processing databases @@ -150,12 +154,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv_bak OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -230,6 +234,9 @@ Warnings: Level Warning Code 1286 Message Unknown storage engine 'ARCHIVE' +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; +drop view mysql.user_bak; alter table mysql.user drop column default_role, drop column max_statement_time; Phase 1/7: Checking and upgrading mysql database Processing databases @@ -239,12 +246,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv_bak OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -306,3 +313,5 @@ table_comment drop table t1, t2; uninstall plugin blackhole; uninstall plugin archive; +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; diff --git a/mysql-test/main/mysql_upgrade_noengine.test b/mysql-test/main/mysql_upgrade_noengine.test index 1d65e7ffa1c..e295f09eb4e 100644 --- a/mysql-test/main/mysql_upgrade_noengine.test +++ b/mysql-test/main/mysql_upgrade_noengine.test @@ -3,6 +3,8 @@ # source include/have_innodb.inc; source include/not_embedded.inc; +source include/switch_to_mysql_user.inc; +drop view mysql.user_bak; if (!$HA_BLACKHOLE_SO) { skip Need blackhole plugin; @@ -33,6 +35,11 @@ exec $MYSQL_UPGRADE 2>&1; select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test' and table_name='t1'; select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test' and table_name='t2'; +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; +source include/switch_to_mysql_user.inc; +drop view mysql.user_bak; + # pretend it's an upgrade from 10.0 alter table mysql.user drop column default_role, drop column max_statement_time; @@ -47,6 +54,11 @@ exec $MYSQL_UPGRADE 2>&1; select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test' and table_name='t1'; select table_catalog, table_schema, table_name, table_type, engine, row_format, table_rows, data_length, table_comment from information_schema.tables where table_schema='test' and table_name='t2'; +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; +source include/switch_to_mysql_user.inc; +drop view mysql.user_bak; + alter table mysql.user drop column default_role, drop column max_statement_time; remove_file $datadir/mysql_upgrade_info; @@ -60,3 +72,6 @@ drop table t1, t2; remove_file $datadir/mysql_upgrade_info; uninstall plugin blackhole; uninstall plugin archive; + +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; diff --git a/mysql-test/main/mysql_upgrade_ssl.result b/mysql-test/main/mysql_upgrade_ssl.result index 172a1401cdb..ff911e9f54b 100644 --- a/mysql-test/main/mysql_upgrade_ssl.result +++ b/mysql-test/main/mysql_upgrade_ssl.result @@ -9,12 +9,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -32,9 +32,9 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK Phase 4/7: Running 'mysql_fix_privilege_tables' Phase 5/7: Fixing table and database names Phase 6/7: Checking and upgrading tables diff --git a/mysql-test/main/mysql_upgrade_view.result b/mysql-test/main/mysql_upgrade_view.result index 813138b57a8..d22298c6ed0 100644 --- a/mysql-test/main/mysql_upgrade_view.result +++ b/mysql-test/main/mysql_upgrade_view.result @@ -71,12 +71,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats Error : Unknown storage engine 'InnoDB' @@ -100,7 +100,6 @@ mysql.time_zone_transition_type OK mysql.transaction_registry Error : Unknown storage engine 'InnoDB' error : Corrupt -mysql.user OK Repairing tables mysql.innodb_index_stats @@ -114,6 +113,7 @@ Error : Unknown storage engine 'InnoDB' error : Corrupt Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views +mysql.user OK test.v1 OK test.v1badcheck OK test.v2 OK @@ -211,7 +211,7 @@ v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI show create view v4; View Create View character_set_client collation_connection v4 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v4` AS select `t1`.`a` AS `a` from `t1` latin1 latin1_swedish_ci -MySQL upgrade detected +MariaDB upgrade detected Phase 1/7: Checking and upgrading mysql database Processing databases mysql @@ -221,12 +221,12 @@ mysql.db OK mysql.ev_bk OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats Error : Unknown storage engine 'InnoDB' @@ -250,7 +250,6 @@ mysql.time_zone_transition_type OK mysql.transaction_registry Error : Unknown storage engine 'InnoDB' error : Corrupt -mysql.user OK Repairing tables mysql.innodb_index_stats @@ -264,6 +263,7 @@ Error : Unknown storage engine 'InnoDB' error : Corrupt Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views from mysql +mysql.user OK test.v1 OK test.v2 OK test.v3 OK @@ -336,7 +336,7 @@ drop view v1,v2,v3,v4; rename table mysql.event to mysql.ev_bk; flush tables; The --upgrade-system-tables option was used, user tables won't be touched. -MySQL upgrade detected +MariaDB upgrade detected Phase 1/7: Checking and upgrading mysql database Processing databases mysql @@ -346,12 +346,12 @@ mysql.db OK mysql.ev_bk OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats Error : Unknown storage engine 'InnoDB' @@ -375,7 +375,6 @@ mysql.time_zone_transition_type OK mysql.transaction_registry Error : Unknown storage engine 'InnoDB' error : Corrupt -mysql.user OK Repairing tables mysql.innodb_index_stats @@ -389,6 +388,7 @@ Error : Unknown storage engine 'InnoDB' error : Corrupt Phase 2/7: Installing used storage engines... Skipped Phase 3/7: Fixing views from mysql +mysql.user OK test.v1 OK test.v2 OK test.v3 OK diff --git a/mysql-test/main/mysqlcheck.result b/mysql-test/main/mysqlcheck.result index 7259b68be50..063560e388e 100644 --- a/mysql-test/main/mysqlcheck.result +++ b/mysql-test/main/mysqlcheck.result @@ -9,12 +9,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -32,7 +32,6 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK mtr.global_suppressions Table is already up to date mtr.test_suppressions Table is already up to date mysql.column_stats OK @@ -40,12 +39,12 @@ mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats note : Table does not support optimize, doing recreate + analyze instead @@ -69,18 +68,17 @@ mysql.time_zone_transition_type OK mysql.transaction_registry note : Table does not support optimize, doing recreate + analyze instead status : OK -mysql.user OK mysql.column_stats OK mysql.columns_priv OK mysql.db OK mysql.event OK mysql.func OK +mysql.global_priv OK mysql.gtid_slave_pos OK mysql.help_category OK mysql.help_keyword OK mysql.help_relation OK mysql.help_topic OK -mysql.host OK mysql.index_stats OK mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -98,18 +96,17 @@ mysql.time_zone_name OK mysql.time_zone_transition OK mysql.time_zone_transition_type OK mysql.transaction_registry OK -mysql.user OK mysql.column_stats Table is already up to date mysql.columns_priv Table is already up to date mysql.db Table is already up to date mysql.event Table is already up to date mysql.func Table is already up to date +mysql.global_priv Table is already up to date mysql.gtid_slave_pos Table is already up to date mysql.help_category Table is already up to date mysql.help_keyword Table is already up to date mysql.help_relation Table is already up to date mysql.help_topic Table is already up to date -mysql.host Table is already up to date mysql.index_stats Table is already up to date mysql.innodb_index_stats note : Table does not support optimize, doing recreate + analyze instead @@ -133,7 +130,6 @@ mysql.time_zone_transition_type Table is already up to date mysql.transaction_registry note : Table does not support optimize, doing recreate + analyze instead status : OK -mysql.user Table is already up to date create table t1 (a int) engine=myisam; create view v1 as select * from t1; test.t1 OK @@ -433,12 +429,12 @@ mysql.columns_priv Table is already up to date mysql.db Table is already up to date mysql.event Table is already up to date mysql.func Table is already up to date +mysql.global_priv Table is already up to date mysql.gtid_slave_pos Table is already up to date mysql.help_category Table is already up to date mysql.help_keyword Table is already up to date mysql.help_relation Table is already up to date mysql.help_topic Table is already up to date -mysql.host Table is already up to date mysql.index_stats Table is already up to date mysql.innodb_index_stats OK mysql.innodb_table_stats OK @@ -456,7 +452,6 @@ mysql.time_zone_name Table is already up to date mysql.time_zone_transition Table is already up to date mysql.time_zone_transition_type Table is already up to date mysql.transaction_registry OK -mysql.user Table is already up to date mysqltest1.t1 warning : Table is marked as crashed warning : Size of datafile is: 4 Should be: 0 diff --git a/mysql-test/main/mysqld--help,win.rdiff b/mysql-test/main/mysqld--help,win.rdiff index 89d2cd36112..6aba3acab28 100644 --- a/mysql-test/main/mysqld--help,win.rdiff +++ b/mysql-test/main/mysqld--help,win.rdiff @@ -1,6 +1,6 @@ ---- a/mysql-test/r/mysqld--help.result -+++ b/mysql-test/r/mysqld--help.result -@@ -381,7 +381,6 @@ The following options may be given as the first argument: +--- mysqld--help.result 2018-08-12 00:10:13.694793500 +0100 ++++ mysqld--help,win.reject 2018-08-16 20:31:08.353317200 +0100 +@@ -386,7 +386,6 @@ The number of segments in a key cache -L, --language=name Client error messages in given language. May be given as a full path. Deprecated. Use --lc-messages-dir instead. @@ -8,7 +8,7 @@ --lc-messages=name Set the language used for the error messages. -L, --lc-messages-dir=name Directory where error messages are -@@ -603,6 +602,7 @@ The following options may be given as the first argument: +@@ -608,6 +607,7 @@ Use MySQL-5.6 (instead of MariaDB-5.3) format for TIME, DATETIME, TIMESTAMP columns. (Defaults to on; use --skip-mysql56-temporal-format to disable.) @@ -16,17 +16,7 @@ --net-buffer-length=# Buffer length for TCP/IP and socket communication --net-read-timeout=# -@@ -1048,6 +1048,9 @@ The following options may be given as the first argument: - characteristics (isolation level, read only/read - write,snapshot - but not any work done / data modified - within the transaction). -+ --shared-memory Enable the shared memory -+ --shared-memory-base-name=name -+ Base name of shared memory - --show-slave-auth-info - Show user and password in SHOW SLAVE HOSTS on this - master. -@@ -1171,6 +1174,10 @@ The following options may be given as the first argument: +@@ -1188,6 +1188,10 @@ Log slow queries to given log file. Defaults logging to 'hostname'-slow.log. Must be enabled to activate other slow log options @@ -37,7 +27,7 @@ --socket=name Socket file to use for connection --sort-buffer-size=# Each thread that needs to do a sort allocates a buffer of -@@ -1190,6 +1197,7 @@ The following options may be given as the first argument: +@@ -1207,6 +1211,7 @@ EMPTY_STRING_IS_NULL, SIMULTANEOUS_ASSIGNMENT --stack-trace Print a symbolic stack trace on failure (Defaults to on; use --skip-stack-trace to disable.) @@ -45,7 +35,7 @@ --standard-compliant-cte Allow only CTEs compliant to SQL standard (Defaults to on; use --skip-standard-compliant-cte to disable.) -@@ -1257,6 +1265,11 @@ The following options may be given as the first argument: +@@ -1277,6 +1282,11 @@ --thread-pool-max-threads=# Maximum allowed number of worker threads in the thread pool @@ -57,7 +47,7 @@ --thread-pool-oversubscribe=# How many additional active worker threads in a group are allowed. -@@ -1295,8 +1308,8 @@ The following options may be given as the first argument: +@@ -1315,8 +1325,8 @@ automatically convert it to an on-disk MyISAM or Aria table. -t, --tmpdir=name Path for temporary files. Several paths may be specified, @@ -68,7 +58,7 @@ --transaction-alloc-block-size=# Allocation block size for transactions to be stored in binary log -@@ -1430,7 +1443,6 @@ key-cache-block-size 1024 +@@ -1451,7 +1461,6 @@ key-cache-division-limit 100 key-cache-file-hash-size 512 key-cache-segments 0 @@ -76,7 +66,7 @@ lc-messages en_US lc-messages-dir MYSQL_SHAREDIR/ lc-time-names en_US -@@ -1502,6 +1514,7 @@ myisam-sort-buffer-size 134216704 +@@ -1523,6 +1532,7 @@ myisam-stats-method NULLS_UNEQUAL myisam-use-mmap FALSE mysql56-temporal-format TRUE @@ -84,16 +74,7 @@ net-buffer-length 16384 net-read-timeout 30 net-retry-count 10 -@@ -1612,6 +1625,8 @@ session-track-schema TRUE - session-track-state-change FALSE - session-track-system-variables autocommit,character_set_client,character_set_connection,character_set_results,time_zone - session-track-transaction-info OFF -+shared-memory FALSE -+shared-memory-base-name MYSQL - show-slave-auth-info FALSE - silent-startup FALSE - skip-grant-tables TRUE -@@ -1638,6 +1653,7 @@ slave-transaction-retry-interval 0 +@@ -1660,6 +1670,7 @@ slave-type-conversions slow-launch-time 2 slow-query-log FALSE @@ -101,7 +82,7 @@ sort-buffer-size 2097152 sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION stack-trace TRUE -@@ -1652,9 +1668,9 @@ sync-relay-log 10000 +@@ -1674,9 +1685,9 @@ sync-relay-log-info 10000 sysdate-is-now FALSE system-versioning-alter-history ERROR @@ -113,7 +94,7 @@ table-open-cache-instances 8 tc-heuristic-recover OFF tcp-keepalive-interval 0 -@@ -1663,6 +1679,8 @@ tcp-keepalive-time 0 +@@ -1686,6 +1697,8 @@ thread-cache-size 151 thread-pool-idle-timeout 60 thread-pool-max-threads 65536 diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 1c7e9cd839d..8faf332a7dd 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -294,6 +294,15 @@ The following specify which files/extra groups are read (specified before remain --group-concat-max-len=# The maximum length of the result of function GROUP_CONCAT() + --gtid-cleanup-batch-size=# + Normally does not need tuning. How many old rows must + accumulate in the mysql.gtid_slave_pos table before a + background job will be run to delete them. Can be + increased to reduce number of commits if using many + different engines with --gtid_pos_auto_engines, or to + reduce CPU overhead if using a huge number of different + gtid_domain_ids. Can be decreased to reduce number of old + rows in the table. --gtid-domain-id=# Used with global transaction ID to identify logically independent replication streams. When events can propagate through multiple parallel paths (for example @@ -678,7 +687,8 @@ The following specify which files/extra groups are read (specified before remain join_cache_hashed, join_cache_bka, optimize_join_buffer_size, table_elimination, extended_keys, exists_to_in, orderby_uses_equalities, - condition_pushdown_for_derived, split_materialized + condition_pushdown_for_derived, split_materialized, + condition_pushdown_for_subquery --optimizer-use-condition-selectivity=# Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial @@ -1208,7 +1218,8 @@ The following specify which files/extra groups are read (specified before remain ERROR_FOR_DIVISION_BY_ZERO, TRADITIONAL, NO_AUTO_CREATE_USER, HIGH_NOT_PRECEDENCE, NO_ENGINE_SUBSTITUTION, PAD_CHAR_TO_FULL_LENGTH, - EMPTY_STRING_IS_NULL, SIMULTANEOUS_ASSIGNMENT + EMPTY_STRING_IS_NULL, SIMULTANEOUS_ASSIGNMENT, + TIME_ROUND_FRACTIONAL --sql-safe-updates If set to 1, UPDATEs and DELETEs need either a key in the WHERE clause, or a LIMIT clause, or else they will aborted. Prevents the common mistake of accidentally @@ -1273,6 +1284,9 @@ The following specify which files/extra groups are read (specified before remain first TCP keep-alive packet is sent.If set to 0, system dependent default is used. (Automatically configured unless set explicitly) + --tcp-nodelay Set option TCP_NODELAY (disable Nagle's algorithm) on + socket + (Defaults to on; use --skip-tcp-nodelay to disable.) --thread-cache-size=# How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time @@ -1344,7 +1358,8 @@ The following specify which files/extra groups are read (specified before remain (usually get from GUI tools) --use-stat-tables=name Specifies how to use system statistics tables. One of: - NEVER, COMPLEMENTARY, PREFERABLY + NEVER, COMPLEMENTARY, PREFERABLY, + COMPLEMENTARY_FOR_QUERIES, PREFERABLY_FOR_QUERIES -u, --user=name Run mysqld daemon as user. --userstat Enables statistics gathering for USER_STATISTICS, CLIENT_STATISTICS, INDEX_STATISTICS and TABLE_STATISTICS @@ -1429,6 +1444,7 @@ gdb FALSE general-log FALSE getopt-prefix-matching FALSE group-concat-max-len 1048576 +gtid-cleanup-batch-size 64 gtid-domain-id 0 gtid-ignore-duplicates FALSE gtid-pos-auto-engines @@ -1541,8 +1557,8 @@ old-style-user-limits FALSE optimizer-prune-level 1 optimizer-search-depth 62 optimizer-selectivity-sampling-limit 100 -optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on -optimizer-use-condition-selectivity 1 +optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on +optimizer-use-condition-selectivity 4 performance-schema FALSE performance-schema-accounts-size -1 performance-schema-consumer-events-stages-current FALSE @@ -1579,7 +1595,7 @@ performance-schema-max-rwlock-instances -1 performance-schema-max-socket-classes 10 performance-schema-max-socket-instances -1 performance-schema-max-stage-classes 160 -performance-schema-max-statement-classes 200 +performance-schema-max-statement-classes 201 performance-schema-max-table-handles -1 performance-schema-max-table-instances -1 performance-schema-max-thread-classes 50 @@ -1689,6 +1705,7 @@ tc-heuristic-recover OFF tcp-keepalive-interval 0 tcp-keepalive-probes 0 tcp-keepalive-time 0 +tcp-nodelay TRUE thread-cache-size 151 thread-pool-idle-timeout 60 thread-pool-max-threads 65536 @@ -1707,7 +1724,7 @@ transaction-isolation REPEATABLE-READ transaction-prealloc-size 4096 transaction-read-only FALSE updatable-views-with-limit YES -use-stat-tables NEVER +use-stat-tables PREFERABLY_FOR_QUERIES userstat FALSE verbose TRUE wait-timeout 28800 diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result index 1366f9bdd12..1a3b927f981 100644 --- a/mysql-test/main/mysqldump.result +++ b/mysql-test/main/mysqldump.result @@ -2750,6 +2750,8 @@ CREATE PROCEDURE bug9056_proc2(OUT a INT) BEGIN select sum(id) from t1 into a; END // +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead set sql_mode='ansi'; create procedure `a'b` () select 1; set sql_mode=''; @@ -5161,7 +5163,7 @@ USE BUG52792; SET NAMES utf8; CREATE FUNCTION `straße` ( c1 CHAR(20)) RETURNS CHAR(50) DETERMINISTIC -RETURN CONCAT(']]>, ', s, '!'); +RETURN CONCAT(']]>, ', c1, '!'); <?xml version="1.0"?> <mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <database name="BUG52792"> @@ -5170,7 +5172,7 @@ RETURN CONCAT(']]>, ', s, '!'); <![CDATA[ CREATE DEFINER=`root`@`localhost` FUNCTION `straße`( c1 CHAR(20)) RETURNS char(50) CHARSET latin1 DETERMINISTIC -RETURN CONCAT(']]]]><![CDATA[>, ', s, '!') +RETURN CONCAT(']]]]><![CDATA[>, ', c1, '!') ]]> </routine> </routines> diff --git a/mysql-test/main/mysqldump.test b/mysql-test/main/mysqldump.test index 6567596c35c..57462fcf2e2 100644 --- a/mysql-test/main/mysqldump.test +++ b/mysql-test/main/mysqldump.test @@ -707,7 +707,7 @@ drop table t1; --echo # Bug#15328 Segmentation fault occurred if my.cnf is invalid for escape sequence --echo # ---exec $MYSQL_MY_PRINT_DEFAULTS --config-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump +--exec $MYSQL_MY_PRINT_DEFAULTS --defaults-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump --echo # --echo # Bug#19025 mysqldump doesn't correctly dump "auto_increment = [int]" @@ -2362,7 +2362,7 @@ USE BUG52792; SET NAMES utf8; CREATE FUNCTION `straße` ( c1 CHAR(20)) RETURNS CHAR(50) DETERMINISTIC -RETURN CONCAT(']]>, ', s, '!'); +RETURN CONCAT(']]>, ', c1, '!'); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=utf8 --compatible=mysql323 -R -X BUG52792 diff --git a/mysql-test/main/not_embedded_server.result b/mysql-test/main/not_embedded_server.result index ba68ca8619b..bc794ce48c8 100644 --- a/mysql-test/main/not_embedded_server.result +++ b/mysql-test/main/not_embedded_server.result @@ -1,4 +1,4 @@ -call mtr.add_suppression("Can't open and lock privilege tables: Table 'user' was not locked with LOCK TABLES"); +call mtr.add_suppression("Can't open and lock privilege tables: Table 'db' was not locked with LOCK TABLES"); SHOW VARIABLES like 'slave_skip_errors'; Variable_name Value slave_skip_errors OFF @@ -16,7 +16,7 @@ DROP TABLE IF EXISTS t1; CREATE TABLE t1 (c1 INT); LOCK TABLES t1 READ; FLUSH PRIVILEGES; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES UNLOCK TABLES; DROP TABLE t1; # diff --git a/mysql-test/main/not_embedded_server.test b/mysql-test/main/not_embedded_server.test index b2cbdba6850..20f75db25d5 100644 --- a/mysql-test/main/not_embedded_server.test +++ b/mysql-test/main/not_embedded_server.test @@ -6,7 +6,7 @@ # End of 4.1 tests -call mtr.add_suppression("Can't open and lock privilege tables: Table 'user' was not locked with LOCK TABLES"); +call mtr.add_suppression("Can't open and lock privilege tables: Table 'db' was not locked with LOCK TABLES"); # # Bug#43835: SHOW VARIABLES does not include 0 for slave_skip_errors diff --git a/mysql-test/main/null.result b/mysql-test/main/null.result index 2fa89a2d001..6601c5e1ed4 100644 --- a/mysql-test/main/null.result +++ b/mysql-test/main/null.result @@ -515,9 +515,9 @@ NULLIF(TIMESTAMP'2001-01-01 00:00:00',1e0), NULLIF(TIMESTAMP'2001-01-01 00:00:00','2001-01-01'), NULLIF(TIMESTAMP'2001-01-01 00:00:00',TIME'00:00:00'); Warnings: -Warning 1292 Incorrect datetime value: '1' -Warning 1292 Incorrect datetime value: '1.0' -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1.0' +Warning 1292 Truncated incorrect datetime value: '1' SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -536,9 +536,9 @@ NULLIF(DATE'2001-01-01',1e0), NULLIF(DATE'2001-01-01','2001-01-01'), NULLIF(DATE'2001-01-01',TIME'00:00:00'); Warnings: -Warning 1292 Incorrect datetime value: '1' -Warning 1292 Incorrect datetime value: '1.0' -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1.0' +Warning 1292 Truncated incorrect datetime value: '1' SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -1640,8 +1640,8 @@ CASE WHEN TIMESTAMP'2001-01-01 00:00:00'=1 THEN NULL ELSE TIMESTAMP'2001-01-01 00:00:00' END AS b; Warnings: -Warning 1292 Incorrect datetime value: '1' -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' DROP TABLE t1; # # MDEV-8785 Wrong results for EXPLAIN EXTENDED...WHERE NULLIF(latin1_col, _utf8'a' COLLATE utf8_bin) IS NOT NULL diff --git a/mysql-test/main/null_key.result b/mysql-test/main/null_key.result index 4b4a4b80dee..b152596daca 100644 --- a/mysql-test/main/null_key.result +++ b/mysql-test/main/null_key.result @@ -399,8 +399,11 @@ INSERT INTO t3 SELECT * FROM t4; INSERT INTO t3 VALUES (2), (3); ANALYZE table t1, t2, t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK SELECT COUNT(*) FROM t3; COUNT(*) diff --git a/mysql-test/main/old-mode.result b/mysql-test/main/old-mode.result index 73ad613048a..e0a3412bbdf 100644 --- a/mysql-test/main/old-mode.result +++ b/mysql-test/main/old-mode.result @@ -180,3 +180,44 @@ a unix_timestamp(a) 2010-10-31 02:25:26 1288481126 drop table t1, t2; set time_zone=DEFAULT; +# +# MDEV-13995 MAX(timestamp) returns a wrong result near DST change +# +SET global mysql56_temporal_format=false; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP(0)); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/); +SET time_zone='Europe/Moscow'; +SELECT a, COALESCE(a), UNIX_TIMESTAMP(a) FROM t1; +a COALESCE(a) UNIX_TIMESTAMP(a) +2010-10-31 02:25:26 2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:25 2010-10-31 02:25:25 1288481125 +SELECT MIN(a), UNIX_TIMESTAMP(MIN(a)) AS a FROM t1; +MIN(a) a +2010-10-31 02:25:26 1288477526 +SELECT MAX(a), UNIX_TIMESTAMP(MAX(a)) AS a FROM t1; +MAX(a) a +2010-10-31 02:25:25 1288481125 +SELECT t1.a, UNIX_TIMESTAMP(t1.a), t2.a, UNIX_TIMESTAMP(t2.a) FROM t1 t1, t1 t2 WHERE t1.a=t2.a; +a UNIX_TIMESTAMP(t1.a) a UNIX_TIMESTAMP(t2.a) +2010-10-31 02:25:26 1288477526 2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:25 1288481125 2010-10-31 02:25:25 1288481125 +ALTER TABLE t1 MODIFY a TIMESTAMP(1); +SELECT a, COALESCE(a), UNIX_TIMESTAMP(a) FROM t1; +a COALESCE(a) UNIX_TIMESTAMP(a) +2010-10-31 02:25:26.0 2010-10-31 02:25:26.0 1288477526.0 +2010-10-31 02:25:25.0 2010-10-31 02:25:25.0 1288481125.0 +SELECT MIN(a), UNIX_TIMESTAMP(MIN(a)) AS a FROM t1; +MIN(a) a +2010-10-31 02:25:26.0 1288477526.0 +SELECT MAX(a), UNIX_TIMESTAMP(MAX(a)) AS a FROM t1; +MAX(a) a +2010-10-31 02:25:25.0 1288481125.0 +SELECT t1.a, UNIX_TIMESTAMP(t1.a), t2.a, UNIX_TIMESTAMP(t2.a) FROM t1 t1, t1 t2 WHERE t1.a=t2.a; +a UNIX_TIMESTAMP(t1.a) a UNIX_TIMESTAMP(t2.a) +2010-10-31 02:25:26.0 1288477526.0 2010-10-31 02:25:26.0 1288477526.0 +2010-10-31 02:25:25.0 1288481125.0 2010-10-31 02:25:25.0 1288481125.0 +DROP TABLE t1; +SET time_zone=DEFAULT; +SET global mysql56_temporal_format=true; diff --git a/mysql-test/main/old-mode.test b/mysql-test/main/old-mode.test index d7e8ce8ee55..7ec2092009b 100644 --- a/mysql-test/main/old-mode.test +++ b/mysql-test/main/old-mode.test @@ -119,3 +119,32 @@ insert t2 select a from t1; select a, unix_timestamp(a) from t2; drop table t1, t2; set time_zone=DEFAULT; + + +--echo # +--echo # MDEV-13995 MAX(timestamp) returns a wrong result near DST change +--echo # + +# This tests: +# Field_timestamp::val_native() +# Field_timestamp_hires::val_native() +# Type_handler_timestamp_common::type_handler_for_native_format() + +SET global mysql56_temporal_format=false; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP(0)); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/); +SET time_zone='Europe/Moscow'; +SELECT a, COALESCE(a), UNIX_TIMESTAMP(a) FROM t1; +SELECT MIN(a), UNIX_TIMESTAMP(MIN(a)) AS a FROM t1; +SELECT MAX(a), UNIX_TIMESTAMP(MAX(a)) AS a FROM t1; +SELECT t1.a, UNIX_TIMESTAMP(t1.a), t2.a, UNIX_TIMESTAMP(t2.a) FROM t1 t1, t1 t2 WHERE t1.a=t2.a; +ALTER TABLE t1 MODIFY a TIMESTAMP(1); +SELECT a, COALESCE(a), UNIX_TIMESTAMP(a) FROM t1; +SELECT MIN(a), UNIX_TIMESTAMP(MIN(a)) AS a FROM t1; +SELECT MAX(a), UNIX_TIMESTAMP(MAX(a)) AS a FROM t1; +SELECT t1.a, UNIX_TIMESTAMP(t1.a), t2.a, UNIX_TIMESTAMP(t2.a) FROM t1 t1, t1 t2 WHERE t1.a=t2.a; +DROP TABLE t1; +SET time_zone=DEFAULT; +SET global mysql56_temporal_format=true; diff --git a/mysql-test/main/outfile_loaddata.result b/mysql-test/main/outfile_loaddata.result index 1449cb19453..4356f8b113e 100644 --- a/mysql-test/main/outfile_loaddata.result +++ b/mysql-test/main/outfile_loaddata.result @@ -124,16 +124,19 @@ ERROR 42000: Field separator argument is not what is expected; check the manual # LOAD DATA rises error or has unpredictable result -- to be fixed later SELECT * FROM t1 INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/t1.txt' FIELDS ENCLOSED BY 'ÑŠ'; Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead Warning 1638 Non-ASCII separator arguments are not fully supported LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/t1.txt' INTO TABLE t2 CHARACTER SET binary FIELDS ENCLOSED BY 'ÑŠ'; ERROR 42000: Field separator argument is not what is expected; check the manual SELECT * FROM t1 INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/t1.txt' FIELDS ESCAPED BY 'ÑŠ'; Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead Warning 1638 Non-ASCII separator arguments are not fully supported LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/t1.txt' INTO TABLE t2 CHARACTER SET binary FIELDS ESCAPED BY 'ÑŠ'; ERROR 42000: Field separator argument is not what is expected; check the manual SELECT * FROM t1 INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/t1.txt' FIELDS TERMINATED BY 'ÑŠ'; Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead Warning 1638 Non-ASCII separator arguments are not fully supported ################################################## 1ÑŠABC-áâ÷ÑŠDEF-ÂÃÄ @@ -157,6 +160,7 @@ a b c 2 NULL NULL SELECT * FROM t1 INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/t1.txt' LINES STARTING BY 'ÑŠ'; Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead Warning 1638 Non-ASCII separator arguments are not fully supported ################################################## ÑŠ1 ABC-áâ÷ DEF-ÂÃÄ @@ -172,6 +176,7 @@ a b c 2 NULL NULL SELECT * FROM t1 INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/t1.txt' LINES TERMINATED BY 'ÑŠ'; Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead Warning 1638 Non-ASCII separator arguments are not fully supported ################################################## 1 ABC-áâ÷ DEF-ÂÃÄÑŠ2 \N \NÑŠ################################################## diff --git a/mysql-test/main/parser.result b/mysql-test/main/parser.result index 2ed1032f6cf..34c119a322e 100644 --- a/mysql-test/main/parser.result +++ b/mysql-test/main/parser.result @@ -705,6 +705,9 @@ FOR UPDATE; 1 1 SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 +PROCEDURE ANALYSE(); +ERROR HY000: Can't use ORDER clause with this procedure +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 PROCEDURE ANALYSE() FOR UPDATE; ERROR HY000: Can't use ORDER clause with this procedure SELECT 1 FROM @@ -734,7 +737,7 @@ SELECT 1 FROM t1 UNION SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 PROCEDURE ANALYSE() FOR UPDATE; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE() FOR UPDATE' at line 4 +ERROR 42000: Incorrect usage/placement of 'PROCEDURE' SELECT 1 FROM DUAL PROCEDURE ANALYSE() UNION SELECT 1 FROM t1; @@ -754,15 +757,18 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp # "FOR UPDATE" tests SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; 1 -SELECT 1 FROM t1 FOR UPDATE UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; +(SELECT 1 FROM t1 FOR UPDATE) UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; 1 SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1 FOR UPDATE; 1 # "INTO" clause tests SELECT 1 FROM t1 INTO @var17727401; Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead Warning 1329 No data - zero rows fetched, selected, or processed SELECT 1 FROM DUAL INTO @var17727401; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT 1 INTO @var17727401; SELECT 1 INTO @var17727401 FROM t1; Warnings: @@ -778,6 +784,7 @@ Warnings: Warning 1329 No data - zero rows fetched, selected, or processed SELECT 1 FROM t1 WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1 INTO @var17727401; Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead Warning 1329 No data - zero rows fetched, selected, or processed SELECT 1 FROM t1 WHERE 1 INTO @var17727401 GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'GROUP BY 1 HAVING 1 ORDER BY 1 LIMIT 1' at line 1 @@ -794,31 +801,20 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp SELECT 1 FROM t1 INTO @var17727401 UNION SELECT 1 FROM t1 INTO t1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 FROM t1 INTO t1' at line 1 (SELECT 1 FROM t1 INTO @var17727401) UNION (SELECT 1 FROM t1 INTO t1); -ERROR HY000: Incorrect usage of UNION and INTO +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'INTO @var17727401) UNION (SELECT 1 FROM t1 INTO t1)' at line 1 SELECT 1 FROM t1 UNION SELECT 1 FROM t1 INTO @var17727401; Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead Warning 1329 No data - zero rows fetched, selected, or processed SELECT 1 INTO @var17727401 FROM t1 PROCEDURE ANALYSE(); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE()' at line 1 SELECT 1 FROM t1 PROCEDURE ANALYSE() INTO @var17727401; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'INTO @var17727401' at line 1 # ORDER and LIMIT clause combinations -(SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1; -1 -(SELECT 1 FROM t1 LIMIT 1) LIMIT 1; -1 -((SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1) ORDER BY 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ORDER BY 1) ORDER BY 1' at line 1 -((SELECT 1 FROM t1 LIMIT 1) LIMIT 1) LIMIT 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LIMIT 1) LIMIT 1' at line 1 -(SELECT 1 FROM t1 ORDER BY 1) LIMIT 1; -1 -(SELECT 1 FROM t1 LIMIT 1) ORDER BY 1; -1 ((SELECT 1 FROM t1 ORDER BY 1) LIMIT 1) ORDER BY 1); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LIMIT 1) ORDER BY 1)' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1 ((SELECT 1 FROM t1 LIMIT 1) ORDER BY 1) LIMIT 1); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ORDER BY 1) LIMIT 1)' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1 SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1; 1 SELECT (SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1); @@ -1265,19 +1261,27 @@ CREATE TABLE t1 (i INT); (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)) UNION (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)); -ERROR HY000: Incorrect usage of UNION and SELECT ... PROCEDURE ANALYSE() +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE(10, 10)) +UNION +(SELECT * FROM t1 PROCEDURE ANALYSE(10, 10))' at line 1 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)) UNION SELECT * FROM t1 PROCEDURE ANALYSE(10, 10); -ERROR HY000: Incorrect usage of UNION and SELECT ... PROCEDURE ANALYSE() +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE(10, 10)) +UNION +SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)' at line 1 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)) UNION (SELECT 1); -ERROR HY000: Incorrect usage of UNION and SELECT ... PROCEDURE ANALYSE() +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE(10, 10)) +UNION +(SELECT 1)' at line 1 (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)) UNION SELECT 1; -ERROR HY000: Incorrect usage of UNION and SELECT ... PROCEDURE ANALYSE() +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'PROCEDURE ANALYSE(10, 10)) +UNION +SELECT 1' at line 1 SELECT * FROM t1 PROCEDURE ANALYSE(10, 10) UNION (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)); diff --git a/mysql-test/main/parser.test b/mysql-test/main/parser.test index 040678a51df..3a7c4f6467e 100644 --- a/mysql-test/main/parser.test +++ b/mysql-test/main/parser.test @@ -826,6 +826,9 @@ SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 --error ER_ORDER_WITH_PROC SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 + PROCEDURE ANALYSE(); +--error ER_ORDER_WITH_PROC +SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 PROCEDURE ANALYSE() FOR UPDATE; SELECT 1 FROM @@ -851,7 +854,7 @@ UNION SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 FOR UPDATE; ---error ER_PARSE_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT 1 FROM t1 UNION SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1 @@ -876,7 +879,7 @@ UNION --echo # "FOR UPDATE" tests SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; -SELECT 1 FROM t1 FOR UPDATE UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; +(SELECT 1 FROM t1 FOR UPDATE) UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1; SELECT 1 FROM t1 UNION SELECT 1 FROM t1 ORDER BY 1 LIMIT 1 FOR UPDATE; @@ -916,7 +919,7 @@ SELECT EXISTS(SELECT 1 FROM t1 INTO @var17727401); --error ER_PARSE_ERROR SELECT 1 FROM t1 INTO @var17727401 UNION SELECT 1 FROM t1 INTO t1; ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR (SELECT 1 FROM t1 INTO @var17727401) UNION (SELECT 1 FROM t1 INTO t1); SELECT 1 FROM t1 UNION SELECT 1 FROM t1 INTO @var17727401; @@ -931,16 +934,16 @@ SELECT 1 FROM t1 PROCEDURE ANALYSE() INTO @var17727401; # Limited support for (SELECT ...) ORDER/LIMIT: -(SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1; -(SELECT 1 FROM t1 LIMIT 1) LIMIT 1; +# (SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1; +# (SELECT 1 FROM t1 LIMIT 1) LIMIT 1; ---error ER_PARSE_ERROR -((SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1) ORDER BY 1; ---error ER_PARSE_ERROR -((SELECT 1 FROM t1 LIMIT 1) LIMIT 1) LIMIT 1; +#--error ER_PARSE_ERROR +# ((SELECT 1 FROM t1 ORDER BY 1) ORDER BY 1) ORDER BY 1; +#--error ER_PARSE_ERROR +# ((SELECT 1 FROM t1 LIMIT 1) LIMIT 1) LIMIT 1; -(SELECT 1 FROM t1 ORDER BY 1) LIMIT 1; -(SELECT 1 FROM t1 LIMIT 1) ORDER BY 1; +# (SELECT 1 FROM t1 ORDER BY 1) LIMIT 1; +# (SELECT 1 FROM t1 LIMIT 1) ORDER BY 1; --error ER_PARSE_ERROR ((SELECT 1 FROM t1 ORDER BY 1) LIMIT 1) ORDER BY 1); @@ -1276,22 +1279,22 @@ DROP TABLE t1; --echo # CREATE TABLE t1 (i INT); ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)) UNION (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)); ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)) UNION SELECT * FROM t1 PROCEDURE ANALYSE(10, 10); ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)) UNION (SELECT 1); ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR (SELECT * FROM t1 PROCEDURE ANALYSE(10, 10)) UNION SELECT 1; diff --git a/mysql-test/main/partition.result b/mysql-test/main/partition.result index bf5d45846a5..2108c88588d 100644 --- a/mysql-test/main/partition.result +++ b/mysql-test/main/partition.result @@ -286,6 +286,7 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par t1 1 a 1 a A NULL NULL NULL YES BTREE analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show indexes from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -1029,6 +1030,7 @@ PARTITION BY LIST (a) (PARTITION x1 VALUES IN (10), PARTITION x2 VALUES IN (20)); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK drop table t1; create table t1 @@ -1824,6 +1826,7 @@ Table Op Msg_type Msg_text test.t1 check status OK ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze note The storage engine for the table doesn't support analyze drop table t1; drop procedure if exists mysqltest_1; @@ -2060,6 +2063,7 @@ ALTER TABLE t1 ANALYZE PARTITION p1 EXTENDED; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'EXTENDED' at line 1 ALTER TABLE t1 ANALYZE PARTITION p1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK ALTER TABLE t1 CHECK PARTITION p1; Table Op Msg_type Msg_text diff --git a/mysql-test/main/partition_binlog.result b/mysql-test/main/partition_binlog.result index 21eca8f1c00..3e6100b51d8 100644 --- a/mysql-test/main/partition_binlog.result +++ b/mysql-test/main/partition_binlog.result @@ -27,6 +27,7 @@ Table Op Msg_type Msg_text test.t1 repair error Error in list of partitions to test.t1 ALTER TABLE t1 ANALYZE PARTITION p0; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK ALTER TABLE t1 CHECK PARTITION p0; Table Op Msg_type Msg_text diff --git a/mysql-test/main/partition_explicit_prune.result b/mysql-test/main/partition_explicit_prune.result index 951b21db3e1..9c1174c5414 100644 --- a/mysql-test/main/partition_explicit_prune.result +++ b/mysql-test/main/partition_explicit_prune.result @@ -233,6 +233,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0; VARIABLE_NAME VARIABLE_VALUE HANDLER_COMMIT 1 +HANDLER_READ_KEY 6 HANDLER_TMP_WRITE 24 HANDLER_WRITE 2 # Should be 1 commit @@ -315,6 +316,7 @@ a b 1000 `p100-99999`(-subp6) ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SET @save_innodb_stats_on_metadata=@@global.innodb_stats_on_metadata; SET @@global.innodb_stats_on_metadata=ON; @@ -348,6 +350,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0; VARIABLE_NAME VARIABLE_VALUE HANDLER_COMMIT 1 HANDLER_READ_FIRST 1 +HANDLER_READ_KEY 6 HANDLER_TMP_WRITE 24 # Should be 1 commit # 4 locks (1 ha_partition + 1 ha_innobase) x 2 (lock/unlock) @@ -690,6 +693,8 @@ a b -21 REPLACEd by REPLACE FLUSH STATUS; SELECT * FROM t1 PARTITION (pNeg, `p10-99`) INTO OUTFILE 'loadtest.txt'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0; VARIABLE_NAME VARIABLE_VALUE @@ -1056,6 +1061,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0; VARIABLE_NAME VARIABLE_VALUE HANDLER_COMMIT 1 HANDLER_READ_FIRST 5 +HANDLER_READ_KEY 6 HANDLER_READ_NEXT 5 HANDLER_TMP_WRITE 24 HANDLER_WRITE 10 @@ -1075,6 +1081,7 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0; VARIABLE_NAME VARIABLE_VALUE HANDLER_READ_FIRST 5 +HANDLER_READ_KEY 6 HANDLER_ROLLBACK 1 HANDLER_TMP_WRITE 24 HANDLER_WRITE 1 @@ -1102,6 +1109,7 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0; VARIABLE_NAME VARIABLE_VALUE HANDLER_COMMIT 1 HANDLER_READ_FIRST 5 +HANDLER_READ_KEY 6 HANDLER_READ_NEXT 5 HANDLER_TMP_WRITE 24 HANDLER_WRITE 10 diff --git a/mysql-test/main/partition_innodb.result b/mysql-test/main/partition_innodb.result index 3d8d2040a48..7d26e5fe216 100644 --- a/mysql-test/main/partition_innodb.result +++ b/mysql-test/main/partition_innodb.result @@ -26,6 +26,7 @@ INSERT INTO t1 VALUES (0, 'Mod Zero'), (1, 'One'), (2, 'Two'), (3, 'Three'), INSERT INTO t1 SELECT a + 30, b FROM t1 WHERE a >= 0; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN SELECT b FROM t1 WHERE b between 'L' and 'N' AND a > -100; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/main/perror-win.result b/mysql-test/main/perror-win.result index 139b566757f..0e9d2e48a99 100644 --- a/mysql-test/main/perror-win.result +++ b/mysql-test/main/perror-win.result @@ -1,7 +1,7 @@ -MySQL error code 150: Foreign key constraint is incorrectly formed +MariaDB error code 150: Foreign key constraint is incorrectly formed Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed.
OS error code 23: Too many open files in system Win32 error code 23: Data error (cyclic redundancy check).
-MySQL error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192s' for key %d +MariaDB error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192s' for key %d Win32 error code 1062: The service has not been started.
Illegal error code: 30000 diff --git a/mysql-test/main/perror.result b/mysql-test/main/perror.result index 46554442721..ad2106524e5 100644 --- a/mysql-test/main/perror.result +++ b/mysql-test/main/perror.result @@ -1,6 +1,6 @@ Illegal error code: 10000 -MySQL error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192s' for key %d -MySQL error code 1408 (ER_STARTUP): %s: ready for connections. +MariaDB error code 1062 (ER_DUP_ENTRY): Duplicate entry '%-.192s' for key %d +MariaDB error code 1408 (ER_STARTUP): %s: ready for connections. Version: '%s' socket: '%s' port: %d %s -MySQL error code 1459 (ER_TABLE_NEEDS_UPGRADE): Upgrade required. Please do "REPAIR %s %`s" or dump/reload to fix it! -MySQL error code 1461 (ER_MAX_PREPARED_STMT_COUNT_REACHED): Can't create more than max_prepared_stmt_count statements (current value: %u) +MariaDB error code 1459 (ER_TABLE_NEEDS_UPGRADE): Upgrade required. Please do "REPAIR %s %`s" or dump/reload to fix it! +MariaDB error code 1461 (ER_MAX_PREPARED_STMT_COUNT_REACHED): Can't create more than max_prepared_stmt_count statements (current value: %u) diff --git a/mysql-test/main/plugin.result b/mysql-test/main/plugin.result index 3a141a25b5c..fde2550ad81 100644 --- a/mysql-test/main/plugin.result +++ b/mysql-test/main/plugin.result @@ -12,7 +12,7 @@ PLUGIN_STATUS ACTIVE PLUGIN_TYPE STORAGE ENGINE PLUGIN_TYPE_VERSION # PLUGIN_LIBRARY ha_example.so -PLUGIN_LIBRARY_VERSION 1.13 +PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_AUTHOR Brian Aker, MySQL AB PLUGIN_DESCRIPTION Example storage engine PLUGIN_LICENSE GPL @@ -25,7 +25,7 @@ PLUGIN_STATUS ACTIVE PLUGIN_TYPE DAEMON PLUGIN_TYPE_VERSION # PLUGIN_LIBRARY ha_example.so -PLUGIN_LIBRARY_VERSION 1.13 +PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_AUTHOR Sergei Golubchik PLUGIN_DESCRIPTION Unusable Daemon PLUGIN_LICENSE GPL @@ -64,7 +64,7 @@ PLUGIN_STATUS DELETED PLUGIN_TYPE STORAGE ENGINE PLUGIN_TYPE_VERSION # PLUGIN_LIBRARY ha_example.so -PLUGIN_LIBRARY_VERSION 1.13 +PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_AUTHOR Brian Aker, MySQL AB PLUGIN_DESCRIPTION Example storage engine PLUGIN_LICENSE GPL @@ -331,3 +331,48 @@ UNINSTALL PLUGIN example; RENAME TABLE t1 TO t2; ERROR 42S02: Table 'test.t1' doesn't exist DROP TABLE t1; +# +# INSTALL IF NOT EXISTS PLUGIN name SONAME library / +# UNINSTALL IF EXISTS PLUGIN|SONAME name +# +select PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE from information_schema.plugins where plugin_library like 'ha_example%'; +PLUGIN_NAME PLUGIN_STATUS PLUGIN_TYPE +INSTALL PLUGIN IF NOT EXISTS example SONAME 'ha_example'; +select PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE from information_schema.plugins where plugin_library like 'ha_example%'; +PLUGIN_NAME PLUGIN_STATUS PLUGIN_TYPE +EXAMPLE ACTIVE STORAGE ENGINE +INSTALL PLUGIN example SONAME 'ha_example'; +ERROR HY000: Plugin 'example' already installed +INSTALL PLUGIN IF NOT EXISTS example SONAME 'ha_example'; +Warnings: +Note 1968 Plugin 'example' already installed +SHOW WARNINGS; +Level Code Message +Note 1968 Plugin 'example' already installed +UNINSTALL PLUGIN IF EXISTS example; +select PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE from information_schema.plugins where plugin_library like 'ha_example%'; +PLUGIN_NAME PLUGIN_STATUS PLUGIN_TYPE +UNINSTALL PLUGIN IF EXISTS example; +Warnings: +Note 1305 PLUGIN example does not exist +SHOW WARNINGS; +Level Code Message +Note 1305 PLUGIN example does not exist +UNINSTALL PLUGIN example; +ERROR 42000: PLUGIN example does not exist +INSTALL SONAME 'ha_example'; +select PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE from information_schema.plugins where plugin_library like 'ha_example%'; +PLUGIN_NAME PLUGIN_STATUS PLUGIN_TYPE +EXAMPLE ACTIVE STORAGE ENGINE +UNUSABLE ACTIVE DAEMON +UNINSTALL SONAME IF EXISTS 'ha_example'; +UNINSTALL SONAME IF EXISTS 'ha_example'; +Warnings: +Note 1305 SONAME ha_example.so does not exist +SHOW WARNINGS; +Level Code Message +Note 1305 SONAME ha_example.so does not exist +select PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE from information_schema.plugins where plugin_library like 'ha_example%'; +PLUGIN_NAME PLUGIN_STATUS PLUGIN_TYPE +UNINSTALL SONAME 'ha_example'; +ERROR 42000: SONAME ha_example.so does not exist diff --git a/mysql-test/main/plugin.test b/mysql-test/main/plugin.test index 68c4d5afd64..273e1e064a5 100644 --- a/mysql-test/main/plugin.test +++ b/mysql-test/main/plugin.test @@ -265,3 +265,43 @@ UNINSTALL PLUGIN example; --error ER_NO_SUCH_TABLE RENAME TABLE t1 TO t2; DROP TABLE t1; + +--echo # +--echo # INSTALL IF NOT EXISTS PLUGIN name SONAME library / +--echo # UNINSTALL IF EXISTS PLUGIN|SONAME name +--echo # + +select PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE from information_schema.plugins where plugin_library like 'ha_example%'; +INSTALL PLUGIN IF NOT EXISTS example SONAME 'ha_example'; +select PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE from information_schema.plugins where plugin_library like 'ha_example%'; + +--replace_regex /\.dll/.so/ +--error ER_PLUGIN_INSTALLED +INSTALL PLUGIN example SONAME 'ha_example'; + +INSTALL PLUGIN IF NOT EXISTS example SONAME 'ha_example'; +SHOW WARNINGS; + +UNINSTALL PLUGIN IF EXISTS example; +select PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE from information_schema.plugins where plugin_library like 'ha_example%'; + +UNINSTALL PLUGIN IF EXISTS example; +SHOW WARNINGS; + +--error 1305 +UNINSTALL PLUGIN example; + +INSTALL SONAME 'ha_example'; +select PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE from information_schema.plugins where plugin_library like 'ha_example%'; + +UNINSTALL SONAME IF EXISTS 'ha_example'; + +--replace_regex /\.dll/.so/ +UNINSTALL SONAME IF EXISTS 'ha_example'; +--replace_regex /\.dll/.so/ +SHOW WARNINGS; +select PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE from information_schema.plugins where plugin_library like 'ha_example%'; + +--replace_regex /\.dll/.so/ +--error 1305 +UNINSTALL SONAME 'ha_example'; diff --git a/mysql-test/main/plugin_auth.result b/mysql-test/main/plugin_auth.result index e470cc010c0..7c3d029ad7d 100644 --- a/mysql-test/main/plugin_auth.result +++ b/mysql-test/main/plugin_auth.result @@ -30,7 +30,7 @@ proxies_priv CREATE TABLE `proxies_priv` ( `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`Host`,`User`,`Proxied_host`,`Proxied_user`), KEY `Grantor` (`Grantor`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User proxy privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User proxy privileges' connect plug_con,localhost,plug,plug_dest; connection plug_con; select USER(),CURRENT_USER(); @@ -362,6 +362,7 @@ uplain@localhost uplain@localhost connection default; disconnect cleartext_con; DROP USER uplain@localhost; +drop view mysql.user_bak; # # Bug #59038 : mysql.user.authentication_string column # causes configuration wizard to fail @@ -443,6 +444,8 @@ ORDER BY COLUMN_NAME; IS_NULLABLE COLUMN_NAME NO authentication_string NO plugin +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; # # Bug # 11766641: 59792: BIN/MYSQL -UUNKNOWN -PUNKNOWN # .-> USING PASSWORD: NO diff --git a/mysql-test/main/plugin_auth.test b/mysql-test/main/plugin_auth.test index c3c18b7e427..9af8f25d153 100644 --- a/mysql-test/main/plugin_auth.test +++ b/mysql-test/main/plugin_auth.test @@ -445,6 +445,10 @@ connection default; disconnect cleartext_con; DROP USER uplain@localhost; +# prepare for two tests that use mysql.user table +source include/switch_to_mysql_user.inc; +drop view mysql.user_bak; + --echo # --echo # Bug #59038 : mysql.user.authentication_string column --echo # causes configuration wizard to fail @@ -502,7 +506,6 @@ SELECT IS_NULLABLE, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='mysql' ORDER BY COLUMN_NAME; - --echo # --echo # Bug #11936829: diff. between mysql.user (authentication_string) --echo # in fresh and upgraded 5.5.11 @@ -524,7 +527,8 @@ SELECT IS_NULLABLE, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS ORDER BY COLUMN_NAME; let $datadir= `select @@datadir`; remove_file $datadir/mysql_upgrade_info; - +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; --echo # --echo # Bug # 11766641: 59792: BIN/MYSQL -UUNKNOWN -PUNKNOWN diff --git a/mysql-test/main/plugin_auth_qa.result b/mysql-test/main/plugin_auth_qa.result index 4f274c45971..e00ac1a4c96 100644 --- a/mysql-test/main/plugin_auth_qa.result +++ b/mysql-test/main/plugin_auth_qa.result @@ -1,38 +1,38 @@ set sql_mode=""; CREATE DATABASE test_user_db; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string ========== test 1.1 ====================================================== CREATE USER plug IDENTIFIED WITH test_plugin_server; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server DROP USER plug; GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH test_plugin_server; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server REVOKE ALL PRIVILEGES ON test_user_db.* FROM plug; DROP USER plug; CREATE USER plug IDENTIFIED WITH 'test_plugin_server'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server DROP USER plug; GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH 'test_plugin_server'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server REVOKE ALL PRIVILEGES ON test_user_db.* FROM plug; DROP USER plug; CREATE USER plug IDENTIFIED WITH test_plugin_server AS ''; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server DROP USER plug; GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH test_plugin_server AS ''; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server REVOKE ALL PRIVILEGES ON test_user_db.* FROM plug; DROP USER plug; @@ -100,63 +100,63 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; ========== test 1.1.1.6/1.1.2.5 ============================ SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server plug_dest CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server plug_dest -plug_dest +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER plug, plug_dest; CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server plug_dest DROP USER plug; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -plug_dest +User plugin authentication_string +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER plug_dest; GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server plug_dest CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server plug_dest -plug_dest +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER plug, plug_dest; GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH test_plugin_server AS 'plug_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server plug_dest DROP USER plug; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -plug_dest +User plugin authentication_string +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER plug_dest; CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server plug_dest GRANT ALL PRIVILEGES ON test_user_db.* TO plug_dest IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server plug_dest -plug_dest +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER plug, plug_dest; CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server plug_dest DROP USER plug; GRANT ALL PRIVILEGES ON test_user_db.* TO plug_dest IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -plug_dest +User plugin authentication_string +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER plug_dest; CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; @@ -170,12 +170,12 @@ ERROR HY000: Operation CREATE USER failed for 'plug'@'%' DROP USER plug; CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password +User plugin authentication_string Password plug test_plugin_server plug_dest GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password -plug *939AEE68989794C0F408277411C26055CDF41119 +User plugin authentication_string Password +plug mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 *939AEE68989794C0F408277411C26055CDF41119 DROP USER plug; GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug IDENTIFIED BY 'plug_dest_passwd'; @@ -184,18 +184,18 @@ DROP USER plug; CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password +User plugin authentication_string Password plug test_plugin_server plug_dest plug_dest test_plugin_server plug_dest DROP USER plug,plug_dest; CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password +User plugin authentication_string Password plug test_plugin_server plug_dest GRANT ALL PRIVILEGES ON test_user_db.* TO plug_dest IDENTIFIED WITH test_plugin_server AS 'plug_dest'; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password +User plugin authentication_string Password plug test_plugin_server plug_dest plug_dest test_plugin_server plug_dest DROP USER plug,plug_dest; @@ -203,24 +203,24 @@ DROP USER plug,plug_dest; SET NAMES utf8; CREATE USER plüg IDENTIFIED WITH 'test_plugin_server' AS 'plüg_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plüg test_plugin_server plüg_dest DROP USER plüg; CREATE USER plüg_dest IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -plüg_dest +User plugin authentication_string +plüg_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER plüg_dest; SET NAMES ascii; CREATE USER 'plüg' IDENTIFIED WITH 'test_plugin_server' AS 'plüg_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string pl??g test_plugin_server pl??g_dest DROP USER 'plüg'; CREATE USER 'plüg_dest' IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -pl??g_dest +User plugin authentication_string +pl??g_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER 'plüg_dest'; SET NAMES latin1; ========== test 1.1.1.5 ==================================== @@ -228,36 +228,36 @@ CREATE USER 'plüg' IDENTIFIED WITH 'test_plügin_server' AS 'plüg_dest'; ERROR HY000: Plugin 'test_plügin_server' is not loaded CREATE USER 'plug' IDENTIFIED WITH 'test_plugin_server' AS 'plüg_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server plüg_dest DROP USER 'plug'; CREATE USER 'plüg_dest' IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -plüg_dest +User plugin authentication_string +plüg_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER 'plüg_dest'; SET NAMES utf8; CREATE USER plüg IDENTIFIED WITH 'test_plügin_server' AS 'plüg_dest'; ERROR HY000: Plugin 'test_plügin_server' is not loaded CREATE USER 'plüg' IDENTIFIED WITH 'test_plugin_server' AS 'plüg_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plüg test_plugin_server plüg_dest DROP USER 'plüg'; CREATE USER 'plüg_dest' IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -plüg_dest +User plugin authentication_string +plüg_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER 'plüg_dest'; CREATE USER plüg IDENTIFIED WITH test_plugin_server AS 'plüg_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plüg test_plugin_server plüg_dest DROP USER plüg; CREATE USER plüg_dest IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -plüg_dest +User plugin authentication_string +plüg_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER plüg_dest; ========== test 1.1.1.2/1.1.2.2============================= SET @auth_name= 'test_plugin_server'; @@ -271,13 +271,13 @@ CREATE USER plug IDENTIFIED WITH 'hh''s_test_plugin_server' AS 'plug_dest'; ERROR HY000: Plugin 'hh's_test_plugin_server' is not loaded CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'hh''s_plug_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string plug test_plugin_server hh's_plug_dest DROP USER plug; CREATE USER 'hh''s_plug_dest' IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -hh's_plug_dest +User plugin authentication_string +hh's_plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 DROP USER 'hh''s_plug_dest'; ========== test 1.1.1.4 ==================================== CREATE USER plug IDENTIFIED WITH hh''s_test_plugin_server AS 'plug_dest'; @@ -285,21 +285,21 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp ========== test 1.1.3.1 ==================================== GRANT INSERT ON test_user_db.* TO grant_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string grant_user test_plugin_server plug_dest CREATE USER plug_dest; DROP USER plug_dest; GRANT ALL PRIVILEGES ON test_user_db.* TO plug_dest; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string grant_user test_plugin_server plug_dest -plug_dest +plug_dest mysql_native_password DROP USER grant_user,plug_dest; set @save_sql_mode= @@sql_mode; SET @@sql_mode=no_auto_create_user; GRANT INSERT ON test_user_db.* TO grant_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string grant_user test_plugin_server plug_dest CREATE USER plug_dest; DROP USER plug_dest; @@ -308,19 +308,19 @@ ERROR 28000: Can't find any matching row in the user table DROP USER grant_user; GRANT INSERT ON test_user_db.* TO grant_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string grant_user test_plugin_server plug_dest CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password +User plugin authentication_string Password grant_user test_plugin_server plug_dest -plug_dest *939AEE68989794C0F408277411C26055CDF41119 +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 *939AEE68989794C0F408277411C26055CDF41119 DROP USER plug_dest; GRANT ALL PRIVILEGES ON test_user_db.* TO plug_dest IDENTIFIED BY 'plug_user_passwd'; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password +User plugin authentication_string Password grant_user test_plugin_server plug_dest -plug_dest *560881EB651416CEF77314D07D55EDCD5FC1BD6D +plug_dest mysql_native_password *560881EB651416CEF77314D07D55EDCD5FC1BD6D *560881EB651416CEF77314D07D55EDCD5FC1BD6D DROP USER grant_user,plug_dest; set @@sql_mode= @save_sql_mode; DROP DATABASE test_user_db; diff --git a/mysql-test/main/plugin_auth_qa_1.result b/mysql-test/main/plugin_auth_qa_1.result index 42a7b1491c0..dd709fee04c 100644 --- a/mysql-test/main/plugin_auth_qa_1.result +++ b/mysql-test/main/plugin_auth_qa_1.result @@ -1,6 +1,6 @@ CREATE DATABASE test_user_db; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string ========== test 1.1.3.2 ==================================== CREATE USER plug_user IDENTIFIED WITH test_plugin_server AS 'plug_dest'; CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; @@ -19,8 +19,8 @@ IDENTIFIED WITH test_plugin_server AS 'plug_dest'; GRANT ALL PRIVILEGES ON test_user_db.* TO plug_dest IDENTIFIED BY 'plug_dest_passwd'; GRANT PROXY ON plug_dest TO plug_user; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -plug_dest +User plugin authentication_string +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 plug_user test_plugin_server plug_dest 1) current_user() @@ -70,8 +70,8 @@ ERROR 1045 (28000): Access denied for user 'plug_user'@'localhost' (using passwo GRANT PROXY ON new_dest TO plug_user; ERROR 1045 (28000): Access denied for user 'plug_user'@'localhost' (using password: YES) SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -new_dest +User plugin authentication_string +new_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 plug_user test_plugin_server plug_dest DROP USER plug_user,new_dest; CREATE USER plug_user @@ -88,8 +88,8 @@ ERROR 1045 (28000): Access denied for user 'plug_user'@'localhost' (using passwo GRANT PROXY ON new_dest TO plug_user; ERROR 1045 (28000): Access denied for user 'plug_user'@'localhost' (using password: YES) SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -new_dest +User plugin authentication_string +new_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 plug_user test_plugin_server plug_dest DROP USER plug_user,new_dest; CREATE USER plug_user @@ -109,15 +109,15 @@ USER() CURRENT_USER() new_user@localhost plug_dest@% connection default; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string new_user test_plugin_server plug_dest -plug_dest +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 disconnect plug_user; -UPDATE mysql.user SET user='plug_user' WHERE user='new_user'; +UPDATE mysql.global_priv SET user='plug_user' WHERE user='new_user'; FLUSH PRIVILEGES; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -plug_dest +User plugin authentication_string +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 plug_user test_plugin_server plug_dest DROP USER plug_dest,plug_user; ========== test 1.3 ======================================== @@ -132,35 +132,37 @@ plug_user@localhost plug_dest@% connection default; disconnect plug_user; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -plug_dest +User plugin authentication_string +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 plug_user test_plugin_server plug_dest -UPDATE mysql.user SET user='new_user' WHERE user='plug_user'; +UPDATE mysql.global_priv SET user='new_user' WHERE user='plug_user'; FLUSH PRIVILEGES; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string new_user test_plugin_server plug_dest -plug_dest -UPDATE mysql.user SET authentication_string='new_dest' WHERE user='new_user'; +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 +UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.authentication_string', 'new_dest') WHERE user='new_user'; FLUSH PRIVILEGES; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string new_user test_plugin_server new_dest -plug_dest -UPDATE mysql.user SET plugin='new_plugin_server' WHERE user='new_user'; +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 +UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.plugin', 'new_plugin_server') WHERE user='new_user'; FLUSH PRIVILEGES; +Warnings: +Warning 1524 Plugin 'new_plugin_server' is not loaded SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string new_user new_plugin_server new_dest -plug_dest -ERROR HY000: Plugin 'new_plugin_server' is not loaded -UPDATE mysql.user SET plugin='test_plugin_server' WHERE user='new_user'; -UPDATE mysql.user SET USER='new_dest' WHERE user='plug_dest'; +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 +ERROR 28000: Access denied for user 'new_user'@'localhost' (using password: YES) +UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.plugin', 'test_plugin_server') WHERE user='new_user'; +UPDATE mysql.global_priv SET user='new_dest' WHERE user='plug_dest'; FLUSH PRIVILEGES; GRANT PROXY ON new_dest TO new_user; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -new_dest +User plugin authentication_string +new_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 new_user test_plugin_server new_dest connect plug_user,localhost,new_user,new_dest; select USER(),CURRENT_USER(); @@ -168,14 +170,14 @@ USER() CURRENT_USER() new_user@localhost new_dest@% connection default; disconnect plug_user; -UPDATE mysql.user SET USER='plug_dest' WHERE user='new_dest'; +UPDATE mysql.global_priv SET user='plug_dest' WHERE user='new_dest'; FLUSH PRIVILEGES; CREATE USER new_dest IDENTIFIED BY 'new_dest_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -new_dest +User plugin authentication_string +new_dest mysql_native_password *01422E86A6FFF84618914AF149F9AEF64B84170A new_user test_plugin_server new_dest -plug_dest +plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 GRANT ALL PRIVILEGES ON test.* TO new_user; connect plug_user,localhost,new_dest,new_dest_passwd; select USER(),CURRENT_USER(); @@ -188,9 +190,9 @@ DROP USER new_user,new_dest,plug_dest; CREATE USER ''@'%%' IDENTIFIED WITH test_plugin_server AS 'proxied_user'; CREATE USER proxied_user IDENTIFIED BY 'proxied_user_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string test_plugin_server proxied_user -proxied_user +proxied_user mysql_native_password *D7A51428CD38DB3C5293B9321DA1228BFB1611DD connect proxy_con,localhost,proxied_user,proxied_user_passwd; SELECT USER(),CURRENT_USER(); USER() CURRENT_USER() @@ -224,9 +226,9 @@ GRANT ALL PRIVILEGES ON test_user_db.* TO ''@'%%' IDENTIFIED WITH test_plugin_server AS 'proxied_user'; CREATE USER proxied_user IDENTIFIED BY 'proxied_user_passwd'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string test_plugin_server proxied_user -proxied_user +proxied_user mysql_native_password *D7A51428CD38DB3C5293B9321DA1228BFB1611DD connect proxy_con,localhost,proxied_user,proxied_user_passwd; SELECT USER(),CURRENT_USER(); USER() CURRENT_USER() @@ -266,13 +268,13 @@ GRANT PROXY ON proxied_user_3 TO ''@'%%'; GRANT PROXY ON proxied_user_4 TO ''@'%%'; GRANT PROXY ON proxied_user_5 TO ''@'%%'; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string +User plugin authentication_string test_plugin_server proxied_user -proxied_user_1 -proxied_user_2 -proxied_user_3 -proxied_user_4 -proxied_user_5 +proxied_user_1 mysql_native_password *551D5A5177FCC3340F7D2FB0F4D8D1EEA7F7EF71 +proxied_user_2 mysql_native_password *3D948F77C6A988AFDCA9755AB2A6724362557220 +proxied_user_3 mysql_native_password *41A18925D237DEE738C76581153990B037F462E3 +proxied_user_4 mysql_native_password *F990073A9B96FF535C2D0721406042B8751E593F +proxied_user_5 mysql_native_password *5AA915C5D0B5B1336336FD2BF7768BC09FD1F5B2 connect proxy_con_1,localhost,proxied_user_1,'proxied_user_1_pwd'; connect proxy_con_2,localhost,proxied_user_2,proxied_user_2_pwd; connect proxy_con_3,localhost,proxied_user_3,proxied_user_3_pwd; diff --git a/mysql-test/main/plugin_auth_qa_1.test b/mysql-test/main/plugin_auth_qa_1.test index b0b8ffb3544..81a9155a390 100644 --- a/mysql-test/main/plugin_auth_qa_1.test +++ b/mysql-test/main/plugin_auth_qa_1.test @@ -110,7 +110,7 @@ connection default; --sorted_result SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; disconnect plug_user; -UPDATE mysql.user SET user='plug_user' WHERE user='new_user'; +UPDATE mysql.global_priv SET user='plug_user' WHERE user='new_user'; FLUSH PRIVILEGES; --sorted_result SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; @@ -128,24 +128,24 @@ connection default; disconnect plug_user; --sorted_result SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -UPDATE mysql.user SET user='new_user' WHERE user='plug_user'; +UPDATE mysql.global_priv SET user='new_user' WHERE user='plug_user'; FLUSH PRIVILEGES; --sorted_result SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -UPDATE mysql.user SET authentication_string='new_dest' WHERE user='new_user'; +UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.authentication_string', 'new_dest') WHERE user='new_user'; FLUSH PRIVILEGES; --sorted_result SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -UPDATE mysql.user SET plugin='new_plugin_server' WHERE user='new_user'; +UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.plugin', 'new_plugin_server') WHERE user='new_user'; FLUSH PRIVILEGES; --sorted_result SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; --disable_query_log ---error ER_PLUGIN_IS_NOT_LOADED +--error ER_ACCESS_DENIED_ERROR connect(plug_user,localhost,new_user,new_dest); --enable_query_log -UPDATE mysql.user SET plugin='test_plugin_server' WHERE user='new_user'; -UPDATE mysql.user SET USER='new_dest' WHERE user='plug_dest'; +UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.plugin', 'test_plugin_server') WHERE user='new_user'; +UPDATE mysql.global_priv SET user='new_dest' WHERE user='plug_dest'; FLUSH PRIVILEGES; GRANT PROXY ON new_dest TO new_user; --sorted_result @@ -154,7 +154,7 @@ connect(plug_user,localhost,new_user,new_dest); select USER(),CURRENT_USER(); connection default; disconnect plug_user; -UPDATE mysql.user SET USER='plug_dest' WHERE user='new_dest'; +UPDATE mysql.global_priv SET user='plug_dest' WHERE user='new_dest'; FLUSH PRIVILEGES; CREATE USER new_dest IDENTIFIED BY 'new_dest_passwd'; --sorted_result diff --git a/mysql-test/main/plugin_auth_qa_2.result b/mysql-test/main/plugin_auth_qa_2.result index fa88530be6a..e71132e2bc9 100644 --- a/mysql-test/main/plugin_auth_qa_2.result +++ b/mysql-test/main/plugin_auth_qa_2.result @@ -6,8 +6,8 @@ CREATE USER qa_test_1_dest IDENTIFIED BY 'dest_passwd'; GRANT ALL PRIVILEGES ON test_user_db.* TO qa_test_1_dest identified by 'dest_passwd'; GRANT PROXY ON qa_test_1_dest TO qa_test_1_user; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -qa_test_1_dest +User plugin authentication_string +qa_test_1_dest mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 qa_test_1_user qa_auth_interface qa_test_1_dest SELECT @@proxy_user; @@proxy_user @@ -19,8 +19,8 @@ exec MYSQL -h localhost -P MASTER_MYPORT -u qa_test_1_user --password=qa_test_1_ current_user() user() @@local.proxy_user @@local.external_user qa_test_1_user@% qa_test_1_user@localhost NULL NULL SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -qa_test_1_dest +User plugin authentication_string +qa_test_1_dest mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 qa_test_1_user qa_auth_interface qa_test_1_dest DROP USER qa_test_1_user; DROP USER qa_test_1_dest; @@ -32,9 +32,9 @@ GRANT ALL PRIVILEGES ON test_user_db.* TO qa_test_2_dest identified by 'dest_pas GRANT PROXY ON qa_test_2_dest TO qa_test_2_user; GRANT PROXY ON authenticated_as TO qa_test_2_user; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -authenticated_as -qa_test_2_dest +User plugin authentication_string +authenticated_as mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 +qa_test_2_dest mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 qa_test_2_user qa_auth_interface qa_test_2_dest SELECT @@proxy_user; @@proxy_user @@ -46,9 +46,9 @@ exec MYSQL -h localhost -P MASTER_MYPORT -u qa_test_2_user --password=qa_test_2_ current_user() user() @@local.proxy_user @@local.external_user authenticated_as@% user_name@localhost 'qa_test_2_user'@'%' externaluser SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -authenticated_as -qa_test_2_dest +User plugin authentication_string +authenticated_as mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 +qa_test_2_dest mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 qa_test_2_user qa_auth_interface qa_test_2_dest DROP USER qa_test_2_user; DROP USER qa_test_2_dest; @@ -82,9 +82,9 @@ GRANT ALL PRIVILEGES ON test_user_db.* TO ''@'localhost' identified by 'dest_pas GRANT PROXY ON qa_test_5_dest TO qa_test_5_user; GRANT PROXY ON qa_test_5_dest TO ''@'localhost'; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password - *DFCACE76914AD7BD801FC1A1ECF6562272621A22 -qa_test_5_dest *DFCACE76914AD7BD801FC1A1ECF6562272621A22 +User plugin authentication_string Password + mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 *DFCACE76914AD7BD801FC1A1ECF6562272621A22 +qa_test_5_dest mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 *DFCACE76914AD7BD801FC1A1ECF6562272621A22 qa_test_5_user qa_auth_interface qa_test_5_dest exec MYSQL -h localhost -P MASTER_MYPORT --user=qa_test_5_user --password=qa_test_5_dest test_user_db -e "SELECT current_user(),user(),@@local.proxy_user,@@local.external_user;" 2>&1 ERROR 1045 (28000): Access denied for user 'qa_test_5_user'@'localhost' (using password: YES) @@ -97,22 +97,22 @@ CREATE USER qa_test_6_dest IDENTIFIED BY 'dest_passwd'; GRANT ALL PRIVILEGES ON test_user_db.* TO qa_test_6_dest identified by 'dest_passwd'; GRANT PROXY ON qa_test_6_dest TO qa_test_6_user; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password -qa_test_6_dest *DFCACE76914AD7BD801FC1A1ECF6562272621A22 +User plugin authentication_string Password +qa_test_6_dest mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 *DFCACE76914AD7BD801FC1A1ECF6562272621A22 qa_test_6_user qa_auth_interface qa_test_6_dest exec MYSQL -h localhost -P MASTER_MYPORT --user=qa_test_6_user --password=qa_test_6_dest test_user_db -e "SELECT current_user(),user(),@@local.proxy_user,@@local.external_user;" 2>&1 ERROR 1045 (28000): Access denied for user 'qa_test_6_user'@'localhost' (using password: YES) GRANT PROXY ON qa_test_6_dest TO root IDENTIFIED WITH qa_auth_interface AS 'qa_test_6_dest'; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password -qa_test_6_dest *DFCACE76914AD7BD801FC1A1ECF6562272621A22 +User plugin authentication_string Password +qa_test_6_dest mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 *DFCACE76914AD7BD801FC1A1ECF6562272621A22 qa_test_6_user qa_auth_interface qa_test_6_dest exec MYSQL -h localhost -P MASTER_MYPORT --user=root --password=qa_test_6_dest test_user_db -e "SELECT current_user(),user(),@@local.proxy_user,@@local.external_user;" 2>&1 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) REVOKE PROXY ON qa_test_6_dest FROM root; SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; -user plugin authentication_string -qa_test_6_dest +User plugin authentication_string +qa_test_6_dest mysql_native_password *DFCACE76914AD7BD801FC1A1ECF6562272621A22 qa_test_6_user qa_auth_interface qa_test_6_dest exec MYSQL -h localhost -P MASTER_MYPORT --user=root --password=qa_test_6_dest test_user_db -e "SELECT current_user(),user(),@@local.proxy_user,@@local.external_user;" 2>&1 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) @@ -120,7 +120,7 @@ DROP USER qa_test_6_user; DROP USER qa_test_6_dest; DELETE FROM mysql.user WHERE user='root' AND plugin='qa_auth_interface'; SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root'; -user plugin authentication_string password +User plugin authentication_string Password === Test of the --default_auth option for clients ==== CREATE USER qa_test_11_user IDENTIFIED WITH qa_auth_interface AS 'qa_test_11_dest'; CREATE USER qa_test_11_dest IDENTIFIED BY 'dest_passwd'; diff --git a/mysql-test/main/plugin_innodb.result b/mysql-test/main/plugin_innodb.result index 48510ad8745..d8cc777d9cb 100644 --- a/mysql-test/main/plugin_innodb.result +++ b/mysql-test/main/plugin_innodb.result @@ -7,5 +7,5 @@ create table t1(a int) engine=example; select * from t1; a drop table t1; -alter table mysql.plugin engine=myisam; +alter table mysql.plugin engine=aria; uninstall plugin example; diff --git a/mysql-test/main/plugin_innodb.test b/mysql-test/main/plugin_innodb.test index fb5dd84b997..5700486b218 100644 --- a/mysql-test/main/plugin_innodb.test +++ b/mysql-test/main/plugin_innodb.test @@ -22,6 +22,6 @@ create table t1(a int) engine=example; select * from t1; drop table t1; -alter table mysql.plugin engine=myisam; +alter table mysql.plugin engine=aria; uninstall plugin example; diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index b0c7c7d9847..a72b6660288 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -244,6 +244,8 @@ prepare stmt1 from "insert into t1 select i from t1"; execute stmt1; execute stmt1; prepare stmt1 from "select * from t1 into outfile '<MYSQLTEST_VARDIR>/tmp/f1.txt'"; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead execute stmt1; deallocate prepare stmt1; drop table t1; @@ -1379,9 +1381,11 @@ test.t1 optimize status Table is already up to date prepare stmt from "analyze table t1"; execute stmt; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date execute stmt; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date prepare stmt from "repair table t1, t2, t3"; execute stmt; @@ -1408,13 +1412,19 @@ test.t3 optimize status Table is already up to date prepare stmt from "analyze table t1, t2, t3"; execute stmt; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status Table is already up to date execute stmt; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status Table is already up to date prepare stmt from "repair table t1, t4, t3"; execute stmt; @@ -1447,11 +1457,13 @@ execute stmt; Table Op Msg_type Msg_text test.t4 analyze Error Table 'test.t4' doesn't exist test.t4 analyze status Operation failed +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date execute stmt; Table Op Msg_type Msg_text test.t4 analyze Error Table 'test.t4' doesn't exist test.t4 analyze status Operation failed +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date deallocate prepare stmt; drop table t1, t2, t3; @@ -1518,6 +1530,7 @@ Field Type Null Key Default Extra i int(11) YES NULL execute stmt_analyze; Table Op Msg_type Msg_text +mysqltest_long_database_name_to_thrash_heap.t1 analyze status Engine-independent statistics collected mysqltest_long_database_name_to_thrash_heap.t1 analyze status Table is already up to date execute stmt_optimize; Table Op Msg_type Msg_text @@ -2132,12 +2145,13 @@ Database Table In_use Name_locked mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User -select Host, Db from mysql.host limit 0; -Host Db show open tables from mysql; Database Table In_use Name_locked +mysql column_stats 0 0 mysql general_log 0 0 -mysql host 0 0 +mysql global_priv 0 0 +mysql index_stats 0 0 +mysql table_stats 0 0 mysql user 0 0 call proc_1(); show open tables from mysql; @@ -2145,12 +2159,13 @@ Database Table In_use Name_locked mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User -select Host, Db from mysql.host limit 0; -Host Db show open tables from mysql; Database Table In_use Name_locked +mysql column_stats 0 0 mysql general_log 0 0 -mysql host 0 0 +mysql global_priv 0 0 +mysql index_stats 0 0 +mysql table_stats 0 0 mysql user 0 0 call proc_1(); show open tables from mysql; @@ -2158,12 +2173,13 @@ Database Table In_use Name_locked mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User -select Host, Db from mysql.host limit 0; -Host Db show open tables from mysql; Database Table In_use Name_locked +mysql column_stats 0 0 mysql general_log 0 0 -mysql host 0 0 +mysql global_priv 0 0 +mysql index_stats 0 0 +mysql table_stats 0 0 mysql user 0 0 call proc_1(); show open tables from mysql; @@ -2171,12 +2187,13 @@ Database Table In_use Name_locked mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User -select Host, Db from mysql.host limit 0; -Host Db show open tables from mysql; Database Table In_use Name_locked +mysql column_stats 0 0 mysql general_log 0 0 -mysql host 0 0 +mysql global_priv 0 0 +mysql index_stats 0 0 +mysql table_stats 0 0 mysql user 0 0 flush tables; create function func_1() returns int begin flush tables; return 1; end| @@ -2189,12 +2206,13 @@ drop procedure proc_1; flush tables; select Host, User from mysql.user limit 0; Host User -select Host, Db from mysql.host limit 0; -Host Db show open tables from mysql; Database Table In_use Name_locked +mysql column_stats 0 0 mysql general_log 0 0 -mysql host 0 0 +mysql global_priv 0 0 +mysql index_stats 0 0 +mysql table_stats 0 0 mysql user 0 0 prepare abc from "flush tables"; execute abc; @@ -2203,12 +2221,13 @@ Database Table In_use Name_locked mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User -select Host, Db from mysql.host limit 0; -Host Db show open tables from mysql; Database Table In_use Name_locked +mysql column_stats 0 0 mysql general_log 0 0 -mysql host 0 0 +mysql global_priv 0 0 +mysql index_stats 0 0 +mysql table_stats 0 0 mysql user 0 0 execute abc; show open tables from mysql; @@ -2216,12 +2235,13 @@ Database Table In_use Name_locked mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User -select Host, Db from mysql.host limit 0; -Host Db show open tables from mysql; Database Table In_use Name_locked +mysql column_stats 0 0 mysql general_log 0 0 -mysql host 0 0 +mysql global_priv 0 0 +mysql index_stats 0 0 +mysql table_stats 0 0 mysql user 0 0 execute abc; show open tables from mysql; @@ -2229,12 +2249,13 @@ Database Table In_use Name_locked mysql general_log 0 0 select Host, User from mysql.user limit 0; Host User -select Host, Db from mysql.host limit 0; -Host Db show open tables from mysql; Database Table In_use Name_locked +mysql column_stats 0 0 mysql general_log 0 0 -mysql host 0 0 +mysql global_priv 0 0 +mysql index_stats 0 0 +mysql table_stats 0 0 mysql user 0 0 flush tables; deallocate prepare abc; @@ -5243,6 +5264,7 @@ CREATE PROCEDURE p1(tn VARCHAR(32)) EXECUTE IMMEDIATE CONCAT('ANALYZE TABLE ',tn); CALL p1('t1'); Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date DROP PROCEDURE p1; DROP TABLE t1; diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test index 2b8a05094a6..86ae11ccb61 100644 --- a/mysql-test/main/ps.test +++ b/mysql-test/main/ps.test @@ -2228,28 +2228,24 @@ flush tables; --sorted_result show open tables from mysql; select Host, User from mysql.user limit 0; -select Host, Db from mysql.host limit 0; --sorted_result show open tables from mysql; call proc_1(); --sorted_result show open tables from mysql; select Host, User from mysql.user limit 0; -select Host, Db from mysql.host limit 0; --sorted_result show open tables from mysql; call proc_1(); --sorted_result show open tables from mysql; select Host, User from mysql.user limit 0; -select Host, Db from mysql.host limit 0; --sorted_result show open tables from mysql; call proc_1(); --sorted_result show open tables from mysql; select Host, User from mysql.user limit 0; -select Host, Db from mysql.host limit 0; --sorted_result show open tables from mysql; flush tables; @@ -2269,7 +2265,6 @@ drop procedure proc_1; --disable_ps_protocol flush tables; select Host, User from mysql.user limit 0; -select Host, Db from mysql.host limit 0; --sorted_result show open tables from mysql; --enable_ps_protocol @@ -2279,21 +2274,18 @@ execute abc; --sorted_result show open tables from mysql; select Host, User from mysql.user limit 0; -select Host, Db from mysql.host limit 0; --sorted_result show open tables from mysql; execute abc; --sorted_result show open tables from mysql; select Host, User from mysql.user limit 0; -select Host, Db from mysql.host limit 0; --sorted_result show open tables from mysql; execute abc; --sorted_result show open tables from mysql; select Host, User from mysql.user limit 0; -select Host, Db from mysql.host limit 0; --sorted_result show open tables from mysql; flush tables; diff --git a/mysql-test/main/ps_ddl.result b/mysql-test/main/ps_ddl.result index 68acf50aee1..c5c5b5a9ac0 100644 --- a/mysql-test/main/ps_ddl.result +++ b/mysql-test/main/ps_ddl.result @@ -20,6 +20,8 @@ else select '' as "SUCCESS"; end if; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead set @reprepare_count= 0; flush status; ===================================================================== @@ -767,11 +769,12 @@ deallocate prepare stmt; # # Test 3: View referencing an Information schema table # -create view t1 as select table_name from information_schema.views; +create view t1 as select table_name from information_schema.views order by table_name; prepare stmt from "select * from t1"; execute stmt; table_name t1 +user call p_verify_reprepare_count(0); SUCCESS @@ -779,6 +782,7 @@ create temporary table t1 (a int); execute stmt; table_name t1 +user call p_verify_reprepare_count(0); SUCCESS @@ -1071,6 +1075,8 @@ call p1(x); return x; end| create procedure p1(out x int) select max(a) from t1 into x; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead prepare stmt from "select * from v1"; execute stmt; f1() @@ -1083,6 +1089,8 @@ SUCCESS drop procedure p1; create procedure p1(out x int) select max(a) from t2 into x; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # XXX: used to be a bug. The prelocked list was not invalidated # and we kept opening table t1, whereas the procedure # is now referring to table t2 @@ -1399,6 +1407,7 @@ SUCCESS prepare stmt from "analyze table t1"; execute stmt; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK drop table t1; create table t1 (a1 int, a2 int); @@ -1406,14 +1415,17 @@ insert into t1 values (1, 10), (2, 20), (3, 30); # t1 has changed, and it's not a problem execute stmt; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK alter table t1 add column b varchar(50) default NULL; execute stmt; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK alter table t1 drop column b; execute stmt; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK call p_verify_reprepare_count(0); SUCCESS diff --git a/mysql-test/main/ps_ddl.test b/mysql-test/main/ps_ddl.test index 90226d379bf..dafb5b5dea3 100644 --- a/mysql-test/main/ps_ddl.test +++ b/mysql-test/main/ps_ddl.test @@ -699,7 +699,7 @@ deallocate prepare stmt; --echo # --echo # Test 3: View referencing an Information schema table --echo # -create view t1 as select table_name from information_schema.views; +create view t1 as select table_name from information_schema.views order by table_name; prepare stmt from "select * from t1"; execute stmt; diff --git a/mysql-test/main/ps_ddl1.result b/mysql-test/main/ps_ddl1.result index 667cbed8a7a..5178ee64f16 100644 --- a/mysql-test/main/ps_ddl1.result +++ b/mysql-test/main/ps_ddl1.result @@ -20,6 +20,8 @@ else select '' as "SUCCESS"; end if; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead set @reprepare_count= 0; flush status; drop table if exists t1; diff --git a/mysql-test/main/query_cache.result b/mysql-test/main/query_cache.result index 9c010cbffc7..f5d8b5eb461 100644 --- a/mysql-test/main/query_cache.result +++ b/mysql-test/main/query_cache.result @@ -645,9 +645,13 @@ show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 select * from t1 into outfile "query_cache.out.file"; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select * from t1 into outfile "query_cache.out.file"; ERROR HY000: File 'query_cache.out.file' already exists select * from t1 limit 1 into dumpfile "query_cache.dump.file"; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 @@ -963,19 +967,19 @@ INSERT INTO t1 VALUES ('20050326'); INSERT INTO t1 VALUES ('20050325'); SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) -0 +1 Warnings: -Warning 1292 Incorrect datetime value: '20050327 invalid' +Warning 1292 Truncated incorrect date value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) -0 +1 Warnings: -Warning 1292 Incorrect datetime value: '20050328 invalid' +Warning 1292 Truncated incorrect date value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) -0 +1 Warnings: -Warning 1292 Incorrect datetime value: '20050327 invalid' +Warning 1292 Truncated incorrect date value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 @@ -1100,6 +1104,8 @@ Declare var1 int; select max(a) from t1 into var1; return var1; end// +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create procedure `p1`() begin select a, f1() from t1; @@ -1858,17 +1864,17 @@ DROP TABLE t1; SET GLOBAL query_cache_size= default; CREATE TABLE t1( a INT ); SET @v = ( SELECT SQL_CACHE 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1 )' at line 1 +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' SET @v = ( SELECT SQL_NO_CACHE 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1 )' at line 1 +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' SELECT a FROM t1 WHERE a IN ( SELECT SQL_CACHE a FROM t1 ); -ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' SELECT a FROM t1 WHERE a IN ( SELECT SQL_NO_CACHE a FROM t1 ); -ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' SELECT ( SELECT SQL_CACHE a FROM t1 ); -ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' SELECT ( SELECT SQL_NO_CACHE a FROM t1 ); -ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' SELECT SQL_CACHE * FROM t1; a SELECT SQL_NO_CACHE * FROM t1; @@ -1878,18 +1884,18 @@ ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' SELECT * FROM t1 WHERE a IN (SELECT SQL_CACHE a FROM t1); -ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_CACHE a FROM t1); -ERROR 42S22: Unknown column 'SQL_CACHE' in 'field list' +ERROR 42000: Incorrect usage/placement of 'SQL_CACHE' SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' SELECT * FROM t1 WHERE a IN (SELECT SQL_NO_CACHE a FROM t1); -ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); -ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' SELECT SQL_CACHE SQL_NO_CACHE * FROM t1; -ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE +ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE SELECT SQL_NO_CACHE SQL_CACHE * FROM t1; ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1; @@ -1902,10 +1908,10 @@ SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' SELECT SQL_CACHE * FROM t1 WHERE a IN (SELECT SQL_NO_CACHE a FROM t1); -ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' SELECT SQL_CACHE * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); -ERROR 42S22: Unknown column 'SQL_NO_CACHE' in 'field list' +ERROR 42000: Incorrect usage/placement of 'SQL_NO_CACHE' DROP TABLE t1; End of 5.1 tests # diff --git a/mysql-test/main/query_cache.test b/mysql-test/main/query_cache.test index 1b1e24bc6f4..389aa0de2fa 100644 --- a/mysql-test/main/query_cache.test +++ b/mysql-test/main/query_cache.test @@ -1534,22 +1534,21 @@ SET GLOBAL query_cache_size= default; # CREATE TABLE t1( a INT ); ---error ER_PARSE_ERROR +--error ER_CANT_USE_OPTION_HERE SET @v = ( SELECT SQL_CACHE 1 ); ---error ER_PARSE_ERROR +--error ER_CANT_USE_OPTION_HERE SET @v = ( SELECT SQL_NO_CACHE 1 ); # -# Keywords 'SQL_CACHE' and 'SQL_NO_CACHE' are allowed as column names. -# Hence the error messages are not intuitive. +# Keywords 'SQL_CACHE' and 'SQL_NO_CACHE'. # ---error ER_BAD_FIELD_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT a FROM t1 WHERE a IN ( SELECT SQL_CACHE a FROM t1 ); ---error ER_BAD_FIELD_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT a FROM t1 WHERE a IN ( SELECT SQL_NO_CACHE a FROM t1 ); ---error ER_BAD_FIELD_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT ( SELECT SQL_CACHE a FROM t1 ); ---error ER_BAD_FIELD_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT ( SELECT SQL_NO_CACHE a FROM t1 ); SELECT SQL_CACHE * FROM t1; @@ -1560,16 +1559,16 @@ SELECT SQL_NO_CACHE * FROM t1; SELECT * FROM t1 UNION SELECT SQL_CACHE * FROM t1; --error ER_CANT_USE_OPTION_HERE SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; ---error ER_BAD_FIELD_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT * FROM t1 WHERE a IN (SELECT SQL_CACHE a FROM t1); ---error ER_BAD_FIELD_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_CACHE a FROM t1); --error ER_CANT_USE_OPTION_HERE SELECT * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; ---error ER_BAD_FIELD_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT * FROM t1 WHERE a IN (SELECT SQL_NO_CACHE a FROM t1); ---error ER_BAD_FIELD_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); --error ER_WRONG_USAGE @@ -1584,10 +1583,10 @@ SELECT SQL_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_CACHE * FROM t1; --error ER_CANT_USE_OPTION_HERE SELECT SQL_NO_CACHE * FROM t1 UNION SELECT SQL_NO_CACHE * FROM t1; ---error ER_BAD_FIELD_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT SQL_CACHE * FROM t1 WHERE a IN (SELECT SQL_NO_CACHE a FROM t1); ---error ER_BAD_FIELD_ERROR +--error ER_CANT_USE_OPTION_HERE SELECT SQL_CACHE * FROM t1 WHERE a IN (SELECT a FROM t1 UNION SELECT SQL_NO_CACHE a FROM t1); diff --git a/mysql-test/main/range.result b/mysql-test/main/range.result index 32e0cf2868c..2c2f7be096d 100644 --- a/mysql-test/main/range.result +++ b/mysql-test/main/range.result @@ -416,7 +416,9 @@ count(*) 1026 analyze table t1,t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0; id select_type table type possible_keys key key_len ref rows Extra @@ -1101,7 +1103,7 @@ id select_type table type possible_keys key key_len ref rows Extra SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; item started price Warnings: -Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' +Warning 1292 Truncated incorrect datetime value: '2005-12-01 24:00:00' SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-02 00:00:00'; item started price A1 2005-11-01 08:00:00 1000.000 @@ -1113,7 +1115,7 @@ id select_type table type possible_keys key key_len ref rows Extra SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; item started price Warnings: -Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' +Warning 1292 Truncated incorrect datetime value: '2005-12-01 24:00:00' SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-02 00:00:00'; item started price A1 2005-11-01 08:00:00 1000.000 @@ -1563,7 +1565,7 @@ str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND str_to_date('2007-20-00', '%Y-%m-%d') <= ''; str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND @@ -1578,7 +1580,7 @@ SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'; str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND ''; str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND '' NULL @@ -1886,6 +1888,7 @@ alter table t1 add key2 int not null, add index i2(key2); update t1 set key2=key1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK create table t2 (a int); insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8); @@ -2084,6 +2087,7 @@ insert into t2 select * from t2; insert into t2 values (0, 0, 0, 0), (1, 1, 1, 1); analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK select a, b from t2 where (a, b) in ((0, 0), (1, 1)); a b @@ -2473,7 +2477,7 @@ EXPLAIN "key_length": "5", "used_key_parts": ["d"], "rows": 3, - "filtered": 100, + "filtered": 55, "index_condition": "t2.d is not null", "attached_condition": "(t2.d,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((2,2)))" }, @@ -2529,8 +2533,8 @@ insert into t2 values explain select * from t1,t2 where a = d and (a,e) in ((3,3),(7,7),(8,8)) and length(f) = 1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range idx idx 5 NULL 6 Using index condition -1 SIMPLE t2 ref idx1,idx2 idx1 5 test.t1.a 12 Using where +1 SIMPLE t2 range idx1,idx2 idx1 5 NULL 8 Using index condition; Using where +1 SIMPLE t1 ref idx idx 5 test.t2.d 8 explain format=json select * from t1,t2 where a = d and (a,e) in ((3,3),(7,7),(8,8)) and length(f) = 1; EXPLAIN @@ -2538,27 +2542,27 @@ EXPLAIN "query_block": { "select_id": 1, "table": { - "table_name": "t1", + "table_name": "t2", "access_type": "range", - "possible_keys": ["idx"], - "key": "idx", + "possible_keys": ["idx1", "idx2"], + "key": "idx1", "key_length": "5", - "used_key_parts": ["a"], - "rows": 6, - "filtered": 100, - "index_condition": "t1.a is not null" + "used_key_parts": ["d"], + "rows": 8, + "filtered": 12.5, + "index_condition": "t2.d is not null", + "attached_condition": "(t2.d,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1" }, "table": { - "table_name": "t2", + "table_name": "t1", "access_type": "ref", - "possible_keys": ["idx1", "idx2"], - "key": "idx1", + "possible_keys": ["idx"], + "key": "idx", "key_length": "5", - "used_key_parts": ["d"], - "ref": ["test.t1.a"], - "rows": 12, - "filtered": 100, - "attached_condition": "(t1.a,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1" + "used_key_parts": ["a"], + "ref": ["test.t2.d"], + "rows": 8, + "filtered": 100 } } } @@ -2566,16 +2570,16 @@ select * from t1,t2 where a = d and (a,e) in ((3,3),(7,7),(8,8)) and length(f) = 1; a b c d e f 3 2 uuuw 3 3 i -3 2 uuuw 3 3 i -3 2 uuua 3 3 i 3 2 uuua 3 3 i 3 3 zzzz 3 3 i -3 3 zzzz 3 3 i -3 3 zyxw 3 3 i 3 3 zyxw 3 3 i 3 3 zzza 3 3 i -3 3 zzza 3 3 i 3 3 zyxa 3 3 i +3 2 uuuw 3 3 i +3 2 uuua 3 3 i +3 3 zzzz 3 3 i +3 3 zyxw 3 3 i +3 3 zzza 3 3 i 3 3 zyxa 3 3 i 7 7 xxxyy 7 7 h 7 7 xxxya 7 7 h @@ -2586,16 +2590,16 @@ where a = d and (a,e) in ((3,3),(7,7),(8,8)) and length(f) = 1"; execute stmt; a b c d e f 3 2 uuuw 3 3 i -3 2 uuuw 3 3 i -3 2 uuua 3 3 i 3 2 uuua 3 3 i 3 3 zzzz 3 3 i -3 3 zzzz 3 3 i -3 3 zyxw 3 3 i 3 3 zyxw 3 3 i 3 3 zzza 3 3 i -3 3 zzza 3 3 i 3 3 zyxa 3 3 i +3 2 uuuw 3 3 i +3 2 uuua 3 3 i +3 3 zzzz 3 3 i +3 3 zyxw 3 3 i +3 3 zzza 3 3 i 3 3 zyxa 3 3 i 7 7 xxxyy 7 7 h 7 7 xxxya 7 7 h @@ -2604,16 +2608,16 @@ a b c d e f execute stmt; a b c d e f 3 2 uuuw 3 3 i -3 2 uuuw 3 3 i 3 2 uuua 3 3 i -3 2 uuua 3 3 i -3 3 zzzz 3 3 i 3 3 zzzz 3 3 i 3 3 zyxw 3 3 i -3 3 zyxw 3 3 i -3 3 zzza 3 3 i 3 3 zzza 3 3 i 3 3 zyxa 3 3 i +3 2 uuuw 3 3 i +3 2 uuua 3 3 i +3 3 zzzz 3 3 i +3 3 zyxw 3 3 i +3 3 zzza 3 3 i 3 3 zyxa 3 3 i 7 7 xxxyy 7 7 h 7 7 xxxya 7 7 h @@ -2642,7 +2646,7 @@ EXPLAIN "key_length": "5", "used_key_parts": ["e"], "rows": 6, - "filtered": 100, + "filtered": 6.7308, "attached_condition": "(t2.d,t2.e) in (<cache>((4,4)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1 and t2.d is not null" }, "table": { @@ -2993,6 +2997,7 @@ insert into t1 select a+15, concat(b,'yy') from t1; insert into t1 select a+100, concat(b,'xx') from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select cast(count(a)/count(distinct a) as unsigned) as rec_per_key from t1; rec_per_key @@ -3011,7 +3016,7 @@ a b set eq_range_index_dive_limit=2; explain select * from t1 where a in (8, 15, 31, 1, 9); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range idx idx 5 NULL 10 Using index condition +1 SIMPLE t1 range idx idx 5 NULL 5 Using index condition select * from t1 where a in (8, 15, 31, 1, 9); a b 1 yy diff --git a/mysql-test/main/range_innodb.result b/mysql-test/main/range_innodb.result index 794e6c7b3cc..2ede6351957 100644 --- a/mysql-test/main/range_innodb.result +++ b/mysql-test/main/range_innodb.result @@ -30,6 +30,7 @@ repeat('0123456789', 10) from t1; analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK # The following must not use "Range checked for each record": explain select * from t0 left join t2 on t2.a <t0.a and t2.b between 50 and 250; diff --git a/mysql-test/main/range_mrr_icp.result b/mysql-test/main/range_mrr_icp.result index 6b5bf33239f..97f35bfe7b3 100644 --- a/mysql-test/main/range_mrr_icp.result +++ b/mysql-test/main/range_mrr_icp.result @@ -418,7 +418,9 @@ count(*) 1026 analyze table t1,t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0; id select_type table type possible_keys key key_len ref rows Extra @@ -1103,7 +1105,7 @@ id select_type table type possible_keys key key_len ref rows Extra SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; item started price Warnings: -Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' +Warning 1292 Truncated incorrect datetime value: '2005-12-01 24:00:00' SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-02 00:00:00'; item started price A1 2005-11-01 08:00:00 1000.000 @@ -1115,7 +1117,7 @@ id select_type table type possible_keys key key_len ref rows Extra SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00'; item started price Warnings: -Warning 1292 Incorrect datetime value: '2005-12-01 24:00:00' +Warning 1292 Truncated incorrect datetime value: '2005-12-01 24:00:00' SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-02 00:00:00'; item started price A1 2005-11-01 08:00:00 1000.000 @@ -1565,7 +1567,7 @@ str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND str_to_date('2007-20-00', '%Y-%m-%d') <= ''; str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND @@ -1580,7 +1582,7 @@ SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'; str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND ''; str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND '' NULL @@ -1888,6 +1890,7 @@ alter table t1 add key2 int not null, add index i2(key2); update t1 set key2=key1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK create table t2 (a int); insert into t2 values (1),(2),(3),(4),(5),(6),(7),(8); @@ -2086,6 +2089,7 @@ insert into t2 select * from t2; insert into t2 values (0, 0, 0, 0), (1, 1, 1, 1); analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK select a, b from t2 where (a, b) in ((0, 0), (1, 1)); a b @@ -2478,7 +2482,7 @@ EXPLAIN "key_length": "5", "used_key_parts": ["d"], "rows": 3, - "filtered": 100, + "filtered": 55, "index_condition": "t2.d is not null", "attached_condition": "(t2.d,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((2,2)))", "mrr_type": "Rowid-ordered scan" @@ -2535,8 +2539,8 @@ insert into t2 values explain select * from t1,t2 where a = d and (a,e) in ((3,3),(7,7),(8,8)) and length(f) = 1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range idx idx 5 NULL 6 Using index condition; Rowid-ordered scan -1 SIMPLE t2 ref idx1,idx2 idx1 5 test.t1.a 12 Using where +1 SIMPLE t2 range idx1,idx2 idx1 5 NULL 8 Using index condition; Using where; Rowid-ordered scan +1 SIMPLE t1 ref idx idx 5 test.t2.d 8 explain format=json select * from t1,t2 where a = d and (a,e) in ((3,3),(7,7),(8,8)) and length(f) = 1; EXPLAIN @@ -2544,88 +2548,88 @@ EXPLAIN "query_block": { "select_id": 1, "table": { - "table_name": "t1", + "table_name": "t2", "access_type": "range", - "possible_keys": ["idx"], - "key": "idx", + "possible_keys": ["idx1", "idx2"], + "key": "idx1", "key_length": "5", - "used_key_parts": ["a"], - "rows": 6, - "filtered": 100, - "index_condition": "t1.a is not null", + "used_key_parts": ["d"], + "rows": 8, + "filtered": 12.5, + "index_condition": "t2.d is not null", + "attached_condition": "(t2.d,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1", "mrr_type": "Rowid-ordered scan" }, "table": { - "table_name": "t2", + "table_name": "t1", "access_type": "ref", - "possible_keys": ["idx1", "idx2"], - "key": "idx1", + "possible_keys": ["idx"], + "key": "idx", "key_length": "5", - "used_key_parts": ["d"], - "ref": ["test.t1.a"], - "rows": 12, - "filtered": 100, - "attached_condition": "(t1.a,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1" + "used_key_parts": ["a"], + "ref": ["test.t2.d"], + "rows": 8, + "filtered": 100 } } } select * from t1,t2 where a = d and (a,e) in ((3,3),(7,7),(8,8)) and length(f) = 1; a b c d e f +3 2 uuuw 3 3 i +3 2 uuua 3 3 i 3 3 zzzz 3 3 i -3 3 zzzz 3 3 i -7 8 xxxxx 7 7 h -7 7 xxxyy 7 7 h 3 3 zyxw 3 3 i -3 3 zyxw 3 3 i -3 2 uuuw 3 3 i -3 2 uuuw 3 3 i 3 3 zzza 3 3 i -3 3 zzza 3 3 i -7 8 xxxxa 7 7 h -7 7 xxxya 7 7 h 3 3 zyxa 3 3 i -3 3 zyxa 3 3 i -3 2 uuua 3 3 i +7 7 xxxyy 7 7 h +7 7 xxxya 7 7 h +7 8 xxxxx 7 7 h +7 8 xxxxa 7 7 h +3 2 uuuw 3 3 i 3 2 uuua 3 3 i +3 3 zzzz 3 3 i +3 3 zyxw 3 3 i +3 3 zzza 3 3 i +3 3 zyxa 3 3 i prepare stmt from "select * from t1,t2 where a = d and (a,e) in ((3,3),(7,7),(8,8)) and length(f) = 1"; execute stmt; a b c d e f +3 2 uuuw 3 3 i +3 2 uuua 3 3 i 3 3 zzzz 3 3 i -3 3 zzzz 3 3 i -7 8 xxxxx 7 7 h -7 7 xxxyy 7 7 h -3 3 zyxw 3 3 i 3 3 zyxw 3 3 i -3 2 uuuw 3 3 i -3 2 uuuw 3 3 i -3 3 zzza 3 3 i 3 3 zzza 3 3 i -7 8 xxxxa 7 7 h -7 7 xxxya 7 7 h -3 3 zyxa 3 3 i 3 3 zyxa 3 3 i +7 7 xxxyy 7 7 h +7 7 xxxya 7 7 h +7 8 xxxxx 7 7 h +7 8 xxxxa 7 7 h +3 2 uuuw 3 3 i 3 2 uuua 3 3 i -3 2 uuua 3 3 i +3 3 zzzz 3 3 i +3 3 zyxw 3 3 i +3 3 zzza 3 3 i +3 3 zyxa 3 3 i execute stmt; a b c d e f +3 2 uuuw 3 3 i +3 2 uuua 3 3 i 3 3 zzzz 3 3 i -3 3 zzzz 3 3 i -7 8 xxxxx 7 7 h -7 7 xxxyy 7 7 h -3 3 zyxw 3 3 i 3 3 zyxw 3 3 i -3 2 uuuw 3 3 i -3 2 uuuw 3 3 i -3 3 zzza 3 3 i 3 3 zzza 3 3 i -7 8 xxxxa 7 7 h -7 7 xxxya 7 7 h -3 3 zyxa 3 3 i 3 3 zyxa 3 3 i +7 7 xxxyy 7 7 h +7 7 xxxya 7 7 h +7 8 xxxxx 7 7 h +7 8 xxxxa 7 7 h +3 2 uuuw 3 3 i 3 2 uuua 3 3 i -3 2 uuua 3 3 i +3 3 zzzz 3 3 i +3 3 zyxw 3 3 i +3 3 zzza 3 3 i +3 3 zyxa 3 3 i deallocate prepare stmt; insert into t1 select * from t1; # join order: (t2,t1) with ref access of t1 @@ -2649,7 +2653,7 @@ EXPLAIN "key_length": "5", "used_key_parts": ["e"], "rows": 6, - "filtered": 100, + "filtered": 6.7308, "attached_condition": "(t2.d,t2.e) in (<cache>((4,4)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1 and t2.d is not null", "mrr_type": "Rowid-ordered scan" }, @@ -3005,6 +3009,7 @@ insert into t1 select a+15, concat(b,'yy') from t1; insert into t1 select a+100, concat(b,'xx') from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select cast(count(a)/count(distinct a) as unsigned) as rec_per_key from t1; rec_per_key @@ -3023,7 +3028,7 @@ a b set eq_range_index_dive_limit=2; explain select * from t1 where a in (8, 15, 31, 1, 9); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range idx idx 5 NULL 10 Using index condition; Rowid-ordered scan +1 SIMPLE t1 range idx idx 5 NULL 5 Using index condition; Rowid-ordered scan select * from t1 where a in (8, 15, 31, 1, 9); a b 1 yy diff --git a/mysql-test/main/range_vs_index_merge.result b/mysql-test/main/range_vs_index_merge.result index bc46a4fdd0b..b10e499aad8 100644 --- a/mysql-test/main/range_vs_index_merge.result +++ b/mysql-test/main/range_vs_index_merge.result @@ -1430,6 +1430,7 @@ insert into t1(account_id, login, home_state, work_state) select 1, 'pw', 'ak', 'ak' from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select count(*) from t1 where account_id = 1; count(*) @@ -1491,6 +1492,7 @@ insert into t1 (c2, c3, c4, c5, cp) select c2, c3, c4, c5, cp from t1 where cp = 4; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select * from t1 where (c2=1 and c3=1) or (c4=2 and c5=1); @@ -1543,6 +1545,7 @@ insert into t1 (c2,c3,c4) select c2,c3,3 from t1 where c2 != 'a'; insert into t1 (c2,c3,c4) select c2,c3,4 from t1 where c2 != 'a'; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select count(*) from t1 where (c2='e' OR c3='q'); count(*) @@ -1582,6 +1585,7 @@ update t1 set c1=lpad(id+1000, 12, ' '), c2=lpad(id+10000, 15, ' '); alter table t1 add unique index (c1), add unique index (c2), add index (c3); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date explain select * from t1 where (c1=' 100000' or c2=' 2000000'); diff --git a/mysql-test/main/range_vs_index_merge_innodb.result b/mysql-test/main/range_vs_index_merge_innodb.result index ce90f522d6e..2ecd4d4abaa 100644 --- a/mysql-test/main/range_vs_index_merge_innodb.result +++ b/mysql-test/main/range_vs_index_merge_innodb.result @@ -1431,6 +1431,7 @@ insert into t1(account_id, login, home_state, work_state) select 1, 'pw', 'ak', 'ak' from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select count(*) from t1 where account_id = 1; count(*) @@ -1492,6 +1493,7 @@ insert into t1 (c2, c3, c4, c5, cp) select c2, c3, c4, c5, cp from t1 where cp = 4; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select * from t1 where (c2=1 and c3=1) or (c4=2 and c5=1); @@ -1544,6 +1546,7 @@ insert into t1 (c2,c3,c4) select c2,c3,3 from t1 where c2 != 'a'; insert into t1 (c2,c3,c4) select c2,c3,4 from t1 where c2 != 'a'; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select count(*) from t1 where (c2='e' OR c3='q'); count(*) @@ -1583,6 +1586,7 @@ update t1 set c1=lpad(id+1000, 12, ' '), c2=lpad(id+10000, 15, ' '); alter table t1 add unique index (c1), add unique index (c2), add index (c3); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select * from t1 where (c1=' 100000' or c2=' 2000000'); diff --git a/mysql-test/main/repair.result b/mysql-test/main/repair.result index 75d7525ee71..18a7cf509c4 100644 --- a/mysql-test/main/repair.result +++ b/mysql-test/main/repair.result @@ -78,7 +78,7 @@ INSERT INTO t1 VALUES ('0'),('0'),('0'),('0'),('0'),('0'),('0'); Warnings: Error 1034 myisam_sort_buffer_size is too small. X -Error 1034 Number of rows changed from 0 to 157 +Warning 1034 Number of rows changed from 0 to 157 SET myisam_repair_threads=2; REPAIR TABLE t1; Table Op Msg_type Msg_text diff --git a/mysql-test/main/row.result b/mysql-test/main/row.result index 7483f37970f..40d3e2640f0 100644 --- a/mysql-test/main/row.result +++ b/mysql-test/main/row.result @@ -15,28 +15,50 @@ select row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a')); row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a')) 1 Warnings: -Warning 1292 Truncated incorrect DECIMAL value: 'a' -Warning 1292 Truncated incorrect INTEGER value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' select row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3)); row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3)) 1 Warnings: -Warning 1292 Truncated incorrect INTEGER value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3)); row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3)) 1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3)); row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3)) 1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'a' select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3)); row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3)) -0 +1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'b' +Warning 1292 Truncated incorrect DOUBLE value: 'a' select row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3)); row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3)) -NULL +1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'b' +Warning 1292 Truncated incorrect DOUBLE value: 'b' +Warning 1292 Truncated incorrect DOUBLE value: 'a' select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3)); row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3)) -0 +1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: 'b' +Warning 1292 Truncated incorrect DOUBLE value: 'b' +Warning 1292 Truncated incorrect DOUBLE value: 'a' select (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4))); (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4))) 1 @@ -461,7 +483,7 @@ select * from t1,t2 where (a,b) = (c,d); a b c d abc 1 abc 1 select host,user from mysql.user where (host,user) = ('localhost','test'); -host user +Host User drop table t1,t2; # # Bug#52124 memory leaks like a sieve in datetime, timestamp, time, date fields + warnings diff --git a/mysql-test/main/secure_file_priv_win.result b/mysql-test/main/secure_file_priv_win.result index d456c24d20c..af402ae9537 100644 --- a/mysql-test/main/secure_file_priv_win.result +++ b/mysql-test/main/secure_file_priv_win.result @@ -1,6 +1,8 @@ CREATE TABLE t1 (c1 longtext); INSERT INTO t1 values ('a'); SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR/B11764517.tmp'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead show global variables like 'secure_file_priv'; Variable_name Value secure_file_priv MYSQL_TMP_DIR/ @@ -32,7 +34,15 @@ ERROR HY000: The MariaDB server is running with the --secure-file-priv option so SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR\\..a..\\..\\..\\B11764517-2.tmp'; ERROR HY000: The MariaDB server is running with the --secure-file-priv option so it cannot execute this statement SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR\\B11764517-2.tmp'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR/B11764517-3.tmp'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR_UCASE/B11764517-4.tmp'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR_LCASE/B11764517-5.tmp'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead DROP TABLE t1; diff --git a/mysql-test/main/select.result b/mysql-test/main/select.result index 9b6a570717b..9029828080a 100644 --- a/mysql-test/main/select.result +++ b/mysql-test/main/select.result @@ -2118,8 +2118,8 @@ INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12 SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid; gvid the_success the_fail the_size the_time Warnings: -Warning 1292 Incorrect datetime value: 'wrong-date-value' -Warning 1292 Incorrect datetime value: 'wrong-date-value' +Warning 1292 Truncated incorrect datetime value: 'wrong-date-value' +Warning 1292 Truncated incorrect datetime value: 'wrong-date-value' SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid; gvid the_success the_fail the_size the_time DROP TABLE t1,t2; @@ -3453,6 +3453,7 @@ create table t2 (a int, b int, c int, e int, primary key(a,b,c)); insert into t2 select A.a, B.a, C.a, C.a from t1 A, t1 B, t1 C; analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK select 'In next EXPLAIN, B.rows must be exactly 10:' Z; Z @@ -3746,12 +3747,14 @@ CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDAT INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00"); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CREATE TABLE t2 (a INT, dt1 DATETIME, dt2 DATETIME, PRIMARY KEY (a)); INSERT INTO t2 VALUES (30, "2006-01-01 00:00:00", "2999-12-31 00:00:00"); INSERT INTO t2 SELECT a+1,dt1,dt2 FROM t2; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=30 @@ -4111,7 +4114,7 @@ select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6'; str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' 0 Warnings: -Warning 1292 Incorrect datetime value: '2007/10/2000:00:00 GMT-6' +Warning 1292 Truncated incorrect datetime value: '2007/10/2000:00:00 GMT-6' select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6'; str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' 1 @@ -4198,7 +4201,7 @@ select str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20'; str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20'; str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20' 0 @@ -4212,22 +4215,22 @@ select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = ''; str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '' 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select str_to_date('1','%Y-%m-%d') = '1'; str_to_date('1','%Y-%m-%d') = '1' 0 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' select str_to_date('1','%Y-%m-%d') = '1'; str_to_date('1','%Y-%m-%d') = '1' 0 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' select str_to_date('','%Y-%m-%d') = ''; str_to_date('','%Y-%m-%d') = '' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01'; str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01' 1 @@ -5282,30 +5285,30 @@ SELECT * FROM t1 HAVING f1 = 'zz'; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'zz' SELECT * FROM t1 HAVING f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'aa' SELECT * FROM t1 HAVING f1 = 'zz' AND f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'aa' SELECT * FROM t1 WHERE f1 = 'zz' AND f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'aa' SELECT * FROM v1 HAVING f1 = 'zz' AND f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'aa' DROP TABLE t1; DROP VIEW v1; # diff --git a/mysql-test/main/select_jcl6.result b/mysql-test/main/select_jcl6.result index d78fad15da1..490fa05b039 100644 --- a/mysql-test/main/select_jcl6.result +++ b/mysql-test/main/select_jcl6.result @@ -2129,8 +2129,8 @@ INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12 SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid; gvid the_success the_fail the_size the_time Warnings: -Warning 1292 Incorrect datetime value: 'wrong-date-value' -Warning 1292 Incorrect datetime value: 'wrong-date-value' +Warning 1292 Truncated incorrect datetime value: 'wrong-date-value' +Warning 1292 Truncated incorrect datetime value: 'wrong-date-value' SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid; gvid the_success the_fail the_size the_time DROP TABLE t1,t2; @@ -3464,6 +3464,7 @@ create table t2 (a int, b int, c int, e int, primary key(a,b,c)); insert into t2 select A.a, B.a, C.a, C.a from t1 A, t1 B, t1 C; analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK select 'In next EXPLAIN, B.rows must be exactly 10:' Z; Z @@ -3757,12 +3758,14 @@ CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDAT INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00"); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CREATE TABLE t2 (a INT, dt1 DATETIME, dt2 DATETIME, PRIMARY KEY (a)); INSERT INTO t2 VALUES (30, "2006-01-01 00:00:00", "2999-12-31 00:00:00"); INSERT INTO t2 SELECT a+1,dt1,dt2 FROM t2; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=30 @@ -4122,7 +4125,7 @@ select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6'; str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' 0 Warnings: -Warning 1292 Incorrect datetime value: '2007/10/2000:00:00 GMT-6' +Warning 1292 Truncated incorrect datetime value: '2007/10/2000:00:00 GMT-6' select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6'; str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' 1 @@ -4209,7 +4212,7 @@ select str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20'; str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20'; str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20' 0 @@ -4223,22 +4226,22 @@ select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = ''; str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '' 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select str_to_date('1','%Y-%m-%d') = '1'; str_to_date('1','%Y-%m-%d') = '1' 0 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' select str_to_date('1','%Y-%m-%d') = '1'; str_to_date('1','%Y-%m-%d') = '1' 0 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' select str_to_date('','%Y-%m-%d') = ''; str_to_date('','%Y-%m-%d') = '' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01'; str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01' 1 @@ -5293,30 +5296,30 @@ SELECT * FROM t1 HAVING f1 = 'zz'; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'zz' SELECT * FROM t1 HAVING f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'aa' SELECT * FROM t1 HAVING f1 = 'zz' AND f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'aa' SELECT * FROM t1 WHERE f1 = 'zz' AND f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'aa' SELECT * FROM v1 HAVING f1 = 'zz' AND f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'aa' DROP TABLE t1; DROP VIEW v1; # diff --git a/mysql-test/main/select_pkeycache.result b/mysql-test/main/select_pkeycache.result index 9b6a570717b..9029828080a 100644 --- a/mysql-test/main/select_pkeycache.result +++ b/mysql-test/main/select_pkeycache.result @@ -2118,8 +2118,8 @@ INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12 SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid; gvid the_success the_fail the_size the_time Warnings: -Warning 1292 Incorrect datetime value: 'wrong-date-value' -Warning 1292 Incorrect datetime value: 'wrong-date-value' +Warning 1292 Truncated incorrect datetime value: 'wrong-date-value' +Warning 1292 Truncated incorrect datetime value: 'wrong-date-value' SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid; gvid the_success the_fail the_size the_time DROP TABLE t1,t2; @@ -3453,6 +3453,7 @@ create table t2 (a int, b int, c int, e int, primary key(a,b,c)); insert into t2 select A.a, B.a, C.a, C.a from t1 A, t1 B, t1 C; analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK select 'In next EXPLAIN, B.rows must be exactly 10:' Z; Z @@ -3746,12 +3747,14 @@ CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDAT INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00"); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CREATE TABLE t2 (a INT, dt1 DATETIME, dt2 DATETIME, PRIMARY KEY (a)); INSERT INTO t2 VALUES (30, "2006-01-01 00:00:00", "2999-12-31 00:00:00"); INSERT INTO t2 SELECT a+1,dt1,dt2 FROM t2; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=30 @@ -4111,7 +4114,7 @@ select str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6'; str_to_date('2007-10-09','%Y-%m-%d') <= '2007/10/2000:00:00 GMT-6' 0 Warnings: -Warning 1292 Incorrect datetime value: '2007/10/2000:00:00 GMT-6' +Warning 1292 Truncated incorrect datetime value: '2007/10/2000:00:00 GMT-6' select str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6'; str_to_date('2007-10-01','%Y-%m-%d') = '2007-10-1 00:00:00 GMT-6' 1 @@ -4198,7 +4201,7 @@ select str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20'; str_to_date('2007-10-00','%Y-%m-%d') between '' and '2007/10/20' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20'; str_to_date('','%Y-%m-%d') between '2007/10/01' and '2007/10/20' 0 @@ -4212,22 +4215,22 @@ select str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = ''; str_to_date('2007-10-00 12:34','%Y-%m-%d %H:%i') = '' 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select str_to_date('1','%Y-%m-%d') = '1'; str_to_date('1','%Y-%m-%d') = '1' 0 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' select str_to_date('1','%Y-%m-%d') = '1'; str_to_date('1','%Y-%m-%d') = '1' 0 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' select str_to_date('','%Y-%m-%d') = ''; str_to_date('','%Y-%m-%d') = '' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01'; str_to_date('2000-01-01','%Y-%m-%d') between '1000-01-01' and '2001-01-01' 1 @@ -5282,30 +5285,30 @@ SELECT * FROM t1 HAVING f1 = 'zz'; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'zz' SELECT * FROM t1 HAVING f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'aa' SELECT * FROM t1 HAVING f1 = 'zz' AND f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'aa' SELECT * FROM t1 WHERE f1 = 'zz' AND f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'aa' SELECT * FROM v1 HAVING f1 = 'zz' AND f1 <= 'aa' ; f1 0000-00-00 Warnings: -Warning 1292 Incorrect datetime value: 'zz' -Warning 1292 Incorrect datetime value: 'aa' +Warning 1292 Truncated incorrect datetime value: 'zz' +Warning 1292 Truncated incorrect datetime value: 'aa' DROP TABLE t1; DROP VIEW v1; # diff --git a/mysql-test/main/select_safe.result b/mysql-test/main/select_safe.result index 60364b8c4ec..649e2dc484e 100644 --- a/mysql-test/main/select_safe.result +++ b/mysql-test/main/select_safe.result @@ -62,19 +62,20 @@ a b 5 a analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"); insert into t1 values (null,"b"),(null,"b"),(null,"c"),(null,"c"),(null,"d"),(null,"d"),(null,"e"),(null,"e"),(null,"a"),(null,"e"); insert into t1 values (null,"x"),(null,"x"),(null,"y"),(null,"y"),(null,"z"),(null,"z"),(null,"v"),(null,"v"),(null,"a"),(null,"v"); explain select STRAIGHT_JOIN * from t1,t1 as t2 where t1.b=t2.b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL b NULL NULL NULL 41 Using where -1 SIMPLE t2 ref b b 21 test.t1.b 6 +1 SIMPLE t1 ALL b NULL NULL NULL 11 +1 SIMPLE t2 ALL b NULL NULL NULL 11 Using where; Using join buffer (flat, BNL join) set MAX_SEEKS_FOR_KEY=1; explain select STRAIGHT_JOIN * from t1,t1 as t2 where t1.b=t2.b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL b NULL NULL NULL 41 Using where -1 SIMPLE t2 ref b b 21 test.t1.b 6 +1 SIMPLE t1 ALL b NULL NULL NULL 11 +1 SIMPLE t2 ALL b NULL NULL NULL 11 Using where; Using join buffer (flat, BNL join) SET MAX_SEEKS_FOR_KEY=DEFAULT; drop table t1; create table t1 (a int); diff --git a/mysql-test/main/set_password.result b/mysql-test/main/set_password.result index 733d9c96187..bb1124e09d4 100644 --- a/mysql-test/main/set_password.result +++ b/mysql-test/main/set_password.result @@ -8,12 +8,12 @@ create user oldpass@localhost identified by password '378b243e220ca493'; create user oldpassold@localhost identified with 'mysql_old_password'; set password for oldpassold@localhost = '378b243e220ca493'; select user, host, password, plugin, authentication_string from mysql.user where user != 'root'; -user host password plugin authentication_string -natauth localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 -newpass localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 +User Host Password plugin authentication_string +natauth localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 mysql_native_password *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 +newpass localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 mysql_native_password *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 newpassnat localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 mysql_native_password *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 -oldauth localhost 378b243e220ca493 -oldpass localhost 378b243e220ca493 +oldauth localhost 378b243e220ca493 mysql_old_password 378b243e220ca493 +oldpass localhost 378b243e220ca493 mysql_old_password 378b243e220ca493 oldpassold localhost 378b243e220ca493 mysql_old_password 378b243e220ca493 connect con,localhost,natauth,test,; select current_user(); @@ -85,7 +85,7 @@ set password for oldauth@localhost = PASSWORD('test2'); set password for oldpass@localhost = PASSWORD('test2'); set password for oldpassold@localhost = PASSWORD('test2'); select user, host, password, plugin, authentication_string from mysql.user where user != 'root'; -user host password plugin authentication_string +User Host Password plugin authentication_string natauth localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E mysql_native_password *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E newpass localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E mysql_native_password *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E newpassnat localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E mysql_native_password *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E @@ -173,7 +173,7 @@ disconnect foo; connection default; select user,host,password,plugin,authentication_string from mysql.user where user='foo'; user host password plugin authentication_string -foo localhost *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB mysql_native_password *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB +foo localhost mysql_native_password *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB set password for 'foo'@'localhost' = ''; select user,host,password,plugin,authentication_string from mysql.user where user='foo'; user host password plugin authentication_string diff --git a/mysql-test/main/set_password.test b/mysql-test/main/set_password.test index fc1ecb5ef5c..c67dc22dc81 100644 --- a/mysql-test/main/set_password.test +++ b/mysql-test/main/set_password.test @@ -132,6 +132,7 @@ set global secure_auth=default; # # MDEV-16238 root/localhost authn prioritizes authentication_string over Password # +--source include/switch_to_mysql_user.inc create user foo@localhost identified with mysql_native_password; update mysql.user set authentication_string=password('foo'), plugin='mysql_native_password' where user='foo' and host='localhost'; set password for 'foo'@'localhost' = password('bar'); @@ -145,3 +146,4 @@ select user,host,password,plugin,authentication_string from mysql.user where use set password for 'foo'@'localhost' = ''; select user,host,password,plugin,authentication_string from mysql.user where user='foo'; drop user foo@localhost; +--source include/switch_to_mysql_global_priv.inc diff --git a/mysql-test/main/set_statement.result b/mysql-test/main/set_statement.result index c34e1171899..a12954927b6 100644 --- a/mysql-test/main/set_statement.result +++ b/mysql-test/main/set_statement.result @@ -1225,3 +1225,10 @@ set @rnd=1; select @rnd; @rnd 0 +create table t (a int); +SET sql_mode=ORACLE; +SET STATEMENT myisam_sort_buffer_size=800000 FOR OPTIMIZE TABLE t; +Table Op Msg_type Msg_text +test.t optimize status Table is already up to date +SET sql_mode=default; +drop table t; diff --git a/mysql-test/main/set_statement.test b/mysql-test/main/set_statement.test index cc361553cfd..e2a3288106b 100644 --- a/mysql-test/main/set_statement.test +++ b/mysql-test/main/set_statement.test @@ -1130,3 +1130,10 @@ while ($1) --enable_query_log --echo # @rnd should be 0 select @rnd; + +create table t (a int); +SET sql_mode=ORACLE; +SET STATEMENT myisam_sort_buffer_size=800000 FOR OPTIMIZE TABLE t; +SET sql_mode=default; +drop table t; + diff --git a/mysql-test/main/shm-master.opt b/mysql-test/main/shm-master.opt deleted file mode 100644 index d71395213b1..00000000000 --- a/mysql-test/main/shm-master.opt +++ /dev/null @@ -1 +0,0 @@ ---skip-grant-tables --loose-shared-memory-base-name=HeyMrBaseNameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$MTR_BUILD_THREAD --loose-shared-memory=1 diff --git a/mysql-test/main/shm.result b/mysql-test/main/shm.result deleted file mode 100644 index 65187b6b19b..00000000000 --- a/mysql-test/main/shm.result +++ /dev/null @@ -1,2170 +0,0 @@ -connect shm_con,localhost,root,,,,$shm_name,SHM; -drop table if exists t1,t2,t3,t4; -CREATE TABLE t1 ( -Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL, -Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL -); -INSERT INTO t1 VALUES (9410,9412); -select period from t1; -period -9410 -select * from t1; -Period Varor_period -9410 9412 -select t1.* from t1; -Period Varor_period -9410 9412 -CREATE TABLE t2 ( -auto int not null auto_increment, -fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL, -companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL, -fld3 char(30) DEFAULT '' NOT NULL, -fld4 char(35) DEFAULT '' NOT NULL, -fld5 char(35) DEFAULT '' NOT NULL, -fld6 char(4) DEFAULT '' NOT NULL, -UNIQUE fld1 (fld1), -KEY fld3 (fld3), -PRIMARY KEY (auto) -); -select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%"; -fld3 -imaginable -select fld3 from t2 where fld3 like "%cultivation" ; -fld3 -cultivation -select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3; -fld3 companynr -concoct 58 -druggists 58 -engrossing 58 -Eurydice 58 -exclaimers 58 -ferociousness 58 -hopelessness 58 -Huey 58 -imaginable 58 -judges 58 -merging 58 -ostrich 58 -peering 58 -Phelps 58 -presumes 58 -Ruth 58 -sentences 58 -Shylock 58 -straggled 58 -synergy 58 -thanking 58 -tying 58 -unlocks 58 -select fld3,companynr from t2 where companynr = 58 order by fld3; -fld3 companynr -concoct 58 -druggists 58 -engrossing 58 -Eurydice 58 -exclaimers 58 -ferociousness 58 -hopelessness 58 -Huey 58 -imaginable 58 -judges 58 -merging 58 -ostrich 58 -peering 58 -Phelps 58 -presumes 58 -Ruth 58 -sentences 58 -Shylock 58 -straggled 58 -synergy 58 -thanking 58 -tying 58 -unlocks 58 -select fld3 from t2 order by fld3 desc limit 10; -fld3 -youthfulness -yelped -Wotan -workers -Witt -witchcraft -Winsett -Willy -willed -wildcats -select fld3 from t2 order by fld3 desc limit 5; -fld3 -youthfulness -yelped -Wotan -workers -Witt -select fld3 from t2 order by fld3 desc limit 5,5; -fld3 -witchcraft -Winsett -Willy -willed -wildcats -select t2.fld3 from t2 where fld3 = 'honeysuckle'; -fld3 -honeysuckle -select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_'; -fld3 -honeysuckle -select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_'; -fld3 -honeysuckle -select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%'; -fld3 -honeysuckle -select t2.fld3 from t2 where fld3 LIKE 'h%le'; -fld3 -honeysuckle -select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_'; -fld3 -select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%'; -fld3 -explain select t2.fld3 from t2 where fld3 = 'honeysuckle'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index -explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index -explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index -explain select fld3 from t2 ignore index (fld3,not_used); -ERROR 42000: Key 'not_used' doesn't exist in table 't2' -explain select fld3 from t2 use index (not_used); -ERROR 42000: Key 'not_used' doesn't exist in table 't2' -select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; -fld3 -honeysuckle -honoring -explain select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range fld3 fld3 30 NULL 2 Using where; Using index -select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3; -fld1 fld3 -148504 Colombo -068305 Colombo -000000 nondecreasing -select fld1,fld3 from t2 where companynr = 37 and fld3 = 'appendixes'; -fld1 fld3 -232605 appendixes -1232605 appendixes -1232606 appendixes -1232607 appendixes -1232608 appendixes -1232609 appendixes -select fld1 from t2 where fld1=250501 or fld1="250502"; -fld1 -250501 -250502 -explain select fld1 from t2 where fld1=250501 or fld1="250502"; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range fld1 fld1 4 NULL 2 Using where; Using index -select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502; -fld1 -250501 -250502 -250505 -250601 -explain select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range fld1 fld1 4 NULL 4 Using where; Using index -select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%'; -fld1 fld3 -012001 flanking -013602 foldout -013606 fingerings -018007 fanatic -018017 featherweight -018054 fetters -018103 flint -018104 flopping -036002 funereal -038017 fetched -038205 firearm -058004 Fenton -088303 feminine -186002 freakish -188007 flurried -188505 fitting -198006 furthermore -202301 Fitzpatrick -208101 fiftieth -208113 freest -218008 finishers -218022 feed -218401 faithful -226205 foothill -226209 furnishings -228306 forthcoming -228311 fated -231315 freezes -232102 forgivably -238007 filial -238008 fixedly -select fld3 from t2 where fld3 like "L%" and fld3 = "ok"; -fld3 -select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly"); -fld3 -Chantilly -select fld1,fld3 from t2 where fld1 like "25050%"; -fld1 fld3 -250501 poisoning -250502 Iraqis -250503 heaving -250504 population -250505 bomb -select fld1,fld3 from t2 where fld1 like "25050_"; -fld1 fld3 -250501 poisoning -250502 Iraqis -250503 heaving -250504 population -250505 bomb -select distinct companynr from t2; -companynr -00 -37 -36 -50 -58 -29 -40 -53 -65 -41 -34 -68 -select distinct companynr from t2 order by companynr; -companynr -00 -29 -34 -36 -37 -40 -41 -50 -53 -58 -65 -68 -select distinct companynr from t2 order by companynr desc; -companynr -68 -65 -58 -53 -50 -41 -40 -37 -36 -34 -29 -00 -select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%"; -fld3 period -obliterates 9410 -offload 9410 -opaquely 9410 -organizer 9410 -overestimating 9410 -overlay 9410 -select distinct fld3 from t2 where companynr = 34 order by fld3; -fld3 -absentee -accessed -ahead -alphabetic -Asiaticizations -attitude -aye -bankruptcies -belays -Blythe -bomb -boulevard -bulldozes -cannot -caressing -charcoal -checksumming -chess -clubroom -colorful -cosy -creator -crying -Darius -diffusing -duality -Eiffel -Epiphany -Ernestine -explorers -exterminated -famine -forked -Gershwins -heaving -Hodges -Iraqis -Italianization -Lagos -landslide -libretto -Majorca -mastering -narrowed -occurred -offerers -Palestine -Peruvianizes -pharmaceutic -poisoning -population -Pygmalion -rats -realest -recording -regimented -retransmitting -reviver -rouses -scars -sicker -sleepwalk -stopped -sugars -translatable -uncles -unexpected -uprisings -versatility -vest -select distinct fld3 from t2 limit 10; -fld3 -abates -abiding -Abraham -abrogating -absentee -abut -accessed -accruing -accumulating -accuracies -select distinct fld3 from t2 having fld3 like "A%" limit 10; -fld3 -abates -abiding -Abraham -abrogating -absentee -abut -accessed -accruing -accumulating -accuracies -select distinct substring(fld3,1,3) from t2 where fld3 like "A%"; -substring(fld3,1,3) -aba -abi -Abr -abs -abu -acc -acq -acu -Ade -adj -Adl -adm -Ado -ads -adv -aer -aff -afi -afl -afo -agi -ahe -aim -air -Ald -alg -ali -all -alp -alr -ama -ame -amm -ana -and -ane -Ang -ani -Ann -Ant -api -app -aqu -Ara -arc -Arm -arr -Art -Asi -ask -asp -ass -ast -att -aud -Aug -aut -ave -avo -awe -aye -Azt -select distinct substring(fld3,1,3) as a from t2 having a like "A%" order by a limit 10; -a -aba -abi -Abr -abs -abu -acc -acq -acu -Ade -adj -select distinct substring(fld3,1,3) from t2 where fld3 like "A%" limit 10; -substring(fld3,1,3) -aba -abi -Abr -abs -abu -acc -acq -acu -Ade -adj -select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10; -a -aba -abi -Abr -abs -abu -acc -acq -acu -Ade -adj -create table t3 ( -period int not null, -name char(32) not null, -companynr int not null, -price double(11,0), -price2 double(11,0), -key (period), -key (name) -); -create temporary table tmp engine = myisam select * from t3; -insert into t3 select * from tmp; -insert into tmp select * from t3; -insert into t3 select * from tmp; -insert into tmp select * from t3; -insert into t3 select * from tmp; -insert into tmp select * from t3; -insert into t3 select * from tmp; -insert into tmp select * from t3; -insert into t3 select * from tmp; -insert into tmp select * from t3; -insert into t3 select * from tmp; -insert into tmp select * from t3; -insert into t3 select * from tmp; -insert into tmp select * from t3; -insert into t3 select * from tmp; -insert into tmp select * from t3; -insert into t3 select * from tmp; -alter table t3 add t2nr int not null auto_increment primary key first; -drop table tmp; -SET BIG_TABLES=1; -select distinct concat(fld3," ",fld3) as namn from t2,t3 where t2.fld1=t3.t2nr order by namn limit 10; -namn -Abraham Abraham -abrogating abrogating -admonishing admonishing -Adolph Adolph -afield afield -aging aging -ammonium ammonium -analyzable analyzable -animals animals -animized animized -SET BIG_TABLES=0; -select distinct concat(fld3," ",fld3) from t2,t3 where t2.fld1=t3.t2nr order by fld3 limit 10; -concat(fld3," ",fld3) -Abraham Abraham -abrogating abrogating -admonishing admonishing -Adolph Adolph -afield afield -aging aging -ammonium ammonium -analyzable analyzable -animals animals -animized animized -select distinct fld5 from t2 limit 10; -fld5 -neat -Steinberg -jarring -tinily -balled -persist -attainments -fanatic -measures -rightfulness -select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10; -fld3 count(*) -affixed 1 -and 1 -annoyers 1 -Anthony 1 -assayed 1 -assurers 1 -attendants 1 -bedlam 1 -bedpost 1 -boasted 1 -SET BIG_TABLES=1; -select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10; -fld3 count(*) -affixed 1 -and 1 -annoyers 1 -Anthony 1 -assayed 1 -assurers 1 -attendants 1 -bedlam 1 -bedpost 1 -boasted 1 -SET BIG_TABLES=0; -select distinct fld3,repeat("a",length(fld3)),count(*) from t2 group by companynr,fld3 limit 100,10; -fld3 repeat("a",length(fld3)) count(*) -circus aaaaaa 1 -cited aaaaa 1 -Colombo aaaaaaa 1 -congresswoman aaaaaaaaaaaaa 1 -contrition aaaaaaaaaa 1 -corny aaaaa 1 -cultivation aaaaaaaaaaa 1 -definiteness aaaaaaaaaaaa 1 -demultiplex aaaaaaaaaaa 1 -disappointing aaaaaaaaaaaaa 1 -select distinct companynr,rtrim(space(512+companynr)) from t3 order by 1,2; -companynr rtrim(space(512+companynr)) -37 -78 -101 -154 -311 -447 -512 -select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by fld3; -fld3 -explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort -1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using filesort -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 index period period 4 NULL 1 -1 SIMPLE t1 ref period period 4 test.t3.period 4181 -explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index period period 4 NULL 1 -1 SIMPLE t3 ref period period 4 test.t1.period 4181 -select period from t1; -period -9410 -select period from t1 where period=1900; -period -select fld3,period from t1,t2 where fld1 = 011401 order by period; -fld3 period -breaking 9410 -select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001; -fld3 period -breaking 1001 -explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 const fld1 fld1 4 const 1 -1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1 -select fld3,period from t2,t1 where companynr*10 = 37*10; -fld3 period -breaking 9410 -Romans 9410 -intercepted 9410 -bewilderingly 9410 -astound 9410 -admonishing 9410 -sumac 9410 -flanking 9410 -combed 9410 -subjective 9410 -scatterbrain 9410 -Eulerian 9410 -Kane 9410 -overlay 9410 -perturb 9410 -goblins 9410 -annihilates 9410 -Wotan 9410 -snatching 9410 -concludes 9410 -laterally 9410 -yelped 9410 -grazing 9410 -Baird 9410 -celery 9410 -misunderstander 9410 -handgun 9410 -foldout 9410 -mystic 9410 -succumbed 9410 -Nabisco 9410 -fingerings 9410 -aging 9410 -afield 9410 -ammonium 9410 -boat 9410 -intelligibility 9410 -Augustine 9410 -teethe 9410 -dreaded 9410 -scholastics 9410 -audiology 9410 -wallet 9410 -parters 9410 -eschew 9410 -quitter 9410 -neat 9410 -Steinberg 9410 -jarring 9410 -tinily 9410 -balled 9410 -persist 9410 -attainments 9410 -fanatic 9410 -measures 9410 -rightfulness 9410 -capably 9410 -impulsive 9410 -starlet 9410 -terminators 9410 -untying 9410 -announces 9410 -featherweight 9410 -pessimist 9410 -daughter 9410 -decliner 9410 -lawgiver 9410 -stated 9410 -readable 9410 -attrition 9410 -cascade 9410 -motors 9410 -interrogate 9410 -pests 9410 -stairway 9410 -dopers 9410 -testicle 9410 -Parsifal 9410 -leavings 9410 -postulation 9410 -squeaking 9410 -contrasted 9410 -leftover 9410 -whiteners 9410 -erases 9410 -Punjab 9410 -Merritt 9410 -Quixotism 9410 -sweetish 9410 -dogging 9410 -scornfully 9410 -bellow 9410 -bills 9410 -cupboard 9410 -sureties 9410 -puddings 9410 -fetters 9410 -bivalves 9410 -incurring 9410 -Adolph 9410 -pithed 9410 -Miles 9410 -trimmings 9410 -tragedies 9410 -skulking 9410 -flint 9410 -flopping 9410 -relaxing 9410 -offload 9410 -suites 9410 -lists 9410 -animized 9410 -multilayer 9410 -standardizes 9410 -Judas 9410 -vacuuming 9410 -dentally 9410 -humanness 9410 -inch 9410 -Weissmuller 9410 -irresponsibly 9410 -luckily 9410 -culled 9410 -medical 9410 -bloodbath 9410 -subschema 9410 -animals 9410 -Micronesia 9410 -repetitions 9410 -Antares 9410 -ventilate 9410 -pityingly 9410 -interdependent 9410 -Graves 9410 -neonatal 9410 -chafe 9410 -honoring 9410 -realtor 9410 -elite 9410 -funereal 9410 -abrogating 9410 -sorters 9410 -Conley 9410 -lectured 9410 -Abraham 9410 -Hawaii 9410 -cage 9410 -hushes 9410 -Simla 9410 -reporters 9410 -Dutchman 9410 -descendants 9410 -groupings 9410 -dissociate 9410 -coexist 9410 -Beebe 9410 -Taoism 9410 -Connally 9410 -fetched 9410 -checkpoints 9410 -rusting 9410 -galling 9410 -obliterates 9410 -traitor 9410 -resumes 9410 -analyzable 9410 -terminator 9410 -gritty 9410 -firearm 9410 -minima 9410 -Selfridge 9410 -disable 9410 -witchcraft 9410 -betroth 9410 -Manhattanize 9410 -imprint 9410 -peeked 9410 -swelling 9410 -interrelationships 9410 -riser 9410 -Gandhian 9410 -peacock 9410 -bee 9410 -kanji 9410 -dental 9410 -scarf 9410 -chasm 9410 -insolence 9410 -syndicate 9410 -alike 9410 -imperial 9410 -convulsion 9410 -railway 9410 -validate 9410 -normalizes 9410 -comprehensive 9410 -chewing 9410 -denizen 9410 -schemer 9410 -chronicle 9410 -Kline 9410 -Anatole 9410 -partridges 9410 -brunch 9410 -recruited 9410 -dimensions 9410 -Chicana 9410 -announced 9410 -praised 9410 -employing 9410 -linear 9410 -quagmire 9410 -western 9410 -relishing 9410 -serving 9410 -scheduling 9410 -lore 9410 -eventful 9410 -arteriole 9410 -disentangle 9410 -cured 9410 -Fenton 9410 -avoidable 9410 -drains 9410 -detectably 9410 -husky 9410 -impelling 9410 -undoes 9410 -evened 9410 -squeezes 9410 -destroyer 9410 -rudeness 9410 -beaner 9410 -boorish 9410 -Everhart 9410 -encompass 9410 -mushrooms 9410 -Alison 9410 -externally 9410 -pellagra 9410 -cult 9410 -creek 9410 -Huffman 9410 -Majorca 9410 -governing 9410 -gadfly 9410 -reassigned 9410 -intentness 9410 -craziness 9410 -psychic 9410 -squabbled 9410 -burlesque 9410 -capped 9410 -extracted 9410 -DiMaggio 9410 -exclamation 9410 -subdirectory 9410 -Gothicism 9410 -feminine 9410 -metaphysically 9410 -sanding 9410 -Miltonism 9410 -freakish 9410 -index 9410 -straight 9410 -flurried 9410 -denotative 9410 -coming 9410 -commencements 9410 -gentleman 9410 -gifted 9410 -Shanghais 9410 -sportswriting 9410 -sloping 9410 -navies 9410 -leaflet 9410 -shooter 9410 -Joplin 9410 -babies 9410 -assails 9410 -admiring 9410 -swaying 9410 -Goldstine 9410 -fitting 9410 -Norwalk 9410 -analogy 9410 -deludes 9410 -cokes 9410 -Clayton 9410 -exhausts 9410 -causality 9410 -sating 9410 -icon 9410 -throttles 9410 -communicants 9410 -dehydrate 9410 -priceless 9410 -publicly 9410 -incidentals 9410 -commonplace 9410 -mumbles 9410 -furthermore 9410 -cautioned 9410 -parametrized 9410 -registration 9410 -sadly 9410 -positioning 9410 -babysitting 9410 -eternal 9410 -hoarder 9410 -congregates 9410 -rains 9410 -workers 9410 -sags 9410 -unplug 9410 -garage 9410 -boulder 9410 -specifics 9410 -Teresa 9410 -Winsett 9410 -convenient 9410 -buckboards 9410 -amenities 9410 -resplendent 9410 -sews 9410 -participated 9410 -Simon 9410 -certificates 9410 -Fitzpatrick 9410 -Evanston 9410 -misted 9410 -textures 9410 -save 9410 -count 9410 -rightful 9410 -chaperone 9410 -Lizzy 9410 -clenched 9410 -effortlessly 9410 -accessed 9410 -beaters 9410 -Hornblower 9410 -vests 9410 -indulgences 9410 -infallibly 9410 -unwilling 9410 -excrete 9410 -spools 9410 -crunches 9410 -overestimating 9410 -ineffective 9410 -humiliation 9410 -sophomore 9410 -star 9410 -rifles 9410 -dialysis 9410 -arriving 9410 -indulge 9410 -clockers 9410 -languages 9410 -Antarctica 9410 -percentage 9410 -ceiling 9410 -specification 9410 -regimented 9410 -ciphers 9410 -pictures 9410 -serpents 9410 -allot 9410 -realized 9410 -mayoral 9410 -opaquely 9410 -hostess 9410 -fiftieth 9410 -incorrectly 9410 -decomposition 9410 -stranglings 9410 -mixture 9410 -electroencephalography 9410 -similarities 9410 -charges 9410 -freest 9410 -Greenberg 9410 -tinting 9410 -expelled 9410 -warm 9410 -smoothed 9410 -deductions 9410 -Romano 9410 -bitterroot 9410 -corset 9410 -securing 9410 -environing 9410 -cute 9410 -Crays 9410 -heiress 9410 -inform 9410 -avenge 9410 -universals 9410 -Kinsey 9410 -ravines 9410 -bestseller 9410 -equilibrium 9410 -extents 9410 -relatively 9410 -pressure 9410 -critiques 9410 -befouled 9410 -rightfully 9410 -mechanizing 9410 -Latinizes 9410 -timesharing 9410 -Aden 9410 -embassies 9410 -males 9410 -shapelessly 9410 -mastering 9410 -Newtonian 9410 -finishers 9410 -abates 9410 -teem 9410 -kiting 9410 -stodgy 9410 -feed 9410 -guitars 9410 -airships 9410 -store 9410 -denounces 9410 -Pyle 9410 -Saxony 9410 -serializations 9410 -Peruvian 9410 -taxonomically 9410 -kingdom 9410 -stint 9410 -Sault 9410 -faithful 9410 -Ganymede 9410 -tidiness 9410 -gainful 9410 -contrary 9410 -Tipperary 9410 -tropics 9410 -theorizers 9410 -renew 9410 -already 9410 -terminal 9410 -Hegelian 9410 -hypothesizer 9410 -warningly 9410 -journalizing 9410 -nested 9410 -Lars 9410 -saplings 9410 -foothill 9410 -labeled 9410 -imperiously 9410 -reporters 9410 -furnishings 9410 -precipitable 9410 -discounts 9410 -excises 9410 -Stalin 9410 -despot 9410 -ripeness 9410 -Arabia 9410 -unruly 9410 -mournfulness 9410 -boom 9410 -slaughter 9410 -Sabine 9410 -handy 9410 -rural 9410 -organizer 9410 -shipyard 9410 -civics 9410 -inaccuracy 9410 -rules 9410 -juveniles 9410 -comprised 9410 -investigations 9410 -stabilizes 9410 -seminaries 9410 -Hunter 9410 -sporty 9410 -test 9410 -weasels 9410 -CERN 9410 -tempering 9410 -afore 9410 -Galatean 9410 -techniques 9410 -error 9410 -veranda 9410 -severely 9410 -Cassites 9410 -forthcoming 9410 -guides 9410 -vanish 9410 -lied 9410 -sawtooth 9410 -fated 9410 -gradually 9410 -widens 9410 -preclude 9410 -evenhandedly 9410 -percentage 9410 -disobedience 9410 -humility 9410 -gleaning 9410 -petted 9410 -bloater 9410 -minion 9410 -marginal 9410 -apiary 9410 -measures 9410 -precaution 9410 -repelled 9410 -primary 9410 -coverings 9410 -Artemia 9410 -navigate 9410 -spatial 9410 -Gurkha 9410 -meanwhile 9410 -Melinda 9410 -Butterfield 9410 -Aldrich 9410 -previewing 9410 -glut 9410 -unaffected 9410 -inmate 9410 -mineral 9410 -impending 9410 -meditation 9410 -ideas 9410 -miniaturizes 9410 -lewdly 9410 -title 9410 -youthfulness 9410 -creak 9410 -Chippewa 9410 -clamored 9410 -freezes 9410 -forgivably 9410 -reduce 9410 -McGovern 9410 -Nazis 9410 -epistle 9410 -socializes 9410 -conceptions 9410 -Kevin 9410 -uncovering 9410 -chews 9410 -appendixes 9410 -appendixes 9410 -appendixes 9410 -appendixes 9410 -appendixes 9410 -appendixes 9410 -raining 9410 -infest 9410 -compartment 9410 -minting 9410 -ducks 9410 -roped 9410 -waltz 9410 -Lillian 9410 -repressions 9410 -chillingly 9410 -noncritical 9410 -lithograph 9410 -spongers 9410 -parenthood 9410 -posed 9410 -instruments 9410 -filial 9410 -fixedly 9410 -relives 9410 -Pandora 9410 -watering 9410 -ungrateful 9410 -secures 9410 -poison 9410 -dusted 9410 -encompasses 9410 -presentation 9410 -Kantian 9410 -select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price; -fld3 period price price2 -admonishing 1002 28357832 8723648 -analyzable 1002 28357832 8723648 -annihilates 1001 5987435 234724 -Antares 1002 28357832 8723648 -astound 1001 5987435 234724 -audiology 1001 5987435 234724 -Augustine 1002 28357832 8723648 -Baird 1002 28357832 8723648 -bewilderingly 1001 5987435 234724 -breaking 1001 5987435 234724 -Conley 1001 5987435 234724 -dentally 1002 28357832 8723648 -dissociate 1002 28357832 8723648 -elite 1001 5987435 234724 -eschew 1001 5987435 234724 -Eulerian 1001 5987435 234724 -flanking 1001 5987435 234724 -foldout 1002 28357832 8723648 -funereal 1002 28357832 8723648 -galling 1002 28357832 8723648 -Graves 1001 5987435 234724 -grazing 1001 5987435 234724 -groupings 1001 5987435 234724 -handgun 1001 5987435 234724 -humility 1002 28357832 8723648 -impulsive 1002 28357832 8723648 -inch 1001 5987435 234724 -intelligibility 1001 5987435 234724 -jarring 1001 5987435 234724 -lawgiver 1001 5987435 234724 -lectured 1002 28357832 8723648 -Merritt 1002 28357832 8723648 -neonatal 1001 5987435 234724 -offload 1002 28357832 8723648 -parters 1002 28357832 8723648 -pityingly 1002 28357832 8723648 -puddings 1002 28357832 8723648 -Punjab 1001 5987435 234724 -quitter 1002 28357832 8723648 -realtor 1001 5987435 234724 -relaxing 1001 5987435 234724 -repetitions 1001 5987435 234724 -resumes 1001 5987435 234724 -Romans 1002 28357832 8723648 -rusting 1001 5987435 234724 -scholastics 1001 5987435 234724 -skulking 1002 28357832 8723648 -stated 1002 28357832 8723648 -suites 1002 28357832 8723648 -sureties 1001 5987435 234724 -testicle 1002 28357832 8723648 -tinily 1002 28357832 8723648 -tragedies 1001 5987435 234724 -trimmings 1001 5987435 234724 -vacuuming 1001 5987435 234724 -ventilate 1001 5987435 234724 -wallet 1001 5987435 234724 -Weissmuller 1002 28357832 8723648 -Wotan 1002 28357832 8723648 -select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37; -fld1 fld3 period price price2 -018201 relaxing 1001 5987435 234724 -018601 vacuuming 1001 5987435 234724 -018801 inch 1001 5987435 234724 -018811 repetitions 1001 5987435 234724 -create table t4 ( -companynr tinyint(2) unsigned zerofill NOT NULL default '00', -companyname char(30) NOT NULL default '', -PRIMARY KEY (companynr), -UNIQUE KEY companyname(companyname) -) ENGINE=MyISAM MAX_ROWS=50 PACK_KEYS=1 COMMENT='companynames'; -select STRAIGHT_JOIN t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr; -companynr companyname -00 Unknown -29 company 1 -34 company 2 -36 company 3 -37 company 4 -40 company 5 -41 company 6 -50 company 11 -53 company 7 -58 company 8 -65 company 9 -68 company 10 -select SQL_SMALL_RESULT t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr; -companynr companyname -00 Unknown -29 company 1 -34 company 2 -36 company 3 -37 company 4 -40 company 5 -41 company 6 -50 company 11 -53 company 7 -58 company 8 -65 company 9 -68 company 10 -select * from t1,t1 t12; -Period Varor_period Period Varor_period -9410 9412 9410 9412 -select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505; -fld1 fld1 -250501 250501 -250502 250501 -250503 250501 -250504 250501 -250505 250501 -250501 250502 -250502 250502 -250503 250502 -250504 250502 -250505 250502 -250501 250503 -250502 250503 -250503 250503 -250504 250503 -250505 250503 -250501 250504 -250502 250504 -250503 250504 -250504 250504 -250505 250504 -250501 250505 -250502 250505 -250503 250505 -250504 250505 -250505 250505 -SET @save_optimizer_switch=@@optimizer_switch; -SET optimizer_switch='outer_join_with_cache=off'; -insert into t2 (fld1, companynr) values (999999,99); -select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; -companynr companyname -99 NULL -select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null; -count(*) -1199 -explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 -1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where; Not exists -explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 ALL NULL NULL NULL NULL 12 -1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Not exists -select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; -companynr companyname -select count(*) from t2 left join t4 using (companynr) where companynr is not null; -count(*) -1200 -explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE -explain select companynr,companyname from t4 left join t2 using (companynr) where companynr is null; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE -delete from t2 where fld1=999999; -explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 -explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 -explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 -explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 ALL NULL NULL NULL NULL 12 -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 ALL NULL NULL NULL NULL 12 -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where -SET optimizer_switch=@save_optimizer_switch; -select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; -companynr companynr -37 36 -41 40 -explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Using join buffer (flat, BNL join) -select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; -fld1 companynr fld3 period -038008 37 reporters 1008 -038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period -038008 37 reporters 1008 -038208 37 Selfridge 1008 -select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009; -fld1 companynr fld3 period -038008 37 reporters 1008 -038208 37 Selfridge 1008 -select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909); -period -9410 -select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6))); -period -9410 -select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1; -fld1 -250501 -250502 -250503 -250505 -select fld1 from t2 where fld1 in (250502,98005,98006,250503,250605,250606) and fld1 >=250502 and fld1 not in (250605,250606); -fld1 -250502 -250503 -select fld1 from t2 where fld1 between 250502 and 250504; -fld1 -250502 -250503 -250504 -select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld3 like "L%" or fld3 like "G%")) and fld3 like "L%" ; -fld3 -label -labeled -labeled -landslide -laterally -leaflet -lewdly -Lillian -luckily -select count(*) from t1; -count(*) -1 -select companynr,count(*),sum(fld1) from t2 group by companynr; -companynr count(*) sum(fld1) -00 82 10355753 -29 95 14473298 -34 70 17788966 -36 215 22786296 -37 588 83602098 -40 37 6618386 -41 52 12816335 -50 11 1595438 -53 4 793210 -58 23 2254293 -65 10 2284055 -68 12 3097288 -select companynr,count(*) from t2 group by companynr order by companynr desc limit 5; -companynr count(*) -68 12 -65 10 -58 23 -53 4 -50 11 -select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; -count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1) -70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069 -explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>""; -id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 100.00 Using where -Warnings: -Note 1003 select count(0) AS `count(*)`,min(`test`.`t2`.`fld4`) AS `min(fld4)`,max(`test`.`t2`.`fld4`) AS `max(fld4)`,sum(`test`.`t2`.`fld1`) AS `sum(fld1)`,avg(`test`.`t2`.`fld1`) AS `avg(fld1)`,std(`test`.`t2`.`fld1`) AS `std(fld1)`,variance(`test`.`t2`.`fld1`) AS `variance(fld1)` from `test`.`t2` where `test`.`t2`.`companynr` = 34 and `test`.`t2`.`fld4` <> '' -select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3; -companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1) -00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087 -29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026 -34 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069 -select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; -companynr t2nr count(price) sum(price) min(price) max(price) avg(price) -37 1 1 5987435 5987435 5987435 5987435.0000 -37 2 1 28357832 28357832 28357832 28357832.0000 -37 3 1 39654943 39654943 39654943 39654943.0000 -37 11 1 5987435 5987435 5987435 5987435.0000 -37 12 1 28357832 28357832 28357832 28357832.0000 -37 13 1 39654943 39654943 39654943 39654943.0000 -37 21 1 5987435 5987435 5987435 5987435.0000 -37 22 1 28357832 28357832 28357832 28357832.0000 -37 23 1 39654943 39654943 39654943 39654943.0000 -37 31 1 5987435 5987435 5987435 5987435.0000 -select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10; -companynr t2nr count(price) sum(price) min(price) max(price) avg(price) -37 1 1 5987435 5987435 5987435 5987435.0000 -37 2 1 28357832 28357832 28357832 28357832.0000 -37 3 1 39654943 39654943 39654943 39654943.0000 -37 11 1 5987435 5987435 5987435 5987435.0000 -37 12 1 28357832 28357832 28357832 28357832.0000 -37 13 1 39654943 39654943 39654943 39654943.0000 -37 21 1 5987435 5987435 5987435 5987435.0000 -37 22 1 28357832 28357832 28357832 28357832.0000 -37 23 1 39654943 39654943 39654943 39654943.0000 -37 31 1 5987435 5987435 5987435 5987435.0000 -select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ; -companynr count(price) sum(price) min(price) max(price) avg(price) -37 12543 309394878010 5987435 39654943 24666736.6667 -78 8362 414611089292 726498 98439034 49582766.0000 -101 4181 3489454238 834598 834598 834598.0000 -154 4181 4112197254950 983543950 983543950 983543950.0000 -311 4181 979599938 234298 234298 234298.0000 -447 4181 9929180954 2374834 2374834 2374834.0000 -512 4181 3288532102 786542 786542 786542.0000 -select distinct mod(companynr,10) from t4 group by companynr; -mod(companynr,10) -0 -9 -4 -6 -7 -1 -3 -8 -5 -select distinct 1 from t4 group by companynr; -1 -1 -select count(distinct fld1) from t2; -count(distinct fld1) -1199 -select companynr,count(distinct fld1) from t2 group by companynr; -companynr count(distinct fld1) -00 82 -29 95 -34 70 -36 215 -37 588 -40 37 -41 52 -50 11 -53 4 -58 23 -65 10 -68 12 -select companynr,count(*) from t2 group by companynr; -companynr count(*) -00 82 -29 95 -34 70 -36 215 -37 588 -40 37 -41 52 -50 11 -53 4 -58 23 -65 10 -68 12 -select companynr,count(distinct concat(fld1,repeat(65,1000))) from t2 group by companynr; -companynr count(distinct concat(fld1,repeat(65,1000))) -00 82 -29 95 -34 70 -36 215 -37 588 -40 37 -41 52 -50 11 -53 4 -58 23 -65 10 -68 12 -select companynr,count(distinct concat(fld1,repeat(65,200))) from t2 group by companynr; -companynr count(distinct concat(fld1,repeat(65,200))) -00 82 -29 95 -34 70 -36 215 -37 588 -40 37 -41 52 -50 11 -53 4 -58 23 -65 10 -68 12 -select companynr,count(distinct floor(fld1/100)) from t2 group by companynr; -companynr count(distinct floor(fld1/100)) -00 47 -29 35 -34 14 -36 69 -37 108 -40 16 -41 11 -50 9 -53 1 -58 1 -65 1 -68 1 -select companynr,count(distinct concat(repeat(65,1000),floor(fld1/100))) from t2 group by companynr; -companynr count(distinct concat(repeat(65,1000),floor(fld1/100))) -00 47 -29 35 -34 14 -36 69 -37 108 -40 16 -41 11 -50 9 -53 1 -58 1 -65 1 -68 1 -select sum(fld1),fld3 from t2 where fld3="Romans" group by fld1 limit 10; -sum(fld1) fld3 -11402 Romans -select name,count(*) from t3 where name='cloakroom' group by name; -name count(*) -cloakroom 4181 -select name,count(*) from t3 where name='cloakroom' and price>10 group by name; -name count(*) -cloakroom 4181 -select count(*) from t3 where name='cloakroom' and price2=823742; -count(*) -4181 -select name,count(*) from t3 where name='cloakroom' and price2=823742 group by name; -name count(*) -cloakroom 4181 -select name,count(*) from t3 where name >= "extramarital" and price <= 39654943 group by name; -name count(*) -extramarital 4181 -gazer 4181 -gems 4181 -Iranizes 4181 -spates 4181 -tucked 4181 -violinist 4181 -select t2.fld3,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; -fld3 count(*) -spates 4181 -select companynr|0,companyname from t4 group by 1; -companynr|0 companyname -0 Unknown -29 company 1 -34 company 2 -36 company 3 -37 company 4 -40 company 5 -41 company 6 -50 company 11 -53 company 7 -58 company 8 -65 company 9 -68 company 10 -select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by t2.companynr order by companyname; -companynr companyname count(*) -29 company 1 95 -68 company 10 12 -50 company 11 11 -34 company 2 70 -36 company 3 215 -37 company 4 588 -40 company 5 37 -41 company 6 52 -53 company 7 4 -58 company 8 23 -65 company 9 10 -00 Unknown 82 -select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name; -fld1 count(*) -158402 4181 -select sum(Period)/count(*) from t1; -sum(Period)/count(*) -9410.0000 -select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr; -companynr count sum diff func -37 12543 309394878010 0.0000 464091 -78 8362 414611089292 0.0000 652236 -101 4181 3489454238 0.0000 422281 -154 4181 4112197254950 0.0000 643874 -311 4181 979599938 0.0000 1300291 -447 4181 9929180954 0.0000 1868907 -512 4181 3288532102 0.0000 2140672 -select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg; -companynr avg -154 983543950.0000 -select companynr,count(*) from t2 group by companynr order by 2 desc; -companynr count(*) -37 588 -36 215 -29 95 -00 82 -34 70 -41 52 -40 37 -58 23 -68 12 -50 11 -65 10 -53 4 -select companynr,count(*) from t2 where companynr > 40 group by companynr order by 2 desc; -companynr count(*) -41 52 -58 23 -68 12 -50 11 -65 10 -53 4 -select t2.fld4,t2.fld1,count(price),sum(price),min(price),max(price),avg(price) from t3,t2 where t3.companynr = 37 and t2.fld1 = t3.t2nr group by fld1,t2.fld4; -fld4 fld1 count(price) sum(price) min(price) max(price) avg(price) -teethe 000001 1 5987435 5987435 5987435 5987435.0000 -dreaded 011401 1 5987435 5987435 5987435 5987435.0000 -scholastics 011402 1 28357832 28357832 28357832 28357832.0000 -audiology 011403 1 39654943 39654943 39654943 39654943.0000 -wallet 011501 1 5987435 5987435 5987435 5987435.0000 -parters 011701 1 5987435 5987435 5987435 5987435.0000 -eschew 011702 1 28357832 28357832 28357832 28357832.0000 -quitter 011703 1 39654943 39654943 39654943 39654943.0000 -neat 012001 1 5987435 5987435 5987435 5987435.0000 -Steinberg 012003 1 39654943 39654943 39654943 39654943.0000 -balled 012301 1 5987435 5987435 5987435 5987435.0000 -persist 012302 1 28357832 28357832 28357832 28357832.0000 -attainments 012303 1 39654943 39654943 39654943 39654943.0000 -capably 012501 1 5987435 5987435 5987435 5987435.0000 -impulsive 012602 1 28357832 28357832 28357832 28357832.0000 -starlet 012603 1 39654943 39654943 39654943 39654943.0000 -featherweight 012701 1 5987435 5987435 5987435 5987435.0000 -pessimist 012702 1 28357832 28357832 28357832 28357832.0000 -daughter 012703 1 39654943 39654943 39654943 39654943.0000 -lawgiver 013601 1 5987435 5987435 5987435 5987435.0000 -stated 013602 1 28357832 28357832 28357832 28357832.0000 -readable 013603 1 39654943 39654943 39654943 39654943.0000 -testicle 013801 1 5987435 5987435 5987435 5987435.0000 -Parsifal 013802 1 28357832 28357832 28357832 28357832.0000 -leavings 013803 1 39654943 39654943 39654943 39654943.0000 -squeaking 013901 1 5987435 5987435 5987435 5987435.0000 -contrasted 016001 1 5987435 5987435 5987435 5987435.0000 -leftover 016201 1 5987435 5987435 5987435 5987435.0000 -whiteners 016202 1 28357832 28357832 28357832 28357832.0000 -erases 016301 1 5987435 5987435 5987435 5987435.0000 -Punjab 016302 1 28357832 28357832 28357832 28357832.0000 -Merritt 016303 1 39654943 39654943 39654943 39654943.0000 -sweetish 018001 1 5987435 5987435 5987435 5987435.0000 -dogging 018002 1 28357832 28357832 28357832 28357832.0000 -scornfully 018003 1 39654943 39654943 39654943 39654943.0000 -fetters 018012 1 28357832 28357832 28357832 28357832.0000 -bivalves 018013 1 39654943 39654943 39654943 39654943.0000 -skulking 018021 1 5987435 5987435 5987435 5987435.0000 -flint 018022 1 28357832 28357832 28357832 28357832.0000 -flopping 018023 1 39654943 39654943 39654943 39654943.0000 -Judas 018032 1 28357832 28357832 28357832 28357832.0000 -vacuuming 018033 1 39654943 39654943 39654943 39654943.0000 -medical 018041 1 5987435 5987435 5987435 5987435.0000 -bloodbath 018042 1 28357832 28357832 28357832 28357832.0000 -subschema 018043 1 39654943 39654943 39654943 39654943.0000 -interdependent 018051 1 5987435 5987435 5987435 5987435.0000 -Graves 018052 1 28357832 28357832 28357832 28357832.0000 -neonatal 018053 1 39654943 39654943 39654943 39654943.0000 -sorters 018061 1 5987435 5987435 5987435 5987435.0000 -epistle 018062 1 28357832 28357832 28357832 28357832.0000 -Conley 018101 1 5987435 5987435 5987435 5987435.0000 -lectured 018102 1 28357832 28357832 28357832 28357832.0000 -Abraham 018103 1 39654943 39654943 39654943 39654943.0000 -cage 018201 1 5987435 5987435 5987435 5987435.0000 -hushes 018202 1 28357832 28357832 28357832 28357832.0000 -Simla 018402 1 28357832 28357832 28357832 28357832.0000 -reporters 018403 1 39654943 39654943 39654943 39654943.0000 -coexist 018601 1 5987435 5987435 5987435 5987435.0000 -Beebe 018602 1 28357832 28357832 28357832 28357832.0000 -Taoism 018603 1 39654943 39654943 39654943 39654943.0000 -Connally 018801 1 5987435 5987435 5987435 5987435.0000 -fetched 018802 1 28357832 28357832 28357832 28357832.0000 -checkpoints 018803 1 39654943 39654943 39654943 39654943.0000 -gritty 018811 1 5987435 5987435 5987435 5987435.0000 -firearm 018812 1 28357832 28357832 28357832 28357832.0000 -minima 019101 1 5987435 5987435 5987435 5987435.0000 -Selfridge 019102 1 28357832 28357832 28357832 28357832.0000 -disable 019103 1 39654943 39654943 39654943 39654943.0000 -witchcraft 019201 1 5987435 5987435 5987435 5987435.0000 -betroth 030501 1 5987435 5987435 5987435 5987435.0000 -Manhattanize 030502 1 28357832 28357832 28357832 28357832.0000 -imprint 030503 1 39654943 39654943 39654943 39654943.0000 -swelling 031901 1 5987435 5987435 5987435 5987435.0000 -interrelationships 036001 1 5987435 5987435 5987435 5987435.0000 -riser 036002 1 28357832 28357832 28357832 28357832.0000 -bee 038001 1 5987435 5987435 5987435 5987435.0000 -kanji 038002 1 28357832 28357832 28357832 28357832.0000 -dental 038003 1 39654943 39654943 39654943 39654943.0000 -railway 038011 1 5987435 5987435 5987435 5987435.0000 -validate 038012 1 28357832 28357832 28357832 28357832.0000 -normalizes 038013 1 39654943 39654943 39654943 39654943.0000 -Kline 038101 1 5987435 5987435 5987435 5987435.0000 -Anatole 038102 1 28357832 28357832 28357832 28357832.0000 -partridges 038103 1 39654943 39654943 39654943 39654943.0000 -recruited 038201 1 5987435 5987435 5987435 5987435.0000 -dimensions 038202 1 28357832 28357832 28357832 28357832.0000 -Chicana 038203 1 39654943 39654943 39654943 39654943.0000 -select t3.companynr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 group by companynr,fld3; -companynr fld3 sum(price) -512 boat 786542 -512 capably 786542 -512 cupboard 786542 -512 decliner 786542 -512 descendants 786542 -512 dopers 786542 -512 erases 786542 -512 Micronesia 786542 -512 Miles 786542 -512 skies 786542 -select t2.companynr,count(*),min(fld3),max(fld3),sum(price),avg(price) from t2,t3 where t3.companynr >= 30 and t3.companynr <= 58 and t3.t2nr = t2.fld1 and 1+1=2 group by t2.companynr; -companynr count(*) min(fld3) max(fld3) sum(price) avg(price) -00 1 Omaha Omaha 5987435 5987435.0000 -36 1 dubbed dubbed 28357832 28357832.0000 -37 83 Abraham Wotan 1908978016 22999735.1325 -50 2 scribbled tapestry 68012775 34006387.5000 -select t3.companynr+0,t3.t2nr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 37 group by 1,t3.t2nr,fld3,fld3,fld3,fld3,fld3 order by fld1; -t3.companynr+0 t2nr fld3 sum(price) -37 1 Omaha 5987435 -37 11401 breaking 5987435 -37 11402 Romans 28357832 -37 11403 intercepted 39654943 -37 11501 bewilderingly 5987435 -37 11701 astound 5987435 -37 11702 admonishing 28357832 -37 11703 sumac 39654943 -37 12001 flanking 5987435 -37 12003 combed 39654943 -37 12301 Eulerian 5987435 -37 12302 dubbed 28357832 -37 12303 Kane 39654943 -37 12501 annihilates 5987435 -37 12602 Wotan 28357832 -37 12603 snatching 39654943 -37 12701 grazing 5987435 -37 12702 Baird 28357832 -37 12703 celery 39654943 -37 13601 handgun 5987435 -37 13602 foldout 28357832 -37 13603 mystic 39654943 -37 13801 intelligibility 5987435 -37 13802 Augustine 28357832 -37 13803 teethe 39654943 -37 13901 scholastics 5987435 -37 16001 audiology 5987435 -37 16201 wallet 5987435 -37 16202 parters 28357832 -37 16301 eschew 5987435 -37 16302 quitter 28357832 -37 16303 neat 39654943 -37 18001 jarring 5987435 -37 18002 tinily 28357832 -37 18003 balled 39654943 -37 18012 impulsive 28357832 -37 18013 starlet 39654943 -37 18021 lawgiver 5987435 -37 18022 stated 28357832 -37 18023 readable 39654943 -37 18032 testicle 28357832 -37 18033 Parsifal 39654943 -37 18041 Punjab 5987435 -37 18042 Merritt 28357832 -37 18043 Quixotism 39654943 -37 18051 sureties 5987435 -37 18052 puddings 28357832 -37 18053 tapestry 39654943 -37 18061 trimmings 5987435 -37 18062 humility 28357832 -37 18101 tragedies 5987435 -37 18102 skulking 28357832 -37 18103 flint 39654943 -37 18201 relaxing 5987435 -37 18202 offload 28357832 -37 18402 suites 28357832 -37 18403 lists 39654943 -37 18601 vacuuming 5987435 -37 18602 dentally 28357832 -37 18603 humanness 39654943 -37 18801 inch 5987435 -37 18802 Weissmuller 28357832 -37 18803 irresponsibly 39654943 -37 18811 repetitions 5987435 -37 18812 Antares 28357832 -37 19101 ventilate 5987435 -37 19102 pityingly 28357832 -37 19103 interdependent 39654943 -37 19201 Graves 5987435 -37 30501 neonatal 5987435 -37 30502 scribbled 28357832 -37 30503 chafe 39654943 -37 31901 realtor 5987435 -37 36001 elite 5987435 -37 36002 funereal 28357832 -37 38001 Conley 5987435 -37 38002 lectured 28357832 -37 38003 Abraham 39654943 -37 38011 groupings 5987435 -37 38012 dissociate 28357832 -37 38013 coexist 39654943 -37 38101 rusting 5987435 -37 38102 galling 28357832 -37 38103 obliterates 39654943 -37 38201 resumes 5987435 -37 38202 analyzable 28357832 -37 38203 terminator 39654943 -select sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1= t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008; -sum(price) -234298 -select t2.fld1,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1 = t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008 or t3.t2nr = t2.fld1 and t2.fld1 = 38008 group by t2.fld1; -fld1 sum(price) -038008 234298 -explain select fld3 from t2 where 1>2 or 2>3; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE -explain select fld3 from t2 where fld1=fld1; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 -select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502; -companynr fld1 -34 250501 -34 250502 -select companynr,fld1 from t2 WHERE fld1>=250501 HAVING fld1<=250502; -companynr fld1 -34 250501 -34 250502 -select companynr,count(*) as count,sum(fld1) as sum from t2 group by companynr having count > 40 and sum/count >= 120000; -companynr count sum -00 82 10355753 -29 95 14473298 -34 70 17788966 -37 588 83602098 -41 52 12816335 -select companynr from t2 group by companynr having count(*) > 40 and sum(fld1)/count(*) >= 120000 ; -companynr -00 -29 -34 -37 -41 -select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by companyname having t2.companynr >= 40; -companynr companyname count(*) -68 company 10 12 -50 company 11 11 -40 company 5 37 -41 company 6 52 -53 company 7 4 -58 company 8 23 -65 company 9 10 -select count(*) from t2; -count(*) -1199 -select count(*) from t2 where fld1 < 098024; -count(*) -387 -select min(fld1) from t2 where fld1>= 098024; -min(fld1) -98024 -select max(fld1) from t2 where fld1>= 098024; -max(fld1) -1232609 -select count(*) from t3 where price2=76234234; -count(*) -4181 -select count(*) from t3 where companynr=512 and price2=76234234; -count(*) -4181 -explain select min(fld1),max(fld1),count(*) from t2; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -select min(fld1),max(fld1),count(*) from t2; -min(fld1) max(fld1) count(*) -0 1232609 1199 -select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742; -min(t2nr) max(t2nr) -2115 2115 -select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78; -count(*) min(t2nr) max(t2nr) -4181 4 41804 -select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20; -t2nr count(*) -9 1 -19 1 -29 1 -39 1 -49 1 -59 1 -69 1 -79 1 -89 1 -99 1 -109 1 -119 1 -129 1 -139 1 -149 1 -159 1 -169 1 -179 1 -189 1 -199 1 -select max(t2nr) from t3 where price=983543950; -max(t2nr) -41807 -select t1.period from t3 = t1 limit 1; -period -1001 -select t1.period from t1 as t1 limit 1; -period -9410 -select t1.period as "Nuvarande period" from t1 as t1 limit 1; -Nuvarande period -9410 -select period as ok_period from t1 limit 1; -ok_period -9410 -select period as ok_period from t1 group by ok_period limit 1; -ok_period -9410 -select 1+1 as summa from t1 group by summa limit 1; -summa -2 -select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1; -Nuvarande period -9410 -show tables; -Tables_in_test -t1 -t2 -t3 -t4 -show tables from test like "s%"; -Tables_in_test (s%) -show tables from test like "t?"; -Tables_in_test (t?) -show full columns from t2; -Field Type Collation Null Key Default Extra Privileges Comment -auto int(11) NULL NO PRI NULL auto_increment # -fld1 int(6) unsigned zerofill NULL NO UNI 000000 # -companynr tinyint(2) unsigned zerofill NULL NO 00 # -fld3 char(30) latin1_swedish_ci NO MUL # -fld4 char(35) latin1_swedish_ci NO # -fld5 char(35) latin1_swedish_ci NO # -fld6 char(4) latin1_swedish_ci NO # -show full columns from t2 from test like 'f%'; -Field Type Collation Null Key Default Extra Privileges Comment -fld1 int(6) unsigned zerofill NULL NO UNI 000000 # -fld3 char(30) latin1_swedish_ci NO MUL # -fld4 char(35) latin1_swedish_ci NO # -fld5 char(35) latin1_swedish_ci NO # -fld6 char(4) latin1_swedish_ci NO # -show full columns from t2 from test like 's%'; -Field Type Collation Null Key Default Extra Privileges Comment -show keys from t2; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment -t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE -t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE -t2 1 fld3 1 fld3 A NULL NULL NULL BTREE -drop table t4, t3, t2, t1; -CREATE TABLE t1 ( -cont_nr int(11) NOT NULL auto_increment, -ver_nr int(11) NOT NULL default '0', -aufnr int(11) NOT NULL default '0', -username varchar(50) NOT NULL default '', -hdl_nr int(11) NOT NULL default '0', -eintrag date NOT NULL default '0000-00-00', -st_klasse varchar(40) NOT NULL default '', -st_wert varchar(40) NOT NULL default '', -st_zusatz varchar(40) NOT NULL default '', -st_bemerkung varchar(255) NOT NULL default '', -kunden_art varchar(40) NOT NULL default '', -mcbs_knr int(11) default NULL, -mcbs_aufnr int(11) NOT NULL default '0', -schufa_status char(1) default '?', -bemerkung text, -wirknetz text, -wf_igz int(11) NOT NULL default '0', -tarifcode varchar(80) default NULL, -recycle char(1) default NULL, -sim varchar(30) default NULL, -mcbs_tpl varchar(30) default NULL, -emp_nr int(11) NOT NULL default '0', -laufzeit int(11) default NULL, -hdl_name varchar(30) default NULL, -prov_hdl_nr int(11) NOT NULL default '0', -auto_wirknetz varchar(50) default NULL, -auto_billing varchar(50) default NULL, -touch timestamp NOT NULL, -kategorie varchar(50) default NULL, -kundentyp varchar(20) NOT NULL default '', -sammel_rech_msisdn varchar(30) NOT NULL default '', -p_nr varchar(9) NOT NULL default '', -suffix char(3) NOT NULL default '', -PRIMARY KEY (cont_nr), -KEY idx_aufnr(aufnr), -KEY idx_hdl_nr(hdl_nr), -KEY idx_st_klasse(st_klasse), -KEY ver_nr(ver_nr), -KEY eintrag_idx(eintrag), -KEY emp_nr_idx(emp_nr), -KEY wf_igz(wf_igz), -KEY touch(touch), -KEY hdl_tag(eintrag,hdl_nr), -KEY prov_hdl_nr(prov_hdl_nr), -KEY mcbs_aufnr(mcbs_aufnr), -KEY kundentyp(kundentyp), -KEY p_nr(p_nr,suffix) -) ENGINE=MyISAM; -INSERT INTO t1 VALUES (3359356,405,3359356,'Mustermann Musterfrau',52500,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1485525,2122316,'+','','N',1909160,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',3,24,'MobilCom Shop Koeln',52500,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); -INSERT INTO t1 VALUES (3359357,468,3359357,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1503580,2139699,'+','','P',1909171,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); -INSERT INTO t1 VALUES (3359358,407,3359358,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1501358,2137473,'N','','N',1909159,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); -INSERT INTO t1 VALUES (3359359,468,3359359,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1507831,2143894,'+','','P',1909162,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); -INSERT INTO t1 VALUES (3359360,0,0,'Mustermann Musterfrau',29674907,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1900169997,2414578,'+',NULL,'N',1909148,'',NULL,NULL,'RV99066_2',20,NULL,'POS',29674907,NULL,NULL,20010202105916,'Mobilfunk','','','97317481','007'); -INSERT INTO t1 VALUES (3359361,406,3359361,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag storniert','','(7001-84):Storno, Kd. möchte nicht mehr','privat',NULL,0,'+','','P',1909150,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); -INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1509984,2145874,'+','','P',1909154,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); -SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie; -Kundentyp kategorie -Privat (Private Nutzung) Mobilfunk -Warnings: -Warning 1052 Column 'kundentyp' in group statement is ambiguous -drop table t1; -connection default; -disconnect shm_con; -mysqld is alive -SET @max_allowed_packet= @@global.max_allowed_packet; -SET @net_buffer_length= @@global.net_buffer_length; -SET GLOBAL max_allowed_packet= 1024; -Warnings: -Warning 1708 The value of 'max_allowed_packet' should be no less than the value of 'net_buffer_length' -SET GLOBAL net_buffer_length= 1024; -ERROR 1153 (08S01) at line 1: Got a packet bigger than 'max_allowed_packet' bytes -SET GLOBAL max_allowed_packet= @max_allowed_packet; -SET GLOBAL net_buffer_length= @net_buffer_length; -End of 5.0 tests. diff --git a/mysql-test/main/shm.test b/mysql-test/main/shm.test deleted file mode 100644 index 346ce49476e..00000000000 --- a/mysql-test/main/shm.test +++ /dev/null @@ -1,47 +0,0 @@ -# We currently only have shm support on windows, so in order -# to optimize things we skip this test on all other platforms ---source include/windows.inc - -# thread pool causes different results --- source include/not_threadpool.inc - -# Only run this test if shared memory is avaliable -let $shm= query_get_value("SHOW VARIABLES LIKE 'shared_memory'", Value, 1); -if ($shm != ON){ - skip No shm support; -} -let $shm_name= query_get_value("SHOW GLOBAL VARIABLES LIKE 'shared_memory_base_name'", Value, 1); - -# Connect using SHM for testing -connect(shm_con,localhost,root,,,,$shm_name,SHM); - -# Source select test case --- source include/common-tests.inc - -connection default; -disconnect shm_con; - -# -# Bug #24924: shared-memory-base-name that is too long causes buffer overflow -# ---exec $MYSQLADMIN --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --shared-memory-base-name=HeyMrBaseNameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ping - -# -# Bug #33899: Deadlock in mysql_real_query with shared memory connections -# - -let $stmt= `SELECT REPEAT('a', 2048)`; - -SET @max_allowed_packet= @@global.max_allowed_packet; -SET @net_buffer_length= @@global.net_buffer_length; - -SET GLOBAL max_allowed_packet= 1024; -SET GLOBAL net_buffer_length= 1024; - ---error 1 ---exec echo SELECT '$stmt'| $MYSQL --protocol=memory --shared-memory-base-name=$shm_name 2>&1 - -SET GLOBAL max_allowed_packet= @max_allowed_packet; -SET GLOBAL net_buffer_length= @net_buffer_length; - ---echo End of 5.0 tests. diff --git a/mysql-test/main/show_check.result b/mysql-test/main/show_check.result index 5083f1e615b..741514b99b1 100644 --- a/mysql-test/main/show_check.result +++ b/mysql-test/main/show_check.result @@ -162,8 +162,9 @@ Catalog Database Table Table_alias Column Column_alias Type Length Max length Is def Table 253 128 7 Y 0 39 8 def Op 253 10 7 Y 0 39 8 def Msg_type 253 10 6 Y 0 39 8 -def Msg_text 250 393216 2 Y 0 39 8 +def Msg_text 250 393216 39 Y 0 39 8 Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -261,7 +262,10 @@ create table t1(n int); insert into t1 values (1); show open tables; Database Table In_use Name_locked +mysql column_stats 0 0 mysql general_log 0 0 +mysql index_stats 0 0 +mysql table_stats 0 0 test t1 0 0 drop table t1; create table t1 (a int not null, b VARCHAR(10), INDEX (b) ) AVG_ROW_LENGTH=10 CHECKSUM=1 COMMENT="test" ENGINE=MYISAM MIN_ROWS=10 MAX_ROWS=100 PACK_KEYS=1 DELAY_KEY_WRITE=1 ROW_FORMAT=fixed; @@ -757,11 +761,11 @@ View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select sql_no_cache current_timestamp() AS `NOW()` binary binary DROP VIEW v1; CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE NOW(); -ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE +ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE CREATE VIEW v1 AS SELECT SQL_NO_CACHE SQL_CACHE NOW(); ERROR HY000: Incorrect usage of SQL_NO_CACHE and SQL_CACHE CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE SQL_CACHE NOW(); -ERROR HY000: Incorrect usage of SQL_CACHE and SQL_NO_CACHE +ERROR HY000: Option 'SQL_CACHE' used twice in statement CREATE PROCEDURE p1() BEGIN SET @s= 'CREATE VIEW v1 AS SELECT SQL_CACHE 1'; diff --git a/mysql-test/main/show_check.test b/mysql-test/main/show_check.test index a24fa632ea5..b6885b1fcaf 100644 --- a/mysql-test/main/show_check.test +++ b/mysql-test/main/show_check.test @@ -558,7 +558,7 @@ CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE NOW(); --error ER_WRONG_USAGE CREATE VIEW v1 AS SELECT SQL_NO_CACHE SQL_CACHE NOW(); ---error ER_WRONG_USAGE +--error ER_DUP_ARGUMENT CREATE VIEW v1 AS SELECT SQL_CACHE SQL_NO_CACHE SQL_CACHE NOW(); # Check CREATE VIEW in a prepared statement in a procedure. diff --git a/mysql-test/main/show_create_user.result b/mysql-test/main/show_create_user.result index 63013eca074..1205b658b6e 100644 --- a/mysql-test/main/show_create_user.result +++ b/mysql-test/main/show_create_user.result @@ -10,10 +10,10 @@ create user foo2@test identified by 'password'; show create user foo2@test; CREATE USER for foo2@test CREATE USER 'foo2'@'test' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' -alter user foo2@test identified with 'someplugin' as 'somepassword'; +alter user foo2@test identified with 'mysql_old_password' as '0123456789ABCDEF'; show create user foo2@test; CREATE USER for foo2@test -CREATE USER 'foo2'@'test' IDENTIFIED VIA someplugin USING 'somepassword' +CREATE USER 'foo2'@'test' IDENTIFIED BY PASSWORD '0123456789ABCDEF' create user foo3@test require SSL; show create user foo3@test; CREATE USER for foo3@test diff --git a/mysql-test/main/show_create_user.test b/mysql-test/main/show_create_user.test index a10c8aeeda6..03852b5abbc 100644 --- a/mysql-test/main/show_create_user.test +++ b/mysql-test/main/show_create_user.test @@ -9,7 +9,7 @@ show create user foo@test; create user foo2@test identified by 'password'; show create user foo2@test; -alter user foo2@test identified with 'someplugin' as 'somepassword'; +alter user foo2@test identified with 'mysql_old_password' as '0123456789ABCDEF'; show create user foo2@test; create user foo3@test require SSL; diff --git a/mysql-test/main/show_grants_with_plugin-7985.result b/mysql-test/main/show_grants_with_plugin-7985.result deleted file mode 100644 index bb475b7cba9..00000000000 --- a/mysql-test/main/show_grants_with_plugin-7985.result +++ /dev/null @@ -1,197 +0,0 @@ -call mtr.add_suppression("password and an authentication plugin"); -# -# Create a user with mysql_native_password plugin. -# The user has no password or auth_string set. -# -create user u1; -GRANT SELECT ON mysql.* to u1 IDENTIFIED VIA mysql_native_password; -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; -user host password plugin authentication_string -u1 % -# -# The user's grants should show no password at all. -# -show grants for u1; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -# -# Test to see if connecting with no password is succesful. -# -connect con1, localhost, u1,,; -show grants; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -disconnect con1; -connection default; -# -# Test after flushing privileges. -# -flush privileges; -connect con1, localhost, u1,,; -show grants; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -disconnect con1; -connection default; -# -# Now add a mysql_native password string in authentication_string. -# -GRANT SELECT ON mysql.* to u1 IDENTIFIED VIA mysql_native_password -USING '*7AFEFD08B6B720E781FB000CAA418F54FA662626'; -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; -user host password plugin authentication_string -u1 % *7AFEFD08B6B720E781FB000CAA418F54FA662626 -# -# Test to see if connecting with password is succesful. -# -connect con1, localhost, u1,'SOMETHING',; -show grants; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' IDENTIFIED BY PASSWORD '*7AFEFD08B6B720E781FB000CAA418F54FA662626' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -disconnect con1; -connection default; -# -# Test after flushing privileges. -# -flush privileges; -connect con1, localhost, u1,'SOMETHING',; -show grants; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' IDENTIFIED BY PASSWORD '*7AFEFD08B6B720E781FB000CAA418F54FA662626' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -disconnect con1; -connection default; -# -# Now we also set a password for the user. -# -set password for u1 = PASSWORD('SOMETHINGELSE'); -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; -user host password plugin authentication_string -u1 % *054B7BBD2B9A553DA560520DCD3F76DA2D81B7C6 mysql_native_password *054B7BBD2B9A553DA560520DCD3F76DA2D81B7C6 -# -# Here we should use the password field, as that primes over -# the authentication_string field. -# -show grants for u1; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' IDENTIFIED BY PASSWORD '*054B7BBD2B9A553DA560520DCD3F76DA2D81B7C6' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -# -# Logging in with the user's password should work. -# -connect con1, localhost, u1,'SOMETHINGELSE',; -show grants; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' IDENTIFIED BY PASSWORD '*054B7BBD2B9A553DA560520DCD3F76DA2D81B7C6' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -disconnect con1; -connection default; -# -# Reload privileges and test logging in again. -# -flush privileges; -show grants for u1; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' IDENTIFIED BY PASSWORD '*054B7BBD2B9A553DA560520DCD3F76DA2D81B7C6' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -# -# Here we connect via the user's password again. -# -connect con1, localhost, u1,'SOMETHINGELSE',; -show grants; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' IDENTIFIED BY PASSWORD '*054B7BBD2B9A553DA560520DCD3F76DA2D81B7C6' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -disconnect con1; -connection default; -# -# Now we remove the authentication plugin password, flush privileges and -# try again. -# -update mysql.user set password=authentication_string, plugin='', authentication_string='' where user='u1'; -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; -user host password plugin authentication_string -u1 % *054B7BBD2B9A553DA560520DCD3F76DA2D81B7C6 -flush privileges; -show grants for u1; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' IDENTIFIED BY PASSWORD '*054B7BBD2B9A553DA560520DCD3F76DA2D81B7C6' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -# -# Here we connect via the user's password. -# -connect con1, localhost, u1,'SOMETHINGELSE',; -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; -user host password plugin authentication_string -u1 % *054B7BBD2B9A553DA560520DCD3F76DA2D81B7C6 -disconnect con1; -connection default; -# -# Try and set a wrong auth_string password, with mysql_native_password. -# Make sure it fails. -# -GRANT USAGE ON *.* TO u1 IDENTIFIED VIA mysql_native_password USING 'asd'; -ERROR HY000: Password hash should be a 41-digit hexadecimal number -# -# Now set a correct password. -# -GRANT SELECT ON mysql.* to u1 IDENTIFIED VIA mysql_native_password -USING '*7AFEFD08B6B720E781FB000CAA418F54FA662626'; -show grants for u1; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' IDENTIFIED BY PASSWORD '*7AFEFD08B6B720E781FB000CAA418F54FA662626' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -# -# Test if the user can now use that password instead. -# -connect con1, localhost, u1,'SOMETHING',; -show grants; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' IDENTIFIED BY PASSWORD '*7AFEFD08B6B720E781FB000CAA418F54FA662626' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -disconnect con1; -# -# Test if the user can now use that password instead, after flushing privileges; -# -connection default; -flush privileges; -connect con1, localhost, u1,'SOMETHING',; -show grants; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' IDENTIFIED BY PASSWORD '*7AFEFD08B6B720E781FB000CAA418F54FA662626' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -disconnect con1; -connection default; -# -# Clear all passwords from the user. -# -set password for u1 = ''; -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; -user host password plugin authentication_string -u1 % mysql_native_password -# -# Test no password connect. -# -connect con1, localhost, u1,,; -show grants; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -disconnect con1; -connection default; -# -# Test no password connect, after flushing privileges. -# -flush privileges; -connect con1, localhost, u1,,; -show grants; -Grants for u1@% -GRANT USAGE ON *.* TO 'u1'@'%' -GRANT SELECT ON `mysql`.* TO 'u1'@'%' -disconnect con1; -connection default; -drop user u1; diff --git a/mysql-test/main/show_grants_with_plugin-7985.test b/mysql-test/main/show_grants_with_plugin-7985.test deleted file mode 100644 index 85952870254..00000000000 --- a/mysql-test/main/show_grants_with_plugin-7985.test +++ /dev/null @@ -1,160 +0,0 @@ ---source include/not_embedded.inc -call mtr.add_suppression("password and an authentication plugin"); - ---echo # ---echo # Create a user with mysql_native_password plugin. ---echo # The user has no password or auth_string set. ---echo # - -create user u1; -GRANT SELECT ON mysql.* to u1 IDENTIFIED VIA mysql_native_password; -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; - ---echo # ---echo # The user's grants should show no password at all. ---echo # -show grants for u1; ---echo # ---echo # Test to see if connecting with no password is succesful. ---echo # ---connect (con1, localhost, u1,,) -show grants; ---disconnect con1 - ---connection default ---echo # ---echo # Test after flushing privileges. ---echo # -flush privileges; ---connect (con1, localhost, u1,,) -show grants; ---disconnect con1 - ---connection default ---echo # ---echo # Now add a mysql_native password string in authentication_string. ---echo # -# Password string is SOMETHING -GRANT SELECT ON mysql.* to u1 IDENTIFIED VIA mysql_native_password -USING '*7AFEFD08B6B720E781FB000CAA418F54FA662626'; -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; ---echo # ---echo # Test to see if connecting with password is succesful. ---echo # ---connect (con1, localhost, u1,'SOMETHING',) -show grants; ---disconnect con1 - ---connection default ---echo # ---echo # Test after flushing privileges. ---echo # -flush privileges; ---connect (con1, localhost, u1,'SOMETHING',) -show grants; ---disconnect con1 ---connection default - ---echo # ---echo # Now we also set a password for the user. ---echo # -set password for u1 = PASSWORD('SOMETHINGELSE'); -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; - ---echo # ---echo # Here we should use the password field, as that primes over ---echo # the authentication_string field. ---echo # -show grants for u1; - ---echo # ---echo # Logging in with the user's password should work. ---echo # ---connect (con1, localhost, u1,'SOMETHINGELSE',) -show grants; ---disconnect con1 ---connection default ---echo # ---echo # Reload privileges and test logging in again. ---echo # -flush privileges; -show grants for u1; ---echo # ---echo # Here we connect via the user's password again. ---echo # ---connect (con1, localhost, u1,'SOMETHINGELSE',) -show grants; ---disconnect con1 ---connection default - ---echo # ---echo # Now we remove the authentication plugin password, flush privileges and ---echo # try again. ---echo # -update mysql.user set password=authentication_string, plugin='', authentication_string='' where user='u1'; -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; -flush privileges; -show grants for u1; ---echo # ---echo # Here we connect via the user's password. ---echo # ---connect (con1, localhost, u1,'SOMETHINGELSE',) -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; ---disconnect con1 ---connection default - ---echo # ---echo # Try and set a wrong auth_string password, with mysql_native_password. ---echo # Make sure it fails. ---echo # ---error ER_PASSWD_LENGTH -GRANT USAGE ON *.* TO u1 IDENTIFIED VIA mysql_native_password USING 'asd'; ---echo # ---echo # Now set a correct password. ---echo # -GRANT SELECT ON mysql.* to u1 IDENTIFIED VIA mysql_native_password -USING '*7AFEFD08B6B720E781FB000CAA418F54FA662626'; -show grants for u1; - ---echo # ---echo # Test if the user can now use that password instead. ---echo # ---connect (con1, localhost, u1,'SOMETHING',) -show grants; ---disconnect con1 - ---echo # ---echo # Test if the user can now use that password instead, after flushing privileges; ---echo # ---connection default -flush privileges; - ---connect (con1, localhost, u1,'SOMETHING',) -show grants; ---disconnect con1 ---connection default - ---echo # ---echo # Clear all passwords from the user. ---echo # -set password for u1 = ''; -select user, host, password, plugin, authentication_string from mysql.user where user = 'u1'; - ---echo # ---echo # Test no password connect. ---echo # ---connect (con1, localhost, u1,,) -show grants; ---disconnect con1 ---connection default - ---echo # ---echo # Test no password connect, after flushing privileges. ---echo # -flush privileges; ---connect (con1, localhost, u1,,) -show grants; ---disconnect con1 ---connection default - -drop user u1; diff --git a/mysql-test/main/signal.result b/mysql-test/main/signal.result index 215f7db8b0d..e329c58a47e 100644 --- a/mysql-test/main/signal.result +++ b/mysql-test/main/signal.result @@ -2285,17 +2285,13 @@ begin DECLARE foo CONDITION FOR SQLSTATE '12345'; SIGNAL foo SET MYSQL_ERRNO = `65`; /* illegal */ end $$ -call test_signal $$ ERROR 42S22: Unknown column '65' in 'field list' -drop procedure test_signal $$ create procedure test_signal() begin DECLARE foo CONDITION FOR SQLSTATE '12345'; SIGNAL foo SET MYSQL_ERRNO = `A`; /* illegal */ end $$ -call test_signal $$ ERROR 42S22: Unknown column 'A' in 'field list' -drop procedure test_signal $$ create procedure test_signal() begin DECLARE foo CONDITION FOR SQLSTATE '12345'; @@ -2346,9 +2342,7 @@ DECLARE foo CONDITION FOR SQLSTATE '12345'; SIGNAL foo SET MYSQL_ERRNO = 1000, MESSAGE_TEXT = `Hello`; end $$ -call test_signal $$ ERROR 42S22: Unknown column 'Hello' in 'field list' -drop procedure test_signal $$ create procedure test_signal() begin DECLARE foo CONDITION FOR SQLSTATE '12345'; diff --git a/mysql-test/main/signal.test b/mysql-test/main/signal.test index e4dcb5a71cf..5b40863b0e6 100644 --- a/mysql-test/main/signal.test +++ b/mysql-test/main/signal.test @@ -2546,25 +2546,21 @@ end $$ call test_signal $$ drop procedure test_signal $$ +-- error ER_BAD_FIELD_ERROR create procedure test_signal() begin DECLARE foo CONDITION FOR SQLSTATE '12345'; SIGNAL foo SET MYSQL_ERRNO = `65`; /* illegal */ end $$ --- error ER_BAD_FIELD_ERROR -call test_signal $$ -drop procedure test_signal $$ +-- error ER_BAD_FIELD_ERROR create procedure test_signal() begin DECLARE foo CONDITION FOR SQLSTATE '12345'; SIGNAL foo SET MYSQL_ERRNO = `A`; /* illegal */ end $$ --- error ER_BAD_FIELD_ERROR -call test_signal $$ -drop procedure test_signal $$ create procedure test_signal() begin @@ -2620,6 +2616,7 @@ end $$ call test_signal $$ drop procedure test_signal $$ +-- error ER_BAD_FIELD_ERROR create procedure test_signal() begin DECLARE foo CONDITION FOR SQLSTATE '12345'; @@ -2627,10 +2624,6 @@ begin MESSAGE_TEXT = `Hello`; end $$ --- error ER_BAD_FIELD_ERROR -call test_signal $$ -drop procedure test_signal $$ - create procedure test_signal() begin DECLARE foo CONDITION FOR SQLSTATE '12345'; diff --git a/mysql-test/main/signal_demo1.result b/mysql-test/main/signal_demo1.result index 752f23a48d6..d919f48404f 100644 --- a/mysql-test/main/signal_demo1.result +++ b/mysql-test/main/signal_demo1.result @@ -75,6 +75,9 @@ end; end case; end $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create procedure check_pk_inventory(in id integer) begin declare x integer; @@ -92,6 +95,8 @@ MYSQL_ERRNO = 10000; end if; end $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create procedure check_pk_order(in id integer) begin declare x integer; @@ -108,6 +113,8 @@ MYSQL_ERRNO = 10000; end if; end $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create trigger po_order_bi before insert on po_order for each row begin diff --git a/mysql-test/main/sp-anchor-row-type-cursor.result b/mysql-test/main/sp-anchor-row-type-cursor.result index add771c534c..64359988a3d 100644 --- a/mysql-test/main/sp-anchor-row-type-cursor.result +++ b/mysql-test/main/sp-anchor-row-type-cursor.result @@ -936,6 +936,8 @@ SELECT rec1.a, rec1.b; END; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: The used SELECT statements have a different number of columns DROP TABLE t1; @@ -955,6 +957,8 @@ SELECT rec1.a, rec1.b; END; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: Operand should contain 2 column(s) DROP TABLE t1; @@ -972,6 +976,8 @@ SELECT rec1.a, rec1.b; END; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); rec1.a rec1.b 10 b10 diff --git a/mysql-test/main/sp-anchor-row-type-table.result b/mysql-test/main/sp-anchor-row-type-table.result index 6abf1e18315..b51ee5bf55d 100644 --- a/mysql-test/main/sp-anchor-row-type-table.result +++ b/mysql-test/main/sp-anchor-row-type-table.result @@ -606,6 +606,8 @@ SELECT 10,'a','b' FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: The used SELECT statements have a different number of columns DROP TABLE t1; @@ -622,6 +624,8 @@ SELECT 10,'a' FROM t1 INTO rec1, rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: Operand should contain 2 column(s) DROP TABLE t1; @@ -638,6 +642,8 @@ SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); rec1.a rec1.b 10 b10 diff --git a/mysql-test/main/sp-anchor-type.result b/mysql-test/main/sp-anchor-type.result index 2b61854d514..f7674735821 100644 --- a/mysql-test/main/sp-anchor-type.result +++ b/mysql-test/main/sp-anchor-type.result @@ -957,6 +957,8 @@ SELECT * FROM t1 INTO v_a, v_b, v_c; SELECT v_a, v_b, v_c; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); v_a v_b v_c 1 b1 2001-01-01 10:20:30.123 diff --git a/mysql-test/main/sp-big.result b/mysql-test/main/sp-big.result index e12136eb36d..0a07a3aa7a8 100644 --- a/mysql-test/main/sp-big.result +++ b/mysql-test/main/sp-big.result @@ -77,6 +77,8 @@ select count(*) as cnt from (select id1 from t1 force index (primary) where id1 set id1_cond = id1_cond + 1; end while; end// +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead insert t1 select seq, seq, 1, 1, seq, seq, seq from seq_1_to_2000; set @before=unix_timestamp(); call select_test(); diff --git a/mysql-test/main/sp-bugs.result b/mysql-test/main/sp-bugs.result index a699cd11c5a..3ab3d19ccfb 100644 --- a/mysql-test/main/sp-bugs.result +++ b/mysql-test/main/sp-bugs.result @@ -60,20 +60,6 @@ ERROR HY000: Trigger does not exist DROP TABLE t1; DROP PROCEDURE p1; # -# Bug#50423: Crash on second call of a procedure dropping a trigger -# -DROP TABLE IF EXISTS t1; -DROP TRIGGER IF EXISTS tr1; -DROP PROCEDURE IF EXISTS p1; -CREATE TABLE t1 (f1 INTEGER); -CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @aux = 1; -CREATE PROCEDURE p1 () DROP TRIGGER tr1; -CALL p1 (); -CALL p1 (); -ERROR HY000: Trigger does not exist -DROP TABLE t1; -DROP PROCEDURE p1; -# # Bug#54375: Error in stored procedure leaves connection # in different default schema # diff --git a/mysql-test/main/sp-bugs.test b/mysql-test/main/sp-bugs.test index 2dd70d28249..6695b05b72d 100644 --- a/mysql-test/main/sp-bugs.test +++ b/mysql-test/main/sp-bugs.test @@ -81,27 +81,6 @@ DROP TABLE t1; DROP PROCEDURE p1; --echo # ---echo # Bug#50423: Crash on second call of a procedure dropping a trigger ---echo # - ---disable_warnings -DROP TABLE IF EXISTS t1; -DROP TRIGGER IF EXISTS tr1; -DROP PROCEDURE IF EXISTS p1; ---enable_warnings - -CREATE TABLE t1 (f1 INTEGER); -CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @aux = 1; -CREATE PROCEDURE p1 () DROP TRIGGER tr1; - -CALL p1 (); ---error ER_TRG_DOES_NOT_EXIST -CALL p1 (); - -DROP TABLE t1; -DROP PROCEDURE p1; - ---echo # --echo # Bug#54375: Error in stored procedure leaves connection --echo # in different default schema --echo # diff --git a/mysql-test/main/sp-destruct.test b/mysql-test/main/sp-destruct.test index 8870df29299..12299fa230b 100644 --- a/mysql-test/main/sp-destruct.test +++ b/mysql-test/main/sp-destruct.test @@ -17,8 +17,8 @@ call mtr.add_suppression("Stored routine .test...bug14233_[123].: invalid value let $MYSQLD_DATADIR= `select @@datadir`; flush table mysql.proc; --copy_file $MYSQLD_DATADIR/mysql/proc.frm $MYSQLTEST_VARDIR/tmp/proc.frm ---copy_file $MYSQLD_DATADIR/mysql/proc.MYD $MYSQLTEST_VARDIR/tmp/proc.MYD ---copy_file $MYSQLD_DATADIR/mysql/proc.MYI $MYSQLTEST_VARDIR/tmp/proc.MYI +--copy_file $MYSQLD_DATADIR/mysql/proc.MAD $MYSQLTEST_VARDIR/tmp/proc.MAD +--copy_file $MYSQLD_DATADIR/mysql/proc.MAI $MYSQLTEST_VARDIR/tmp/proc.MAI use test; @@ -70,8 +70,8 @@ flush table mysql.proc; # Drop the mysql.proc table --remove_file $MYSQLD_DATADIR/mysql/proc.frm ---remove_file $MYSQLD_DATADIR/mysql/proc.MYD ---remove_file $MYSQLD_DATADIR/mysql/proc.MYI +--remove_file $MYSQLD_DATADIR/mysql/proc.MAD +--remove_file $MYSQLD_DATADIR/mysql/proc.MAI --error ER_NO_SUCH_TABLE call bug14233(); --error ER_NO_SUCH_TABLE @@ -81,11 +81,11 @@ insert into t1 values (0); # Restore mysql.proc --copy_file $MYSQLTEST_VARDIR/tmp/proc.frm $MYSQLD_DATADIR/mysql/proc.frm ---copy_file $MYSQLTEST_VARDIR/tmp/proc.MYD $MYSQLD_DATADIR/mysql/proc.MYD ---copy_file $MYSQLTEST_VARDIR/tmp/proc.MYI $MYSQLD_DATADIR/mysql/proc.MYI +--copy_file $MYSQLTEST_VARDIR/tmp/proc.MAD $MYSQLD_DATADIR/mysql/proc.MAD +--copy_file $MYSQLTEST_VARDIR/tmp/proc.MAI $MYSQLD_DATADIR/mysql/proc.MAI --remove_file $MYSQLTEST_VARDIR/tmp/proc.frm ---remove_file $MYSQLTEST_VARDIR/tmp/proc.MYD ---remove_file $MYSQLTEST_VARDIR/tmp/proc.MYI +--remove_file $MYSQLTEST_VARDIR/tmp/proc.MAD +--remove_file $MYSQLTEST_VARDIR/tmp/proc.MAI flush table mysql.proc; flush privileges; @@ -233,8 +233,8 @@ drop database if exists mysqltest; flush table mysql.proc; let $MYSQLD_DATADIR= `select @@datadir`; --copy_file $MYSQLD_DATADIR/mysql/proc.frm $MYSQLTEST_VARDIR/tmp/proc.frm ---copy_file $MYSQLD_DATADIR/mysql/proc.MYD $MYSQLTEST_VARDIR/tmp/proc.MYD ---copy_file $MYSQLD_DATADIR/mysql/proc.MYI $MYSQLTEST_VARDIR/tmp/proc.MYI +--copy_file $MYSQLD_DATADIR/mysql/proc.MAD $MYSQLTEST_VARDIR/tmp/proc.MAD +--copy_file $MYSQLD_DATADIR/mysql/proc.MAI $MYSQLTEST_VARDIR/tmp/proc.MAI create database mysqltest; --echo # Corrupt mysql.proc to make it unusable by current version of server. @@ -245,11 +245,11 @@ drop database mysqltest; --echo # Restore mysql.proc. drop table mysql.proc; --copy_file $MYSQLTEST_VARDIR/tmp/proc.frm $MYSQLD_DATADIR/mysql/proc.frm ---copy_file $MYSQLTEST_VARDIR/tmp/proc.MYD $MYSQLD_DATADIR/mysql/proc.MYD ---copy_file $MYSQLTEST_VARDIR/tmp/proc.MYI $MYSQLD_DATADIR/mysql/proc.MYI +--copy_file $MYSQLTEST_VARDIR/tmp/proc.MAD $MYSQLD_DATADIR/mysql/proc.MAD +--copy_file $MYSQLTEST_VARDIR/tmp/proc.MAI $MYSQLD_DATADIR/mysql/proc.MAI --remove_file $MYSQLTEST_VARDIR/tmp/proc.frm ---remove_file $MYSQLTEST_VARDIR/tmp/proc.MYD ---remove_file $MYSQLTEST_VARDIR/tmp/proc.MYI +--remove_file $MYSQLTEST_VARDIR/tmp/proc.MAD +--remove_file $MYSQLTEST_VARDIR/tmp/proc.MAI --echo # diff --git a/mysql-test/main/sp-error.result b/mysql-test/main/sp-error.result index 1a32665c886..3d4e7895fa4 100644 --- a/mysql-test/main/sp-error.result +++ b/mysql-test/main/sp-error.result @@ -1,5 +1,7 @@ drop table if exists t1, t2; SELECT * FROM mysql.proc INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/proc.txt'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead delete from mysql.proc; create procedure syntaxerror(t int)| ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 @@ -12,6 +14,8 @@ create table t3 ( x int )| insert into t3 values (2), (3)| create procedure bad_into(out param int) select x from t3 into param| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead call bad_into(@x)| ERROR 42000: Result consisted of more than one row drop procedure bad_into| @@ -439,6 +443,9 @@ create procedure nodb.bug3339() begin end| ERROR 42000: Unknown database 'nodb' create procedure bug2653_1(a int, out b int) set b = aa| +call bug2653_1(1, @b)| +ERROR 42S22: Unknown column 'aa' in 'field list' +drop procedure bug2653_1| create procedure bug2653_2(a int, out b int) begin if aa < 0 then @@ -447,12 +454,7 @@ else set b = a; end if; end| -call bug2653_1(1, @b)| ERROR 42S22: Unknown column 'aa' in 'field list' -call bug2653_2(2, @b)| -ERROR 42S22: Unknown column 'aa' in 'field list' -drop procedure bug2653_1| -drop procedure bug2653_2| create procedure bug4344() drop procedure bug4344| ERROR HY000: Can't drop or alter a PROCEDURE from within another stored routine create procedure bug4344() drop function bug4344| @@ -1067,6 +1069,7 @@ IF bug13037_foo THEN SELECT 1; END IF; END| +ERROR 42S22: Unknown column 'bug13037_foo' in 'field list' CREATE PROCEDURE bug13037_p2() BEGIN SET @bug13037_foo = bug13037_bar; @@ -1076,19 +1079,14 @@ BEGIN SELECT bug13037_foo; END| -CALL bug13037_p1(); -ERROR 42S22: Unknown column 'bug13037_foo' in 'field list' CALL bug13037_p2(); ERROR 42S22: Unknown column 'bug13037_bar' in 'field list' CALL bug13037_p3(); ERROR 42S22: Unknown column 'bug13037_foo' in 'field list' -CALL bug13037_p1(); -ERROR 42S22: Unknown column 'bug13037_foo' in 'field list' CALL bug13037_p2(); ERROR 42S22: Unknown column 'bug13037_bar' in 'field list' CALL bug13037_p3(); ERROR 42S22: Unknown column 'bug13037_foo' in 'field list' -DROP PROCEDURE bug13037_p1; DROP PROCEDURE bug13037_p2; DROP PROCEDURE bug13037_p3; create database mysqltest1; @@ -2848,6 +2846,8 @@ DECLARE v VARCHAR(5) DEFAULT -1; SELECT b FROM t1 WHERE a = 2 INTO v; RETURN v; END| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Here we check that the NOT_FOUND condition raised in f1() # is not visible in the outer function (f2), i.e. the continue diff --git a/mysql-test/main/sp-error.test b/mysql-test/main/sp-error.test index 0e16948f438..475d677b820 100644 --- a/mysql-test/main/sp-error.test +++ b/mysql-test/main/sp-error.test @@ -608,6 +608,12 @@ create procedure nodb.bug3339() begin end| create procedure bug2653_1(a int, out b int) set b = aa| +--error ER_BAD_FIELD_ERROR +call bug2653_1(1, @b)| + +drop procedure bug2653_1| + +--error ER_BAD_FIELD_ERROR create procedure bug2653_2(a int, out b int) begin if aa < 0 then @@ -617,13 +623,6 @@ begin end if; end| ---error 1054 -call bug2653_1(1, @b)| ---error 1054 -call bug2653_2(2, @b)| - -drop procedure bug2653_1| -drop procedure bug2653_2| # # BUG#4344 @@ -1507,6 +1506,7 @@ DROP PROCEDURE IF EXISTS bug13037_p3; delimiter |; +--error ER_BAD_FIELD_ERROR CREATE PROCEDURE bug13037_p1() BEGIN IF bug13037_foo THEN @@ -1529,20 +1529,15 @@ delimiter ;| --echo --error 1054 -CALL bug13037_p1(); ---error 1054 CALL bug13037_p2(); --error 1054 CALL bug13037_p3(); --error 1054 -CALL bug13037_p1(); ---error 1054 CALL bug13037_p2(); --error 1054 CALL bug13037_p3(); -DROP PROCEDURE bug13037_p1; DROP PROCEDURE bug13037_p2; DROP PROCEDURE bug13037_p3; diff --git a/mysql-test/main/sp-row.result b/mysql-test/main/sp-row.result index da8258d9ec4..4b87798e0bb 100644 --- a/mysql-test/main/sp-row.result +++ b/mysql-test/main/sp-row.result @@ -2135,6 +2135,8 @@ SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: The used SELECT statements have a different number of columns DROP TABLE t1; @@ -2149,6 +2151,8 @@ SELECT * FROM t1 INTO rec1, rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: Operand should contain 2 column(s) DROP TABLE t1; @@ -2163,6 +2167,8 @@ SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); rec1.a rec1.b 10 b10 diff --git a/mysql-test/main/sp-security.result b/mysql-test/main/sp-security.result index 4487528210f..662d52902d0 100644 --- a/mysql-test/main/sp-security.result +++ b/mysql-test/main/sp-security.result @@ -506,9 +506,9 @@ DROP DATABASE mysqltest; GRANT USAGE ON *.* TO user19857@localhost IDENTIFIED BY 'meow'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE ROUTINE, ALTER ROUTINE ON test.* TO user19857@localhost; -SELECT Host,User,Password FROM mysql.user WHERE User='user19857'; -Host User Password -localhost user19857 *82DC221D557298F6CE9961037DB1C90604792F5C +SELECT Host,User,Plugin,Authentication_string FROM mysql.user WHERE User='user19857'; +Host User plugin authentication_string +localhost user19857 mysql_native_password *82DC221D557298F6CE9961037DB1C90604792F5C connect mysqltest_2_con,localhost,user19857,meow,test; connection mysqltest_2_con; USE test; @@ -533,9 +533,9 @@ connection mysqltest_2_con; DROP PROCEDURE IF EXISTS test.sp19857; connection con1root; disconnect mysqltest_2_con; -SELECT Host,User,Password FROM mysql.user WHERE User='user19857'; -Host User Password -localhost user19857 *82DC221D557298F6CE9961037DB1C90604792F5C +SELECT Host,User,Plugin,Authentication_string FROM mysql.user WHERE User='user19857'; +Host User plugin authentication_string +localhost user19857 mysql_native_password *82DC221D557298F6CE9961037DB1C90604792F5C DROP USER user19857@localhost; disconnect con1root; connection default; @@ -711,9 +711,7 @@ disconnect con2; DROP USER user2@localhost; DROP DATABASE db1; create user foo@local_ost; -create user foo@`local\_ost`; -update mysql.user set plugin='foobar' where host='local\\_ost'; -flush privileges; +create user foo@`local\_ost` identified via mysql_old_password using '0123456789ABCDEF'; create database foodb; grant create routine on foodb.* to foo@local_ost; connect con1,localhost,foo; @@ -767,21 +765,23 @@ connection default; disconnect conn1; drop user bug12602983_user@localhost; drop database mysqltest_db; +create user u1@localhost; +grant all privileges on *.* to u1@localhost with grant option; +connect u1, localhost, u1; set password=password('foobar'); create procedure sp1() select 1; show grants; -Grants for root@localhost -GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*9B500343BC52E2911172EB52AE5CF4847604C6E5' WITH GRANT OPTION -GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION +Grants for u1@localhost +GRANT ALL PRIVILEGES ON *.* TO 'u1'@'localhost' IDENTIFIED BY PASSWORD '*9B500343BC52E2911172EB52AE5CF4847604C6E5' WITH GRANT OPTION grant execute on procedure sp1 to current_user() identified by 'barfoo'; show grants; -Grants for root@localhost -GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*343915A8181B5728EADBDC73E1F7E6B0C3998483' WITH GRANT OPTION -GRANT EXECUTE ON PROCEDURE `test`.`sp1` TO 'root'@'localhost' -GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION +Grants for u1@localhost +GRANT ALL PRIVILEGES ON *.* TO 'u1'@'localhost' IDENTIFIED BY PASSWORD '*343915A8181B5728EADBDC73E1F7E6B0C3998483' WITH GRANT OPTION +GRANT EXECUTE ON PROCEDURE `test`.`sp1` TO 'u1'@'localhost' drop procedure sp1; -set password=''; -update mysql.user set plugin=''; +disconnect u1; +connection default; +drop user u1@localhost; # # MDEV-13396 Unexpected "alter routine comand defined" during CREATE OR REPLACE PROCEDURE # diff --git a/mysql-test/main/sp-security.test b/mysql-test/main/sp-security.test index 4f645ce2cd3..7a87fae4097 100644 --- a/mysql-test/main/sp-security.test +++ b/mysql-test/main/sp-security.test @@ -742,7 +742,7 @@ DROP DATABASE mysqltest; GRANT USAGE ON *.* TO user19857@localhost IDENTIFIED BY 'meow'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE ROUTINE, ALTER ROUTINE ON test.* TO user19857@localhost; -SELECT Host,User,Password FROM mysql.user WHERE User='user19857'; +SELECT Host,User,Plugin,Authentication_string FROM mysql.user WHERE User='user19857'; --connect (mysqltest_2_con,localhost,user19857,meow,test) --connection mysqltest_2_con @@ -770,7 +770,7 @@ DROP PROCEDURE IF EXISTS test.sp19857; --disconnect mysqltest_2_con -SELECT Host,User,Password FROM mysql.user WHERE User='user19857'; +SELECT Host,User,Plugin,Authentication_string FROM mysql.user WHERE User='user19857'; DROP USER user19857@localhost; @@ -977,16 +977,7 @@ DROP DATABASE db1; # Bug#27407480: AUTOMATIC_SP_PRIVILEGES REQUIRES NEED THE INSERT PRIVILEGES FOR MYSQL.USER TABLE # create user foo@local_ost; -# -# Create a user with an authentification plugin 'foobar'. -# Instead of using a normal "CREATE USER <user> IDENTIFIED VIA <plugin>" -# we do CREATE (without VIA) followed by UPDATE and FLUSH. -# This is to avoid installing a real plugin and thus avoid the test dependency. -# We won't login under this user in the below test, so this is fine. -# -create user foo@`local\_ost`; -update mysql.user set plugin='foobar' where host='local\\_ost'; -flush privileges; +create user foo@`local\_ost` identified via mysql_old_password using '0123456789ABCDEF'; create database foodb; grant create routine on foodb.* to foo@local_ost; connect con1,localhost,foo; @@ -1044,15 +1035,18 @@ drop database mysqltest_db; # Wait till all disconnects are completed --source include/wait_until_count_sessions.inc +create user u1@localhost; +grant all privileges on *.* to u1@localhost with grant option; +connect u1, localhost, u1; set password=password('foobar'); create procedure sp1() select 1; show grants; grant execute on procedure sp1 to current_user() identified by 'barfoo'; show grants; drop procedure sp1; -set password=''; -#cleanup after MDEV-16238 -update mysql.user set plugin=''; +disconnect u1; +connection default; +drop user u1@localhost; --echo # --echo # MDEV-13396 Unexpected "alter routine comand defined" during CREATE OR REPLACE PROCEDURE diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 64668e0c8ec..b110ab670ae 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -314,10 +314,12 @@ delete from t1| drop procedure b| drop procedure if exists b2| create procedure b2(x int) -repeat(select 1 into outfile 'b2'); +repeat(select 1) into outfile 'b2'; insert into test.t1 values (repeat("b2",3), x); set x = x-1; until x = 0 end repeat| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead drop procedure b2| drop procedure if exists c| create procedure c(x int) @@ -2291,9 +2293,11 @@ create procedure bug3843() analyze table t1| call bug3843()| Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK call bug3843()| Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date select 1+2| 1+2 @@ -2440,7 +2444,7 @@ drop procedure if exists bug4904| create procedure bug4904() begin declare continue handler for sqlstate 'HY000' begin end; -create table t2 as select * from t3; +create table not_existing_table as select * from t3; end| call bug4904()| ERROR 42S02: Table 'test.t3' doesn't exist @@ -4179,6 +4183,7 @@ select v, isnull(v); end if; end; end| +ERROR 42S22: Unknown column 'undefined_var' in 'field list' create procedure bug14643_2() begin declare continue handler for sqlexception select 'boo' as 'Handler'; @@ -4190,18 +4195,7 @@ select 2; end case; select undefined_var; end| -call bug14643_1()| -Handler -boo -v isnull(v) -NULL 1 -call bug14643_2()| -Handler -boo -Handler -boo -drop procedure bug14643_1| -drop procedure bug14643_2| +ERROR 42S22: Unknown column 'undefined_var' in 'field list' drop procedure if exists bug14304| drop table if exists t3, t4| create table t3(a int primary key auto_increment)| @@ -4231,9 +4225,7 @@ create procedure bug14376() begin declare x int default x; end| -call bug14376()| ERROR 42S22: Unknown column 'x' in 'field list' -drop procedure bug14376| create procedure bug14376() begin declare x int default 42; @@ -4290,6 +4282,9 @@ select i as 'A local variable in a nested compound statement takes precedence o end; end; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead call bug5967("a - stored procedure parameter")| a a - stored procedure parameter @@ -4338,8 +4333,11 @@ test.t3 optimize status OK test.v1 optimize Error 'test.v1' is not of type 'BASE TABLE' test.v1 optimize status Operation failed Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status Table is already up to date test.v1 analyze Error 'test.v1' is not of type 'BASE TABLE' test.v1 analyze status Operation failed @@ -4357,8 +4355,11 @@ test.t3 optimize status OK test.v1 optimize Error 'test.v1' is not of type 'BASE TABLE' test.v1 optimize status Operation failed Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status Table is already up to date test.v1 analyze Error 'test.v1' is not of type 'BASE TABLE' test.v1 analyze status Operation failed @@ -4376,8 +4377,11 @@ test.t3 optimize status OK test.v1 optimize Error 'test.v1' is not of type 'BASE TABLE' test.v1 optimize status Operation failed Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status Table is already up to date test.v1 analyze Error 'test.v1' is not of type 'BASE TABLE' test.v1 analyze status Operation failed @@ -4476,6 +4480,7 @@ select 'no' as 'v'; end if; select 'done' as 'End'; end| +ERROR 42S22: Unknown column 'v' in 'field list' create procedure bug14498_2() begin declare continue handler for sqlexception select 'error' as 'Handler'; @@ -4484,6 +4489,7 @@ select 'yes' as 'v'; end while; select 'done' as 'End'; end| +ERROR 42S22: Unknown column 'v' in 'field list' create procedure bug14498_3() begin declare continue handler for sqlexception select 'error' as 'Handler'; @@ -4492,6 +4498,7 @@ select 'maybe' as 'v'; until v end repeat; select 'done' as 'End'; end| +ERROR 42S22: Unknown column 'v' in 'field list' create procedure bug14498_4() begin declare continue handler for sqlexception select 'error' as 'Handler'; @@ -4505,6 +4512,7 @@ select '?' as 'v'; end case; select 'done' as 'End'; end| +ERROR 42S22: Unknown column 'v' in 'field list' create procedure bug14498_5() begin declare continue handler for sqlexception select 'error' as 'Handler'; @@ -4518,38 +4526,7 @@ select '?' as 'v'; end case; select 'done' as 'End'; end| -call bug14498_1()| -Handler -error -End -done -call bug14498_2()| -Handler -error -End -done -call bug14498_3()| -v -maybe -Handler -error -End -done -call bug14498_4()| -Handler -error -End -done -call bug14498_5()| -Handler -error -End -done -drop procedure bug14498_1| -drop procedure bug14498_2| -drop procedure bug14498_3| -drop procedure bug14498_4| -drop procedure bug14498_5| +ERROR 42S22: Unknown column 'v' in 'field list' drop table if exists t3| drop procedure if exists bug15231_1| drop procedure if exists bug15231_2| @@ -5797,6 +5774,8 @@ end; select 1 from no_such_view limit 1 into x; return x; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create function func_8407_b() returns int begin declare x int default 0; @@ -8356,14 +8335,12 @@ DECLARE name VARCHAR(10); SET name="hello"; call p1(name2); END| +ERROR 42S22: Unknown column 'name2' in 'field list' call p2(); a hello -call p3(); -ERROR 42S22: Unknown column 'name2' in 'field list' drop procedure p1; drop procedure p2; -drop procedure p3; # # MDEV-15328: MariaDB 10.2.13 Crashes upon CALL PROCEDURE PARAM # LAST_INSERT_ID () @@ -8593,11 +8570,11 @@ RETURN a = timestamp'2038-01-19 03:14:07.999999' END $$ SELECT f1(e) FROM t1; -ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30' +ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30.000000' SELECT f2(e) FROM t1; -ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30' +ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30.000000' SELECT f3(e) FROM t1; -ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30' +ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30.000000' DROP FUNCTION f1; DROP FUNCTION f2; DROP FUNCTION f3; diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index 72e6ad6bcba..721855895c7 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -440,7 +440,7 @@ drop procedure b| drop procedure if exists b2| --enable_warnings create procedure b2(x int) -repeat(select 1 into outfile 'b2'); +repeat(select 1) into outfile 'b2'; insert into test.t1 values (repeat("b2",3), x); set x = x-1; until x = 0 end repeat| @@ -2918,7 +2918,7 @@ create procedure bug4904() begin declare continue handler for sqlstate 'HY000' begin end; - create table t2 as select * from t3; + create table not_existing_table as select * from t3; end| -- error 1146 @@ -5040,6 +5040,7 @@ drop procedure if exists bug14643_1| drop procedure if exists bug14643_2| --enable_warnings +--error ER_BAD_FIELD_ERROR create procedure bug14643_1() begin declare continue handler for sqlexception select 'boo' as 'Handler'; @@ -5055,6 +5056,7 @@ begin end; end| +--error ER_BAD_FIELD_ERROR create procedure bug14643_2() begin declare continue handler for sqlexception select 'boo' as 'Handler'; @@ -5069,11 +5071,6 @@ begin select undefined_var; end| -call bug14643_1()| -call bug14643_2()| - -drop procedure bug14643_1| -drop procedure bug14643_2| # # BUG#14304: auto_increment field incorrect set in SP @@ -5114,15 +5111,12 @@ drop table t3, t4| drop procedure if exists bug14376| --enable_warnings +--error ER_BAD_FIELD_ERROR create procedure bug14376() begin declare x int default x; end| -# Not the error we want, but that's what we got for now... ---error ER_BAD_FIELD_ERROR -call bug14376()| -drop procedure bug14376| create procedure bug14376() begin @@ -5344,6 +5338,7 @@ drop procedure if exists bug14498_4| drop procedure if exists bug14498_5| --enable_warnings +--error ER_BAD_FIELD_ERROR create procedure bug14498_1() begin declare continue handler for sqlexception select 'error' as 'Handler'; @@ -5356,6 +5351,7 @@ begin select 'done' as 'End'; end| +--error ER_BAD_FIELD_ERROR create procedure bug14498_2() begin declare continue handler for sqlexception select 'error' as 'Handler'; @@ -5366,6 +5362,7 @@ begin select 'done' as 'End'; end| +--error ER_BAD_FIELD_ERROR create procedure bug14498_3() begin declare continue handler for sqlexception select 'error' as 'Handler'; @@ -5376,6 +5373,7 @@ begin select 'done' as 'End'; end| +--error ER_BAD_FIELD_ERROR create procedure bug14498_4() begin declare continue handler for sqlexception select 'error' as 'Handler'; @@ -5391,6 +5389,7 @@ begin select 'done' as 'End'; end| +--error ER_BAD_FIELD_ERROR create procedure bug14498_5() begin declare continue handler for sqlexception select 'error' as 'Handler'; @@ -5406,17 +5405,6 @@ begin select 'done' as 'End'; end| -call bug14498_1()| -call bug14498_2()| -call bug14498_3()| -call bug14498_4()| -call bug14498_5()| - -drop procedure bug14498_1| -drop procedure bug14498_2| -drop procedure bug14498_3| -drop procedure bug14498_4| -drop procedure bug14498_5| # # BUG#15231: Stored procedure bug with not found condition handler @@ -9863,6 +9851,8 @@ BEGIN SET name="hello"; call p1(name); END| + +--error ER_BAD_FIELD_ERROR CREATE OR REPLACE PROCEDURE p3 () BEGIN DECLARE name VARCHAR(10); @@ -9873,11 +9863,8 @@ END| DELIMITER ;| call p2(); ---error ER_BAD_FIELD_ERROR -call p3(); drop procedure p1; drop procedure p2; -drop procedure p3; --echo # --echo # MDEV-15328: MariaDB 10.2.13 Crashes upon CALL PROCEDURE PARAM diff --git a/mysql-test/main/sp_notembedded.result b/mysql-test/main/sp_notembedded.result index 8edb9e79b70..3883225e9bc 100644 --- a/mysql-test/main/sp_notembedded.result +++ b/mysql-test/main/sp_notembedded.result @@ -231,8 +231,6 @@ CREATE PROCEDURE p1(i INT) BEGIN END; disconnect con1; connection default; DROP PROCEDURE p1; -DELETE FROM mysql.user WHERE User='mysqltest_1'; -FLUSH PRIVILEGES; # # Bug#44521 Prepared Statement: CALL p() - crashes: `! thd->main_da.is_sent' failed et.al. # @@ -324,7 +322,7 @@ DROP EVENT teste_bug11763507; # -- End of 5.1 tests # ------------------------------------------------------------------ grant create routine on test.* to foo1@localhost identified by 'foo'; -update mysql.user set password = replace(password, '*', '-') where user='foo1'; +update mysql.user set authentication_string = replace(authentication_string, '*', '-') where user='foo1'; connect foo,localhost,foo1,foo; show grants; Grants for foo1@localhost diff --git a/mysql-test/main/sp_notembedded.test b/mysql-test/main/sp_notembedded.test index 41bfd871c39..2f1c4cd92f5 100644 --- a/mysql-test/main/sp_notembedded.test +++ b/mysql-test/main/sp_notembedded.test @@ -305,6 +305,7 @@ set session low_priority_updates=default; # # Bug#44798 MySQL engine crashes when creating stored procedures with execute_priv=N # +--source include/switch_to_mysql_user.inc INSERT IGNORE INTO mysql.user (Host, User, Password, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv, Reload_priv, Shutdown_priv, Process_priv, File_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Show_db_priv, Super_priv, @@ -323,10 +324,7 @@ CREATE PROCEDURE p1(i INT) BEGIN END; disconnect con1; connection default; DROP PROCEDURE p1; - -DELETE FROM mysql.user WHERE User='mysqltest_1'; -FLUSH PRIVILEGES; - +--source include/switch_to_mysql_global_priv.inc --echo # --echo # Bug#44521 Prepared Statement: CALL p() - crashes: `! thd->main_da.is_sent' failed et.al. @@ -464,8 +462,9 @@ DROP EVENT teste_bug11763507; # A case of SHOW GRANTS # (creating a new procedure changes the password) # +--source include/switch_to_mysql_user.inc grant create routine on test.* to foo1@localhost identified by 'foo'; -update mysql.user set password = replace(password, '*', '-') where user='foo1'; +update mysql.user set authentication_string = replace(authentication_string, '*', '-') where user='foo1'; --connect (foo,localhost,foo1,foo) show grants; --connection default @@ -479,6 +478,7 @@ show grants; --disconnect foo drop procedure spfoo; drop user foo1@localhost; +--source include/switch_to_mysql_global_priv.inc # # Restore global concurrent_insert value. Keep in the end of the test file. diff --git a/mysql-test/main/sp_trans.result b/mysql-test/main/sp_trans.result index ef802279c9c..dad1aa7c0ff 100644 --- a/mysql-test/main/sp_trans.result +++ b/mysql-test/main/sp_trans.result @@ -506,6 +506,8 @@ insert into t3 select a from t3; select count(*)*255 from t3 into table_size; until table_size > max_table_size*2 end repeat; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead call bug14210_fill_table()| drop procedure bug14210_fill_table| create table t4 like t3| diff --git a/mysql-test/main/sp_trans_log.result b/mysql-test/main/sp_trans_log.result index b72e8332fad..adc9eafc370 100644 --- a/mysql-test/main/sp_trans_log.result +++ b/mysql-test/main/sp_trans_log.result @@ -11,6 +11,8 @@ insert into t1 values (null); select count(*) from t1 into @a; return @a; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead reset master; insert into t2 values (bug23333(),1); ERROR 23000: Duplicate entry '1' for key 'PRIMARY' diff --git a/mysql-test/main/sql_mode.result b/mysql-test/main/sql_mode.result index 238bae2efd8..25a90703bf5 100644 --- a/mysql-test/main/sql_mode.result +++ b/mysql-test/main/sql_mode.result @@ -476,10 +476,14 @@ select @@sql_mode; @@sql_mode REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI set sql_mode=2147483648*2*2*2; -ERROR 42000: Variable 'sql_mode' can't be set to the value of '17179869184' select @@sql_mode; @@sql_mode -REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_TABLE_OPTIONS,ANSI +TIME_ROUND_FRACTIONAL +set sql_mode=2147483648*2*2*2*2; +ERROR 42000: Variable 'sql_mode' can't be set to the value of '34359738368' +select @@sql_mode; +@@sql_mode +TIME_ROUND_FRACTIONAL set sql_mode=PAD_CHAR_TO_FULL_LENGTH; create table t1 (a int auto_increment primary key, b char(5)); insert into t1 (b) values('a'),('b\t'),('c '); diff --git a/mysql-test/main/sql_mode.test b/mysql-test/main/sql_mode.test index 8cf50f73f6f..97f5cf42791 100644 --- a/mysql-test/main/sql_mode.test +++ b/mysql-test/main/sql_mode.test @@ -263,8 +263,10 @@ set sql_mode=4194304; select @@sql_mode; set sql_mode=16384+(65536*4); select @@sql_mode; +set sql_mode=2147483648*2*2*2; +select @@sql_mode; --error 1231 -set sql_mode=2147483648*2*2*2; # that mode does not exist +set sql_mode=2147483648*2*2*2*2; # that mode does not exist select @@sql_mode; # diff --git a/mysql-test/main/stat_tables.result b/mysql-test/main/stat_tables.result index 3ebc3b47833..db550c1c80e 100644 --- a/mysql-test/main/stat_tables.result +++ b/mysql-test/main/stat_tables.result @@ -64,12 +64,12 @@ and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01' group by n_name order by revenue desc; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE orders range PRIMARY,i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 179 Using where; Using temporary; Using filesort -1 SIMPLE customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where -1 SIMPLE nation eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.customer.c_nationkey 1 -1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) +1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using temporary; Using filesort +1 SIMPLE nation ref PRIMARY,i_n_regionkey i_n_regionkey 5 dbt3_s001.region.r_regionkey 5 +1 SIMPLE supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 SIMPLE customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 SIMPLE orders ref PRIMARY,i_o_orderdate,i_o_custkey i_o_custkey 5 dbt3_s001.customer.c_custkey 15 Using where 1 SIMPLE lineitem ref PRIMARY,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where -1 SIMPLE supplier eq_ref PRIMARY,i_s_nationkey PRIMARY 4 dbt3_s001.lineitem.l_suppkey 1 Using where select n_name, sum(l_extendedprice * (1 - l_discount)) as revenue from customer, orders, lineitem, supplier, nation, region where c_custkey = o_custkey and l_orderkey = o_orderkey @@ -80,7 +80,7 @@ and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01' group by n_name order by revenue desc; n_name revenue -PERU 321915.8715 +PERU 321915.87150000007 ARGENTINA 69817.1451 set optimizer_switch=@save_optimizer_switch; delete from mysql.index_stats; @@ -171,12 +171,12 @@ and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01' group by n_name order by revenue desc; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE orders range PRIMARY,i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 179 Using where; Using temporary; Using filesort -1 SIMPLE customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where -1 SIMPLE nation eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.customer.c_nationkey 1 -1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) +1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using temporary; Using filesort +1 SIMPLE nation ref PRIMARY,i_n_regionkey i_n_regionkey 5 dbt3_s001.region.r_regionkey 5 +1 SIMPLE supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 +1 SIMPLE customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 +1 SIMPLE orders ref PRIMARY,i_o_orderdate,i_o_custkey i_o_custkey 5 dbt3_s001.customer.c_custkey 15 Using where 1 SIMPLE lineitem ref PRIMARY,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where -1 SIMPLE supplier eq_ref PRIMARY,i_s_nationkey PRIMARY 4 dbt3_s001.lineitem.l_suppkey 1 Using where select n_name, sum(l_extendedprice * (1 - l_discount)) as revenue from customer, orders, lineitem, supplier, nation, region where c_custkey = o_custkey and l_orderkey = o_orderkey @@ -187,7 +187,7 @@ and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01' group by n_name order by revenue desc; n_name revenue -PERU 321915.8715 +PERU 321915.87150000007 ARGENTINA 69817.1451 set optimizer_switch=@save_optimizer_switch; EXPLAIN select o_year, @@ -207,14 +207,14 @@ and o_orderdate between date '1995-01-01' and date '1996-12-31' group by o_year order by o_year; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE orders ALL PRIMARY,i_o_orderdate,i_o_custkey NULL NULL NULL 1500 Using where; Using temporary; Using filesort -1 SIMPLE customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where -1 SIMPLE n1 eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.customer.c_nationkey 1 -1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) -1 SIMPLE lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where -1 SIMPLE part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where +1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using temporary; Using filesort +1 SIMPLE part ALL PRIMARY NULL NULL NULL 200 Using where; Using join buffer (flat, BNL join) +1 SIMPLE lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey_partkey 5 dbt3_s001.part.p_partkey 30 Using index condition 1 SIMPLE supplier eq_ref PRIMARY,i_s_nationkey PRIMARY 4 dbt3_s001.lineitem.l_suppkey 1 Using where 1 SIMPLE n2 eq_ref PRIMARY PRIMARY 4 dbt3_s001.supplier.s_nationkey 1 +1 SIMPLE orders eq_ref PRIMARY,i_o_orderdate,i_o_custkey PRIMARY 4 dbt3_s001.lineitem.l_orderkey 1 Using where +1 SIMPLE customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 +1 SIMPLE n1 ref PRIMARY,i_n_regionkey i_n_regionkey 5 dbt3_s001.region.r_regionkey 5 Using where select o_year, sum(case when nation = 'UNITED STATES' then volume else 0 end) / sum(volume) as mkt_share @@ -587,7 +587,7 @@ explain SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE PROFILING ALL NULL NULL NULL NULL NULL -1 SIMPLE user ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join) +1 SIMPLE global_priv ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join) set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set use_stat_tables=@save_use_stat_tables; # @@ -625,3 +625,59 @@ MAX(pk) NULL DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; +# +# MDEV-17255: New optimizer defaults and ANALYZE TABLE +# +create table t1 (a int, b int); +insert into t1(a,b) values (1,2),(1,3),(1,4),(1,5),(2,6),(2,7),(3,8),(3,9),(3,9),(4,10); +set use_stat_tables= preferably_for_queries; +# +# with use_stat_tables= PREFERABLY_FOR_QUERIES +# analyze table t1 will not collect statistics +# +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +select * from mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +analyze +select * from t1 where a = 1 and b=3; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10.00 100.00 10.00 Using where +# +# with use_stat_tables= PREFERABLY_FOR_QUERIES +# analyze table t1 will collect statistics if we use PERSISTENT +# for columns, indexes or everything +# +analyze table t1 persistent for columns (a) indexes (); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +select * from mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 a 1 4 0.0000 4.0000 2.5000 0 NULL NULL +# filtered shows that we used the data from stat tables +analyze +select * from t1 where a = 1 and b=3; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10.00 25.00 10.00 Using where +# +# with use_stat_tables= PREFERABLY +# analyze table t1 will collect statistics +# +set use_stat_tables=PREFERABLY; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +select * from mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 a 1 4 0.0000 4.0000 2.5000 0 NULL NULL +test t1 b 2 10 0.0000 4.0000 1.1111 0 NULL NULL +# filtered shows that we used the data from stat tables +analyze +select * from t1 where a=1 and b=3; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10.00 2.78 10.00 Using where +drop table t1; +set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/main/stat_tables.test b/mysql-test/main/stat_tables.test index b89ab2bbd2d..2c1d53a2583 100644 --- a/mysql-test/main/stat_tables.test +++ b/mysql-test/main/stat_tables.test @@ -191,7 +191,7 @@ FLUSH TABLE t1; SET use_stat_tables='never'; EXPLAIN SELECT * FROM t1; ---move_file $MYSQLTEST_VARDIR/mysqld.1/data/mysql/table_stats.MYD $MYSQLTEST_VARDIR/mysqld.1/data/mysql/table_stats.MYD.save +--move_file $MYSQLTEST_VARDIR/mysqld.1/data/mysql/table_stats.MAD $MYSQLTEST_VARDIR/mysqld.1/data/mysql/table_stats.MAD.save FLUSH TABLES; SET use_stat_tables='preferably'; @@ -200,7 +200,7 @@ EXPLAIN SELECT * FROM t1; --enable_warnings # Cleanup ---move_file $MYSQLTEST_VARDIR/mysqld.1/data/mysql/table_stats.MYD.save $MYSQLTEST_VARDIR/mysqld.1/data/mysql/table_stats.MYD +--move_file $MYSQLTEST_VARDIR/mysqld.1/data/mysql/table_stats.MAD.save $MYSQLTEST_VARDIR/mysqld.1/data/mysql/table_stats.MAD DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; @@ -400,5 +400,47 @@ CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT); SELECT MAX(pk) FROM t1; DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; + +--echo # +--echo # MDEV-17255: New optimizer defaults and ANALYZE TABLE +--echo # + +create table t1 (a int, b int); +insert into t1(a,b) values (1,2),(1,3),(1,4),(1,5),(2,6),(2,7),(3,8),(3,9),(3,9),(4,10); +set use_stat_tables= preferably_for_queries; +--echo # +--echo # with use_stat_tables= PREFERABLY_FOR_QUERIES +--echo # analyze table t1 will not collect statistics +--echo # + +analyze table t1; +select * from mysql.column_stats; +analyze +select * from t1 where a = 1 and b=3; +--echo # +--echo # with use_stat_tables= PREFERABLY_FOR_QUERIES +--echo # analyze table t1 will collect statistics if we use PERSISTENT +--echo # for columns, indexes or everything +--echo # + +analyze table t1 persistent for columns (a) indexes (); +select * from mysql.column_stats; +--echo # filtered shows that we used the data from stat tables +analyze +select * from t1 where a = 1 and b=3; + +--echo # +--echo # with use_stat_tables= PREFERABLY +--echo # analyze table t1 will collect statistics +--echo # + +set use_stat_tables=PREFERABLY; +analyze table t1; +select * from mysql.column_stats; +--echo # filtered shows that we used the data from stat tables +analyze +select * from t1 where a=1 and b=3; +drop table t1; set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/main/stat_tables_disabled.result b/mysql-test/main/stat_tables_disabled.result index f57abc34e0c..f2207592f98 100644 --- a/mysql-test/main/stat_tables_disabled.result +++ b/mysql-test/main/stat_tables_disabled.result @@ -1,10 +1,10 @@ SET SESSION STORAGE_ENGINE='InnoDB'; select @@global.use_stat_tables; @@global.use_stat_tables -NEVER +PREFERABLY select @@session.use_stat_tables; @@session.use_stat_tables -NEVER +PREFERABLY set @save_use_stat_tables=@@use_stat_tables; set use_stat_tables='preferably'; DROP DATABASE IF EXISTS dbt3_s001; diff --git a/mysql-test/main/stat_tables_innodb.result b/mysql-test/main/stat_tables_innodb.result index a6c5525a0d3..c8b18f05876 100644 --- a/mysql-test/main/stat_tables_innodb.result +++ b/mysql-test/main/stat_tables_innodb.result @@ -67,11 +67,11 @@ and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01' group by n_name order by revenue desc; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE orders range PRIMARY,i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 213 Using where; Using temporary; Using filesort -1 SIMPLE customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where -1 SIMPLE nation eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.customer.c_nationkey 1 -1 SIMPLE supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.customer.c_nationkey 1 Using index -1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) +1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using temporary; Using filesort +1 SIMPLE nation ref PRIMARY,i_n_regionkey i_n_regionkey 5 dbt3_s001.region.r_regionkey 5 +1 SIMPLE supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 Using index +1 SIMPLE customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 Using index +1 SIMPLE orders ref PRIMARY,i_o_orderdate,i_o_custkey i_o_custkey 5 dbt3_s001.customer.c_custkey 15 Using where 1 SIMPLE lineitem ref PRIMARY,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where select n_name, sum(l_extendedprice * (1 - l_discount)) as revenue from customer, orders, lineitem, supplier, nation, region @@ -83,7 +83,7 @@ and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01' group by n_name order by revenue desc; n_name revenue -PERU 321915.8715 +PERU 321915.87150000007 ARGENTINA 69817.1451 set optimizer_switch=@save_optimizer_switch; delete from mysql.index_stats; @@ -198,11 +198,11 @@ and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01' group by n_name order by revenue desc; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE orders range PRIMARY,i_o_orderdate,i_o_custkey i_o_orderdate 4 NULL 213 Using where; Using temporary; Using filesort -1 SIMPLE customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where -1 SIMPLE nation eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.customer.c_nationkey 1 -1 SIMPLE supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.customer.c_nationkey 1 Using index -1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) +1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using temporary; Using filesort +1 SIMPLE nation ref PRIMARY,i_n_regionkey i_n_regionkey 5 dbt3_s001.region.r_regionkey 5 +1 SIMPLE supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 Using index +1 SIMPLE customer ref PRIMARY,i_c_nationkey i_c_nationkey 5 dbt3_s001.nation.n_nationkey 6 Using index +1 SIMPLE orders ref PRIMARY,i_o_orderdate,i_o_custkey i_o_custkey 5 dbt3_s001.customer.c_custkey 15 Using where 1 SIMPLE lineitem ref PRIMARY,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where select n_name, sum(l_extendedprice * (1 - l_discount)) as revenue from customer, orders, lineitem, supplier, nation, region @@ -214,7 +214,7 @@ and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01' group by n_name order by revenue desc; n_name revenue -PERU 321915.8715 +PERU 321915.87150000007 ARGENTINA 69817.1451 set optimizer_switch=@save_optimizer_switch; EXPLAIN select o_year, @@ -234,14 +234,14 @@ and o_orderdate between date '1995-01-01' and date '1996-12-31' group by o_year order by o_year; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE orders ALL PRIMARY,i_o_orderdate,i_o_custkey NULL NULL NULL 1500 Using where; Using temporary; Using filesort -1 SIMPLE customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where -1 SIMPLE n1 eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.customer.c_nationkey 1 -1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) -1 SIMPLE lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where -1 SIMPLE part eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_partkey 1 Using where +1 SIMPLE region ALL PRIMARY NULL NULL NULL 5 Using where; Using temporary; Using filesort +1 SIMPLE part ALL PRIMARY NULL NULL NULL 200 Using where; Using join buffer (flat, BNL join) +1 SIMPLE lineitem ref PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity i_l_suppkey_partkey 5 dbt3_s001.part.p_partkey 30 Using index condition 1 SIMPLE supplier eq_ref PRIMARY,i_s_nationkey PRIMARY 4 dbt3_s001.lineitem.l_suppkey 1 Using where 1 SIMPLE n2 eq_ref PRIMARY PRIMARY 4 dbt3_s001.supplier.s_nationkey 1 +1 SIMPLE orders eq_ref PRIMARY,i_o_orderdate,i_o_custkey PRIMARY 4 dbt3_s001.lineitem.l_orderkey 1 Using where +1 SIMPLE customer eq_ref PRIMARY,i_c_nationkey PRIMARY 4 dbt3_s001.orders.o_custkey 1 Using where +1 SIMPLE n1 eq_ref PRIMARY,i_n_regionkey PRIMARY 4 dbt3_s001.customer.c_nationkey 1 Using where select o_year, sum(case when nation = 'UNITED STATES' then volume else 0 end) / sum(volume) as mkt_share @@ -614,7 +614,7 @@ explain SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE PROFILING ALL NULL NULL NULL NULL NULL -1 SIMPLE user ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join) +1 SIMPLE global_priv ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join) set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set use_stat_tables=@save_use_stat_tables; # @@ -652,5 +652,61 @@ MAX(pk) NULL DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; +# +# MDEV-17255: New optimizer defaults and ANALYZE TABLE +# +create table t1 (a int, b int); +insert into t1(a,b) values (1,2),(1,3),(1,4),(1,5),(2,6),(2,7),(3,8),(3,9),(3,9),(4,10); +set use_stat_tables= preferably_for_queries; +# +# with use_stat_tables= PREFERABLY_FOR_QUERIES +# analyze table t1 will not collect statistics +# +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +select * from mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +analyze +select * from t1 where a = 1 and b=3; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10.00 100.00 10.00 Using where +# +# with use_stat_tables= PREFERABLY_FOR_QUERIES +# analyze table t1 will collect statistics if we use PERSISTENT +# for columns, indexes or everything +# +analyze table t1 persistent for columns (a) indexes (); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select * from mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 a 1 4 0.0000 4.0000 2.5000 0 NULL NULL +# filtered shows that we used the data from stat tables +analyze +select * from t1 where a = 1 and b=3; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10.00 25.00 10.00 Using where +# +# with use_stat_tables= PREFERABLY +# analyze table t1 will collect statistics +# +set use_stat_tables=PREFERABLY; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select * from mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 a 1 4 0.0000 4.0000 2.5000 0 NULL NULL +test t1 b 2 10 0.0000 4.0000 1.1111 0 NULL NULL +# filtered shows that we used the data from stat tables +analyze +select * from t1 where a=1 and b=3; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10.00 2.78 10.00 Using where +drop table t1; +set use_stat_tables=@save_use_stat_tables; set optimizer_switch=@save_optimizer_switch_for_stat_tables_test; SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/mysql-test/main/stat_tables_rbr.result b/mysql-test/main/stat_tables_rbr.result index 7ae7ade4398..130d1f6da9a 100644 --- a/mysql-test/main/stat_tables_rbr.result +++ b/mysql-test/main/stat_tables_rbr.result @@ -1,15 +1,15 @@ # # Bug mdev-463: assertion failure when running ANALYZE with RBR on # -SET GLOBAL use_stat_tables = PREFERABLY; connect con1,localhost,root,,; CREATE TABLE t1 (i INT) ENGINE=InnoDB; +set use_stat_tables= PREFERABLY; ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; -SET GLOBAL use_stat_tables = DEFAULT; +SET use_stat_tables = DEFAULT; disconnect con1; connection default; SET use_stat_tables = PREFERABLY; diff --git a/mysql-test/main/stat_tables_rbr.test b/mysql-test/main/stat_tables_rbr.test index 29f7c4e6622..1b6a9603743 100644 --- a/mysql-test/main/stat_tables_rbr.test +++ b/mysql-test/main/stat_tables_rbr.test @@ -6,15 +6,14 @@ --echo # Bug mdev-463: assertion failure when running ANALYZE with RBR on --echo # -SET GLOBAL use_stat_tables = PREFERABLY; - --connect (con1,localhost,root,,) CREATE TABLE t1 (i INT) ENGINE=InnoDB; +set use_stat_tables= PREFERABLY; ANALYZE TABLE t1; # Cleanup DROP TABLE t1; -SET GLOBAL use_stat_tables = DEFAULT; +SET use_stat_tables = DEFAULT; --disconnect con1 --connection default diff --git a/mysql-test/main/status.result b/mysql-test/main/status.result index 688d8acee1a..37c551328f0 100644 --- a/mysql-test/main/status.result +++ b/mysql-test/main/status.result @@ -324,7 +324,7 @@ Handler_mrr_key_refills 0 Handler_mrr_rowid_refills 0 Handler_prepare 0 Handler_read_first 0 -Handler_read_key 4 +Handler_read_key 9 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 @@ -403,9 +403,9 @@ Table_open_cache_overflows 0 SHOW STATUS LIKE 'Table_open_cache%'; Variable_name Value Table_open_cache_active_instances 1 -Table_open_cache_hits 30 -Table_open_cache_misses 15 -Table_open_cache_overflows 5 +Table_open_cache_hits 72 +Table_open_cache_misses 18 +Table_open_cache_overflows 8 FLUSH TABLES; FLUSH STATUS; SET @@global.table_open_cache= @old_table_open_cache; diff --git a/mysql-test/main/str_to_datetime_457.result b/mysql-test/main/str_to_datetime_457.result index 4fd0d00691c..e365c303c81 100644 --- a/mysql-test/main/str_to_datetime_457.result +++ b/mysql-test/main/str_to_datetime_457.result @@ -1,6 +1,6 @@ select cast('01:02:03 ' as time), cast('01:02:03 ' as time); cast('01:02:03 ' as time) cast('01:02:03 ' as time) -01:02:03 00:00:00 +01:02:03 01:02:03 select cast('2002-011-012' as date), cast('2002.11.12' as date), cast('2002.011.012' as date); cast('2002-011-012' as date) cast('2002.11.12' as date) cast('2002.011.012' as date) 2002-11-12 2002-11-12 2002-11-12 @@ -17,10 +17,7 @@ Warnings: Warning 1292 Incorrect datetime value: '0' select extract(hour from '100000:02:03'), extract(hour from '100000:02:03 '); extract(hour from '100000:02:03') extract(hour from '100000:02:03 ') -NULL NULL -Warnings: -Warning 1292 Truncated incorrect time value: '100000:02:03' -Warning 1292 Truncated incorrect time value: '100000:02:03 ' +16 16 # # backward compatibility craziness # diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result index 2f7c5039c67..5b45fa08e1e 100644 --- a/mysql-test/main/subselect.result +++ b/mysql-test/main/subselect.result @@ -179,7 +179,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); a b 1 7 2 7 -(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3; +(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) +union (select * from t4 order by a limit 2) order by a limit 3; a b 1 7 2 7 @@ -343,7 +344,7 @@ patient_uq clinic_uq explain extended select * from t6 where exists (select * from t7 where uq = clinic_uq); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t7 index PRIMARY PRIMARY 4 NULL 2 100.00 Using index -1 PRIMARY t6 ALL i1 NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t6 ALL i1 NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) Warnings: Note 1276 Field or reference 'test.t6.clinic_uq' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t7` join `test`.`t6` where `test`.`t6`.`clinic_uq` = `test`.`t7`.`uq` @@ -1440,7 +1441,7 @@ a explain extended select * from t2 where t2.a in (select a from t1); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 4 75.00 Using where; Using index; Using join buffer (flat, BNL join) +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 Using index Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a` select * from t2 where t2.a in (select a from t1 where t1.b <> 30); @@ -1450,7 +1451,7 @@ a explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a` and `test`.`t1`.`b` <> 30 select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); @@ -1460,8 +1461,8 @@ a explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) -1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 Using index +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 +1 PRIMARY t3 index PRIMARY PRIMARY 4 NULL 3 100.00 Using where; Using index; Using join buffer (flat, BNL join) Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t3` join `test`.`t2` where `test`.`t3`.`a` = `test`.`t1`.`b` and `test`.`t1`.`a` = `test`.`t2`.`a` drop table t1, t2, t3; @@ -1629,7 +1630,7 @@ Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index -2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key +2 SUBQUERY t2 index_subquery s1 s1 6 func 2 50.00 Using index; Using where; Full scan on NULL key Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` drop table t1,t2; @@ -3726,7 +3727,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS i SELECT * FROM t1 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION (SELECT i FROM t1)))' at line 2 +i explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) from t1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12)) @@ -5186,35 +5187,23 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1) ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1)) ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') t1a ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) t1a ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) ON 1' at line 1 SELECT * FROM (t1 t1a); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1 SELECT * FROM ((t1 t1a)); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1 SELECT * FROM t1 JOIN (SELECT 1 t1a) alias ON 1; a t1a 1 1 @@ -5289,11 +5278,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1; SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2); a b SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 +1 +1 ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1' at line 1 +1 +1 SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ) +1 SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1 SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -5303,9 +5295,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); ((SELECT 1 UNION SELECT 1 UNION SELECT 1)) 1 SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; 1 1 @@ -5313,19 +5305,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -7021,8 +7019,8 @@ SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index a a 5 NULL 2 Using where; Using index -2 SUBQUERY <subquery3> ALL distinct_key NULL NULL NULL 1 -2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +2 SUBQUERY <subquery3> eq_ref distinct_key distinct_key 4 test.t2.c 1 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10; @@ -7081,12 +7079,6 @@ call procedure2(); ControlRev NULL drop procedure procedure2; -SELECT -(SELECT user FROM mysql.user -WHERE h.host in (SELECT host FROM mysql.user) -) AS sq -FROM mysql.host h GROUP BY h.host; -sq # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun @@ -7299,3 +7291,18 @@ pk i c pk i c 1 10 foo 1 10 foo DROP TABLE t; # End of 10.2 tests +# +# Start of 10.4 tests +# +# +# MDEV-16861 Split Item::update_null_value() into a new virtual method in Type_handler +# +SELECT ROW(1,2) = EXISTS (SELECT 1); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = 1 IN (SELECT 1 UNION SELECT 2); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +# +# End of 10.4 tests +# diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test index 189dde382dd..d7c266cafb0 100644 --- a/mysql-test/main/subselect.test +++ b/mysql-test/main/subselect.test @@ -99,7 +99,8 @@ select (select a from t3), a from t2; select * from t2 where t2.a=(select a from t1); insert into t3 values (6),(7),(3); select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); -(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3; +(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) +union (select * from t4 order by a limit 2) order by a limit 3; (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a); explain extended (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a); select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2; @@ -2604,8 +2605,6 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS (SELECT i FROM t1) ); -#TODO:not supported ---error ER_PARSE_ERROR SELECT * FROM t1 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); @@ -4313,7 +4312,7 @@ SELECT * FROM (SELECT 1 a UNION SELECT 1 a ORDER BY a LIMIT 1) t1a; # aliases after. # SELECT * FROM t1 JOIN (SELECT 1 UNION SELECT 1) alias ON 1; ---error ER_DERIVED_MUST_HAVE_ALIAS +--error ER_PARSE_ERROR SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; --error ER_PARSE_ERROR SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; @@ -4324,10 +4323,14 @@ SELECT * FROM t1 JOIN (t1 t1a) t1a ON 1; --error ER_PARSE_ERROR SELECT * FROM t1 JOIN ((t1 t1a)) t1a ON 1; +--error ER_PARSE_ERROR SELECT * FROM t1 JOIN (t1 t1a) ON 1; +--error ER_PARSE_ERROR SELECT * FROM t1 JOIN ((t1 t1a)) ON 1; +--error ER_PARSE_ERROR SELECT * FROM (t1 t1a); +--error ER_PARSE_ERROR SELECT * FROM ((t1 t1a)); SELECT * FROM t1 JOIN (SELECT 1 t1a) alias ON 1; @@ -4391,12 +4394,9 @@ SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2); # Make sure the parser does not allow nested UNIONs anywhere ---error ER_PARSE_ERROR SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ); ---error ER_PARSE_ERROR ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; ---error ER_PARSE_ERROR SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); --error ER_PARSE_ERROR SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; @@ -4405,25 +4405,19 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); --error ER_PARSE_ERROR SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); ---error ER_DERIVED_MUST_HAVE_ALIAS +--error ER_PARSE_ERROR SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; ---error ER_PARSE_ERROR SELECT * FROM t1 WHERE a = ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); ---error ER_PARSE_ERROR SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); ---error ER_PARSE_ERROR SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); ---error ER_PARSE_ERROR SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); --error ER_PARSE_ERROR SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ---error ER_PARSE_ERROR SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ---error ER_PARSE_ERROR SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); --error ER_PARSE_ERROR SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); @@ -5933,13 +5927,6 @@ call procedure2(); drop procedure procedure2; -SELECT - (SELECT user FROM mysql.user - WHERE h.host in (SELECT host FROM mysql.user) - ) AS sq -FROM mysql.host h GROUP BY h.host; - - --echo # --echo # MDEV-7846:Server crashes in Item_subselect::fix --echo #_fields or fails with Thread stack overrun @@ -6166,3 +6153,23 @@ SELECT * FROM t t1 RIGHT JOIN t t2 ON (t2.pk = t1.pk) DROP TABLE t; --echo # End of 10.2 tests + + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-16861 Split Item::update_null_value() into a new virtual method in Type_handler +--echo # + +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT ROW(1,2) = EXISTS (SELECT 1); +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT ROW(1,2) = 1 IN (SELECT 1 UNION SELECT 2); +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION +SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/subselect_exists2in.result b/mysql-test/main/subselect_exists2in.result index 95fc1c19b82..4029a246a8b 100644 --- a/mysql-test/main/subselect_exists2in.result +++ b/mysql-test/main/subselect_exists2in.result @@ -142,6 +142,7 @@ create index idx_t1_1 on t1 (a1,a2,b,c); create index idx_t1_2 on t1 (a1,a2,b); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date create table t2 ( a1 char(64), a2 char(64) not null, b char(16), c char(16), d char(16), dummy char(64) default ' ' @@ -169,6 +170,7 @@ create index idx_t2_1 on t2 (a1,a2,b,c); create index idx_t2_2 on t2 (a1,a2,b); analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date create table t3 ( a1 char(1), a2 char(1), b char(1), c char(4) not null, d char(3), dummy char(1) default ' ' @@ -230,6 +232,7 @@ create index idx_t3_1 on t3 (a1,a2,b,c); create index idx_t3_2 on t3 (a1,a2,b); analyze table t3; Table Op Msg_type Msg_text +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status Table is already up to date explain select a1,a2,b,c,min(c), max(c) from t1 where exists ( select * from t2 diff --git a/mysql-test/main/subselect_exists2in_costmat.result b/mysql-test/main/subselect_exists2in_costmat.result index a46996d9bad..1c9574aafd3 100644 --- a/mysql-test/main/subselect_exists2in_costmat.result +++ b/mysql-test/main/subselect_exists2in_costmat.result @@ -37,6 +37,8 @@ create index Language on CountryLanguage(Language); create index CityName on City(Name); alter table City change population population int(11) null default 0; select max(id) from City into @max_city_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead insert into City values (@max_city_id + 1,'Kilifarevo','BGR',NULL); SELECT COUNT(*) FROM Country; COUNT(*) @@ -63,7 +65,7 @@ Name LIKE 'L%') AND surfacearea > 1000000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country ALL Name,SurfaceArea NULL NULL NULL 239 Using where -2 MATERIALIZED City ALL Population,Country NULL NULL NULL 4080 Using where +2 MATERIALIZED City ALL Population,Country NULL NULL NULL 4079 Using where SELECT Name FROM Country WHERE (EXISTS (select 1 from City where City.Population > 100000 and Code = Country) OR diff --git a/mysql-test/main/subselect_extra.result b/mysql-test/main/subselect_extra.result index a3a0f1f9a15..edae4abfb3d 100644 --- a/mysql-test/main/subselect_extra.result +++ b/mysql-test/main/subselect_extra.result @@ -132,6 +132,7 @@ create index idx_t1_1 on t1 (a1,a2,b,c); create index idx_t1_2 on t1 (a1,a2,b); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date create table t2 ( a1 char(64), a2 char(64) not null, b char(16), c char(16), d char(16), dummy char(64) default ' ' @@ -159,6 +160,7 @@ create index idx_t2_1 on t2 (a1,a2,b,c); create index idx_t2_2 on t2 (a1,a2,b); analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date create table t3 ( a1 char(1), a2 char(1), b char(1), c char(4) not null, d char(3), dummy char(1) default ' ' @@ -220,6 +222,7 @@ create index idx_t3_1 on t3 (a1,a2,b,c); create index idx_t3_2 on t3 (a1,a2,b); analyze table t3; Table Op Msg_type Msg_text +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status Table is already up to date explain select a1,a2,b,c,min(c), max(c) from t1 where exists ( select * from t2 @@ -302,6 +305,7 @@ INSERT INTO t1 SELECT a + 64,b FROM t1; INSERT INTO t1 SELECT a + 128,b FROM t1 limit 16; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN SELECT 1 FROM t1 WHERE a IN (SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2)); diff --git a/mysql-test/main/subselect_extra_no_semijoin.result b/mysql-test/main/subselect_extra_no_semijoin.result index ec9ddb0452e..8aca24b6097 100644 --- a/mysql-test/main/subselect_extra_no_semijoin.result +++ b/mysql-test/main/subselect_extra_no_semijoin.result @@ -136,6 +136,7 @@ create index idx_t1_1 on t1 (a1,a2,b,c); create index idx_t1_2 on t1 (a1,a2,b); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date create table t2 ( a1 char(64), a2 char(64) not null, b char(16), c char(16), d char(16), dummy char(64) default ' ' @@ -163,6 +164,7 @@ create index idx_t2_1 on t2 (a1,a2,b,c); create index idx_t2_2 on t2 (a1,a2,b); analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date create table t3 ( a1 char(1), a2 char(1), b char(1), c char(4) not null, d char(3), dummy char(1) default ' ' @@ -224,6 +226,7 @@ create index idx_t3_1 on t3 (a1,a2,b,c); create index idx_t3_2 on t3 (a1,a2,b); analyze table t3; Table Op Msg_type Msg_text +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status Table is already up to date explain select a1,a2,b,c,min(c), max(c) from t1 where exists ( select * from t2 @@ -306,6 +309,7 @@ INSERT INTO t1 SELECT a + 64,b FROM t1; INSERT INTO t1 SELECT a + 128,b FROM t1 limit 16; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN SELECT 1 FROM t1 WHERE a IN (SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2)); diff --git a/mysql-test/main/subselect_innodb.result b/mysql-test/main/subselect_innodb.result index ec7f2c0a3d5..799adf1d116 100644 --- a/mysql-test/main/subselect_innodb.result +++ b/mysql-test/main/subselect_innodb.result @@ -561,6 +561,7 @@ update t2 set key2=key1; alter table t2 add key(key2); analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK flush tables; # Table tsubq must use 'ref' + Using filesort (not 'index' w/o filesort) diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result index 2ba851808df..732024bb607 100644 --- a/mysql-test/main/subselect_mat.result +++ b/mysql-test/main/subselect_mat.result @@ -1925,7 +1925,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(/*always not null*/ 1 is null) or `<subquery2>`.`MAX(c)` = 7) +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(/*always not null*/ 1 is null) or `<subquery2>`.`MAX(c)` = 7) SELECT * FROM t1 WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b); a b @@ -2179,11 +2179,11 @@ drop database mysqltest4; # (both 1st and further executions) CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM; INSERT INTO t1 VALUES (0),(8); -SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2)); +SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2); a 0 PREPARE stmt FROM " -SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2)) +SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2) "; execute stmt; a @@ -2526,7 +2526,7 @@ select * from t1 where (a,b) in (select max(a),b from t2 group by b); show status where Variable_name like 'Handler_read%' or Variable_name like 'Handler_%write%'; Variable_name Value Handler_read_first 0 -Handler_read_key 5000 +Handler_read_key 5004 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 diff --git a/mysql-test/main/subselect_mat_cost.result b/mysql-test/main/subselect_mat_cost.result index a9f980fff5d..39ccc93936f 100644 --- a/mysql-test/main/subselect_mat_cost.result +++ b/mysql-test/main/subselect_mat_cost.result @@ -40,6 +40,8 @@ create index Language on CountryLanguage(Language); create index CityName on City(Name); alter table City change population population int(11) null default 0; select max(id) from City into @max_city_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead insert into City values (@max_city_id + 1,'Kilifarevo','BGR',NULL); SELECT COUNT(*) FROM Country; COUNT(*) @@ -65,7 +67,7 @@ Name LIKE 'L%') AND surfacearea > 1000000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country ALL Name,SurfaceArea NULL NULL NULL 239 Using where -2 MATERIALIZED City ALL Population,Country NULL NULL NULL 4080 Using where +2 MATERIALIZED City ALL Population,Country NULL NULL NULL 4079 Using where SELECT Name FROM Country WHERE (Code IN (select Country from City where City.Population > 100000) OR Name LIKE 'L%') AND @@ -111,7 +113,7 @@ Name LIKE 'L%') AND surfacearea > 10*1000000; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country range Name,SurfaceArea SurfaceArea 4 NULL 5 Using index condition; Using where; Rowid-ordered scan -2 DEPENDENT SUBQUERY City index_subquery Population,Country Country 3 func 18 Using where +2 DEPENDENT SUBQUERY City index_subquery Population,Country Country 3 func 17 Using where SELECT Name FROM Country WHERE (Code IN (select Country from City where City.Population > 100000) OR Name LIKE 'L%') AND @@ -133,7 +135,7 @@ Country.SurfaceArea < 3000 AND Country.SurfaceArea > 10 AND City.name LIKE '%Island%'); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country ALL PRIMARY,SurfaceArea NULL NULL NULL 239 Using where -1 PRIMARY City ref Country Country 3 world.Country.Code 18 Using where +1 PRIMARY City ref Country Country 3 world.Country.Code 17 Using where 2 MATERIALIZED CountryLanguage ALL Percentage,Language NULL NULL NULL 984 Using where SELECT * FROM Country, City @@ -158,7 +160,7 @@ Country.SurfaceArea < 3000 AND Country.SurfaceArea > 10 AND Country.name LIKE '%Island%'); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country ALL PRIMARY,SurfaceArea NULL NULL NULL 239 Using where -1 PRIMARY City ref Country Country 3 world.Country.Code 18 +1 PRIMARY City ref Country Country 3 world.Country.Code 17 2 DEPENDENT SUBQUERY CountryLanguage index_subquery Percentage,Language Language 30 func 2 Using where SELECT * FROM Country, City @@ -203,7 +205,7 @@ OR (select Country, Language from CountryLanguage)); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country ALL PRIMARY,SurfaceArea NULL NULL NULL 239 Using where -1 PRIMARY City ref Country Country 3 world.Country.Code 18 Using where +1 PRIMARY City ref Country Country 3 world.Country.Code 17 Using where 3 MATERIALIZED CountryLanguage index PRIMARY,Language PRIMARY 33 NULL 984 Using index 2 DEPENDENT SUBQUERY CountryLanguage unique_subquery PRIMARY,Percentage,Language PRIMARY 33 func,func 1 Using where SELECT City.Name, Country.Name @@ -232,7 +234,7 @@ select count(*) from City where City.id not in (select capital from Country where capital is not null and population < 100000); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY City index NULL PRIMARY 4 NULL 4080 Using where; Using index +1 PRIMARY City index NULL PRIMARY 4 NULL 4079 Using where; Using index 2 MATERIALIZED Country ALL NULL NULL NULL NULL 239 Using where Q2.2e: @@ -371,7 +373,7 @@ FROM City LEFT JOIN Country ON (Country = Code) HAVING City.Name LIKE "Santa%"); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY CountryLanguage index NULL PRIMARY 33 NULL 984 Using where; Using index -2 MATERIALIZED City ALL NULL NULL NULL NULL 4080 +2 MATERIALIZED City ALL NULL NULL NULL NULL 4079 2 MATERIALIZED Country eq_ref PRIMARY PRIMARY 3 world.City.Country 1 Using index select count(*) from CountryLanguage @@ -429,7 +431,7 @@ capital is null); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country ALL NULL NULL NULL NULL 239 Using where 1 PRIMARY City eq_ref PRIMARY PRIMARY 4 world.Country.Capital 1 Using where -2 MATERIALIZED City index NULL CityName 35 NULL 4080 Using index +2 MATERIALIZED City index NULL CityName 35 NULL 4079 Using index select * from Country, City where capital = id and (City.name in (SELECT name FROM City @@ -450,7 +452,7 @@ WHERE Country.Code NOT IN (SELECT Country FROM City GROUP BY Name HAVING COUNT(Name) = 1); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country ALL NULL NULL NULL NULL 239 Using where -2 MATERIALIZED City ALL NULL NULL NULL NULL 4080 Using temporary +2 MATERIALIZED City ALL NULL NULL NULL NULL 4079 Using temporary SELECT Name FROM Country WHERE Country.Code NOT IN @@ -513,7 +515,7 @@ GROUP BY City.Name HAVING City.Name IN (select Name from Country where population < 1000000); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY Country index PRIMARY PRIMARY 3 NULL 239 Using index; Using temporary; Using filesort -1 PRIMARY City ref Country Country 3 world.Country.Code 18 +1 PRIMARY City ref Country Country 3 world.Country.Code 17 2 MATERIALIZED Country ALL Name NULL NULL NULL 239 Using where SELECT City.Name, City.Population FROM City JOIN Country ON City.Country = Country.Code @@ -538,7 +540,7 @@ SELECT Name, round(Population/1000) FROM City WHERE Country = "IND" AND Population < 100000); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY City ALL NULL NULL NULL NULL 4080 Using where +1 PRIMARY City ALL NULL NULL NULL NULL 4079 Using where 2 DEPENDENT SUBQUERY City ref Population,Country,CityName CityName 35 func 1 Using where 3 DEPENDENT UNION City ref Population,Country,CityName CityName 35 func 1 Using where NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL diff --git a/mysql-test/main/subselect_mat_cost_bugs.result b/mysql-test/main/subselect_mat_cost_bugs.result index 6377ae556d2..2c696ed36fd 100644 --- a/mysql-test/main/subselect_mat_cost_bugs.result +++ b/mysql-test/main/subselect_mat_cost_bugs.result @@ -310,6 +310,7 @@ create index key3 on t2 (kp2); SET @@optimizer_switch='materialization=off,semijoin=off,in_to_exists=on'; analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK explain select c1 from t1 where c1 in (select kp1 from t2 where kp2 = 10 and c2 = 4) or c1 > 7; diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result index f8fd29aced9..6f8f8716812 100644 --- a/mysql-test/main/subselect_no_exists_to_in.result +++ b/mysql-test/main/subselect_no_exists_to_in.result @@ -183,7 +183,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); a b 1 7 2 7 -(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3; +(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) +union (select * from t4 order by a limit 2) order by a limit 3; a b 1 7 2 7 @@ -1444,7 +1445,7 @@ a explain extended select * from t2 where t2.a in (select a from t1); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 4 75.00 Using where; Using index; Using join buffer (flat, BNL join) +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 Using index Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a` select * from t2 where t2.a in (select a from t1 where t1.b <> 30); @@ -1454,7 +1455,7 @@ a explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a` and `test`.`t1`.`b` <> 30 select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); @@ -1464,8 +1465,8 @@ a explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) -1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 Using index +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 +1 PRIMARY t3 index PRIMARY PRIMARY 4 NULL 3 100.00 Using where; Using index; Using join buffer (flat, BNL join) Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t3` join `test`.`t2` where `test`.`t3`.`a` = `test`.`t1`.`b` and `test`.`t1`.`a` = `test`.`t2`.`a` drop table t1, t2, t3; @@ -1633,7 +1634,7 @@ Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index -2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key +2 SUBQUERY t2 index_subquery s1 s1 6 func 2 50.00 Using index; Using where; Full scan on NULL key Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` drop table t1,t2; @@ -3729,7 +3730,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS i SELECT * FROM t1 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION (SELECT i FROM t1)))' at line 2 +i explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) from t1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12)) @@ -5188,35 +5189,23 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1) ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1)) ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') t1a ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) t1a ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) ON 1' at line 1 SELECT * FROM (t1 t1a); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1 SELECT * FROM ((t1 t1a)); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1 SELECT * FROM t1 JOIN (SELECT 1 t1a) alias ON 1; a t1a 1 1 @@ -5291,11 +5280,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1; SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2); a b SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 +1 +1 ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1' at line 1 +1 +1 SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ) +1 SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1 SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -5305,9 +5297,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); ((SELECT 1 UNION SELECT 1 UNION SELECT 1)) 1 SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; 1 1 @@ -5315,19 +5307,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -7021,8 +7019,8 @@ SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index a a 5 NULL 2 Using where; Using index -2 SUBQUERY <subquery3> ALL distinct_key NULL NULL NULL 1 -2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +2 SUBQUERY <subquery3> eq_ref distinct_key distinct_key 4 test.t2.c 1 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10; @@ -7081,12 +7079,6 @@ call procedure2(); ControlRev NULL drop procedure procedure2; -SELECT -(SELECT user FROM mysql.user -WHERE h.host in (SELECT host FROM mysql.user) -) AS sq -FROM mysql.host h GROUP BY h.host; -sq # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun @@ -7299,6 +7291,21 @@ pk i c pk i c 1 10 foo 1 10 foo DROP TABLE t; # End of 10.2 tests +# +# Start of 10.4 tests +# +# +# MDEV-16861 Split Item::update_null_value() into a new virtual method in Type_handler +# +SELECT ROW(1,2) = EXISTS (SELECT 1); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = 1 IN (SELECT 1 UNION SELECT 2); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +# +# End of 10.4 tests +# set optimizer_switch=default; select @@optimizer_switch like '%exists_to_in=off%'; @@optimizer_switch like '%exists_to_in=off%' diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result index 89f236a5a60..01d8c0edeb3 100644 --- a/mysql-test/main/subselect_no_mat.result +++ b/mysql-test/main/subselect_no_mat.result @@ -186,7 +186,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); a b 1 7 2 7 -(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3; +(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) +union (select * from t4 order by a limit 2) order by a limit 3; a b 1 7 2 7 @@ -350,7 +351,7 @@ patient_uq clinic_uq explain extended select * from t6 where exists (select * from t7 where uq = clinic_uq); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t7 index PRIMARY PRIMARY 4 NULL 2 100.00 Using index -1 PRIMARY t6 ALL i1 NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t6 ALL i1 NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) Warnings: Note 1276 Field or reference 'test.t6.clinic_uq' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t7` join `test`.`t6` where `test`.`t6`.`clinic_uq` = `test`.`t7`.`uq` @@ -1447,7 +1448,7 @@ a explain extended select * from t2 where t2.a in (select a from t1); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 4 75.00 Using where; Using index; Using join buffer (flat, BNL join) +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 Using index Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a` select * from t2 where t2.a in (select a from t1 where t1.b <> 30); @@ -1457,7 +1458,7 @@ a explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a` and `test`.`t1`.`b` <> 30 select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); @@ -1467,8 +1468,8 @@ a explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) -1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 Using index +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 +1 PRIMARY t3 index PRIMARY PRIMARY 4 NULL 3 100.00 Using where; Using index; Using join buffer (flat, BNL join) Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t3` join `test`.`t2` where `test`.`t3`.`a` = `test`.`t1`.`b` and `test`.`t1`.`a` = `test`.`t2`.`a` drop table t1, t2, t3; @@ -1636,7 +1637,7 @@ Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index -2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key +2 SUBQUERY t2 index_subquery s1 s1 6 func 2 50.00 Using index; Using where; Full scan on NULL key Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` drop table t1,t2; @@ -3729,7 +3730,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS i SELECT * FROM t1 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION (SELECT i FROM t1)))' at line 2 +i explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) from t1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12)) @@ -5186,35 +5187,23 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1) ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1)) ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') t1a ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) t1a ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) ON 1' at line 1 SELECT * FROM (t1 t1a); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1 SELECT * FROM ((t1 t1a)); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1 SELECT * FROM t1 JOIN (SELECT 1 t1a) alias ON 1; a t1a 1 1 @@ -5289,11 +5278,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1; SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2); a b SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 +1 +1 ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1' at line 1 +1 +1 SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ) +1 SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1 SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -5303,9 +5295,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); ((SELECT 1 UNION SELECT 1 UNION SELECT 1)) 1 SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; 1 1 @@ -5313,19 +5305,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -7074,12 +7072,6 @@ call procedure2(); ControlRev NULL drop procedure procedure2; -SELECT -(SELECT user FROM mysql.user -WHERE h.host in (SELECT host FROM mysql.user) -) AS sq -FROM mysql.host h GROUP BY h.host; -sq # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun @@ -7292,6 +7284,21 @@ pk i c pk i c 1 10 foo 1 10 foo DROP TABLE t; # End of 10.2 tests +# +# Start of 10.4 tests +# +# +# MDEV-16861 Split Item::update_null_value() into a new virtual method in Type_handler +# +SELECT ROW(1,2) = EXISTS (SELECT 1); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = 1 IN (SELECT 1 UNION SELECT 2); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +# +# End of 10.4 tests +# set optimizer_switch=default; select @@optimizer_switch like '%materialization=on%'; @@optimizer_switch like '%materialization=on%' diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result index 348cffb9c53..dc397cd5451 100644 --- a/mysql-test/main/subselect_no_opts.result +++ b/mysql-test/main/subselect_no_opts.result @@ -182,7 +182,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); a b 1 7 2 7 -(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3; +(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) +union (select * from t4 order by a limit 2) order by a limit 3; a b 1 7 2 7 @@ -1632,7 +1633,7 @@ Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`. explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index -2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key +2 SUBQUERY t2 index_subquery s1 s1 6 func 2 50.00 Using index; Using where; Full scan on NULL key Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` drop table t1,t2; @@ -3725,7 +3726,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS i SELECT * FROM t1 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION (SELECT i FROM t1)))' at line 2 +i explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) from t1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12)) @@ -5182,35 +5183,23 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1) ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1)) ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') t1a ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) t1a ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) ON 1' at line 1 SELECT * FROM (t1 t1a); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1 SELECT * FROM ((t1 t1a)); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1 SELECT * FROM t1 JOIN (SELECT 1 t1a) alias ON 1; a t1a 1 1 @@ -5285,11 +5274,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1; SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2); a b SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 +1 +1 ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1' at line 1 +1 +1 SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ) +1 SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1 SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -5299,9 +5291,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); ((SELECT 1 UNION SELECT 1 UNION SELECT 1)) 1 SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; 1 1 @@ -5309,19 +5301,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -7012,8 +7010,8 @@ SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index a a 5 NULL 2 Using where; Using index -2 SUBQUERY <subquery3> ALL distinct_key NULL NULL NULL 1 -2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +2 SUBQUERY <subquery3> eq_ref distinct_key distinct_key 4 test.t2.c 1 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10; @@ -7072,12 +7070,6 @@ call procedure2(); ControlRev NULL drop procedure procedure2; -SELECT -(SELECT user FROM mysql.user -WHERE h.host in (SELECT host FROM mysql.user) -) AS sq -FROM mysql.host h GROUP BY h.host; -sq # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun @@ -7290,4 +7282,19 @@ pk i c pk i c 1 10 foo 1 10 foo DROP TABLE t; # End of 10.2 tests +# +# Start of 10.4 tests +# +# +# MDEV-16861 Split Item::update_null_value() into a new virtual method in Type_handler +# +SELECT ROW(1,2) = EXISTS (SELECT 1); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = 1 IN (SELECT 1 UNION SELECT 2); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +# +# End of 10.4 tests +# set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result index 230c645b261..7bd3853208c 100644 --- a/mysql-test/main/subselect_no_scache.result +++ b/mysql-test/main/subselect_no_scache.result @@ -185,7 +185,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); a b 1 7 2 7 -(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3; +(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) +union (select * from t4 order by a limit 2) order by a limit 3; a b 1 7 2 7 @@ -349,7 +350,7 @@ patient_uq clinic_uq explain extended select * from t6 where exists (select * from t7 where uq = clinic_uq); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t7 index PRIMARY PRIMARY 4 NULL 2 100.00 Using index -1 PRIMARY t6 ALL i1 NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t6 ALL i1 NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) Warnings: Note 1276 Field or reference 'test.t6.clinic_uq' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t7` join `test`.`t6` where `test`.`t6`.`clinic_uq` = `test`.`t7`.`uq` @@ -1446,7 +1447,7 @@ a explain extended select * from t2 where t2.a in (select a from t1); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 index PRIMARY PRIMARY 4 NULL 4 75.00 Using where; Using index; Using join buffer (flat, BNL join) +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 Using index Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a` select * from t2 where t2.a in (select a from t1 where t1.b <> 30); @@ -1456,7 +1457,7 @@ a explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where `test`.`t1`.`a` = `test`.`t2`.`a` and `test`.`t1`.`b` <> 30 select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); @@ -1466,8 +1467,8 @@ a explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index -1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) -1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 Using index +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 100.00 +1 PRIMARY t3 index PRIMARY PRIMARY 4 NULL 3 100.00 Using where; Using index; Using join buffer (flat, BNL join) Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t3` join `test`.`t2` where `test`.`t3`.`a` = `test`.`t1`.`b` and `test`.`t1`.`a` = `test`.`t2`.`a` drop table t1, t2, t3; @@ -1635,7 +1636,7 @@ Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`. explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index -2 SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key +2 SUBQUERY t2 index_subquery s1 s1 6 func 2 50.00 Using index; Using where; Full scan on NULL key Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,!<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where `test`.`t2`.`s1` < 'a2' having trigcond(`test`.`t2`.`s1` is null)))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` drop table t1,t2; @@ -3732,7 +3733,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS i SELECT * FROM t1 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION (SELECT i FROM t1)))' at line 2 +i explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) from t1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12)) @@ -5192,35 +5193,23 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1) ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1)) ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') t1a ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) t1a ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) ON 1' at line 1 SELECT * FROM (t1 t1a); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1 SELECT * FROM ((t1 t1a)); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1 SELECT * FROM t1 JOIN (SELECT 1 t1a) alias ON 1; a t1a 1 1 @@ -5295,11 +5284,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1; SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2); a b SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 +1 +1 ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1' at line 1 +1 +1 SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ) +1 SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1 SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -5309,9 +5301,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); ((SELECT 1 UNION SELECT 1 UNION SELECT 1)) 1 SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; 1 1 @@ -5319,19 +5311,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -7027,8 +7025,8 @@ SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index a a 5 NULL 2 Using where; Using index -2 SUBQUERY <subquery3> ALL distinct_key NULL NULL NULL 1 -2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +2 SUBQUERY <subquery3> eq_ref distinct_key distinct_key 4 test.t2.c 1 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10; @@ -7087,12 +7085,6 @@ call procedure2(); ControlRev NULL drop procedure procedure2; -SELECT -(SELECT user FROM mysql.user -WHERE h.host in (SELECT host FROM mysql.user) -) AS sq -FROM mysql.host h GROUP BY h.host; -sq # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun @@ -7305,6 +7297,21 @@ pk i c pk i c 1 10 foo 1 10 foo DROP TABLE t; # End of 10.2 tests +# +# Start of 10.4 tests +# +# +# MDEV-16861 Split Item::update_null_value() into a new virtual method in Type_handler +# +SELECT ROW(1,2) = EXISTS (SELECT 1); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = 1 IN (SELECT 1 UNION SELECT 2); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +# +# End of 10.4 tests +# set optimizer_switch=default; select @@optimizer_switch like '%subquery_cache=on%'; @@optimizer_switch like '%subquery_cache=on%' diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result index e58a01d1983..9eccf868237 100644 --- a/mysql-test/main/subselect_no_semijoin.result +++ b/mysql-test/main/subselect_no_semijoin.result @@ -182,7 +182,8 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); a b 1 7 2 7 -(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3; +(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) +union (select * from t4 order by a limit 2) order by a limit 3; a b 1 7 2 7 @@ -3725,7 +3726,7 @@ SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS i SELECT * FROM t1 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION (SELECT i FROM t1)))' at line 2 +i explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) from t1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'union (select t12.i from t1 t12)) @@ -5182,35 +5183,23 @@ a 1 1 1 2 1 SELECT * FROM t1 JOIN ((SELECT 1 UNION SELECT 1)) ON 1; -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a UNION SELECT 1) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1) ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a UNION SELECT 1)) ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)) ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1)) ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') t1a ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) t1a ON 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't1a ON 1' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) t1a ON 1' at line 1 SELECT * FROM t1 JOIN (t1 t1a) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') ON 1' at line 1 SELECT * FROM t1 JOIN ((t1 t1a)) ON 1; -a a -1 1 -2 1 -1 2 -2 2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) ON 1' at line 1 SELECT * FROM (t1 t1a); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 1 SELECT * FROM ((t1 t1a)); -a -1 -2 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '))' at line 1 SELECT * FROM t1 JOIN (SELECT 1 t1a) alias ON 1; a t1a 1 1 @@ -5285,11 +5274,14 @@ SELECT ( SELECT a FROM t1 WHERE a = 1 UNION SELECT 1 ), a FROM t1; SELECT * FROM t2 WHERE (a, b) IN (SELECT a, b FROM t2); a b SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 +1 +1 ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1' at line 1 +1 +1 SELECT ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ) +1 SELECT ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1' at line 1 SELECT ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -5299,9 +5291,9 @@ SELECT ((SELECT 1 UNION SELECT 1 UNION SELECT 1)); ((SELECT 1 UNION SELECT 1 UNION SELECT 1)) 1 SELECT * FROM ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: Every derived table must have its own alias +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 SELECT * FROM ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ) a; 1 1 @@ -5309,19 +5301,25 @@ SELECT * FROM ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ) a; 1 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ALL ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( SELECT 1 UNION ( SELECT 1 UNION SELECT 1 ) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ALL ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a = ANY ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 ) UNION SELECT 1 )' at line 1 +a +1 SELECT * FROM t1 WHERE a IN ( ( SELECT 1 UNION SELECT 1 ) UNION SELECT 1 ); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT 1 )' at line 1 SELECT * FROM t1 WHERE a = ( SELECT 1 UNION SELECT 1 UNION SELECT 1 ); @@ -7012,8 +7010,8 @@ SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index a a 5 NULL 2 Using where; Using index -2 SUBQUERY <subquery3> ALL distinct_key NULL NULL NULL 1 -2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where +2 SUBQUERY <subquery3> eq_ref distinct_key distinct_key 4 test.t2.c 1 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t2 WHERE c IN (SELECT MAX(d) FROM t3)) OR a = 10; @@ -7072,12 +7070,6 @@ call procedure2(); ControlRev NULL drop procedure procedure2; -SELECT -(SELECT user FROM mysql.user -WHERE h.host in (SELECT host FROM mysql.user) -) AS sq -FROM mysql.host h GROUP BY h.host; -sq # # MDEV-7846:Server crashes in Item_subselect::fix #_fields or fails with Thread stack overrun @@ -7290,5 +7282,20 @@ pk i c pk i c 1 10 foo 1 10 foo DROP TABLE t; # End of 10.2 tests +# +# Start of 10.4 tests +# +# +# MDEV-16861 Split Item::update_null_value() into a new virtual method in Type_handler +# +SELECT ROW(1,2) = EXISTS (SELECT 1); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = 1 IN (SELECT 1 UNION SELECT 2); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +SELECT ROW(1,2) = (1 = ANY (SELECT 1 UNION SELECT 2)); +ERROR HY000: Illegal parameter data types row and boolean for operation '=' +# +# End of 10.4 tests +# set @optimizer_switch_for_subselect_test=null; set @join_cache_level_for_subselect_test=NULL; diff --git a/mysql-test/main/subselect_sj.result b/mysql-test/main/subselect_sj.result index b50ae942899..aef3ec17c10 100644 --- a/mysql-test/main/subselect_sj.result +++ b/mysql-test/main/subselect_sj.result @@ -1675,7 +1675,7 @@ CREATE TABLE t3 ( f11 int) ; INSERT IGNORE INTO t3 VALUES (0); SELECT alias1.f11 AS field2 FROM ( t3 AS alias2 JOIN t1 AS alias3 ON alias3.f10 = 1) -LEFT JOIN ( t2 AS alias1 ) ON alias3.f11 = 1 +LEFT JOIN t2 AS alias1 ON alias3.f11 = 1 WHERE alias2.f11 IN ( SELECT f11 FROM t2 ) GROUP BY field2 ; field2 @@ -3095,7 +3095,9 @@ insert into t2 select b+10 from t2; insert into t2 select b+10 from t2; analyze table t1,t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK explain select a from t1, t2 where b between 1 and 2 and a in (select b from t2); diff --git a/mysql-test/main/subselect_sj.test b/mysql-test/main/subselect_sj.test index 04770761553..962a69c10c1 100644 --- a/mysql-test/main/subselect_sj.test +++ b/mysql-test/main/subselect_sj.test @@ -1462,7 +1462,7 @@ INSERT IGNORE INTO t3 VALUES (0); SELECT alias1.f11 AS field2 FROM ( t3 AS alias2 JOIN t1 AS alias3 ON alias3.f10 = 1) -LEFT JOIN ( t2 AS alias1 ) ON alias3.f11 = 1 +LEFT JOIN t2 AS alias1 ON alias3.f11 = 1 WHERE alias2.f11 IN ( SELECT f11 FROM t2 ) GROUP BY field2 ; diff --git a/mysql-test/main/subselect_sj2_mat.result b/mysql-test/main/subselect_sj2_mat.result index 884451d7dff..78df07667f9 100644 --- a/mysql-test/main/subselect_sj2_mat.result +++ b/mysql-test/main/subselect_sj2_mat.result @@ -1853,18 +1853,18 @@ AND t3.id_product IN (SELECT id_product FROM t2 t2_3 WHERE t2_3.id_t2 = 18 OR t2 AND t3.id_product IN (SELECT id_product FROM t2 t2_4 WHERE t2_4.id_t2 = 34 OR t2_4.id_t2 = 23) AND t3.id_product IN (SELECT id_product FROM t2 t2_5 WHERE t2_5.id_t2 = 29 OR t2_5.id_t2 = 28 OR t2_5.id_t2 = 26); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL PRIMARY 8 NULL 73 Using index -1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t1.id_product 1 Using index +1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 12 +1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t2_2.id_product 1 Using where; Using index 1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 4 func 1 Using where -1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 func 1 Using where -1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 Using where -1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 Using where -1 PRIMARY t4 eq_ref PRIMARY PRIMARY 8 test.t1.id_product,const 1 Using where; Using index -1 PRIMARY <subquery6> eq_ref distinct_key distinct_key 4 func 1 Using where 1 PRIMARY t5 ALL NULL NULL NULL NULL 18 Using where; Using join buffer (flat, BNL join) +1 PRIMARY <subquery6> eq_ref distinct_key distinct_key 4 func 1 Using where +1 PRIMARY t4 eq_ref PRIMARY PRIMARY 8 test.t3.id_product,const 1 Using where; Using index +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 Using where +1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 func 1 Using where +1 PRIMARY t1 index NULL PRIMARY 8 NULL 73 Using where; Using index; Using join buffer (flat, BNL join) +3 MATERIALIZED t2_2 ref id_t2,id_product id_t2 5 const 12 Using where 5 MATERIALIZED t2_4 range id_t2,id_product id_t2 5 NULL 18 Using index condition; Using where -4 MATERIALIZED t2_3 range id_t2,id_product id_t2 5 NULL 32 Using index condition; Using where -3 MATERIALIZED t2_2 ref id_t2,id_product id_t2 5 const 12 -2 MATERIALIZED t2_1 ref id_t2,id_product id_t2 5 const 50 6 MATERIALIZED t2_5 range id_t2,id_product id_t2 5 NULL 30 Using index condition; Using where +2 MATERIALIZED t2_1 ref id_t2,id_product id_t2 5 const 50 +4 MATERIALIZED t2_3 range id_t2,id_product id_t2 5 NULL 32 Using index condition; Using where drop table t1,t2,t3,t4,t5; diff --git a/mysql-test/main/subselect_sj_jcl6.result b/mysql-test/main/subselect_sj_jcl6.result index d7b77be7b54..cdc6f99d133 100644 --- a/mysql-test/main/subselect_sj_jcl6.result +++ b/mysql-test/main/subselect_sj_jcl6.result @@ -1688,7 +1688,7 @@ CREATE TABLE t3 ( f11 int) ; INSERT IGNORE INTO t3 VALUES (0); SELECT alias1.f11 AS field2 FROM ( t3 AS alias2 JOIN t1 AS alias3 ON alias3.f10 = 1) -LEFT JOIN ( t2 AS alias1 ) ON alias3.f11 = 1 +LEFT JOIN t2 AS alias1 ON alias3.f11 = 1 WHERE alias2.f11 IN ( SELECT f11 FROM t2 ) GROUP BY field2 ; field2 @@ -3109,7 +3109,9 @@ insert into t2 select b+10 from t2; insert into t2 select b+10 from t2; analyze table t1,t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK explain select a from t1, t2 where b between 1 and 2 and a in (select b from t2); diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result index 85c314e5fde..a494b9d1cf7 100644 --- a/mysql-test/main/subselect_sj_mat.result +++ b/mysql-test/main/subselect_sj_mat.result @@ -302,7 +302,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 16 func,func 1 100.00 1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 func,func 1 100.00 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where -3 MATERIALIZED t2i index it2i1,it2i2,it2i3 it2i3 18 NULL 5 80.00 Using where; Using index; Using join buffer (flat, BNL join) +3 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3.c1,test.t3.c2 2 100.00 Using index 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3`) where `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and `test`.`t2`.`b1` > '0' and `test`.`t3`.`c2` > '0' @@ -344,7 +344,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 16 func,func 1 100.00 1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 func,func 1 100.00 5 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where -5 MATERIALIZED t2i index it2i1,it2i2,it2i3 it2i3 18 NULL 5 80.00 Using where; Using index; Using join buffer (flat, BNL join) +5 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3.c1,test.t3.c2 2 100.00 Using index 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where 4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where @@ -370,7 +370,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 16 func,func 1 100.00 1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join) 5 MATERIALIZED t3c ALL NULL NULL NULL NULL 4 100.00 Using where -5 MATERIALIZED t2i index it2i1,it2i2,it2i3 it2i3 18 NULL 5 80.00 Using where; Using index; Using join buffer (flat, BNL join) +5 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3c.c1,test.t3c.c2 2 100.00 Using index 4 MATERIALIZED t3b ALL NULL NULL NULL NULL 4 100.00 Using where 3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where Warnings: @@ -403,7 +403,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY <subquery5> eq_ref distinct_key # # # 1 100.00 # 1 PRIMARY <subquery2> eq_ref distinct_key # # # 1 100.00 # 5 MATERIALIZED t3 ALL NULL # # # 4 100.00 # -5 MATERIALIZED t2i index it2i1,it2i2,it2i3 # # # 5 80.00 # +5 MATERIALIZED t2i ref it2i1,it2i2,it2i3 # # # 2 100.00 # 2 MATERIALIZED t2 ALL NULL # # # 5 100.00 # 4 MATERIALIZED t3 ALL NULL # # # 4 100.00 # 3 MATERIALIZED t3 ALL NULL # # # 4 100.00 # @@ -438,7 +438,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 16 func,func 1 100.00 4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where -4 MATERIALIZED t2i index it2i1,it2i2,it2i3 it2i3 18 NULL 5 80.00 Using where; Using index; Using join buffer (flat, BNL join) +4 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3.c1,test.t3.c2 2 100.00 Using index 2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL @@ -459,15 +459,15 @@ where (c1, c2) in (select b1, b2 from t2i where b2 > '0')) and a1 = c1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where +1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 4 100.00 Using where 1 PRIMARY t3 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) -1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 16 func,func 1 100.00 4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where -4 MATERIALIZED t2i index it2i1,it2i2,it2i3 it2i3 18 NULL 5 80.00 Using where; Using index; Using join buffer (flat, BNL join) +4 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3.c1,test.t3.c2 2 100.00 Using index 2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0' +Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and `test`.`t3`.`c2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0' select * from t1, t3 where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and (c1, c2) in (select c1, c2 from t3 @@ -1963,7 +1963,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(/*always not null*/ 1 is null) or `<subquery2>`.`MAX(c)` = 7) +Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(/*always not null*/ 1 is null) or `<subquery2>`.`MAX(c)` = 7) SELECT * FROM t1 WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b); a b @@ -2219,11 +2219,11 @@ drop database mysqltest4; # (both 1st and further executions) CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM; INSERT INTO t1 VALUES (0),(8); -SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2)); +SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2); a 0 PREPARE stmt FROM " -SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2)) +SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2) "; execute stmt; a @@ -2566,7 +2566,7 @@ select * from t1 where (a,b) in (select max(a),b from t2 group by b); show status where Variable_name like 'Handler_read%' or Variable_name like 'Handler_%write%'; Variable_name Value Handler_read_first 0 -Handler_read_key 5000 +Handler_read_key 5004 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 diff --git a/mysql-test/main/subselect_sj_mat.test b/mysql-test/main/subselect_sj_mat.test index 7853b528e8f..7b8179bba38 100644 --- a/mysql-test/main/subselect_sj_mat.test +++ b/mysql-test/main/subselect_sj_mat.test @@ -1848,9 +1848,9 @@ drop database mysqltest4; CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM; INSERT INTO t1 VALUES (0),(8); -SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2)); +SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2); PREPARE stmt FROM " -SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2)) +SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM t1 AS t2) "; execute stmt; execute stmt; diff --git a/mysql-test/main/system_mysql_db.result b/mysql-test/main/system_mysql_db.result index 2abcfb92ffa..e7cd9bc628b 100644 --- a/mysql-test/main/system_mysql_db.result +++ b/mysql-test/main/system_mysql_db.result @@ -6,12 +6,12 @@ db event func general_log +global_priv gtid_slave_pos help_category help_keyword help_relation help_topic -host index_stats innodb_index_stats innodb_table_stats @@ -59,84 +59,10 @@ db CREATE TABLE `db` ( `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', PRIMARY KEY (`Host`,`Db`,`User`), KEY `User` (`User`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges' -show create table host; -Table Create Table -host CREATE TABLE `host` ( - `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', - `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', - `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - PRIMARY KEY (`Host`,`Db`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Database privileges' show create table user; -Table Create Table -user CREATE TABLE `user` ( - `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', - `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', - `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', - `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', - `ssl_cipher` blob NOT NULL, - `x509_issuer` blob NOT NULL, - `x509_subject` blob NOT NULL, - `max_questions` int(11) unsigned NOT NULL DEFAULT 0, - `max_updates` int(11) unsigned NOT NULL DEFAULT 0, - `max_connections` int(11) unsigned NOT NULL DEFAULT 0, - `max_user_connections` int(11) NOT NULL DEFAULT 0, - `plugin` char(64) CHARACTER SET latin1 NOT NULL DEFAULT '', - `authentication_string` text COLLATE utf8_bin NOT NULL, - `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', - `max_statement_time` decimal(12,6) NOT NULL DEFAULT 0.000000, - PRIMARY KEY (`Host`,`User`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges' +View Create View character_set_client collation_connection +user CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `user` AS select `global_priv`.`Host` AS `Host`,`global_priv`.`User` AS `User`,if(json_value(`global_priv`.`Priv`,'$.plugin') in ('mysql_native_password','mysql_old_password'),ifnull(json_value(`global_priv`.`Priv`,'$.authentication_string'),''),'') AS `Password`,if(json_value(`global_priv`.`Priv`,'$.access') & 1,'Y','N') AS `Select_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2,'Y','N') AS `Insert_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4,'Y','N') AS `Update_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8,'Y','N') AS `Delete_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16,'Y','N') AS `Create_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 32,'Y','N') AS `Drop_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 64,'Y','N') AS `Reload_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 128,'Y','N') AS `Shutdown_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 256,'Y','N') AS `Process_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 512,'Y','N') AS `File_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 1024,'Y','N') AS `Grant_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2048,'Y','N') AS `References_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4096,'Y','N') AS `Index_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8192,'Y','N') AS `Alter_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16384,'Y','N') AS `Show_db_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 32768,'Y','N') AS `Super_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 65536,'Y','N') AS `Create_tmp_table_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 131072,'Y','N') AS `Lock_tables_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 262144,'Y','N') AS `Execute_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 524288,'Y','N') AS `Repl_slave_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 1048576,'Y','N') AS `Repl_client_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2097152,'Y','N') AS `Create_view_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4194304,'Y','N') AS `Show_view_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8388608,'Y','N') AS `Create_routine_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16777216,'Y','N') AS `Alter_routine_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 33554432,'Y','N') AS `Create_user_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 67108864,'Y','N') AS `Event_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 134217728,'Y','N') AS `Trigger_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 268435456,'Y','N') AS `Create_tablespace_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 536870912,'Y','N') AS `Delete_history_priv`,elt(ifnull(json_value(`global_priv`.`Priv`,'$.ssl_type'),0) + 1,'','ANY','X509','SPECIFIED') AS `ssl_type`,ifnull(json_value(`global_priv`.`Priv`,'$.ssl_cipher'),'') AS `ssl_cipher`,ifnull(json_value(`global_priv`.`Priv`,'$.x509_issuer'),'') AS `x509_issuer`,ifnull(json_value(`global_priv`.`Priv`,'$.x509_subject'),'') AS `x509_subject`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_questions'),0) as unsigned) AS `max_questions`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_updates'),0) as unsigned) AS `max_updates`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_connections'),0) as unsigned) AS `max_connections`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_user_connections'),0) as signed) AS `max_user_connections`,ifnull(json_value(`global_priv`.`Priv`,'$.plugin'),'') AS `plugin`,ifnull(json_value(`global_priv`.`Priv`,'$.authentication_string'),'') AS `authentication_string`,'N' AS `password_expired`,elt(ifnull(json_value(`global_priv`.`Priv`,'$.is_role'),0) + 1,'N','Y') AS `is_role`,ifnull(json_value(`global_priv`.`Priv`,'$.default_role'),'') AS `default_role`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_statement_time'),0.0) as decimal(12,6)) AS `max_statement_time` from `global_priv` latin1 latin1_swedish_ci show create table func; Table Create Table func CREATE TABLE `func` ( @@ -145,7 +71,15 @@ func CREATE TABLE `func` ( `dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '', `type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL, PRIMARY KEY (`name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User defined functions' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User defined functions' +show create table global_priv; +Table Create Table +global_priv CREATE TABLE `global_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Priv` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), + PRIMARY KEY (`Host`,`User`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table tables_priv; Table Create Table tables_priv CREATE TABLE `tables_priv` ( @@ -159,7 +93,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Table privileges' show create table columns_priv; Table Create Table columns_priv CREATE TABLE `columns_priv` ( @@ -171,7 +105,7 @@ columns_priv CREATE TABLE `columns_priv` ( `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Column privileges' show create table procs_priv; Table Create Table procs_priv CREATE TABLE `procs_priv` ( @@ -185,7 +119,7 @@ procs_priv CREATE TABLE `procs_priv` ( `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`), KEY `Grantor` (`Grantor`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Procedure privileges' show create table servers; Table Create Table servers CREATE TABLE `servers` ( @@ -199,7 +133,7 @@ servers CREATE TABLE `servers` ( `Wrapper` char(64) NOT NULL DEFAULT '', `Owner` char(64) NOT NULL DEFAULT '', PRIMARY KEY (`Server_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL Foreign Servers table' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL Foreign Servers table' show create table proc; Table Create Table proc CREATE TABLE `proc` ( @@ -217,7 +151,7 @@ proc CREATE TABLE `proc` ( `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, @@ -225,7 +159,7 @@ proc CREATE TABLE `proc` ( `body_utf8` longblob DEFAULT NULL, `aggregate` enum('NONE','GROUP') NOT NULL DEFAULT 'NONE', PRIMARY KEY (`db`,`name`,`type`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Stored Procedures' show create table event; Table Create Table event CREATE TABLE `event` ( @@ -243,7 +177,7 @@ event CREATE TABLE `event` ( `ends` datetime DEFAULT NULL, `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `originator` int(10) unsigned NOT NULL, `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', @@ -252,7 +186,7 @@ event CREATE TABLE `event` ( `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `body_utf8` longblob DEFAULT NULL, PRIMARY KEY (`db`,`name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events' show create table general_log; Table Create Table general_log CREATE TABLE `general_log` ( @@ -287,7 +221,7 @@ table_stats CREATE TABLE `table_stats` ( `table_name` varchar(64) COLLATE utf8_bin NOT NULL, `cardinality` bigint(21) unsigned DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Tables' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Tables' show create table column_stats; Table Create Table column_stats CREATE TABLE `column_stats` ( @@ -303,7 +237,7 @@ column_stats CREATE TABLE `column_stats` ( `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8_bin DEFAULT NULL, `histogram` varbinary(255) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`column_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Columns' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns' show create table index_stats; Table Create Table index_stats CREATE TABLE `index_stats` ( @@ -313,6 +247,6 @@ index_stats CREATE TABLE `index_stats` ( `prefix_arity` int(11) unsigned NOT NULL, `avg_frequency` decimal(12,4) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Indexes' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes' show tables; Tables_in_test diff --git a/mysql-test/main/no_password_column-mdev-11170.result b/mysql-test/main/system_mysql_db_507.result index 6195100436d..1fa4af66719 100644 --- a/mysql-test/main/no_password_column-mdev-11170.result +++ b/mysql-test/main/system_mysql_db_507.result @@ -3,8 +3,6 @@ # Fatal error: mysql.user table is damaged or in # unsupported 3.20 format # -create table backup_user like mysql.user; -insert into backup_user select * from mysql.user; # # Original mysql.user table # @@ -60,7 +58,12 @@ max_statement_time decimal(12,6) NO 0.000000 # # Drop the password column. # -alter table mysql.user drop column password; +alter table mysql.user drop column password, +drop column is_role, +drop column default_role, +add column password_last_changed timestamp null default null after password_expired, +add column password_lifetime smallint unsigned after password_last_changed, +add column account_locked enum('n','y') character set utf8 not null default 'n' after password_lifetime; flush privileges; # # Create users without the password column present. @@ -87,7 +90,7 @@ select user, host, select_priv, plugin, authentication_string from mysql.user where user like "%oo" order by user; user host select_priv plugin authentication_string -foo % N +foo % N mysql_native_password goo % N mysql_native_password *F3A2A51A9B0F2BE2468926B4132313728C250DBF ioo % N mysql_old_password 7a8f886d28473e85 # @@ -164,6 +167,3 @@ ioo % Y mysql_old_password 7a8f886d28473e85 # # Reset to final original state. # -drop table mysql.user; -rename table backup_user to mysql.user; -flush privileges; diff --git a/mysql-test/main/no_password_column-mdev-11170.test b/mysql-test/main/system_mysql_db_507.test index 2cc4ba82ee8..b57a2a09c8e 100644 --- a/mysql-test/main/no_password_column-mdev-11170.test +++ b/mysql-test/main/system_mysql_db_507.test @@ -5,9 +5,7 @@ --echo # unsupported 3.20 format --echo # - -create table backup_user like mysql.user; -insert into backup_user select * from mysql.user; +--source include/switch_to_mysql_user.inc --echo # --echo # Original mysql.user table @@ -17,7 +15,12 @@ describe mysql.user; --echo # --echo # Drop the password column. --echo # -alter table mysql.user drop column password; +alter table mysql.user drop column password, + drop column is_role, + drop column default_role, + add column password_last_changed timestamp null default null after password_expired, + add column password_lifetime smallint unsigned after password_last_changed, + add column account_locked enum('n','y') character set utf8 not null default 'n' after password_lifetime; flush privileges; --echo # @@ -85,11 +88,7 @@ select user, host, select_priv, plugin, authentication_string from mysql.user where user like "%oo" order by user; - --echo # --echo # Reset to final original state. --echo # -drop table mysql.user; -rename table backup_user to mysql.user; - -flush privileges; +--source include/switch_to_mysql_global_priv.inc diff --git a/mysql-test/main/system_mysql_db_fix40123.result b/mysql-test/main/system_mysql_db_fix40123.result index 2abcfb92ffa..c4c4d3df706 100644 --- a/mysql-test/main/system_mysql_db_fix40123.result +++ b/mysql-test/main/system_mysql_db_fix40123.result @@ -6,6 +6,7 @@ db event func general_log +global_priv gtid_slave_pos help_category help_keyword @@ -59,32 +60,7 @@ db CREATE TABLE `db` ( `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', PRIMARY KEY (`Host`,`Db`,`User`), KEY `User` (`User`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges' -show create table host; -Table Create Table -host CREATE TABLE `host` ( - `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', - `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', - `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - PRIMARY KEY (`Host`,`Db`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Database privileges' show create table user; Table Create Table user CREATE TABLE `user` ( @@ -136,7 +112,7 @@ user CREATE TABLE `user` ( `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', `max_statement_time` decimal(12,6) NOT NULL DEFAULT 0.000000, PRIMARY KEY (`Host`,`User`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table func; Table Create Table func CREATE TABLE `func` ( @@ -145,7 +121,15 @@ func CREATE TABLE `func` ( `dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '', `type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL, PRIMARY KEY (`name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User defined functions' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User defined functions' +show create table global_priv; +Table Create Table +global_priv CREATE TABLE `global_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Priv` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), + PRIMARY KEY (`Host`,`User`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table tables_priv; Table Create Table tables_priv CREATE TABLE `tables_priv` ( @@ -159,7 +143,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Table privileges' show create table columns_priv; Table Create Table columns_priv CREATE TABLE `columns_priv` ( @@ -171,7 +155,7 @@ columns_priv CREATE TABLE `columns_priv` ( `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Column privileges' show create table procs_priv; Table Create Table procs_priv CREATE TABLE `procs_priv` ( @@ -185,7 +169,7 @@ procs_priv CREATE TABLE `procs_priv` ( `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`), KEY `Grantor` (`Grantor`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Procedure privileges' show create table servers; Table Create Table servers CREATE TABLE `servers` ( @@ -199,7 +183,7 @@ servers CREATE TABLE `servers` ( `Wrapper` char(64) NOT NULL DEFAULT '', `Owner` char(64) NOT NULL DEFAULT '', PRIMARY KEY (`Server_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL Foreign Servers table' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL Foreign Servers table' show create table proc; Table Create Table proc CREATE TABLE `proc` ( @@ -217,7 +201,7 @@ proc CREATE TABLE `proc` ( `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, @@ -225,7 +209,7 @@ proc CREATE TABLE `proc` ( `body_utf8` longblob DEFAULT NULL, `aggregate` enum('NONE','GROUP') NOT NULL DEFAULT 'NONE', PRIMARY KEY (`db`,`name`,`type`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Stored Procedures' show create table event; Table Create Table event CREATE TABLE `event` ( @@ -243,7 +227,7 @@ event CREATE TABLE `event` ( `ends` datetime DEFAULT NULL, `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `originator` int(10) unsigned NOT NULL, `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', @@ -252,7 +236,7 @@ event CREATE TABLE `event` ( `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `body_utf8` longblob DEFAULT NULL, PRIMARY KEY (`db`,`name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events' show create table general_log; Table Create Table general_log CREATE TABLE `general_log` ( @@ -287,7 +271,7 @@ table_stats CREATE TABLE `table_stats` ( `table_name` varchar(64) COLLATE utf8_bin NOT NULL, `cardinality` bigint(21) unsigned DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Tables' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Tables' show create table column_stats; Table Create Table column_stats CREATE TABLE `column_stats` ( @@ -303,7 +287,7 @@ column_stats CREATE TABLE `column_stats` ( `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8_bin DEFAULT NULL, `histogram` varbinary(255) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`column_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Columns' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns' show create table index_stats; Table Create Table index_stats CREATE TABLE `index_stats` ( @@ -313,6 +297,6 @@ index_stats CREATE TABLE `index_stats` ( `prefix_arity` int(11) unsigned NOT NULL, `avg_frequency` decimal(12,4) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Indexes' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes' show tables; Tables_in_test diff --git a/mysql-test/main/system_mysql_db_fix40123.test b/mysql-test/main/system_mysql_db_fix40123.test index 2d17a0964e5..3f313c4ec1f 100644 --- a/mysql-test/main/system_mysql_db_fix40123.test +++ b/mysql-test/main/system_mysql_db_fix40123.test @@ -72,7 +72,7 @@ CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, -- disable_query_log # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos; +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; -- enable_query_log diff --git a/mysql-test/main/system_mysql_db_fix50030.result b/mysql-test/main/system_mysql_db_fix50030.result index 81b6da4c16d..3a79afb04f0 100644 --- a/mysql-test/main/system_mysql_db_fix50030.result +++ b/mysql-test/main/system_mysql_db_fix50030.result @@ -6,6 +6,7 @@ db event func general_log +global_priv gtid_slave_pos help_category help_keyword @@ -59,32 +60,7 @@ db CREATE TABLE `db` ( `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', PRIMARY KEY (`Host`,`Db`,`User`), KEY `User` (`User`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges' -show create table host; -Table Create Table -host CREATE TABLE `host` ( - `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', - `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', - `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - PRIMARY KEY (`Host`,`Db`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Database privileges' show create table user; Table Create Table user CREATE TABLE `user` ( @@ -136,7 +112,7 @@ user CREATE TABLE `user` ( `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', `max_statement_time` decimal(12,6) NOT NULL DEFAULT 0.000000, PRIMARY KEY (`Host`,`User`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table func; Table Create Table func CREATE TABLE `func` ( @@ -145,7 +121,15 @@ func CREATE TABLE `func` ( `dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '', `type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL, PRIMARY KEY (`name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User defined functions' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User defined functions' +show create table global_priv; +Table Create Table +global_priv CREATE TABLE `global_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Priv` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), + PRIMARY KEY (`Host`,`User`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table tables_priv; Table Create Table tables_priv CREATE TABLE `tables_priv` ( @@ -159,7 +143,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Table privileges' show create table columns_priv; Table Create Table columns_priv CREATE TABLE `columns_priv` ( @@ -171,7 +155,7 @@ columns_priv CREATE TABLE `columns_priv` ( `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Column privileges' show create table procs_priv; Table Create Table procs_priv CREATE TABLE `procs_priv` ( @@ -185,7 +169,7 @@ procs_priv CREATE TABLE `procs_priv` ( `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`), KEY `Grantor` (`Grantor`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Procedure privileges' show create table servers; Table Create Table servers CREATE TABLE `servers` ( @@ -199,7 +183,7 @@ servers CREATE TABLE `servers` ( `Wrapper` char(64) NOT NULL DEFAULT '', `Owner` char(64) NOT NULL DEFAULT '', PRIMARY KEY (`Server_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL Foreign Servers table' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL Foreign Servers table' show create table proc; Table Create Table proc CREATE TABLE `proc` ( @@ -217,7 +201,7 @@ proc CREATE TABLE `proc` ( `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, @@ -225,7 +209,7 @@ proc CREATE TABLE `proc` ( `body_utf8` longblob DEFAULT NULL, `aggregate` enum('NONE','GROUP') NOT NULL DEFAULT 'NONE', PRIMARY KEY (`db`,`name`,`type`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Stored Procedures' show create table event; Table Create Table event CREATE TABLE `event` ( @@ -243,7 +227,7 @@ event CREATE TABLE `event` ( `ends` datetime DEFAULT NULL, `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `originator` int(10) unsigned NOT NULL, `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', @@ -252,7 +236,7 @@ event CREATE TABLE `event` ( `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `body_utf8` longblob DEFAULT NULL, PRIMARY KEY (`db`,`name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events' show create table general_log; Table Create Table general_log CREATE TABLE `general_log` ( @@ -287,7 +271,7 @@ table_stats CREATE TABLE `table_stats` ( `table_name` varchar(64) COLLATE utf8_bin NOT NULL, `cardinality` bigint(21) unsigned DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Tables' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Tables' show create table column_stats; Table Create Table column_stats CREATE TABLE `column_stats` ( @@ -303,7 +287,7 @@ column_stats CREATE TABLE `column_stats` ( `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8_bin DEFAULT NULL, `histogram` varbinary(255) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`column_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Columns' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns' show create table index_stats; Table Create Table index_stats CREATE TABLE `index_stats` ( @@ -313,6 +297,6 @@ index_stats CREATE TABLE `index_stats` ( `prefix_arity` int(11) unsigned NOT NULL, `avg_frequency` decimal(12,4) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Indexes' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes' show tables; Tables_in_test diff --git a/mysql-test/main/system_mysql_db_fix50030.test b/mysql-test/main/system_mysql_db_fix50030.test index 9506c3465e7..33dcc873615 100644 --- a/mysql-test/main/system_mysql_db_fix50030.test +++ b/mysql-test/main/system_mysql_db_fix50030.test @@ -79,7 +79,7 @@ INSERT INTO servers VALUES ('test','localhost','test','root','', 0,'','mysql','r -- disable_query_log # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos; +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; -- enable_query_log diff --git a/mysql-test/main/system_mysql_db_fix50117.result b/mysql-test/main/system_mysql_db_fix50117.result index 2abcfb92ffa..c4c4d3df706 100644 --- a/mysql-test/main/system_mysql_db_fix50117.result +++ b/mysql-test/main/system_mysql_db_fix50117.result @@ -6,6 +6,7 @@ db event func general_log +global_priv gtid_slave_pos help_category help_keyword @@ -59,32 +60,7 @@ db CREATE TABLE `db` ( `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', PRIMARY KEY (`Host`,`Db`,`User`), KEY `User` (`User`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges' -show create table host; -Table Create Table -host CREATE TABLE `host` ( - `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', - `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', - `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - PRIMARY KEY (`Host`,`Db`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Database privileges' show create table user; Table Create Table user CREATE TABLE `user` ( @@ -136,7 +112,7 @@ user CREATE TABLE `user` ( `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', `max_statement_time` decimal(12,6) NOT NULL DEFAULT 0.000000, PRIMARY KEY (`Host`,`User`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table func; Table Create Table func CREATE TABLE `func` ( @@ -145,7 +121,15 @@ func CREATE TABLE `func` ( `dl` char(128) COLLATE utf8_bin NOT NULL DEFAULT '', `type` enum('function','aggregate') CHARACTER SET utf8 NOT NULL, PRIMARY KEY (`name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User defined functions' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User defined functions' +show create table global_priv; +Table Create Table +global_priv CREATE TABLE `global_priv` ( + `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `Priv` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}' CHECK (json_valid(`Priv`)), + PRIMARY KEY (`Host`,`User`) +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' show create table tables_priv; Table Create Table tables_priv CREATE TABLE `tables_priv` ( @@ -159,7 +143,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Table privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Table privileges' show create table columns_priv; Table Create Table columns_priv CREATE TABLE `columns_priv` ( @@ -171,7 +155,7 @@ columns_priv CREATE TABLE `columns_priv` ( `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `Column_priv` set('Select','Insert','Update','References') CHARACTER SET utf8 NOT NULL DEFAULT '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`,`Column_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Column privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Column privileges' show create table procs_priv; Table Create Table procs_priv CREATE TABLE `procs_priv` ( @@ -185,7 +169,7 @@ procs_priv CREATE TABLE `procs_priv` ( `Timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`), KEY `Grantor` (`Grantor`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Procedure privileges' show create table servers; Table Create Table servers CREATE TABLE `servers` ( @@ -199,7 +183,7 @@ servers CREATE TABLE `servers` ( `Wrapper` char(64) NOT NULL DEFAULT '', `Owner` char(64) NOT NULL DEFAULT '', PRIMARY KEY (`Server_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='MySQL Foreign Servers table' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='MySQL Foreign Servers table' show create table proc; Table Create Table proc CREATE TABLE `proc` ( @@ -217,7 +201,7 @@ proc CREATE TABLE `proc` ( `definer` char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `created` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `character_set_client` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `collation_connection` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, @@ -225,7 +209,7 @@ proc CREATE TABLE `proc` ( `body_utf8` longblob DEFAULT NULL, `aggregate` enum('NONE','GROUP') NOT NULL DEFAULT 'NONE', PRIMARY KEY (`db`,`name`,`type`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Stored Procedures' show create table event; Table Create Table event CREATE TABLE `event` ( @@ -243,7 +227,7 @@ event CREATE TABLE `event` ( `ends` datetime DEFAULT NULL, `status` enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL DEFAULT 'ENABLED', `on_completion` enum('DROP','PRESERVE') NOT NULL DEFAULT 'DROP', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NOT NULL DEFAULT '', + `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NOT NULL DEFAULT '', `comment` char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `originator` int(10) unsigned NOT NULL, `time_zone` char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', @@ -252,7 +236,7 @@ event CREATE TABLE `event` ( `db_collation` char(32) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `body_utf8` longblob DEFAULT NULL, PRIMARY KEY (`db`,`name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events' +) ENGINE=Aria DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Events' show create table general_log; Table Create Table general_log CREATE TABLE `general_log` ( @@ -287,7 +271,7 @@ table_stats CREATE TABLE `table_stats` ( `table_name` varchar(64) COLLATE utf8_bin NOT NULL, `cardinality` bigint(21) unsigned DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Tables' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Tables' show create table column_stats; Table Create Table column_stats CREATE TABLE `column_stats` ( @@ -303,7 +287,7 @@ column_stats CREATE TABLE `column_stats` ( `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8_bin DEFAULT NULL, `histogram` varbinary(255) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`column_name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Columns' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns' show create table index_stats; Table Create Table index_stats CREATE TABLE `index_stats` ( @@ -313,6 +297,6 @@ index_stats CREATE TABLE `index_stats` ( `prefix_arity` int(11) unsigned NOT NULL, `avg_frequency` decimal(12,4) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Indexes' +) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes' show tables; Tables_in_test diff --git a/mysql-test/main/system_mysql_db_fix50117.test b/mysql-test/main/system_mysql_db_fix50117.test index f8bef3da162..2fe6869d761 100644 --- a/mysql-test/main/system_mysql_db_fix50117.test +++ b/mysql-test/main/system_mysql_db_fix50117.test @@ -96,7 +96,7 @@ CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_b -- disable_query_log # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos; +DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; -- enable_query_log diff --git a/mysql-test/main/system_mysql_db_refs.result b/mysql-test/main/system_mysql_db_refs.result index 96ecd2f27c0..870a550bb95 100644 --- a/mysql-test/main/system_mysql_db_refs.result +++ b/mysql-test/main/system_mysql_db_refs.result @@ -2,9 +2,6 @@ set @name="This is a very long string, that mustn't find room in a system field create table test_db select * from mysql.db; delete from test_db; insert ignore into test_db (Host,Db,User) values (@name,@name,@name); -create table test_host select * from mysql.host; -delete from test_host; -insert ignore into test_host (Host,Db) values (@name,@name); create table test_user select * from mysql.user; delete from test_user; insert ignore into test_user (Host,User) values (@name,@name); @@ -19,28 +16,24 @@ delete from test_columns_priv; insert ignore into test_columns_priv (Host,Db,User,Table_name,Column_name) values (@name,@name,@name,@name,@name); select if(isnull(test_db.Host),'WRONG!!!','ok') as test_db_Host, -if(isnull(test_host.Host),'WRONG!!!','ok') as test_host_Host, if(isnull(test_user.Host),'WRONG!!!','ok') as test_user_Host, if(isnull(test_tables_priv.Host),'WRONG!!!','ok') as test_tables_priv_Host, if(isnull(test_columns_priv.Host),'WRONG!!!','ok') as test_columns_priv_Host from test_db -left join test_host on test_db.Host=test_host.Host left join test_user on test_db.Host=test_user.Host left join test_tables_priv on test_db.Host=test_tables_priv.Host left join test_columns_priv on test_db.Host=test_columns_priv.Host; -test_db_Host test_host_Host test_user_Host test_tables_priv_Host test_columns_priv_Host -ok ok ok ok ok +test_db_Host test_user_Host test_tables_priv_Host test_columns_priv_Host +ok ok ok ok select if(isnull(test_db.Db),'WRONG!!!','ok') as test_db_Db, -if(isnull(test_host.Db),'WRONG!!!','ok') as test_host_Db, if(isnull(test_tables_priv.Db),'WRONG!!!','ok') as test_tables_priv_Db, if(isnull(test_columns_priv.Db),'WRONG!!!','ok') as est_columns_priv_Db from test_db -left join test_host on test_db.Db=test_host.Db left join test_tables_priv on test_db.Db=test_tables_priv.Db left join test_columns_priv on test_db.Db=test_columns_priv.Db; -test_db_Db test_host_Db test_tables_priv_Db est_columns_priv_Db -ok ok ok ok +test_db_Db test_tables_priv_Db est_columns_priv_Db +ok ok ok select if(isnull(test_db.User),'WRONG!!!','ok') as test_db_User, if(isnull(test_user.User),'WRONG!!!','ok') as test_user_User, @@ -62,6 +55,5 @@ ok ok drop table test_columns_priv; drop table test_tables_priv; drop table test_func; -drop table test_host; drop table test_user; drop table test_db; diff --git a/mysql-test/main/system_mysql_db_refs.test b/mysql-test/main/system_mysql_db_refs.test index 63f30e7db63..084d5bbf868 100644 --- a/mysql-test/main/system_mysql_db_refs.test +++ b/mysql-test/main/system_mysql_db_refs.test @@ -14,12 +14,6 @@ delete from test_db; insert ignore into test_db (Host,Db,User) values (@name,@name,@name); --enable_warnings -create table test_host select * from mysql.host; -delete from test_host; ---disable_warnings -insert ignore into test_host (Host,Db) values (@name,@name); ---enable_warnings - create table test_user select * from mysql.user; delete from test_user; --disable_warnings @@ -48,13 +42,11 @@ insert ignore into test_columns_priv (Host,Db,User,Table_name,Column_name) value select if(isnull(test_db.Host),'WRONG!!!','ok') as test_db_Host, - if(isnull(test_host.Host),'WRONG!!!','ok') as test_host_Host, if(isnull(test_user.Host),'WRONG!!!','ok') as test_user_Host, if(isnull(test_tables_priv.Host),'WRONG!!!','ok') as test_tables_priv_Host, if(isnull(test_columns_priv.Host),'WRONG!!!','ok') as test_columns_priv_Host from test_db -left join test_host on test_db.Host=test_host.Host left join test_user on test_db.Host=test_user.Host left join test_tables_priv on test_db.Host=test_tables_priv.Host left join test_columns_priv on test_db.Host=test_columns_priv.Host; @@ -63,12 +55,10 @@ left join test_columns_priv on test_db.Host=test_columns_priv.Host; select if(isnull(test_db.Db),'WRONG!!!','ok') as test_db_Db, - if(isnull(test_host.Db),'WRONG!!!','ok') as test_host_Db, if(isnull(test_tables_priv.Db),'WRONG!!!','ok') as test_tables_priv_Db, if(isnull(test_columns_priv.Db),'WRONG!!!','ok') as est_columns_priv_Db from test_db -left join test_host on test_db.Db=test_host.Db left join test_tables_priv on test_db.Db=test_tables_priv.Db left join test_columns_priv on test_db.Db=test_columns_priv.Db; @@ -96,7 +86,6 @@ left join test_columns_priv on test_tables_priv.Table_name=test_columns_priv.Tab drop table test_columns_priv; drop table test_tables_priv; drop table test_func; -drop table test_host; drop table test_user; drop table test_db; diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result index 1d485af4a4d..454356bb5fb 100644 --- a/mysql-test/main/table_value_constr.result +++ b/mysql-test/main/table_value_constr.result @@ -366,7 +366,6 @@ values (1,2); 1 2 1 2 3 4 -1 2 # combination of different structures that uses VALUES structures : UNION + UNION ALL values (1,2),(3,4) union all diff --git a/mysql-test/main/temp_table_frm.result b/mysql-test/main/temp_table_frm.result index 19c66380af2..a9c59ff5969 100644 --- a/mysql-test/main/temp_table_frm.result +++ b/mysql-test/main/temp_table_frm.result @@ -1,3 +1,7 @@ +set @save_use_stat_tables= @@use_stat_tables; +set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity; +set @@optimizer_use_condition_selectivity=1; +set @@use_stat_tables= NEVER; set @@session.max_heap_table_size=16*1024*1024; create table t1 select * from information_schema.session_status where variable_name like 'Opened%'; create temporary table t2 (a int) engine=memory; @@ -18,4 +22,6 @@ OPENED_PLUGIN_LIBRARIES 0 OPENED_TABLE_DEFINITIONS 2 OPENED_TABLES 1 OPENED_VIEWS 0 +set @@use_stat_tables= @save_use_stat_tables; +set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; drop table t1; diff --git a/mysql-test/main/temp_table_frm.test b/mysql-test/main/temp_table_frm.test index 178bd15004b..ddc4ffa575c 100644 --- a/mysql-test/main/temp_table_frm.test +++ b/mysql-test/main/temp_table_frm.test @@ -3,6 +3,11 @@ # # Ensure we don't overflow the internal heap table size in the join +set @save_use_stat_tables= @@use_stat_tables; +set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity; + +set @@optimizer_use_condition_selectivity=1; +set @@use_stat_tables= NEVER; set @@session.max_heap_table_size=16*1024*1024; create table t1 select * from information_schema.session_status where variable_name like 'Opened%'; create temporary table t2 (a int) engine=memory; @@ -13,4 +18,6 @@ let $tmpdir= `select @@tmpdir`; truncate table t2; select variable_name, session_status.variable_value - t1.variable_value from information_schema.session_status join t1 using (variable_name); -drop table t1; +set @@use_stat_tables= @save_use_stat_tables; +set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; +drop table t1;
\ No newline at end of file diff --git a/mysql-test/main/temporal_literal.result b/mysql-test/main/temporal_literal.result index d2417d7f9eb..2197b990f3b 100644 --- a/mysql-test/main/temporal_literal.result +++ b/mysql-test/main/temporal_literal.result @@ -294,17 +294,17 @@ SELECT TIMESTAMP'2001-00-00 00:00:00.9999999'; TIMESTAMP'2001-00-00 00:00:00.9999999' 2001-00-00 00:00:00.999999 Warnings: -Note 1292 Truncated incorrect datetime value: '2001-00-00 00:00:00.9999999' +Note 1292 Truncated incorrect DATETIME value: '2001-00-00 00:00:00.9999999' SELECT TIMESTAMP'2001-00-01 00:00:00.9999999'; TIMESTAMP'2001-00-01 00:00:00.9999999' 2001-00-01 00:00:00.999999 Warnings: -Note 1292 Truncated incorrect datetime value: '2001-00-01 00:00:00.9999999' +Note 1292 Truncated incorrect DATETIME value: '2001-00-01 00:00:00.9999999' SELECT TIMESTAMP'2001-01-00 00:00:00.9999999'; TIMESTAMP'2001-01-00 00:00:00.9999999' 2001-01-00 00:00:00.999999 Warnings: -Note 1292 Truncated incorrect datetime value: '2001-01-00 00:00:00.9999999' +Note 1292 Truncated incorrect DATETIME value: '2001-01-00 00:00:00.9999999' # # String literal with bad dates and nanoseconds to DATETIME(N) # @@ -416,7 +416,7 @@ SELECT TIME'10:10:10.1234567'; TIME'10:10:10.1234567' 10:10:10.123456 Warnings: -Note 1292 Truncated incorrect time value: '10:10:10.1234567' +Note 1292 Truncated incorrect TIME value: '10:10:10.1234567' SELECT TIME('10:10:10.1234567'); TIME('10:10:10.1234567') 10:10:10.123456 @@ -440,7 +440,7 @@ SELECT TIMESTAMP'2001-01-01 10:10:10.1234567'; TIMESTAMP'2001-01-01 10:10:10.1234567' 2001-01-01 10:10:10.123456 Warnings: -Note 1292 Truncated incorrect datetime value: '2001-01-01 10:10:10.1234567' +Note 1292 Truncated incorrect DATETIME value: '2001-01-01 10:10:10.1234567' SELECT TIMESTAMP('2001-01-01 10:10:10.1234567'); TIMESTAMP('2001-01-01 10:10:10.1234567') 2001-01-01 10:10:10.123456 @@ -463,7 +463,7 @@ Warning 1292 Truncated incorrect datetime value: '2001-01-01 10:10:10.1234567xyz CREATE TABLE t1 (a TIME(6)); INSERT INTO t1 VALUES (TIME'10:20:30.1234567'); Warnings: -Note 1292 Truncated incorrect time value: '10:20:30.1234567' +Note 1292 Truncated incorrect TIME value: '10:20:30.1234567' INSERT INTO t1 VALUES (TIME('10:20:30.1234567')); Warnings: Note 1292 Truncated incorrect time value: '10:20:30.1234567' diff --git a/mysql-test/main/timezone2.result b/mysql-test/main/timezone2.result index 096e996bffb..dd137045d1a 100644 --- a/mysql-test/main/timezone2.result +++ b/mysql-test/main/timezone2.result @@ -332,3 +332,228 @@ NULL # # End of 5.3 tests # +# +# Start of 10.4 tests +# +# +# MDEV-17203 Move fractional second truncation from Item_xxx_typecast::get_date() to Time and Datetime constructors +# (an addition for the test for MDEV-4653) +SET timestamp=unix_timestamp('2001-02-03 10:20:30'); +SET old_mode=ZERO_DATE_TIME_CAST; +SELECT CONVERT_TZ(TIME('00:00:00'),'+00:00','+7:5'); +CONVERT_TZ(TIME('00:00:00'),'+00:00','+7:5') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '00:00:00' +SELECT CONVERT_TZ(TIME('2010-01-01 00:00:00'),'+00:00','+7:5'); +CONVERT_TZ(TIME('2010-01-01 00:00:00'),'+00:00','+7:5') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '00:00:00' +SET old_mode=DEFAULT; +SET timestamp=DEFAULT; +# +# MDEV-13995 MAX(timestamp) returns a wrong result near DST change +# +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/); +SET time_zone='Europe/Moscow'; +SELECT a, UNIX_TIMESTAMP(a) FROM t1; +a UNIX_TIMESTAMP(a) +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:25 1288481125 +SELECT UNIX_TIMESTAMP(MAX(a)) AS a FROM t1; +a +1288481125 +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t2 SELECT MAX(a) AS a FROM t1; +SELECT a, UNIX_TIMESTAMP(a) FROM t2; +a UNIX_TIMESTAMP(a) +2010-10-31 02:25:25 1288481125 +DROP TABLE t2; +DROP TABLE t1; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP); +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/); +INSERT INTO t2 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/); +SET time_zone='Europe/Moscow'; +SELECT UNIX_TIMESTAMP(t1.a), UNIX_TIMESTAMP(t2.a) FROM t1,t2; +UNIX_TIMESTAMP(t1.a) UNIX_TIMESTAMP(t2.a) +1288477526 1288481125 +SELECT * FROM t1,t2 WHERE t1.a < t2.a; +a a +2010-10-31 02:25:26 2010-10-31 02:25:25 +DROP TABLE t1,t2; +BEGIN NOT ATOMIC +DECLARE a,b TIMESTAMP; +SET time_zone='+00:00'; +SET a=FROM_UNIXTIME(1288477526); +SET b=FROM_UNIXTIME(1288481125); +SELECT a < b; +SET time_zone='Europe/Moscow'; +SELECT a < b; +END; +$$ +a < b +1 +a < b +1 +CREATE OR REPLACE FUNCTION f1(uts INT) RETURNS TIMESTAMP +BEGIN +DECLARE ts TIMESTAMP; +DECLARE tz VARCHAR(64) DEFAULT @@time_zone; +SET time_zone='+00:00'; +SET ts=FROM_UNIXTIME(uts); +SET time_zone=tz; +RETURN ts; +END; +$$ +SET time_zone='+00:00'; +SELECT f1(1288477526) < f1(1288481125); +f1(1288477526) < f1(1288481125) +1 +SET time_zone='Europe/Moscow'; +SELECT f1(1288477526) < f1(1288481125); +f1(1288477526) < f1(1288481125) +1 +DROP FUNCTION f1; +CREATE TABLE t1 (a TIMESTAMP,b TIMESTAMP); +SET time_zone='+00:00'; +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/, +FROM_UNIXTIME(1288481125) /*winter time in Moscow*/); +SELECT *, LEAST(a,b) FROM t1; +a b LEAST(a,b) +2010-10-30 22:25:26 2010-10-30 23:25:25 2010-10-30 22:25:26 +SET time_zone='Europe/Moscow'; +SELECT *, LEAST(a,b) FROM t1; +a b LEAST(a,b) +2010-10-31 02:25:26 2010-10-31 02:25:25 2010-10-31 02:25:26 +SELECT UNIX_TIMESTAMP(a), UNIX_TIMESTAMP(b), UNIX_TIMESTAMP(LEAST(a,b)) FROM t1; +UNIX_TIMESTAMP(a) UNIX_TIMESTAMP(b) UNIX_TIMESTAMP(LEAST(a,b)) +1288477526 1288481125 1288477526 +DROP TABLE t1; +CREATE TABLE t1 (a TIMESTAMP,b TIMESTAMP,c TIMESTAMP); +SET time_zone='+00:00'; +INSERT INTO t1 VALUES ( +FROM_UNIXTIME(1288477526) /*summer time in Moscow*/, +FROM_UNIXTIME(1288481125) /*winter time in Moscow*/, +FROM_UNIXTIME(1288481126) /*winter time in Moscow*/); +SELECT b BETWEEN a AND c FROM t1; +b BETWEEN a AND c +1 +SET time_zone='Europe/Moscow'; +SELECT b BETWEEN a AND c FROM t1; +b BETWEEN a AND c +1 +DROP TABLE t1; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288481125) /*winter time in Moscow*/); +SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a; +a UNIX_TIMESTAMP(a) +2010-10-30 22:25:26 1288477526 +2010-10-30 23:25:25 1288481125 +SELECT COALESCE(a) AS a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a; +a UNIX_TIMESTAMP(a) +2010-10-30 22:25:26 1288477526 +2010-10-30 23:25:25 1288481125 +SET time_zone='Europe/Moscow'; +SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a; +a UNIX_TIMESTAMP(a) +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:25 1288481125 +SELECT COALESCE(a) AS a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a; +a UNIX_TIMESTAMP(a) +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:25 1288481125 +DROP TABLE t1; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288481126) /*winter time in Moscow*/); +SET time_zone='Europe/Moscow'; +SELECT a, UNIX_TIMESTAMP(a) FROM t1 GROUP BY a; +a UNIX_TIMESTAMP(a) +2010-10-31 02:25:26 1288477526 +2010-10-31 02:25:26 1288481126 +DROP TABLE t1; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126)); +SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),CASE a WHEN b THEN 'eq' ELSE 'ne' END AS x FROM t1; +UNIX_TIMESTAMP(a) UNIX_TIMESTAMP(b) x +1288477526 1288481126 ne +SET time_zone='Europe/Moscow'; +SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),CASE a WHEN b THEN 'eq' ELSE 'ne' END AS x FROM t1; +UNIX_TIMESTAMP(a) UNIX_TIMESTAMP(b) x +1288477526 1288481126 ne +DROP TABLE t1; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP,c TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126),FROM_UNIXTIME(1288481127)); +SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),a IN (b,c) AS x FROM t1; +UNIX_TIMESTAMP(a) UNIX_TIMESTAMP(b) x +1288477526 1288481126 0 +SET time_zone='Europe/Moscow'; +SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),a IN (b,c) AS x FROM t1; +UNIX_TIMESTAMP(a) UNIX_TIMESTAMP(b) x +1288477526 1288481126 0 +DROP TABLE t1; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126)); +SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1); +a b +SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1); +a b +SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1)); +a b +SET time_zone='Europe/Moscow'; +SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1); +a b +SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1); +a b +SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1)); +a b +DROP TABLE t1; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1100000000),FROM_UNIXTIME(1200000000)); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1100000001),FROM_UNIXTIME(1200000001)); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126)); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1300000000),FROM_UNIXTIME(1400000000)); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1300000001),FROM_UNIXTIME(1400000001)); +SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1); +a b +SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1); +a b +SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1)); +a b +SET time_zone='Europe/Moscow'; +SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1); +a b +SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1); +a b +SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1)); +a b +DROP TABLE t1; +# +# MDEV-17979 Assertion `0' failed in Item::val_native upon SELECT with timestamp, NULLIF, GROUP BY +# +SET time_zone='+00:00'; +CREATE TABLE t1 (a INT, ts TIMESTAMP) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1, FROM_UNIXTIME(1288481126) /*winter time in Moscow*/); +SET time_zone='Europe/Moscow'; +CREATE TABLE t2 AS SELECT ts, COALESCE(ts) AS cts FROM t1 GROUP BY cts; +SELECT ts, cts, UNIX_TIMESTAMP(ts) AS uts, UNIX_TIMESTAMP(cts) AS ucts FROM t2; +ts cts uts ucts +2010-10-31 02:25:26 2010-10-31 02:25:26 1288481126 1288481126 +DROP TABLE t1,t2; +SET time_zone=DEFAULT; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/timezone2.test b/mysql-test/main/timezone2.test index 7a38610ad95..db515653651 100644 --- a/mysql-test/main/timezone2.test +++ b/mysql-test/main/timezone2.test @@ -308,3 +308,201 @@ SELECT CONVERT_TZ('2001-10-08 00:00:00', MAKE_SET(0,'+01:00'), '+00:00' ); --echo # --echo # End of 5.3 tests --echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-17203 Move fractional second truncation from Item_xxx_typecast::get_date() to Time and Datetime constructors +--echo # (an addition for the test for MDEV-4653) + +SET timestamp=unix_timestamp('2001-02-03 10:20:30'); +SET old_mode=ZERO_DATE_TIME_CAST; +SELECT CONVERT_TZ(TIME('00:00:00'),'+00:00','+7:5'); +SELECT CONVERT_TZ(TIME('2010-01-01 00:00:00'),'+00:00','+7:5'); +SET old_mode=DEFAULT; +SET timestamp=DEFAULT; + +--echo # +--echo # MDEV-13995 MAX(timestamp) returns a wrong result near DST change +--echo # + +# MAX() +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/); +SET time_zone='Europe/Moscow'; +SELECT a, UNIX_TIMESTAMP(a) FROM t1; +SELECT UNIX_TIMESTAMP(MAX(a)) AS a FROM t1; +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t2 SELECT MAX(a) AS a FROM t1; +SELECT a, UNIX_TIMESTAMP(a) FROM t2; +DROP TABLE t2; +DROP TABLE t1; + + +# Comparison +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP); +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Moscow*/); +INSERT INTO t2 VALUES (FROM_UNIXTIME(1288477526+3599) /*winter time in Moscow*/); +SET time_zone='Europe/Moscow'; +SELECT UNIX_TIMESTAMP(t1.a), UNIX_TIMESTAMP(t2.a) FROM t1,t2; +SELECT * FROM t1,t2 WHERE t1.a < t2.a; +DROP TABLE t1,t2; + + +# SP variable comparison +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE a,b TIMESTAMP; + SET time_zone='+00:00'; + SET a=FROM_UNIXTIME(1288477526); + SET b=FROM_UNIXTIME(1288481125); + SELECT a < b; + SET time_zone='Europe/Moscow'; + SELECT a < b; +END; +$$ +DELIMITER ;$$ + + +# SP function comparison +DELIMITER $$; +CREATE OR REPLACE FUNCTION f1(uts INT) RETURNS TIMESTAMP +BEGIN + DECLARE ts TIMESTAMP; + DECLARE tz VARCHAR(64) DEFAULT @@time_zone; + SET time_zone='+00:00'; + SET ts=FROM_UNIXTIME(uts); + SET time_zone=tz; + RETURN ts; +END; +$$ +DELIMITER ;$$ +SET time_zone='+00:00'; +SELECT f1(1288477526) < f1(1288481125); +SET time_zone='Europe/Moscow'; +SELECT f1(1288477526) < f1(1288481125); +DROP FUNCTION f1; + + +# LEAST() +CREATE TABLE t1 (a TIMESTAMP,b TIMESTAMP); +SET time_zone='+00:00'; +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/, + FROM_UNIXTIME(1288481125) /*winter time in Moscow*/); +SELECT *, LEAST(a,b) FROM t1; +SET time_zone='Europe/Moscow'; +SELECT *, LEAST(a,b) FROM t1; +SELECT UNIX_TIMESTAMP(a), UNIX_TIMESTAMP(b), UNIX_TIMESTAMP(LEAST(a,b)) FROM t1; +DROP TABLE t1; + + +# BETWEEN +CREATE TABLE t1 (a TIMESTAMP,b TIMESTAMP,c TIMESTAMP); +SET time_zone='+00:00'; +INSERT INTO t1 VALUES ( + FROM_UNIXTIME(1288477526) /*summer time in Moscow*/, + FROM_UNIXTIME(1288481125) /*winter time in Moscow*/, + FROM_UNIXTIME(1288481126) /*winter time in Moscow*/); +SELECT b BETWEEN a AND c FROM t1; +SET time_zone='Europe/Moscow'; +SELECT b BETWEEN a AND c FROM t1; +DROP TABLE t1; + + +# ORDER BY +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288481125) /*winter time in Moscow*/); +SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a; +SELECT COALESCE(a) AS a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a; +SET time_zone='Europe/Moscow'; +SELECT a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a; +SELECT COALESCE(a) AS a, UNIX_TIMESTAMP(a) FROM t1 ORDER BY a; +DROP TABLE t1; + + +# GROUP BY +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526) /*summer time in Mowcow*/); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288481126) /*winter time in Moscow*/); +SET time_zone='Europe/Moscow'; +SELECT a, UNIX_TIMESTAMP(a) FROM t1 GROUP BY a; +DROP TABLE t1; + + +# CASE +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126)); +SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),CASE a WHEN b THEN 'eq' ELSE 'ne' END AS x FROM t1; +SET time_zone='Europe/Moscow'; +SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),CASE a WHEN b THEN 'eq' ELSE 'ne' END AS x FROM t1; +DROP TABLE t1; + + +# IN +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP,c TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126),FROM_UNIXTIME(1288481127)); +SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),a IN (b,c) AS x FROM t1; +SET time_zone='Europe/Moscow'; +SELECT UNIX_TIMESTAMP(a),UNIX_TIMESTAMP(b),a IN (b,c) AS x FROM t1; +DROP TABLE t1; + +# Comparison and IN in combination with a subquery (with one row) + +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126)); +SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1); +SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1); +SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1)); + +SET time_zone='Europe/Moscow'; +SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1); +SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1); +SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1)); +DROP TABLE t1; + +# Comparison and IN in combinarion with a subquery (with multiple rows) +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1100000000),FROM_UNIXTIME(1200000000)); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1100000001),FROM_UNIXTIME(1200000001)); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1288477526),FROM_UNIXTIME(1288481126)); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1300000000),FROM_UNIXTIME(1400000000)); +INSERT INTO t1 VALUES (FROM_UNIXTIME(1300000001),FROM_UNIXTIME(1400000001)); +SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1); +SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1); +SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1)); + +SET time_zone='Europe/Moscow'; +SELECT * FROM t1 WHERE a = (SELECT MAX(b) FROM t1); +SELECT * FROM t1 WHERE a = (SELECT MIN(b) FROM t1); +SELECT * FROM t1 WHERE a IN ((SELECT MAX(b) FROM t1), (SELECT MIN(b) FROM t1)); +DROP TABLE t1; + +--echo # +--echo # MDEV-17979 Assertion `0' failed in Item::val_native upon SELECT with timestamp, NULLIF, GROUP BY +--echo # + +SET time_zone='+00:00'; +CREATE TABLE t1 (a INT, ts TIMESTAMP) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1, FROM_UNIXTIME(1288481126) /*winter time in Moscow*/); +SET time_zone='Europe/Moscow'; +CREATE TABLE t2 AS SELECT ts, COALESCE(ts) AS cts FROM t1 GROUP BY cts; +SELECT ts, cts, UNIX_TIMESTAMP(ts) AS uts, UNIX_TIMESTAMP(cts) AS ucts FROM t2; +DROP TABLE t1,t2; +SET time_zone=DEFAULT; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/trigger.result b/mysql-test/main/trigger.result index 69308009928..1adf3c68a08 100644 --- a/mysql-test/main/trigger.result +++ b/mysql-test/main/trigger.result @@ -736,6 +736,8 @@ select user() into user; set NEW.username = user; select count(*) from ((select 1) union (select 2)) as d1 into i; end| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead update t1 set data = 1; connection addconroot1; update t1 set data = 2; @@ -2084,6 +2086,8 @@ FOR EACH ROW BEGIN SELECT 1 FROM t1 c WHERE (@bug51650 IS NULL OR @bug51650 != c.b) AND c.b = NEW.a LIMIT 1 INTO @foo; END// +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SET @bug51650 = 1; INSERT IGNORE INTO t2 VALUES(); INSERT IGNORE INTO t1 SET b = '777'; @@ -2142,7 +2146,7 @@ insert into t2 values (1),(2); delete from t1 where i=1; show status like 'Opened_tables'; Variable_name Value -Opened_tables 3 +Opened_tables 6 select * from t1; i 2 diff --git a/mysql-test/main/trigger_notembedded.test b/mysql-test/main/trigger_notembedded.test index a31594826e7..051cd43f16f 100644 --- a/mysql-test/main/trigger_notembedded.test +++ b/mysql-test/main/trigger_notembedded.test @@ -907,7 +907,7 @@ connection flush; connection default; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for global read lock"; + where state = "Waiting for backup lock"; --source include/wait_condition.inc create trigger t1_bi before insert on t1 for each row begin end; unlock tables; diff --git a/mysql-test/main/truncate_coverage.result b/mysql-test/main/truncate_coverage.result index 078de1ef3ab..9a343832b69 100644 --- a/mysql-test/main/truncate_coverage.result +++ b/mysql-test/main/truncate_coverage.result @@ -40,7 +40,7 @@ TRUNCATE TABLE m1; connection con2; SET DEBUG_SYNC= 'now WAIT_FOR opened'; # Sending: -FLUSH TABLES; +FLUSH TABLES m1; connection default; # Waiting for FLUSH TABLES to be blocked. SET DEBUG_SYNC= 'now SIGNAL dropped'; diff --git a/mysql-test/main/truncate_coverage.test b/mysql-test/main/truncate_coverage.test index 3351ce84232..1b793c6638c 100644 --- a/mysql-test/main/truncate_coverage.test +++ b/mysql-test/main/truncate_coverage.test @@ -81,12 +81,12 @@ SET DEBUG_SYNC= 'open_tables_after_open_and_process_table SIGNAL opened WAIT_FOR connection con2; SET DEBUG_SYNC= 'now WAIT_FOR opened'; --echo # Sending: ---send FLUSH TABLES +--send FLUSH TABLES m1 connection default; --echo # Waiting for FLUSH TABLES to be blocked. let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.processlist - WHERE state= 'Waiting for table flush' AND info= 'FLUSH TABLES'; + WHERE state= 'Waiting for table metadata lock' AND info= 'FLUSH TABLES m1'; --source include/wait_condition.inc SET DEBUG_SYNC= 'now SIGNAL dropped'; diff --git a/mysql-test/main/type_bit.result b/mysql-test/main/type_bit.result index eeedc501dc4..12fe302a5be 100644 --- a/mysql-test/main/type_bit.result +++ b/mysql-test/main/type_bit.result @@ -849,3 +849,21 @@ DROP TABLE IF EXISTS t1; # # End of 10.2 tests # +# +# Start of 10.4 tests +# +# +# MDEV-15759 Expect "Impossible WHERE" for indexed_int_column=out_of_range_int_constant +# +CREATE TABLE t1 (a BIT(7), KEY(a)); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +EXPLAIN SELECT * FROM t1 WHERE a=200; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN SELECT * FROM t1 WHERE a<=>200; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_bit.test b/mysql-test/main/type_bit.test index 04db1511833..c6d5a1f2f05 100644 --- a/mysql-test/main/type_bit.test +++ b/mysql-test/main/type_bit.test @@ -483,3 +483,21 @@ DROP TABLE IF EXISTS t1; --echo # End of 10.2 tests --echo # +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-15759 Expect "Impossible WHERE" for indexed_int_column=out_of_range_int_constant +--echo # + +CREATE TABLE t1 (a BIT(7), KEY(a)); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +EXPLAIN SELECT * FROM t1 WHERE a=200; +EXPLAIN SELECT * FROM t1 WHERE a<=>200; +DROP TABLE t1; + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_date.result b/mysql-test/main/type_date.result index e87cd836317..fb117d40dd7 100644 --- a/mysql-test/main/type_date.result +++ b/mysql-test/main/type_date.result @@ -621,7 +621,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=11+RAND() AND a=' garbage '; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Warning 1292 Incorrect datetime value: ' garbage ' +Warning 1292 Truncated incorrect datetime value: ' garbage ' Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'0000-00-00' and <cache>(octet_length(DATE'0000-00-00')) = 11 + rand() DROP TABLE t1; CREATE TABLE t1 (a DATE); @@ -889,3 +889,114 @@ DROP TABLE t1; # # End of 10.3 tests # +# +# Start of 10.4 tests +# +# +# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +# +CREATE TABLE t1 (a DATE); +INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02'),('2001-01-03'); +# Equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001:01:01',a)<=>COALESCE(DATE'2001-01-01',a); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',DATE'2001-01-01'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING DATE'2001-01-01'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING DATE'2001-01-01'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +# Equal values but of different data types (should not propagate) +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001:01:01',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:00',a); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(DATE'2001-01-01',`test`.`t1`.`a`) <=> coalesce(TIMESTAMP'2001-01-01 00:00:00',`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',TIMESTAMP'2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(DATE'2001-01-01'),`test`.`t1`.`a`) <=> coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00'),`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(DATE'2001-01-01',`test`.`t1`.`a`) <=> coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00'),`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING TIMESTAMP'2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00'),`test`.`t1`.`a`) <=> coalesce(DATE'2001-01-01',`test`.`t1`.`a`) +# Not equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001-01-01',a)<=>COALESCE(DATE'2001-01-02',a); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(DATE'2001-01-01',`test`.`t1`.`a`) <=> coalesce(DATE'2001-01-02',`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',DATE'2001-01-02'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(DATE'2001-01-01'),`test`.`t1`.`a`) <=> coalesce(<cache>(DATE'2001-01-02'),`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING DATE'2001-01-02'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(DATE'2001-01-01',`test`.`t1`.`a`) <=> coalesce(<cache>(DATE'2001-01-02'),`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING DATE'2001-01-02'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(DATE'2001-01-02'),`test`.`t1`.`a`) <=> coalesce(DATE'2001-01-01',`test`.`t1`.`a`) +DROP TABLE t1; +# +# MDEV-15406 NO_ZERO_IN_DATE erroneously affects how CAST(AS DATE) warns about fractional digit truncation +# +SET sql_mode=''; +CREATE TABLE t1 (a DATE); +SELECT CAST(20061108.01 AS DATE); +CAST(20061108.01 AS DATE) +2006-11-08 +Warnings: +Note 1292 Truncated incorrect date value: '20061108.01' +INSERT INTO t1 VALUES (20061108.01); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +DROP TABLE t1; +SET sql_mode=NO_ZERO_IN_DATE; +SELECT CAST(20061108.01 AS DATE); +CAST(20061108.01 AS DATE) +2006-11-08 +Warnings: +Note 1292 Truncated incorrect date value: '20061108.01' +CREATE TABLE t1 (a DATE); +INSERT INTO t1 VALUES (20061108.01); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +DROP TABLE t1; +SET sql_mode=DEFAULT; +# +# MDEV-17216 Assertion `!dt->fraction_remainder(decimals())' failed in Field_temporal_with_date::store_TIME_with_warning +# +SET sql_mode=''; +CREATE TABLE t1 (i1 date ); +CREATE TABLE t2 (i2 int unsigned ); +INSERT INTO t2 VALUES (0); +INSERT INTO t1 SELECT * FROM t2; +DROP TABLE t1,t2; +SET sql_mode=DEFAULT; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_date.test b/mysql-test/main/type_date.test index 8d29a54a26c..75bbfb3b916 100644 --- a/mysql-test/main/type_date.test +++ b/mysql-test/main/type_date.test @@ -614,3 +614,69 @@ DROP TABLE t1; --echo # --echo # End of 10.3 tests --echo # + + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +--echo # + +CREATE TABLE t1 (a DATE); +INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02'),('2001-01-03'); +--echo # Equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001:01:01',a)<=>COALESCE(DATE'2001-01-01',a); +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',DATE'2001-01-01'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING DATE'2001-01-01'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING DATE'2001-01-01'; + +--echo # Equal values but of different data types (should not propagate) +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001:01:01',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:00',a); +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',TIMESTAMP'2001-01-01 00:00:00'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING TIMESTAMP'2001-01-01 00:00:00'; + +--echo # Not equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001-01-01',a)<=>COALESCE(DATE'2001-01-02',a); +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',DATE'2001-01-02'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING DATE'2001-01-02'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING DATE'2001-01-02'; + +DROP TABLE t1; + + +--echo # +--echo # MDEV-15406 NO_ZERO_IN_DATE erroneously affects how CAST(AS DATE) warns about fractional digit truncation +--echo # + +SET sql_mode=''; +CREATE TABLE t1 (a DATE); +SELECT CAST(20061108.01 AS DATE); +INSERT INTO t1 VALUES (20061108.01); +DROP TABLE t1; + +SET sql_mode=NO_ZERO_IN_DATE; +SELECT CAST(20061108.01 AS DATE); +CREATE TABLE t1 (a DATE); +INSERT INTO t1 VALUES (20061108.01); +DROP TABLE t1; +SET sql_mode=DEFAULT; + + +--echo # +--echo # MDEV-17216 Assertion `!dt->fraction_remainder(decimals())' failed in Field_temporal_with_date::store_TIME_with_warning +--echo # +SET sql_mode=''; +CREATE TABLE t1 (i1 date ); +CREATE TABLE t2 (i2 int unsigned ); +INSERT INTO t2 VALUES (0); +INSERT INTO t1 SELECT * FROM t2; +DROP TABLE t1,t2; +SET sql_mode=DEFAULT; + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_date_round.result b/mysql-test/main/type_date_round.result new file mode 100644 index 00000000000..0da78c6afe5 --- /dev/null +++ b/mysql-test/main/type_date_round.result @@ -0,0 +1,174 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; +# +# DATE: SET +# +CREATE TABLE t1 (a DATE, b DATETIME(4)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +SELECT a FROM t1; +a +2000-12-31 +DROP TABLE t1; +CREATE TABLE t1 (a DATE, b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2000-12-31 +2000-12-31 +DROP TABLE t1; +CREATE TABLE t1 (a DATE, b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2000-12-31 +2000-12-31 +DROP TABLE t1; +# +# DATE: ALTER +# +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a DATE; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +SELECT a FROM t1; +a +2000-12-31 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a DATE; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2000-12-31 +2000-12-31 +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a DATE; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2000-12-31 +2000-12-31 +DROP TABLE t1; +# +# DATE: CAST +# +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +SELECT a, CAST(a AS DATE) FROM t1; +a CAST(a AS DATE) +2000-12-31 23:59:59.9999 2000-12-31 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +SELECT a, CAST(a AS DATE) FROM t1; +a CAST(a AS DATE) +2000-12-31 23:59:59.9999 2000-12-31 +2000-12-31 23:59:59.9999999 2000-12-31 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +SELECT a, CAST(a AS DATE) FROM t1; +a CAST(a AS DATE) +20001231235959.9999000000 2000-12-31 +20001231235959.9999999000 2000-12-31 +DROP TABLE t1; +# +# Equal field propagation +# +CREATE TABLE t1 (a DATE); +INSERT INTO t1 VALUES (20010101); +INSERT INTO t1 VALUES (20010102); +SELECT * FROM t1 WHERE a= 20010101235959.9999999; +a +2001-01-02 +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999'; +a +2001-01-02 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999'; +a +2001-01-02 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02'; +a +2001-01-02 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2001-01-02' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = DATE'2001-01-02' +DROP TABLE t1; +# +# Comparing non-temporal to DATE +# +# Although conversion from non-temporal to DATE (e.g. on SET) does not round, +# comparison between non-temporal to DATE is performed as DATETIME. +# So rounding does happen here. +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +SELECT * FROM t1 WHERE a=DATE'2001-01-02'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE CONCAT(a)=DATE'2001-01-02'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=DATE'2001-01-02'; +a +20010101235959.9999999 +SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02'; +a +20010101235959.9999999 +DROP TABLE t1; diff --git a/mysql-test/main/type_date_round.test b/mysql-test/main/type_date_round.test new file mode 100644 index 00000000000..61e1d0a401c --- /dev/null +++ b/mysql-test/main/type_date_round.test @@ -0,0 +1,113 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; + +--echo # +--echo # DATE: SET +--echo # + +CREATE TABLE t1 (a DATE, b DATETIME(4)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DATE, b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DATE, b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # DATE: ALTER +--echo # + +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a DATE; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a DATE; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a DATE; +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # DATE: CAST +--echo # + +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +SELECT a, CAST(a AS DATE) FROM t1; +DROP TABLE t1; + +# This truncates microseconds but rounds nanoseconds (MySQL Bug #92475) +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +SELECT a, CAST(a AS DATE) FROM t1; +DROP TABLE t1; + +# This truncates microseconds but rounds nanoseconds (MySQL Bug #92475) +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +SELECT a, CAST(a AS DATE) FROM t1; +DROP TABLE t1; + + +--echo # +--echo # Equal field propagation +--echo # + +CREATE TABLE t1 (a DATE); +INSERT INTO t1 VALUES (20010101); +INSERT INTO t1 VALUES (20010102); +# DATE is compared to non-temporal as DATETIME +# In the below queries nanoseconds should round to microseconds +SELECT * FROM t1 WHERE a= 20010101235959.9999999; +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999'; +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999'; +SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND a>='2001-01-01 23:59:59.9999999'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 23:59:59.9999999' AND CONCAT(a)='2001-01-02'; +DROP TABLE t1; + + +--echo # +--echo # Comparing non-temporal to DATE +--echo # + +--echo # Although conversion from non-temporal to DATE (e.g. on SET) does not round, +--echo # comparison between non-temporal to DATE is performed as DATETIME. +--echo # So rounding does happen here. + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +SELECT * FROM t1 WHERE a=DATE'2001-01-02'; +SELECT * FROM t1 WHERE CONCAT(a)=DATE'2001-01-02'; +SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02'; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=DATE'2001-01-02'; +SELECT * FROM t1 WHERE COALESCE(a)=DATE'2001-01-02'; +DROP TABLE t1; diff --git a/mysql-test/main/type_datetime.result b/mysql-test/main/type_datetime.result index b3910553f97..6f2aa386276 100644 --- a/mysql-test/main/type_datetime.result +++ b/mysql-test/main/type_datetime.result @@ -361,7 +361,7 @@ greatest(cast('01-01-01' as date), '01-01-02') + 0 20010102 select least(cast('01-01-01' as datetime), '01-01-02') + 0; least(cast('01-01-01' as datetime), '01-01-02') + 0 -20010101000000.000000 +20010101000000 select cast(least(cast('01-01-01' as datetime), '01-01-02') as signed); cast(least(cast('01-01-01' as datetime), '01-01-02') as signed) 20010101000000 @@ -399,7 +399,7 @@ if(@bug28261 = f1, '', @bug28261:= f1) 2001-01-01 2002-02-02 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select if(@bug28261 = f1, '', @bug28261:= f1) from t1; if(@bug28261 = f1, '', @bug28261:= f1) 2001-01-01 @@ -423,11 +423,11 @@ f1 2001-01-01 00:00:00 2002-02-02 00:00:00 Warnings: -Warning 1292 Incorrect datetime value: '2002010' +Warning 1292 Truncated incorrect datetime value: '2002010' select * from t1 where f1 between 20020101 and 2007010100000; f1 Warnings: -Warning 1292 Incorrect datetime value: '2007010100000' +Warning 1292 Truncated incorrect datetime value: '2007010100000' drop table t1; # # Bug#27216: functions with parameters of different date types may @@ -498,7 +498,7 @@ f1 45:44:44 15:44:44 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' drop table t1; create table t1 (a tinyint); insert into t1 values (), (), (); @@ -575,18 +575,18 @@ CAST('NULL' AS DATE) < CAST('NULL' AS DATE) n9; n1 n2 n3 n4 n5 n6 n7 n8 n9 0 0 1 1 1 0 1 0 0 Warnings: -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' -Warning 1292 Incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' End of 5.0 tests set @org_mode=@@sql_mode; create table t1 (da date default '1962-03-03 23:33:34', dt datetime default '1962-03-03'); @@ -917,7 +917,7 @@ CREATE TABLE t1 (a DATETIME); INSERT INTO t1 VALUES ('0000-00-00 10:20:30'); SELECT a, LEAST(a,'2001-01-01 10:20:30') FROM t1; a LEAST(a,'2001-01-01 10:20:30') -0000-00-00 10:20:30 0000-00-00 10:20:30.000000 +0000-00-00 10:20:30 0000-00-00 10:20:30 DROP TABLE t1; CREATE TABLE t1 (a DATETIME(6)); INSERT INTO t1 VALUES ('0000-00-00 00:00:00.000001'); @@ -1012,7 +1012,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage '; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Warning 1292 Incorrect datetime value: ' garbage ' +Warning 1292 Truncated incorrect datetime value: ' garbage ' Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00' and <cache>(octet_length(TIMESTAMP'0000-00-00 00:00:00')) = 30 + rand() DROP TABLE t1; CREATE TABLE t1 (a DATETIME);; @@ -1131,11 +1131,11 @@ INSERT INTO t1 VALUES ('00:00:00'),('00:01:00'); SELECT 1 FROM t1 WHERE 2016 > SOME (SELECT CAST(a AS DATETIME) FROM t1); 1 Warnings: -Warning 1292 Incorrect datetime value: '2016' +Warning 1292 Truncated incorrect datetime value: '2016' SELECT * FROM t1 WHERE 2016 > CAST(a AS DATETIME); a Warnings: -Warning 1292 Incorrect datetime value: '2016' +Warning 1292 Truncated incorrect datetime value: '2016' SELECT 1 FROM t1 WHERE 20160101 > SOME (SELECT CAST(a AS DATETIME) FROM t1); 1 1 @@ -1301,3 +1301,138 @@ DROP TABLE t1; # # End of 10.3 tests # +# +# Start of 10.4 tests +# +# +# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +# +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-02 00:00:00'),('2001-01-03 00:00:00'); +# Equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP'2001:01:01 00:00:00',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:00',a); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00',TIMESTAMP'2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)' USING TIMESTAMP'2001-01-01 00:00:00'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +# Not equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP'2001:01:01 00:00:00',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:01',a); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(TIMESTAMP'2001-01-01 00:00:00',`test`.`t1`.`a`) <=> coalesce(TIMESTAMP'2001-01-01 00:00:01',`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00',TIMESTAMP'2001-01-01 00:00:01'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00'),`test`.`t1`.`a`) <=> coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:01'),`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:01'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(TIMESTAMP'2001-01-01 00:00:00',`test`.`t1`.`a`) <=> coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:01'),`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)' USING TIMESTAMP'2001-01-01 00:00:01'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:01'),`test`.`t1`.`a`) <=> coalesce(TIMESTAMP'2001-01-01 00:00:00',`test`.`t1`.`a`) +DROP TABLE t1; +# +# MDEV-16426 Optimizer erroneously treats equal constants of different formats as same +# +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01'),('2001-01-01 00:00:02'); +Equal values +SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a)); +a +2001-01-01 00:00:00 +2001-01-01 00:00:01 +2001-01-01 00:00:02 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.0'; +a +2001-01-01 00:00:00 +2001-01-01 00:00:01 +2001-01-01 00:00:02 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.0'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(coalesce(TIME'00:00:00.0',`test`.`t1`.`a`)) <=> octet_length(coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00.0'),`test`.`t1`.`a`)) +Values with different formats +SELECT LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a)),LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a)) FROM t1; +LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a)) LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a)) +21 22 +21 22 +21 22 +SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a)); +a +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(coalesce(TIMESTAMP'2001-01-01 00:00:00.0',`test`.`t1`.`a`)) <=> octet_length(coalesce(TIMESTAMP'2001-01-01 00:00:00.00',`test`.`t1`.`a`)) +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.00'; +a +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.00'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(coalesce(TIME'00:00:00.0',`test`.`t1`.`a`)) <=> octet_length(coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00.00'),`test`.`t1`.`a`)) +DROP TABLE t1; +# +# MDEV-17216 Assertion `!dt->fraction_remainder(decimals())' failed in Field_temporal_with_date::store_TIME_with_warning +# +CREATE TABLE t1 (b BIT(20)); +CREATE TABLE t2 (t DATETIME); +INSERT IGNORE INTO t1 VALUES (b'000001001100000'); +INSERT INTO t2 SELECT * FROM t1; +DROP TABLE t1, t2; +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 SELECT CAST(20010101 AS UNSIGNED); +DROP TABLE t1; +# +# MDEV-17563 Different results using table or view when comparing values of time type +# +CREATE TABLE t1 (pk int, x1 datetime, x2 varchar(1)); +INSERT INTO t1 VALUES (17,'2001-01-01 09:16:37',''); +INSERT INTO t1 VALUES (18,'2001-01-01 09:16:37','k'); +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT pk FROM t1 WHERE x1 >x2; +pk +17 +18 +Warnings: +Warning 1292 Truncated incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: 'k' +SELECT pk FROM v1 WHERE x1 >x2; +pk +17 +18 +Warnings: +Warning 1292 Truncated incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: 'k' +DROP VIEW v1; +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_datetime.test b/mysql-test/main/type_datetime.test index 7ed723fb4aa..7bd7883f469 100644 --- a/mysql-test/main/type_datetime.test +++ b/mysql-test/main/type_datetime.test @@ -849,3 +849,84 @@ DROP TABLE t1; --echo # --echo # End of 10.3 tests --echo # + + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +--echo # + +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-02 00:00:00'),('2001-01-03 00:00:00'); +--echo # Equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP'2001:01:01 00:00:00',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:00',a); +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00',TIMESTAMP'2001-01-01 00:00:00'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)' USING TIMESTAMP'2001-01-01 00:00:00'; + +--echo # Not equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP'2001:01:01 00:00:00',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:01',a); +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00',TIMESTAMP'2001-01-01 00:00:01'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:01'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)' USING TIMESTAMP'2001-01-01 00:00:01'; + +DROP TABLE t1; + + +--echo # +--echo # MDEV-16426 Optimizer erroneously treats equal constants of different formats as same +--echo # +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01'),('2001-01-01 00:00:02'); + +--echo Equal values +SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a)); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a)); +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.0'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.0'; + +--echo Values with different formats +SELECT LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a)),LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a)) FROM t1; +SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a)); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a)); +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.00'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.00'; + +DROP TABLE t1; + + +--echo # +--echo # MDEV-17216 Assertion `!dt->fraction_remainder(decimals())' failed in Field_temporal_with_date::store_TIME_with_warning +--echo # + +CREATE TABLE t1 (b BIT(20)); +CREATE TABLE t2 (t DATETIME); +INSERT IGNORE INTO t1 VALUES (b'000001001100000'); +INSERT INTO t2 SELECT * FROM t1; +DROP TABLE t1, t2; + +CREATE TABLE t1 (a DATETIME); +INSERT INTO t1 SELECT CAST(20010101 AS UNSIGNED); +DROP TABLE t1; + + +--echo # +--echo # MDEV-17563 Different results using table or view when comparing values of time type +--echo # + +CREATE TABLE t1 (pk int, x1 datetime, x2 varchar(1)); +INSERT INTO t1 VALUES (17,'2001-01-01 09:16:37',''); +INSERT INTO t1 VALUES (18,'2001-01-01 09:16:37','k'); +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT pk FROM t1 WHERE x1 >x2; +SELECT pk FROM v1 WHERE x1 >x2; +DROP VIEW v1; +DROP TABLE t1; + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_datetime_round.result b/mysql-test/main/type_datetime_round.result new file mode 100644 index 00000000000..c6584223268 --- /dev/null +++ b/mysql-test/main/type_datetime_round.result @@ -0,0 +1,205 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; +# +# DATETIME: SET +# +CREATE TABLE t1 (a DATETIME(3), b DATETIME(4)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a DATETIME(3), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a DATETIME(3), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +# +# DATETIME: ALTER +# +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a DATETIME(3); +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a DATETIME(3); +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a DATETIME(3); +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +# +# Corner case: +# ALTER DATETIME to a shorter DATETIME +# All values round, maximum possible value truncates. +# +SET time_zone='+00:00'; +CREATE TABLE t1 (ID INT, a DATETIME(6), comment VARCHAR(64)); +INSERT INTO t1 VALUES (0, '9999-12-30 23:59:58.999999', 'Should round'); +INSERT INTO t1 VALUES (1, '9999-12-31 22:59:59.999999', 'Should round'); +INSERT INTO t1 VALUES (2, '9999-12-31 23:59:58.999999', 'Should round'); +INSERT INTO t1 VALUES (3, '9999-12-31 23:59:59.999999', 'Should truncate'); +ALTER TABLE t1 MODIFY a DATETIME(5); +Warnings: +Warning 1264 Out of range value for column 'a' at row 4 +SELECT * FROM t1; +ID a comment +0 9999-12-30 23:59:59.00000 Should round +1 9999-12-31 23:00:00.00000 Should round +2 9999-12-31 23:59:59.00000 Should round +3 9999-12-31 23:59:59.99999 Should truncate +DROP TABLE t1; +SET time_zone=DEFAULT; +# +# NOW +# +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a DATETIME(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-01 00:00:00.0000 +3 2011-01-01 00:00:00.0000 +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; +# +# DATETIME: CAST +# +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +a CAST(a AS DATETIME(3)) +2000-12-31 23:59:59.9999 2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +a CAST(a AS DATETIME(3)) +2000-12-31 23:59:59.9999 2001-01-01 00:00:00.000 +2000-12-31 23:59:59.9999999 2001-01-01 00:00:00.000 +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +a CAST(a AS DATETIME(3)) +20001231235959.9999000000 2001-01-01 00:00:00.000 +20001231235959.9999999000 2001-01-01 00:00:00.000 +DROP TABLE t1; +# +# Equal field propagation +# +CREATE TABLE t1 (a DATETIME(6)); +INSERT INTO t1 VALUES (20010101235959.999999); +INSERT INTO t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=20010101235959.9999999; +a +2001-01-02 00:00:00.000000 +SELECT * FROM t1 WHERE a='20010101235959.9999999'; +a +2001-01-02 00:00:00.000000 +Warnings: +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999'; +a +2001-01-02 00:00:00.000000 +Warnings: +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000'; +a +2001-01-02 00:00:00.000000 +Warnings: +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-02 00:00:00' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect datetime value: '20010101235959.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'2001-01-02 00:00:00' +DROP TABLE t1; +# +# Comparing non-temporal to DATETIME +# +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE CONCAT(a)=TIMESTAMP'2001-01-02 00:00:00'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00'; +a +2001-01-01 23:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00'; +a +20010101235959.9999999 +SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00'; +a +20010101235959.9999999 +DROP TABLE t1; +# +# Literal corner case +# +SELECT TIMESTAMP'9999-12-31 23:59:59.999999'; +TIMESTAMP'9999-12-31 23:59:59.999999' +9999-12-31 23:59:59.999999 +SELECT TIME'9999-12-31 23:59:59.9999999'; +ERROR HY000: Incorrect TIME value: '9999-12-31 23:59:59.9999999' diff --git a/mysql-test/main/type_datetime_round.test b/mysql-test/main/type_datetime_round.test new file mode 100644 index 00000000000..15aec2cf4e0 --- /dev/null +++ b/mysql-test/main/type_datetime_round.test @@ -0,0 +1,147 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; + +--echo # +--echo # DATETIME: SET +--echo # + +CREATE TABLE t1 (a DATETIME(3), b DATETIME(4)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DATETIME(3), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DATETIME(3), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # DATETIME: ALTER +--echo # + +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a DATETIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a DATETIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a DATETIME(3); +SELECT a FROM t1; +DROP TABLE t1; + + +--echo # +--echo # Corner case: +--echo # ALTER DATETIME to a shorter DATETIME +--echo # All values round, maximum possible value truncates. +--echo # + +SET time_zone='+00:00'; +CREATE TABLE t1 (ID INT, a DATETIME(6), comment VARCHAR(64)); +INSERT INTO t1 VALUES (0, '9999-12-30 23:59:58.999999', 'Should round'); +INSERT INTO t1 VALUES (1, '9999-12-31 22:59:59.999999', 'Should round'); +INSERT INTO t1 VALUES (2, '9999-12-31 23:59:58.999999', 'Should round'); +INSERT INTO t1 VALUES (3, '9999-12-31 23:59:59.999999', 'Should truncate'); +ALTER TABLE t1 MODIFY a DATETIME(5); +SELECT * FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; + + +--echo # +--echo # NOW +--echo # + +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a DATETIME(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; + + +--echo # +--echo # DATETIME: CAST +--echo # + +CREATE TABLE t1 (a DATETIME(4)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +SELECT a, CAST(a AS DATETIME(3)) FROM t1; +DROP TABLE t1; + + +--echo # +--echo # Equal field propagation +--echo # + +CREATE TABLE t1 (a DATETIME(6)); +INSERT INTO t1 VALUES (20010101235959.999999); +INSERT INTO t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=20010101235959.9999999; +SELECT * FROM t1 WHERE a='20010101235959.9999999'; +SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999'; +SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND a>='20010101235959.9999999'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='20010101235959.9999999' AND CONCAT(a)='2001-01-02 00:00:00.000000'; +DROP TABLE t1; + +--echo # +--echo # Comparing non-temporal to DATETIME +--echo # + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00'; +SELECT * FROM t1 WHERE CONCAT(a)=TIMESTAMP'2001-01-02 00:00:00'; +SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00'; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-02 00:00:00'; +SELECT * FROM t1 WHERE COALESCE(a)=TIMESTAMP'2001-01-02 00:00:00'; +DROP TABLE t1; + +--echo # +--echo # Literal corner case +--echo # + +SELECT TIMESTAMP'9999-12-31 23:59:59.999999'; +--error ER_WRONG_VALUE +SELECT TIME'9999-12-31 23:59:59.9999999'; diff --git a/mysql-test/main/type_decimal.result b/mysql-test/main/type_decimal.result index 20ace300f3e..769c59b197d 100644 --- a/mysql-test/main/type_decimal.result +++ b/mysql-test/main/type_decimal.result @@ -1109,3 +1109,114 @@ t2 CREATE TABLE `t2` ( DROP TABLE t2; DROP TABLE t1; DROP TABLE t1dec102; +# +# End of 10.3 tests +# +# +# Start of 10.4 tests +# +# +# MDEV-11362 True condition elimination does not work for DECIMAL dynamic SQL parameters +# +CREATE TABLE t1 (a DECIMAL(10,1)); +INSERT INTO t1 VALUES (1),(2),(3); +# Equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>1.0+a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1.0,1.0; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>?+a' USING 1.0; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1.0+a' USING 1.0; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +# Not equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>1.1+a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1.0 + `test`.`t1`.`a` <=> 1.1 + `test`.`t1`.`a` +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1.0,1.1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1.0 + `test`.`t1`.`a` <=> 1.1 + `test`.`t1`.`a` +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>?+a' USING 1.1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1.0 + `test`.`t1`.`a` <=> 1.1 + `test`.`t1`.`a` +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1.0+a' USING 1.1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1.1 + `test`.`t1`.`a` <=> 1.0 + `test`.`t1`.`a` +DROP TABLE t1; +# +# MDEV-16426 Optimizer erroneously treats equal constants of different formats as same +# +CREATE TABLE t1 (a DECIMAL(10,3)); +INSERT INTO t1 VALUES (10.0),(10.1); +Equal values +SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.0)+a; +a +10.000 +10.100 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.0)+a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.0; +a +10.000 +10.100 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.0; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +Values with different formats +SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.00)+a; +a +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.00)+a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <cache>(octet_length(10.0)) + `test`.`t1`.`a` <=> <cache>(octet_length(10.00)) + `test`.`t1`.`a` +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.00; +a +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.00; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <cache>(octet_length(10.0)) + `test`.`t1`.`a` <=> <cache>(octet_length(10.00)) + `test`.`t1`.`a` +DROP TABLE t1; +# +# MDEV-16984 Assertion `dec' failed in Dec_ptr::cmp +# +SET sql_mode=''; +CREATE TABLE t1 (dc decimal(10)); +INSERT INTO t1 VALUES (0000000),(NULL); +SELECT 1 FROM t1 GROUP BY 'm' <=> dc; +1 +1 +1 +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: 'm' +DROP TABLE t1; +SET sql_mode=DEFAULT; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_decimal.test b/mysql-test/main/type_decimal.test index 319f85edf9a..53ad2698f50 100644 --- a/mysql-test/main/type_decimal.test +++ b/mysql-test/main/type_decimal.test @@ -694,3 +694,67 @@ DROP TABLE t2; DROP TABLE t1; DROP TABLE t1dec102; + +--echo # +--echo # End of 10.3 tests +--echo # + + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-11362 True condition elimination does not work for DECIMAL dynamic SQL parameters +--echo # + +CREATE TABLE t1 (a DECIMAL(10,1)); +INSERT INTO t1 VALUES (1),(2),(3); +--echo # Equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>1.0+a; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1.0,1.0; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>?+a' USING 1.0; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1.0+a' USING 1.0; +--echo # Not equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>1.1+a; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1.0,1.1; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>?+a' USING 1.1; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1.0+a' USING 1.1; +DROP TABLE t1; + +--echo # +--echo # MDEV-16426 Optimizer erroneously treats equal constants of different formats as same +--echo # + +CREATE TABLE t1 (a DECIMAL(10,3)); +INSERT INTO t1 VALUES (10.0),(10.1); + +--echo Equal values +SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.0)+a; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.0)+a; +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.0; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.0; + +--echo Values with different formats +SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.00)+a; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.00)+a; +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.00; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.00; + +DROP TABLE t1; + + +--echo # +--echo # MDEV-16984 Assertion `dec' failed in Dec_ptr::cmp +--echo # +SET sql_mode=''; +CREATE TABLE t1 (dc decimal(10)); +INSERT INTO t1 VALUES (0000000),(NULL); +SELECT 1 FROM t1 GROUP BY 'm' <=> dc; +DROP TABLE t1; +SET sql_mode=DEFAULT; + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_float.result b/mysql-test/main/type_float.result index be7c639ddd3..0ce54c0126c 100644 --- a/mysql-test/main/type_float.result +++ b/mysql-test/main/type_float.result @@ -840,3 +840,35 @@ DROP TABLE t1; # # End of 10.2 tests # +# +# Start of 10.4 tests +# +# +# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +# +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES (1),(2),(3); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1e0+a<=>1e0+a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1e0,1e0; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1e0+a' USING 1e0; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1e0+a<=>?+a' USING 1e0; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_float.test b/mysql-test/main/type_float.test index 9dba1c709d5..f42d3445e2a 100644 --- a/mysql-test/main/type_float.test +++ b/mysql-test/main/type_float.test @@ -581,3 +581,24 @@ DROP TABLE t1; --echo # --echo # End of 10.2 tests --echo # + + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +--echo # + +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES (1),(2),(3); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1e0+a<=>1e0+a; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1e0,1e0; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1e0+a' USING 1e0; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1e0+a<=>?+a' USING 1e0; +DROP TABLE t1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_hex_hybrid.result b/mysql-test/main/type_hex_hybrid.result new file mode 100644 index 00000000000..eec24f6e89e --- /dev/null +++ b/mysql-test/main/type_hex_hybrid.result @@ -0,0 +1,24 @@ +# +# Start of 10.4 tests +# +# +# MDEV-16426 Optimizer erroneously treats equal constants of different formats as same +# +SET NAMES utf8; +CREATE TABLE t1 (a DECIMAL(10,3)); +INSERT INTO t1 VALUES (10.0),(10.1); +SELECT CHARSET('a'),CHARSET(0x61),LENGTH(CHARSET('a'))+a,LENGTH(CHARSET(0x61))+a FROM t1; +CHARSET('a') CHARSET(0x61) LENGTH(CHARSET('a'))+a LENGTH(CHARSET(0x61))+a +utf8 binary 14.000 16.000 +utf8 binary 14.100 16.100 +SELECT * FROM t1 WHERE LENGTH(CHARSET('a'))+a<=>LENGTH(CHARSET(0x61))+a; +a +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(CHARSET('a'))+a<=>LENGTH(CHARSET(0x61))+a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <cache>(octet_length(charset('a'))) + `test`.`t1`.`a` <=> <cache>(octet_length(charset(0x61))) + `test`.`t1`.`a` +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_hex_hybrid.test b/mysql-test/main/type_hex_hybrid.test new file mode 100644 index 00000000000..a39750e2635 --- /dev/null +++ b/mysql-test/main/type_hex_hybrid.test @@ -0,0 +1,21 @@ +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-16426 Optimizer erroneously treats equal constants of different formats as same +--echo # + +# It's important for CHARSET('a') and CHARSET(0x61) to have different lengths in this test. +# 'latin1' and 'binary' have same lengths, so using 'utf8'. +SET NAMES utf8; +CREATE TABLE t1 (a DECIMAL(10,3)); +INSERT INTO t1 VALUES (10.0),(10.1); +SELECT CHARSET('a'),CHARSET(0x61),LENGTH(CHARSET('a'))+a,LENGTH(CHARSET(0x61))+a FROM t1; +SELECT * FROM t1 WHERE LENGTH(CHARSET('a'))+a<=>LENGTH(CHARSET(0x61))+a; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(CHARSET('a'))+a<=>LENGTH(CHARSET(0x61))+a; +DROP TABLE t1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_int.result b/mysql-test/main/type_int.result index 607b333aae1..a3a702609c9 100644 --- a/mysql-test/main/type_int.result +++ b/mysql-test/main/type_int.result @@ -238,3 +238,47 @@ DROP FUNCTION sint64; # # End of 10.3 tests # +# +# Start of 10.4 tests +# +# +# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1+a<=>1+a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1,1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1+a' USING 1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1+a<=>?+a' USING 1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +DROP TABLE t1; +# +# MDEV-15759 Expect "Impossible WHERE" for indexed_int_column=out_of_range_int_constant +# +CREATE TABLE t1 (a TINYINT, KEY(a)); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +EXPLAIN SELECT * FROM t1 WHERE a=200; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN SELECT * FROM t1 WHERE a<=>200; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_int.test b/mysql-test/main/type_int.test index 87f73fabbc8..8d56f94388c 100644 --- a/mysql-test/main/type_int.test +++ b/mysql-test/main/type_int.test @@ -179,3 +179,34 @@ DROP FUNCTION sint64; --echo # --echo # End of 10.3 tests --echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1+a<=>1+a; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1,1; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1+a' USING 1; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1+a<=>?+a' USING 1; +DROP TABLE t1; + +--echo # +--echo # MDEV-15759 Expect "Impossible WHERE" for indexed_int_column=out_of_range_int_constant +--echo # + +CREATE TABLE t1 (a TINYINT, KEY(a)); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +EXPLAIN SELECT * FROM t1 WHERE a=200; +EXPLAIN SELECT * FROM t1 WHERE a<=>200; +DROP TABLE t1; + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_interval.result b/mysql-test/main/type_interval.result new file mode 100644 index 00000000000..65c84022210 --- /dev/null +++ b/mysql-test/main/type_interval.result @@ -0,0 +1,83 @@ +# +# Start of 10.4 tests +# +# +# MDEV-17776 CAST(x AS INTERVAL DAY_SECOND(N)) +# +CREATE TABLE t1 (a VARCHAR(128)); +INSERT INTO t1 VALUES +('00:00:00'), +('+00:00:01'), +('-00:00:01'), +('838:59:59'), +('839:00:00'), +('2018:01:02'), +('87649415:59:59'), +('3652058 23:59:59'), +('87649416:00:00'), +('3652059 00:00:00'); +SELECT +EXTRACT(DAY FROM a) AS d, +EXTRACT(HOUR FROM a) AS h, +a, +CAST(a AS INTERVAL DAY_SECOND(6)) AS cast_itds +FROM t1; +d h a cast_itds +0 0 00:00:00 00:00:00.000000 +0 0 +00:00:01 00:00:01.000000 +0 0 -00:00:01 -00:00:01.000000 +34 22 838:59:59 34 22:59:59.000000 +34 23 839:00:00 34 23:00:00.000000 +84 2 2018:01:02 84 02:01:02.000000 +3652058 23 87649415:59:59 3652058 23:59:59.000000 +3652058 23 3652058 23:59:59 3652058 23:59:59.000000 +NULL NULL 87649416:00:00 NULL +NULL NULL 3652059 00:00:00 NULL +Warnings: +Warning 1292 Incorrect interval value: '87649416:00:00' +Warning 1292 Incorrect interval value: '87649416:00:00' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '87649416:00:00' +Warning 1292 Incorrect interval value: '3652059 00:00:00' +Warning 1292 Incorrect interval value: '3652059 00:00:00' +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '3652059 00:00:00' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,9)); +INSERT INTO t1 VALUES +(0), +(1), +(-1), +(8385959), +(8390000), +(20180102), +(876494155959), +(876494160000); +SELECT +EXTRACT(DAY FROM a) AS d, +EXTRACT(HOUR FROM a) AS h, +a, +CAST(a AS INTERVAL DAY_SECOND(6)) AS cast_itds +FROM t1; +d h a cast_itds +0 0 0.000000000 00:00:00.000000 +0 0 1.000000000 00:00:01.000000 +0 0 -1.000000000 -00:00:01.000000 +34 22 8385959.000000000 34 22:59:59.000000 +34 23 8390000.000000000 34 23:00:00.000000 +84 2 20180102.000000000 84 02:01:02.000000 +3652058 23 876494155959.000000000 3652058 23:59:59.000000 +NULL NULL 876494160000.000000000 NULL +Warnings: +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '0.000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '1.000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '-1.000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8385959.000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '8390000.000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '20180102.000000000' +Note 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '876494155959.000000000' +Warning 1292 Incorrect interval value: '876494160000.000000000' for column `test`.`t1`.`a` at row 8 +Warning 1292 Incorrect interval value: '876494160000.000000000' for column `test`.`t1`.`a` at row 8 +Warning 1292 Incorrect INTERVAL DAY TO SECOND value: '876494160000.000000000' +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_interval.test b/mysql-test/main/type_interval.test new file mode 100644 index 00000000000..15999dc609d --- /dev/null +++ b/mysql-test/main/type_interval.test @@ -0,0 +1,54 @@ +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-17776 CAST(x AS INTERVAL DAY_SECOND(N)) +--echo # + +CREATE TABLE t1 (a VARCHAR(128)); +INSERT INTO t1 VALUES +('00:00:00'), +('+00:00:01'), +('-00:00:01'), +('838:59:59'), +('839:00:00'), +('2018:01:02'), +('87649415:59:59'), +('3652058 23:59:59'), +('87649416:00:00'), +('3652059 00:00:00'); + +SELECT + EXTRACT(DAY FROM a) AS d, + EXTRACT(HOUR FROM a) AS h, + a, + CAST(a AS INTERVAL DAY_SECOND(6)) AS cast_itds +FROM t1; + +DROP TABLE t1; + + +CREATE TABLE t1 (a DECIMAL(32,9)); +INSERT INTO t1 VALUES +(0), +(1), +(-1), +(8385959), +(8390000), +(20180102), +(876494155959), +(876494160000); + +SELECT + EXTRACT(DAY FROM a) AS d, + EXTRACT(HOUR FROM a) AS h, + a, + CAST(a AS INTERVAL DAY_SECOND(6)) AS cast_itds +FROM t1; + +DROP TABLE t1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_temporal_innodb.result b/mysql-test/main/type_temporal_innodb.result index b869822722d..f8d8bc018bd 100644 --- a/mysql-test/main/type_temporal_innodb.result +++ b/mysql-test/main/type_temporal_innodb.result @@ -56,7 +56,7 @@ SELECT DATE'0000-00-00'=''; DATE'0000-00-00'='' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' CREATE TABLE t1 (a ENUM('a'), b DATE, c INT, KEY(b)) ENGINE=InnoDB; INSERT IGNORE INTO t1 VALUES ('','0000-00-00',0); Warnings: @@ -65,49 +65,49 @@ SELECT * FROM t1 WHERE b=''; a b c 0000-00-00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; a b c 0000-00-00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT * FROM t1 WHERE a=b; a b c 0000-00-00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; 1 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' ALTER TABLE t1 ENGINE=MyISAM; SELECT * FROM t1 WHERE b=''; a b c 0000-00-00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; a b c 0000-00-00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT * FROM t1 WHERE a=b; a b c 0000-00-00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; 1 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' DROP TABLE t1; SELECT TIMESTAMP'0000-00-00 00:00:00'=''; TIMESTAMP'0000-00-00 00:00:00'='' 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' CREATE TABLE t1 (a ENUM('a'), b DATETIME, c INT, KEY(b)) ENGINE=InnoDB; INSERT IGNORE INTO t1 VALUES ('','0000-00-00 00:00:00',0); Warnings: @@ -116,43 +116,43 @@ SELECT * FROM t1 WHERE b=''; a b c 0000-00-00 00:00:00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; a b c 0000-00-00 00:00:00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT * FROM t1 WHERE a=b; a b c 0000-00-00 00:00:00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; 1 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' ALTER TABLE t1 ENGINE=MyISAM; SELECT * FROM t1 WHERE b=''; a b c 0000-00-00 00:00:00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; a b c 0000-00-00 00:00:00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT * FROM t1 WHERE a=b; a b c 0000-00-00 00:00:00 0 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; 1 1 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' DROP TABLE t1; CREATE TABLE t1 (d DATE) ENGINE=InnoDB; INSERT INTO t1 VALUES ('2012-12-21'); diff --git a/mysql-test/main/type_temporal_mysql56_debug.result b/mysql-test/main/type_temporal_mysql56_debug.result new file mode 100644 index 00000000000..a6a6c071ea3 --- /dev/null +++ b/mysql-test/main/type_temporal_mysql56_debug.result @@ -0,0 +1,416 @@ +# +# Start of 10.4 tests +# +# +# MDEV-16542 Fix ALTER TABLE FORCE to upgrade temporal types +# +CREATE PROCEDURE mdev16542_create_select() +BEGIN +SELECT '# CREATE..SELECT and SHOW' AS ``; +CREATE TABLE t2 AS SELECT +a0, a1, a2, a3, a4, a5, a6, +COALESCE(a0), +COALESCE(a1), +COALESCE(a2), +COALESCE(a3), +COALESCE(a4), +COALESCE(a5), +COALESCE(a6) +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; +END; +$$ +CREATE PROCEDURE mdev16542_alter_force_and_show() +BEGIN +SELECT '# ALTER..FORCE and SHOW' AS ``; +ALTER TABLE t1 FORCE; +SHOW CREATE TABLE t1; +END; +$$ +CREATE PROCEDURE mdev16542() +BEGIN +SET SESSION debug_dbug="+d,sql_type"; +SELECT '# Original table' AS ``; +SHOW CREATE TABLE t1; +CALL mdev16542_create_select(); +CALL mdev16542_alter_force_and_show(); +SELECT '# Setting @@global.mysql56_temporal_format=false' AS ``; +SET @@global.mysql56_temporal_format=false; +CALL mdev16542_create_select(); +CALL mdev16542_alter_force_and_show(); +SELECT '# Setting @@global.mysql56_temporal_format=true' AS ``; +SET @@global.mysql56_temporal_format=true; +CALL mdev16542_create_select(); +CALL mdev16542_alter_force_and_show(); +SET SESSION debug_dbug="-d,sql_type"; +END; +$$ +SET @@global.mysql56_temporal_format=true; +CREATE TABLE t1 ( +a0 TIME, +a1 TIME(1), +a2 TIME(2), +a3 TIME(3), +a4 TIME(4), +a5 TIME(5), +a6 TIME(6) +); +CALL mdev16542; + +# Original table +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` time /* mysql-5.6 */ DEFAULT NULL, + `a1` time(1) /* mysql-5.6 */ DEFAULT NULL, + `a2` time(2) /* mysql-5.6 */ DEFAULT NULL, + `a3` time(3) /* mysql-5.6 */ DEFAULT NULL, + `a4` time(4) /* mysql-5.6 */ DEFAULT NULL, + `a5` time(5) /* mysql-5.6 */ DEFAULT NULL, + `a6` time(6) /* mysql-5.6 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# CREATE..SELECT and SHOW +Table Create Table +t2 CREATE TABLE `t2` ( + `a0` time /* mysql-5.6 */ DEFAULT NULL, + `a1` time(1) /* mysql-5.6 */ DEFAULT NULL, + `a2` time(2) /* mysql-5.6 */ DEFAULT NULL, + `a3` time(3) /* mysql-5.6 */ DEFAULT NULL, + `a4` time(4) /* mysql-5.6 */ DEFAULT NULL, + `a5` time(5) /* mysql-5.6 */ DEFAULT NULL, + `a6` time(6) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a0)` time /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a1)` time(1) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a2)` time(2) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a3)` time(3) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a4)` time(4) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a5)` time(5) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a6)` time(6) /* mysql-5.6 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# ALTER..FORCE and SHOW +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` time /* mysql-5.6 */ DEFAULT NULL, + `a1` time(1) /* mysql-5.6 */ DEFAULT NULL, + `a2` time(2) /* mysql-5.6 */ DEFAULT NULL, + `a3` time(3) /* mysql-5.6 */ DEFAULT NULL, + `a4` time(4) /* mysql-5.6 */ DEFAULT NULL, + `a5` time(5) /* mysql-5.6 */ DEFAULT NULL, + `a6` time(6) /* mysql-5.6 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# Setting @@global.mysql56_temporal_format=false + +# CREATE..SELECT and SHOW +Table Create Table +t2 CREATE TABLE `t2` ( + `a0` time /* mariadb-5.3 */ DEFAULT NULL, + `a1` time(1) /* mariadb-5.3 */ DEFAULT NULL, + `a2` time(2) /* mariadb-5.3 */ DEFAULT NULL, + `a3` time(3) /* mariadb-5.3 */ DEFAULT NULL, + `a4` time(4) /* mariadb-5.3 */ DEFAULT NULL, + `a5` time(5) /* mariadb-5.3 */ DEFAULT NULL, + `a6` time(6) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a0)` time /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a1)` time(1) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a2)` time(2) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a3)` time(3) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a4)` time(4) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a5)` time(5) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a6)` time(6) /* mariadb-5.3 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# ALTER..FORCE and SHOW +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` time /* mariadb-5.3 */ DEFAULT NULL, + `a1` time(1) /* mariadb-5.3 */ DEFAULT NULL, + `a2` time(2) /* mariadb-5.3 */ DEFAULT NULL, + `a3` time(3) /* mariadb-5.3 */ DEFAULT NULL, + `a4` time(4) /* mariadb-5.3 */ DEFAULT NULL, + `a5` time(5) /* mariadb-5.3 */ DEFAULT NULL, + `a6` time(6) /* mariadb-5.3 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# Setting @@global.mysql56_temporal_format=true + +# CREATE..SELECT and SHOW +Table Create Table +t2 CREATE TABLE `t2` ( + `a0` time /* mysql-5.6 */ DEFAULT NULL, + `a1` time(1) /* mysql-5.6 */ DEFAULT NULL, + `a2` time(2) /* mysql-5.6 */ DEFAULT NULL, + `a3` time(3) /* mysql-5.6 */ DEFAULT NULL, + `a4` time(4) /* mysql-5.6 */ DEFAULT NULL, + `a5` time(5) /* mysql-5.6 */ DEFAULT NULL, + `a6` time(6) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a0)` time /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a1)` time(1) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a2)` time(2) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a3)` time(3) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a4)` time(4) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a5)` time(5) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a6)` time(6) /* mysql-5.6 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# ALTER..FORCE and SHOW +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` time /* mysql-5.6 */ DEFAULT NULL, + `a1` time(1) /* mysql-5.6 */ DEFAULT NULL, + `a2` time(2) /* mysql-5.6 */ DEFAULT NULL, + `a3` time(3) /* mysql-5.6 */ DEFAULT NULL, + `a4` time(4) /* mysql-5.6 */ DEFAULT NULL, + `a5` time(5) /* mysql-5.6 */ DEFAULT NULL, + `a6` time(6) /* mysql-5.6 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( +a0 DATETIME, +a1 DATETIME(1), +a2 DATETIME(2), +a3 DATETIME(3), +a4 DATETIME(4), +a5 DATETIME(5), +a6 DATETIME(6) +); +CALL mdev16542; + +# Original table +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` datetime /* mysql-5.6 */ DEFAULT NULL, + `a1` datetime(1) /* mysql-5.6 */ DEFAULT NULL, + `a2` datetime(2) /* mysql-5.6 */ DEFAULT NULL, + `a3` datetime(3) /* mysql-5.6 */ DEFAULT NULL, + `a4` datetime(4) /* mysql-5.6 */ DEFAULT NULL, + `a5` datetime(5) /* mysql-5.6 */ DEFAULT NULL, + `a6` datetime(6) /* mysql-5.6 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# CREATE..SELECT and SHOW +Table Create Table +t2 CREATE TABLE `t2` ( + `a0` datetime /* mysql-5.6 */ DEFAULT NULL, + `a1` datetime(1) /* mysql-5.6 */ DEFAULT NULL, + `a2` datetime(2) /* mysql-5.6 */ DEFAULT NULL, + `a3` datetime(3) /* mysql-5.6 */ DEFAULT NULL, + `a4` datetime(4) /* mysql-5.6 */ DEFAULT NULL, + `a5` datetime(5) /* mysql-5.6 */ DEFAULT NULL, + `a6` datetime(6) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a0)` datetime /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a1)` datetime(1) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a2)` datetime(2) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a3)` datetime(3) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a4)` datetime(4) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a5)` datetime(5) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a6)` datetime(6) /* mysql-5.6 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# ALTER..FORCE and SHOW +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` datetime /* mysql-5.6 */ DEFAULT NULL, + `a1` datetime(1) /* mysql-5.6 */ DEFAULT NULL, + `a2` datetime(2) /* mysql-5.6 */ DEFAULT NULL, + `a3` datetime(3) /* mysql-5.6 */ DEFAULT NULL, + `a4` datetime(4) /* mysql-5.6 */ DEFAULT NULL, + `a5` datetime(5) /* mysql-5.6 */ DEFAULT NULL, + `a6` datetime(6) /* mysql-5.6 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# Setting @@global.mysql56_temporal_format=false + +# CREATE..SELECT and SHOW +Table Create Table +t2 CREATE TABLE `t2` ( + `a0` datetime /* mariadb-5.3 */ DEFAULT NULL, + `a1` datetime(1) /* mariadb-5.3 */ DEFAULT NULL, + `a2` datetime(2) /* mariadb-5.3 */ DEFAULT NULL, + `a3` datetime(3) /* mariadb-5.3 */ DEFAULT NULL, + `a4` datetime(4) /* mariadb-5.3 */ DEFAULT NULL, + `a5` datetime(5) /* mariadb-5.3 */ DEFAULT NULL, + `a6` datetime(6) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a0)` datetime /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a1)` datetime(1) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a2)` datetime(2) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a3)` datetime(3) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a4)` datetime(4) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a5)` datetime(5) /* mariadb-5.3 */ DEFAULT NULL, + `COALESCE(a6)` datetime(6) /* mariadb-5.3 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# ALTER..FORCE and SHOW +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` datetime /* mariadb-5.3 */ DEFAULT NULL, + `a1` datetime(1) /* mariadb-5.3 */ DEFAULT NULL, + `a2` datetime(2) /* mariadb-5.3 */ DEFAULT NULL, + `a3` datetime(3) /* mariadb-5.3 */ DEFAULT NULL, + `a4` datetime(4) /* mariadb-5.3 */ DEFAULT NULL, + `a5` datetime(5) /* mariadb-5.3 */ DEFAULT NULL, + `a6` datetime(6) /* mariadb-5.3 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# Setting @@global.mysql56_temporal_format=true + +# CREATE..SELECT and SHOW +Table Create Table +t2 CREATE TABLE `t2` ( + `a0` datetime /* mysql-5.6 */ DEFAULT NULL, + `a1` datetime(1) /* mysql-5.6 */ DEFAULT NULL, + `a2` datetime(2) /* mysql-5.6 */ DEFAULT NULL, + `a3` datetime(3) /* mysql-5.6 */ DEFAULT NULL, + `a4` datetime(4) /* mysql-5.6 */ DEFAULT NULL, + `a5` datetime(5) /* mysql-5.6 */ DEFAULT NULL, + `a6` datetime(6) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a0)` datetime /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a1)` datetime(1) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a2)` datetime(2) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a3)` datetime(3) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a4)` datetime(4) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a5)` datetime(5) /* mysql-5.6 */ DEFAULT NULL, + `COALESCE(a6)` datetime(6) /* mysql-5.6 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# ALTER..FORCE and SHOW +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` datetime /* mysql-5.6 */ DEFAULT NULL, + `a1` datetime(1) /* mysql-5.6 */ DEFAULT NULL, + `a2` datetime(2) /* mysql-5.6 */ DEFAULT NULL, + `a3` datetime(3) /* mysql-5.6 */ DEFAULT NULL, + `a4` datetime(4) /* mysql-5.6 */ DEFAULT NULL, + `a5` datetime(5) /* mysql-5.6 */ DEFAULT NULL, + `a6` datetime(6) /* mysql-5.6 */ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 ( +a0 TIMESTAMP, +a1 TIMESTAMP(1), +a2 TIMESTAMP(2), +a3 TIMESTAMP(3), +a4 TIMESTAMP(4), +a5 TIMESTAMP(5), +a6 TIMESTAMP(6) +); +CALL mdev16542; + +# Original table +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` timestamp /* mysql-5.6 */ NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `a1` timestamp(1) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0', + `a2` timestamp(2) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00', + `a3` timestamp(3) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000', + `a4` timestamp(4) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0000', + `a5` timestamp(5) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00000', + `a6` timestamp(6) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000000' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# CREATE..SELECT and SHOW +Table Create Table +t2 CREATE TABLE `t2` ( + `a0` timestamp /* mysql-5.6 */ NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `a1` timestamp(1) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0', + `a2` timestamp(2) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00', + `a3` timestamp(3) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000', + `a4` timestamp(4) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0000', + `a5` timestamp(5) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00000', + `a6` timestamp(6) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000000', + `COALESCE(a0)` timestamp /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a1)` timestamp(1) /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a2)` timestamp(2) /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a3)` timestamp(3) /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a4)` timestamp(4) /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a5)` timestamp(5) /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a6)` timestamp(6) /* mysql-5.6 */ NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# ALTER..FORCE and SHOW +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` timestamp /* mysql-5.6 */ NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `a1` timestamp(1) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0', + `a2` timestamp(2) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00', + `a3` timestamp(3) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000', + `a4` timestamp(4) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0000', + `a5` timestamp(5) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00000', + `a6` timestamp(6) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000000' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# Setting @@global.mysql56_temporal_format=false + +# CREATE..SELECT and SHOW +Table Create Table +t2 CREATE TABLE `t2` ( + `a0` timestamp /* mariadb-5.3 */ NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `a1` timestamp(1) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0', + `a2` timestamp(2) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00', + `a3` timestamp(3) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000', + `a4` timestamp(4) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0000', + `a5` timestamp(5) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00000', + `a6` timestamp(6) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000000', + `COALESCE(a0)` timestamp /* mariadb-5.3 */ NULL DEFAULT NULL, + `COALESCE(a1)` timestamp(1) /* mariadb-5.3 */ NULL DEFAULT NULL, + `COALESCE(a2)` timestamp(2) /* mariadb-5.3 */ NULL DEFAULT NULL, + `COALESCE(a3)` timestamp(3) /* mariadb-5.3 */ NULL DEFAULT NULL, + `COALESCE(a4)` timestamp(4) /* mariadb-5.3 */ NULL DEFAULT NULL, + `COALESCE(a5)` timestamp(5) /* mariadb-5.3 */ NULL DEFAULT NULL, + `COALESCE(a6)` timestamp(6) /* mariadb-5.3 */ NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# ALTER..FORCE and SHOW +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` timestamp /* mariadb-5.3 */ NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `a1` timestamp(1) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0', + `a2` timestamp(2) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00', + `a3` timestamp(3) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000', + `a4` timestamp(4) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0000', + `a5` timestamp(5) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00000', + `a6` timestamp(6) /* mariadb-5.3 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000000' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# Setting @@global.mysql56_temporal_format=true + +# CREATE..SELECT and SHOW +Table Create Table +t2 CREATE TABLE `t2` ( + `a0` timestamp /* mysql-5.6 */ NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `a1` timestamp(1) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0', + `a2` timestamp(2) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00', + `a3` timestamp(3) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000', + `a4` timestamp(4) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0000', + `a5` timestamp(5) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00000', + `a6` timestamp(6) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000000', + `COALESCE(a0)` timestamp /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a1)` timestamp(1) /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a2)` timestamp(2) /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a3)` timestamp(3) /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a4)` timestamp(4) /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a5)` timestamp(5) /* mysql-5.6 */ NULL DEFAULT NULL, + `COALESCE(a6)` timestamp(6) /* mysql-5.6 */ NULL DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 + +# ALTER..FORCE and SHOW +Table Create Table +t1 CREATE TABLE `t1` ( + `a0` timestamp /* mysql-5.6 */ NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `a1` timestamp(1) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0', + `a2` timestamp(2) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00', + `a3` timestamp(3) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000', + `a4` timestamp(4) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.0000', + `a5` timestamp(5) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.00000', + `a6` timestamp(6) /* mysql-5.6 */ NOT NULL DEFAULT '0000-00-00 00:00:00.000000' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET @@global.mysql56_temporal_format=DEFAULT; +DROP PROCEDURE mdev16542; +DROP PROCEDURE mdev16542_create_select; +DROP PROCEDURE mdev16542_alter_force_and_show; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_temporal_mysql56_debug.test b/mysql-test/main/type_temporal_mysql56_debug.test new file mode 100644 index 00000000000..12edde94598 --- /dev/null +++ b/mysql-test/main/type_temporal_mysql56_debug.test @@ -0,0 +1,107 @@ +--source include/have_debug.inc + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-16542 Fix ALTER TABLE FORCE to upgrade temporal types +--echo # + +DELIMITER $$; +CREATE PROCEDURE mdev16542_create_select() +BEGIN + SELECT '# CREATE..SELECT and SHOW' AS ``; + CREATE TABLE t2 AS SELECT + a0, a1, a2, a3, a4, a5, a6, + COALESCE(a0), + COALESCE(a1), + COALESCE(a2), + COALESCE(a3), + COALESCE(a4), + COALESCE(a5), + COALESCE(a6) + FROM t1; + SHOW CREATE TABLE t2; + DROP TABLE t2; +END; +$$ + +CREATE PROCEDURE mdev16542_alter_force_and_show() +BEGIN + SELECT '# ALTER..FORCE and SHOW' AS ``; + ALTER TABLE t1 FORCE; + SHOW CREATE TABLE t1; +END; +$$ + +CREATE PROCEDURE mdev16542() +BEGIN + SET SESSION debug_dbug="+d,sql_type"; + SELECT '# Original table' AS ``; + SHOW CREATE TABLE t1; + CALL mdev16542_create_select(); + CALL mdev16542_alter_force_and_show(); + + SELECT '# Setting @@global.mysql56_temporal_format=false' AS ``; + SET @@global.mysql56_temporal_format=false; + CALL mdev16542_create_select(); + CALL mdev16542_alter_force_and_show(); + + SELECT '# Setting @@global.mysql56_temporal_format=true' AS ``; + SET @@global.mysql56_temporal_format=true; + CALL mdev16542_create_select(); + CALL mdev16542_alter_force_and_show(); + SET SESSION debug_dbug="-d,sql_type"; +END; +$$ +DELIMITER ;$$ + +SET @@global.mysql56_temporal_format=true; + +CREATE TABLE t1 ( + a0 TIME, + a1 TIME(1), + a2 TIME(2), + a3 TIME(3), + a4 TIME(4), + a5 TIME(5), + a6 TIME(6) +); +CALL mdev16542; +DROP TABLE t1; + + +CREATE TABLE t1 ( + a0 DATETIME, + a1 DATETIME(1), + a2 DATETIME(2), + a3 DATETIME(3), + a4 DATETIME(4), + a5 DATETIME(5), + a6 DATETIME(6) +); +CALL mdev16542; +DROP TABLE t1; + + +CREATE TABLE t1 ( + a0 TIMESTAMP, + a1 TIMESTAMP(1), + a2 TIMESTAMP(2), + a3 TIMESTAMP(3), + a4 TIMESTAMP(4), + a5 TIMESTAMP(5), + a6 TIMESTAMP(6) +); +CALL mdev16542; +DROP TABLE t1; + +SET @@global.mysql56_temporal_format=DEFAULT; +DROP PROCEDURE mdev16542; +DROP PROCEDURE mdev16542_create_select; +DROP PROCEDURE mdev16542_alter_force_and_show; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_time.result b/mysql-test/main/type_time.result index 44f0d50d94e..38b732d6f16 100644 --- a/mysql-test/main/type_time.result +++ b/mysql-test/main/type_time.result @@ -841,6 +841,18 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-01 10:20:30' and octet_length(`test`.`t1`.`a`) = 30 + rand() +EXPLAIN EXTENDED +SELECT * FROM t1 WHERE a=TIMESTAMP'0000-01-00 10:20:30' AND LENGTH(a)=8; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-01-00 10:20:30' and octet_length(`test`.`t1`.`a`) = 8 +EXPLAIN EXTENDED +SELECT * FROM t1 WHERE a=TIMESTAMP'0001-00-00 10:20:30' AND LENGTH(a)=8; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0001-00-00 10:20:30' and octet_length(`test`.`t1`.`a`) = 8 # Old mode, TIMESTAMP-alike string literal, zero YYYYMMDD, Ok to propagate SELECT * FROM t1 WHERE a='0000-00-00 10:20:30'; a @@ -1451,9 +1463,9 @@ GREATEST('2010-01-01 10:10:10',TIME('-20:20:20')) AS gt_minus20_implicit, GREATEST(CAST('2010-01-01 10:10:10' AS TIME(6)),TIME('-20:20:20')) AS gt_minis20_explicit, GREATEST('2010-01-01 10:10:10',TIME('20:20:20')) AS gt_plus20_implicit, GREATEST(CAST('2010-01-01 10:10:10' AS TIME(6)),TIME('20:20:20')) AS gt_plus20_explicit; -gt_minus20_implicit 10:10:10.000000 +gt_minus20_implicit 10:10:10 gt_minis20_explicit 10:10:10.000000 -gt_plus20_implicit 20:20:20.000000 +gt_plus20_implicit 20:20:20 gt_plus20_explicit 20:20:20.000000 SELECT HOUR(GREATEST('2010-01-01 10:10:10',TIME('-20:20:20'))) AS gt_minus20_implicit, @@ -1469,9 +1481,9 @@ LEAST('2010-01-01 10:10:10',TIME('-20:20:20')) AS lt_minus20_implicit, LEAST(CAST('2010-01-01 10:10:10' AS TIME(6)),TIME('-20:20:20')) AS lt_minus20_explicit, LEAST('2010-01-01 10:10:10',TIME('20:20:20')) AS lt_plus20_implicit, LEAST(CAST('2010-01-01 10:10:10' AS TIME(6)),TIME('20:20:20')) AS lt_plus20_explicit; -lt_minus20_implicit -20:20:20.000000 +lt_minus20_implicit -20:20:20 lt_minus20_explicit -20:20:20.000000 -lt_plus20_implicit 10:10:10.000000 +lt_plus20_implicit 10:10:10 lt_plus20_explicit 10:10:10.000000 SELECT HOUR(LEAST('2010-01-01 10:10:10',TIME('-20:20:20'))) AS lt_minus20_implicit, @@ -1487,9 +1499,9 @@ GREATEST('2010-01-01 10:10:10',TIME('-200:20:20')) AS gt_minus200_implicit, GREATEST(CAST('2010-01-01 10:10:10' AS TIME(6)),TIME('-200:20:20')) AS gt_minus200_explictit, GREATEST('2010-01-01 10:10:10',TIME('200:20:20')) AS gt_plus200_implicit, GREATEST(CAST('2010-01-01 10:10:10' AS TIME(6)),TIME('200:20:20')) AS gt_plus200_explicit; -gt_minus200_implicit 10:10:10.000000 +gt_minus200_implicit 10:10:10 gt_minus200_explictit 10:10:10.000000 -gt_plus200_implicit 200:20:20.000000 +gt_plus200_implicit 200:20:20 gt_plus200_explicit 200:20:20.000000 SELECT HOUR(GREATEST('2010-01-01 10:10:10',TIME('-200:20:20'))) AS gt_minus200_implicit, @@ -1505,9 +1517,9 @@ LEAST('2010-01-01 10:10:10',TIME('-200:20:20')) AS lt_minus200_implicit, LEAST(CAST('2010-01-01 10:10:10' AS TIME(6)),TIME('-200:20:20')) AS lt_minus200_explictit, LEAST('2010-01-01 10:10:10',TIME('200:20:20')) AS lt_plus200_implicit, LEAST(CAST('2010-01-01 10:10:10' AS TIME(6)),TIME('200:20:20')) AS lt_plus200_explicit; -lt_minus200_implicit -200:20:20.000000 +lt_minus200_implicit -200:20:20 lt_minus200_explictit -200:20:20.000000 -lt_plus200_implicit 10:10:10.000000 +lt_plus200_implicit 10:10:10 lt_plus200_explicit 10:10:10.000000 SELECT HOUR(LEAST('2010-01-01 10:10:10',TIME('-200:20:20'))) AS lt_minus200_implicit, @@ -1953,3 +1965,217 @@ a filler -838:00:04.1 yes -838:00:03.1 yes DROP TABLE t1; +# +# Start of 10.4 tests +# +# +# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +# +CREATE TABLE t1 (a TIME); +INSERT INTO t1 VALUES (1),(2),(3); +# Equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME'10:20:30',a)<=>COALESCE(TIME'10:20:30',a); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIME'10:20:30',TIME'10:20:30'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME''10:20:30'',a)<=>COALESCE(?,a)' USING TIME'10:20:30'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIME''10:20:30'',a)' USING TIME'10:20:30'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +# Not equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME'10:20:30',a)<=>COALESCE(TIME'10:20:31',a); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(TIME'10:20:30',`test`.`t1`.`a`) <=> coalesce(TIME'10:20:31',`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIME'10:20:30',TIME'10:20:31'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(TIME'10:20:30'),`test`.`t1`.`a`) <=> coalesce(<cache>(TIME'10:20:31'),`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME''10:20:30'',a)<=>COALESCE(?,a)' USING TIME'10:20:31'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(TIME'10:20:30',`test`.`t1`.`a`) <=> coalesce(<cache>(TIME'10:20:31'),`test`.`t1`.`a`) +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIME''10:20:30'',a)' USING TIME'10:20:31'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(TIME'10:20:31'),`test`.`t1`.`a`) <=> coalesce(TIME'10:20:30',`test`.`t1`.`a`) +DROP TABLE t1; +# +# MDEV-16426 Optimizer erroneously treats equal constants of different formats as same +# +CREATE TABLE t1 (a TIME); +INSERT INTO t1 VALUES ('00:00:00'),('00:00:01'),('00:00:02'); +Equal values +SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.0',a)); +a +00:00:00 +00:00:01 +00:00:02 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.0',a)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.0'; +a +00:00:00 +00:00:01 +00:00:02 +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.0'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1 +Values with different formats +SELECT LENGTH(COALESCE(TIME'00:00:00.0',a)),LENGTH(COALESCE(TIME'00:00:00.00',a)) FROM t1; +LENGTH(COALESCE(TIME'00:00:00.0',a)) LENGTH(COALESCE(TIME'00:00:00.00',a)) +10 11 +10 11 +10 11 +SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.00',a)); +a +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.00',a)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(coalesce(TIME'00:00:00.0',`test`.`t1`.`a`)) <=> octet_length(coalesce(TIME'00:00:00.00',`test`.`t1`.`a`)) +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.00'; +a +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.00'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(coalesce(TIME'00:00:00.0',`test`.`t1`.`a`)) <=> octet_length(coalesce(<cache>(TIME'00:00:00.00'),`test`.`t1`.`a`)) +DROP TABLE t1; +# +# MDEV-16971 Assertion `is_valid_value_slow()' failed in Time::adjust_time_range_or_invalidate +# +SET sql_mode=''; +CREATE TABLE t1 (d1 date, t1 time, KEY t1 (t1)); +INSERT INTO t1 VALUES ('1982-12-19','08:16:31'),('1981-04-19','21:52:59'),('1971-06-09','07:15:44'),('2007-08-15','03:55:02'),('1993-06-05','04:17:51'),('2034-07-01','17:31:12'),('1998-08-24','08:09:27'),('1991-01-15','01:14:07'),('2001-02-25','10:41:28'),('1974-06-24','10:21:58'),('1977-04-21','16:38:05'),('1981-12-03','01:24:42'),('1972-06-15','20:19:16'),('1989-08-10','08:53:47'),('2018-05-19','15:06:49'),('1984-01-12','15:56:11'),('2013-01-23','04:16:16'),('2000-06-10','02:06:44'),('1995-01-03','04:51:38'); +CREATE TABLE t2 (d1 date ); +INSERT INTO t2 VALUES ('2018-06-01'),('1979-10-25'),('1974-08-22'),('1980-06-17'); +SELECT * FROM (t1 JOIN t2 ON (t2.d1 = t1.t1)) WHERE (t1.d1 > 70 ); +d1 t1 d1 +UPDATE (t1 JOIN t2 ON (t2.d1 = t1.t1)) SET t1.d1 = '2018-07-07' WHERE (t1.d1 > 70 ); +DROP TABLE t1,t2; +# +# MDEV-17219 Assertion `!t->fraction_remainder(decimals())' failed in Field_time::store_TIME_with_warning +# +SET optimizer_use_condition_selectivity=3; +CREATE TABLE t1 (it TIME NOT NULL); +INSERT INTO t1 VALUES ('07:25:13'),('05:15:55'),('09:58:01'),('04:23:57'),('19:37:28'),('01:38:05'),('20:50:52'); +SELECT 1 FROM t1 WHERE it < -7487797330456870912; +1 +Warnings: +Warning 1292 Truncated incorrect time value: '-7487797330456870912' +DROP TABLE t1; +SET optimizer_use_condition_selectivity=DEFAULT; +# +# MDEV-17417 TIME(99991231235959) returns 838:59:59 instead of 23:59:58 +# +SELECT TIME(99991231235957), TIME(99991231235958), TIME(99991231235959); +TIME(99991231235957) TIME(99991231235958) TIME(99991231235959) +23:59:57 23:59:58 23:59:59 +# +# MDEV-17634 Regression: TIME(0)=TIME('z') returns NULL vs 1 +# +SELECT +TIMESTAMP(0)=TIMESTAMP('z') AS ts, +DATE(0)=DATE('z') AS d, +TIME(0)=TIME('z') AS t; +ts d t +1 1 1 +Warnings: +Warning 1292 Truncated incorrect datetime value: 'z' +Warning 1292 Truncated incorrect datetime value: 'z' +Warning 1292 Truncated incorrect time value: 'z' +SELECT +TIMESTAMP(0)=TIMESTAMP('') AS ts, +DATE(0)=DATE('') AS d, +TIME(0)=TIME('') AS t; +ts d t +1 1 1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' +Warning 1292 Truncated incorrect time value: '' +# +# MDEV-17563 Different results using table or view when comparing values of time type +# +CREATE TABLE t1 (pk int, x1 time, x2 varchar(1)); +INSERT INTO t1 VALUES (17,'09:16:37','k'),(70,'19:44:22','k'); +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT pk FROM t1 WHERE x1 >x2; +pk +17 +70 +Warnings: +Warning 1292 Truncated incorrect time value: 'k' +Warning 1292 Truncated incorrect time value: 'k' +SELECT pk FROM v1 WHERE x1 >x2; +pk +17 +70 +Warnings: +Warning 1292 Truncated incorrect time value: 'k' +Warning 1292 Truncated incorrect time value: 'k' +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (pk int, x1 time, x2 varchar(1)); +INSERT INTO t1 VALUES (17,'09:16:37',''),(70,'19:44:22','k'); +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT pk FROM t1 WHERE x1 >x2; +pk +17 +70 +Warnings: +Warning 1292 Truncated incorrect time value: '' +Warning 1292 Truncated incorrect time value: 'k' +SELECT pk FROM v1 WHERE x1 >x2; +pk +17 +70 +Warnings: +Warning 1292 Truncated incorrect time value: '' +Warning 1292 Truncated incorrect time value: 'k' +DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; +# +# MDEV-17625 Different warnings when comparing a garbage to DATETIME vs TIME +# +SELECT TIMESTAMP(0)='z', DATE(0)='z', TIME(0)='z'; +TIMESTAMP(0)='z' DATE(0)='z' TIME(0)='z' +1 1 1 +Warnings: +Warning 1292 Truncated incorrect datetime value: 'z' +Warning 1292 Truncated incorrect datetime value: 'z' +Warning 1292 Truncated incorrect time value: 'z' +# +# MDEV-17319 Assertion `ts_type != MYSQL_TIMESTAMP_TIME' failed upon inserting into TIME field +# +CREATE TABLE t1 (t TIME); +SET SESSION SQL_MODE='TRADITIONAL'; +INSERT INTO t1 VALUES ('0000-00-00 00:00:00'),('0000-00-00 00:00:00'); +ERROR 22007: Incorrect time value: '0000-00-00 00:00:00' for column `test`.`t1`.`t` at row 1 +SET sql_mode=DEFAULT; +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_time.test b/mysql-test/main/type_time.test index d8bb66fcd5c..67f714e61db 100644 --- a/mysql-test/main/type_time.test +++ b/mysql-test/main/type_time.test @@ -514,6 +514,11 @@ SELECT * FROM t1 WHERE a=TIMESTAMP'0000-00-01 10:20:30' AND LENGTH(a)=8; EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=TIMESTAMP'0000-00-01 10:20:30' AND LENGTH(a)=30+RAND(); +EXPLAIN EXTENDED +SELECT * FROM t1 WHERE a=TIMESTAMP'0000-01-00 10:20:30' AND LENGTH(a)=8; +EXPLAIN EXTENDED +SELECT * FROM t1 WHERE a=TIMESTAMP'0001-00-00 10:20:30' AND LENGTH(a)=8; + --echo # Old mode, TIMESTAMP-alike string literal, zero YYYYMMDD, Ok to propagate SELECT * FROM t1 WHERE a='0000-00-00 10:20:30'; SELECT * FROM t1 WHERE a='0000-00-00 10:20:30' AND LENGTH(a)=8; @@ -1290,3 +1295,132 @@ INSERT INTO t1 VALUES ('-838:00:04.1', 'yes'); EXPLAIN SELECT * FROM t1 WHERE a NOT IN ('-838:00:01.1','-838:00:02.1'); SELECT * FROM t1 WHERE a NOT IN ('-838:00:01.1','-838:00:02.1'); DROP TABLE t1; + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters +--echo # + +CREATE TABLE t1 (a TIME); +INSERT INTO t1 VALUES (1),(2),(3); +--echo # Equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME'10:20:30',a)<=>COALESCE(TIME'10:20:30',a); +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIME'10:20:30',TIME'10:20:30'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME''10:20:30'',a)<=>COALESCE(?,a)' USING TIME'10:20:30'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIME''10:20:30'',a)' USING TIME'10:20:30'; +--echo # Not equal values +EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME'10:20:30',a)<=>COALESCE(TIME'10:20:31',a); +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIME'10:20:30',TIME'10:20:31'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME''10:20:30'',a)<=>COALESCE(?,a)' USING TIME'10:20:31'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIME''10:20:30'',a)' USING TIME'10:20:31'; +DROP TABLE t1; + +--echo # +--echo # MDEV-16426 Optimizer erroneously treats equal constants of different formats as same +--echo # +CREATE TABLE t1 (a TIME); +INSERT INTO t1 VALUES ('00:00:00'),('00:00:01'),('00:00:02'); + +--echo Equal values +SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.0',a)); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.0',a)); +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.0'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.0'; + +--echo Values with different formats +SELECT LENGTH(COALESCE(TIME'00:00:00.0',a)),LENGTH(COALESCE(TIME'00:00:00.00',a)) FROM t1; +SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.00',a)); +EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.00',a)); +EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.00'; +EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.00'; + +DROP TABLE t1; + +--echo # +--echo # MDEV-16971 Assertion `is_valid_value_slow()' failed in Time::adjust_time_range_or_invalidate +--echo # +SET sql_mode=''; +CREATE TABLE t1 (d1 date, t1 time, KEY t1 (t1)); +INSERT INTO t1 VALUES ('1982-12-19','08:16:31'),('1981-04-19','21:52:59'),('1971-06-09','07:15:44'),('2007-08-15','03:55:02'),('1993-06-05','04:17:51'),('2034-07-01','17:31:12'),('1998-08-24','08:09:27'),('1991-01-15','01:14:07'),('2001-02-25','10:41:28'),('1974-06-24','10:21:58'),('1977-04-21','16:38:05'),('1981-12-03','01:24:42'),('1972-06-15','20:19:16'),('1989-08-10','08:53:47'),('2018-05-19','15:06:49'),('1984-01-12','15:56:11'),('2013-01-23','04:16:16'),('2000-06-10','02:06:44'),('1995-01-03','04:51:38'); +CREATE TABLE t2 (d1 date ); +INSERT INTO t2 VALUES ('2018-06-01'),('1979-10-25'),('1974-08-22'),('1980-06-17'); +SELECT * FROM (t1 JOIN t2 ON (t2.d1 = t1.t1)) WHERE (t1.d1 > 70 ); +UPDATE (t1 JOIN t2 ON (t2.d1 = t1.t1)) SET t1.d1 = '2018-07-07' WHERE (t1.d1 > 70 ); +DROP TABLE t1,t2; + +--echo # +--echo # MDEV-17219 Assertion `!t->fraction_remainder(decimals())' failed in Field_time::store_TIME_with_warning +--echo # +SET optimizer_use_condition_selectivity=3; +CREATE TABLE t1 (it TIME NOT NULL); +INSERT INTO t1 VALUES ('07:25:13'),('05:15:55'),('09:58:01'),('04:23:57'),('19:37:28'),('01:38:05'),('20:50:52'); +SELECT 1 FROM t1 WHERE it < -7487797330456870912; +DROP TABLE t1; +SET optimizer_use_condition_selectivity=DEFAULT; + +--echo # +--echo # MDEV-17417 TIME(99991231235959) returns 838:59:59 instead of 23:59:58 +--echo # +SELECT TIME(99991231235957), TIME(99991231235958), TIME(99991231235959); + +--echo # +--echo # MDEV-17634 Regression: TIME(0)=TIME('z') returns NULL vs 1 +--echo # +SELECT + TIMESTAMP(0)=TIMESTAMP('z') AS ts, + DATE(0)=DATE('z') AS d, + TIME(0)=TIME('z') AS t; + +SELECT + TIMESTAMP(0)=TIMESTAMP('') AS ts, + DATE(0)=DATE('') AS d, + TIME(0)=TIME('') AS t; + + +--echo # +--echo # MDEV-17563 Different results using table or view when comparing values of time type +--echo # + +CREATE TABLE t1 (pk int, x1 time, x2 varchar(1)); +INSERT INTO t1 VALUES (17,'09:16:37','k'),(70,'19:44:22','k'); +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT pk FROM t1 WHERE x1 >x2; +SELECT pk FROM v1 WHERE x1 >x2; +DROP VIEW v1; +DROP TABLE t1; + + +CREATE TABLE t1 (pk int, x1 time, x2 varchar(1)); +INSERT INTO t1 VALUES (17,'09:16:37',''),(70,'19:44:22','k'); +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT pk FROM t1 WHERE x1 >x2; +SELECT pk FROM v1 WHERE x1 >x2; +DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; + + +--echo # +--echo # MDEV-17625 Different warnings when comparing a garbage to DATETIME vs TIME +--echo # + +SELECT TIMESTAMP(0)='z', DATE(0)='z', TIME(0)='z'; + + +--echo # +--echo # MDEV-17319 Assertion `ts_type != MYSQL_TIMESTAMP_TIME' failed upon inserting into TIME field +--echo # + +CREATE TABLE t1 (t TIME); +SET SESSION SQL_MODE='TRADITIONAL'; +--error ER_TRUNCATED_WRONG_VALUE +INSERT INTO t1 VALUES ('0000-00-00 00:00:00'),('0000-00-00 00:00:00'); +SET sql_mode=DEFAULT; +DROP TABLE t1; + + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_time_round.result b/mysql-test/main/type_time_round.result new file mode 100644 index 00000000000..31e97c888db --- /dev/null +++ b/mysql-test/main/type_time_round.result @@ -0,0 +1,260 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; +# +# TIME: SET +# +CREATE TABLE t1 (a TIME(3), b TIME(4)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(3), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999'); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(3), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,0.9999); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(3), b DOUBLE); +INSERT INTO t1 VALUES(NULL,0.9999); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(6), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +SELECT a FROM t1; +a +00:00:01.000000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(6), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +00:00:01.000000 +DROP TABLE t1; +CREATE TABLE t1 (a TIME(6), b DOUBLE); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +00:00:01.000000 +DROP TABLE t1; +# +# TIME: ALTER +# +CREATE TABLE t1 (a TIME(4)); +INSERT INTO t1 VALUES('00:00:00.9999'); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +a +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999'); +INSERT INTO t1 VALUES('00:00:00.9999999'); +ALTER TABLE t1 MODIFY a TIME(3); +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +ALTER TABLE t1 MODIFY a TIME(3); +Warnings: +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +00:00:01.000 +00:00:01.000 +DROP TABLE t1; +# +# TIME: CAST +# +CREATE TABLE t1 (a TIME(4)); +INSERT INTO t1 VALUES('00:00:00.9999'); +SELECT a, CAST(a AS TIME(3)) FROM t1; +a CAST(a AS TIME(3)) +00:00:00.9999 00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999'); +INSERT INTO t1 VALUES('00:00:00.9999999'); +SELECT a, CAST(a AS TIME(3)) FROM t1; +a CAST(a AS TIME(3)) +00:00:00.9999 00:00:01.000 +00:00:00.9999999 00:00:01.000 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(3)) FROM t1; +a CAST(a AS TIME(3)) +0.9999000000 00:00:01.000 +0.9999999000 00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(3)) FROM t1; +a CAST(a AS TIME(3)) +0.9999 00:00:01.000 +0.9999999 00:00:01.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999999'); +SELECT a, CAST(a AS TIME(6)) FROM t1; +a CAST(a AS TIME(6)) +00:00:00.9999999 00:00:01.000000 +Warnings: +Note 1292 Truncated incorrect time value: '00:00:00.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(6)) FROM t1; +a CAST(a AS TIME(6)) +0.9999999000 00:00:01.000000 +DROP TABLE t1; +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(6)) FROM t1; +a CAST(a AS TIME(6)) +0.9999999 00:00:01.000000 +DROP TABLE t1; +# +# NOW +# +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a TIME(4)); +INSERT INTO t1 (a) VALUES (now(6)); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +id a +1 24:00:00.0000 +2 24:00:00.0000 +3 24:00:00.0000 +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; +# +# Equal field propagation +# +CREATE TABLE t1 (a TIME(6)); +INSERT INTO t1 VALUES (0.999999); +INSERT INTO t1 VALUES (0.9999999); +SELECT * FROM t1 WHERE a=0.9999999; +a +00:00:01.000000 +SELECT * FROM t1 WHERE a='0.9999999'; +a +00:00:01.000000 +Warnings: +Note 1292 Truncated incorrect time value: '0.9999999' +SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999'; +a +00:00:01.000000 +Warnings: +Note 1292 Truncated incorrect time value: '0.9999999' +Note 1292 Truncated incorrect time value: '0.9999999' +SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000'; +a +00:00:01.000000 +Warnings: +Note 1292 Truncated incorrect time value: '0.9999999' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect time value: '0.9999999' +Note 1292 Truncated incorrect time value: '0.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:01' +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1292 Truncated incorrect time value: '0.9999999' +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIME'00:00:01' +DROP TABLE t1; +# +# Comparing non-temporal to TIME +# +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('22:59:59.9999999'); +SELECT * FROM t1 WHERE a=TIME'23:00:00'; +a +22:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '22:59:59.9999999' +SELECT * FROM t1 WHERE CONCAT(a)=TIME'23:00:00'; +a +22:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '22:59:59.9999999' +SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00'; +a +22:59:59.9999999 +Warnings: +Note 1292 Truncated incorrect time value: '22:59:59.9999999' +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (225959.9999999); +SELECT * FROM t1 WHERE a=TIME'23:00:00'; +a +225959.9999999 +SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00'; +a +225959.9999999 +DROP TABLE t1; +# +# Literal corner case +# +SELECT TIME'838:59:59.999999'; +TIME'838:59:59.999999' +838:59:59.999999 +SELECT TIME'838:59:59.9999999'; +ERROR HY000: Incorrect TIME value: '838:59:59.9999999' +SELECT TIME'839:00:00'; +ERROR HY000: Incorrect TIME value: '839:00:00' diff --git a/mysql-test/main/type_time_round.test b/mysql-test/main/type_time_round.test new file mode 100644 index 00000000000..6d4b2d8947a --- /dev/null +++ b/mysql-test/main/type_time_round.test @@ -0,0 +1,184 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; + +--echo # +--echo # TIME: SET +--echo # + +CREATE TABLE t1 (a TIME(3), b TIME(4)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(3), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999'); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(3), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,0.9999); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(3), b DOUBLE); +INSERT INTO t1 VALUES(NULL,0.9999); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(6), b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'00:00:00.9999999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(6), b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIME(6), b DOUBLE); +INSERT INTO t1 VALUES(NULL,0.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # TIME: ALTER +--echo # + +CREATE TABLE t1 (a TIME(4)); +INSERT INTO t1 VALUES('00:00:00.9999'); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999'); +INSERT INTO t1 VALUES('00:00:00.9999999'); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +ALTER TABLE t1 MODIFY a TIME(3); +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # TIME: CAST +--echo # + +CREATE TABLE t1 (a TIME(4)); +INSERT INTO t1 VALUES('00:00:00.9999'); +SELECT a, CAST(a AS TIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999'); +INSERT INTO t1 VALUES('00:00:00.9999999'); +SELECT a, CAST(a AS TIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(3)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('00:00:00.9999999'); +SELECT a, CAST(a AS TIME(6)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(6)) FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES(0.9999999); +SELECT a, CAST(a AS TIME(6)) FROM t1; +DROP TABLE t1; + + +--echo # +--echo # NOW +--echo # + +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a TIME(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; + + +--echo # +--echo # Equal field propagation +--echo # + +CREATE TABLE t1 (a TIME(6)); +INSERT INTO t1 VALUES (0.999999); +INSERT INTO t1 VALUES (0.9999999); +SELECT * FROM t1 WHERE a=0.9999999; +SELECT * FROM t1 WHERE a='0.9999999'; +SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999'; +SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND a>='0.9999999'; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='0.9999999' AND CONCAT(a)='00:00:01.000000'; +DROP TABLE t1; + + +--echo # +--echo # Comparing non-temporal to TIME +--echo # + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('22:59:59.9999999'); +SELECT * FROM t1 WHERE a=TIME'23:00:00'; +SELECT * FROM t1 WHERE CONCAT(a)=TIME'23:00:00'; +SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00'; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (225959.9999999); +SELECT * FROM t1 WHERE a=TIME'23:00:00'; +SELECT * FROM t1 WHERE COALESCE(a)=TIME'23:00:00'; +DROP TABLE t1; + +--echo # +--echo # Literal corner case +--echo # + +SELECT TIME'838:59:59.999999'; +--error ER_WRONG_VALUE +SELECT TIME'838:59:59.9999999'; +--error ER_WRONG_VALUE +SELECT TIME'839:00:00'; diff --git a/mysql-test/main/type_timestamp.result b/mysql-test/main/type_timestamp.result index 498cc472f17..14fa13d59e2 100644 --- a/mysql-test/main/type_timestamp.result +++ b/mysql-test/main/type_timestamp.result @@ -492,8 +492,12 @@ INSERT INTO t1 (f2,f3) VALUES (NOW(), "0000-00-00 00:00:00"); INSERT INTO t1 (f2,f3) VALUES (NOW(), NULL); INSERT INTO t1 (f2,f3) VALUES (NOW(), ASCII(NULL)); INSERT INTO t1 (f2,f3) VALUES (NOW(), FROM_UNIXTIME('9999999999')); +Warnings: +Warning 1292 Truncated incorrect unixtime value: '9999999999' INSERT INTO t1 (f2,f3) VALUES (NOW(), TIME(NULL)); UPDATE t1 SET f2=NOW(), f3=FROM_UNIXTIME('9999999999') WHERE f1=1; +Warnings: +Warning 1292 Truncated incorrect unixtime value: '9999999999' SELECT f1,f2-f3 FROM t1; f1 f2-f3 1 0 @@ -868,7 +872,7 @@ SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage '; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Warning 1292 Incorrect datetime value: ' garbage ' +Warning 1292 Truncated incorrect datetime value: ' garbage ' Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00' and <cache>(octet_length(TIMESTAMP'0000-00-00 00:00:00')) = 30 + rand() DROP TABLE t1; CREATE TABLE t1 (a TIMESTAMP);; @@ -1014,3 +1018,130 @@ DROP TABLE t1; # # End of 10.3 tests # +# +# Start of 10.4 tests +# +# +# MDEV-17216 Assertion `!dt->fraction_remainder(decimals())' failed in Field_temporal_with_date::store_TIME_with_warning +# +CREATE TABLE t1 (b BIT(20)); +CREATE TABLE t2 (t TIMESTAMP); +INSERT IGNORE INTO t1 VALUES (b'000001001100000'); +INSERT INTO t2 SELECT * FROM t1; +DROP TABLE t1, t2; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 SELECT CAST(20010101 AS UNSIGNED); +DROP TABLE t1; +# +# MDEV-17928 Conversion from TIMESTAMP to VARCHAR SP variables does not work well on fractional digits +# +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30.123456'); +CREATE PROCEDURE p1() +BEGIN +DECLARE ts10 TIMESTAMP(1) DEFAULT NOW(); +DECLARE ts16 TIMESTAMP(1) DEFAULT NOW(6); +DECLARE dt10 DATETIME(1) DEFAULT NOW(); +DECLARE dt16 DATETIME(1) DEFAULT NOW(6); +DECLARE vts10 VARCHAR(32) DEFAULT ts10; +DECLARE vts16 VARCHAR(32) DEFAULT ts16; +DECLARE vdt10 VARCHAR(32) DEFAULT dt10; +DECLARE vdt16 VARCHAR(32) DEFAULT dt16; +DECLARE tts10 TEXT(32) DEFAULT ts10; +DECLARE tts16 TEXT(32) DEFAULT ts16; +DECLARE tdt10 TEXT(32) DEFAULT dt10; +DECLARE tdt16 TEXT(32) DEFAULT dt16; +SELECT vts10, vts16, vdt10, vdt16; +SELECT tts10, tts16, tdt10, tdt16; +END; +$$ +CALL p1; +vts10 2001-01-01 10:20:30.0 +vts16 2001-01-01 10:20:30.1 +vdt10 2001-01-01 10:20:30.0 +vdt16 2001-01-01 10:20:30.1 +tts10 2001-01-01 10:20:30.0 +tts16 2001-01-01 10:20:30.1 +tdt10 2001-01-01 10:20:30.0 +tdt16 2001-01-01 10:20:30.1 +DROP PROCEDURE p1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; +# +# MDEV-13995 MAX(timestamp) returns a wrong result near DST change +# +# Testing Item_func_rollup_const::val_native() +# There is a bug in the below output (MDEV-16612) +# Please remove this comment when MDEV-16612 is fixed and results are re-recorded +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1),(2); +BEGIN NOT ATOMIC +DECLARE v TIMESTAMP DEFAULT '2001-01-01 10:20:30'; -- "v" will be wrapped into Item_func_rollup_const +SELECT id, v AS v, COUNT(*) FROM t1 GROUP BY id,v WITH ROLLUP; +END; +$$ +id v COUNT(*) +1 2001-01-01 10:20:30 1 +1 2001-01-01 10:20:30 1 +2 2001-01-01 10:20:30 1 +2 2001-01-01 10:20:30 1 +NULL 2001-01-01 10:20:30 2 +DROP TABLE t1; +# +# Testing Type_handler_timestamp_common::Item_save_in_field() +# "txt" is expected to have three fractional digits +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30.123456'); +CREATE TABLE t1 (ts1 TIMESTAMP(1) NOT NULL, ts2 TIMESTAMP(3) NOT NULL, txt TEXT); +INSERT INTO t1 VALUES ('0000-00-00 00:00:00', '0000-00-00 00:00:00',COALESCE(ts1,ts2)); +INSERT INTO t1 VALUES (NOW(),NOW(),COALESCE(ts1,ts2)); +INSERT INTO t1 VALUES (NOW(1),NOW(3),COALESCE(ts1,ts2)); +SELECT * FROM t1; +ts1 ts2 txt +0000-00-00 00:00:00.0 0000-00-00 00:00:00.000 0000-00-00 00:00:00.000 +2001-01-01 10:20:30.0 2001-01-01 10:20:30.000 2001-01-01 10:20:30.000 +2001-01-01 10:20:30.1 2001-01-01 10:20:30.123 2001-01-01 10:20:30.100 +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; +# +# Testing Field_timestamp::store_native +# +SET sql_mode=''; +CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP); +INSERT INTO t1 VALUES ('0000-00-00 00:00:00','0000-00-00 00:00:00'); +SET sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE'; +UPDATE t1 SET a=b; +ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column `test`.`t1`.`a` at row 1 +UPDATE t1 SET a=COALESCE(b); +ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column `test`.`t1`.`a` at row 1 +DROP TABLE t1; +SET sql_mode=DEFAULT; +# +# MDEV-17979 Assertion `0' failed in Item::val_native upon SELECT with timestamp, NULLIF, GROUP BY +# +CREATE TABLE t1 (a INT, b TIMESTAMP) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,'2018-06-19 00:00:00'); +SELECT NULLIF(b, 'N/A') AS f, MAX(a) FROM t1 GROUP BY f; +f MAX(a) +2018-06-19 00:00:00 1 +Warnings: +Warning 1292 Truncated incorrect datetime value: 'N/A' +DROP TABLE t1; +# +# MDEV-17972 Assertion `is_valid_value_slow()' failed in Datetime::Datetime +# +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP(6)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('2001-01-01 10:20:30'); +FLUSH TABLES; +MYD +FF77777777FFFFFF +SELECT a, CAST(a AS DATETIME) AS dt0, CAST(a AS DATETIME(6)) AS dt6 FROM t1; +a dt0 dt6 +2033-07-07 03:01:11.999999 2033-07-07 03:01:11 2033-07-07 03:01:11.999999 +DROP TABLE t1; +SET time_zone=DEFAULT; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_timestamp.test b/mysql-test/main/type_timestamp.test index 6d81a86331a..3eb2c86e57f 100644 --- a/mysql-test/main/type_timestamp.test +++ b/mysql-test/main/type_timestamp.test @@ -606,3 +606,140 @@ DROP TABLE t1; --echo # --echo # End of 10.3 tests --echo # + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-17216 Assertion `!dt->fraction_remainder(decimals())' failed in Field_temporal_with_date::store_TIME_with_warning +--echo # + +CREATE TABLE t1 (b BIT(20)); +CREATE TABLE t2 (t TIMESTAMP); +INSERT IGNORE INTO t1 VALUES (b'000001001100000'); +INSERT INTO t2 SELECT * FROM t1; +DROP TABLE t1, t2; + +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 SELECT CAST(20010101 AS UNSIGNED); +DROP TABLE t1; + + +--echo # +--echo # MDEV-17928 Conversion from TIMESTAMP to VARCHAR SP variables does not work well on fractional digits +--echo # + +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30.123456'); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE ts10 TIMESTAMP(1) DEFAULT NOW(); + DECLARE ts16 TIMESTAMP(1) DEFAULT NOW(6); + DECLARE dt10 DATETIME(1) DEFAULT NOW(); + DECLARE dt16 DATETIME(1) DEFAULT NOW(6); + DECLARE vts10 VARCHAR(32) DEFAULT ts10; + DECLARE vts16 VARCHAR(32) DEFAULT ts16; + DECLARE vdt10 VARCHAR(32) DEFAULT dt10; + DECLARE vdt16 VARCHAR(32) DEFAULT dt16; + DECLARE tts10 TEXT(32) DEFAULT ts10; + DECLARE tts16 TEXT(32) DEFAULT ts16; + DECLARE tdt10 TEXT(32) DEFAULT dt10; + DECLARE tdt16 TEXT(32) DEFAULT dt16; + + SELECT vts10, vts16, vdt10, vdt16; + SELECT tts10, tts16, tdt10, tdt16; +END; +$$ +DELIMITER ;$$ +--vertical_results +CALL p1; +--horizontal_results +DROP PROCEDURE p1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; + +--echo # +--echo # MDEV-13995 MAX(timestamp) returns a wrong result near DST change +--echo # + +--echo # Testing Item_func_rollup_const::val_native() + +--echo # There is a bug in the below output (MDEV-16612) +--echo # Please remove this comment when MDEV-16612 is fixed and results are re-recorded + +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1),(2); +DELIMITER $$; +BEGIN NOT ATOMIC + DECLARE v TIMESTAMP DEFAULT '2001-01-01 10:20:30'; -- "v" will be wrapped into Item_func_rollup_const + SELECT id, v AS v, COUNT(*) FROM t1 GROUP BY id,v WITH ROLLUP; +END; +$$ +DELIMITER ;$$ +DROP TABLE t1; + +--echo # +--echo # Testing Type_handler_timestamp_common::Item_save_in_field() +--echo # "txt" is expected to have three fractional digits +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30.123456'); +CREATE TABLE t1 (ts1 TIMESTAMP(1) NOT NULL, ts2 TIMESTAMP(3) NOT NULL, txt TEXT); +INSERT INTO t1 VALUES ('0000-00-00 00:00:00', '0000-00-00 00:00:00',COALESCE(ts1,ts2)); +INSERT INTO t1 VALUES (NOW(),NOW(),COALESCE(ts1,ts2)); +INSERT INTO t1 VALUES (NOW(1),NOW(3),COALESCE(ts1,ts2)); +SELECT * FROM t1; +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; + +--echo # +--echo # Testing Field_timestamp::store_native +--echo # + +SET sql_mode=''; +CREATE TABLE t1 (a TIMESTAMP, b TIMESTAMP); +INSERT INTO t1 VALUES ('0000-00-00 00:00:00','0000-00-00 00:00:00'); +SET sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE'; +--error ER_TRUNCATED_WRONG_VALUE +UPDATE t1 SET a=b; +--error ER_TRUNCATED_WRONG_VALUE +UPDATE t1 SET a=COALESCE(b); +DROP TABLE t1; +SET sql_mode=DEFAULT; + +--echo # +--echo # MDEV-17979 Assertion `0' failed in Item::val_native upon SELECT with timestamp, NULLIF, GROUP BY +--echo # + +CREATE TABLE t1 (a INT, b TIMESTAMP) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,'2018-06-19 00:00:00'); +SELECT NULLIF(b, 'N/A') AS f, MAX(a) FROM t1 GROUP BY f; +DROP TABLE t1; + +--echo # +--echo # MDEV-17972 Assertion `is_valid_value_slow()' failed in Datetime::Datetime +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +SET time_zone='+00:00'; +CREATE TABLE t1 (a TIMESTAMP(6)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('2001-01-01 10:20:30'); +FLUSH TABLES; +--remove_file $MYSQLD_DATADIR/test/t1.MYD +--disable_query_log +# Write a data file with one record: +# 0xFF - record flags +# 0x77777777 - TIMESTAMP integer part +# 0xFFFFFF - TIMESTAMP bad fractional part +--eval SELECT CONCAT(0xFF,0x77777777,0xFFFFFF) INTO OUTFILE '$MYSQLD_DATADIR/test/t1.MYD' FIELDS TERMINATED BY '' ESCAPED BY '' LINES TERMINATED BY '' +--eval SELECT HEX(LOAD_FILE('$MYSQLD_DATADIR/test/t1.MYD')) AS MYD +--enable_query_log +SELECT a, CAST(a AS DATETIME) AS dt0, CAST(a AS DATETIME(6)) AS dt6 FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/type_timestamp_round.result b/mysql-test/main/type_timestamp_round.result new file mode 100644 index 00000000000..7931aa0ff5b --- /dev/null +++ b/mysql-test/main/type_timestamp_round.result @@ -0,0 +1,191 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; +# +# TIMESTAMP: SET +# +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b TIMESTAMP(4) NULL DEFAULT NULL); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +Warnings: +Note 1265 Data truncated for column 'a' at row 2 +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +# +# TIMESTAMP: ALTER +# +CREATE TABLE t1 (a TIMESTAMP(4) NULL DEFAULT NULL); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +Warnings: +Note 1292 Truncated incorrect datetime value: '2000-12-31 23:59:59.9999999' +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +SELECT a FROM t1; +a +2001-01-01 00:00:00.000 +2001-01-01 00:00:00.000 +DROP TABLE t1; +# +# Corner case: +# ALTER TIMESTAMP to a shorter TIMESTAMP +# All values round, maximum possible value truncates. +# +SET time_zone='+00:00'; +CREATE TABLE t1 (ID INT, a TIMESTAMP(6), comment VARCHAR(64)); +INSERT INTO t1 VALUES (0, '2038-01-18 23:59:59.999999', 'Should round'); +INSERT INTO t1 VALUES (1, '2038-01-19 03:14:06.999999', 'Should round'); +INSERT INTO t1 VALUES (2, '2038-01-19 03:14:07.999999', 'Should truncate'); +ALTER TABLE t1 MODIFY a TIMESTAMP(5); +Warnings: +Warning 1264 Out of range value for column 'a' at row 3 +SELECT * FROM t1; +ID a comment +0 2038-01-19 00:00:00.00000 Should round +1 2038-01-19 03:14:07.00000 Should round +2 2038-01-19 03:14:07.99999 Should truncate +DROP TABLE t1; +SET time_zone=DEFAULT; +# +# NOW +# +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a TIMESTAMP(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-01 00:00:00.0000 +3 2011-01-01 00:00:00.0000 +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; +# +# DATETIME to TIMESTAMP conversion with DST change +# +SET sql_mode=IF(@@version LIKE '%MariaDB%', +'STRICT_ALL_TABLES,TIME_ROUND_FRACTIONAL', +'STRICT_ALL_TABLES'); +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap */); +ERROR 22007: Incorrect datetime value: '2010-03-28 01:59:59.9' for column `test`.`t1`.`a` at row 1 +SELECT * FROM t1; +a +2010-03-28 01:59:59 +DROP TABLE t1; +SET time_zone=DEFAULT; +SET sql_mode=@default_sql_mode; +SET sql_mode=IF(@@version LIKE '%MariaDB%','TIME_ROUND_FRACTIONAL',''); +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap, then gets fixed to the first second of the summer time */); +Warnings: +Warning 1299 Invalid TIMESTAMP value in column 'a' at row 1 +SELECT a, UNIX_TIMESTAMP(a) FROM t1; +a UNIX_TIMESTAMP(a) +2010-03-28 01:59:59 1269730799 +2010-03-28 03:00:00 1269730800 +DROP TABLE t1; +SET time_zone=DEFAULT; +SET sql_mode=@default_sql_mode; +# +# Comparing non-temporal to TIMESTAMP +# +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t2 VALUES ('2001-01-02 00:00:00'); +SELECT * FROM t1,t2 WHERE t1.a=t2.a; +a a +2001-01-01 23:59:59.9999999 2001-01-02 00:00:00 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1,t2 WHERE CONCAT(t1.a)=t2.a; +a a +2001-01-01 23:59:59.9999999 2001-01-02 00:00:00 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a; +a a +2001-01-01 23:59:59.9999999 2001-01-02 00:00:00 +Warnings: +Note 1292 Truncated incorrect datetime value: '2001-01-01 23:59:59.9999999' +DROP TABLE t1,t2; +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t2 VALUES ('2001-01-02 00:00:00'); +SELECT * FROM t1,t2 WHERE t1.a=t2.a; +a a +20010101235959.9999999 2001-01-02 00:00:00 +SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a; +a a +20010101235959.9999999 2001-01-02 00:00:00 +DROP TABLE t1,t2; +# +# MDEV-13995 MAX(timestamp) returns a wrong result near DST change +# +# Test Field_timestamp::store_native() +# +SET sql_mode=@default_sql_mode; +SET time_zone='+00:00'; +CREATE TABLE t1 (ts0 TIMESTAMP, ts1 TIMESTAMP(1)); +INSERT INTO t1 VALUES ('2001-01-01 10:20:30', '2001-01-01 10:20:30.9'); +SELECT * FROM t1; +ts0 ts1 +2001-01-01 10:20:30 2001-01-01 10:20:30.9 +# This should round +UPDATE t1 SET ts0=COALESCE(ts1); +SELECT * FROM t1; +ts0 ts1 +2001-01-01 10:20:31 2001-01-01 10:20:30.9 +# Corner case +UPDATE t1 SET ts1=FROM_UNIXTIME(2147483647.9); +UPDATE t1 SET ts0=COALESCE(ts1); +Warnings: +Warning 1264 Out of range value for column 'ts0' at row 1 +SELECT * FROM t1; +ts0 ts1 +2038-01-19 03:14:07 2038-01-19 03:14:07.9 +DROP TABLE t1; +SET time_zone=DEFAULT; diff --git a/mysql-test/main/type_timestamp_round.test b/mysql-test/main/type_timestamp_round.test new file mode 100644 index 00000000000..19e0ea86da5 --- /dev/null +++ b/mysql-test/main/type_timestamp_round.test @@ -0,0 +1,160 @@ +SET sql_mode=IF(@@version LIKE '%MariaDB%', 'TIME_ROUND_FRACTIONAL', ''); +SET @default_sql_mode=@@sql_mode; + +--echo # +--echo # TIMESTAMP: SET +--echo # + +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b TIMESTAMP(4) NULL DEFAULT NULL); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b VARCHAR(64)); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES(NULL,'2000-12-31 23:59:59.9999999'); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a TIMESTAMP(3) NULL DEFAULT NULL, b DECIMAL(38,10)); +INSERT INTO t1 VALUES(NULL,20001231235959.9999); +INSERT INTO t1 VALUES(NULL,20001231235959.9999999); +UPDATE t1 SET a=b; +SELECT a FROM t1; +DROP TABLE t1; + +--echo # +--echo # TIMESTAMP: ALTER +--echo # + +CREATE TABLE t1 (a TIMESTAMP(4) NULL DEFAULT NULL); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999'); +INSERT INTO t1 VALUES('2000-12-31 23:59:59.9999999'); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +SELECT a FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a DECIMAL(38,10)); +INSERT INTO t1 VALUES(20001231235959.9999); +INSERT INTO t1 VALUES(20001231235959.9999999); +ALTER TABLE t1 MODIFY a TIMESTAMP(3) NULL DEFAULT NULL; +SELECT a FROM t1; +DROP TABLE t1; + + +--echo # +--echo # Corner case: +--echo # ALTER TIMESTAMP to a shorter TIMESTAMP +--echo # All values round, maximum possible value truncates. +--echo # + +SET time_zone='+00:00'; +CREATE TABLE t1 (ID INT, a TIMESTAMP(6), comment VARCHAR(64)); +INSERT INTO t1 VALUES (0, '2038-01-18 23:59:59.999999', 'Should round'); +INSERT INTO t1 VALUES (1, '2038-01-19 03:14:06.999999', 'Should round'); +INSERT INTO t1 VALUES (2, '2038-01-19 03:14:07.999999', 'Should truncate'); +ALTER TABLE t1 MODIFY a TIMESTAMP(5); +SELECT * FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; + +--echo # +--echo # NOW +--echo # + +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE OR REPLACE TABLE t1 (id SERIAL, a TIMESTAMP(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIMESTAMP(6)); +INSERT INTO t1 (a) VALUES (CURRENT_TIME(6)); +SELECT * FROM t1; +DROP TABLE t1; +SET timestamp=DEFAULT; +SET time_zone=DEFAULT; + + +--echo # +--echo # DATETIME to TIMESTAMP conversion with DST change +--echo # + +--disable_warnings +SET sql_mode=IF(@@version LIKE '%MariaDB%', + 'STRICT_ALL_TABLES,TIME_ROUND_FRACTIONAL', + 'STRICT_ALL_TABLES'); +--enable_warnings +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */); +--error ER_TRUNCATED_WRONG_VALUE +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap */); +SELECT * FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; +--disable_warnings +SET sql_mode=@default_sql_mode; +--enable_warnings + +SET sql_mode=IF(@@version LIKE '%MariaDB%','TIME_ROUND_FRACTIONAL',''); +SET time_zone='Europe/Moscow'; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.0' /* Winter time */); +INSERT INTO t1 VALUES ('2010-03-28 01:59:59.9' /* Rounds to the DST gap, then gets fixed to the first second of the summer time */); +SELECT a, UNIX_TIMESTAMP(a) FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; +--disable_warnings +SET sql_mode=@default_sql_mode; +--enable_warnings + + +--echo # +--echo # Comparing non-temporal to TIMESTAMP +--echo # + +CREATE TABLE t1 (a VARCHAR(64)); +INSERT t1 VALUES ('2001-01-01 23:59:59.9999999'); +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t2 VALUES ('2001-01-02 00:00:00'); +SELECT * FROM t1,t2 WHERE t1.a=t2.a; +SELECT * FROM t1,t2 WHERE CONCAT(t1.a)=t2.a; +SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a; +DROP TABLE t1,t2; + +CREATE TABLE t1 (a DECIMAL(32,7)); +INSERT t1 VALUES (20010101235959.9999999); +CREATE TABLE t2 (a TIMESTAMP); +INSERT INTO t2 VALUES ('2001-01-02 00:00:00'); +SELECT * FROM t1,t2 WHERE t1.a=t2.a; +SELECT * FROM t1,t2 WHERE COALESCE(t1.a)=t2.a; +DROP TABLE t1,t2; + + +--echo # +--echo # MDEV-13995 MAX(timestamp) returns a wrong result near DST change +--echo # +--echo # Test Field_timestamp::store_native() +--echo # + +SET sql_mode=@default_sql_mode; +SET time_zone='+00:00'; +CREATE TABLE t1 (ts0 TIMESTAMP, ts1 TIMESTAMP(1)); +INSERT INTO t1 VALUES ('2001-01-01 10:20:30', '2001-01-01 10:20:30.9'); +SELECT * FROM t1; +--echo # This should round +UPDATE t1 SET ts0=COALESCE(ts1); +SELECT * FROM t1; +--echo # Corner case +UPDATE t1 SET ts1=FROM_UNIXTIME(2147483647.9); +UPDATE t1 SET ts0=COALESCE(ts1); +SELECT * FROM t1; +DROP TABLE t1; +SET time_zone=DEFAULT; diff --git a/mysql-test/main/type_varchar.result b/mysql-test/main/type_varchar.result index 0b2a5b54d08..53f390e8b38 100644 --- a/mysql-test/main/type_varchar.result +++ b/mysql-test/main/type_varchar.result @@ -12,7 +12,7 @@ t1 CREATE TABLE `t1` ( show create table vchar; Table Create Table vchar CREATE TABLE `vchar` ( - `v` varchar(30) DEFAULT NULL, + `v` varchar(30)/*old*/ DEFAULT NULL, `c` char(3) DEFAULT NULL, `e` enum('abc','def','ghi') DEFAULT NULL, `t` text DEFAULT NULL diff --git a/mysql-test/main/type_varchar_mysql41.result b/mysql-test/main/type_varchar_mysql41.result new file mode 100644 index 00000000000..116e29a27c5 --- /dev/null +++ b/mysql-test/main/type_varchar_mysql41.result @@ -0,0 +1,113 @@ +# +# MDEV-16325 CREATE..SELECT..UNION creates a wrong field type for old varchar +# +CREATE PROCEDURE p1(col VARCHAR(32)) +BEGIN +EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2_simple AS SELECT col FROM t1old','col',col); +SHOW CREATE TABLE t2_simple; +DROP TABLE t2_simple; +EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2_union_vv AS SELECT col FROM t1old UNION SELECT col FROM t1old','col',col); +SHOW CREATE TABLE t2_union_vv; +DROP TABLE t2_union_vv; +EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2_union_vn AS SELECT col FROM t1old UNION SELECT NULL','col',col); +SHOW CREATE TABLE t2_union_vn; +DROP TABLE t2_union_vn; +EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2_union_nv AS SELECT NULL AS col UNION SELECT col FROM t1old','col',col); +SHOW CREATE TABLE t2_union_nv; +DROP TABLE t2_union_nv; +EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2 AS SELECT + COALESCE(col), + COALESCE(col,col), + COALESCE(col,NULL), + COALESCE(NULL,col) + FROM t1old', 'col', col); +SHOW CREATE TABLE t2; +DROP TABLE t2; +EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2 AS SELECT + LEAST(col,col), + LEAST(col,NULL), + LEAST(NULL,col) + FROM t1old','col',col); +SHOW CREATE TABLE t2; +DROP TABLE t2; +END; +$$ +TRUNCATE TABLE t1old; +SHOW CREATE TABLE t1old; +Table Create Table +t1old CREATE TABLE `t1old` ( + `v` varchar(30)/*old*/ DEFAULT NULL, + `c` char(3) DEFAULT NULL, + `e` enum('abc','def','ghi') DEFAULT NULL, + `t` text DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +CALL p1('v'); +Table Create Table +t2_simple CREATE TABLE `t2_simple` ( + `v` varchar(30) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Table Create Table +t2_union_vv CREATE TABLE `t2_union_vv` ( + `v` varchar(30) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Table Create Table +t2_union_vn CREATE TABLE `t2_union_vn` ( + `v` varchar(30) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Table Create Table +t2_union_nv CREATE TABLE `t2_union_nv` ( + `v` varchar(30) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Table Create Table +t2 CREATE TABLE `t2` ( + `COALESCE(v)` varchar(30) DEFAULT NULL, + `COALESCE(v,v)` varchar(30) DEFAULT NULL, + `COALESCE(v,NULL)` varchar(30) DEFAULT NULL, + `COALESCE(NULL,v)` varchar(30) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Table Create Table +t2 CREATE TABLE `t2` ( + `LEAST(v,v)` varchar(30) DEFAULT NULL, + `LEAST(v,NULL)` varchar(30) DEFAULT NULL, + `LEAST(NULL,v)` varchar(30) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1old; +TRUNCATE TABLE t1old; +SHOW CREATE TABLE t1old; +Table Create Table +t1old CREATE TABLE `t1old` ( + `a` varbinary(255)/*old*/ DEFAULT NULL, + `b` varchar(255)/*old*/ DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +CALL p1('a'); +Table Create Table +t2_simple CREATE TABLE `t2_simple` ( + `a` varbinary(255) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Table Create Table +t2_union_vv CREATE TABLE `t2_union_vv` ( + `a` varbinary(255) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Table Create Table +t2_union_vn CREATE TABLE `t2_union_vn` ( + `a` varbinary(255) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Table Create Table +t2_union_nv CREATE TABLE `t2_union_nv` ( + `a` varbinary(255) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Table Create Table +t2 CREATE TABLE `t2` ( + `COALESCE(a)` varbinary(255) DEFAULT NULL, + `COALESCE(a,a)` varbinary(255) DEFAULT NULL, + `COALESCE(a,NULL)` varbinary(255) DEFAULT NULL, + `COALESCE(NULL,a)` varbinary(255) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Table Create Table +t2 CREATE TABLE `t2` ( + `LEAST(a,a)` varbinary(255) DEFAULT NULL, + `LEAST(a,NULL)` varbinary(255) DEFAULT NULL, + `LEAST(NULL,a)` varbinary(255) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1old; +DROP PROCEDURE p1; diff --git a/mysql-test/main/type_varchar_mysql41.test b/mysql-test/main/type_varchar_mysql41.test new file mode 100644 index 00000000000..5624e9edaaa --- /dev/null +++ b/mysql-test/main/type_varchar_mysql41.test @@ -0,0 +1,59 @@ +--echo # +--echo # MDEV-16325 CREATE..SELECT..UNION creates a wrong field type for old varchar +--echo # + + +DELIMITER $$; +CREATE PROCEDURE p1(col VARCHAR(32)) +BEGIN + EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2_simple AS SELECT col FROM t1old','col',col); + SHOW CREATE TABLE t2_simple; + DROP TABLE t2_simple; + + EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2_union_vv AS SELECT col FROM t1old UNION SELECT col FROM t1old','col',col); + SHOW CREATE TABLE t2_union_vv; + DROP TABLE t2_union_vv; + + EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2_union_vn AS SELECT col FROM t1old UNION SELECT NULL','col',col); + SHOW CREATE TABLE t2_union_vn; + DROP TABLE t2_union_vn; + + EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2_union_nv AS SELECT NULL AS col UNION SELECT col FROM t1old','col',col); + SHOW CREATE TABLE t2_union_nv; + DROP TABLE t2_union_nv; + + EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2 AS SELECT + COALESCE(col), + COALESCE(col,col), + COALESCE(col,NULL), + COALESCE(NULL,col) + FROM t1old', 'col', col); + SHOW CREATE TABLE t2; + DROP TABLE t2; + + EXECUTE IMMEDIATE REPLACE('CREATE TABLE t2 AS SELECT + LEAST(col,col), + LEAST(col,NULL), + LEAST(NULL,col) + FROM t1old','col',col); + SHOW CREATE TABLE t2; + DROP TABLE t2; +END; +$$ +DELIMITER ;$$ + +let $MYSQLD_DATADIR= `SELECT @@datadir`; +copy_file $MYSQL_TEST_DIR/std_data/vchar.frm $MYSQLD_DATADIR/test/t1old.frm; +TRUNCATE TABLE t1old; +SHOW CREATE TABLE t1old; +CALL p1('v'); +DROP TABLE t1old; + +let $MYSQLD_DATADIR= `SELECT @@datadir`; +copy_file $MYSQL_TEST_DIR/std_data/bug19371.frm $MYSQLD_DATADIR/test/t1old.frm; +TRUNCATE TABLE t1old; +SHOW CREATE TABLE t1old; +CALL p1('a'); +DROP TABLE t1old; + +DROP PROCEDURE p1; diff --git a/mysql-test/main/type_year.result b/mysql-test/main/type_year.result index c4b72483c99..3f589f38267 100644 --- a/mysql-test/main/type_year.result +++ b/mysql-test/main/type_year.result @@ -493,3 +493,88 @@ DROP TABLE t1; # # End of 10.2 tests # +# +# Start of 10.4 tests +# +# +# MDEV-16451 Split Item_equal::add_const() into a virtual method in type_handler() +# +CREATE TABLE t1 (a YEAR(4)); +INSERT INTO t1 VALUES (93),(94); +SELECT * FROM t1; +a +1993 +1994 +SELECT * FROM t1 WHERE a=1993 and a=93; +a +1993 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=1993 and a=93; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1993 +DROP TABLE t1; +CREATE TABLE t1 (a YEAR(2)); +Warnings: +Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead +INSERT INTO t1 VALUES (93),(94); +SELECT * FROM t1; +a +93 +94 +SELECT * FROM t1 WHERE a=1993 and a=93; +a +93 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=1993 and a=93; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 93 +DROP TABLE t1; +# +# MDEV-16926 CAST(COALESCE(year_field)) returns wrong value +# +CREATE OR REPLACE TABLE t1 (a YEAR); +INSERT INTO t1 VALUES (1970),(1978),(2000),(2069); +SELECT a, CAST(a AS DATE), CAST(COALESCE(a) AS DATE) FROM t1; +a CAST(a AS DATE) CAST(COALESCE(a) AS DATE) +1970 1970-00-00 1970-00-00 +1978 1978-00-00 1978-00-00 +2000 2000-00-00 2000-00-00 +2069 2069-00-00 2069-00-00 +SELECT MIN(a), MAX(a) FROM t1; +MIN(a) MAX(a) +1970 2069 +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a YEAR(2)); +Warnings: +Note 1287 'YEAR(2)' is deprecated and will be removed in a future release. Please use YEAR(4) instead +INSERT INTO t1 VALUES (1970),(1978),(2000),(2069); +SELECT a, CAST(a AS DATE), CAST(COALESCE(a) AS DATE) FROM t1; +a CAST(a AS DATE) CAST(COALESCE(a) AS DATE) +70 1970-00-00 1970-00-00 +78 1978-00-00 1978-00-00 +00 2000-00-00 2000-00-00 +69 2069-00-00 2069-00-00 +SELECT MIN(a), MAX(a) FROM t1; +MIN(a) MAX(a) +70 69 +DROP TABLE t1; +# +# MDEV-17015 Assertion `m_year <= 9999' failed in Year::Year upon bad argument to MAKEDATE +# +SELECT MAKEDATE(18446744073709551615, 1); +MAKEDATE(18446744073709551615, 1) +NULL +# +# MDEV-17607 DATE(COALESCE(year_column)) returns a wrong result +# +CREATE TABLE t1 (a YEAR); +INSERT INTO t1 VALUES (NULL); +SELECT COALESCE(a), DATE(COALESCE(a)) FROM t1; +COALESCE(a) DATE(COALESCE(a)) +NULL NULL +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_year.test b/mysql-test/main/type_year.test index 5a02c038caa..ea7514898cd 100644 --- a/mysql-test/main/type_year.test +++ b/mysql-test/main/type_year.test @@ -261,3 +261,60 @@ DROP TABLE t1; --echo # --echo # End of 10.2 tests --echo # + + +--echo # +--echo # Start of 10.4 tests +--echo # + +--echo # +--echo # MDEV-16451 Split Item_equal::add_const() into a virtual method in type_handler() +--echo # + +CREATE TABLE t1 (a YEAR(4)); +INSERT INTO t1 VALUES (93),(94); +SELECT * FROM t1; +SELECT * FROM t1 WHERE a=1993 and a=93; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=1993 and a=93; +DROP TABLE t1; + +CREATE TABLE t1 (a YEAR(2)); +INSERT INTO t1 VALUES (93),(94); +SELECT * FROM t1; +SELECT * FROM t1 WHERE a=1993 and a=93; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=1993 and a=93; +DROP TABLE t1; + +--echo # +--echo # MDEV-16926 CAST(COALESCE(year_field)) returns wrong value +--echo # + +CREATE OR REPLACE TABLE t1 (a YEAR); +INSERT INTO t1 VALUES (1970),(1978),(2000),(2069); +SELECT a, CAST(a AS DATE), CAST(COALESCE(a) AS DATE) FROM t1; +SELECT MIN(a), MAX(a) FROM t1; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a YEAR(2)); +INSERT INTO t1 VALUES (1970),(1978),(2000),(2069); +SELECT a, CAST(a AS DATE), CAST(COALESCE(a) AS DATE) FROM t1; +SELECT MIN(a), MAX(a) FROM t1; +DROP TABLE t1; + +--echo # +--echo # MDEV-17015 Assertion `m_year <= 9999' failed in Year::Year upon bad argument to MAKEDATE +--echo # +SELECT MAKEDATE(18446744073709551615, 1); + +--echo # +--echo # MDEV-17607 DATE(COALESCE(year_column)) returns a wrong result +--echo # + +CREATE TABLE t1 (a YEAR); +INSERT INTO t1 VALUES (NULL); +SELECT COALESCE(a), DATE(COALESCE(a)) FROM t1; +DROP TABLE t1; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/udf.result b/mysql-test/main/udf.result index 6af6b167511..13eb186135b 100644 --- a/mysql-test/main/udf.result +++ b/mysql-test/main/udf.result @@ -465,3 +465,108 @@ a b Hello HL DROP FUNCTION METAPHON; DROP TABLE t1; + +MDEV-15073: Generic UDAF parser code in server for windows functions + +CREATE AGGREGATE FUNCTION avgcost +RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; +CREATE AGGREGATE FUNCTION avg2 +RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; +CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; +create table t1(pk int primary key, +a int, +sum int, +price float(24)); +insert into t1 values +(1, 1, 100, 50.00), +(2, 1, 100, 100.00), +(3, 1, 100, 50.00), +(4, 1, 100, 50.00), +(5, 1, 100, 50.00), +(6, 1, 100, NULL), +(7, 1, NULL, NULL), +(8, 2, 2, 2), +(9, 2, 4, 4); +select pk, a, sum, price, avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +from t1; +pk a sum price avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +1 1 100 50 75.0000 +2 1 100 100 66.6667 +3 1 100 50 66.6667 +4 1 100 50 50.0000 +5 1 100 50 50.0000 +6 1 100 NULL 50.0000 +7 1 NULL NULL 0.0000 +8 2 2 2 3.3333 +9 2 4 4 3.3333 +select pk, a, sum, price, avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +pk a sum price avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +1 1 100 50 50.0000 +2 1 100 100 75.0000 +3 1 100 50 75.0000 +4 1 100 50 50.0000 +5 1 100 50 50.0000 +6 1 100 NULL 50.0000 +7 1 NULL NULL 0.0000 +8 2 2 2 2.0000 +9 2 4 4 3.3333 +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +from t1; +pk a sum price avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +1 1 100 50 0.7500 +2 1 100 100 0.6667 +3 1 100 50 0.6667 +4 1 100 50 0.5000 +5 1 100 50 0.5000 +6 1 100 NULL 0.5000 +7 1 NULL NULL 0.0000 +8 2 2 2 1.0000 +9 2 4 4 1.0000 +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +pk a sum price avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +1 1 100 50 0.5000 +2 1 100 100 0.7500 +3 1 100 50 0.7500 +4 1 100 50 0.5000 +5 1 100 50 0.5000 +6 1 100 NULL 0.5000 +7 1 NULL NULL 0.0000 +8 2 2 2 1.0000 +9 2 4 4 1.0000 +select pk, a, sum, price, tttttttt(sprice,sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from ' at line 1 +select pk, a, sum, price, myfunc_double(sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from ' at line 1 +select pk, a, sum, price, round(sprice,sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from ' at line 1 +select pk, a, sum, price, myfunc_double(sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from ' at line 1 +set @save_sql_mode = @@sql_mode; +set sql_mode="oracle"; +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +pk a sum price avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +1 1 100 50 0.5000 +2 1 100 100 0.7500 +3 1 100 50 0.7500 +4 1 100 50 0.5000 +5 1 100 50 0.5000 +6 1 100 NULL 0.5000 +7 1 NULL NULL 0.0000 +8 2 2 2 1.0000 +9 2 4 4 1.0000 +set sql_mode= @save_sql_mode; +drop table t1; +DROP FUNCTION avgcost; +DROP FUNCTION avg2; +DROP FUNCTION myfunc_double; diff --git a/mysql-test/main/udf.test b/mysql-test/main/udf.test index c3a25c6bcce..43d66dc68e2 100644 --- a/mysql-test/main/udf.test +++ b/mysql-test/main/udf.test @@ -528,3 +528,69 @@ DROP FUNCTION METAPHON; #INSERT INTO t1 (a) VALUES ('Hello'); #SELECT * FROM t1; DROP TABLE t1; + +--echo +--echo MDEV-15073: Generic UDAF parser code in server for windows functions +--echo + +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE AGGREGATE FUNCTION avgcost + RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE AGGREGATE FUNCTION avg2 + RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; +--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB +eval CREATE FUNCTION myfunc_double RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; + +create table t1(pk int primary key, + a int, + sum int, + price float(24)); +insert into t1 values + (1, 1, 100, 50.00), + (2, 1, 100, 100.00), + (3, 1, 100, 50.00), + (4, 1, 100, 50.00), + (5, 1, 100, 50.00), + (6, 1, 100, NULL), + (7, 1, NULL, NULL), + (8, 2, 2, 2), + (9, 2, 4, 4); + +--sorted_result +select pk, a, sum, price, avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +from t1; +--sorted_result +select pk, a, sum, price, avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; + +--sorted_result +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) +from t1; +--sorted_result +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +--error ER_PARSE_ERROR +select pk, a, sum, price, tttttttt(sprice,sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +--error ER_PARSE_ERROR +select pk, a, sum, price, myfunc_double(sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +--error ER_PARSE_ERROR +select pk, a, sum, price, round(sprice,sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +--error ER_PARSE_ERROR +select pk, a, sum, price, myfunc_double(sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; + +set @save_sql_mode = @@sql_mode; +set sql_mode="oracle"; +--sorted_result +select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) +from t1; +set sql_mode= @save_sql_mode; + +drop table t1; +DROP FUNCTION avgcost; +DROP FUNCTION avg2; +DROP FUNCTION myfunc_double; diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result index a41148f2600..f30f2d91123 100644 --- a/mysql-test/main/union.result +++ b/mysql-test/main/union.result @@ -81,7 +81,7 @@ a b 2 b 1 a (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b; -ERROR 42000: Table 't1' from one of the SELECTs cannot be used in global ORDER clause +ERROR 42000: Table 't1' from one of the SELECTs cannot be used in ORDER clause explain extended (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 4 100.00 @@ -494,7 +494,7 @@ drop temporary table t1; create table t1 select a from t1 union select a from t2; ERROR 42S01: Table 't1' already exists select a from t1 union select a from t2 order by t2.a; -ERROR 42000: Table 't2' from one of the SELECTs cannot be used in field list +ERROR 42000: Table 't2' from one of the SELECTs cannot be used in ORDER clause drop table t1,t2; select length(version()) > 1 as `*` UNION select 2; * @@ -564,7 +564,7 @@ explain (select * from t1 where a=1 and b=10) union (select straight_join t1.a,t id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 2 UNION t1 index PRIMARY PRIMARY 4 NULL 4 Using index -2 UNION t2 index PRIMARY PRIMARY 4 NULL 4 Using where; Using index; Using join buffer (flat, BNL join) +2 UNION t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using index NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL explain (select * from t1 where a=1) union (select * from t1 where b=1); id select_type table type possible_keys key key_len ref rows Extra @@ -1532,12 +1532,15 @@ SELECT a FROM (SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY c) AS test; ERROR 42S22: Unknown column 'c' in 'order clause' DROP TABLE t1; (select 1 into @var) union (select 1); -ERROR HY000: Incorrect usage of UNION and INTO +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'into @var) union (select 1)' at line 1 (select 1) union (select 1 into @var); -select @var; -@var -1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'into @var)' at line 1 (select 2) union (select 1 into @var); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'into @var)' at line 1 +(select 1) union (select 1) into @var; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead +(select 2) union (select 1) into @var; ERROR 42000: Result consisted of more than one row CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (10), (20); @@ -1663,8 +1666,20 @@ UNION SELECT a FROM t1 WHERE 0 ) alias; SELECT a FROM t1 UNION SELECT a INTO @v FROM t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FROM t1' at line 1 SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file5' FROM t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FROM t1' at line 1 SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file6' FROM t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FROM t1' at line 1 +SELECT a FROM t1 UNION SELECT a FROM t1 INTO @v ; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead +SELECT a FROM t1 UNION SELECT a FROM t1 INTO OUTFILE 'union.out.file5'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead +SELECT a FROM t1 UNION SELECT a FROM t1 INTO OUTFILE 'union.out.file6'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT a INTO @v FROM t1 UNION SELECT a FROM t1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UNION SELECT a FROM t1' at line 1 SELECT a INTO OUTFILE 'union.out.file7' FROM t1 UNION SELECT a FROM t1; @@ -2019,14 +2034,14 @@ SET @@global.slow_query_log= @old_slow_query_log; CREATE TABLE t1 (a int); CREATE TABLE t2 (b int); CREATE TABLE t3 (c int); -SELECT a FROM t1 UNION SELECT b FROM t2 JOIN (t3) ON ( t2.b = t3.c ); +SELECT a FROM t1 UNION SELECT b FROM t2 JOIN t3 ON ( t2.b = t3.c ); a DROP TABLE t1, t2, t3; CREATE TABLE t1 (pk int NOT NULL); CREATE TABLE t2 (pk int NOT NULL, fk int NOT NULL); -SELECT t1.pk FROM t1 LEFT JOIN (t2) ON (t1.pk = t2.fk) +SELECT t1.pk FROM t1 LEFT JOIN t2 ON (t1.pk = t2.fk) UNION -SELECT t1.pk FROM t1 LEFT JOIN (t2) ON (t1.pk = t2.fk); +SELECT t1.pk FROM t1 LEFT JOIN t2 ON (t1.pk = t2.fk); pk DROP TABLE t1,t2; create table t1 (a int); diff --git a/mysql-test/main/union.test b/mysql-test/main/union.test index 878d7118ef5..ca14731600e 100644 --- a/mysql-test/main/union.test +++ b/mysql-test/main/union.test @@ -973,13 +973,17 @@ DROP TABLE t1; # # Bug#23345: Wrongly allowed INTO in a non-last select of a UNION. +# (fixed) # ---error 1221 +--error ER_PARSE_ERROR (select 1 into @var) union (select 1); +--error ER_PARSE_ERROR (select 1) union (select 1 into @var); -select @var; ---error 1172 +--error ER_PARSE_ERROR (select 2) union (select 1 into @var); +(select 1) union (select 1) into @var; +--error ER_TOO_MANY_ROWS +(select 2) union (select 1) into @var; # # Bug#27848: order-by of union clashes with rollup of select part @@ -1099,9 +1103,15 @@ SELECT a INTO DUMPFILE 'union.out.file2' FROM ( SELECT a FROM t1 WHERE 0 ) alias; +--error ER_PARSE_ERROR SELECT a FROM t1 UNION SELECT a INTO @v FROM t1; +--error ER_PARSE_ERROR SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file5' FROM t1; +--error ER_PARSE_ERROR SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file6' FROM t1; +SELECT a FROM t1 UNION SELECT a FROM t1 INTO @v ; +SELECT a FROM t1 UNION SELECT a FROM t1 INTO OUTFILE 'union.out.file5'; +SELECT a FROM t1 UNION SELECT a FROM t1 INTO OUTFILE 'union.out.file6'; --error ER_PARSE_ERROR SELECT a INTO @v FROM t1 UNION SELECT a FROM t1; --error ER_PARSE_ERROR @@ -1361,15 +1371,15 @@ SET @@global.slow_query_log= @old_slow_query_log; CREATE TABLE t1 (a int); CREATE TABLE t2 (b int); CREATE TABLE t3 (c int); -SELECT a FROM t1 UNION SELECT b FROM t2 JOIN (t3) ON ( t2.b = t3.c ); +SELECT a FROM t1 UNION SELECT b FROM t2 JOIN t3 ON ( t2.b = t3.c ); DROP TABLE t1, t2, t3; CREATE TABLE t1 (pk int NOT NULL); CREATE TABLE t2 (pk int NOT NULL, fk int NOT NULL); -SELECT t1.pk FROM t1 LEFT JOIN (t2) ON (t1.pk = t2.fk) +SELECT t1.pk FROM t1 LEFT JOIN t2 ON (t1.pk = t2.fk) UNION -SELECT t1.pk FROM t1 LEFT JOIN (t2) ON (t1.pk = t2.fk); +SELECT t1.pk FROM t1 LEFT JOIN t2 ON (t1.pk = t2.fk); DROP TABLE t1,t2; diff --git a/mysql-test/main/update.result b/mysql-test/main/update.result index 73ebb73e313..ab6596e8bf1 100644 --- a/mysql-test/main/update.result +++ b/mysql-test/main/update.result @@ -234,7 +234,9 @@ insert into t2 values ( 1, 'abcd1e'); insert into t2 values ( 2, 'abcd2e'); analyze table t1,t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK update t1, t2 set t1.a = t2.a where t2.b = t1.b; show warnings; @@ -326,7 +328,7 @@ delete from t1 order by a limit 1; show status like 'handler_read%'; Variable_name Value Handler_read_first 0 -Handler_read_key 0 +Handler_read_key 4 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 @@ -447,7 +449,7 @@ UPDATE t1 SET user_id=null WHERE request_id=9999999999999; show status like '%Handler_read%'; Variable_name Value Handler_read_first 0 -Handler_read_key 3 +Handler_read_key 2 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 @@ -459,7 +461,7 @@ UPDATE t1 SET user_id=null WHERE request_id=999999999999999999999999999999; show status like '%Handler_read%'; Variable_name Value Handler_read_first 0 -Handler_read_key 3 +Handler_read_key 2 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 diff --git a/mysql-test/main/update_innodb.result b/mysql-test/main/update_innodb.result index 0a85c6dab3e..3ef61cd88c2 100644 --- a/mysql-test/main/update_innodb.result +++ b/mysql-test/main/update_innodb.result @@ -65,3 +65,57 @@ SELECT * FROM t1; a_id b_id c_id 1 NULL NULL drop table t1,t2; +CREATE OR REPLACE TABLE t1 (a INT NOT NULL PRIMARY KEY) engine=innodb; +CREATE OR REPLACE TABLE t2 (a INT NOT NULL PRIMARY KEY) engine=innodb; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +BEGIN; +SELECT * FROM t1 UNION +SELECT * FROM t2 FOR UPDATE; +a +1 +2 +connect con2,localhost,root,,; +BEGIN; +SELECT * FROM t2 FOR UPDATE;; +connection default; +select * from t2; +a +2 +update t2 set a=a+100; +commit; +connection con2; +a +102 +commit; +connection default; +drop table t1,t2; +CREATE OR REPLACE TABLE t1 (a INT NOT NULL PRIMARY KEY) engine=innodb; +CREATE OR REPLACE TABLE t2 (a INT NOT NULL PRIMARY KEY) engine=innodb; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +BEGIN; +SELECT * FROM ( +SELECT * FROM t1 UNION +SELECT * FROM t2 FOR UPDATE +) t; +a +1 +2 +connection con2; +BEGIN; +SELECT * FROM t2 FOR UPDATE;; +connection default; +select * from t2; +a +2 +update t2 set a=a+100; +commit; +connection con2; +a +102 +commit; +connection default; +disconnect con2; +drop table t1,t2; +# End of 10.4 tests diff --git a/mysql-test/main/update_innodb.test b/mysql-test/main/update_innodb.test index acc8aceab00..01b2724191e 100644 --- a/mysql-test/main/update_innodb.test +++ b/mysql-test/main/update_innodb.test @@ -75,3 +75,62 @@ SELECT t2.b_id FROM t1,t2 WHERE t2.c_id = t1.c_id; UPDATE t1 SET b_id = (SELECT t2.b_id FROM t2 t2 WHERE t2.c_id = t1.c_id); SELECT * FROM t1; drop table t1,t2; + + +--source include/have_innodb.inc + +CREATE OR REPLACE TABLE t1 (a INT NOT NULL PRIMARY KEY) engine=innodb; +CREATE OR REPLACE TABLE t2 (a INT NOT NULL PRIMARY KEY) engine=innodb; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +BEGIN; +SELECT * FROM t1 UNION +SELECT * FROM t2 FOR UPDATE; + +--connect(con2,localhost,root,,) +BEGIN; +--send SELECT * FROM t2 FOR UPDATE; +--connection default + +select * from t2; +update t2 set a=a+100; +commit; + +--connection con2 +--reap + +commit; + +--connection default +drop table t1,t2; + + +CREATE OR REPLACE TABLE t1 (a INT NOT NULL PRIMARY KEY) engine=innodb; +CREATE OR REPLACE TABLE t2 (a INT NOT NULL PRIMARY KEY) engine=innodb; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2); +BEGIN; +SELECT * FROM ( + SELECT * FROM t1 UNION + SELECT * FROM t2 FOR UPDATE + ) t; + +--connection con2 +BEGIN; +--send SELECT * FROM t2 FOR UPDATE; +--connection default + +select * from t2; +update t2 set a=a+100; +commit; + +--connection con2 +--reap + +commit; + +--connection default +disconnect con2; +drop table t1,t2; + +--echo # End of 10.4 tests diff --git a/mysql-test/main/update_use_source.result b/mysql-test/main/update_use_source.result index e5585fcee5d..9e43b54d81c 100644 --- a/mysql-test/main/update_use_source.result +++ b/mysql-test/main/update_use_source.result @@ -1177,6 +1177,7 @@ insert t1 (c1,c2,c3) select 3,seq,seq%10 from seq_1_to_200; create index t1_idx1 on t1(c3); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date update t1 set c1=2 where exists (select 'x' from t1); select count(*) from t1 where c1=2; diff --git a/mysql-test/main/userstat.result b/mysql-test/main/userstat.result index 1db891e0184..0067149691a 100644 --- a/mysql-test/main/userstat.result +++ b/mysql-test/main/userstat.result @@ -1,5 +1,7 @@ DROP TABLE IF EXISTS t1; select variable_value from information_schema.global_status where variable_name="handler_read_key" into @global_read_key; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead show columns from information_schema.client_statistics; Field Type Null Key Default Extra CLIENT varchar(64) NO @@ -117,7 +119,7 @@ Handler_mrr_key_refills 0 Handler_mrr_rowid_refills 0 Handler_prepare 18 Handler_read_first 0 -Handler_read_key 9 +Handler_read_key 17 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 @@ -135,7 +137,7 @@ Handler_update 5 Handler_write 7 select variable_value - @global_read_key as "handler_read_key" from information_schema.global_status where variable_name="handler_read_key"; handler_read_key -9 +17 disconnect ssl_con; set @@global.userstat=0; select * from information_schema.index_statistics; diff --git a/mysql-test/main/varbinary.result b/mysql-test/main/varbinary.result index 58cab5ad1ca..3a182e74692 100644 --- a/mysql-test/main/varbinary.result +++ b/mysql-test/main/varbinary.result @@ -82,8 +82,8 @@ drop table t1; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` varbinary(255) DEFAULT NULL, - `b` varchar(255) DEFAULT NULL + `a` varbinary(255)/*old*/ DEFAULT NULL, + `b` varchar(255)/*old*/ DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select length(a), length(b) from t1; length(a) length(b) diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result index 2bc82f90e46..317f02cadaa 100644 --- a/mysql-test/main/view.result +++ b/mysql-test/main/view.result @@ -615,6 +615,7 @@ select is_updatable from information_schema.views; is_updatable YES YES +YES select * from t1; col1 col2 5 Hello, view world @@ -2443,6 +2444,8 @@ SELECT Meaning FROM v1 INTO retn; RETURN retn; END // +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE VIEW v2 AS SELECT f1(); select * from v2; f1() @@ -2614,6 +2617,8 @@ declare mx int; select max(a) from t1 into mx; return mx; end// +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create view v1 as select f1() as a; create view v2 as select * from v1; drop table t1; @@ -3152,10 +3157,14 @@ DROP VIEW v1; DROP TABLE t1; DROP VIEW IF EXISTS v1; SELECT * FROM (SELECT 1) AS t into @w; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE VIEW v1 AS SELECT * FROM (SELECT 1) AS t into @w; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'into @w' at line 1 # Previously the following would fail. SELECT * FROM (SELECT 1) AS t into @w; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead drop view if exists view_24532_a; drop view if exists view_24532_b; drop table if exists table_24532; @@ -3952,6 +3961,8 @@ BEGIN SELECT a FROM v2 INTO @a; RETURN @a; END// +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Trigger pre-locking when opening v2. CREATE VIEW v1 AS SELECT f1() FROM t1; SHOW CREATE VIEW v1; @@ -4093,7 +4104,7 @@ LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 ; SELECT 1 -FROM (( SELECT 1 +FROM ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4101,8 +4112,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t1) -LEFT OUTER JOIN (( SELECT 1 +) t1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4110,8 +4121,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t2) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t2 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4119,8 +4130,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t3) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t3 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4128,8 +4139,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t4) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t4 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4137,8 +4148,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t5) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t5 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4146,8 +4157,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t6) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t6 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4155,8 +4166,8 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t7) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t7 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4164,18 +4175,18 @@ LEFT JOIN t4 d_alias_1 ON d_alias_1.d1 = a_alias_1.a1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t8) ON 1=1 +) t8 ON 1=1 ; 1 SELECT 1 -FROM (v1 t1) -LEFT OUTER JOIN (v1 t2) ON 1=1 -LEFT OUTER JOIN (v1 t3) ON 1=1 -LEFT OUTER JOIN (v1 t4) ON 1=1 -LEFT OUTER JOIN (v1 t5) ON 1=1 -LEFT OUTER JOIN (v1 t6) ON 1=1 -LEFT OUTER JOIN (v1 t7) ON 1=1 -LEFT OUTER JOIN (v1 t8) ON 1=1 +FROM v1 t1 +LEFT OUTER JOIN v1 t2 ON 1=1 +LEFT OUTER JOIN v1 t3 ON 1=1 +LEFT OUTER JOIN v1 t4 ON 1=1 +LEFT OUTER JOIN v1 t5 ON 1=1 +LEFT OUTER JOIN v1 t6 ON 1=1 +LEFT OUTER JOIN v1 t7 ON 1=1 +LEFT OUTER JOIN v1 t8 ON 1=1 ; 1 drop view v1; diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test index 82ef38f0eb6..658cd09ae6f 100644 --- a/mysql-test/main/view.test +++ b/mysql-test/main/view.test @@ -4042,7 +4042,7 @@ CREATE OR REPLACE view v1 AS ; SELECT 1 -FROM (( SELECT 1 +FROM ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4050,8 +4050,8 @@ FROM (( SELECT 1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t1) -LEFT OUTER JOIN (( SELECT 1 +) t1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4059,8 +4059,8 @@ LEFT OUTER JOIN (( SELECT 1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t2) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t2 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4068,8 +4068,8 @@ LEFT OUTER JOIN (( SELECT 1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t3) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t3 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4077,8 +4077,8 @@ LEFT OUTER JOIN (( SELECT 1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t4) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t4 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4086,8 +4086,8 @@ LEFT OUTER JOIN (( SELECT 1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t5) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t5 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4095,8 +4095,8 @@ LEFT OUTER JOIN (( SELECT 1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t6) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t6 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4104,8 +4104,8 @@ LEFT OUTER JOIN (( SELECT 1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t7) ON 1=1 -LEFT OUTER JOIN (( SELECT 1 +) t7 ON 1=1 +LEFT OUTER JOIN ( SELECT 1 FROM t1 a_alias_1 LEFT JOIN (t2 b_alias_1 JOIN t1 a_alias_2) ON b_alias_1.b1 = a_alias_1.a1 AND a_alias_2.a1 = a_alias_1.a1 LEFT JOIN t3 c_alias_1 ON c_alias_1.c1 = a_alias_1.a1 @@ -4113,18 +4113,18 @@ LEFT OUTER JOIN (( SELECT 1 LEFT JOIN t3 c_alias_2 ON c_alias_2.c1 = a_alias_1.a1 LEFT JOIN t5 e_alias_1 ON e_alias_1.e1 = a_alias_1.a1 LEFT JOIN t6 f_alias_1 ON f_alias_1.f1 = a_alias_1.a1 -) t8) ON 1=1 +) t8 ON 1=1 ; SELECT 1 -FROM (v1 t1) -LEFT OUTER JOIN (v1 t2) ON 1=1 -LEFT OUTER JOIN (v1 t3) ON 1=1 -LEFT OUTER JOIN (v1 t4) ON 1=1 -LEFT OUTER JOIN (v1 t5) ON 1=1 -LEFT OUTER JOIN (v1 t6) ON 1=1 -LEFT OUTER JOIN (v1 t7) ON 1=1 -LEFT OUTER JOIN (v1 t8) ON 1=1 +FROM v1 t1 +LEFT OUTER JOIN v1 t2 ON 1=1 +LEFT OUTER JOIN v1 t3 ON 1=1 +LEFT OUTER JOIN v1 t4 ON 1=1 +LEFT OUTER JOIN v1 t5 ON 1=1 +LEFT OUTER JOIN v1 t6 ON 1=1 +LEFT OUTER JOIN v1 t7 ON 1=1 +LEFT OUTER JOIN v1 t8 ON 1=1 ; drop view v1; diff --git a/mysql-test/main/view_grant.result b/mysql-test/main/view_grant.result index 82594128d85..df1429eaa4d 100644 --- a/mysql-test/main/view_grant.result +++ b/mysql-test/main/view_grant.result @@ -406,6 +406,8 @@ create table t2 (s1 int); drop function if exists f2; create function f2 () returns int begin declare v int; select s1 from t2 into v; return v; end// +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create algorithm=TEMPTABLE view v1 as select f2() from t1; create algorithm=MERGE view v2 as select f2() from t1; create algorithm=TEMPTABLE SQL SECURITY INVOKER view v3 as select f2() from t1; @@ -449,6 +451,8 @@ create table t2 (s1 int); drop function if exists f2; create function f2 () returns int begin declare v int; select s1 from t2 into v; return v; end// +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create user mysqltest_1@localhost; grant select on t1 to mysqltest_1@localhost; grant execute on function f2 to mysqltest_1@localhost; @@ -558,11 +562,6 @@ use test; REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; drop user mysqltest_1@localhost; drop database mysqltest; -drop view if exists v1; -drop table if exists t1; -create table t1 as select * from mysql.user where user=''; -delete from mysql.user where user=''; -flush privileges; create user 'test14256'@'%'; grant all on test.* to 'test14256'@'%'; connect test14256,localhost,test14256,,test; @@ -588,9 +587,6 @@ test14256@% test14256@% 1 connection root; disconnect test14256; drop user test14256; -insert into mysql.user select * from t1; -flush privileges; -drop table t1; connection root; create database mysqltest; use mysqltest; diff --git a/mysql-test/main/view_grant.test b/mysql-test/main/view_grant.test index a70241138aa..65757e95fb3 100644 --- a/mysql-test/main/view_grant.test +++ b/mysql-test/main/view_grant.test @@ -669,16 +669,6 @@ drop database mysqltest; # # Bug#14256 definer in view definition is not fully qualified # ---disable_warnings -drop view if exists v1; -drop table if exists t1; ---enable_warnings - -# Backup anonymous users and remove them. (They get in the way of -# the one we test with here otherwise.) -create table t1 as select * from mysql.user where user=''; -delete from mysql.user where user=''; -flush privileges; # Create the test user create user 'test14256'@'%'; @@ -708,12 +698,6 @@ connection root; disconnect test14256; drop user test14256; -# Restore the anonymous users. -insert into mysql.user select * from t1; -flush privileges; - -drop table t1; - # # Bug#14726 freeing stack variable in case of an error of opening a view when # we have locked tables with LOCK TABLES statement. diff --git a/mysql-test/main/win.result b/mysql-test/main/win.result index 6ee6f01ba8d..ce8c1311222 100644 --- a/mysql-test/main/win.result +++ b/mysql-test/main/win.result @@ -3490,3 +3490,14 @@ d x 00:00:01 00:00:02 00:00:02 NULL DROP TABLE t1; +# +# MDEV-16722: Assertion `type() != NULL_ITEM' failed +# +create table t1 (a int); +insert into t1 values (1),(2),(3); +SELECT row_number() OVER (order by a) FROM t1 order by NAME_CONST('myname',NULL); +row_number() OVER (order by a) +1 +2 +3 +drop table t1; diff --git a/mysql-test/main/win.test b/mysql-test/main/win.test index 1b49ac681f4..0254667579a 100644 --- a/mysql-test/main/win.test +++ b/mysql-test/main/win.test @@ -2245,3 +2245,12 @@ CREATE TABLE t1 (d time); INSERT INTO t1 VALUES ('00:00:01'),('00:00:02'); SELECT *, LEAD(d) OVER (ORDER BY d) AS x FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-16722: Assertion `type() != NULL_ITEM' failed +--echo # + +create table t1 (a int); +insert into t1 values (1),(2),(3); +SELECT row_number() OVER (order by a) FROM t1 order by NAME_CONST('myname',NULL); +drop table t1; diff --git a/mysql-test/main/win_big-mdev-11697.result b/mysql-test/main/win_big-mdev-11697.result index e5dc271839c..ec9d2243c88 100644 --- a/mysql-test/main/win_big-mdev-11697.result +++ b/mysql-test/main/win_big-mdev-11697.result @@ -12,6 +12,7 @@ select * from data_generator commit; analyze table test_table; Table Op Msg_type Msg_text +test.test_table analyze status Engine-independent statistics collected test.test_table analyze status OK explain select * from (select id, lead(id) over(order by id) next_id from test_table order by id) a limit 10; id select_type table type possible_keys key key_len ref rows Extra @@ -44,6 +45,7 @@ select * from data_generator commit; analyze table test_table; Table Op Msg_type Msg_text +test.test_table analyze status Engine-independent statistics collected test.test_table analyze status OK explain select * from (select id, lead(id) over(order by id) next_id from test_table order by id) a limit 10; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 349cba26b75..b5b8a92f1ec 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -102,6 +102,7 @@ use mtr_unique; use mtr_results; use IO::Socket::INET; use IO::Select; +use Time::HiRes qw(gettimeofday); require "mtr_process.pl"; require "mtr_io.pl"; @@ -2292,6 +2293,10 @@ sub environment_setup { $ENV{'EXE_MYSQL'}= $exe_mysql; $ENV{'MYSQL_PLUGIN'}= $exe_mysql_plugin; $ENV{'MYSQL_EMBEDDED'}= $exe_mysql_embedded; + if(IS_WINDOWS) + { + $ENV{'MYSQL_INSTALL_DB_EXE'}= mtr_exe_exists("$bindir/sql$opt_vs_config/mysql_install_db"); + } my $client_config_exe= mtr_exe_maybe_exists( @@ -2603,8 +2608,22 @@ sub setup_vardir() { unlink "$plugindir/symlink_test"; } + for (<$bindir/plugin/auth_pam/auth_pam_tool>) + { + mkpath("$plugindir/auth_pam_tool_dir"); + if ($opt_use_copy) + { + copy rel2abs($_), "$plugindir/auth_pam_tool_dir/auth_pam_tool" + } + else + { + symlink rel2abs($_), "$plugindir/auth_pam_tool_dir/auth_pam_tool"; + } + } + for (<$bindir/storage/*/*.so>, <$bindir/plugin/*/*.so>, + <$bindir/plugin/*/auth_pam_tool_dir>, <$bindir/libmariadb/plugins/*/*.so>, <$bindir/libmariadb/*.so>, <$bindir/sql/*.so>) @@ -3226,8 +3245,8 @@ sub mysql_install_db { $bootstrap_sql_file); # mysql.gtid_slave_pos was created in InnoDB, but many tests - # run without InnoDB. Alter it to MyISAM now - mtr_tofile($bootstrap_sql_file, "ALTER TABLE gtid_slave_pos ENGINE=MyISAM;\n"); + # run without InnoDB. Alter it to Aria now + mtr_tofile($bootstrap_sql_file, "ALTER TABLE gtid_slave_pos ENGINE=Aria transactional=0;\n"); } else { @@ -3244,7 +3263,7 @@ sub mysql_install_db { # Remove anonymous users mtr_tofile($bootstrap_sql_file, - "DELETE FROM mysql.user where user= '';\n"); + "DELETE FROM mysql.global_priv where user= '';\n"); # Create mtr database mtr_tofile($bootstrap_sql_file, @@ -3267,6 +3286,7 @@ sub mysql_install_db { # Create directories mysql and test mkpath("$install_datadir/mysql"); + my $realtime= gettimeofday(); if ( My::SafeProcess->run ( name => "bootstrap", @@ -3284,6 +3304,10 @@ sub mysql_install_db { "Could not install system database from $bootstrap_sql_file\n" . "The $path_bootstrap_log file contains:\n$data\n"); } + else + { + mtr_verbose("Spent " . sprintf("%.3f", (gettimeofday() - $realtime)) . " seconds in bootstrap"); + } } @@ -4467,6 +4491,7 @@ sub extract_warning_lines ($$) { qr|Access denied for user|, qr|Aborted connection|, qr|table.*is full|, + qr|\[ERROR\] mysqld: \Z|, # Warning from Aria recovery qr|Linux Native AIO|, # warning that aio does not work on /dev/shm qr|InnoDB: io_setup\(\) attempt|, qr|InnoDB: io_setup\(\) failed with EAGAIN|, diff --git a/mysql-test/std_data/rpl/mysql-5.7.11-stm-temporal-round-binlog.000001 b/mysql-test/std_data/rpl/mysql-5.7.11-stm-temporal-round-binlog.000001 Binary files differnew file mode 100644 index 00000000000..5010e164e43 --- /dev/null +++ b/mysql-test/std_data/rpl/mysql-5.7.11-stm-temporal-round-binlog.000001 diff --git a/mysql-test/std_data/rpl/mysql-8.0.13-stm-temporal-round-binlog.000001 b/mysql-test/std_data/rpl/mysql-8.0.13-stm-temporal-round-binlog.000001 Binary files differnew file mode 100644 index 00000000000..4d582fdf5bb --- /dev/null +++ b/mysql-test/std_data/rpl/mysql-8.0.13-stm-temporal-round-binlog.000001 diff --git a/mysql-test/std_data/server-new-cert.pem b/mysql-test/std_data/server-new-cert.pem new file mode 100644 index 00000000000..d780cebf68f --- /dev/null +++ b/mysql-test/std_data/server-new-cert.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7 (0x7) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=cacert, C=FI, ST=Helsinki, L=Helsinki, O=MariaDB + Validity + Not Before: Dec 11 17:13:59 2018 GMT + Not After : Dec 7 17:13:59 2038 GMT + Subject: C=FI, ST=Helsinki, L=Helsinki, O=MariaDB, CN=server-new + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (1024 bit) + Modulus: + 00:c9:40:33:d7:fb:b7:a2:bc:4e:d4:65:27:1a:c9: + da:8b:2e:fc:a9:60:1a:69:e8:fd:e3:13:78:b6:08: + 3b:3e:fd:d3:b0:d3:6c:a1:79:bd:85:ca:be:a1:0a: + 4e:2a:ee:2c:8d:da:72:e6:85:56:ec:3a:7c:46:a3: + d3:18:e7:19:19:8d:14:7e:de:d2:a4:2f:22:56:1c: + 21:03:24:f6:2d:55:4e:49:25:9f:32:01:94:66:47: + e4:fa:fa:45:b1:b7:33:26:da:f1:c7:29:3b:ba:fe: + e8:d4:f1:fc:29:57:6b:3a:be:ef:2e:1d:da:ef:0a: + d7:54:8d:67:00:7b:7a:29:2b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + FF:42:5E:88:AC:6A:C8:80:63:A8:AF:20:C6:BE:E8:A4:02:D5:42:AF + X509v3 Authority Key Identifier: + keyid:1C:C7:2B:AA:1B:B1:BB:2E:9A:F4:0F:B1:86:60:57:38:C2:41:05:12 + + Signature Algorithm: sha256WithRSAEncryption + 7c:cc:c1:93:43:83:a9:ea:19:9d:1c:a1:f8:e1:c1:61:58:c0: + db:ef:43:6e:d7:cf:4d:75:38:6e:cb:03:25:5d:21:af:03:b1: + 86:5f:b3:d1:e2:6f:8c:89:55:b7:82:6a:c0:d6:46:08:0c:68: + 9d:ef:cc:2e:79:f5:d8:0b:f2:13:3a:52:cc:08:d5:3a:f0:d8: + 5c:9e:85:a7:38:31:9d:7c:61:2b:59:ee:c0:16:a6:16:dd:80: + e2:ef:96:3d:b0:13:ec:9b:9a:91:69:3f:6c:46:87:05:55:b7: + 32:85:51:da:02:c3:ac:2d:c3:5e:9a:51:f8:96:75:0b:63:29: + 4e:47:47:f1:82:a6:ad:44:3d:51:b3:19:8b:ae:26:a9:15:a0: + 73:b6:70:6e:4f:72:9d:69:4e:b2:9b:2a:a8:50:87:b8:9f:c0: + a7:37:0f:9e:bc:4c:80:b9:b8:47:28:8e:33:c3:7f:d7:fe:31: + f0:a9:1c:7a:f7:a3:34:21:d4:e4:53:86:a3:7e:1d:1c:a7:65: + fb:ec:f9:1f:17:1e:4f:19:f9:fe:dd:ee:53:0f:b5:98:b7:7a: + ef:12:6c:8d:32:78:66:a5:42:d7:3d:a5:09:f8:06:05:a4:ff: + bd:4e:e7:85:c4:f0:dc:dc:20:26:84:91:69:e8:cf:3b:27:9f: + 35:36:cc:ff +-----BEGIN CERTIFICATE----- +MIIDIjCCAgqgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQ8wDQYDVQQDDAZjYWNl +cnQxCzAJBgNVBAYTAkZJMREwDwYDVQQIDAhIZWxzaW5raTERMA8GA1UEBwwISGVs +c2lua2kxEDAOBgNVBAoMB01hcmlhREIwHhcNMTgxMjExMTcxMzU5WhcNMzgxMjA3 +MTcxMzU5WjBaMQswCQYDVQQGEwJGSTERMA8GA1UECAwISGVsc2lua2kxETAPBgNV +BAcMCEhlbHNpbmtpMRAwDgYDVQQKDAdNYXJpYURCMRMwEQYDVQQDDApzZXJ2ZXIt +bmV3MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJQDPX+7eivE7UZScaydqL +LvypYBpp6P3jE3i2CDs+/dOw02yheb2Fyr6hCk4q7iyN2nLmhVbsOnxGo9MY5xkZ +jRR+3tKkLyJWHCEDJPYtVU5JJZ8yAZRmR+T6+kWxtzMm2vHHKTu6/ujU8fwpV2s6 +vu8uHdrvCtdUjWcAe3opKwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIB +DQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU/0Je +iKxqyIBjqK8gxr7opALVQq8wHwYDVR0jBBgwFoAUHMcrqhuxuy6a9A+xhmBXOMJB +BRIwDQYJKoZIhvcNAQELBQADggEBAHzMwZNDg6nqGZ0cofjhwWFYwNvvQ27Xz011 +OG7LAyVdIa8DsYZfs9Hib4yJVbeCasDWRggMaJ3vzC559dgL8hM6UswI1Trw2Fye +hac4MZ18YStZ7sAWphbdgOLvlj2wE+ybmpFpP2xGhwVVtzKFUdoCw6wtw16aUfiW +dQtjKU5HR/GCpq1EPVGzGYuuJqkVoHO2cG5Pcp1pTrKbKqhQh7ifwKc3D568TIC5 +uEcojjPDf9f+MfCpHHr3ozQh1ORThqN+HRynZfvs+R8XHk8Z+f7d7lMPtZi3eu8S +bI0yeGalQtc9pQn4BgWk/71O54XE8NzcICaEkWnozzsnnzU2zP8= +-----END CERTIFICATE----- diff --git a/mysql-test/std_data/server-new-key.pem b/mysql-test/std_data/server-new-key.pem new file mode 100644 index 00000000000..093666d5c1b --- /dev/null +++ b/mysql-test/std_data/server-new-key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDJQDPX+7eivE7UZScaydqLLvypYBpp6P3jE3i2CDs+/dOw02yh +eb2Fyr6hCk4q7iyN2nLmhVbsOnxGo9MY5xkZjRR+3tKkLyJWHCEDJPYtVU5JJZ8y +AZRmR+T6+kWxtzMm2vHHKTu6/ujU8fwpV2s6vu8uHdrvCtdUjWcAe3opKwIDAQAB +AoGBAKlH3dPxIdg6+TvjEe+Qlsm4bkKyWcV4fAaDnGfRqLQloej9DkUNOAPQNGUV +XAb0bHmtpDSPODxgPaTVrH0n9o1tTXrfIijSM7zm0Ub2H7YPMNMUSae+9K3bdXoL +aHjlYYXBXULa093nXOXNmjX17pBKUmiAkKCoqxTMx9QGW8rRAkEA/aqjdIrbaEJd +Mky4bLzaSZITls/8+LPekUpH+TXdjgSMMaDxd4OXAnA34fssPOhsD8yzgeo2XZZj +Snk4wfBHrwJBAMsaITNwvAXj3joX/eTD4Q/FcwdaPt4dL2BS13uJrva/TZGEAnOn +n5nu2exZDslxyoKA5SBl2oZbhtCAA1elWUUCQQCeo8rZpcWVrHtQa76i8nCpthte +I/EXMJYu0v+0EUXf/WQX3YllrvwP4FJyl3yREuIR93kD9I/Pc6/g8XLXhwetAkB1 +VG8BrIqyTGVA4kNGOPJ3jfVZtgTDg9CusKzTLULqQLGq8rwH3DoTTyyNoRUtwpLe +uV+kS7LmE1HaeVl09IyRAkBXb/5p2D+Dfb/3/mx5/YuFNwB07sY+H0CrzO1qSo62 +q0nzNK3/irTzqtuerwy/YkBTz/T75GePIK4P0b9elNlb +-----END RSA PRIVATE KEY----- diff --git a/mysql-test/suite/archive/disabled.def b/mysql-test/suite/archive/disabled.def new file mode 100644 index 00000000000..ae841eaaf33 --- /dev/null +++ b/mysql-test/suite/archive/disabled.def @@ -0,0 +1,13 @@ +############################################################################## +# +# List the test cases that are to be disabled temporarily. +# +# Separate the test case name and the comment with ':'. +# +# <testcasename> : BUG#<xxxx> <date disabled> <disabler> <comment> +# +# Do not use any TAB characters for whitespace. +# +############################################################################## + +archive_gis : MDEV-17297 wait for the fix and then enable it diff --git a/mysql-test/suite/archive/flush.result b/mysql-test/suite/archive/flush.result new file mode 100644 index 00000000000..428f32d09f8 --- /dev/null +++ b/mysql-test/suite/archive/flush.result @@ -0,0 +1,18 @@ +CREATE TABLE t1(a INT) ENGINE=archive; +INSERT INTO t1 VALUES(1); +connect con1, localhost, root; +LOCK TABLE t1 READ; +connection default; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +# Must return 1 row +SELECT * FROM t2; +a +1 +SELECT * FROM t1; +a +1 +connection con1; +UNLOCK TABLES; +connection default; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/archive/flush.test b/mysql-test/suite/archive/flush.test new file mode 100644 index 00000000000..feadef08d7a --- /dev/null +++ b/mysql-test/suite/archive/flush.test @@ -0,0 +1,25 @@ +--source include/have_archive.inc + +let $MYSQLD_DATADIR= `SELECT @@datadir`; +CREATE TABLE t1(a INT) ENGINE=archive; +INSERT INTO t1 VALUES(1); +# Works correct if we uncomment next row +#FLUSH TABLE t1; + +connect(con1, localhost, root); +LOCK TABLE t1 READ; + +connection default; +FLUSH TABLES WITH READ LOCK; +copy_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/t2.frm; +copy_file $MYSQLD_DATADIR/test/t1.ARZ $MYSQLD_DATADIR/test/t2.ARZ; +UNLOCK TABLES; +--echo # Must return 1 row +SELECT * FROM t2; +SELECT * FROM t1; + +connection con1; +UNLOCK TABLES; + +connection default; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/archive/rnd_pos.result b/mysql-test/suite/archive/rnd_pos.result new file mode 100644 index 00000000000..b6b6748d53f --- /dev/null +++ b/mysql-test/suite/archive/rnd_pos.result @@ -0,0 +1,56 @@ +create table t1(c1 int not null, c2 double not null, c3 char(255) not null) engine=archive; +insert t1 select seq, seq+0.7, concat('row with c1 = ', seq) from seq_1_to_10; +explain partitions select c1,c3 from t1 order by c2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 10 Using filesort +set max_length_for_sort_data = 4; +explain partitions select c1,c3 from t1 order by c2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 10 Using temporary; Using filesort +flush status; +select c1,c3 from t1 order by c2; +c1 c3 +1 row with c1 = 1 +2 row with c1 = 2 +3 row with c1 = 3 +4 row with c1 = 4 +5 row with c1 = 5 +6 row with c1 = 6 +7 row with c1 = 7 +8 row with c1 = 8 +9 row with c1 = 9 +10 row with c1 = 10 +set max_length_for_sort_data = default; +show status where variable_name like '%tmp%' and value != 0; +Variable_name Value +Created_tmp_tables 1 +Handler_tmp_write 10 +Rows_tmp_read 20 +alter table t1 partition by hash (c1) partitions 3; +explain partitions select c1,c3 from t1 order by c2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2 ALL NULL NULL NULL NULL 10 Using filesort +set max_length_for_sort_data = 4; +explain partitions select c1,c3 from t1 order by c2; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2 ALL NULL NULL NULL NULL 10 Using temporary; Using filesort +flush status; +select c1,c3 from t1 order by c2; +c1 c3 +1 row with c1 = 1 +2 row with c1 = 2 +3 row with c1 = 3 +4 row with c1 = 4 +5 row with c1 = 5 +6 row with c1 = 6 +7 row with c1 = 7 +8 row with c1 = 8 +9 row with c1 = 9 +10 row with c1 = 10 +set max_length_for_sort_data = default; +show status where variable_name like '%tmp%' and value != 0; +Variable_name Value +Created_tmp_tables 1 +Handler_tmp_write 10 +Rows_tmp_read 20 +drop table t1; diff --git a/mysql-test/suite/archive/rnd_pos.test b/mysql-test/suite/archive/rnd_pos.test new file mode 100644 index 00000000000..7a1d78ea003 --- /dev/null +++ b/mysql-test/suite/archive/rnd_pos.test @@ -0,0 +1,27 @@ +# +# MDEV-14500 Support engines without rnd_pos +# +source include/have_archive.inc; +source include/have_sequence.inc; +source include/have_partition.inc; + +create table t1(c1 int not null, c2 double not null, c3 char(255) not null) engine=archive; +insert t1 select seq, seq+0.7, concat('row with c1 = ', seq) from seq_1_to_10; +explain partitions select c1,c3 from t1 order by c2; +set max_length_for_sort_data = 4; +explain partitions select c1,c3 from t1 order by c2; +flush status; +select c1,c3 from t1 order by c2; +set max_length_for_sort_data = default; +show status where variable_name like '%tmp%' and value != 0; + +alter table t1 partition by hash (c1) partitions 3; +explain partitions select c1,c3 from t1 order by c2; +set max_length_for_sort_data = 4; +explain partitions select c1,c3 from t1 order by c2; +flush status; +select c1,c3 from t1 order by c2; +set max_length_for_sort_data = default; +show status where variable_name like '%tmp%' and value != 0; + +drop table t1; diff --git a/mysql-test/suite/binlog/include/binlog.test b/mysql-test/suite/binlog/include/binlog.test index 40befc9d3d1..e5d4efb183b 100644 --- a/mysql-test/suite/binlog/include/binlog.test +++ b/mysql-test/suite/binlog/include/binlog.test @@ -269,12 +269,10 @@ create table if not exists t3 like tt1; # the mysql database is replicated even when the current database is # 'mysql'. ---disable_warnings USE mysql; -INSERT IGNORE INTO user SET host='localhost', user='@#@', password=password('Just a test'); -UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@'; -DELETE FROM user WHERE host='localhost' AND user='@#@'; ---enable_warnings +INSERT db SET host='localhost', user='@#@', db='Just a test'; +UPDATE db SET db='Another db' WHERE host='localhost' AND user='@#@'; +DELETE FROM db WHERE host='localhost' AND user='@#@'; use test; source include/show_binlog_events.inc; diff --git a/mysql-test/suite/binlog/r/binlog_row_binlog.result b/mysql-test/suite/binlog/r/binlog_row_binlog.result index 4068a80771c..2d79de6960a 100644 --- a/mysql-test/suite/binlog/r/binlog_row_binlog.result +++ b/mysql-test/suite/binlog/r/binlog_row_binlog.result @@ -843,9 +843,9 @@ create table if not exists t2 select * from t1; create temporary table tt1 (a int); create table if not exists t3 like tt1; USE mysql; -INSERT IGNORE INTO user SET host='localhost', user='@#@', password=password('Just a test'); -UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@'; -DELETE FROM user WHERE host='localhost' AND user='@#@'; +INSERT db SET host='localhost', user='@#@', db='Just a test'; +UPDATE db SET db='Another db' WHERE host='localhost' AND user='@#@'; +DELETE FROM db WHERE host='localhost' AND user='@#@'; use test; include/show_binlog_events.inc Log_name Pos Event_type Server_id End_log_pos Info @@ -894,18 +894,18 @@ master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t3` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # INSERT IGNORE INTO user SET host='localhost', user='@#@', password=password('Just a test') -master-bin.000001 # Table_map # # table_id: # (mysql.user) +master-bin.000001 # Annotate_rows # # INSERT db SET host='localhost', user='@#@', db='Just a test' +master-bin.000001 # Table_map # # table_id: # (mysql.db) master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@' -master-bin.000001 # Table_map # # table_id: # (mysql.user) +master-bin.000001 # Annotate_rows # # UPDATE db SET db='Another db' WHERE host='localhost' AND user='@#@' +master-bin.000001 # Table_map # # table_id: # (mysql.db) master-bin.000001 # Update_rows_v1 # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Annotate_rows # # DELETE FROM user WHERE host='localhost' AND user='@#@' -master-bin.000001 # Table_map # # table_id: # (mysql.user) +master-bin.000001 # Annotate_rows # # DELETE FROM db WHERE host='localhost' AND user='@#@' +master-bin.000001 # Table_map # # table_id: # (mysql.db) master-bin.000001 # Delete_rows_v1 # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT drop table t1,t2,t3,tt1; diff --git a/mysql-test/suite/binlog/r/binlog_stm_binlog.result b/mysql-test/suite/binlog/r/binlog_stm_binlog.result index 872ba40e05f..ccc3db2ba7e 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_binlog.result +++ b/mysql-test/suite/binlog/r/binlog_stm_binlog.result @@ -1,4 +1,3 @@ -drop table if exists t1; create table t1 (a int, b int) engine=innodb; begin; insert into t1 values (1,2); @@ -6,8 +5,6 @@ commit; include/show_binlog_events.inc Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t1` /* generated by server */ -master-bin.000001 # Gtid # # GTID #-#-# master-bin.000001 # Query # # use `test`; create table t1 (a int, b int) engine=innodb master-bin.000001 # Gtid # # BEGIN GTID #-#-# master-bin.000001 # Query # # use `test`; insert into t1 values (1,2) @@ -451,9 +448,9 @@ create table if not exists t2 select * from t1; create temporary table tt1 (a int); create table if not exists t3 like tt1; USE mysql; -INSERT IGNORE INTO user SET host='localhost', user='@#@', password=password('Just a test'); -UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@'; -DELETE FROM user WHERE host='localhost' AND user='@#@'; +INSERT db SET host='localhost', user='@#@', db='Just a test'; +UPDATE db SET db='Another db' WHERE host='localhost' AND user='@#@'; +DELETE FROM db WHERE host='localhost' AND user='@#@'; use test; include/show_binlog_events.inc Log_name Pos Event_type Server_id End_log_pos Info @@ -501,15 +498,14 @@ master-bin.000001 # Query # # use `test`; create temporary table tt1 (a int) master-bin.000001 # Gtid # # GTID #-#-# master-bin.000001 # Query # # use `test`; create table if not exists t3 like tt1 master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Query # # use `mysql`; INSERT IGNORE INTO user SET host='localhost', user='@#@', password=password('Just a test') +master-bin.000001 # Query # # use `mysql`; INSERT db SET host='localhost', user='@#@', db='Just a test' master-bin.000001 # Query # # COMMIT master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Query # # use `mysql`; UPDATE user SET password=password('Another password') WHERE host='localhost' AND user='@#@' +master-bin.000001 # Query # # use `mysql`; UPDATE db SET db='Another db' WHERE host='localhost' AND user='@#@' master-bin.000001 # Query # # COMMIT master-bin.000001 # Gtid # # BEGIN GTID #-#-# -master-bin.000001 # Query # # use `mysql`; DELETE FROM user WHERE host='localhost' AND user='@#@' +master-bin.000001 # Query # # use `mysql`; DELETE FROM db WHERE host='localhost' AND user='@#@' master-bin.000001 # Query # # COMMIT -master-bin.000001 # Rotate # # master-bin.000002;pos=POS drop table t1,t2,t3,tt1; reset master; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam; diff --git a/mysql-test/suite/binlog/t/binlog_stm_binlog.test b/mysql-test/suite/binlog/t/binlog_stm_binlog.test index c3d8066f807..e9c8e0ed874 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_binlog.test +++ b/mysql-test/suite/binlog/t/binlog_stm_binlog.test @@ -3,10 +3,6 @@ let collation=utf8_unicode_ci; --source include/have_collation.inc ---disable_warnings -drop table if exists t1; ---enable_warnings - # REQUIREMENT # replace_regex should replace output of SHOW BINLOG EVENTS diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel.result b/mysql-test/suite/binlog_encryption/rpl_parallel.result index 20f3facea27..5f78a378829 100644 --- a/mysql-test/suite/binlog_encryption/rpl_parallel.result +++ b/mysql-test/suite/binlog_encryption/rpl_parallel.result @@ -1518,6 +1518,7 @@ SET SESSION debug_dbug="+d,binlog_force_commit_id"; SET @commit_id= 10000; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK INSERT INTO t3 VALUES (120, 0); SET @commit_id= 10001; diff --git a/mysql-test/suite/binlog_encryption/rpl_switch_stm_row_mixed.result b/mysql-test/suite/binlog_encryption/rpl_switch_stm_row_mixed.result index 2f7f1b07cb4..936f604be2e 100644 --- a/mysql-test/suite/binlog_encryption/rpl_switch_stm_row_mixed.result +++ b/mysql-test/suite/binlog_encryption/rpl_switch_stm_row_mixed.result @@ -140,7 +140,7 @@ create table t4 select * from t1 where 3 in (select 1 union select 2 union selec SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3); Warnings: -Warning 1292 Incorrect datetime value: '3' +Warning 1292 Truncated incorrect datetime value: '3' insert ignore into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4); create procedure foo() begin diff --git a/mysql-test/suite/compat/oracle/r/sp-package-innodb.result b/mysql-test/suite/compat/oracle/r/sp-package-innodb.result index 50eb2dc6cd0..0ac357df5da 100644 --- a/mysql-test/suite/compat/oracle/r/sp-package-innodb.result +++ b/mysql-test/suite/compat/oracle/r/sp-package-innodb.result @@ -23,6 +23,8 @@ a:=a+1; INSERT INTO t1 VALUES (a,'pkg1 initialization'); END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL pkg1.p1; SELECT * FROM t1 ORDER BY a; a routine diff --git a/mysql-test/suite/compat/oracle/r/sp-package-mdl.result b/mysql-test/suite/compat/oracle/r/sp-package-mdl.result index 18cc834461c..bb46341f202 100644 --- a/mysql-test/suite/compat/oracle/r/sp-package-mdl.result +++ b/mysql-test/suite/compat/oracle/r/sp-package-mdl.result @@ -61,8 +61,8 @@ TABLE_NAME pkg1.p1 CONN 2 INFO DROP PACKAGE pkg1 STATE Waiting for stored package body metadata lock -LOCK_MODE MDL_INTENTION_EXCLUSIVE -LOCK_TYPE Global read lock +LOCK_MODE MDL_BACKUP_DDL +LOCK_TYPE Backup lock TABLE_NAME CONN 2 INFO DROP PACKAGE pkg1 diff --git a/mysql-test/suite/compat/oracle/r/sp-package.result b/mysql-test/suite/compat/oracle/r/sp-package.result index 9a53b04d4ad..4f0f05b1939 100644 --- a/mysql-test/suite/compat/oracle/r/sp-package.result +++ b/mysql-test/suite/compat/oracle/r/sp-package.result @@ -2028,6 +2028,8 @@ $$ CALL p1.p1(); @a 11 +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1.p1(); @a 12 @@ -2059,6 +2061,8 @@ BEGIN SELECT MAX(a) FROM t1 INTO @a; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1.p1(); @a 11 @@ -2092,6 +2096,8 @@ BEGIN SELECT 1 FROM t1 INTO @a; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1.p1(); ERROR 42S02: Table 'test.t1' doesn't exist SELECT p1.f1(); @@ -2650,6 +2656,9 @@ SELECT * FROM t1 INTO b; SELECT b.a, b.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1.p1; b.a b.b 10 b diff --git a/mysql-test/suite/compat/oracle/r/sp-row.result b/mysql-test/suite/compat/oracle/r/sp-row.result index 72b33768864..218fb5d463a 100644 --- a/mysql-test/suite/compat/oracle/r/sp-row.result +++ b/mysql-test/suite/compat/oracle/r/sp-row.result @@ -2833,6 +2833,8 @@ SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: The used SELECT statements have a different number of columns DROP TABLE t1; @@ -2847,6 +2849,8 @@ SELECT * FROM t1 INTO rec1, rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: Operand should contain 2 column(s) DROP TABLE t1; @@ -2861,6 +2865,8 @@ SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); rec1.a rec1.b 10 b10 @@ -2876,6 +2882,8 @@ SELECT 10,'a','b' FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: The used SELECT statements have a different number of columns DROP TABLE t1; @@ -2890,6 +2898,8 @@ SELECT 10,'a' FROM t1 INTO rec1, rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: Operand should contain 2 column(s) DROP TABLE t1; @@ -2904,6 +2914,8 @@ SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); rec1.a rec1.b 10 b10 @@ -2920,6 +2932,8 @@ SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: The used SELECT statements have a different number of columns DROP TABLE t1; @@ -2935,6 +2949,8 @@ SELECT * FROM t1 INTO rec1, rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); ERROR 21000: Operand should contain 2 column(s) DROP TABLE t1; @@ -2950,6 +2966,8 @@ SELECT * FROM t1 INTO rec1; SELECT rec1.a, rec1.b; END; $$ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL p1(); rec1.a rec1.b 10 b10 diff --git a/mysql-test/suite/compat/oracle/r/sp.result b/mysql-test/suite/compat/oracle/r/sp.result index 8fa49c4092a..6db999b238f 100644 --- a/mysql-test/suite/compat/oracle/r/sp.result +++ b/mysql-test/suite/compat/oracle/r/sp.result @@ -1019,9 +1019,7 @@ LOOP EXIT WHEN unknown_ident IS NULL; END LOOP; END$$ -CALL p1; ERROR 42S22: Unknown column 'unknown_ident' in 'field list' -DROP PROCEDURE p1; CREATE PROCEDURE p1 AS BEGIN @@ -1030,9 +1028,7 @@ LOOP EXIT label WHEN unknown_ident IS NULL; END LOOP; END$$ -CALL p1; ERROR 42S22: Unknown column 'unknown_ident' in 'field list' -DROP PROCEDURE p1; CREATE PROCEDURE p1 AS BEGIN @@ -1040,9 +1036,7 @@ LOOP CONTINUE WHEN unknown_ident IS NULL; END LOOP; END$$ -CALL p1; ERROR 42S22: Unknown column 'unknown_ident' in 'field list' -DROP PROCEDURE p1; CREATE PROCEDURE p1 AS BEGIN @@ -1051,9 +1045,7 @@ LOOP CONTINUE label WHEN unknown_ident IS NULL; END LOOP; END$$ -CALL p1; ERROR 42S22: Unknown column 'unknown_ident' in 'field list' -DROP PROCEDURE p1; # # MDEV-10583 sql_mode=ORACLE: SQL%ROWCOUNT # diff --git a/mysql-test/suite/compat/oracle/t/sp.test b/mysql-test/suite/compat/oracle/t/sp.test index 6020bd95993..96b4cd59fbd 100644 --- a/mysql-test/suite/compat/oracle/t/sp.test +++ b/mysql-test/suite/compat/oracle/t/sp.test @@ -1092,6 +1092,7 @@ DROP FUNCTION f1; --echo # DELIMITER $$; +--error ER_BAD_FIELD_ERROR CREATE PROCEDURE p1 AS BEGIN @@ -1100,12 +1101,10 @@ BEGIN END LOOP; END$$ DELIMITER ;$$ ---error ER_BAD_FIELD_ERROR -CALL p1; -DROP PROCEDURE p1; DELIMITER $$; +--error ER_BAD_FIELD_ERROR CREATE PROCEDURE p1 AS BEGIN @@ -1115,12 +1114,10 @@ BEGIN END LOOP; END$$ DELIMITER ;$$ ---error ER_BAD_FIELD_ERROR -CALL p1; -DROP PROCEDURE p1; DELIMITER $$; +--error ER_BAD_FIELD_ERROR CREATE PROCEDURE p1 AS BEGIN @@ -1129,12 +1126,10 @@ BEGIN END LOOP; END$$ DELIMITER ;$$ ---error ER_BAD_FIELD_ERROR -CALL p1; -DROP PROCEDURE p1; DELIMITER $$; +--error ER_BAD_FIELD_ERROR CREATE PROCEDURE p1 AS BEGIN @@ -1144,9 +1139,6 @@ BEGIN END LOOP; END$$ DELIMITER ;$$ ---error ER_BAD_FIELD_ERROR -CALL p1; -DROP PROCEDURE p1; --echo # --echo # MDEV-10583 sql_mode=ORACLE: SQL%ROWCOUNT diff --git a/mysql-test/suite/csv/flush.result b/mysql-test/suite/csv/flush.result new file mode 100644 index 00000000000..b0b9b21bd0a --- /dev/null +++ b/mysql-test/suite/csv/flush.result @@ -0,0 +1,25 @@ +CREATE TABLE t1(a INT NOT NULL) ENGINE=csv; +INSERT INTO t1 VALUES(1); +connect con1, localhost, root; +LOCK TABLE t1 READ; +connection default; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +# Must return 1 row +SELECT * FROM t2; +a +1 +SELECT * FROM t1; +a +1 +connection con1; +UNLOCK TABLES; +connection default; +INSERT INTO t2 VALUES(2); +INSERT INTO t2 VALUES(2); +SELECT * from t1,t2; +a a +1 1 +1 2 +1 2 +DROP TABLE t1, t2; diff --git a/mysql-test/suite/csv/flush.test b/mysql-test/suite/csv/flush.test new file mode 100644 index 00000000000..934ac26f291 --- /dev/null +++ b/mysql-test/suite/csv/flush.test @@ -0,0 +1,30 @@ +--source include/have_csv.inc + +let $MYSQLD_DATADIR= `SELECT @@datadir`; +CREATE TABLE t1(a INT NOT NULL) ENGINE=csv; +INSERT INTO t1 VALUES(1); +# works correct if uncommented +#FLUSH TABLE t1; + +connect(con1, localhost, root); +LOCK TABLE t1 READ; + +connection default; +FLUSH TABLES WITH READ LOCK; +copy_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/t2.frm; +copy_file $MYSQLD_DATADIR/test/t1.CSV $MYSQLD_DATADIR/test/t2.CSV; +copy_file $MYSQLD_DATADIR/test/t1.CSM $MYSQLD_DATADIR/test/t2.CSM; +UNLOCK TABLES; +--echo # Must return 1 row +SELECT * FROM t2; +SELECT * FROM t1; +connection con1; +UNLOCK TABLES; + +connection default; + +INSERT INTO t2 VALUES(2); +INSERT INTO t2 VALUES(2); +SELECT * from t1,t2; + +DROP TABLE t1, t2; diff --git a/mysql-test/suite/encryption/r/debug_key_management.result b/mysql-test/suite/encryption/r/debug_key_management.result index 02e05b4d221..91ca77f09b2 100644 --- a/mysql-test/suite/encryption/r/debug_key_management.result +++ b/mysql-test/suite/encryption/r/debug_key_management.result @@ -1,3 +1,4 @@ +create table t1(a serial) engine=innoDB; set global innodb_encrypt_tables=ON; show variables like 'innodb_encrypt%'; Variable_name Value @@ -13,5 +14,13 @@ set global debug_key_management_version=10; select count(*) from information_schema.innodb_tablespaces_encryption where current_key_version <> 10; count(*) 0 +SET GLOBAL debug_dbug = '+d,ib_log'; +SET GLOBAL innodb_log_checkpoint_now = 1; +SET GLOBAL innodb_flush_log_at_trx_commit = 1; +INSERT INTO t1 VALUES(NULL); set global innodb_encrypt_tables=OFF; set global debug_key_management_version=1; +select * from t1; +a +1 +drop table t1; diff --git a/mysql-test/suite/encryption/r/innodb-first-page-read.result b/mysql-test/suite/encryption/r/innodb-first-page-read.result deleted file mode 100644 index 29253885e83..00000000000 --- a/mysql-test/suite/encryption/r/innodb-first-page-read.result +++ /dev/null @@ -1,96 +0,0 @@ -FLUSH STATUS; -create database innodb_test; -use innodb_test; -create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; -create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact; -create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic; -create table innodb_compressed(c1 bigint not null, b char(200)) engine=innodb row_format=compressed; -create table innodb_compressed1(c1 bigint not null, b char(200)) engine=innodb row_format=compressed key_block_size=1; -create table innodb_compressed2(c1 bigint not null, b char(200)) engine=innodb row_format=compressed key_block_size=2; -create table innodb_compressed4(c1 bigint not null, b char(200)) engine=innodb row_format=compressed key_block_size=4; -create table innodb_compressed8(c1 bigint not null, b char(200)) engine=innodb row_format=compressed key_block_size=8; -create table innodb_compressed16(c1 bigint not null, b char(200)) engine=innodb row_format=compressed key_block_size=16; -create table innodb_redundant(c1 bigint not null, b char(200)) engine=innodb row_format=redundant; -create table innodb_pagecomp(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes; -create table innodb_pagecomp1(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=1; -create table innodb_pagecomp2(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=2; -create table innodb_pagecomp3(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=3; -create table innodb_pagecomp4(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=4; -create table innodb_pagecomp5(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=5; -create table innodb_pagecomp6(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=6; -create table innodb_pagecomp7(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=7; -create table innodb_pagecomp8(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=8; -create table innodb_pagecomp9(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=9; -create table innodb_datadir1(c1 bigint not null, b char(200)) engine=innodb DATA DIRECTORY='MYSQL_TMP_DIR'; -create table innodb_datadir2(c1 bigint not null, b char(200)) engine=innodb row_format=compressed DATA DIRECTORY='MYSQL_TMP_DIR'; -create table innodb_datadir3(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes DATA DIRECTORY='MYSQL_TMP_DIR'; -begin; -insert into innodb_normal values (1,'secret'); -insert into innodb_compact select * from innodb_normal; -insert into innodb_dynamic select * from innodb_normal; -insert into innodb_compressed select * from innodb_normal; -insert into innodb_compressed1 select * from innodb_normal; -insert into innodb_compressed2 select * from innodb_normal; -insert into innodb_compressed4 select * from innodb_normal; -insert into innodb_compressed8 select * from innodb_normal; -insert into innodb_compressed16 select * from innodb_normal; -insert into innodb_redundant select * from innodb_normal; -insert into innodb_pagecomp select * from innodb_normal; -insert into innodb_pagecomp1 select * from innodb_normal; -insert into innodb_pagecomp2 select * from innodb_normal; -insert into innodb_pagecomp3 select * from innodb_normal; -insert into innodb_pagecomp4 select * from innodb_normal; -insert into innodb_pagecomp5 select * from innodb_normal; -insert into innodb_pagecomp6 select * from innodb_normal; -insert into innodb_pagecomp7 select * from innodb_normal; -insert into innodb_pagecomp8 select * from innodb_normal; -insert into innodb_pagecomp9 select * from innodb_normal; -insert into innodb_datadir1 select * from innodb_normal; -insert into innodb_datadir2 select * from innodb_normal; -insert into innodb_datadir3 select * from innodb_normal; -commit; -FLUSH STATUS; -# Restart server and see how many page 0's are read -# result should actual number of tables except remote tables could be read twice -# i.e. < 23 + 3*2 = 29 -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -VARIABLE_VALUE <= 29 -1 -use innodb_test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -VARIABLE_VALUE <= 29 -1 -use test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -VARIABLE_VALUE <= 29 -1 -set global innodb_encrypt_tables=OFF; -# wait until tables are decrypted -# result should be actual number of tables except remote tables could be read twice -# i.e. < 23 + 3*2 = 29 -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -VARIABLE_VALUE <= 29 -1 -use innodb_test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -VARIABLE_VALUE <= 29 -1 -use test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -VARIABLE_VALUE <= 29 -1 -FLUSH STATUS; -# restart and see number read page 0 -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -VARIABLE_VALUE <= 29 -1 -use innodb_test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -VARIABLE_VALUE <= 29 -1 -use test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -VARIABLE_VALUE <= 29 -1 -drop database innodb_test; -FLUSH STATUS; diff --git a/mysql-test/suite/encryption/r/innodb_lotoftables.result b/mysql-test/suite/encryption/r/innodb_lotoftables.result index 45800c8cd0b..3de38dc59ea 100644 --- a/mysql-test/suite/encryption/r/innodb_lotoftables.result +++ b/mysql-test/suite/encryption/r/innodb_lotoftables.result @@ -8,29 +8,17 @@ innodb_encryption_rotation_iops 100 innodb_encryption_threads 0 create database innodb_encrypted_1; use innodb_encrypted_1; -show status like 'innodb_pages0_read%'; -Variable_name Value -Innodb_pages0_read 4 set autocommit=0; set autocommit=1; commit work; -show status like 'innodb_pages0_read%'; -Variable_name Value -Innodb_pages0_read 4 # should be empty SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE NAME LIKE 'innodb_encrypted%'; NAME create database innodb_encrypted_2; use innodb_encrypted_2; -show status like 'innodb_pages0_read%'; -Variable_name Value -Innodb_pages0_read 4 set autocommit=0; commit work; set autocommit=1; -show status like 'innodb_pages0_read%'; -Variable_name Value -Innodb_pages0_read 4 # should contain 100 tables SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; NAME @@ -139,15 +127,9 @@ SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_ NAME create database innodb_encrypted_3; use innodb_encrypted_3; -show status like 'innodb_pages0_read%'; -Variable_name Value -Innodb_pages0_read 4 set autocommit=0; commit work; set autocommit=1; -show status like 'innodb_pages0_read%'; -Variable_name Value -Innodb_pages0_read 4 # should contain 100 tables SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; NAME @@ -355,9 +337,6 @@ innodb_encrypted_3/t_97 innodb_encrypted_3/t_98 innodb_encrypted_3/t_99 use test; -show status like 'innodb_pages0_read%'; -Variable_name Value -Innodb_pages0_read 4 SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; NAME innodb_encrypted_2/t_1 @@ -768,43 +747,12 @@ innodb_encrypted_3/t_96 innodb_encrypted_3/t_97 innodb_encrypted_3/t_98 innodb_encrypted_3/t_99 -show status like 'innodb_pages0_read%'; -Variable_name Value -Innodb_pages0_read 4 # Success! # Restart mysqld --innodb_encrypt_tables=0 --innodb_encryption_threads=0 # Restart Success! -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -variable_value <= 303 -1 -use test; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -variable_value <= 303 -1 -use innodb_encrypted_1; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -variable_value <= 303 -1 -use innodb_encrypted_2; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -variable_value <= 303 -1 -use innodb_encrypted_3; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -variable_value <= 303 -1 use innodb_encrypted_1; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -variable_value <= 303 -1 use innodb_encrypted_2; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -variable_value <= 303 -1 use innodb_encrypted_3; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -variable_value <= 303 -1 SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; NAME innodb_encrypted_3/t_1 diff --git a/mysql-test/suite/encryption/t/debug_key_management.test b/mysql-test/suite/encryption/t/debug_key_management.test index 22b213c6135..c370ecf5bd8 100644 --- a/mysql-test/suite/encryption/t/debug_key_management.test +++ b/mysql-test/suite/encryption/t/debug_key_management.test @@ -1,10 +1,15 @@ -- source include/have_innodb.inc +-- source include/have_debug.inc +-- source include/not_embedded.inc + if (`select count(*) = 0 from information_schema.plugins where plugin_name = 'debug_key_management' and plugin_status='active'`) { --skip Needs debug_key_management } +create table t1(a serial) engine=innoDB; + set global innodb_encrypt_tables=ON; show variables like 'innodb_encrypt%'; @@ -17,10 +22,21 @@ set global debug_key_management_version=10; let $wait_condition= select count(*) = $tables_count from information_schema.innodb_tablespaces_encryption where current_key_version=10; --source include/wait_condition.inc - select count(*) from information_schema.innodb_tablespaces_encryption where current_key_version <> 10; + +# Test redo log key rotation and crash recovery. +SET GLOBAL debug_dbug = '+d,ib_log'; +SET GLOBAL innodb_log_checkpoint_now = 1; +SET GLOBAL innodb_flush_log_at_trx_commit = 1; +INSERT INTO t1 VALUES(NULL); +let $shutdown_timeout = 0; +-- source include/restart_mysqld.inc + # Note that we expect that key_version is increasing so disable encryption before reset set global innodb_encrypt_tables=OFF; set global debug_key_management_version=1; +select * from t1; + +drop table t1; diff --git a/mysql-test/suite/encryption/t/innodb-first-page-read.test b/mysql-test/suite/encryption/t/innodb-first-page-read.test deleted file mode 100644 index c86e16c52b8..00000000000 --- a/mysql-test/suite/encryption/t/innodb-first-page-read.test +++ /dev/null @@ -1,104 +0,0 @@ --- source include/have_innodb.inc --- source include/have_file_key_management_plugin.inc --- source include/not_embedded.inc - -FLUSH STATUS; - -create database innodb_test; -use innodb_test; -create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; -create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact; -create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic; -create table innodb_compressed(c1 bigint not null, b char(200)) engine=innodb row_format=compressed; -create table innodb_compressed1(c1 bigint not null, b char(200)) engine=innodb row_format=compressed key_block_size=1; -create table innodb_compressed2(c1 bigint not null, b char(200)) engine=innodb row_format=compressed key_block_size=2; -create table innodb_compressed4(c1 bigint not null, b char(200)) engine=innodb row_format=compressed key_block_size=4; -create table innodb_compressed8(c1 bigint not null, b char(200)) engine=innodb row_format=compressed key_block_size=8; -create table innodb_compressed16(c1 bigint not null, b char(200)) engine=innodb row_format=compressed key_block_size=16; -create table innodb_redundant(c1 bigint not null, b char(200)) engine=innodb row_format=redundant; -create table innodb_pagecomp(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes; -create table innodb_pagecomp1(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=1; -create table innodb_pagecomp2(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=2; -create table innodb_pagecomp3(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=3; -create table innodb_pagecomp4(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=4; -create table innodb_pagecomp5(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=5; -create table innodb_pagecomp6(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=6; -create table innodb_pagecomp7(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=7; -create table innodb_pagecomp8(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=8; -create table innodb_pagecomp9(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes page_compression_level=9; - ---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR -eval create table innodb_datadir1(c1 bigint not null, b char(200)) engine=innodb DATA DIRECTORY='$MYSQL_TMP_DIR'; ---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR -eval create table innodb_datadir2(c1 bigint not null, b char(200)) engine=innodb row_format=compressed DATA DIRECTORY='$MYSQL_TMP_DIR'; ---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR -eval create table innodb_datadir3(c1 bigint not null, b char(200)) engine=innodb page_compressed=yes DATA DIRECTORY='$MYSQL_TMP_DIR'; - -begin; -insert into innodb_normal values (1,'secret'); -insert into innodb_compact select * from innodb_normal; -insert into innodb_dynamic select * from innodb_normal; -insert into innodb_compressed select * from innodb_normal; -insert into innodb_compressed1 select * from innodb_normal; -insert into innodb_compressed2 select * from innodb_normal; -insert into innodb_compressed4 select * from innodb_normal; -insert into innodb_compressed8 select * from innodb_normal; -insert into innodb_compressed16 select * from innodb_normal; -insert into innodb_redundant select * from innodb_normal; -insert into innodb_pagecomp select * from innodb_normal; -insert into innodb_pagecomp1 select * from innodb_normal; -insert into innodb_pagecomp2 select * from innodb_normal; -insert into innodb_pagecomp3 select * from innodb_normal; -insert into innodb_pagecomp4 select * from innodb_normal; -insert into innodb_pagecomp5 select * from innodb_normal; -insert into innodb_pagecomp6 select * from innodb_normal; -insert into innodb_pagecomp7 select * from innodb_normal; -insert into innodb_pagecomp8 select * from innodb_normal; -insert into innodb_pagecomp9 select * from innodb_normal; -insert into innodb_datadir1 select * from innodb_normal; -insert into innodb_datadir2 select * from innodb_normal; -insert into innodb_datadir3 select * from innodb_normal; -commit; - -FLUSH STATUS; - ---echo # Restart server and see how many page 0's are read ---source include/restart_mysqld.inc - ---echo # result should actual number of tables except remote tables could be read twice ---echo # i.e. < 23 + 3*2 = 29 - -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -use innodb_test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -use test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; - -set global innodb_encrypt_tables=OFF; - ---echo # wait until tables are decrypted ---let $wait_condition=SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 ---source include/wait_condition.inc - ---echo # result should be actual number of tables except remote tables could be read twice ---echo # i.e. < 23 + 3*2 = 29 - -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -use innodb_test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -use test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; - -FLUSH STATUS; - ---echo # restart and see number read page 0 --- source include/restart_mysqld.inc - -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -use innodb_test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; -use test; -SELECT VARIABLE_VALUE <= 29 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'innodb_pages0_read'; - -drop database innodb_test; -FLUSH STATUS; diff --git a/mysql-test/suite/encryption/t/innodb_lotoftables.test b/mysql-test/suite/encryption/t/innodb_lotoftables.test index 4ccdc7d5c49..413fc8685f2 100644 --- a/mysql-test/suite/encryption/t/innodb_lotoftables.test +++ b/mysql-test/suite/encryption/t/innodb_lotoftables.test @@ -21,7 +21,6 @@ SHOW VARIABLES LIKE 'innodb_encrypt%'; # create database innodb_encrypted_1; use innodb_encrypted_1; -show status like 'innodb_pages0_read%'; set autocommit=0; let $tables = 100; @@ -44,7 +43,6 @@ while ($tables) set autocommit=1; commit work; -show status like 'innodb_pages0_read%'; # # Verify # @@ -56,7 +54,6 @@ SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE NAME LIK # create database innodb_encrypted_2; use innodb_encrypted_2; -show status like 'innodb_pages0_read%'; set autocommit=0; --disable_query_log @@ -79,7 +76,6 @@ while ($tables) commit work; set autocommit=1; -show status like 'innodb_pages0_read%'; # # Verify # @@ -93,7 +89,6 @@ SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_ # create database innodb_encrypted_3; use innodb_encrypted_3; -show status like 'innodb_pages0_read%'; set autocommit=0; --disable_query_log @@ -116,7 +111,6 @@ while ($tables) commit work; set autocommit=1; -show status like 'innodb_pages0_read%'; # # Verify # @@ -126,7 +120,6 @@ SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_ SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; use test; -show status like 'innodb_pages0_read%'; SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; @@ -140,7 +133,6 @@ SET GLOBAL innodb_encryption_threads=4; SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; -show status like 'innodb_pages0_read%'; --echo # Success! --echo # Restart mysqld --innodb_encrypt_tables=0 --innodb_encryption_threads=0 @@ -149,16 +141,6 @@ show status like 'innodb_pages0_read%'; --echo # Restart Success! -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -use test; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -use innodb_encrypted_1; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -use innodb_encrypted_2; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; -use innodb_encrypted_3; -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; - use innodb_encrypted_1; --disable_result_log @@ -172,8 +154,6 @@ while ($tables) --enable_query_log --enable_result_log -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; - use innodb_encrypted_2; --disable_result_log @@ -187,8 +167,6 @@ while ($tables) --enable_query_log --enable_result_log -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; - use innodb_encrypted_3; --disable_result_log @@ -202,8 +180,6 @@ while ($tables) --enable_query_log --enable_result_log -SELECT variable_value <= 303 FROM information_schema.global_status WHERE variable_name = 'innodb_pages0_read'; - SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 AND NAME LIKE 'innodb_encrypted%' ORDER BY NAME; diff --git a/mysql-test/suite/engines/funcs/r/an_calendar.result b/mysql-test/suite/engines/funcs/r/an_calendar.result index f057c3b618f..669b097b325 100644 --- a/mysql-test/suite/engines/funcs/r/an_calendar.result +++ b/mysql-test/suite/engines/funcs/r/an_calendar.result @@ -11,6 +11,7 @@ Note 1265 Data truncated for column 'c1' at row 1 Note 1265 Data truncated for column 'c2' at row 1 ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 TIME NULL, c2 TIME NULL); @@ -25,6 +26,7 @@ Note 1265 Data truncated for column 'c1' at row 1 Note 1265 Data truncated for column 'c2' at row 1 ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 DATETIME NULL, c2 DATETIME NULL); @@ -33,6 +35,7 @@ INSERT INTO t1 VALUES(NOW(),NOW()); INSERT INTO t1 VALUES(NOW(),NOW()); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 TIMESTAMP NULL, c2 TIMESTAMP NULL); @@ -41,5 +44,6 @@ INSERT INTO t1 VALUES(NOW(),NOW()); INSERT INTO t1 VALUES(NOW(),NOW()); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; diff --git a/mysql-test/suite/engines/funcs/r/an_number.result b/mysql-test/suite/engines/funcs/r/an_number.result index a77fc0e7d69..257213d0bf8 100644 --- a/mysql-test/suite/engines/funcs/r/an_number.result +++ b/mysql-test/suite/engines/funcs/r/an_number.result @@ -4,6 +4,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 SMALLINT NULL, c2 SMALLINT NULL); @@ -11,6 +12,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 MEDIUMINT NULL, c2 MEDIUMINT NULL); @@ -18,6 +20,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 INT NULL, c2 INT NULL); @@ -25,6 +28,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 INTEGER NULL, c2 INTEGER NULL); @@ -32,6 +36,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 BIGINT NULL, c2 BIGINT NULL); @@ -39,6 +44,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 DECIMAL NULL, c2 DECIMAL NULL); @@ -46,6 +52,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 DEC NULL, c2 DEC NULL); @@ -53,6 +60,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 FIXED NULL, c2 FIXED NULL); @@ -60,6 +68,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 NUMERIC NULL, c2 NUMERIC NULL); @@ -67,6 +76,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 DOUBLE NULL, c2 DOUBLE NULL); @@ -74,6 +84,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 REAL NULL, c2 REAL NULL); @@ -81,6 +92,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 DOUBLE PRECISION NULL, c2 DOUBLE PRECISION NULL); @@ -88,6 +100,7 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 FLOAT NULL, c2 FLOAT NULL); @@ -95,5 +108,6 @@ INSERT INTO t1 VALUES(1,2); INSERT INTO t1 VALUES(3,4); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; diff --git a/mysql-test/suite/engines/funcs/r/an_string.result b/mysql-test/suite/engines/funcs/r/an_string.result index c7762155a7d..f3e7eaedb15 100644 --- a/mysql-test/suite/engines/funcs/r/an_string.result +++ b/mysql-test/suite/engines/funcs/r/an_string.result @@ -4,6 +4,7 @@ INSERT INTO t1 VALUES('abc','ABCDEFG'); INSERT INTO t1 VALUES('123','1234567890'); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 VARCHAR(100) NULL, c2 VARCHAR(100) NULL); @@ -11,6 +12,7 @@ INSERT INTO t1 VALUES('abc','ABCDEFG'); INSERT INTO t1 VALUES('123','1234567890'); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 BINARY(100) NULL, c2 BINARY(100) NULL); @@ -18,6 +20,7 @@ INSERT INTO t1 VALUES('abc','ABCDEFG'); INSERT INTO t1 VALUES('123','1234567890'); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 VARBINARY(100) NULL, c2 VARBINARY(100) NULL); @@ -25,6 +28,7 @@ INSERT INTO t1 VALUES('abc','ABCDEFG'); INSERT INTO t1 VALUES('123','1234567890'); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 BLOB(100) NULL, c2 BLOB(100) NULL); @@ -32,6 +36,9 @@ INSERT INTO t1 VALUES('abc','ABCDEFG'); INSERT INTO t1 VALUES('123','1234567890'); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'c1' +test.t1 analyze Warning Engine-independent statistics are not collected for column 'c2' test.t1 analyze status OK DROP TABLE t1; CREATE TABLE t1(c1 TEXT(100) NULL, c2 TEXT(100) NULL); @@ -39,5 +46,8 @@ INSERT INTO t1 VALUES('abc','ABCDEFG'); INSERT INTO t1 VALUES('123','1234567890'); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'c1' +test.t1 analyze Warning Engine-independent statistics are not collected for column 'c2' test.t1 analyze status OK DROP TABLE t1; diff --git a/mysql-test/suite/engines/funcs/r/tc_partition_analyze.result b/mysql-test/suite/engines/funcs/r/tc_partition_analyze.result index 884408d29b3..52a8b2de642 100644 --- a/mysql-test/suite/engines/funcs/r/tc_partition_analyze.result +++ b/mysql-test/suite/engines/funcs/r/tc_partition_analyze.result @@ -33,6 +33,7 @@ t1 CREATE TABLE `t1` ( PARTITION `p5` VALUES LESS THAN MAXVALUE ENGINE = ENGINE) ALTER TABLE t1 ANALYZE PARTITION p1,p2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM t1 ORDER BY c1; c1 c2 diff --git a/mysql-test/suite/funcs_1/r/innodb_func_view.result b/mysql-test/suite/funcs_1/r/innodb_func_view.result index 7be6bb2f049..7850e017fb2 100644 --- a/mysql-test/suite/funcs_1/r/innodb_func_view.result +++ b/mysql-test/suite/funcs_1/r/innodb_func_view.result @@ -3778,14 +3778,14 @@ WHERE select_id = 51 OR select_id IS NULL order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as time) AS `CAST(my_varbinary_1000 AS TIME)`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3795,14 +3795,14 @@ WHERE select_id = 51 OR select_id IS NULL) order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' DROP VIEW v1; @@ -3813,15 +3813,15 @@ my_binary_30, id FROM t1_values WHERE select_id = 50 OR select_id IS NULL order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL 2 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 22 Warnings: -Warning 1292 Truncated incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '-1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '1 17:58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' SHOW CREATE VIEW v1; @@ -3832,15 +3832,15 @@ WHERE v1.id IN (SELECT id FROM t1_values WHERE select_id = 50 OR select_id IS NULL) order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- +NULL +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- -00:00:01 -1 41:58:00 1 17:58 Warnings: -Warning 1292 Truncated incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '-1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '1 17:58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' DROP VIEW v1; @@ -3854,14 +3854,14 @@ WHERE select_id = 49 OR select_id IS NULL order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as time) AS `CAST(my_varchar_1000 AS TIME)`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3871,14 +3871,14 @@ WHERE select_id = 49 OR select_id IS NULL) order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' DROP VIEW v1; @@ -3890,14 +3890,14 @@ WHERE select_id = 48 OR select_id IS NULL order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_char_30` as time) AS `CAST(my_char_30 AS TIME)`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3907,14 +3907,14 @@ WHERE select_id = 48 OR select_id IS NULL) order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' DROP VIEW v1; diff --git a/mysql-test/suite/funcs_1/r/is_check_constraints.result b/mysql-test/suite/funcs_1/r/is_check_constraints.result index 678cfb8db2f..eaf90f44544 100644 --- a/mysql-test/suite/funcs_1/r/is_check_constraints.result +++ b/mysql-test/suite/funcs_1/r/is_check_constraints.result @@ -9,6 +9,11 @@ t int, check (t>32) # table constraint ) ENGINE=myisam; SELECT * from information_schema.check_constraints order by check_clause; CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA mysql +CONSTRAINT_NAME Priv +TABLE_NAME global_priv +CHECK_CLAUSE json_valid(`Priv`) +CONSTRAINT_CATALOG def CONSTRAINT_SCHEMA test CONSTRAINT_NAME CONSTRAINT_1 TABLE_NAME t0 @@ -17,6 +22,11 @@ ALTER TABLE t0 ADD CONSTRAINT CHK_t0_t CHECK(t<100); SELECT * from information_schema.check_constraints order by check_clause; CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA mysql +CONSTRAINT_NAME Priv +TABLE_NAME global_priv +CHECK_CLAUSE json_valid(`Priv`) +CONSTRAINT_CATALOG def CONSTRAINT_SCHEMA test CONSTRAINT_NAME CHK_t0_t TABLE_NAME t0 @@ -30,6 +40,11 @@ ALTER TABLE t0 DROP CONSTRAINT CHK_t0_t; SELECT * from information_schema.check_constraints order by check_clause; CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA mysql +CONSTRAINT_NAME Priv +TABLE_NAME global_priv +CHECK_CLAUSE json_valid(`Priv`) +CONSTRAINT_CATALOG def CONSTRAINT_SCHEMA test CONSTRAINT_NAME CONSTRAINT_1 TABLE_NAME t0 @@ -40,6 +55,11 @@ tt int, CONSTRAINT CHK_tt CHECK(tt<100) # table constraint ) ENGINE=InnoDB; SELECT * from information_schema.check_constraints order by check_clause; CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA mysql +CONSTRAINT_NAME Priv +TABLE_NAME global_priv +CHECK_CLAUSE json_valid(`Priv`) +CONSTRAINT_CATALOG def CONSTRAINT_SCHEMA test CONSTRAINT_NAME CHK_tt TABLE_NAME t1 @@ -58,6 +78,11 @@ ALTER TABLE t1 DROP CONSTRAINT CHK_tt; SELECT * from information_schema.check_constraints order by check_clause; CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA mysql +CONSTRAINT_NAME Priv +TABLE_NAME global_priv +CHECK_CLAUSE json_valid(`Priv`) +CONSTRAINT_CATALOG def CONSTRAINT_SCHEMA test CONSTRAINT_NAME t TABLE_NAME t1 @@ -81,6 +106,11 @@ CONSTRAINT_NAME name TABLE_NAME t2 CHECK_CLAUSE char_length(`name`) > 2 CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA mysql +CONSTRAINT_NAME Priv +TABLE_NAME global_priv +CHECK_CLAUSE json_valid(`Priv`) +CONSTRAINT_CATALOG def CONSTRAINT_SCHEMA test CONSTRAINT_NAME CHK_dates TABLE_NAME t2 @@ -104,6 +134,11 @@ CONSTRAINT_NAME name TABLE_NAME t2 CHECK_CLAUSE char_length(`name`) > 2 CONSTRAINT_CATALOG def +CONSTRAINT_SCHEMA mysql +CONSTRAINT_NAME Priv +TABLE_NAME global_priv +CHECK_CLAUSE json_valid(`Priv`) +CONSTRAINT_CATALOG def CONSTRAINT_SCHEMA test CONSTRAINT_NAME CHK_dates TABLE_NAME t2 @@ -132,6 +167,7 @@ CONSTRAINT b check (b>10) # table constraint select * from information_schema.check_constraints order by check_clause; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_NAME CHECK_CLAUSE def test name t2 char_length(`name`) > 2 +def mysql Priv global_priv json_valid(`Priv`) def test b t3 `b` > 0 def test b t3 `b` > 10 def test CHK_dates t2 `start_date` is null diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index f5452e0c8e8..31160f8a3ec 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -61,7 +61,7 @@ def mysql event modified 9 '0000-00-00 00:00:00' NO timestamp NULL NULL NULL NUL def mysql event name 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) PRI select,insert,update,references NEVER NULL def mysql event on_completion 14 'DROP' NO enum 8 24 NULL NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE') select,insert,update,references NEVER NULL def mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL -def mysql event sql_mode 15 '' NO set 539 1617 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') select,insert,update,references NEVER NULL +def mysql event sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') select,insert,update,references NEVER NULL def mysql event starts 11 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select,insert,update,references NEVER NULL def mysql event status 13 'ENABLED' NO enum 18 54 NULL NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') select,insert,update,references NEVER NULL def mysql event time_zone 18 'SYSTEM' NO char 64 64 NULL NULL NULL latin1 latin1_swedish_ci char(64) select,insert,update,references NEVER NULL @@ -75,6 +75,9 @@ def mysql general_log event_time 1 current_timestamp(6) NO timestamp NULL NULL N def mysql general_log server_id 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL def mysql general_log thread_id 3 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select,insert,update,references NEVER NULL def mysql general_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext select,insert,update,references NEVER NULL +def mysql global_priv Host 1 '' NO char 60 180 NULL NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references NEVER NULL +def mysql global_priv Priv 3 '{}' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext select,insert,update,references NEVER NULL +def mysql global_priv User 2 '' NO char 80 240 NULL NULL NULL utf8 utf8_bin char(80) PRI select,insert,update,references NEVER NULL def mysql gtid_slave_pos domain_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI select,insert,update,references NEVER NULL def mysql gtid_slave_pos seq_no 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL def mysql gtid_slave_pos server_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned select,insert,update,references NEVER NULL @@ -93,26 +96,6 @@ def mysql help_topic help_category_id 3 NULL NO smallint NULL NULL 5 0 NULL NULL def mysql help_topic help_topic_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI select,insert,update,references NEVER NULL def mysql help_topic name 2 NULL NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) UNI select,insert,update,references NEVER NULL def mysql help_topic url 6 NULL NO text 65535 65535 NULL NULL NULL utf8 utf8_general_ci text select,insert,update,references NEVER NULL -def mysql host Alter_priv 12 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Alter_routine_priv 18 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Create_priv 7 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Create_routine_priv 17 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Create_tmp_table_priv 13 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Create_view_priv 15 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Db 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references NEVER NULL -def mysql host Delete_priv 6 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Drop_priv 8 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Execute_priv 19 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Grant_priv 9 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Host 1 '' NO char 60 180 NULL NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references NEVER NULL -def mysql host Index_priv 11 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Insert_priv 4 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Lock_tables_priv 14 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host References_priv 10 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Select_priv 3 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Show_view_priv 16 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Trigger_priv 20 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql host Update_priv 5 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL def mysql index_stats avg_frequency 5 NULL YES decimal NULL NULL 12 4 NULL NULL NULL decimal(12,4) select,insert,update,references NEVER NULL def mysql index_stats db_name 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references NEVER NULL def mysql index_stats index_name 3 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references NEVER NULL @@ -153,7 +136,7 @@ def mysql proc returns 10 NULL NO longblob 4294967295 4294967295 NULL NULL NULL def mysql proc security_type 8 'DEFINER' NO enum 7 21 NULL NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER') select,insert,update,references NEVER NULL def mysql proc specific_name 4 '' NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) select,insert,update,references NEVER NULL def mysql proc sql_data_access 6 'CONTAINS_SQL' NO enum 17 51 NULL NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') select,insert,update,references NEVER NULL -def mysql proc sql_mode 15 '' NO set 539 1617 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') select,insert,update,references NEVER NULL +def mysql proc sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') select,insert,update,references NEVER NULL def mysql proc type 3 NULL NO enum 12 36 NULL NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') PRI select,insert,update,references NEVER NULL def mysql procs_priv Db 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references NEVER NULL def mysql procs_priv Grantor 6 '' NO char 141 423 NULL NULL NULL utf8 utf8_bin char(141) MUL select,insert,update,references NEVER NULL @@ -226,53 +209,53 @@ def mysql transaction_registry commit_id 2 NULL NO bigint NULL NULL 20 0 NULL NU def mysql transaction_registry commit_timestamp 4 '0000-00-00 00:00:00.000000' NO timestamp NULL NULL NULL NULL 6 NULL NULL timestamp(6) MUL select,insert,update,references NEVER NULL def mysql transaction_registry isolation_level 5 NULL NO enum 16 48 NULL NULL NULL utf8 utf8_bin enum('READ-UNCOMMITTED','READ-COMMITTED','REPEATABLE-READ','SERIALIZABLE') select,insert,update,references NEVER NULL def mysql transaction_registry transaction_id 1 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned PRI select,insert,update,references NEVER NULL -def mysql user Alter_priv 17 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Alter_routine_priv 28 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user authentication_string 43 NULL NO text 65535 65535 NULL NULL NULL utf8 utf8_bin text select,insert,update,references NEVER NULL -def mysql user Create_priv 8 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Create_routine_priv 27 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Create_tablespace_priv 32 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Create_tmp_table_priv 20 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Create_user_priv 29 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Create_view_priv 25 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user default_role 46 '' NO char 80 240 NULL NULL NULL utf8 utf8_bin char(80) select,insert,update,references NEVER NULL -def mysql user Delete_history_priv 33 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Delete_priv 7 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Drop_priv 9 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Event_priv 30 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Execute_priv 22 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user File_priv 13 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Grant_priv 14 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Host 1 '' NO char 60 180 NULL NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references NEVER NULL -def mysql user Index_priv 16 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Insert_priv 5 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user is_role 45 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Lock_tables_priv 21 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user max_connections 40 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned select,insert,update,references NEVER NULL -def mysql user max_questions 38 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned select,insert,update,references NEVER NULL +def mysql user Alter_priv 17 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Alter_routine_priv 28 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user authentication_string 43 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext select,insert,update,references NEVER NULL +def mysql user Create_priv 8 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Create_routine_priv 27 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Create_tablespace_priv 32 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Create_tmp_table_priv 20 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Create_user_priv 29 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Create_view_priv 25 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user default_role 46 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext select,insert,update,references NEVER NULL +def mysql user Delete_history_priv 33 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Delete_priv 7 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Drop_priv 9 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Event_priv 30 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Execute_priv 22 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user File_priv 13 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Grant_priv 14 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Host 1 '' NO char 60 180 NULL NULL NULL utf8 utf8_bin char(60) select,insert,update,references NEVER NULL +def mysql user Index_priv 16 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Insert_priv 5 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user is_role 45 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Lock_tables_priv 21 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user max_connections 40 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL +def mysql user max_questions 38 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL def mysql user max_statement_time 47 0.000000 NO decimal NULL NULL 12 6 NULL NULL NULL decimal(12,6) select,insert,update,references NEVER NULL -def mysql user max_updates 39 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned select,insert,update,references NEVER NULL -def mysql user max_user_connections 41 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references NEVER NULL -def mysql user Password 3 '' NO char 41 41 NULL NULL NULL latin1 latin1_bin char(41) select,insert,update,references NEVER NULL -def mysql user password_expired 44 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user plugin 42 '' NO char 64 64 NULL NULL NULL latin1 latin1_swedish_ci char(64) select,insert,update,references NEVER NULL -def mysql user Process_priv 12 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user References_priv 15 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Reload_priv 10 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Repl_client_priv 24 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Repl_slave_priv 23 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Select_priv 4 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Show_db_priv 18 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Show_view_priv 26 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Shutdown_priv 11 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user ssl_cipher 35 NULL NO blob 65535 65535 NULL NULL NULL NULL NULL blob select,insert,update,references NEVER NULL -def mysql user ssl_type 34 '' NO enum 9 27 NULL NULL NULL utf8 utf8_general_ci enum('','ANY','X509','SPECIFIED') select,insert,update,references NEVER NULL -def mysql user Super_priv 19 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Trigger_priv 31 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user Update_priv 6 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references NEVER NULL -def mysql user User 2 '' NO char 80 240 NULL NULL NULL utf8 utf8_bin char(80) PRI select,insert,update,references NEVER NULL -def mysql user x509_issuer 36 NULL NO blob 65535 65535 NULL NULL NULL NULL NULL blob select,insert,update,references NEVER NULL -def mysql user x509_subject 37 NULL NO blob 65535 65535 NULL NULL NULL NULL NULL blob select,insert,update,references NEVER NULL +def mysql user max_updates 39 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL +def mysql user max_user_connections 41 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select,insert,update,references NEVER NULL +def mysql user Password 3 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext select,insert,update,references NEVER NULL +def mysql user password_expired 44 '' NO varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user plugin 42 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext select,insert,update,references NEVER NULL +def mysql user Process_priv 12 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user References_priv 15 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Reload_priv 10 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Repl_client_priv 24 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Repl_slave_priv 23 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Select_priv 4 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Show_db_priv 18 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Show_view_priv 26 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Shutdown_priv 11 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user ssl_cipher 35 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext select,insert,update,references NEVER NULL +def mysql user ssl_type 34 NULL YES varchar 9 9 NULL NULL NULL latin1 latin1_swedish_ci varchar(9) select,insert,update,references NEVER NULL +def mysql user Super_priv 19 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Trigger_priv 31 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user Update_priv 6 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) select,insert,update,references NEVER NULL +def mysql user User 2 '' NO char 80 240 NULL NULL NULL utf8 utf8_bin char(80) select,insert,update,references NEVER NULL +def mysql user x509_issuer 36 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext select,insert,update,references NEVER NULL +def mysql user x509_subject 37 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext select,insert,update,references NEVER NULL ########################################################################## # Show the quotient of CHARACTER_OCTET_LENGTH and CHARACTER_MAXIMUM_LENGTH ########################################################################## @@ -289,11 +272,12 @@ COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME 1.0000 blob NULL NULL 1.0000 longblob NULL NULL 1.0000 varbinary NULL NULL -1.0000 char latin1 latin1_bin 1.0000 char latin1 latin1_swedish_ci +1.0000 varchar latin1 latin1_swedish_ci 1.0000 text utf8 utf8_bin 1.0000 mediumtext utf8 utf8_general_ci 1.0000 text utf8 utf8_general_ci +1.0000 longtext utf8mb4 utf8mb4_bin SELECT DISTINCT CHARACTER_OCTET_LENGTH / CHARACTER_MAXIMUM_LENGTH AS COL_CML, DATA_TYPE, @@ -400,7 +384,7 @@ NULL mysql event starts datetime NULL NULL NULL NULL datetime NULL mysql event ends datetime NULL NULL NULL NULL datetime 3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') 3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE') -3.0000 mysql event sql_mode set 539 1617 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') +3.0000 mysql event sql_mode set 561 1683 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') 3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64) NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned 1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64) @@ -418,6 +402,9 @@ NULL mysql general_log thread_id bigint NULL NULL NULL NULL bigint(21) unsigned NULL mysql general_log server_id int NULL NULL NULL NULL int(10) unsigned 3.0000 mysql general_log command_type varchar 64 192 utf8 utf8_general_ci varchar(64) 1.0000 mysql general_log argument mediumtext 16777215 16777215 utf8 utf8_general_ci mediumtext +3.0000 mysql global_priv Host char 60 180 utf8 utf8_bin char(60) +3.0000 mysql global_priv User char 80 240 utf8 utf8_bin char(80) +1.0000 mysql global_priv Priv longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext NULL mysql gtid_slave_pos domain_id int NULL NULL NULL NULL int(10) unsigned NULL mysql gtid_slave_pos sub_id bigint NULL NULL NULL NULL bigint(20) unsigned NULL mysql gtid_slave_pos server_id int NULL NULL NULL NULL int(10) unsigned @@ -436,26 +423,6 @@ NULL mysql help_topic help_category_id smallint NULL NULL NULL NULL smallint(5) 1.0000 mysql help_topic description text 65535 65535 utf8 utf8_general_ci text 1.0000 mysql help_topic example text 65535 65535 utf8 utf8_general_ci text 1.0000 mysql help_topic url text 65535 65535 utf8 utf8_general_ci text -3.0000 mysql host Host char 60 180 utf8 utf8_bin char(60) -3.0000 mysql host Db char 64 192 utf8 utf8_bin char(64) -3.0000 mysql host Select_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Insert_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Update_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Delete_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Create_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Drop_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Grant_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host References_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Index_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Alter_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Create_tmp_table_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Lock_tables_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Create_view_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Show_view_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Create_routine_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Alter_routine_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Execute_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Trigger_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') 3.0000 mysql index_stats db_name varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 mysql index_stats table_name varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 mysql index_stats index_name varchar 64 192 utf8 utf8_bin varchar(64) @@ -491,7 +458,7 @@ NULL mysql innodb_table_stats sum_of_other_index_sizes bigint NULL NULL NULL NUL 3.0000 mysql proc definer char 141 423 utf8 utf8_bin char(141) NULL mysql proc created timestamp NULL NULL NULL NULL timestamp NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp -3.0000 mysql proc sql_mode set 539 1617 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') +3.0000 mysql proc sql_mode set 561 1683 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') 1.0000 mysql proc comment text 65535 65535 utf8 utf8_bin text 3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32) 3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32) @@ -571,48 +538,48 @@ NULL mysql transaction_registry commit_timestamp timestamp NULL NULL NULL NULL t 3.0000 mysql transaction_registry isolation_level enum 16 48 utf8 utf8_bin enum('READ-UNCOMMITTED','READ-COMMITTED','REPEATABLE-READ','SERIALIZABLE') 3.0000 mysql user Host char 60 180 utf8 utf8_bin char(60) 3.0000 mysql user User char 80 240 utf8 utf8_bin char(80) -1.0000 mysql user Password char 41 41 latin1 latin1_bin char(41) -3.0000 mysql user Select_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Insert_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Update_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Delete_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Drop_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Reload_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Shutdown_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Process_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user File_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Grant_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user References_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Index_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Alter_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Show_db_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Super_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_tmp_table_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Lock_tables_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Execute_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Repl_slave_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Repl_client_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_view_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Show_view_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_routine_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Alter_routine_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_user_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Event_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Trigger_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_tablespace_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Delete_history_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user ssl_type enum 9 27 utf8 utf8_general_ci enum('','ANY','X509','SPECIFIED') -1.0000 mysql user ssl_cipher blob 65535 65535 NULL NULL blob -1.0000 mysql user x509_issuer blob 65535 65535 NULL NULL blob -1.0000 mysql user x509_subject blob 65535 65535 NULL NULL blob -NULL mysql user max_questions int NULL NULL NULL NULL int(11) unsigned -NULL mysql user max_updates int NULL NULL NULL NULL int(11) unsigned -NULL mysql user max_connections int NULL NULL NULL NULL int(11) unsigned -NULL mysql user max_user_connections int NULL NULL NULL NULL int(11) -1.0000 mysql user plugin char 64 64 latin1 latin1_swedish_ci char(64) -1.0000 mysql user authentication_string text 65535 65535 utf8 utf8_bin text -3.0000 mysql user password_expired enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user is_role enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user default_role char 80 240 utf8 utf8_bin char(80) +1.0000 mysql user Password longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql user Select_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Insert_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Update_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Delete_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Drop_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Reload_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Shutdown_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Process_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user File_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Grant_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user References_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Index_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Alter_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Show_db_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Super_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_tmp_table_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Lock_tables_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Execute_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Repl_slave_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Repl_client_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_view_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Show_view_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_routine_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Alter_routine_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_user_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Event_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Trigger_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_tablespace_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Delete_history_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user ssl_type varchar 9 9 latin1 latin1_swedish_ci varchar(9) +1.0000 mysql user ssl_cipher longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql user x509_issuer longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql user x509_subject longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +NULL mysql user max_questions bigint NULL NULL NULL NULL bigint(20) unsigned +NULL mysql user max_updates bigint NULL NULL NULL NULL bigint(20) unsigned +NULL mysql user max_connections bigint NULL NULL NULL NULL bigint(20) unsigned +NULL mysql user max_user_connections bigint NULL NULL NULL NULL bigint(21) +1.0000 mysql user plugin longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql user authentication_string longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql user password_expired varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user is_role varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user default_role longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext NULL mysql user max_statement_time decimal NULL NULL NULL NULL decimal(12,6) diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result index 9f17724b356..6ad671a54c8 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result @@ -61,7 +61,7 @@ def mysql event modified 9 '0000-00-00 00:00:00' NO timestamp NULL NULL NULL NUL def mysql event name 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) PRI NEVER NULL def mysql event on_completion 14 'DROP' NO enum 8 24 NULL NULL NULL utf8 utf8_general_ci enum('DROP','PRESERVE') NEVER NULL def mysql event originator 17 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned NEVER NULL -def mysql event sql_mode 15 '' NO set 539 1617 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NEVER NULL +def mysql event sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NEVER NULL def mysql event starts 11 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime NEVER NULL def mysql event status 13 'ENABLED' NO enum 18 54 NULL NULL NULL utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') NEVER NULL def mysql event time_zone 18 'SYSTEM' NO char 64 64 NULL NULL NULL latin1 latin1_swedish_ci char(64) NEVER NULL @@ -75,6 +75,9 @@ def mysql general_log event_time 1 current_timestamp(6) NO timestamp NULL NULL N def mysql general_log server_id 4 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned NEVER NULL def mysql general_log thread_id 3 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned NEVER NULL def mysql general_log user_host 2 NULL NO mediumtext 16777215 16777215 NULL NULL NULL utf8 utf8_general_ci mediumtext NEVER NULL +def mysql global_priv Host 1 '' NO char 60 180 NULL NULL NULL utf8 utf8_bin char(60) PRI NEVER NULL +def mysql global_priv Priv 3 '{}' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext NEVER NULL +def mysql global_priv User 2 '' NO char 80 240 NULL NULL NULL utf8 utf8_bin char(80) PRI NEVER NULL def mysql gtid_slave_pos domain_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI NEVER NULL def mysql gtid_slave_pos seq_no 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned NEVER NULL def mysql gtid_slave_pos server_id 3 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned NEVER NULL @@ -93,26 +96,6 @@ def mysql help_topic help_category_id 3 NULL NO smallint NULL NULL 5 0 NULL NULL def mysql help_topic help_topic_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI NEVER NULL def mysql help_topic name 2 NULL NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) UNI NEVER NULL def mysql help_topic url 6 NULL NO text 65535 65535 NULL NULL NULL utf8 utf8_general_ci text NEVER NULL -def mysql host Alter_priv 12 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Alter_routine_priv 18 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Create_priv 7 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Create_routine_priv 17 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Create_tmp_table_priv 13 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Create_view_priv 15 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Db 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI NEVER NULL -def mysql host Delete_priv 6 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Drop_priv 8 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Execute_priv 19 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Grant_priv 9 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Host 1 '' NO char 60 180 NULL NULL NULL utf8 utf8_bin char(60) PRI NEVER NULL -def mysql host Index_priv 11 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Insert_priv 4 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Lock_tables_priv 14 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host References_priv 10 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Select_priv 3 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Show_view_priv 16 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Trigger_priv 20 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql host Update_priv 5 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL def mysql index_stats avg_frequency 5 NULL YES decimal NULL NULL 12 4 NULL NULL NULL decimal(12,4) NEVER NULL def mysql index_stats db_name 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI NEVER NULL def mysql index_stats index_name 3 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI NEVER NULL @@ -139,7 +122,7 @@ def mysql proc returns 10 NULL NO longblob 4294967295 4294967295 NULL NULL NULL def mysql proc security_type 8 'DEFINER' NO enum 7 21 NULL NULL NULL utf8 utf8_general_ci enum('INVOKER','DEFINER') NEVER NULL def mysql proc specific_name 4 '' NO char 64 192 NULL NULL NULL utf8 utf8_general_ci char(64) NEVER NULL def mysql proc sql_data_access 6 'CONTAINS_SQL' NO enum 17 51 NULL NULL NULL utf8 utf8_general_ci enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA') NEVER NULL -def mysql proc sql_mode 15 '' NO set 539 1617 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') NEVER NULL +def mysql proc sql_mode 15 '' NO set 561 1683 NULL NULL NULL utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') NEVER NULL def mysql proc type 3 NULL NO enum 12 36 NULL NULL NULL utf8 utf8_general_ci enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') PRI NEVER NULL def mysql procs_priv Db 2 '' NO char 64 192 NULL NULL NULL utf8 utf8_bin char(64) PRI NEVER NULL def mysql procs_priv Grantor 6 '' NO char 141 423 NULL NULL NULL utf8 utf8_bin char(141) MUL NEVER NULL @@ -207,53 +190,53 @@ def mysql time_zone_transition_type Is_DST 4 0 NO tinyint NULL NULL 3 0 NULL NUL def mysql time_zone_transition_type Offset 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL def mysql time_zone_transition_type Time_zone_id 1 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI NEVER NULL def mysql time_zone_transition_type Transition_type_id 2 NULL NO int NULL NULL 10 0 NULL NULL NULL int(10) unsigned PRI NEVER NULL -def mysql user Alter_priv 17 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Alter_routine_priv 28 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user authentication_string 43 NULL NO text 65535 65535 NULL NULL NULL utf8 utf8_bin text NEVER NULL -def mysql user Create_priv 8 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Create_routine_priv 27 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Create_tablespace_priv 32 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Create_tmp_table_priv 20 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Create_user_priv 29 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Create_view_priv 25 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user default_role 46 '' NO char 80 240 NULL NULL NULL utf8 utf8_bin char(80) NEVER NULL -def mysql user Delete_history_priv 33 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Delete_priv 7 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Drop_priv 9 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Event_priv 30 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Execute_priv 22 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user File_priv 13 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Grant_priv 14 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Host 1 '' NO char 60 180 NULL NULL NULL utf8 utf8_bin char(60) PRI NEVER NULL -def mysql user Index_priv 16 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Insert_priv 5 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user is_role 45 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Lock_tables_priv 21 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user max_connections 40 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned NEVER NULL -def mysql user max_questions 38 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned NEVER NULL +def mysql user Alter_priv 17 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Alter_routine_priv 28 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user authentication_string 43 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext NEVER NULL +def mysql user Create_priv 8 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Create_routine_priv 27 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Create_tablespace_priv 32 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Create_tmp_table_priv 20 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Create_user_priv 29 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Create_view_priv 25 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user default_role 46 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext NEVER NULL +def mysql user Delete_history_priv 33 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Delete_priv 7 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Drop_priv 9 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Event_priv 30 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Execute_priv 22 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user File_priv 13 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Grant_priv 14 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Host 1 '' NO char 60 180 NULL NULL NULL utf8 utf8_bin char(60) NEVER NULL +def mysql user Index_priv 16 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Insert_priv 5 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user is_role 45 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Lock_tables_priv 21 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user max_connections 40 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned NEVER NULL +def mysql user max_questions 38 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned NEVER NULL def mysql user max_statement_time 47 0.000000 NO decimal NULL NULL 12 6 NULL NULL NULL decimal(12,6) NEVER NULL -def mysql user max_updates 39 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned NEVER NULL -def mysql user max_user_connections 41 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) NEVER NULL -def mysql user Password 3 '' NO char 41 41 NULL NULL NULL latin1 latin1_bin char(41) NEVER NULL -def mysql user password_expired 44 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user plugin 42 '' NO char 64 64 NULL NULL NULL latin1 latin1_swedish_ci char(64) NEVER NULL -def mysql user Process_priv 12 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user References_priv 15 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Reload_priv 10 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Repl_client_priv 24 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Repl_slave_priv 23 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Select_priv 4 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Show_db_priv 18 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Show_view_priv 26 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Shutdown_priv 11 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user ssl_cipher 35 NULL NO blob 65535 65535 NULL NULL NULL NULL NULL blob NEVER NULL -def mysql user ssl_type 34 '' NO enum 9 27 NULL NULL NULL utf8 utf8_general_ci enum('','ANY','X509','SPECIFIED') NEVER NULL -def mysql user Super_priv 19 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Trigger_priv 31 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user Update_priv 6 'N' NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') NEVER NULL -def mysql user User 2 '' NO char 80 240 NULL NULL NULL utf8 utf8_bin char(80) PRI NEVER NULL -def mysql user x509_issuer 36 NULL NO blob 65535 65535 NULL NULL NULL NULL NULL blob NEVER NULL -def mysql user x509_subject 37 NULL NO blob 65535 65535 NULL NULL NULL NULL NULL blob NEVER NULL +def mysql user max_updates 39 0 NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned NEVER NULL +def mysql user max_user_connections 41 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) NEVER NULL +def mysql user Password 3 NULL YES longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext NEVER NULL +def mysql user password_expired 44 '' NO varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user plugin 42 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext NEVER NULL +def mysql user Process_priv 12 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user References_priv 15 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Reload_priv 10 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Repl_client_priv 24 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Repl_slave_priv 23 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Select_priv 4 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Show_db_priv 18 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Show_view_priv 26 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Shutdown_priv 11 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user ssl_cipher 35 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext NEVER NULL +def mysql user ssl_type 34 NULL YES varchar 9 9 NULL NULL NULL latin1 latin1_swedish_ci varchar(9) NEVER NULL +def mysql user Super_priv 19 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Trigger_priv 31 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user Update_priv 6 NULL YES varchar 1 1 NULL NULL NULL latin1 latin1_swedish_ci varchar(1) NEVER NULL +def mysql user User 2 '' NO char 80 240 NULL NULL NULL utf8 utf8_bin char(80) NEVER NULL +def mysql user x509_issuer 36 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext NEVER NULL +def mysql user x509_subject 37 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8mb4 utf8mb4_bin longtext NEVER NULL Warnings: Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' @@ -274,11 +257,12 @@ COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME 1.0000 blob NULL NULL 1.0000 longblob NULL NULL 1.0000 varbinary NULL NULL -1.0000 char latin1 latin1_bin 1.0000 char latin1 latin1_swedish_ci +1.0000 varchar latin1 latin1_swedish_ci 1.0000 text utf8 utf8_bin 1.0000 mediumtext utf8 utf8_general_ci 1.0000 text utf8 utf8_general_ci +1.0000 longtext utf8mb4 utf8mb4_bin Warnings: Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' @@ -397,7 +381,7 @@ NULL mysql event starts datetime NULL NULL NULL NULL datetime NULL mysql event ends datetime NULL NULL NULL NULL datetime 3.0000 mysql event status enum 18 54 utf8 utf8_general_ci enum('ENABLED','DISABLED','SLAVESIDE_DISABLED') 3.0000 mysql event on_completion enum 8 24 utf8 utf8_general_ci enum('DROP','PRESERVE') -3.0000 mysql event sql_mode set 539 1617 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') +3.0000 mysql event sql_mode set 561 1683 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') 3.0000 mysql event comment char 64 192 utf8 utf8_bin char(64) NULL mysql event originator int NULL NULL NULL NULL int(10) unsigned 1.0000 mysql event time_zone char 64 64 latin1 latin1_swedish_ci char(64) @@ -415,6 +399,9 @@ NULL mysql general_log thread_id bigint NULL NULL NULL NULL bigint(21) unsigned NULL mysql general_log server_id int NULL NULL NULL NULL int(10) unsigned 3.0000 mysql general_log command_type varchar 64 192 utf8 utf8_general_ci varchar(64) 1.0000 mysql general_log argument mediumtext 16777215 16777215 utf8 utf8_general_ci mediumtext +3.0000 mysql global_priv Host char 60 180 utf8 utf8_bin char(60) +3.0000 mysql global_priv User char 80 240 utf8 utf8_bin char(80) +1.0000 mysql global_priv Priv longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext NULL mysql gtid_slave_pos domain_id int NULL NULL NULL NULL int(10) unsigned NULL mysql gtid_slave_pos sub_id bigint NULL NULL NULL NULL bigint(20) unsigned NULL mysql gtid_slave_pos server_id int NULL NULL NULL NULL int(10) unsigned @@ -433,26 +420,6 @@ NULL mysql help_topic help_category_id smallint NULL NULL NULL NULL smallint(5) 1.0000 mysql help_topic description text 65535 65535 utf8 utf8_general_ci text 1.0000 mysql help_topic example text 65535 65535 utf8 utf8_general_ci text 1.0000 mysql help_topic url text 65535 65535 utf8 utf8_general_ci text -3.0000 mysql host Host char 60 180 utf8 utf8_bin char(60) -3.0000 mysql host Db char 64 192 utf8 utf8_bin char(64) -3.0000 mysql host Select_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Insert_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Update_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Delete_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Create_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Drop_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Grant_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host References_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Index_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Alter_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Create_tmp_table_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Lock_tables_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Create_view_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Show_view_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Create_routine_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Alter_routine_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Execute_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql host Trigger_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') 3.0000 mysql index_stats db_name varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 mysql index_stats table_name varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 mysql index_stats index_name varchar 64 192 utf8 utf8_bin varchar(64) @@ -474,7 +441,7 @@ NULL mysql index_stats avg_frequency decimal NULL NULL NULL NULL decimal(12,4) 3.0000 mysql proc definer char 141 423 utf8 utf8_bin char(141) NULL mysql proc created timestamp NULL NULL NULL NULL timestamp NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp -3.0000 mysql proc sql_mode set 539 1617 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') +3.0000 mysql proc sql_mode set 561 1683 utf8 utf8_general_ci set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') 1.0000 mysql proc comment text 65535 65535 utf8 utf8_bin text 3.0000 mysql proc character_set_client char 32 96 utf8 utf8_bin char(32) 3.0000 mysql proc collation_connection char 32 96 utf8 utf8_bin char(32) @@ -549,50 +516,50 @@ NULL mysql time_zone_transition_type Is_DST tinyint NULL NULL NULL NULL tinyint( 3.0000 mysql time_zone_transition_type Abbreviation char 8 24 utf8 utf8_general_ci char(8) 3.0000 mysql user Host char 60 180 utf8 utf8_bin char(60) 3.0000 mysql user User char 80 240 utf8 utf8_bin char(80) -1.0000 mysql user Password char 41 41 latin1 latin1_bin char(41) -3.0000 mysql user Select_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Insert_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Update_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Delete_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Drop_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Reload_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Shutdown_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Process_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user File_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Grant_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user References_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Index_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Alter_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Show_db_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Super_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_tmp_table_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Lock_tables_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Execute_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Repl_slave_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Repl_client_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_view_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Show_view_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_routine_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Alter_routine_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_user_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Event_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Trigger_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Create_tablespace_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user Delete_history_priv enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user ssl_type enum 9 27 utf8 utf8_general_ci enum('','ANY','X509','SPECIFIED') -1.0000 mysql user ssl_cipher blob 65535 65535 NULL NULL blob -1.0000 mysql user x509_issuer blob 65535 65535 NULL NULL blob -1.0000 mysql user x509_subject blob 65535 65535 NULL NULL blob -NULL mysql user max_questions int NULL NULL NULL NULL int(11) unsigned -NULL mysql user max_updates int NULL NULL NULL NULL int(11) unsigned -NULL mysql user max_connections int NULL NULL NULL NULL int(11) unsigned -NULL mysql user max_user_connections int NULL NULL NULL NULL int(11) -1.0000 mysql user plugin char 64 64 latin1 latin1_swedish_ci char(64) -1.0000 mysql user authentication_string text 65535 65535 utf8 utf8_bin text -3.0000 mysql user password_expired enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user is_role enum 1 3 utf8 utf8_general_ci enum('N','Y') -3.0000 mysql user default_role char 80 240 utf8 utf8_bin char(80) +1.0000 mysql user Password longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql user Select_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Insert_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Update_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Delete_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Drop_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Reload_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Shutdown_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Process_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user File_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Grant_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user References_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Index_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Alter_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Show_db_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Super_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_tmp_table_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Lock_tables_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Execute_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Repl_slave_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Repl_client_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_view_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Show_view_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_routine_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Alter_routine_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_user_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Event_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Trigger_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Create_tablespace_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user Delete_history_priv varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user ssl_type varchar 9 9 latin1 latin1_swedish_ci varchar(9) +1.0000 mysql user ssl_cipher longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql user x509_issuer longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql user x509_subject longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +NULL mysql user max_questions bigint NULL NULL NULL NULL bigint(20) unsigned +NULL mysql user max_updates bigint NULL NULL NULL NULL bigint(20) unsigned +NULL mysql user max_connections bigint NULL NULL NULL NULL bigint(20) unsigned +NULL mysql user max_user_connections bigint NULL NULL NULL NULL bigint(21) +1.0000 mysql user plugin longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql user authentication_string longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext +1.0000 mysql user password_expired varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user is_role varchar 1 1 latin1 latin1_swedish_ci varchar(1) +1.0000 mysql user default_role longtext 4294967295 4294967295 utf8mb4 utf8mb4_bin longtext NULL mysql user max_statement_time decimal NULL NULL NULL NULL decimal(12,6) Warnings: Warning 1286 Unknown storage engine 'InnoDB' diff --git a/mysql-test/suite/funcs_1/r/is_key_column_usage.result b/mysql-test/suite/funcs_1/r/is_key_column_usage.result index 5c126a48419..efb67e32cee 100644 --- a/mysql-test/suite/funcs_1/r/is_key_column_usage.result +++ b/mysql-test/suite/funcs_1/r/is_key_column_usage.result @@ -90,6 +90,8 @@ def mysql PRIMARY def mysql db User def mysql PRIMARY def mysql event db def mysql PRIMARY def mysql event name def mysql PRIMARY def mysql func name +def mysql PRIMARY def mysql global_priv Host +def mysql PRIMARY def mysql global_priv User def mysql PRIMARY def mysql gtid_slave_pos domain_id def mysql PRIMARY def mysql gtid_slave_pos sub_id def mysql PRIMARY def mysql help_category help_category_id @@ -100,8 +102,6 @@ def mysql PRIMARY def mysql help_relation help_keyword_id def mysql PRIMARY def mysql help_relation help_topic_id def mysql PRIMARY def mysql help_topic help_topic_id def mysql name def mysql help_topic name -def mysql PRIMARY def mysql host Db -def mysql PRIMARY def mysql host Host def mysql PRIMARY def mysql index_stats db_name def mysql PRIMARY def mysql index_stats index_name def mysql PRIMARY def mysql index_stats prefix_arity @@ -144,8 +144,6 @@ def mysql PRIMARY def mysql time_zone_transition_type Time_zone_id def mysql PRIMARY def mysql time_zone_transition_type Transition_type_id def mysql commit_id def mysql transaction_registry commit_id def mysql PRIMARY def mysql transaction_registry transaction_id -def mysql PRIMARY def mysql user Host -def mysql PRIMARY def mysql user User ######################################################################################## # Testcase 3.2.7.2 + 3.2.7.3: INFORMATION_SCHEMA.KEY_COLUMN_USAGE accessible information ######################################################################################## diff --git a/mysql-test/suite/funcs_1/r/is_key_column_usage_embedded.result b/mysql-test/suite/funcs_1/r/is_key_column_usage_embedded.result index d41f7395483..cf67be8f7a0 100644 --- a/mysql-test/suite/funcs_1/r/is_key_column_usage_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_key_column_usage_embedded.result @@ -90,6 +90,8 @@ def mysql PRIMARY def mysql db User def mysql PRIMARY def mysql event db def mysql PRIMARY def mysql event name def mysql PRIMARY def mysql func name +def mysql PRIMARY def mysql global_priv Host +def mysql PRIMARY def mysql global_priv User def mysql PRIMARY def mysql gtid_slave_pos domain_id def mysql PRIMARY def mysql gtid_slave_pos sub_id def mysql PRIMARY def mysql help_category help_category_id @@ -100,8 +102,6 @@ def mysql PRIMARY def mysql help_relation help_keyword_id def mysql PRIMARY def mysql help_relation help_topic_id def mysql PRIMARY def mysql help_topic help_topic_id def mysql name def mysql help_topic name -def mysql PRIMARY def mysql host Db -def mysql PRIMARY def mysql host Host def mysql PRIMARY def mysql index_stats db_name def mysql PRIMARY def mysql index_stats index_name def mysql PRIMARY def mysql index_stats prefix_arity @@ -144,8 +144,6 @@ def mysql PRIMARY def mysql time_zone_transition_type Time_zone_id def mysql PRIMARY def mysql time_zone_transition_type Transition_type_id def mysql commit_id def mysql transaction_registry commit_id def mysql PRIMARY def mysql transaction_registry transaction_id -def mysql PRIMARY def mysql user Host -def mysql PRIMARY def mysql user User ######################################################################################## # Testcase 3.2.7.2 + 3.2.7.3: INFORMATION_SCHEMA.KEY_COLUMN_USAGE accessible information ######################################################################################## diff --git a/mysql-test/suite/funcs_1/r/is_routines_embedded.result b/mysql-test/suite/funcs_1/r/is_routines_embedded.result index 1739a0c15c8..ec375e9c5f6 100644 --- a/mysql-test/suite/funcs_1/r/is_routines_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_routines_embedded.result @@ -197,7 +197,7 @@ sp_6_408002_2 def db_datadict_2 sp_6_408002_2 PROCEDURE NULL NULL NULL NULL NUL SELECT * FROM db_datadict_2.res_6_408002_2; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost latin1 latin1_swedish_ci latin1_swedish_ci add_suppression def mtr add_suppression PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); FLUSH NO_WRITE_TO_BINLOG TABLE test_suppressions; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci -check_testcase def mtr check_testcase PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name NOT IN ('timestamp') AND variable_name not like "Last_IO_Err*" AND variable_name != 'INNODB_IBUF_MAX_SIZE' AND variable_name != 'INNODB_USE_NATIVE_AIO' AND variable_name != 'INNODB_BUFFER_POOL_LOAD_AT_STARTUP' AND variable_name not like 'GTID%POS' AND variable_name != 'GTID_BINLOG_STATE' ORDER BY variable_name; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY BINARY SCHEMA_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('mtr_wsrep_notify', 'wsrep_schema') ORDER BY BINARY SCHEMA_NAME; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' ORDER BY columns_in_mysql; SELECT * FROM INFORMATION_SCHEMA.EVENTS; SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME NOT IN ('gs_insert', 'ts_insert'); SELECT * FROM INFORMATION_SCHEMA.ROUTINES; SHOW STATUS LIKE 'slave_open_temp_tables'; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.plugin, mysql.proc, mysql.procs_priv, mysql.roles_mapping, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; SELECT * FROM INFORMATION_SCHEMA.PLUGINS; select * from information_schema.session_variables where variable_name = 'debug_sync'; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci +check_testcase def mtr check_testcase PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name NOT IN ('timestamp') AND variable_name not like "Last_IO_Err*" AND variable_name != 'INNODB_IBUF_MAX_SIZE' AND variable_name != 'INNODB_USE_NATIVE_AIO' AND variable_name != 'INNODB_BUFFER_POOL_LOAD_AT_STARTUP' AND variable_name not like 'GTID%POS' AND variable_name != 'GTID_BINLOG_STATE' ORDER BY variable_name; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY BINARY SCHEMA_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('mtr_wsrep_notify', 'wsrep_schema') ORDER BY BINARY SCHEMA_NAME; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' ORDER BY columns_in_mysql; SELECT * FROM INFORMATION_SCHEMA.EVENTS; SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME NOT IN ('gs_insert', 'ts_insert'); SELECT * FROM INFORMATION_SCHEMA.ROUTINES; SHOW STATUS LIKE 'slave_open_temp_tables'; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.plugin, mysql.proc, mysql.procs_priv, mysql.roles_mapping, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.global_priv; SELECT * FROM INFORMATION_SCHEMA.PLUGINS; select * from information_schema.session_variables where variable_name = 'debug_sync'; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci check_warnings def mtr check_warnings PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0, SQL_SAFE_UPDATES=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci connect testuser2, localhost, testuser2, , db_datadict; SELECT * FROM information_schema.routines; @@ -209,7 +209,7 @@ sp_6_408002_2 def db_datadict_2 sp_6_408002_2 PROCEDURE NULL NULL NULL NULL NUL SELECT * FROM db_datadict_2.res_6_408002_2; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost latin1 latin1_swedish_ci latin1_swedish_ci add_suppression def mtr add_suppression PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); FLUSH NO_WRITE_TO_BINLOG TABLE test_suppressions; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci -check_testcase def mtr check_testcase PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name NOT IN ('timestamp') AND variable_name not like "Last_IO_Err*" AND variable_name != 'INNODB_IBUF_MAX_SIZE' AND variable_name != 'INNODB_USE_NATIVE_AIO' AND variable_name != 'INNODB_BUFFER_POOL_LOAD_AT_STARTUP' AND variable_name not like 'GTID%POS' AND variable_name != 'GTID_BINLOG_STATE' ORDER BY variable_name; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY BINARY SCHEMA_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('mtr_wsrep_notify', 'wsrep_schema') ORDER BY BINARY SCHEMA_NAME; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' ORDER BY columns_in_mysql; SELECT * FROM INFORMATION_SCHEMA.EVENTS; SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME NOT IN ('gs_insert', 'ts_insert'); SELECT * FROM INFORMATION_SCHEMA.ROUTINES; SHOW STATUS LIKE 'slave_open_temp_tables'; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.plugin, mysql.proc, mysql.procs_priv, mysql.roles_mapping, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; SELECT * FROM INFORMATION_SCHEMA.PLUGINS; select * from information_schema.session_variables where variable_name = 'debug_sync'; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci +check_testcase def mtr check_testcase PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name NOT IN ('timestamp') AND variable_name not like "Last_IO_Err*" AND variable_name != 'INNODB_IBUF_MAX_SIZE' AND variable_name != 'INNODB_USE_NATIVE_AIO' AND variable_name != 'INNODB_BUFFER_POOL_LOAD_AT_STARTUP' AND variable_name not like 'GTID%POS' AND variable_name != 'GTID_BINLOG_STATE' ORDER BY variable_name; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY BINARY SCHEMA_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('mtr_wsrep_notify', 'wsrep_schema') ORDER BY BINARY SCHEMA_NAME; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' ORDER BY columns_in_mysql; SELECT * FROM INFORMATION_SCHEMA.EVENTS; SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME NOT IN ('gs_insert', 'ts_insert'); SELECT * FROM INFORMATION_SCHEMA.ROUTINES; SHOW STATUS LIKE 'slave_open_temp_tables'; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.plugin, mysql.proc, mysql.procs_priv, mysql.roles_mapping, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.global_priv; SELECT * FROM INFORMATION_SCHEMA.PLUGINS; select * from information_schema.session_variables where variable_name = 'debug_sync'; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci check_warnings def mtr check_warnings PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0, SQL_SAFE_UPDATES=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci connect testuser3, localhost, testuser3, , test; SELECT * FROM information_schema.routines; @@ -221,7 +221,7 @@ sp_6_408002_2 def db_datadict_2 sp_6_408002_2 PROCEDURE NULL NULL NULL NULL NUL SELECT * FROM db_datadict_2.res_6_408002_2; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost latin1 latin1_swedish_ci latin1_swedish_ci add_suppression def mtr add_suppression PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); FLUSH NO_WRITE_TO_BINLOG TABLE test_suppressions; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci -check_testcase def mtr check_testcase PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name NOT IN ('timestamp') AND variable_name not like "Last_IO_Err*" AND variable_name != 'INNODB_IBUF_MAX_SIZE' AND variable_name != 'INNODB_USE_NATIVE_AIO' AND variable_name != 'INNODB_BUFFER_POOL_LOAD_AT_STARTUP' AND variable_name not like 'GTID%POS' AND variable_name != 'GTID_BINLOG_STATE' ORDER BY variable_name; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY BINARY SCHEMA_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('mtr_wsrep_notify', 'wsrep_schema') ORDER BY BINARY SCHEMA_NAME; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' ORDER BY columns_in_mysql; SELECT * FROM INFORMATION_SCHEMA.EVENTS; SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME NOT IN ('gs_insert', 'ts_insert'); SELECT * FROM INFORMATION_SCHEMA.ROUTINES; SHOW STATUS LIKE 'slave_open_temp_tables'; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.plugin, mysql.proc, mysql.procs_priv, mysql.roles_mapping, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; SELECT * FROM INFORMATION_SCHEMA.PLUGINS; select * from information_schema.session_variables where variable_name = 'debug_sync'; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci +check_testcase def mtr check_testcase PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name NOT IN ('timestamp') AND variable_name not like "Last_IO_Err*" AND variable_name != 'INNODB_IBUF_MAX_SIZE' AND variable_name != 'INNODB_USE_NATIVE_AIO' AND variable_name != 'INNODB_BUFFER_POOL_LOAD_AT_STARTUP' AND variable_name not like 'GTID%POS' AND variable_name != 'GTID_BINLOG_STATE' ORDER BY variable_name; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA ORDER BY BINARY SCHEMA_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('mtr_wsrep_notify', 'wsrep_schema') ORDER BY BINARY SCHEMA_NAME; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' ORDER BY columns_in_mysql; SELECT * FROM INFORMATION_SCHEMA.EVENTS; SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME NOT IN ('gs_insert', 'ts_insert'); SELECT * FROM INFORMATION_SCHEMA.ROUTINES; SHOW STATUS LIKE 'slave_open_temp_tables'; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.plugin, mysql.proc, mysql.procs_priv, mysql.roles_mapping, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.global_priv; SELECT * FROM INFORMATION_SCHEMA.PLUGINS; select * from information_schema.session_variables where variable_name = 'debug_sync'; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci check_warnings def mtr check_warnings PROCEDURE NULL NULL NULL NULL NULL NULL NULL NULL SQL BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0, SQL_SAFE_UPDATES=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END NULL NULL SQL NO CONTAINS SQL NULL DEFINER YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss root@localhost utf8 utf8_general_ci latin1_swedish_ci connection default; disconnect testuser1; diff --git a/mysql-test/suite/funcs_1/r/is_statistics.result b/mysql-test/suite/funcs_1/r/is_statistics.result index 419eb0b4b4c..bacc106a1be 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics.result +++ b/mysql-test/suite/funcs_1/r/is_statistics.result @@ -101,6 +101,8 @@ def mysql db mysql User def mysql event mysql PRIMARY def mysql event mysql PRIMARY def mysql func mysql PRIMARY +def mysql global_priv mysql PRIMARY +def mysql global_priv mysql PRIMARY def mysql gtid_slave_pos mysql PRIMARY def mysql gtid_slave_pos mysql PRIMARY def mysql help_category mysql name @@ -111,8 +113,6 @@ def mysql help_relation mysql PRIMARY def mysql help_relation mysql PRIMARY def mysql help_topic mysql name def mysql help_topic mysql PRIMARY -def mysql host mysql PRIMARY -def mysql host mysql PRIMARY def mysql index_stats mysql PRIMARY def mysql index_stats mysql PRIMARY def mysql index_stats mysql PRIMARY @@ -150,8 +150,6 @@ def mysql time_zone_transition mysql PRIMARY def mysql time_zone_transition mysql PRIMARY def mysql time_zone_transition_type mysql PRIMARY def mysql time_zone_transition_type mysql PRIMARY -def mysql user mysql PRIMARY -def mysql user mysql PRIMARY Warnings: Warning 1286 Unknown storage engine 'InnoDB' Warning 1286 Unknown storage engine 'InnoDB' diff --git a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result index 31fb460f9aa..c01c456edf8 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_statistics_mysql.result @@ -22,6 +22,8 @@ def mysql db 1 mysql User 1 User A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 1 db A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 2 name A #CARD# NULL NULL BTREE def mysql func 0 mysql PRIMARY 1 name A #CARD# NULL NULL BTREE +def mysql global_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE +def mysql global_priv 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE def mysql gtid_slave_pos 0 mysql PRIMARY 1 domain_id A #CARD# NULL NULL BTREE def mysql gtid_slave_pos 0 mysql PRIMARY 2 sub_id A #CARD# NULL NULL BTREE def mysql help_category 0 mysql name 1 name A #CARD# NULL NULL BTREE @@ -32,8 +34,6 @@ def mysql help_relation 0 mysql PRIMARY 1 help_keyword_id A #CARD# NULL NULL BT def mysql help_relation 0 mysql PRIMARY 2 help_topic_id A #CARD# NULL NULL BTREE def mysql help_topic 0 mysql name 1 name A #CARD# NULL NULL BTREE def mysql help_topic 0 mysql PRIMARY 1 help_topic_id A #CARD# NULL NULL BTREE -def mysql host 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE -def mysql host 0 mysql PRIMARY 2 Db A #CARD# NULL NULL BTREE def mysql index_stats 0 mysql PRIMARY 1 db_name A #CARD# NULL NULL BTREE def mysql index_stats 0 mysql PRIMARY 2 table_name A #CARD# NULL NULL BTREE def mysql index_stats 0 mysql PRIMARY 3 index_name A #CARD# NULL NULL BTREE @@ -82,8 +82,6 @@ def mysql transaction_registry 0 mysql commit_id 1 commit_id A #CARD# NULL NULL def mysql transaction_registry 1 mysql commit_timestamp 1 commit_timestamp A #CARD# NULL NULL BTREE def mysql transaction_registry 1 mysql commit_timestamp 2 transaction_id A #CARD# NULL NULL BTREE def mysql transaction_registry 0 mysql PRIMARY 1 transaction_id A #CARD# NULL NULL BTREE -def mysql user 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE -def mysql user 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE connect testuser1,localhost,testuser1,,db_datadict; SELECT * FROM information_schema.statistics WHERE table_schema = 'mysql' diff --git a/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result index c81052321f8..b7bd3ec2e23 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_statistics_mysql_embedded.result @@ -22,6 +22,8 @@ def mysql db 1 mysql User 1 User A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 1 db A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 2 name A #CARD# NULL NULL BTREE def mysql func 0 mysql PRIMARY 1 name A #CARD# NULL NULL BTREE +def mysql global_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE +def mysql global_priv 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE def mysql gtid_slave_pos 0 mysql PRIMARY 1 domain_id A #CARD# NULL NULL BTREE def mysql gtid_slave_pos 0 mysql PRIMARY 2 sub_id A #CARD# NULL NULL BTREE def mysql help_category 0 mysql name 1 name A #CARD# NULL NULL BTREE @@ -32,8 +34,6 @@ def mysql help_relation 0 mysql PRIMARY 1 help_keyword_id A #CARD# NULL NULL BT def mysql help_relation 0 mysql PRIMARY 2 help_topic_id A #CARD# NULL NULL BTREE def mysql help_topic 0 mysql name 1 name A #CARD# NULL NULL BTREE def mysql help_topic 0 mysql PRIMARY 1 help_topic_id A #CARD# NULL NULL BTREE -def mysql host 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE -def mysql host 0 mysql PRIMARY 2 Db A #CARD# NULL NULL BTREE def mysql index_stats 0 mysql PRIMARY 1 db_name A #CARD# NULL NULL BTREE def mysql index_stats 0 mysql PRIMARY 2 table_name A #CARD# NULL NULL BTREE def mysql index_stats 0 mysql PRIMARY 3 index_name A #CARD# NULL NULL BTREE @@ -82,8 +82,6 @@ def mysql transaction_registry 0 mysql commit_id 1 commit_id A #CARD# NULL NULL def mysql transaction_registry 1 mysql commit_timestamp 1 commit_timestamp A #CARD# NULL NULL BTREE def mysql transaction_registry 1 mysql commit_timestamp 2 transaction_id A #CARD# NULL NULL BTREE def mysql transaction_registry 0 mysql PRIMARY 1 transaction_id A #CARD# NULL NULL BTREE -def mysql user 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE -def mysql user 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE connect testuser1,localhost,testuser1,,db_datadict; SELECT * FROM information_schema.statistics WHERE table_schema = 'mysql' @@ -104,6 +102,8 @@ def mysql db 1 mysql User 1 User A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 1 db A #CARD# NULL NULL BTREE def mysql event 0 mysql PRIMARY 2 name A #CARD# NULL NULL BTREE def mysql func 0 mysql PRIMARY 1 name A #CARD# NULL NULL BTREE +def mysql global_priv 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE +def mysql global_priv 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE def mysql gtid_slave_pos 0 mysql PRIMARY 1 domain_id A #CARD# NULL NULL BTREE def mysql gtid_slave_pos 0 mysql PRIMARY 2 sub_id A #CARD# NULL NULL BTREE def mysql help_category 0 mysql name 1 name A #CARD# NULL NULL BTREE @@ -114,8 +114,6 @@ def mysql help_relation 0 mysql PRIMARY 1 help_keyword_id A #CARD# NULL NULL BT def mysql help_relation 0 mysql PRIMARY 2 help_topic_id A #CARD# NULL NULL BTREE def mysql help_topic 0 mysql name 1 name A #CARD# NULL NULL BTREE def mysql help_topic 0 mysql PRIMARY 1 help_topic_id A #CARD# NULL NULL BTREE -def mysql host 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE -def mysql host 0 mysql PRIMARY 2 Db A #CARD# NULL NULL BTREE def mysql index_stats 0 mysql PRIMARY 1 db_name A #CARD# NULL NULL BTREE def mysql index_stats 0 mysql PRIMARY 2 table_name A #CARD# NULL NULL BTREE def mysql index_stats 0 mysql PRIMARY 3 index_name A #CARD# NULL NULL BTREE @@ -164,8 +162,6 @@ def mysql transaction_registry 0 mysql commit_id 1 commit_id A #CARD# NULL NULL def mysql transaction_registry 1 mysql commit_timestamp 1 commit_timestamp A #CARD# NULL NULL BTREE def mysql transaction_registry 1 mysql commit_timestamp 2 transaction_id A #CARD# NULL NULL BTREE def mysql transaction_registry 0 mysql PRIMARY 1 transaction_id A #CARD# NULL NULL BTREE -def mysql user 0 mysql PRIMARY 1 Host A #CARD# NULL NULL BTREE -def mysql user 0 mysql PRIMARY 2 User A #CARD# NULL NULL BTREE connection default; disconnect testuser1; DROP USER testuser1@localhost; diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints.result b/mysql-test/suite/funcs_1/r/is_table_constraints.result index d968d3b65de..bc0f9a724a1 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints.result @@ -63,6 +63,8 @@ def mysql PRIMARY mysql column_stats def mysql PRIMARY mysql db def mysql PRIMARY mysql event def mysql PRIMARY mysql func +def mysql PRIMARY mysql global_priv +def mysql Priv mysql global_priv def mysql PRIMARY mysql gtid_slave_pos def mysql name mysql help_category def mysql PRIMARY mysql help_category @@ -71,7 +73,6 @@ def mysql PRIMARY mysql help_keyword def mysql PRIMARY mysql help_relation def mysql name mysql help_topic def mysql PRIMARY mysql help_topic -def mysql PRIMARY mysql host def mysql PRIMARY mysql index_stats def mysql PRIMARY mysql innodb_index_stats def mysql PRIMARY mysql innodb_table_stats @@ -90,7 +91,6 @@ def mysql PRIMARY mysql time_zone_transition def mysql PRIMARY mysql time_zone_transition_type def mysql commit_id mysql transaction_registry def mysql PRIMARY mysql transaction_registry -def mysql PRIMARY mysql user ######################################################################################### # Testcase 3.2.7.2 + 3.2.7.3: INFORMATION_SCHEMA.TABLE_CONSTRAINTS accessible information ######################################################################################### diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result index b56c5115f16..d5da807388b 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql.result @@ -12,6 +12,8 @@ def mysql PRIMARY mysql column_stats PRIMARY KEY def mysql PRIMARY mysql db PRIMARY KEY def mysql PRIMARY mysql event PRIMARY KEY def mysql PRIMARY mysql func PRIMARY KEY +def mysql PRIMARY mysql global_priv PRIMARY KEY +def mysql Priv mysql global_priv CHECK def mysql PRIMARY mysql gtid_slave_pos PRIMARY KEY def mysql name mysql help_category UNIQUE def mysql PRIMARY mysql help_category PRIMARY KEY @@ -20,7 +22,6 @@ def mysql PRIMARY mysql help_keyword PRIMARY KEY def mysql PRIMARY mysql help_relation PRIMARY KEY def mysql name mysql help_topic UNIQUE def mysql PRIMARY mysql help_topic PRIMARY KEY -def mysql PRIMARY mysql host PRIMARY KEY def mysql PRIMARY mysql index_stats PRIMARY KEY def mysql PRIMARY mysql innodb_index_stats PRIMARY KEY def mysql PRIMARY mysql innodb_table_stats PRIMARY KEY @@ -39,7 +40,6 @@ def mysql PRIMARY mysql time_zone_transition PRIMARY KEY def mysql PRIMARY mysql time_zone_transition_type PRIMARY KEY def mysql commit_id mysql transaction_registry UNIQUE def mysql PRIMARY mysql transaction_registry PRIMARY KEY -def mysql PRIMARY mysql user PRIMARY KEY connect testuser1,localhost,testuser1,,db_datadict; SELECT * FROM information_schema.table_constraints WHERE table_schema = 'mysql' diff --git a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result index b40bc0ea0c7..0426877bc1c 100644 --- a/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_table_constraints_mysql_embedded.result @@ -12,6 +12,8 @@ def mysql PRIMARY mysql column_stats PRIMARY KEY def mysql PRIMARY mysql db PRIMARY KEY def mysql PRIMARY mysql event PRIMARY KEY def mysql PRIMARY mysql func PRIMARY KEY +def mysql PRIMARY mysql global_priv PRIMARY KEY +def mysql Priv mysql global_priv CHECK def mysql PRIMARY mysql gtid_slave_pos PRIMARY KEY def mysql name mysql help_category UNIQUE def mysql PRIMARY mysql help_category PRIMARY KEY @@ -20,7 +22,6 @@ def mysql PRIMARY mysql help_keyword PRIMARY KEY def mysql PRIMARY mysql help_relation PRIMARY KEY def mysql name mysql help_topic UNIQUE def mysql PRIMARY mysql help_topic PRIMARY KEY -def mysql PRIMARY mysql host PRIMARY KEY def mysql PRIMARY mysql index_stats PRIMARY KEY def mysql PRIMARY mysql innodb_index_stats PRIMARY KEY def mysql PRIMARY mysql innodb_table_stats PRIMARY KEY @@ -39,7 +40,6 @@ def mysql PRIMARY mysql time_zone_transition PRIMARY KEY def mysql PRIMARY mysql time_zone_transition_type PRIMARY KEY def mysql commit_id mysql transaction_registry UNIQUE def mysql PRIMARY mysql transaction_registry PRIMARY KEY -def mysql PRIMARY mysql user PRIMARY KEY connect testuser1,localhost,testuser1,,db_datadict; SELECT * FROM information_schema.table_constraints WHERE table_schema = 'mysql' @@ -50,6 +50,8 @@ def mysql PRIMARY mysql column_stats PRIMARY KEY def mysql PRIMARY mysql db PRIMARY KEY def mysql PRIMARY mysql event PRIMARY KEY def mysql PRIMARY mysql func PRIMARY KEY +def mysql PRIMARY mysql global_priv PRIMARY KEY +def mysql Priv mysql global_priv CHECK def mysql PRIMARY mysql gtid_slave_pos PRIMARY KEY def mysql name mysql help_category UNIQUE def mysql PRIMARY mysql help_category PRIMARY KEY @@ -58,7 +60,6 @@ def mysql PRIMARY mysql help_keyword PRIMARY KEY def mysql PRIMARY mysql help_relation PRIMARY KEY def mysql name mysql help_topic UNIQUE def mysql PRIMARY mysql help_topic PRIMARY KEY -def mysql PRIMARY mysql host PRIMARY KEY def mysql PRIMARY mysql index_stats PRIMARY KEY def mysql PRIMARY mysql innodb_index_stats PRIMARY KEY def mysql PRIMARY mysql innodb_table_stats PRIMARY KEY @@ -77,7 +78,6 @@ def mysql PRIMARY mysql time_zone_transition PRIMARY KEY def mysql PRIMARY mysql time_zone_transition_type PRIMARY KEY def mysql commit_id mysql transaction_registry UNIQUE def mysql PRIMARY mysql transaction_registry PRIMARY KEY -def mysql PRIMARY mysql user PRIMARY KEY connection default; disconnect testuser1; DROP USER testuser1@localhost; diff --git a/mysql-test/suite/funcs_1/r/is_tables_mysql.result b/mysql-test/suite/funcs_1/r/is_tables_mysql.result index 2ceed585699..be432e2422a 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_tables_mysql.result @@ -16,7 +16,7 @@ TABLE_NAME columns_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -66,7 +66,7 @@ TABLE_NAME db TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -116,7 +116,7 @@ TABLE_NAME func TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -162,11 +162,11 @@ user_comment General log Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME gtid_slave_pos +TABLE_NAME global_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA -VERSION 10 -ROW_FORMAT Fixed +VERSION 11 +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -177,17 +177,17 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION latin1_swedish_ci +TABLE_COLLATION utf8_bin CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment Replication slave GTID position +user_comment Users and global privileges Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_category +TABLE_NAME gtid_slave_pos TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 @@ -202,21 +202,21 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION utf8_general_ci +TABLE_COLLATION latin1_swedish_ci CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment help categories +user_comment Replication slave GTID position Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_keyword +TABLE_NAME help_category TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -233,15 +233,15 @@ CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment help keywords +user_comment help categories Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_relation +TABLE_NAME help_keyword TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -258,11 +258,11 @@ CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment keyword-topic relation +user_comment help keywords Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_topic +TABLE_NAME help_relation TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 @@ -283,15 +283,15 @@ CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment help topics +user_comment keyword-topic relation Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME host +TABLE_NAME help_topic TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -302,13 +302,13 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION utf8_bin +TABLE_COLLATION utf8_general_ci CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment Host privileges; Merged with database privileges +user_comment help topics Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql @@ -441,7 +441,7 @@ TABLE_NAME procs_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -466,7 +466,7 @@ TABLE_NAME proxies_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -491,7 +491,7 @@ TABLE_NAME roles_mapping TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -516,7 +516,7 @@ TABLE_NAME servers TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -566,7 +566,7 @@ TABLE_NAME tables_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -616,7 +616,7 @@ TABLE_NAME time_zone TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -641,7 +641,7 @@ TABLE_NAME time_zone_leap_second TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -666,7 +666,7 @@ TABLE_NAME time_zone_name TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -691,7 +691,7 @@ TABLE_NAME time_zone_transition TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -716,7 +716,7 @@ TABLE_NAME time_zone_transition_type TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -763,10 +763,10 @@ Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql TABLE_NAME user -TABLE_TYPE BASE TABLE -ENGINE MYISAM_OR_MARIA -VERSION 10 -ROW_FORMAT DYNAMIC_OR_PAGE +TABLE_TYPE VIEW +ENGINE NULL +VERSION NULL +ROW_FORMAT NULL TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -777,13 +777,13 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION utf8_bin +TABLE_COLLATION NULL CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# -TEMPORARY N -user_comment Users and global privileges +TEMPORARY NULL +user_comment VIEW Separator ----------------------------------------------------- DROP USER testuser1@localhost; CREATE USER testuser1@localhost; diff --git a/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result index 77fa6ddae1e..01381a5e746 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_tables_mysql_embedded.result @@ -16,7 +16,7 @@ TABLE_NAME columns_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -66,7 +66,7 @@ TABLE_NAME db TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -116,7 +116,7 @@ TABLE_NAME func TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -162,11 +162,11 @@ user_comment General log Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME gtid_slave_pos +TABLE_NAME global_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA -VERSION 10 -ROW_FORMAT Fixed +VERSION 11 +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -177,17 +177,17 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION latin1_swedish_ci +TABLE_COLLATION utf8_bin CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment Replication slave GTID position +user_comment Users and global privileges Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_category +TABLE_NAME gtid_slave_pos TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 @@ -202,21 +202,21 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION utf8_general_ci +TABLE_COLLATION latin1_swedish_ci CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment help categories +user_comment Replication slave GTID position Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_keyword +TABLE_NAME help_category TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -233,15 +233,15 @@ CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment help keywords +user_comment help categories Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_relation +TABLE_NAME help_keyword TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -258,11 +258,11 @@ CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment keyword-topic relation +user_comment help keywords Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_topic +TABLE_NAME help_relation TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 @@ -283,15 +283,15 @@ CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment help topics +user_comment keyword-topic relation Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME host +TABLE_NAME help_topic TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -302,13 +302,13 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION utf8_bin +TABLE_COLLATION utf8_general_ci CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment Host privileges; Merged with database privileges +user_comment help topics Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql @@ -441,7 +441,7 @@ TABLE_NAME procs_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -466,7 +466,7 @@ TABLE_NAME proxies_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -491,7 +491,7 @@ TABLE_NAME roles_mapping TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -516,7 +516,7 @@ TABLE_NAME servers TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -566,7 +566,7 @@ TABLE_NAME tables_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -616,7 +616,7 @@ TABLE_NAME time_zone TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -641,7 +641,7 @@ TABLE_NAME time_zone_leap_second TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -666,7 +666,7 @@ TABLE_NAME time_zone_name TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -691,7 +691,7 @@ TABLE_NAME time_zone_transition TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -716,7 +716,7 @@ TABLE_NAME time_zone_transition_type TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -763,10 +763,10 @@ Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql TABLE_NAME user -TABLE_TYPE BASE TABLE -ENGINE MYISAM_OR_MARIA -VERSION 10 -ROW_FORMAT DYNAMIC_OR_PAGE +TABLE_TYPE VIEW +ENGINE NULL +VERSION NULL +ROW_FORMAT NULL TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -777,13 +777,13 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION utf8_bin +TABLE_COLLATION NULL CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# -TEMPORARY N -user_comment Users and global privileges +TEMPORARY NULL +user_comment VIEW Separator ----------------------------------------------------- DROP USER testuser1@localhost; CREATE USER testuser1@localhost; @@ -805,7 +805,7 @@ TABLE_NAME columns_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -855,7 +855,7 @@ TABLE_NAME db TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -905,7 +905,7 @@ TABLE_NAME func TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -951,11 +951,11 @@ user_comment General log Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME gtid_slave_pos +TABLE_NAME global_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA -VERSION 10 -ROW_FORMAT Fixed +VERSION 11 +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -966,17 +966,17 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION latin1_swedish_ci +TABLE_COLLATION utf8_bin CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment Replication slave GTID position +user_comment Users and global privileges Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_category +TABLE_NAME gtid_slave_pos TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 @@ -991,21 +991,21 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION utf8_general_ci +TABLE_COLLATION latin1_swedish_ci CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment help categories +user_comment Replication slave GTID position Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_keyword +TABLE_NAME help_category TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1022,15 +1022,15 @@ CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment help keywords +user_comment help categories Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_relation +TABLE_NAME help_keyword TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1047,11 +1047,11 @@ CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment keyword-topic relation +user_comment help keywords Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME help_topic +TABLE_NAME help_relation TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 @@ -1072,15 +1072,15 @@ CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment help topics +user_comment keyword-topic relation Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql -TABLE_NAME host +TABLE_NAME help_topic TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1091,13 +1091,13 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION utf8_bin +TABLE_COLLATION utf8_general_ci CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# TEMPORARY N -user_comment Host privileges; Merged with database privileges +user_comment help topics Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql @@ -1230,7 +1230,7 @@ TABLE_NAME procs_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1255,7 +1255,7 @@ TABLE_NAME proxies_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1280,7 +1280,7 @@ TABLE_NAME roles_mapping TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1305,7 +1305,7 @@ TABLE_NAME servers TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1355,7 +1355,7 @@ TABLE_NAME tables_priv TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1405,7 +1405,7 @@ TABLE_NAME time_zone TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1430,7 +1430,7 @@ TABLE_NAME time_zone_leap_second TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1455,7 +1455,7 @@ TABLE_NAME time_zone_name TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1480,7 +1480,7 @@ TABLE_NAME time_zone_transition TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1505,7 +1505,7 @@ TABLE_NAME time_zone_transition_type TABLE_TYPE BASE TABLE ENGINE MYISAM_OR_MARIA VERSION 10 -ROW_FORMAT Fixed +ROW_FORMAT DYNAMIC_OR_PAGE TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1552,10 +1552,10 @@ Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA mysql TABLE_NAME user -TABLE_TYPE BASE TABLE -ENGINE MYISAM_OR_MARIA -VERSION 10 -ROW_FORMAT DYNAMIC_OR_PAGE +TABLE_TYPE VIEW +ENGINE NULL +VERSION NULL +ROW_FORMAT NULL TABLE_ROWS #TBLR# AVG_ROW_LENGTH #ARL# DATA_LENGTH #DL# @@ -1566,13 +1566,13 @@ AUTO_INCREMENT NULL CREATE_TIME #CRT# UPDATE_TIME #UT# CHECK_TIME #CT# -TABLE_COLLATION utf8_bin +TABLE_COLLATION NULL CHECKSUM NULL CREATE_OPTIONS #CO# TABLE_COMMENT #TC# MAX_INDEX_LENGTH #MIL# -TEMPORARY N -user_comment Users and global privileges +TEMPORARY NULL +user_comment VIEW Separator ----------------------------------------------------- connection default; disconnect testuser1; diff --git a/mysql-test/suite/funcs_1/r/is_user_privileges.result b/mysql-test/suite/funcs_1/r/is_user_privileges.result index cb619831baa..fe181fbf069 100644 --- a/mysql-test/suite/funcs_1/r/is_user_privileges.result +++ b/mysql-test/suite/funcs_1/r/is_user_privileges.result @@ -54,7 +54,6 @@ grantee table_catalog privilege_type # Testcases 3.2.16.2+3.2.16.3+3.2.16.4: INFORMATION_SCHEMA.USER_PRIVILEGES # accessible information ########################################################################## -DROP DATABASE IF EXISTS db_datadict; CREATE DATABASE db_datadict; DROP USER 'testuser1'@'localhost'; CREATE USER 'testuser1'@'localhost'; @@ -63,7 +62,7 @@ CREATE USER 'testuser2'@'localhost'; DROP USER 'testuser3'@'localhost'; CREATE USER 'testuser3'@'localhost'; GRANT SELECT ON db_datadict.* TO 'testuser1'@'localhost'; -GRANT SELECT ON mysql.user TO 'testuser1'@'localhost'; +GRANT SELECT ON mysql.global_priv TO 'testuser1'@'localhost'; GRANT INSERT ON *.* TO 'testuser2'@'localhost'; GRANT UPDATE ON *.* TO 'testuser2'@'localhost'; SELECT * FROM information_schema.user_privileges @@ -85,149 +84,29 @@ GRANTEE 'testuser3'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} # # Add GRANT OPTION db_datadict.* to testuser1; GRANT UPDATE ON db_datadict.* TO 'testuser1'@'localhost' WITH GRANT OPTION; @@ -250,149 +129,29 @@ GRANTEE 'testuser3'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} connect testuser1, localhost, testuser1, , db_datadict; SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -401,154 +160,34 @@ GRANTEE 'testuser1'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' GRANT SELECT, UPDATE ON `db_datadict`.* TO 'testuser1'@'localhost' WITH GRANT OPTION -GRANT SELECT ON `mysql`.`user` TO 'testuser1'@'localhost' +GRANT SELECT ON `mysql`.`global_priv` TO 'testuser1'@'localhost' # Now add SELECT on *.* to testuser1; connection default; @@ -574,149 +213,29 @@ GRANTEE 'testuser3'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv Y -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 1, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION; # # Here <SELECT YES> is shown correctly for testuser1; @@ -739,149 +258,29 @@ GRANTEE 'testuser3'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv Y -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv Y -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 1025, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} connection testuser1; SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -890,154 +289,34 @@ GRANTEE 'testuser1'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE SELECT IS_GRANTABLE YES -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv Y -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv Y -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 1025, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} SHOW GRANTS; Grants for testuser1@localhost GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION GRANT SELECT, UPDATE ON `db_datadict`.* TO 'testuser1'@'localhost' WITH GRANT OPTION -GRANT SELECT ON `mysql`.`user` TO 'testuser1'@'localhost' +GRANT SELECT ON `mysql`.`global_priv` TO 'testuser1'@'localhost' connect testuser2, localhost, testuser2, , db_datadict; SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -1050,9 +329,9 @@ GRANTEE 'testuser2'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE UPDATE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -ERROR 42000: SELECT command denied to user 'testuser2'@'localhost' for table 'user' +ERROR 42000: SELECT command denied to user 'testuser2'@'localhost' for table 'global_priv' SHOW GRANTS; Grants for testuser2@localhost GRANT INSERT, UPDATE ON *.* TO 'testuser2'@'localhost' @@ -1064,9 +343,9 @@ GRANTEE 'testuser3'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -ERROR 42000: SELECT command denied to user 'testuser3'@'localhost' for table 'user' +ERROR 42000: SELECT command denied to user 'testuser3'@'localhost' for table 'global_priv' SHOW GRANTS; Grants for testuser3@localhost GRANT USAGE ON *.* TO 'testuser3'@'localhost' @@ -1093,149 +372,29 @@ GRANTEE 'testuser3'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} connection testuser1; SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -1244,9 +403,9 @@ GRANTEE 'testuser1'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -ERROR 42000: SELECT command denied to user 'testuser1'@'localhost' for table 'user' +ERROR 42000: SELECT command denied to user 'testuser1'@'localhost' for table 'global_priv' SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' @@ -1259,19 +418,19 @@ GRANTEE 'testuser1'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -ERROR 42000: SELECT command denied to user 'testuser1'@'localhost' for table 'user' +ERROR 42000: SELECT command denied to user 'testuser1'@'localhost' for table 'global_priv' SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' CREATE TABLE db_datadict.tb_66 ( c1 TEXT ); ERROR 42000: CREATE command denied to user 'testuser1'@'localhost' for table 'tb_66' -# Add ALL on db_datadict.* (and select on mysql.user) to testuser1; +# Add ALL on db_datadict.* (and select on mysql.global_priv) to testuser1; connection default; GRANT ALL ON db_datadict.* TO 'testuser1'@'localhost' WITH GRANT OPTION; -GRANT SELECT ON mysql.user TO 'testuser1'@'localhost'; +GRANT SELECT ON mysql.global_priv TO 'testuser1'@'localhost'; SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' ORDER BY grantee, table_catalog, privilege_type; @@ -1291,149 +450,29 @@ GRANTEE 'testuser3'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} connection testuser1; SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -1442,154 +481,34 @@ GRANTEE 'testuser1'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' GRANT ALL PRIVILEGES ON `db_datadict`.* TO 'testuser1'@'localhost' WITH GRANT OPTION -GRANT SELECT ON `mysql`.`user` TO 'testuser1'@'localhost' +GRANT SELECT ON `mysql`.`global_priv` TO 'testuser1'@'localhost' CREATE TABLE db_datadict.tb_56 ( c1 TEXT ); ERROR 42000: CREATE command denied to user 'testuser1'@'localhost' for table 'tb_56' USE db_datadict; @@ -1600,154 +519,34 @@ GRANTEE 'testuser1'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' GRANT ALL PRIVILEGES ON `db_datadict`.* TO 'testuser1'@'localhost' WITH GRANT OPTION -GRANT SELECT ON `mysql`.`user` TO 'testuser1'@'localhost' +GRANT SELECT ON `mysql`.`global_priv` TO 'testuser1'@'localhost' CREATE TABLE tb_57 ( c1 TEXT ) ENGINE = <other_engine_type>; @@ -1773,149 +572,29 @@ GRANTEE 'testuser3'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -Host localhost -User testuser1 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser2 -Password -Select_priv N -Insert_priv Y -Update_priv Y -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 -Host localhost -User testuser3 -Password -Select_priv N -Insert_priv N -Update_priv N -Delete_priv N -Create_priv N -Drop_priv N -Reload_priv N -Shutdown_priv N -Process_priv N -File_priv N -Grant_priv N -References_priv N -Index_priv N -Alter_priv N -Show_db_priv N -Super_priv N -Create_tmp_table_priv N -Lock_tables_priv N -Execute_priv N -Repl_slave_priv N -Repl_client_priv N -Create_view_priv N -Show_view_priv N -Create_routine_priv N -Alter_routine_priv N -Create_user_priv N -Event_priv N -Trigger_priv N -Create_tablespace_priv N -Delete_history_priv N -ssl_type -ssl_cipher -x509_issuer -x509_subject -max_questions 0 -max_updates 0 -max_connections 0 -max_user_connections 0 -plugin -authentication_string -password_expired N -is_role N -default_role -max_statement_time 0.000000 +host localhost +user testuser1 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser2 +json_detailed(priv) { + "access": 6, + "plugin": "mysql_native_password", + "authentication_string": "" +} +host localhost +user testuser3 +json_detailed(priv) { + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "" +} connection testuser1; SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -1924,9 +603,9 @@ GRANTEE 'testuser1'@'localhost' TABLE_CATALOG def PRIVILEGE_TYPE USAGE IS_GRANTABLE NO -SELECT * FROM mysql.user +SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; -ERROR 42000: SELECT command denied to user 'testuser1'@'localhost' for table 'user' +ERROR 42000: SELECT command denied to user 'testuser1'@'localhost' for table 'global_priv' SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' diff --git a/mysql-test/suite/funcs_1/r/is_views.result b/mysql-test/suite/funcs_1/r/is_views.result index 62ec33c8340..e6a2715bbb3 100644 --- a/mysql-test/suite/funcs_1/r/is_views.result +++ b/mysql-test/suite/funcs_1/r/is_views.result @@ -70,6 +70,7 @@ ALGORITHM varchar(10) NO SELECT table_catalog, table_schema, table_name FROM information_schema.views WHERE table_catalog IS NOT NULL; table_catalog table_schema table_name +def mysql user ################################################################################ # Testcase 3.2.13.2 + 3.2.13.3: INFORMATION_SCHEMA.VIEWS accessible information ################################################################################ diff --git a/mysql-test/suite/funcs_1/r/is_views_embedded.result b/mysql-test/suite/funcs_1/r/is_views_embedded.result index c382370e892..cc6ade7daaf 100644 --- a/mysql-test/suite/funcs_1/r/is_views_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_views_embedded.result @@ -70,6 +70,7 @@ ALGORITHM varchar(10) NO SELECT table_catalog, table_schema, table_name FROM information_schema.views WHERE table_catalog IS NOT NULL; table_catalog table_schema table_name +def mysql user ################################################################################ # Testcase 3.2.13.2 + 3.2.13.3: INFORMATION_SCHEMA.VIEWS accessible information ################################################################################ diff --git a/mysql-test/suite/funcs_1/r/memory_func_view.result b/mysql-test/suite/funcs_1/r/memory_func_view.result index 85539fbf06f..88bfa702be8 100644 --- a/mysql-test/suite/funcs_1/r/memory_func_view.result +++ b/mysql-test/suite/funcs_1/r/memory_func_view.result @@ -3779,14 +3779,14 @@ WHERE select_id = 51 OR select_id IS NULL order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as time) AS `CAST(my_varbinary_1000 AS TIME)`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3796,14 +3796,14 @@ WHERE select_id = 51 OR select_id IS NULL) order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' DROP VIEW v1; @@ -3814,15 +3814,15 @@ my_binary_30, id FROM t1_values WHERE select_id = 50 OR select_id IS NULL order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL 2 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 22 Warnings: -Warning 1292 Truncated incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '-1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '1 17:58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' SHOW CREATE VIEW v1; @@ -3833,15 +3833,15 @@ WHERE v1.id IN (SELECT id FROM t1_values WHERE select_id = 50 OR select_id IS NULL) order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- +NULL +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- -00:00:01 -1 41:58:00 1 17:58 Warnings: -Warning 1292 Truncated incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '-1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '1 17:58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' DROP VIEW v1; @@ -3855,14 +3855,14 @@ WHERE select_id = 49 OR select_id IS NULL order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as time) AS `CAST(my_varchar_1000 AS TIME)`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3872,14 +3872,14 @@ WHERE select_id = 49 OR select_id IS NULL) order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' DROP VIEW v1; @@ -3891,14 +3891,14 @@ WHERE select_id = 48 OR select_id IS NULL order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_char_30` as time) AS `CAST(my_char_30 AS TIME)`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3908,14 +3908,14 @@ WHERE select_id = 48 OR select_id IS NULL) order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' DROP VIEW v1; diff --git a/mysql-test/suite/funcs_1/r/myisam_func_view.result b/mysql-test/suite/funcs_1/r/myisam_func_view.result index 85539fbf06f..88bfa702be8 100644 --- a/mysql-test/suite/funcs_1/r/myisam_func_view.result +++ b/mysql-test/suite/funcs_1/r/myisam_func_view.result @@ -3779,14 +3779,14 @@ WHERE select_id = 51 OR select_id IS NULL order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as time) AS `CAST(my_varbinary_1000 AS TIME)`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3796,14 +3796,14 @@ WHERE select_id = 51 OR select_id IS NULL) order by id; CAST(my_varbinary_1000 AS TIME) my_varbinary_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 23 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' DROP VIEW v1; @@ -3814,15 +3814,15 @@ my_binary_30, id FROM t1_values WHERE select_id = 50 OR select_id IS NULL order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL 2 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 22 Warnings: -Warning 1292 Truncated incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '-1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '1 17:58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' SHOW CREATE VIEW v1; @@ -3833,15 +3833,15 @@ WHERE v1.id IN (SELECT id FROM t1_values WHERE select_id = 50 OR select_id IS NULL) order by id; CAST(my_binary_30 AS TIME) my_binary_30 id NULL NULL 1 -00:00:00 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- +NULL +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- -00:00:01 -1 41:58:00 1 17:58 Warnings: -Warning 1292 Truncated incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '-1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Warning 1292 Truncated incorrect time value: '1 17:58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' DROP VIEW v1; @@ -3855,14 +3855,14 @@ WHERE select_id = 49 OR select_id IS NULL order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as time) AS `CAST(my_varchar_1000 AS TIME)`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3872,14 +3872,14 @@ WHERE select_id = 49 OR select_id IS NULL) order by id; CAST(my_varchar_1000 AS TIME) my_varchar_1000 id NULL NULL 1 NULL 2 -00:00:00 <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <---------1000 characters--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 21 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<---------1000 characters-------------------------------------------------------------------------------------------------------' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$-- ' DROP VIEW v1; @@ -3891,14 +3891,14 @@ WHERE select_id = 48 OR select_id IS NULL order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_char_30` as time) AS `CAST(my_char_30 AS TIME)`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3908,14 +3908,14 @@ WHERE select_id = 48 OR select_id IS NULL) order by id; CAST(my_char_30 AS TIME) my_char_30 id NULL NULL 1 NULL 2 -00:00:00 <--------30 characters-------> 3 --00:00:00 ---äÖüß@µ*$-- 4 +NULL <--------30 characters-------> 3 +NULL ---äÖüß@µ*$-- 4 -00:00:01 -1 5 41:58:00 1 17:58 20 Warnings: -Warning 1292 Truncated incorrect time value: '' -Warning 1292 Truncated incorrect time value: '<--------30 characters------->' -Warning 1292 Truncated incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' +Warning 1292 Incorrect time value: '' +Warning 1292 Incorrect time value: '<--------30 characters------->' +Warning 1292 Incorrect time value: ' ---\xC3\xA4\xC3\x96\xC3\xBC\xC3\x9F@\xC2\xB5*$--' DROP VIEW v1; diff --git a/mysql-test/suite/funcs_1/r/storedproc.result b/mysql-test/suite/funcs_1/r/storedproc.result index 9899456f7a8..81ed8405b7d 100644 --- a/mysql-test/suite/funcs_1/r/storedproc.result +++ b/mysql-test/suite/funcs_1/r/storedproc.result @@ -15723,6 +15723,7 @@ Testcase 4.3.7: DROP PROCEDURE IF EXISTS sp7; CREATE PROCEDURE sp7() BEGIN +DECLARE count INT DEFAULT 100; label1: loop set @dummystring = 'temp value'; if count > 10 then leave label1; @@ -15732,7 +15733,7 @@ END label1 loop; END// ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'iterate; END label1 loop; -END' at line 7 +END' at line 8 DROP PROCEDURE IF EXISTS sp7; CREATE PROCEDURE sp7() BEGIN diff --git a/mysql-test/suite/funcs_1/t/is_user_privileges.test b/mysql-test/suite/funcs_1/t/is_user_privileges.test index a61e9187d15..53d46b83f88 100644 --- a/mysql-test/suite/funcs_1/t/is_user_privileges.test +++ b/mysql-test/suite/funcs_1/t/is_user_privileges.test @@ -77,9 +77,6 @@ WHERE table_catalog IS NULL OR table_catalog <> 'def'; # 3.2.16.4: Ensure that the table does not show any information on any # privileges that are not user privileges for the current user. # ---disable_warnings -DROP DATABASE IF EXISTS db_datadict; ---enable_warnings CREATE DATABASE db_datadict; --error 0,ER_CANNOT_USER @@ -93,7 +90,7 @@ DROP USER 'testuser3'@'localhost'; CREATE USER 'testuser3'@'localhost'; GRANT SELECT ON db_datadict.* TO 'testuser1'@'localhost'; -GRANT SELECT ON mysql.user TO 'testuser1'@'localhost'; +GRANT SELECT ON mysql.global_priv TO 'testuser1'@'localhost'; GRANT INSERT ON *.* TO 'testuser2'@'localhost'; GRANT UPDATE ON *.* TO 'testuser2'@'localhost'; @@ -101,7 +98,7 @@ GRANT UPDATE ON *.* TO 'testuser2'@'localhost'; let $my_select1= SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' ORDER BY grantee, table_catalog, privilege_type; -let $my_select2= SELECT * FROM mysql.user +let $my_select2= SELECT host,user,json_detailed(priv) FROM mysql.global_priv WHERE user LIKE 'testuser%' ORDER BY host, user; let $my_show= SHOW GRANTS; --vertical_results @@ -203,10 +200,10 @@ eval $my_show; CREATE TABLE db_datadict.tb_66 ( c1 TEXT ); --echo ---echo # Add ALL on db_datadict.* (and select on mysql.user) to testuser1; +--echo # Add ALL on db_datadict.* (and select on mysql.global_priv) to testuser1; connection default; GRANT ALL ON db_datadict.* TO 'testuser1'@'localhost' WITH GRANT OPTION; -GRANT SELECT ON mysql.user TO 'testuser1'@'localhost'; +GRANT SELECT ON mysql.global_priv TO 'testuser1'@'localhost'; --vertical_results eval $my_select1; eval $my_select2; diff --git a/mysql-test/suite/funcs_1/t/row_count_func.test b/mysql-test/suite/funcs_1/t/row_count_func.test index 1694928b26c..3a76a6cac7c 100644 --- a/mysql-test/suite/funcs_1/t/row_count_func.test +++ b/mysql-test/suite/funcs_1/t/row_count_func.test @@ -14,6 +14,7 @@ INSERT INTO t1 VALUES (1), (2), (3); --echo --echo # -- Check 1. +--disable_warnings --enable_info --echo SELECT * FROM t1 INTO OUTFILE "MYSQL_TMP_DIR/bug21818.txt"; --disable_query_log # to avoid $MYSQL_TMP_DIR in query log @@ -34,6 +35,7 @@ SELECT a FROM t1 LIMIT 1 INTO @a; --echo SELECT ROW_COUNT(); +--enable_warnings --echo --echo # -- Check 3. diff --git a/mysql-test/suite/funcs_1/t/storedproc.test b/mysql-test/suite/funcs_1/t/storedproc.test index 98385d42b22..31786410a7b 100644 --- a/mysql-test/suite/funcs_1/t/storedproc.test +++ b/mysql-test/suite/funcs_1/t/storedproc.test @@ -18861,6 +18861,7 @@ delimiter //; --error ER_PARSE_ERROR CREATE PROCEDURE sp7() BEGIN + DECLARE count INT DEFAULT 100; label1: loop set @dummystring = 'temp value'; if count > 10 then leave label1; diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index d1d054b87ad..02f2b2e74e8 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -50,3 +50,12 @@ galera_pc_ignore_sb : MDEV-17357 Test failure on galera.galera_pc_ignore_sb MW-328A : MDEV-17847 Galera test failure on MW-328[A|B|C] MW-328B : MDEV-17847 Galera test failure on MW-328[A|B|C] MW-328C : MDEV-17847 Galera test failure on MW-328[A|B|C] +galera_autoinc_sst_xtrabackup : xtrabackup is deprecated +galera_ist_xtrabackup-v2 : xtrabackup is deprecated +galera_sst_xtrabackup-v2_data_dir : xtrabackup is deprecated +galera_sst_xtrabackup-v2_encrypt_with_key : xtrabackup is deprecated +galera_sst_xtrabackup-v2-options : xtrabackup is deprecated +galera_ist_innodb_flush_logs : xtrabackup is deprecated +galera_sst_xtrabackup-v2 : xtrabackup is deprecated +galera.galera_encrypt_tmp_files : Get error failed to enable encryption of temporary files +galera.galera_var_reject_queries : assertion in inline_mysql_socket_send diff --git a/mysql-test/suite/galera/r/galera_admin.result b/mysql-test/suite/galera/r/galera_admin.result index ed753247236..e52bf8ccca3 100644 --- a/mysql-test/suite/galera/r/galera_admin.result +++ b/mysql-test/suite/galera/r/galera_admin.result @@ -16,7 +16,9 @@ connection node_2; connection node_1; ANALYZE TABLE t1, t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK connection node_2; # OPTIMIZE test diff --git a/mysql-test/suite/galera/r/galera_flush_local.result b/mysql-test/suite/galera/r/galera_flush_local.result index a8e798a693d..a155a410a45 100644 --- a/mysql-test/suite/galera/r/galera_flush_local.result +++ b/mysql-test/suite/galera/r/galera_flush_local.result @@ -45,7 +45,9 @@ UNLOCK TABLES; FLUSH LOCAL TABLES t1; ANALYZE LOCAL TABLE t1, t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK OPTIMIZE LOCAL TABLE t1, t2; Table Op Msg_type Msg_text @@ -120,7 +122,9 @@ UNLOCK TABLES; FLUSH TABLES t1; ANALYZE TABLE t1, t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK OPTIMIZE TABLE t1, t2; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/galera/r/galera_many_indexes.result b/mysql-test/suite/galera/r/galera_many_indexes.result index 5691eef4c00..0d8688e3709 100644 --- a/mysql-test/suite/galera/r/galera_many_indexes.result +++ b/mysql-test/suite/galera/r/galera_many_indexes.result @@ -91,6 +91,7 @@ COUNT(*) = 1 INSERT INTO t1 VALUES (REPEAT('b', 767)); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK connection node_1; SELECT COUNT(*) = 2 FROM t1; @@ -98,6 +99,7 @@ COUNT(*) = 2 1 ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DELETE FROM t1 WHERE f1 = REPEAT('b', 767); connection node_1; diff --git a/mysql-test/suite/galera/r/grant.result b/mysql-test/suite/galera/r/grant.result index a2ca72ee8ec..bbcbb06a685 100644 --- a/mysql-test/suite/galera/r/grant.result +++ b/mysql-test/suite/galera/r/grant.result @@ -13,7 +13,7 @@ SET PASSWORD FOR 'user_6266'@'localhost' = PASSWORD('newpass'); # On node_2 connection node_2; SELECT user FROM mysql.user WHERE user='user_6266'; -user +User user_6266 DROP USER 'user_6266'@'localhost'; disconnect node_2; diff --git a/mysql-test/suite/galera/r/query_cache.result b/mysql-test/suite/galera/r/query_cache.result index a1d5d96d627..8592a68141c 100644 --- a/mysql-test/suite/galera/r/query_cache.result +++ b/mysql-test/suite/galera/r/query_cache.result @@ -1336,9 +1336,13 @@ show status like "Qcache_hits"; Variable_name Value Qcache_hits 12 select * from t1 into outfile "query_cache.out.file"; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select * from t1 into outfile "query_cache.out.file"; ERROR HY000: File 'query_cache.out.file' already exists select * from t1 limit 1 into dumpfile "query_cache.dump.file"; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/suite/gcol/r/gcol_bug20746926.result b/mysql-test/suite/gcol/r/gcol_bug20746926.result index 74fe76b3f1a..590caf02503 100644 --- a/mysql-test/suite/gcol/r/gcol_bug20746926.result +++ b/mysql-test/suite/gcol/r/gcol_bug20746926.result @@ -11,22 +11,22 @@ c timestamp generated always as ((a not in (b,b))) stored insert t1(a) values(7777777777); Warnings: Warning 1265 Data truncated for column 'a' at row 1 -Warning 1292 Incorrect datetime value: '0' +Warning 1292 Truncated incorrect datetime value: '0' show warnings; Level Code Message Warning 1265 Data truncated for column 'a' at row 1 -Warning 1292 Incorrect datetime value: '0' +Warning 1292 Truncated incorrect datetime value: '0' disconnect con1; connect con2,localhost,root,,; set sql_mode=''; insert t1(a) values(6666666666); Warnings: Warning 1265 Data truncated for column 'a' at row 1 -Warning 1292 Incorrect datetime value: '0' +Warning 1292 Truncated incorrect datetime value: '0' show warnings; Level Code Message Warning 1265 Data truncated for column 'a' at row 1 -Warning 1292 Incorrect datetime value: '0' +Warning 1292 Truncated incorrect datetime value: '0' drop table t1; disconnect con2; connection default; diff --git a/mysql-test/suite/gcol/r/gcol_bugfixes.result b/mysql-test/suite/gcol/r/gcol_bugfixes.result index 9aff30aabc9..3d19f718287 100644 --- a/mysql-test/suite/gcol/r/gcol_bugfixes.result +++ b/mysql-test/suite/gcol/r/gcol_bugfixes.result @@ -231,6 +231,7 @@ Note 1265 Data truncated for column 'col_time_key' at row 5 Note 1265 Data truncated for column 'col_time_key' at row 6 ANALYZE TABLE c; Table Op Msg_type Msg_text +test.c analyze status Engine-independent statistics collected test.c analyze status OK explain SELECT COUNT(DISTINCT col_varchar_key) AS x FROM c @@ -327,6 +328,7 @@ ALTER TABLE t1 ADD COLUMN c INT GENERATED ALWAYS AS (b + 1) VIRTUAL; ALTER TABLE t1 ADD INDEX( c ); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # Make sure the index is correct. That's kinda important. EXPLAIN diff --git a/mysql-test/suite/gcol/r/gcol_keys_innodb.result b/mysql-test/suite/gcol/r/gcol_keys_innodb.result index de88b745292..2ea0a256df7 100644 --- a/mysql-test/suite/gcol/r/gcol_keys_innodb.result +++ b/mysql-test/suite/gcol/r/gcol_keys_innodb.result @@ -348,6 +348,7 @@ CREATE TABLE t1 (f1 int, gc int AS (f1 + 1) STORED, UNIQUE(gc)); INSERT INTO t1(f1) VALUES (1),(2),(0),(9),(3),(4),(8),(7),(5),(6); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # Should use index SELECT * FROM t1 WHERE f1 + 1 > 7; @@ -455,6 +456,7 @@ INSERT INTO t1(f1) VALUES (070707),(080808); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM t1 WHERE f1 + 1 > 070707; f1 gc_int gc_date @@ -489,6 +491,7 @@ KEY col_int_gc_key(col_int_gc_key) INSERT INTO t1 ( col_int_key) VALUES (7); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT table1.col_int_key + 1 AS field1, table2.col_int_key AS field2 FROM (t1 AS table1 JOIN t1 AS table2 ON (table2.pk = table1.pk)) @@ -727,6 +730,7 @@ INDEX(gc_case)); INSERT INTO t (a, b) VALUES (0, 0), (0, 1), (1, 0), (1, 1); ANALYZE TABLE t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK EXPLAIN SELECT a, b FROM t WHERE (a AND b) = 1; id select_type table type possible_keys key key_len ref rows Extra @@ -809,7 +813,9 @@ CREATE TABLE t2 (b INTEGER); INSERT INTO t2 VALUES (1); ANALYZE TABLE t1, t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK # Used to choose the index on a1 and get wrong results. EXPLAIN SELECT * FROM t1 WHERE (a2 AND a2) = 0; diff --git a/mysql-test/suite/gcol/r/gcol_keys_myisam.result b/mysql-test/suite/gcol/r/gcol_keys_myisam.result index dcbba1f70c1..8ef6736388a 100644 --- a/mysql-test/suite/gcol/r/gcol_keys_myisam.result +++ b/mysql-test/suite/gcol/r/gcol_keys_myisam.result @@ -348,6 +348,7 @@ CREATE TABLE t1 (f1 int, gc int AS (f1 + 1) STORED, UNIQUE(gc)); INSERT INTO t1(f1) VALUES (1),(2),(0),(9),(3),(4),(8),(7),(5),(6); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # Should use index SELECT * FROM t1 WHERE f1 + 1 > 7; @@ -455,6 +456,7 @@ INSERT INTO t1(f1) VALUES (070707),(080808); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM t1 WHERE f1 + 1 > 070707; f1 gc_int gc_date @@ -489,6 +491,7 @@ KEY col_int_gc_key(col_int_gc_key) INSERT INTO t1 ( col_int_key) VALUES (7); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT table1.col_int_key + 1 AS field1, table2.col_int_key AS field2 FROM (t1 AS table1 JOIN t1 AS table2 ON (table2.pk = table1.pk)) @@ -727,6 +730,7 @@ INDEX(gc_case)); INSERT INTO t (a, b) VALUES (0, 0), (0, 1), (1, 0), (1, 1); ANALYZE TABLE t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK EXPLAIN SELECT a, b FROM t WHERE (a AND b) = 1; id select_type table type possible_keys key key_len ref rows Extra @@ -809,7 +813,9 @@ CREATE TABLE t2 (b INTEGER); INSERT INTO t2 VALUES (1); ANALYZE TABLE t1, t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK # Used to choose the index on a1 and get wrong results. EXPLAIN SELECT * FROM t1 WHERE (a2 AND a2) = 0; diff --git a/mysql-test/suite/gcol/r/gcol_select_innodb.result b/mysql-test/suite/gcol/r/gcol_select_innodb.result index bc9bddad690..983e1fb2533 100644 --- a/mysql-test/suite/gcol/r/gcol_select_innodb.result +++ b/mysql-test/suite/gcol/r/gcol_select_innodb.result @@ -20,8 +20,11 @@ c int generated always as (-a) stored unique); insert into t3 (a) values (2),(1),(3); analyze table t1,t2,t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK # select_type=SIMPLE, type=system select * from t2; @@ -676,9 +679,13 @@ INSERT INTO t4 VALUES (1, 'j'), (2, 'c'), (0, 'a'); ANALYZE TABLE t1, t2, t3, t4; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK +test.t4 analyze status Engine-independent statistics collected test.t4 analyze status OK EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1 FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2 diff --git a/mysql-test/suite/gcol/r/gcol_select_myisam.result b/mysql-test/suite/gcol/r/gcol_select_myisam.result index d0fe7fbd0d4..e823458483d 100644 --- a/mysql-test/suite/gcol/r/gcol_select_myisam.result +++ b/mysql-test/suite/gcol/r/gcol_select_myisam.result @@ -20,8 +20,11 @@ c int generated always as (-a) stored unique); insert into t3 (a) values (2),(1),(3); analyze table t1,t2,t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK # select_type=SIMPLE, type=system select * from t2; @@ -853,7 +856,9 @@ Warnings: Note 1265 Data truncated for column 'col_time_key' at row 1 ANALYZE TABLE a, c; Table Op Msg_type Msg_text +test.a analyze status Engine-independent statistics collected test.a analyze status OK +test.c analyze status Engine-independent statistics collected test.c analyze status OK EXPLAIN SELECT @@ -931,7 +936,9 @@ col_varchar_nokey (5, 'b'),(8,'m'),(7, 'j'),(2, 'v'); ANALYZE TABLE c, cc; Table Op Msg_type Msg_text +test.c analyze status Engine-independent statistics collected test.c analyze status OK +test.cc analyze status Engine-independent statistics collected test.cc analyze status OK EXPLAIN SELECT alias2 . col_varchar_key AS field1 @@ -1298,9 +1305,13 @@ INSERT INTO t4 VALUES (1, 'j'), (2, 'c'), (0, 'a'); ANALYZE TABLE t1, t2, t3, t4; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK +test.t4 analyze status Engine-independent statistics collected test.t4 analyze status OK EXPLAIN SELECT /*+ NO_SEMIJOIN(@subq1) */ t1.c1, t2.i1 FROM t1 STRAIGHT_JOIN t3 STRAIGHT_JOIN t2 diff --git a/mysql-test/suite/gcol/r/gcol_view_innodb.result b/mysql-test/suite/gcol/r/gcol_view_innodb.result index ec82c792493..b23dbfc4bff 100644 --- a/mysql-test/suite/gcol/r/gcol_view_innodb.result +++ b/mysql-test/suite/gcol/r/gcol_view_innodb.result @@ -5,6 +5,7 @@ c int generated always as (-a) stored); insert into t1 (a) values (1), (1), (2), (2), (3); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK create view v1 (d,e) as select abs(b), abs(c) from t1; select d,e from v1; diff --git a/mysql-test/suite/gcol/r/gcol_view_myisam.result b/mysql-test/suite/gcol/r/gcol_view_myisam.result index 13cb74ebcb5..264bd904c30 100644 --- a/mysql-test/suite/gcol/r/gcol_view_myisam.result +++ b/mysql-test/suite/gcol/r/gcol_view_myisam.result @@ -5,6 +5,7 @@ c int generated always as (-a) stored); insert into t1 (a) values (1), (1), (2), (2), (3); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK create view v1 (d,e) as select abs(b), abs(c) from t1; select d,e from v1; diff --git a/mysql-test/suite/gcol/r/innodb_virtual_rebuild.result b/mysql-test/suite/gcol/r/innodb_virtual_rebuild.result index 2e35698e47e..35f37034721 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_rebuild.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_rebuild.result @@ -7,31 +7,31 @@ ROW_FORMAT=REDUNDANT; INSERT INTO t4 SET i=1; ALTER TABLE t4 ADD INDEX(v), LOCK=NONE; ALTER TABLE t4 ADD COLUMN k INT, LOCK=NONE; -ALTER TABLE t4 DROP k, LOCK=NONE; ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED -ALTER TABLE t4 DROP INDEX v, LOCK=NONE; ALTER TABLE t4 DROP k, LOCK=NONE; +ERROR 42000: Can't DROP COLUMN `k`; check that it exists +ALTER TABLE t4 DROP INDEX v, LOCK=NONE; INSERT INTO t3 SET i=1; ALTER TABLE t3 ADD INDEX(v), LOCK=NONE; ALTER TABLE t3 ADD COLUMN k INT, LOCK=NONE; -ALTER TABLE t3 DROP k, LOCK=NONE; ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED -ALTER TABLE t3 DROP INDEX v, LOCK=NONE; ALTER TABLE t3 DROP k, LOCK=NONE; +ERROR 42000: Can't DROP COLUMN `k`; check that it exists +ALTER TABLE t3 DROP INDEX v, LOCK=NONE; INSERT INTO t2 SET i=1; ALTER TABLE t2 ADD INDEX(v), LOCK=NONE; ALTER TABLE t2 ADD COLUMN k INT, LOCK=NONE; -ALTER TABLE t2 DROP k, LOCK=NONE; ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED -ALTER TABLE t2 DROP INDEX v, LOCK=NONE; ALTER TABLE t2 DROP k, LOCK=NONE; +ERROR 42000: Can't DROP COLUMN `k`; check that it exists +ALTER TABLE t2 DROP INDEX v, LOCK=NONE; INSERT INTO t1 SET i=1; ALTER TABLE t1 ADD INDEX(v), LOCK=NONE; ALTER TABLE t1 ADD COLUMN k INT, LOCK=NONE; -ALTER TABLE t1 DROP k, LOCK=NONE; ERROR 0A000: LOCK=NONE is not supported. Reason: online rebuild with indexed virtual columns. Try LOCK=SHARED -ALTER TABLE t1 DROP INDEX v, LOCK=NONE; ALTER TABLE t1 DROP k, LOCK=NONE; +ERROR 42000: Can't DROP COLUMN `k`; check that it exists +ALTER TABLE t1 DROP INDEX v, LOCK=NONE; connect ddl,localhost,root,,test; connection default; connection ddl; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_rebuild.test b/mysql-test/suite/gcol/t/innodb_virtual_rebuild.test index 37ab82c46db..fe4f5e307b3 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_rebuild.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_rebuild.test @@ -14,11 +14,12 @@ while ($n) { eval INSERT INTO t$n SET i=1; eval ALTER TABLE t$n ADD INDEX(v), LOCK=NONE; -eval ALTER TABLE t$n ADD COLUMN k INT, LOCK=NONE; +# MDEV-17468 FIXME: Fix this, and remove the 2 --error below. --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +eval ALTER TABLE t$n ADD COLUMN k INT, LOCK=NONE; +--error ER_CANT_DROP_FIELD_OR_KEY eval ALTER TABLE t$n DROP k, LOCK=NONE; eval ALTER TABLE t$n DROP INDEX v, LOCK=NONE; -eval ALTER TABLE t$n DROP k, LOCK=NONE; dec $n; } diff --git a/mysql-test/suite/handler/aria.result b/mysql-test/suite/handler/aria.result index 6b02ac9b085..1896e30f7d5 100644 --- a/mysql-test/suite/handler/aria.result +++ b/mysql-test/suite/handler/aria.result @@ -808,6 +808,7 @@ ERROR 42S02: Unknown table 't1' in HANDLER handler t1 open; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date handler t1 read next; ERROR 42S02: Unknown table 't1' in HANDLER @@ -927,6 +928,7 @@ handler t1 open; lock tables t1 write; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date unlock tables; handler t1 read next; @@ -1483,7 +1485,7 @@ handler t2 open; flush tables with read lock; handler t1 read next; a b -1 1 +2 1 select a from t3; a 1 @@ -1697,6 +1699,8 @@ BEGIN SELECT 1 FROM t2 INTO @a; RETURN 1; END| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT f1(); ERROR 42S02: Table 'test.t2' doesn't exist CREATE TABLE t1(a INT); diff --git a/mysql-test/suite/handler/heap.result b/mysql-test/suite/handler/heap.result index 9679b48a367..32d06b79604 100644 --- a/mysql-test/suite/handler/heap.result +++ b/mysql-test/suite/handler/heap.result @@ -808,7 +808,7 @@ ERROR 42S02: Unknown table 't1' in HANDLER handler t1 open; analyze table t1; Table Op Msg_type Msg_text -test.t1 analyze note The storage engine for the table doesn't support analyze +test.t1 analyze status Operation failed handler t1 read next; ERROR 42S02: Unknown table 't1' in HANDLER # @@ -927,6 +927,7 @@ handler t1 open; lock tables t1 write; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze note The storage engine for the table doesn't support analyze unlock tables; handler t1 read next; @@ -1483,7 +1484,7 @@ handler t2 open; flush tables with read lock; handler t1 read next; a b -1 1 +2 1 select a from t3; a 1 @@ -1697,6 +1698,8 @@ BEGIN SELECT 1 FROM t2 INTO @a; RETURN 1; END| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT f1(); ERROR 42S02: Table 'test.t2' doesn't exist CREATE TABLE t1(a INT); diff --git a/mysql-test/suite/handler/innodb.result b/mysql-test/suite/handler/innodb.result index 80e8ed679a9..a1b2b318911 100644 --- a/mysql-test/suite/handler/innodb.result +++ b/mysql-test/suite/handler/innodb.result @@ -810,6 +810,7 @@ ERROR 42S02: Unknown table 't1' in HANDLER handler t1 open; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK handler t1 read next; ERROR 42S02: Unknown table 't1' in HANDLER @@ -930,6 +931,7 @@ handler t1 open; lock tables t1 write; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK unlock tables; handler t1 read next; @@ -1487,7 +1489,7 @@ handler t2 open; flush tables with read lock; handler t1 read next; a b -1 1 +2 1 select a from t3; a 1 @@ -1701,6 +1703,8 @@ BEGIN SELECT 1 FROM t2 INTO @a; RETURN 1; END| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT f1(); ERROR 42S02: Table 'test.t2' doesn't exist CREATE TABLE t1(a INT); diff --git a/mysql-test/suite/handler/interface.result b/mysql-test/suite/handler/interface.result index c4a169be185..8c39b15b6c9 100644 --- a/mysql-test/suite/handler/interface.result +++ b/mysql-test/suite/handler/interface.result @@ -175,6 +175,7 @@ c1 connect flush,localhost,root,,; connection flush; flush tables; +flush table t1; connect waiter,localhost,root,,; connection waiter; connection default; @@ -258,10 +259,11 @@ a b flush tables; handler t1 read a next; a b -0 a +2 c +flush tables t1; handler t1 read a next; a b -1 b +0 a flush tables with read lock; handler t1 read a next; a b diff --git a/mysql-test/suite/handler/interface.test b/mysql-test/suite/handler/interface.test index 15853dfdbf5..0ecdbf9c5cf 100644 --- a/mysql-test/suite/handler/interface.test +++ b/mysql-test/suite/handler/interface.test @@ -179,12 +179,13 @@ handler t1 open; handler t1 read first; connect (flush,localhost,root,,); connection flush; -send flush tables; +flush tables; +send flush table t1; connect (waiter,localhost,root,,); connection waiter; let $wait_condition= select count(*) = 1 from information_schema.processlist - where state = "Waiting for table flush"; + where state = "Waiting for table metadata lock"; --source include/wait_condition.inc connection default; handler t2 open; @@ -282,6 +283,7 @@ handler t1 read a first; handler t1 read a next; flush tables; handler t1 read a next; +flush tables t1; handler t1 read a next; flush tables with read lock; handler t1 read a next; diff --git a/mysql-test/suite/handler/myisam.result b/mysql-test/suite/handler/myisam.result index 90e1767a1f3..2c5f8c3bfde 100644 --- a/mysql-test/suite/handler/myisam.result +++ b/mysql-test/suite/handler/myisam.result @@ -808,6 +808,7 @@ ERROR 42S02: Unknown table 't1' in HANDLER handler t1 open; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date handler t1 read next; ERROR 42S02: Unknown table 't1' in HANDLER @@ -927,6 +928,7 @@ handler t1 open; lock tables t1 write; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date unlock tables; handler t1 read next; @@ -1483,7 +1485,7 @@ handler t2 open; flush tables with read lock; handler t1 read next; a b -1 1 +2 1 select a from t3; a 1 @@ -1697,6 +1699,8 @@ BEGIN SELECT 1 FROM t2 INTO @a; RETURN 1; END| +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT f1(); ERROR 42S02: Table 'test.t2' doesn't exist CREATE TABLE t1(a INT); diff --git a/mysql-test/suite/innodb/r/alter_table.result b/mysql-test/suite/innodb/r/alter_table.result index 8a0717aa677..3a765a61dd2 100644 --- a/mysql-test/suite/innodb/r/alter_table.result +++ b/mysql-test/suite/innodb/r/alter_table.result @@ -22,3 +22,18 @@ alter table t1 change column id2 id4 varchar(100) not null; select * from t1 where id4 like 'a'; id1 id4 id3 drop table t1; +create table t1 (a int) transactional=1 engine=aria; +create table t2 (a int) transactional=1 engine=innodb; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 TRANSACTIONAL=1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 TRANSACTIONAL=1 +alter table t1 engine=innodb; +alter table t1 add column b int; +drop table t1,t2; diff --git a/mysql-test/suite/innodb/r/analyze_table.result b/mysql-test/suite/innodb/r/analyze_table.result index a5c25289ad1..57095b725eb 100644 --- a/mysql-test/suite/innodb/r/analyze_table.result +++ b/mysql-test/suite/innodb/r/analyze_table.result @@ -19,6 +19,7 @@ COUNT(*) SET GLOBAL innodb_stats_persistent_sample_pages=2000; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; DROP PROCEDURE populate_t1; diff --git a/mysql-test/suite/innodb/r/doublewrite.result b/mysql-test/suite/innodb/r/doublewrite.result index 61c81ee9dff..377f804a836 100644 --- a/mysql-test/suite/innodb/r/doublewrite.result +++ b/mysql-test/suite/innodb/r/doublewrite.result @@ -26,6 +26,8 @@ commit work; # tablespace is full of zeroes. select space from information_schema.innodb_sys_tables where name = 'test/t1' into @space_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Ensure that dirty pages of table t1 is flushed. flush tables t1 for export; unlock tables; @@ -57,6 +59,8 @@ f1 f2 # tablespace is corrupted. select space from information_schema.innodb_sys_tables where name = 'test/t1' into @space_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Ensure that dirty pages of table t1 is flushed. flush tables t1 for export; unlock tables; @@ -85,6 +89,8 @@ f1 f2 # tablespace is full of zeroes. select space from information_schema.innodb_sys_tables where name = 'test/t1' into @space_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Ensure that dirty pages of table t1 is flushed. flush tables t1 for export; unlock tables; @@ -113,6 +119,8 @@ f1 f2 # tablespace is corrupted. select space from information_schema.innodb_sys_tables where name = 'test/t1' into @space_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # Ensure that dirty pages of table t1 is flushed. flush tables t1 for export; unlock tables; diff --git a/mysql-test/suite/innodb/r/innodb-alter-table.result b/mysql-test/suite/innodb/r/innodb-alter-table.result index 0d5afab6bae..ad3b2cb04af 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-table.result +++ b/mysql-test/suite/innodb/r/innodb-alter-table.result @@ -218,6 +218,7 @@ t CREATE TABLE `t` ( PARTITION `p99991231` VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) analyze table t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK select count(*) from t where d ='2017-09-15'; count(*) diff --git a/mysql-test/suite/innodb/r/innodb-alter.result b/mysql-test/suite/innodb/r/innodb-alter.result index e9f827c004e..7b0a43297e0 100644 --- a/mysql-test/suite/innodb/r/innodb-alter.result +++ b/mysql-test/suite/innodb/r/innodb-alter.result @@ -449,6 +449,7 @@ FULLTEXT INDEX(t) ALTER TABLE tu ADD COLUMN c CHAR(1) NOT NULL FIRST, LOCK=NONE; ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED ALTER TABLE tu ADD COLUMN c CHAR(1) NOT NULL, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED DROP TABLE tu; CREATE TABLE tv ( pk INT PRIMARY KEY, FTS_DOC_ID BIGINT UNSIGNED NOT NULL, t TEXT, @@ -458,6 +459,7 @@ FULLTEXT INDEX(t) ALTER TABLE tv ADD COLUMN c CHAR(1) NOT NULL FIRST, LOCK=NONE; ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED ALTER TABLE tv ADD COLUMN c CHAR(1) NOT NULL, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED DROP TABLE tv; ALTER TABLE t1o CHANGE c1 dB_row_Id INT, ALGORITHM=COPY; ERROR 42000: Incorrect column name 'dB_row_Id' diff --git a/mysql-test/suite/innodb/r/innodb-index-online.result b/mysql-test/suite/innodb/r/innodb-index-online.result index c646645ba7a..07b2c0dfaac 100644 --- a/mysql-test/suite/innodb/r/innodb-index-online.result +++ b/mysql-test/suite/innodb/r/innodb-index-online.result @@ -123,6 +123,8 @@ ERROR 23000: Duplicate entry '4' for key 'c2' ALTER TABLE t1 STATS_PERSISTENT=1; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'c3' test.t1 analyze status OK UPDATE mysql.innodb_index_stats SET stat_value = 5 WHERE database_name = 'test' AND table_name= 't1' AND index_name = 'PRIMARY' @@ -141,6 +143,7 @@ ALTER TABLE t1_c2_stats ENGINE=INNODB; DROP INDEX c2 ON t1; ANALYZE TABLE t1_c2_stats; Table Op Msg_type Msg_text +test.t1_c2_stats analyze status Engine-independent statistics collected test.t1_c2_stats analyze status OK SELECT * FROM mysql.innodb_index_stats WHERE table_name IN ('t1', 't1_c2_stats'); database_name table_name index_name last_update stat_name stat_value sample_size stat_description @@ -184,9 +187,11 @@ INSERT INTO t1 SELECT 20 + c1, c2, c3 FROM t1; INSERT INTO t1 SELECT 40 + c1, c2, c3 FROM t1; EXPLAIN SELECT COUNT(*) FROM t1 WHERE c2 > 3; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 80 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'c3' test.t1 analyze status OK connection con1; UPDATE t1_c2_stats SET index_name = 'c2d'; diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result index 8d7dcb84486..1d451fdc68d 100644 --- a/mysql-test/suite/innodb/r/innodb-index.result +++ b/mysql-test/suite/innodb/r/innodb-index.result @@ -77,6 +77,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select * from t1 force index(c) order by c; id select_type table type possible_keys key key_len ref rows Extra @@ -119,6 +120,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select * from t1 force index(c) order by c; id select_type table type possible_keys key key_len ref rows Extra @@ -810,6 +812,7 @@ a b 2 2 analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select * from t1; id select_type table type possible_keys key key_len ref rows Extra @@ -846,6 +849,7 @@ a 2 analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select * from t1; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/suite/innodb/r/innodb-table-online.result b/mysql-test/suite/innodb/r/innodb-table-online.result index 5b5c4d6b9e1..1cfa342c63f 100644 --- a/mysql-test/suite/innodb/r/innodb-table-online.result +++ b/mysql-test/suite/innodb/r/innodb-table-online.result @@ -212,6 +212,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL ROWS Using where ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SET @merge_encrypt_0= (SELECT variable_value FROM information_schema.global_status diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result index ec3856c20b8..ed7477fa033 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result @@ -479,12 +479,6 @@ ALTER TABLE test_wl5522.t1 IMPORT TABLESPACE; ERROR HY000: Index for table 't1' is corrupt; try to repair it SET SESSION debug_dbug=@saved_debug_dbug; restore: t1 .ibd and .cfg files -SET SESSION debug_dbug="+d,ib_import_set_max_rowid_failure"; -ALTER TABLE test_wl5522.t1 IMPORT TABLESPACE; -ERROR HY000: Index for table 't1' is corrupt; try to repair it -SET SESSION debug_dbug=@saved_debug_dbug; -unlink: t1.ibd -unlink: t1.cfg DROP TABLE test_wl5522.t1; CREATE TABLE test_wl5522.t1 ( c1 BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index 86f90c2bd79..100845a081b 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -217,6 +217,7 @@ create index skr on t1 (a); insert into t1 values (3,""), (4,"testing"); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -1608,7 +1609,7 @@ INSERT INTO t1 VALUES (1),(2),(3); CREATE TABLE t2 (b_id tinyint(4) NOT NULL default '0',b_a tinyint(4) NOT NULL default '0', PRIMARY KEY (b_id), KEY (b_a), CONSTRAINT fk_b_a FOREIGN KEY (b_a) REFERENCES t1 (a_id) ON DELETE CASCADE ON UPDATE NO ACTION) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO t2 VALUES (1,1),(2,1),(3,1),(4,2),(5,2); -SELECT * FROM (SELECT t1.*,GROUP_CONCAT(t2.b_id SEPARATOR ',') as b_list FROM (t1 LEFT JOIN (t2) on t1.a_id = t2.b_a) GROUP BY t1.a_id ) AS xyz; +SELECT * FROM (SELECT t1.*,GROUP_CONCAT(t2.b_id SEPARATOR ',') as b_list FROM (t1 LEFT JOIN t2 on t1.a_id = t2.b_a) GROUP BY t1.a_id ) AS xyz; a_id b_list 1 1,2,3 2 4,5 @@ -3236,7 +3237,7 @@ select f1 from t1; f1 show status like "handler_read_key"; Variable_name Value -Handler_read_key 0 +Handler_read_key 3 drop table t1; CREATE TABLE t1 (c1 INT) ENGINE=InnoDB; CREATE TEMPORARY TABLE t2 (c1 INT) ENGINE=InnoDB; diff --git a/mysql-test/suite/innodb/r/innodb_bug14676111.result b/mysql-test/suite/innodb/r/innodb_bug14676111.result index d1e21c92d95..f8f0b3fbccb 100644 --- a/mysql-test/suite/innodb/r/innodb_bug14676111.result +++ b/mysql-test/suite/innodb/r/innodb_bug14676111.result @@ -16,6 +16,7 @@ insert into t1 values (2); connection default; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select CLUST_INDEX_SIZE from information_schema.INNODB_SYS_TABLESTATS where NAME = 'test/t1'; CLUST_INDEX_SIZE @@ -26,6 +27,7 @@ disconnect con4; connection default; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select CLUST_INDEX_SIZE from information_schema.INNODB_SYS_TABLESTATS where NAME = 'test/t1'; CLUST_INDEX_SIZE @@ -36,6 +38,7 @@ disconnect con5; connection default; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select CLUST_INDEX_SIZE from information_schema.INNODB_SYS_TABLESTATS where NAME = 'test/t1'; CLUST_INDEX_SIZE @@ -47,6 +50,7 @@ disconnect con2; connection default; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select CLUST_INDEX_SIZE from information_schema.INNODB_SYS_TABLESTATS where NAME = 'test/t1'; CLUST_INDEX_SIZE @@ -56,6 +60,7 @@ insert into t1 values (2); rollback; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select CLUST_INDEX_SIZE from information_schema.INNODB_SYS_TABLESTATS where NAME = 'test/t1'; CLUST_INDEX_SIZE @@ -65,6 +70,7 @@ insert into t1 values (2); rollback; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select CLUST_INDEX_SIZE from information_schema.INNODB_SYS_TABLESTATS where NAME = 'test/t1'; CLUST_INDEX_SIZE diff --git a/mysql-test/suite/innodb/r/innodb_bug30423.result b/mysql-test/suite/innodb/r/innodb_bug30423.result index c7f823a06ae..786041370ef 100644 --- a/mysql-test/suite/innodb/r/innodb_bug30423.result +++ b/mysql-test/suite/innodb/r/innodb_bug30423.result @@ -19,12 +19,15 @@ select @@innodb_stats_method; nulls_equal analyze table bug30243_1; Table Op Msg_type Msg_text +test.bug30243_1 analyze status Engine-independent statistics collected test.bug30243_1 analyze status OK analyze table bug30243_2; Table Op Msg_type Msg_text +test.bug30243_2 analyze status Engine-independent statistics collected test.bug30243_2 analyze status OK analyze table bug30243_3; Table Op Msg_type Msg_text +test.bug30243_3 analyze status Engine-independent statistics collected test.bug30243_3 analyze status OK set global innodb_stats_method = "NULL"; ERROR 42000: Variable 'innodb_stats_method' can't be set to the value of 'NULL' @@ -34,12 +37,15 @@ select @@innodb_stats_method; nulls_ignored analyze table bug30243_1; Table Op Msg_type Msg_text +test.bug30243_1 analyze status Engine-independent statistics collected test.bug30243_1 analyze status OK analyze table bug30243_2; Table Op Msg_type Msg_text +test.bug30243_2 analyze status Engine-independent statistics collected test.bug30243_2 analyze status OK analyze table bug30243_3; Table Op Msg_type Msg_text +test.bug30243_3 analyze status Engine-independent statistics collected test.bug30243_3 analyze status OK explain SELECT COUNT(*), 0 FROM bug30243_1 orgs @@ -60,12 +66,15 @@ select @@innodb_stats_method; nulls_unequal analyze table bug30243_1; Table Op Msg_type Msg_text +test.bug30243_1 analyze status Engine-independent statistics collected test.bug30243_1 analyze status OK analyze table bug30243_2; Table Op Msg_type Msg_text +test.bug30243_2 analyze status Engine-independent statistics collected test.bug30243_2 analyze status OK analyze table bug30243_3; Table Op Msg_type Msg_text +test.bug30243_3 analyze status Engine-independent statistics collected test.bug30243_3 analyze status OK explain SELECT COUNT(*), 0 FROM bug30243_1 orgs @@ -83,10 +92,12 @@ COUNT(*) set global innodb_stats_method = "nulls_unequal"; analyze table table_bug30423; Table Op Msg_type Msg_text +test.table_bug30423 analyze status Engine-independent statistics collected test.table_bug30423 analyze status OK set global innodb_stats_method = "nulls_ignored"; analyze table table_bug30423; Table Op Msg_type Msg_text +test.table_bug30423 analyze status Engine-independent statistics collected test.table_bug30423 analyze status OK set global innodb_stats_method = nulls_equal; drop table bug30243_2; diff --git a/mysql-test/suite/innodb/r/innodb_bug30919.result b/mysql-test/suite/innodb/r/innodb_bug30919.result index 42aa4ff302b..0062df3f470 100644 --- a/mysql-test/suite/innodb/r/innodb_bug30919.result +++ b/mysql-test/suite/innodb/r/innodb_bug30919.result @@ -35,6 +35,10 @@ FROM test.part_tbl; -- debug to show the problem SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL test.proc_part(); internal_count del_count 999 1000 diff --git a/mysql-test/suite/innodb/r/innodb_bug51920.result b/mysql-test/suite/innodb/r/innodb_bug51920.result index ddb9e29fab2..9bc35174979 100644 --- a/mysql-test/suite/innodb/r/innodb_bug51920.result +++ b/mysql-test/suite/innodb/r/innodb_bug51920.result @@ -11,6 +11,8 @@ connection default; SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO="UPDATE bug51920 SET i=2" INTO @thread_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead KILL @thread_id; connection con1; Got one of the listed errors diff --git a/mysql-test/suite/innodb/r/innodb_bug53046.result b/mysql-test/suite/innodb/r/innodb_bug53046.result index 69be6c4e0a7..0321d5ace19 100644 --- a/mysql-test/suite/innodb/r/innodb_bug53046.result +++ b/mysql-test/suite/innodb/r/innodb_bug53046.result @@ -16,6 +16,7 @@ FROM bug53046_1; INSERT INTO bug53046_2 VALUES (1), (2); ANALYZE TABLE bug53046_1; Table Op Msg_type Msg_text +test.bug53046_1 analyze status Engine-independent statistics collected test.bug53046_1 analyze status OK SHOW TABLE STATUS LIKE 'bug53046_1'; UPDATE bug53046_1 SET c1 = c1 - 1; diff --git a/mysql-test/suite/innodb/r/innodb_bug57252.result b/mysql-test/suite/innodb/r/innodb_bug57252.result index efa50c742e0..2e371cb74ee 100644 --- a/mysql-test/suite/innodb/r/innodb_bug57252.result +++ b/mysql-test/suite/innodb/r/innodb_bug57252.result @@ -1,6 +1,7 @@ cardinality 10 Table Op Msg_type Msg_text +test.bug57252 analyze status Engine-independent statistics collected test.bug57252 analyze status OK cardinality 10 diff --git a/mysql-test/suite/innodb/r/innodb_max_recordsize_32k.result b/mysql-test/suite/innodb/r/innodb_max_recordsize_32k.result index 117b7e4418e..c20c981653c 100644 --- a/mysql-test/suite/innodb/r/innodb_max_recordsize_32k.result +++ b/mysql-test/suite/innodb/r/innodb_max_recordsize_32k.result @@ -325,6 +325,8 @@ LENGTH(col) FLUSH TABLE t; ANALYZE TABLE t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze Warning Engine-independent statistics are not collected for column 'col' test.t analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t'; @@ -345,6 +347,8 @@ LENGTH(col) FLUSH TABLE t; ANALYZE TABLE t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze Warning Engine-independent statistics are not collected for column 'col' test.t analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t'; @@ -365,6 +369,8 @@ LENGTH(col) FLUSH TABLE t; ANALYZE TABLE t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze Warning Engine-independent statistics are not collected for column 'col' test.t analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t'; diff --git a/mysql-test/suite/innodb/r/innodb_max_recordsize_64k.result b/mysql-test/suite/innodb/r/innodb_max_recordsize_64k.result index de957023ff8..a74e7826729 100644 --- a/mysql-test/suite/innodb/r/innodb_max_recordsize_64k.result +++ b/mysql-test/suite/innodb/r/innodb_max_recordsize_64k.result @@ -528,6 +528,8 @@ LENGTH(col) FLUSH TABLE t; ANALYZE TABLE t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze Warning Engine-independent statistics are not collected for column 'col' test.t analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t'; @@ -548,6 +550,8 @@ LENGTH(col) FLUSH TABLE t; ANALYZE TABLE t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze Warning Engine-independent statistics are not collected for column 'col' test.t analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t'; @@ -568,6 +572,8 @@ LENGTH(col) FLUSH TABLE t; ANALYZE TABLE t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze Warning Engine-independent statistics are not collected for column 'col' test.t analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t'; diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index 3663c18ea44..f1573d46a6f 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -191,8 +191,8 @@ min(7) 7 explain select min(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2i ALL NULL NULL NULL NULL 1 -1 SIMPLE t1i ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join) +1 SIMPLE t1i ALL NULL NULL NULL NULL 0 +1 SIMPLE t2i ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join) select min(7) from t2i join t1i; min(7) NULL @@ -207,8 +207,8 @@ max(7) 7 explain select max(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2i ALL NULL NULL NULL NULL 1 -1 SIMPLE t1i ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join) +1 SIMPLE t1i ALL NULL NULL NULL NULL 0 +1 SIMPLE t2i ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join) select max(7) from t2i join t1i; max(7) NULL @@ -239,7 +239,7 @@ select 1, max(1) from t1i where 1=99; explain select count(*), min(7), max(7) from t1m, t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1m system NULL NULL NULL NULL 0 Const row not found -1 SIMPLE t1i ALL NULL NULL NULL NULL 1 +1 SIMPLE t1i ALL NULL NULL NULL NULL 0 select count(*), min(7), max(7) from t1m, t1i; count(*) min(7) max(7) 0 NULL NULL @@ -253,7 +253,7 @@ count(*) min(7) max(7) explain select count(*), min(7), max(7) from t2m, t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2m system NULL NULL NULL NULL 1 -1 SIMPLE t1i ALL NULL NULL NULL NULL 1 +1 SIMPLE t1i ALL NULL NULL NULL NULL 0 select count(*), min(7), max(7) from t2m, t1i; count(*) min(7) max(7) 0 NULL NULL @@ -303,6 +303,7 @@ create index idx12672_1 on t4 (a1,a2,b,c); create index idx12672_2 on t4 (a1,a2,b); analyze table t4; Table Op Msg_type Msg_text +test.t4 analyze status Engine-independent statistics collected test.t4 analyze status OK select distinct a1 from t4 where pk_col not in (1,2,3,4); a1 @@ -2699,6 +2700,7 @@ INSERT INTO t1 SELECT c1+100000,c2+100000,c3+100000 from t1; INSERT INTO t1 SELECT c1+1000000,c2+1000000,c3+1000000 from t1; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT * FROM t1 WHERE c1 = 99999999 AND c3 > 1 ORDER BY c3; c1 c2 c3 @@ -2851,6 +2853,7 @@ INSERT INTO t1 VALUES (1,1,1,1,1,1), (2,2,2,2,2,2), (3,3,3,3,3,3), (11,11,11,11,11,11); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN SELECT COUNT(*) FROM t1; id 1 @@ -3126,7 +3129,7 @@ INSERT INTO t1 VALUES (0); SET SQL_MODE='STRICT_ALL_TABLES'; CREATE TABLE t2 SELECT LEAST((SELECT '' FROM t1),NOW()) FROM `t1`; -ERROR 22007: Incorrect datetime value: '' +ERROR 22007: Truncated incorrect datetime value: '' DROP TABLE t1; SET SQL_MODE=DEFAULT; # diff --git a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result index 79f0e73e745..a90cd22f57a 100644 --- a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result +++ b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result @@ -74,7 +74,6 @@ buffer_pages_written buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NUL buffer_index_pages_written buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of index pages written (innodb_index_pages_written) buffer_non_index_pages_written buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of non index pages written (innodb_non_index_pages_written) buffer_pages_read buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of pages read (innodb_pages_read) -buffer_pages0_read buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of page 0 read (innodb_pages0_read) buffer_index_sec_rec_cluster_reads buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of secondary record reads triggered cluster read buffer_index_sec_rec_cluster_reads_avoided buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of secondary record reads avoided triggering cluster read buffer_data_reads buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Amount of data read in bytes (innodb_data_reads) @@ -183,7 +182,6 @@ trx_nl_ro_commits transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL N trx_commits_insert_update transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of transactions committed with inserts and updates trx_rollbacks transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of transactions rolled back trx_rollbacks_savepoint transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of transactions rolled back to savepoint -trx_rollback_active transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of resurrected active transactions rolled back trx_active_transactions transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of active transactions trx_rseg_history_len transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled value Length of the TRX_RSEG_HISTORY list trx_undo_slots_used transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of undo slots used diff --git a/mysql-test/suite/innodb/r/innodb_stats.result b/mysql-test/suite/innodb/r/innodb_stats.result index d2c3bd0127e..eadce75318b 100644 --- a/mysql-test/suite/innodb/r/innodb_stats.result +++ b/mysql-test/suite/innodb/r/innodb_stats.result @@ -4,6 +4,7 @@ dummy INSERT, the table should be empty dummy INSERT, the table should be empty ANALYZE TABLE test_innodb_stats; Table Op Msg_type Msg_text +test.test_innodb_stats analyze status Engine-independent statistics collected test.test_innodb_stats analyze status OK SELECT stat_name, @@ -56,6 +57,7 @@ TRUNCATE TABLE test_innodb_stats; INSERT INTO test_innodb_stats (a) VALUES (1); ANALYZE TABLE test_innodb_stats; Table Op Msg_type Msg_text +test.test_innodb_stats analyze status Engine-independent statistics collected test.test_innodb_stats analyze status OK SELECT stat_name, @@ -108,6 +110,7 @@ TRUNCATE TABLE test_innodb_stats; INSERT INTO test_innodb_stats (a) VALUES (1), (1); ANALYZE TABLE test_innodb_stats; Table Op Msg_type Msg_text +test.test_innodb_stats analyze status Engine-independent statistics collected test.test_innodb_stats analyze status OK SELECT stat_name, @@ -160,6 +163,7 @@ TRUNCATE TABLE test_innodb_stats; INSERT INTO test_innodb_stats (a) VALUES (1), (1), (1); ANALYZE TABLE test_innodb_stats; Table Op Msg_type Msg_text +test.test_innodb_stats analyze status Engine-independent statistics collected test.test_innodb_stats analyze status OK SELECT stat_name, @@ -212,6 +216,7 @@ TRUNCATE TABLE test_innodb_stats; INSERT INTO test_innodb_stats (a) VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1); ANALYZE TABLE test_innodb_stats; Table Op Msg_type Msg_text +test.test_innodb_stats analyze status Engine-independent statistics collected test.test_innodb_stats analyze status OK SELECT stat_name, @@ -264,6 +269,7 @@ TRUNCATE TABLE test_innodb_stats; INSERT INTO test_innodb_stats (a) VALUES (1), (2); ANALYZE TABLE test_innodb_stats; Table Op Msg_type Msg_text +test.test_innodb_stats analyze status Engine-independent statistics collected test.test_innodb_stats analyze status OK SELECT stat_name, @@ -316,6 +322,7 @@ TRUNCATE TABLE test_innodb_stats; INSERT INTO test_innodb_stats (a) VALUES (1), (1), (2); ANALYZE TABLE test_innodb_stats; Table Op Msg_type Msg_text +test.test_innodb_stats analyze status Engine-independent statistics collected test.test_innodb_stats analyze status OK SELECT stat_name, @@ -368,6 +375,7 @@ TRUNCATE TABLE test_innodb_stats; INSERT INTO test_innodb_stats (a) VALUES (1), (2), (3); ANALYZE TABLE test_innodb_stats; Table Op Msg_type Msg_text +test.test_innodb_stats analyze status Engine-independent statistics collected test.test_innodb_stats analyze status OK SELECT stat_name, @@ -420,6 +428,7 @@ TRUNCATE TABLE test_innodb_stats; INSERT INTO test_innodb_stats (a) VALUES (1), (1), (2), (3), (3); ANALYZE TABLE test_innodb_stats; Table Op Msg_type Msg_text +test.test_innodb_stats analyze status Engine-independent statistics collected test.test_innodb_stats analyze status OK SELECT stat_name, @@ -472,6 +481,7 @@ TRUNCATE TABLE test_innodb_stats; INSERT INTO test_innodb_stats (a) VALUES (1), (2), (3), (4), (5), (1), (2), (3), (4), (5); ANALYZE TABLE test_innodb_stats; Table Op Msg_type Msg_text +test.test_innodb_stats analyze status Engine-independent statistics collected test.test_innodb_stats analyze status OK SELECT stat_name, diff --git a/mysql-test/suite/innodb/r/innodb_stats_drop_locked.result b/mysql-test/suite/innodb/r/innodb_stats_drop_locked.result index b8f312ccd63..fc0a590934a 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_drop_locked.result +++ b/mysql-test/suite/innodb/r/innodb_stats_drop_locked.result @@ -1,4 +1,5 @@ Table Op Msg_type Msg_text +test.innodb_stats_drop_locked analyze status Engine-independent statistics collected test.innodb_stats_drop_locked analyze status OK SET autocommit=0; SELECT table_name FROM mysql.innodb_table_stats diff --git a/mysql-test/suite/innodb/r/innodb_stats_fetch.result b/mysql-test/suite/innodb/r/innodb_stats_fetch.result index b348e41f1d9..67437c46cd3 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_fetch.result +++ b/mysql-test/suite/innodb/r/innodb_stats_fetch.result @@ -5,6 +5,10 @@ ANALYZE TABLE test_ps_fetch; Table test.test_ps_fetch Op analyze Msg_type status +Msg_text Engine-independent statistics collected +Table test.test_ps_fetch +Op analyze +Msg_type status Msg_text OK SELECT n_rows, clustered_index_size, sum_of_other_index_sizes FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_fetch'; diff --git a/mysql-test/suite/innodb/r/innodb_stats_fetch_corrupted.result b/mysql-test/suite/innodb/r/innodb_stats_fetch_corrupted.result index 0f0e941b838..c232a841376 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_fetch_corrupted.result +++ b/mysql-test/suite/innodb/r/innodb_stats_fetch_corrupted.result @@ -7,6 +7,10 @@ ANALYZE TABLE test_ps_fetch_corrupted; Table test.test_ps_fetch_corrupted Op analyze Msg_type status +Msg_text Engine-independent statistics collected +Table test.test_ps_fetch_corrupted +Op analyze +Msg_type status Msg_text OK SELECT n_rows, clustered_index_size, sum_of_other_index_sizes FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_fetch_corrupted'; diff --git a/mysql-test/suite/innodb/r/innodb_stats_fetch_nonexistent.result b/mysql-test/suite/innodb/r/innodb_stats_fetch_nonexistent.result index 6093fbae86b..91bb2bf3ecd 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_fetch_nonexistent.result +++ b/mysql-test/suite/innodb/r/innodb_stats_fetch_nonexistent.result @@ -6,6 +6,10 @@ ANALYZE TABLE test_ps_fetch_nonexistent; Table test.test_ps_fetch_nonexistent Op analyze Msg_type status +Msg_text Engine-independent statistics collected +Table test.test_ps_fetch_nonexistent +Op analyze +Msg_type status Msg_text OK SELECT COUNT(*) FROM mysql.innodb_table_stats WHERE table_name = 'test_ps_fetch_nonexistent'; diff --git a/mysql-test/suite/innodb/r/innodb_stats_persistent.result b/mysql-test/suite/innodb/r/innodb_stats_persistent.result index f4de4b6b82e..44cb3a81372 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_persistent.result +++ b/mysql-test/suite/innodb/r/innodb_stats_persistent.result @@ -19,6 +19,7 @@ COUNT(*) 16 ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK connect con1, localhost, root,,; START TRANSACTION; @@ -100,7 +101,7 @@ COUNT(*) # ha_innobase::records_in_range() would count the delete-marked records. EXPLAIN SELECT * FROM t1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL val 4 NULL 1 Using index +1 SIMPLE t1 index NULL val 4 NULL 16 Using index ROLLBACK; EXPLAIN SELECT * FROM t1; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/suite/innodb/r/innodb_stats_persistent_debug.result b/mysql-test/suite/innodb/r/innodb_stats_persistent_debug.result index 9f93f05fd56..ee1ad318d65 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_persistent_debug.result +++ b/mysql-test/suite/innodb/r/innodb_stats_persistent_debug.result @@ -17,6 +17,7 @@ SET GLOBAL innodb_limit_optimistic_insert_debug = @save_debug; connect con1, localhost, root,,; ANALYZE TABLE t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK disconnect con1; connection default; diff --git a/mysql-test/suite/innodb/r/instant_alter.result b/mysql-test/suite/innodb/r/instant_alter.result index 3ebc161caf1..07160ff91dd 100644 --- a/mysql-test/suite/innodb/r/instant_alter.result +++ b/mysql-test/suite/innodb/r/instant_alter.result @@ -182,8 +182,8 @@ affected rows: 0 info: Records: 0 Duplicates: 0 Warnings: 0 INSERT INTO t1 SET id=9; ALTER TABLE t1 DROP c3; -affected rows: 9 -info: Records: 9 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -236,6 +236,7 @@ UPDATE t2 SET c1 = repeat(id, 4000); connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -246,6 +247,7 @@ ROLLBACK; connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -257,6 +259,7 @@ UPDATE t2 SET d1 = repeat(id, 200); connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -267,6 +270,7 @@ ROLLBACK; connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -386,6 +390,7 @@ COMMIT; connection analyze; ANALYZE TABLE big; Table Op Msg_type Msg_text +test.big analyze status Engine-independent statistics collected test.big analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/big'; @@ -409,6 +414,7 @@ test.big 385477733 connection analyze; ANALYZE TABLE big; Table Op Msg_type Msg_text +test.big analyze status Engine-independent statistics collected test.big analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/big'; @@ -422,6 +428,7 @@ test.big 1705165209 connection analyze; ANALYZE TABLE big; Table Op Msg_type Msg_text +test.big analyze status Engine-independent statistics collected test.big analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/big'; @@ -486,6 +493,128 @@ DELETE FROM t1; COMMIT; InnoDB 0 transactions not purged DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT UNIQUE) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1 (a) VALUES (NULL), (NULL); +ALTER TABLE t1 DROP a, ADD COLUMN a INT; +DELETE FROM t1; +BEGIN; +INSERT INTO t1 SET a=NULL; +ROLLBACK; +DELETE FROM t1; +DROP TABLE t1; +CREATE TABLE t1 (a INT PRIMARY KEY, t VARCHAR(33101) NOT NULL) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1 VALUES(347,''); +ALTER TABLE t1 DROP COLUMN t, ALGORITHM=INSTANT; +SELECT * FROM t1; +a +347 +DROP TABLE t1; +CREATE TABLE t1 (a INT) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1() VALUES(); +ALTER TABLE t1 ADD COLUMN b INT FIRST, ADD COLUMN c INT AFTER b; +SELECT * FROM t1; +b c a +NULL NULL NULL +DROP TABLE t1; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +SET @t=REPEAT('x',@@innodb_page_size / 2); +INSERT INTO t1 VALUES (@t),(@t),(@t),(@t),(@t),(@t),(NULL),(@t),(@t),(@t),(@t); +ALTER TABLE t1 ADD COLUMN a INT FIRST; +UPDATE t1 SET a = 0; +DROP TABLE t1; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1 SET t = @x; +ALTER TABLE t1 DROP COLUMN t, ADD COLUMN i INT NOT NULL DEFAULT 1; +ALTER TABLE t1 ADD COLUMN t TEXT; +SELECT * FROM t1; +i t +1 NULL +DROP TABLE t1; +CREATE TABLE t1 (a INT AUTO_INCREMENT, b INT, KEY(a)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1 SET a=NULL; +ALTER TABLE t1 DROP COLUMN b; +ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 42; +INSERT INTO t1 SET a=NULL; +UPDATE t1 SET a=a+2; +SELECT * FROM t1; +a c +3 42 +4 42 +DROP TABLE t1; +CREATE TABLE t1 (i INT) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1 SET i=1; +ALTER TABLE t1 ADD COLUMN b BIT FIRST; +ALTER TABLE t1 ADD COLUMN v INT AS (i) VIRTUAL; +SELECT * FROM t1; +b i v +NULL 1 1 +DROP TABLE t1; +CREATE TABLE t1 (ts TIMESTAMP) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +ALTER TABLE t1 ADD COLUMN f VARCHAR(8), ADD COLUMN dt DATETIME; +ALTER TABLE t1 ADD COLUMN b BIT, DROP COLUMN f, ADD COLUMN t TIME FIRST; +ALTER TABLE t1 ADD COLUMN ts2 TIMESTAMP; +DROP TABLE t1; +CREATE TABLE t1 (f1 INT, f2 INT, f3 INT) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1 VALUES (4,4,4); +ALTER TABLE t1 DROP f1, DROP f2, ADD f4 INT, ADD f5 INT; +DELETE FROM t1; +ALTER TABLE t1 DROP COLUMN f4; +DROP TABLE t1; +CREATE TABLE t1 (f1 INT, f2 INT, f3 INT) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +ALTER TABLE t1 DROP f2, ADD COLUMN f4 INT; +ALTER TABLE t1 DROP f4; +ALTER TABLE t1 DROP f1; +DROP TABLE t1; +CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT, f INT, KEY(id)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +ALTER TABLE t1 DROP COLUMN id; +INSERT INTO t1 () VALUES (),(); +SELECT * FROM t1; +f +NULL +NULL +ALTER TABLE t1 ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, ADD KEY(id); +SELECT * FROM t1; +id f +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 ( +pk INT PRIMARY KEY, +f1 INT, +f2 CHAR(255), +f3 BIGINT, +f4 INT, +f5 CHAR(255), +f6 CHAR(255), +f7 CHAR(255) NOT NULL, +f8 INT, +f9 CHAR(10) +) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO t1 VALUES +(1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a'), +(2, 2, 'b', 2, 2, 'b', 'b', 'b', 2, 'b'), +(3, 3, 'c', 3, 3, 'c', 'c', 'c', 3, 'c'), +(4, 4, 'd', 4, 4, 'd', 'd', 'd', 4, 'd'), +(5, 5, 'e', 5, 5, 'e', 'e', 'e', 5, 'e'), +(6, 6, 'f', 6, 6, 'f', 'f', 'f', 6, 'f'), +(7, 7, 'g', 7, 7, 'g', 'g', 'g', 7, 'g'), +(8, 8, 'h', 8, 8, 'h', 'h', 'h', 8, 'h'), +(9, 9, 'i', 9, 9, 'i', 'i', 'i', 9, 'i'), +(10, 0, 'j', 0, 0, 'j', 'j', 'j', 0, 'j'), +(11, 1, 'k', 1, 1, 'k', 'k', 'k', 1, 'k'), +(12, 2, 'l', 2, 2, 'l', 'l', 'l', 2, 'l'), +(13, 3, 'm', 3, 3, 'm', 'm', 'm', 3, 'm'), +(14, 4, 'n', 4, 4, 'n', 'n', 'n', 4, 'n'), +(15, 5, 'o', 5, 5, 'o', 'o', 'o', 5, 'o'); +DELETE FROM t1 WHERE pk=1; +InnoDB 0 transactions not purged +INSERT INTO t1 VALUES +(1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a'); +ALTER TABLE t1 DROP COLUMN f1; +DROP TABLE t1; +CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST; +DROP TABLE t1; CREATE TABLE t1 (id INT PRIMARY KEY, c2 INT UNIQUE, c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'), @@ -614,8 +743,8 @@ affected rows: 0 info: Records: 0 Duplicates: 0 Warnings: 0 INSERT INTO t1 SET id=9; ALTER TABLE t1 DROP c3; -affected rows: 9 -info: Records: 9 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -668,6 +797,7 @@ UPDATE t2 SET c1 = repeat(id, 4000); connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -678,6 +808,7 @@ ROLLBACK; connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -689,6 +820,7 @@ UPDATE t2 SET d1 = repeat(id, 200); connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -699,6 +831,7 @@ ROLLBACK; connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -818,6 +951,7 @@ COMMIT; connection analyze; ANALYZE TABLE big; Table Op Msg_type Msg_text +test.big analyze status Engine-independent statistics collected test.big analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/big'; @@ -841,6 +975,7 @@ test.big 385477733 connection analyze; ANALYZE TABLE big; Table Op Msg_type Msg_text +test.big analyze status Engine-independent statistics collected test.big analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/big'; @@ -854,6 +989,7 @@ test.big 1705165209 connection analyze; ANALYZE TABLE big; Table Op Msg_type Msg_text +test.big analyze status Engine-independent statistics collected test.big analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/big'; @@ -918,6 +1054,128 @@ DELETE FROM t1; COMMIT; InnoDB 0 transactions not purged DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT UNIQUE) ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 (a) VALUES (NULL), (NULL); +ALTER TABLE t1 DROP a, ADD COLUMN a INT; +DELETE FROM t1; +BEGIN; +INSERT INTO t1 SET a=NULL; +ROLLBACK; +DELETE FROM t1; +DROP TABLE t1; +CREATE TABLE t1 (a INT PRIMARY KEY, t VARCHAR(33101) NOT NULL) ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 VALUES(347,''); +ALTER TABLE t1 DROP COLUMN t, ALGORITHM=INSTANT; +SELECT * FROM t1; +a +347 +DROP TABLE t1; +CREATE TABLE t1 (a INT) ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1() VALUES(); +ALTER TABLE t1 ADD COLUMN b INT FIRST, ADD COLUMN c INT AFTER b; +SELECT * FROM t1; +b c a +NULL NULL NULL +DROP TABLE t1; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB ROW_FORMAT=COMPACT; +SET @t=REPEAT('x',@@innodb_page_size / 2); +INSERT INTO t1 VALUES (@t),(@t),(@t),(@t),(@t),(@t),(NULL),(@t),(@t),(@t),(@t); +ALTER TABLE t1 ADD COLUMN a INT FIRST; +UPDATE t1 SET a = 0; +DROP TABLE t1; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 SET t = @x; +ALTER TABLE t1 DROP COLUMN t, ADD COLUMN i INT NOT NULL DEFAULT 1; +ALTER TABLE t1 ADD COLUMN t TEXT; +SELECT * FROM t1; +i t +1 NULL +DROP TABLE t1; +CREATE TABLE t1 (a INT AUTO_INCREMENT, b INT, KEY(a)) ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 SET a=NULL; +ALTER TABLE t1 DROP COLUMN b; +ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 42; +INSERT INTO t1 SET a=NULL; +UPDATE t1 SET a=a+2; +SELECT * FROM t1; +a c +3 42 +4 42 +DROP TABLE t1; +CREATE TABLE t1 (i INT) ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 SET i=1; +ALTER TABLE t1 ADD COLUMN b BIT FIRST; +ALTER TABLE t1 ADD COLUMN v INT AS (i) VIRTUAL; +SELECT * FROM t1; +b i v +NULL 1 1 +DROP TABLE t1; +CREATE TABLE t1 (ts TIMESTAMP) ENGINE=InnoDB ROW_FORMAT=COMPACT; +ALTER TABLE t1 ADD COLUMN f VARCHAR(8), ADD COLUMN dt DATETIME; +ALTER TABLE t1 ADD COLUMN b BIT, DROP COLUMN f, ADD COLUMN t TIME FIRST; +ALTER TABLE t1 ADD COLUMN ts2 TIMESTAMP; +DROP TABLE t1; +CREATE TABLE t1 (f1 INT, f2 INT, f3 INT) ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 VALUES (4,4,4); +ALTER TABLE t1 DROP f1, DROP f2, ADD f4 INT, ADD f5 INT; +DELETE FROM t1; +ALTER TABLE t1 DROP COLUMN f4; +DROP TABLE t1; +CREATE TABLE t1 (f1 INT, f2 INT, f3 INT) ENGINE=InnoDB ROW_FORMAT=COMPACT; +ALTER TABLE t1 DROP f2, ADD COLUMN f4 INT; +ALTER TABLE t1 DROP f4; +ALTER TABLE t1 DROP f1; +DROP TABLE t1; +CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT, f INT, KEY(id)) ENGINE=InnoDB ROW_FORMAT=COMPACT; +ALTER TABLE t1 DROP COLUMN id; +INSERT INTO t1 () VALUES (),(); +SELECT * FROM t1; +f +NULL +NULL +ALTER TABLE t1 ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, ADD KEY(id); +SELECT * FROM t1; +id f +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 ( +pk INT PRIMARY KEY, +f1 INT, +f2 CHAR(255), +f3 BIGINT, +f4 INT, +f5 CHAR(255), +f6 CHAR(255), +f7 CHAR(255) NOT NULL, +f8 INT, +f9 CHAR(10) +) ENGINE=InnoDB ROW_FORMAT=COMPACT; +INSERT INTO t1 VALUES +(1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a'), +(2, 2, 'b', 2, 2, 'b', 'b', 'b', 2, 'b'), +(3, 3, 'c', 3, 3, 'c', 'c', 'c', 3, 'c'), +(4, 4, 'd', 4, 4, 'd', 'd', 'd', 4, 'd'), +(5, 5, 'e', 5, 5, 'e', 'e', 'e', 5, 'e'), +(6, 6, 'f', 6, 6, 'f', 'f', 'f', 6, 'f'), +(7, 7, 'g', 7, 7, 'g', 'g', 'g', 7, 'g'), +(8, 8, 'h', 8, 8, 'h', 'h', 'h', 8, 'h'), +(9, 9, 'i', 9, 9, 'i', 'i', 'i', 9, 'i'), +(10, 0, 'j', 0, 0, 'j', 'j', 'j', 0, 'j'), +(11, 1, 'k', 1, 1, 'k', 'k', 'k', 1, 'k'), +(12, 2, 'l', 2, 2, 'l', 'l', 'l', 2, 'l'), +(13, 3, 'm', 3, 3, 'm', 'm', 'm', 3, 'm'), +(14, 4, 'n', 4, 4, 'n', 'n', 'n', 4, 'n'), +(15, 5, 'o', 5, 5, 'o', 'o', 'o', 5, 'o'); +DELETE FROM t1 WHERE pk=1; +InnoDB 0 transactions not purged +INSERT INTO t1 VALUES +(1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a'); +ALTER TABLE t1 DROP COLUMN f1; +DROP TABLE t1; +CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=COMPACT; +ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST; +DROP TABLE t1; CREATE TABLE t1 (id INT PRIMARY KEY, c2 INT UNIQUE, c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'), @@ -1046,8 +1304,8 @@ affected rows: 0 info: Records: 0 Duplicates: 0 Warnings: 0 INSERT INTO t1 SET id=9; ALTER TABLE t1 DROP c3; -affected rows: 9 -info: Records: 9 Duplicates: 0 Warnings: 0 +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -1100,6 +1358,7 @@ UPDATE t2 SET c1 = repeat(id, 4000); connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -1110,6 +1369,7 @@ ROLLBACK; connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -1121,6 +1381,7 @@ UPDATE t2 SET d1 = repeat(id, 200); connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -1131,6 +1392,7 @@ ROLLBACK; connection analyze; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/t2'; @@ -1250,6 +1512,7 @@ COMMIT; connection analyze; ANALYZE TABLE big; Table Op Msg_type Msg_text +test.big analyze status Engine-independent statistics collected test.big analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/big'; @@ -1273,6 +1536,7 @@ test.big 385477733 connection analyze; ANALYZE TABLE big; Table Op Msg_type Msg_text +test.big analyze status Engine-independent statistics collected test.big analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/big'; @@ -1286,6 +1550,7 @@ test.big 1705165209 connection analyze; ANALYZE TABLE big; Table Op Msg_type Msg_text +test.big analyze status Engine-independent statistics collected test.big analyze status OK SELECT clust_index_size FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE name = 'test/big'; @@ -1350,10 +1615,132 @@ DELETE FROM t1; COMMIT; InnoDB 0 transactions not purged DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT UNIQUE) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 (a) VALUES (NULL), (NULL); +ALTER TABLE t1 DROP a, ADD COLUMN a INT; +DELETE FROM t1; +BEGIN; +INSERT INTO t1 SET a=NULL; +ROLLBACK; +DELETE FROM t1; +DROP TABLE t1; +CREATE TABLE t1 (a INT PRIMARY KEY, t VARCHAR(33101) NOT NULL) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 VALUES(347,''); +ALTER TABLE t1 DROP COLUMN t, ALGORITHM=INSTANT; +SELECT * FROM t1; +a +347 +DROP TABLE t1; +CREATE TABLE t1 (a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1() VALUES(); +ALTER TABLE t1 ADD COLUMN b INT FIRST, ADD COLUMN c INT AFTER b; +SELECT * FROM t1; +b c a +NULL NULL NULL +DROP TABLE t1; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +SET @t=REPEAT('x',@@innodb_page_size / 2); +INSERT INTO t1 VALUES (@t),(@t),(@t),(@t),(@t),(@t),(NULL),(@t),(@t),(@t),(@t); +ALTER TABLE t1 ADD COLUMN a INT FIRST; +UPDATE t1 SET a = 0; +DROP TABLE t1; +CREATE TABLE t1 (t TEXT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 SET t = @x; +ALTER TABLE t1 DROP COLUMN t, ADD COLUMN i INT NOT NULL DEFAULT 1; +ALTER TABLE t1 ADD COLUMN t TEXT; +SELECT * FROM t1; +i t +1 NULL +DROP TABLE t1; +CREATE TABLE t1 (a INT AUTO_INCREMENT, b INT, KEY(a)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 SET a=NULL; +ALTER TABLE t1 DROP COLUMN b; +ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 42; +INSERT INTO t1 SET a=NULL; +UPDATE t1 SET a=a+2; +SELECT * FROM t1; +a c +3 42 +4 42 +DROP TABLE t1; +CREATE TABLE t1 (i INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 SET i=1; +ALTER TABLE t1 ADD COLUMN b BIT FIRST; +ALTER TABLE t1 ADD COLUMN v INT AS (i) VIRTUAL; +SELECT * FROM t1; +b i v +NULL 1 1 +DROP TABLE t1; +CREATE TABLE t1 (ts TIMESTAMP) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +ALTER TABLE t1 ADD COLUMN f VARCHAR(8), ADD COLUMN dt DATETIME; +ALTER TABLE t1 ADD COLUMN b BIT, DROP COLUMN f, ADD COLUMN t TIME FIRST; +ALTER TABLE t1 ADD COLUMN ts2 TIMESTAMP; +DROP TABLE t1; +CREATE TABLE t1 (f1 INT, f2 INT, f3 INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 VALUES (4,4,4); +ALTER TABLE t1 DROP f1, DROP f2, ADD f4 INT, ADD f5 INT; +DELETE FROM t1; +ALTER TABLE t1 DROP COLUMN f4; +DROP TABLE t1; +CREATE TABLE t1 (f1 INT, f2 INT, f3 INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +ALTER TABLE t1 DROP f2, ADD COLUMN f4 INT; +ALTER TABLE t1 DROP f4; +ALTER TABLE t1 DROP f1; +DROP TABLE t1; +CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT, f INT, KEY(id)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +ALTER TABLE t1 DROP COLUMN id; +INSERT INTO t1 () VALUES (),(); +SELECT * FROM t1; +f +NULL +NULL +ALTER TABLE t1 ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, ADD KEY(id); +SELECT * FROM t1; +id f +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 ( +pk INT PRIMARY KEY, +f1 INT, +f2 CHAR(255), +f3 BIGINT, +f4 INT, +f5 CHAR(255), +f6 CHAR(255), +f7 CHAR(255) NOT NULL, +f8 INT, +f9 CHAR(10) +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +INSERT INTO t1 VALUES +(1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a'), +(2, 2, 'b', 2, 2, 'b', 'b', 'b', 2, 'b'), +(3, 3, 'c', 3, 3, 'c', 'c', 'c', 3, 'c'), +(4, 4, 'd', 4, 4, 'd', 'd', 'd', 4, 'd'), +(5, 5, 'e', 5, 5, 'e', 'e', 'e', 5, 'e'), +(6, 6, 'f', 6, 6, 'f', 'f', 'f', 6, 'f'), +(7, 7, 'g', 7, 7, 'g', 'g', 'g', 7, 'g'), +(8, 8, 'h', 8, 8, 'h', 'h', 'h', 8, 'h'), +(9, 9, 'i', 9, 9, 'i', 'i', 'i', 9, 'i'), +(10, 0, 'j', 0, 0, 'j', 'j', 'j', 0, 'j'), +(11, 1, 'k', 1, 1, 'k', 'k', 'k', 1, 'k'), +(12, 2, 'l', 2, 2, 'l', 'l', 'l', 2, 'l'), +(13, 3, 'm', 3, 3, 'm', 'm', 'm', 3, 'm'), +(14, 4, 'n', 4, 4, 'n', 'n', 'n', 4, 'n'), +(15, 5, 'o', 5, 5, 'o', 'o', 'o', 5, 'o'); +DELETE FROM t1 WHERE pk=1; +InnoDB 0 transactions not purged +INSERT INTO t1 VALUES +(1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a'); +ALTER TABLE t1 DROP COLUMN f1; +DROP TABLE t1; +CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST; +DROP TABLE t1; disconnect analyze; SELECT variable_value-@old_instant instants FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -51 +120 SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; diff --git a/mysql-test/suite/innodb/r/instant_alter_crash.result b/mysql-test/suite/innodb/r/instant_alter_crash.result index d9e57b397f3..807a4091822 100644 --- a/mysql-test/suite/innodb/r/instant_alter_crash.result +++ b/mysql-test/suite/innodb/r/instant_alter_crash.result @@ -29,10 +29,11 @@ BEGIN; DELETE FROM t1; ROLLBACK; InnoDB 0 transactions not purged -INSERT INTO t2 VALUES (64,42,'De finibus bonorum'), (347,33101,' et malorum'); +INSERT INTO t2 VALUES +(16,1551,'Omnium enim rerum'),(128,1571,' principia parva sunt'); connect ddl, localhost, root; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; -ALTER TABLE t2 ADD COLUMN (c4 TEXT NOT NULL DEFAULT ' et malorum'); +ALTER TABLE t2 DROP COLUMN c3, ADD COLUMN c5 TEXT DEFAULT 'naturam abhorrere'; connection default; SET DEBUG_SYNC='now WAIT_FOR ddl'; SET GLOBAL innodb_flush_log_at_trx_commit=1; @@ -46,8 +47,35 @@ id c2 SELECT * FROM t2; id c2 c3 2 1 De finibus bonorum -64 42 De finibus bonorum -347 33101 et malorum +16 1551 Omnium enim rerum +128 1571 principia parva sunt +BEGIN; +INSERT INTO t1 SET id=1; +DELETE FROM t2; +ROLLBACK; +InnoDB 0 transactions not purged +INSERT INTO t2 VALUES (64,42,'De finibus bonorum'), (347,33101,' et malorum'); +connect ddl, localhost, root; +ALTER TABLE t2 DROP COLUMN c3; +SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; +ALTER TABLE t2 ADD COLUMN (c4 TEXT NOT NULL DEFAULT ' et malorum'); +connection default; +SET DEBUG_SYNC='now WAIT_FOR ddl'; +SET GLOBAL innodb_flush_log_at_trx_commit=1; +DELETE FROM t1; +# Kill the server +disconnect ddl; +SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +SELECT * FROM t1; +id c2 +SELECT * FROM t2; +id c2 +2 1 +64 42 +16 1551 +128 1571 +347 33101 BEGIN; INSERT INTO t1 SET id=1; DELETE FROM t2; @@ -59,27 +87,38 @@ N_RECS=0; LEVEL=0 header=0x010000030074 (id=0x696e66696d756d00) header=0x010008030000 (id=0x73757072656d756d00) t2 clustered index root page(type 18): -N_RECS=4; LEVEL=0 -header=0x010000030088 (id=0x696e66696d756d00) -header=0x1000100b00b9 (id=0x80000000, +N_RECS=6; LEVEL=0 +header=0x01000003008f (id=0x0000000000000000) +header=0x3000100c00d4 (id=0x80000000, DB_TRX_ID=0x000000000000, DB_ROLL_PTR=0x80000000000000, + BLOB=0x000000260000000000000008, c2=NULL(4 bytes), c3=0x44652066696e6962757320626f6e6f72756d) -header=0x0000180900d8 (id=0x80000002, +header=0x0000180900f4 (id=0x80000002, DB_TRX_ID=0x000000000000, DB_ROLL_PTR=0x80000000000000, c2=0x80000001) -header=0x0000200900f8 (id=0x80000040, +header=0x0000200b0124 (id=0x80000010, + DB_TRX_ID=0x000000000000, + DB_ROLL_PTR=0x80000000000000, + c2=0x8000060f, + c3=0x4f6d6e69756d20656e696d20726572756d) +header=0x000028090144 (id=0x80000040, DB_TRX_ID=0x000000000000, DB_ROLL_PTR=0x80000000000000, c2=0x8000002a) -header=0x0000280b0074 (id=0x8000015b, +header=0x0000300b0179 (id=0x80000080, + DB_TRX_ID=0x000000000000, + DB_ROLL_PTR=0x80000000000000, + c2=0x80000623, + c3=0x207072696e63697069612070617276612073756e74) +header=0x0000380b0074 (id=0x8000015b, DB_TRX_ID=0x000000000000, DB_ROLL_PTR=0x80000000000000, c2=0x8000814d, c3=0x206574206d616c6f72756d) -header=0x050008030000 (id=0x73757072656d756d00) +header=0x070008030000 (id=0x000000000000000100) UNLOCK TABLES; DELETE FROM t2; InnoDB 0 transactions not purged @@ -96,7 +135,6 @@ Table Create Table t2 CREATE TABLE `t2` ( `id` int(11) NOT NULL, `c2` int(11) DEFAULT NULL, - `c3` text NOT NULL DEFAULT 'De finibus bonorum', PRIMARY KEY (`id`), UNIQUE KEY `c2` (`c2`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 72e42763569..083e0f5cc74 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -1,5 +1,8 @@ SET @save_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +SET @old_instant= +(SELECT variable_value FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'); CREATE TABLE t1 ( pk INT AUTO_INCREMENT PRIMARY KEY, c1 INT, @@ -197,7 +200,8 @@ DELETE FROM t1; connection ddl; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; ALTER TABLE t1 FORCE; -disconnect stop_purge; +connection stop_purge; +COMMIT; connection default; SET DEBUG_SYNC = 'now WAIT_FOR copied'; InnoDB 1 transactions not purged @@ -211,6 +215,29 @@ SELECT * FROM t1; a b c 1 2 NULL 2 3 4 +ALTER TABLE t1 DROP b, ALGORITHM=INSTANT; +connection stop_purge; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +DELETE FROM t1; +connection ddl; +SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; +ALTER TABLE t1 ADD COLUMN b INT NOT NULL DEFAULT 2 AFTER a, FORCE; +disconnect stop_purge; +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +InnoDB 1 transactions not purged +INSERT INTO t1 SET a=1; +INSERT INTO t1 SET a=2,c=4; +SET DEBUG_SYNC = 'now SIGNAL logged'; +connection ddl; +UPDATE t1 SET b = b + 1 WHERE a = 2; +connection default; +SET DEBUG_SYNC = RESET; +SELECT * FROM t1; +a b c +1 2 NULL +2 3 4 # # MDEV-15872 Crash in online ALTER TABLE...ADD PRIMARY KEY # after instant ADD COLUMN ... NULL @@ -236,4 +263,31 @@ a b c d 1 2 NULL 1 2 3 4 1 DROP TABLE t1; +# +# MDEV-17899 Assertion failures on rollback of instant ADD/DROP +# +SET @save_dbug = @@SESSION.debug_dbug; +SET debug_dbug='+d,ib_commit_inplace_fail_1'; +CREATE TABLE t1 (a int, b int) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,2); +ALTER TABLE t1 DROP COLUMN b; +ERROR HY000: Internal error: Injected error! +ALTER TABLE t1 DROP COLUMN b; +ERROR HY000: Internal error: Injected error! +ALTER TABLE t1 ADD COLUMN c INT; +ERROR HY000: Internal error: Injected error! +SELECT * FROM t1; +a b +1 2 +DROP TABLE t1; +CREATE TABLE t1 (a int, b int) ENGINE=InnoDB; +ALTER TABLE t1 ADD COLUMN c INT; +ERROR HY000: Internal error: Injected error! +DROP TABLE t1; +SET debug_dbug = @save_dbug; +SELECT variable_value-@old_instant instants +FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'; +instants +20 SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/mysql-test/suite/innodb/r/instant_alter_limit.result b/mysql-test/suite/innodb/r/instant_alter_limit.result new file mode 100644 index 00000000000..e66579e4a94 --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_limit.result @@ -0,0 +1,35 @@ +SET @old_instant= +(SELECT variable_value FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'); +CREATE TABLE t(a INT PRIMARY KEY, b INT, c INT, d INT, e INT) +ENGINE=InnoDB; +INSERT INTO t VALUES(1,2,3,4,5); +SELECT * FROM t; +b d a c e +NULL NULL 1 NULL NULL +ALTER TABLE t DROP b, DROP c, DROP d, DROP e, +ADD COLUMN b INT, ALGORITHM=INSTANT; +ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE +ALTER TABLE t CHANGE COLUMN b beta INT AFTER a, ALGORITHM=INSTANT; +ALTER TABLE t DROP e, DROP c, DROP d, ALGORITHM=INSTANT; +SELECT * FROM t; +a beta +1 NULL +ALTER TABLE t DROP COLUMN beta, ALGORITHM=INSTANT; +ALTER TABLE t ADD COLUMN b INT NOT NULL, ALGORITHM=INSTANT; +ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE +SELECT variable_value-@old_instant instants +FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'; +instants +256 +ALTER TABLE t ADD COLUMN b INT NOT NULL; +SELECT variable_value-@old_instant instants +FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'; +instants +256 +SELECT * FROM t; +a b +1 0 +DROP TABLE t; diff --git a/mysql-test/suite/innodb/r/instant_alter_null.result b/mysql-test/suite/innodb/r/instant_alter_null.result new file mode 100644 index 00000000000..f49d60fc301 --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_null.result @@ -0,0 +1,56 @@ +create table t (a int NOT NULL) engine=innodb row_format= compressed; +alter table t modify a int NULL, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE +drop table t; +create table t (a int NOT NULL) engine=innodb row_format= dynamic; +alter table t modify a int NULL, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE +drop table t; +create table t (a int NOT NULL) engine=innodb row_format= compact; +alter table t modify a int NULL, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE +drop table t; +create table t ( +id int primary key, +a int NOT NULL default 0, +b int NOT NULL default 0, +c int NOT NULL default 0, +index idx (a,b,c) +) engine=innodb row_format=redundant; +insert into t (id, a) values (0, NULL); +ERROR 23000: Column 'a' cannot be null +insert into t (id, b) values (0, NULL); +ERROR 23000: Column 'b' cannot be null +insert into t (id, c) values (0, NULL); +ERROR 23000: Column 'c' cannot be null +insert into t values (1,1,1,1); +set @id = (select table_id from information_schema.innodb_sys_tables +where name = 'test/t'); +select * from information_schema.innodb_sys_columns where table_id=@id; +TABLE_ID NAME POS MTYPE PRTYPE LEN +TABLE_ID id 0 6 1283 4 +TABLE_ID a 1 6 1283 4 +TABLE_ID b 2 6 1283 4 +TABLE_ID c 3 6 1283 4 +alter table t modify a int NULL, algorithm=instant; +insert into t values (2, NULL, 2, 2); +alter table t modify b int NULL, algorithm=nocopy; +insert into t values (3, NULL, NULL, 3); +alter table t modify c int NULL, algorithm=inplace; +insert into t values (4, NULL, NULL, NULL); +select * from information_schema.innodb_sys_columns where table_id=@id; +TABLE_ID NAME POS MTYPE PRTYPE LEN +TABLE_ID id 0 6 1283 4 +TABLE_ID a 1 6 1027 4 +TABLE_ID b 2 6 1027 4 +TABLE_ID c 3 6 1027 4 +select * from t; +id a b c +4 NULL NULL NULL +3 NULL NULL 3 +2 NULL 2 2 +1 1 1 1 +check table t; +Table Op Msg_type Msg_text +test.t check status OK +drop table t; diff --git a/mysql-test/suite/innodb/r/instant_alter_purge,release.rdiff b/mysql-test/suite/innodb/r/instant_alter_purge,release.rdiff new file mode 100644 index 00000000000..53d2be18f9c --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_purge,release.rdiff @@ -0,0 +1,18 @@ +--- instant_alter_purge.result ++++ instant_alter_purge,release.result +@@ -32,15 +32,11 @@ + START TRANSACTION WITH CONSISTENT SNAPSHOT; + connection default; + DELETE FROM t1; +-SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL go WAIT_FOR do'; + ALTER TABLE t1 ADD COLUMN f3 INT; + connection purge_control; +-SET DEBUG_SYNC='now WAIT_FOR go'; + COMMIT; + InnoDB 0 transactions not purged +-SET DEBUG_SYNC='now SIGNAL do'; + disconnect purge_control; + connection default; +-SET DEBUG_SYNC=RESET; + DROP TABLE t1; + SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/instant_alter_purge.result b/mysql-test/suite/innodb/r/instant_alter_purge.result new file mode 100644 index 00000000000..a3643610f04 --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_purge.result @@ -0,0 +1,46 @@ +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +# +# MDEV-17793 Crash in purge after instant DROP and emptying the table +# +connect prevent_purge,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +CREATE TABLE t1 (f1 INT, f2 INT) ENGINE=InnoDB; +INSERT INTO t1 () VALUES (); +ALTER TABLE t1 DROP f2, ADD COLUMN f2 INT; +ALTER TABLE t1 DROP f1; +DELETE FROM t1; +connection prevent_purge; +COMMIT; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +ALTER TABLE t1 ADD COLUMN extra TINYINT UNSIGNED NOT NULL DEFAULT 42; +InnoDB 1 transactions not purged +ALTER TABLE t1 DROP extra; +disconnect prevent_purge; +InnoDB 0 transactions not purged +DROP TABLE t1; +# +# MDEV-17813 Crash in instant ALTER TABLE due to purge +# concurrently emptying table +# +CREATE TABLE t1 (f2 INT) ENGINE=InnoDB; +INSERT INTO t1 SET f2=1; +ALTER TABLE t1 ADD COLUMN f1 INT; +connect purge_control,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +DELETE FROM t1; +SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL go WAIT_FOR do'; +ALTER TABLE t1 ADD COLUMN f3 INT; +connection purge_control; +SET DEBUG_SYNC='now WAIT_FOR go'; +COMMIT; +InnoDB 0 transactions not purged +SET DEBUG_SYNC='now SIGNAL do'; +disconnect purge_control; +connection default; +SET DEBUG_SYNC=RESET; +DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/instant_alter_rollback.result b/mysql-test/suite/innodb/r/instant_alter_rollback.result index 2c2083adc46..ecf63a20b4a 100644 --- a/mysql-test/suite/innodb/r/instant_alter_rollback.result +++ b/mysql-test/suite/innodb/r/instant_alter_rollback.result @@ -1,24 +1,46 @@ FLUSH TABLES; # # MDEV-11369: Instant ADD COLUMN for InnoDB +# MDEV-15562: Instant DROP COLUMN or changing the order of columns # connect to_be_killed, localhost, root; +SET @old_instant= +(SELECT variable_value FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'); CREATE TABLE empty (id INT PRIMARY KEY, c2 INT UNIQUE) ENGINE=InnoDB; CREATE TABLE once LIKE empty; CREATE TABLE twice LIKE empty; +CREATE TABLE thrice LIKE empty; INSERT INTO once SET id=1,c2=1; INSERT INTO twice SET id=1,c2=1; +INSERT INTO thrice SET id=1,c2=1; ALTER TABLE empty ADD COLUMN (d1 INT DEFAULT 15); ALTER TABLE once ADD COLUMN (d1 INT DEFAULT 20); ALTER TABLE twice ADD COLUMN (d1 INT DEFAULT 20); +ALTER TABLE thrice ADD COLUMN (d1 INT DEFAULT 20); ALTER TABLE twice ADD COLUMN (d2 INT NOT NULL DEFAULT 10, d3 VARCHAR(15) NOT NULL DEFAULT 'var och en char'); +ALTER TABLE thrice ADD COLUMN +(d2 INT NOT NULL DEFAULT 10, +d3 TEXT NOT NULL DEFAULT 'con'); +ALTER TABLE thrice DROP c2, DROP d3, CHANGE d2 d3 INT NOT NULL FIRST; +SELECT variable_value-@old_instant instants +FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'; +instants +7 BEGIN; INSERT INTO empty set id=0,c2=42; UPDATE once set c2=c2+1; UPDATE twice set c2=c2+1; +UPDATE thrice set d3=d3+1; INSERT INTO twice SET id=2,c2=0,d3=''; +INSERT INTO thrice SET id=2,d3=0; +DELETE FROM empty; +DELETE FROM once; +DELETE FROM twice; +DELETE FROM thrice; connection default; SET GLOBAL innodb_flush_log_at_trx_commit=1; CREATE TABLE foo(a INT PRIMARY KEY) ENGINE=InnoDB; @@ -37,4 +59,7 @@ id c2 d1 SELECT * FROM twice; id c2 d1 d2 d3 1 1 20 10 var och en char -DROP TABLE empty, once, twice; +SELECT * FROM thrice; +d3 id d1 +10 1 20 +DROP TABLE empty, once, twice, thrice; diff --git a/mysql-test/suite/innodb/r/instant_drop.result b/mysql-test/suite/innodb/r/instant_drop.result new file mode 100644 index 00000000000..6ac048ef164 --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_drop.result @@ -0,0 +1,191 @@ +create table t1(f1 int not null, f2 int not null, f3 int not null)engine=innodb; +insert into t1 values(1, 2, 3),(4, 5, 6); +alter table t1 drop column f2, algorithm=instant; +select * from t1; +f1 f3 +1 3 +4 6 +insert into t1 values(1,2); +select * from t1; +f1 f3 +1 3 +4 6 +1 2 +alter table t1 add column f4 int not null default 5, algorithm=instant; +select * from t1; +f1 f3 f4 +1 3 5 +4 6 5 +1 2 5 +alter table t1 drop column f1, algorithm=instant; +select * from t1; +f3 f4 +3 5 +6 5 +2 5 +insert into t1 values(7, 9); +select * from t1; +f3 f4 +3 5 +6 5 +2 5 +7 9 +alter table t1 add column f5 blob default repeat('aaa', 950), drop column f4, algorithm=instant; +select * from t1; +f3 f5 +3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +6 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +7 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +select f3 from t1; +f3 +3 +6 +2 +7 +update t1 set f3 = 10 where f3 > 2; +select * from t1; +f3 f5 +10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +delete from t1 where f3 = 10; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f3` int(11) NOT NULL, + `f5` blob DEFAULT repeat('aaa',950) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +select f3 from t1; +f3 +2 +update t1 set f5 = 'world'; +select * from t1; +f3 f5 +2 world +drop table t1; +create table t1(f1 int, f2 int not null, index idx(f2))engine=innodb; +insert into t1 values(1, 2); +alter table t1 drop column f1, add column f3 varchar(100) default 'thiru', algorithm=instant; +select * from t1 force index (idx); +f2 f3 +2 thiru +alter table t1 drop column f3, algorithm=instant; +select * from t1; +f2 +2 +begin; +insert into t1 values(10); +select * from t1; +f2 +2 +10 +update t1 set f2 = 100; +select * from t1; +f2 +100 +100 +delete from t1 where f2 = 100; +select * from t1; +f2 +rollback; +select * from t1; +f2 +2 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f2` int(11) NOT NULL, + KEY `idx` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +drop table t1; +create table t1(f1 int, f2 int not null)engine=innodb; +insert into t1 values(1, 2); +alter table t1 drop column f2, algorithm=instant; +insert into t1 values(NULL); +select * from t1; +f1 +1 +NULL +drop table t1; +create table t1(f1 int not null, f2 int not null)engine=innodb; +insert into t1 values(1, 2); +alter table t1 add column f5 int default 10, algorithm=instant; +alter table t1 add column f3 int not null default 100, algorithm=instant; +alter table t1 add column f4 int default 100, drop column f3, algorithm=instant; +insert into t1 values(2, 3, 20, 100); +select * from t1; +f1 f2 f5 f4 +1 2 10 100 +2 3 20 100 +drop table t1; +create table t1(f1 int not null, f2 int not null) engine=innodb; +insert into t1 values(1, 1); +alter table t1 drop column f2, add column f3 int default 3, algorithm=instant; +select * from t1; +f1 f3 +1 3 +update t1 set f3 = 19; +select * from t1; +f1 f3 +1 19 +alter table t1 drop column f1, add column f5 tinyint default 10 first, +algorithm=instant; +insert into t1 values(4, 10); +select * from t1; +f5 f3 +10 19 +4 10 +create table t2(f1 int, f2 int not null) engine=innodb; +insert into t2(f1, f2) values(1, 2); +alter table t2 drop column f2, add column f4 varchar(100) default repeat('a', 20), add column f5 int default 10, algorithm=instant; +select * from t2; +f1 f4 f5 +1 aaaaaaaaaaaaaaaaaaaa 10 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + `f4` varchar(100) DEFAULT repeat('a',20), + `f5` int(11) DEFAULT 10 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +alter table t2 add column f6 char(100) default repeat('a', 99), algorithm=instant; +create table t3(f1 int, f2 int not null)engine=innodb; +insert into t3 values(1, 2); +alter table t3 drop column f2, add column f3 int default 1, add column f4 int default 4, algorithm=instant; +select * from t1; +f5 f3 +10 19 +4 10 +alter table t1 add column f6 int default 9,drop column f5, algorithm = instant; +insert into t1 values(4, 9); +alter table t1 force, algorithm=inplace; +select * from t1; +f3 f6 +19 9 +10 9 +4 9 +select * from t2; +f1 f4 f5 f6 +1 aaaaaaaaaaaaaaaaaaaa 10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +alter table t2 force, algorithm=inplace; +select * from t2; +f1 f4 f5 f6 +1 aaaaaaaaaaaaaaaaaaaa 10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + `f4` varchar(100) DEFAULT repeat('a',20), + `f5` int(11) DEFAULT 10, + `f6` char(100) DEFAULT repeat('a',99) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +select * from t3; +f1 f3 f4 +1 1 4 +alter table t3 add column f5 char(100) default repeat('a', 99), algorithm=instant; +select * from t3; +f1 f3 f4 f5 +1 1 4 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +drop table t1,t2,t3; diff --git a/mysql-test/suite/innodb/r/monitor.result b/mysql-test/suite/innodb/r/monitor.result index a40bfdac0d0..4a72a37a7ea 100644 --- a/mysql-test/suite/innodb/r/monitor.result +++ b/mysql-test/suite/innodb/r/monitor.result @@ -39,7 +39,6 @@ buffer_pages_written disabled buffer_index_pages_written disabled buffer_non_index_pages_written disabled buffer_pages_read disabled -buffer_pages0_read disabled buffer_index_sec_rec_cluster_reads disabled buffer_index_sec_rec_cluster_reads_avoided disabled buffer_data_reads disabled @@ -148,7 +147,6 @@ trx_nl_ro_commits disabled trx_commits_insert_update disabled trx_rollbacks disabled trx_rollbacks_savepoint disabled -trx_rollback_active disabled trx_active_transactions disabled trx_rseg_history_len disabled trx_undo_slots_used disabled diff --git a/mysql-test/suite/innodb/r/purge_secondary.result b/mysql-test/suite/innodb/r/purge_secondary.result index 8f20f5baacb..1b5f2896887 100644 --- a/mysql-test/suite/innodb/r/purge_secondary.result +++ b/mysql-test/suite/innodb/r/purge_secondary.result @@ -134,6 +134,7 @@ test.t1 check status OK InnoDB 0 transactions not purged ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT OTHER_INDEX_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS WHERE NAME='test/t1'; diff --git a/mysql-test/suite/innodb/r/system_tables.result b/mysql-test/suite/innodb/r/system_tables.result index 79a24f7e455..8789b4f5aff 100644 --- a/mysql-test/suite/innodb/r/system_tables.result +++ b/mysql-test/suite/innodb/r/system_tables.result @@ -5,4 +5,4 @@ select convert_tz(starttime,'UTC','Europe/Moscow') starttime from envois3; starttime 2008-08-12 02:43:00 drop table envois3; -alter table mysql.time_zone_name engine=MyISAM; +alter table mysql.time_zone_name engine=Aria; diff --git a/mysql-test/suite/innodb/r/undo_truncate_recover.result b/mysql-test/suite/innodb/r/undo_truncate_recover.result index 2619f384847..018ac65537a 100644 --- a/mysql-test/suite/innodb/r/undo_truncate_recover.result +++ b/mysql-test/suite/innodb/r/undo_truncate_recover.result @@ -9,7 +9,6 @@ update t1 set c = 'MariaDB'; update t1 set c = 'InnoDB'; set global debug_dbug = '+d,ib_undo_trunc'; commit; -call mtr.add_suppression("InnoDB: The redo log transaction size "); SET GLOBAL innodb_fast_shutdown=0; FOUND 1 /ib_undo_trunc/ in mysqld.1.err drop table t1; diff --git a/mysql-test/suite/innodb/t/alter_table.test b/mysql-test/suite/innodb/t/alter_table.test index 474035436e5..1a43016a38e 100644 --- a/mysql-test/suite/innodb/t/alter_table.test +++ b/mysql-test/suite/innodb/t/alter_table.test @@ -22,3 +22,15 @@ create table t1 ( alter table t1 change column id2 id4 varchar(100) not null; select * from t1 where id4 like 'a'; drop table t1; + +# +# Check that innodb supports transactional=1 +# + +create table t1 (a int) transactional=1 engine=aria; +create table t2 (a int) transactional=1 engine=innodb; +show create table t1; +show create table t2; +alter table t1 engine=innodb; +alter table t1 add column b int; +drop table t1,t2; diff --git a/mysql-test/suite/innodb/t/innodb-alter.test b/mysql-test/suite/innodb/t/innodb-alter.test index 7c9eb47252d..a7f1eb56dce 100644 --- a/mysql-test/suite/innodb/t/innodb-alter.test +++ b/mysql-test/suite/innodb/t/innodb-alter.test @@ -206,7 +206,7 @@ CREATE TABLE tu ( ) ENGINE=InnoDB; --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE tu ADD COLUMN c CHAR(1) NOT NULL FIRST, LOCK=NONE; -# Instant ADD COLUMN (adding after the visible FTS_DOC_ID) +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE tu ADD COLUMN c CHAR(1) NOT NULL, LOCK=NONE; DROP TABLE tu; @@ -217,7 +217,7 @@ CREATE TABLE tv ( ) ENGINE=InnoDB; --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE tv ADD COLUMN c CHAR(1) NOT NULL FIRST, LOCK=NONE; -# Instant ADD COLUMN (adding after the visible FTS_DOC_ID) +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE tv ADD COLUMN c CHAR(1) NOT NULL, LOCK=NONE; DROP TABLE tv; diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test index ca37521b9cf..15f8544088d 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test @@ -1017,20 +1017,6 @@ do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; ib_restore_tablespaces("test_wl5522", "t1"); EOF -# Test failure after importing the cluster index -SET SESSION debug_dbug="+d,ib_import_set_max_rowid_failure"; - ---error ER_NOT_KEYFILE -ALTER TABLE test_wl5522.t1 IMPORT TABLESPACE; - -SET SESSION debug_dbug=@saved_debug_dbug; - -# Left over from the failed IMPORT -perl; -do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; -ib_unlink_tablespace("test_wl5522", "t1"); -EOF - DROP TABLE test_wl5522.t1; --disable_query_log diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index 472b47899db..dd8a67eeec2 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -1253,7 +1253,7 @@ CREATE TABLE t2 (b_id tinyint(4) NOT NULL default '0',b_a tinyint(4) NOT NULL de CONSTRAINT fk_b_a FOREIGN KEY (b_a) REFERENCES t1 (a_id) ON DELETE CASCADE ON UPDATE NO ACTION) ENGINE=InnoDB DEFAULT CHARSET=latin1; --enable_warnings INSERT INTO t2 VALUES (1,1),(2,1),(3,1),(4,2),(5,2); -SELECT * FROM (SELECT t1.*,GROUP_CONCAT(t2.b_id SEPARATOR ',') as b_list FROM (t1 LEFT JOIN (t2) on t1.a_id = t2.b_a) GROUP BY t1.a_id ) AS xyz; +SELECT * FROM (SELECT t1.*,GROUP_CONCAT(t2.b_id SEPARATOR ',') as b_list FROM (t1 LEFT JOIN t2 on t1.a_id = t2.b_a) GROUP BY t1.a_id ) AS xyz; DROP TABLE t2; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/instant_alter.test b/mysql-test/suite/innodb/t/instant_alter.test index 3e62038e591..db2915479ce 100644 --- a/mysql-test/suite/innodb/t/instant_alter.test +++ b/mysql-test/suite/innodb/t/instant_alter.test @@ -361,6 +361,135 @@ COMMIT; --source include/wait_all_purged.inc DROP TABLE t1; +# MDEV-15562 Instant DROP/ADD/reorder columns + +eval CREATE TABLE t1 (a INT, b INT UNIQUE) $engine; +INSERT INTO t1 (a) VALUES (NULL), (NULL); +ALTER TABLE t1 DROP a, ADD COLUMN a INT; +DELETE FROM t1; +BEGIN;INSERT INTO t1 SET a=NULL;ROLLBACK; +DELETE FROM t1; +DROP TABLE t1; + +eval CREATE TABLE t1 (a INT PRIMARY KEY, t VARCHAR(33101) NOT NULL) $engine; +INSERT INTO t1 VALUES(347,''); +ALTER TABLE t1 DROP COLUMN t, ALGORITHM=INSTANT; +SELECT * FROM t1; +DROP TABLE t1; + +eval CREATE TABLE t1 (a INT) $engine; +INSERT INTO t1() VALUES(); +ALTER TABLE t1 ADD COLUMN b INT FIRST, ADD COLUMN c INT AFTER b; +SELECT * FROM t1; +DROP TABLE t1; + +eval CREATE TABLE t1 (t TEXT) $engine; +SET @t=REPEAT('x',@@innodb_page_size / 2); +INSERT INTO t1 VALUES (@t),(@t),(@t),(@t),(@t),(@t),(NULL),(@t),(@t),(@t),(@t); +ALTER TABLE t1 ADD COLUMN a INT FIRST; +UPDATE t1 SET a = 0; +DROP TABLE t1; + +eval CREATE TABLE t1 (t TEXT) $engine; +INSERT INTO t1 SET t = @x; +ALTER TABLE t1 DROP COLUMN t, ADD COLUMN i INT NOT NULL DEFAULT 1; +ALTER TABLE t1 ADD COLUMN t TEXT; +SELECT * FROM t1; +DROP TABLE t1; + +# +# MDEV-17735 Assertion failure in row_parse_int() on first ADD/DROP COLUMN +# when an AUTO_INCREMENT column is not in PRIMARY KEY +# +eval CREATE TABLE t1 (a INT AUTO_INCREMENT, b INT, KEY(a)) $engine; +INSERT INTO t1 SET a=NULL; +ALTER TABLE t1 DROP COLUMN b; +ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 42; +INSERT INTO t1 SET a=NULL; +UPDATE t1 SET a=a+2; +SELECT * FROM t1; +DROP TABLE t1; + +eval CREATE TABLE t1 (i INT) $engine; +INSERT INTO t1 SET i=1; +ALTER TABLE t1 ADD COLUMN b BIT FIRST; +ALTER TABLE t1 ADD COLUMN v INT AS (i) VIRTUAL; +SELECT * FROM t1; +DROP TABLE t1; + +# MDEV-17721 Corrupted data dictionary after instant DROP COLUMN +eval CREATE TABLE t1 (ts TIMESTAMP) $engine; +ALTER TABLE t1 ADD COLUMN f VARCHAR(8), ADD COLUMN dt DATETIME; +ALTER TABLE t1 ADD COLUMN b BIT, DROP COLUMN f, ADD COLUMN t TIME FIRST; +ALTER TABLE t1 ADD COLUMN ts2 TIMESTAMP; +DROP TABLE t1; + +eval CREATE TABLE t1 (f1 INT, f2 INT, f3 INT) $engine; +INSERT INTO t1 VALUES (4,4,4); +ALTER TABLE t1 DROP f1, DROP f2, ADD f4 INT, ADD f5 INT; +DELETE FROM t1; +ALTER TABLE t1 DROP COLUMN f4; +DROP TABLE t1; + +eval CREATE TABLE t1 (f1 INT, f2 INT, f3 INT) $engine; +ALTER TABLE t1 DROP f2, ADD COLUMN f4 INT; +ALTER TABLE t1 DROP f4; +ALTER TABLE t1 DROP f1; +DROP TABLE t1; + +# MDEV-17901 Crash after instant DROP COLUMN of AUTO_INCREMENT column +eval CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT, f INT, KEY(id)) $engine; +ALTER TABLE t1 DROP COLUMN id; +INSERT INTO t1 () VALUES (),(); +SELECT * FROM t1; +# Adding AUTO_INCREMENT column will always require rebuild. +ALTER TABLE t1 ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, ADD KEY(id); +SELECT * FROM t1; +DROP TABLE t1; + +# MDEV-17763 Assertion `len == 20U' failed in rec_convert_dtuple_to_rec_comp +# upon DROP COLUMN +eval CREATE TABLE t1 ( + pk INT PRIMARY KEY, + f1 INT, + f2 CHAR(255), + f3 BIGINT, + f4 INT, + f5 CHAR(255), + f6 CHAR(255), + f7 CHAR(255) NOT NULL, + f8 INT, + f9 CHAR(10) +) $engine; + +INSERT INTO t1 VALUES + (1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a'), + (2, 2, 'b', 2, 2, 'b', 'b', 'b', 2, 'b'), + (3, 3, 'c', 3, 3, 'c', 'c', 'c', 3, 'c'), + (4, 4, 'd', 4, 4, 'd', 'd', 'd', 4, 'd'), + (5, 5, 'e', 5, 5, 'e', 'e', 'e', 5, 'e'), + (6, 6, 'f', 6, 6, 'f', 'f', 'f', 6, 'f'), + (7, 7, 'g', 7, 7, 'g', 'g', 'g', 7, 'g'), + (8, 8, 'h', 8, 8, 'h', 'h', 'h', 8, 'h'), + (9, 9, 'i', 9, 9, 'i', 'i', 'i', 9, 'i'), + (10, 0, 'j', 0, 0, 'j', 'j', 'j', 0, 'j'), + (11, 1, 'k', 1, 1, 'k', 'k', 'k', 1, 'k'), + (12, 2, 'l', 2, 2, 'l', 'l', 'l', 2, 'l'), + (13, 3, 'm', 3, 3, 'm', 'm', 'm', 3, 'm'), + (14, 4, 'n', 4, 4, 'n', 'n', 'n', 4, 'n'), + (15, 5, 'o', 5, 5, 'o', 'o', 'o', 5, 'o'); + +DELETE FROM t1 WHERE pk=1; +--source include/wait_all_purged.inc +INSERT INTO t1 VALUES + (1, 1, 'a', 1, 1, 'a', 'a', 'a', 1, 'a'); +ALTER TABLE t1 DROP COLUMN f1; +DROP TABLE t1; + +eval CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) $engine; +ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST; +DROP TABLE t1; + dec $format; } disconnect analyze; diff --git a/mysql-test/suite/innodb/t/instant_alter_crash.test b/mysql-test/suite/innodb/t/instant_alter_crash.test index fe7301b4f78..b1615041393 100644 --- a/mysql-test/suite/innodb/t/instant_alter_crash.test +++ b/mysql-test/suite/innodb/t/instant_alter_crash.test @@ -43,9 +43,38 @@ DELETE FROM t1; ROLLBACK; --source include/wait_all_purged.inc +INSERT INTO t2 VALUES +(16,1551,'Omnium enim rerum'),(128,1571,' principia parva sunt'); + +connect ddl, localhost, root; +SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; +--send +ALTER TABLE t2 DROP COLUMN c3, ADD COLUMN c5 TEXT DEFAULT 'naturam abhorrere'; + +connection default; +SET DEBUG_SYNC='now WAIT_FOR ddl'; +SET GLOBAL innodb_flush_log_at_trx_commit=1; +DELETE FROM t1; + +--source include/kill_mysqld.inc +disconnect ddl; +--source include/start_mysqld.inc + +SET @saved_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; + +SELECT * FROM t1; +SELECT * FROM t2; +BEGIN; +INSERT INTO t1 SET id=1; +DELETE FROM t2; +ROLLBACK; +--source include/wait_all_purged.inc + INSERT INTO t2 VALUES (64,42,'De finibus bonorum'), (347,33101,' et malorum'); connect ddl, localhost, root; +ALTER TABLE t2 DROP COLUMN c3; SET DEBUG_SYNC='innodb_alter_inplace_before_commit SIGNAL ddl WAIT_FOR ever'; --send ALTER TABLE t2 ADD COLUMN (c4 TEXT NOT NULL DEFAULT ' et malorum'); @@ -96,16 +125,39 @@ for (my $offset= 0x65; $offset; my $n_fields= unpack("n", substr($page,$offset-4,2)) >> 1 & 0x3ff; my $start= 0; my $name; - for (my $i= 0; $i < $n_fields; $i++) { - my $end= unpack("C", substr($page, $offset-7-$i, 1)); - print ",\n " if $i; - print "$fields[$i]="; - if ($end & 0x80) { - print "NULL(", ($end & 0x7f) - $start, " bytes)" - } else { - print "0x", unpack("H*", substr($page,$offset+$start,$end-$start)) + if (unpack("C", substr($page,$offset-3,1)) & 1) { + for (my $i= 0; $i < $n_fields; $i++) { + my $end= unpack("C", substr($page, $offset-7-$i, 1)); + print ",\n " if $i; + print "$fields[$i]="; + if ($end & 0x80) { + print "NULL(", ($end & 0x7f) - $start, " bytes)" + } else { + print "0x", unpack("H*", substr($page,$offset+$start,$end-$start)) + } + $start= $end & 0x7f; + } + } else { + for (my $i= 0; $i < $n_fields; $i++) { + my $end= unpack("n", substr($page, $offset-8-2*$i, 2)); + print ",\n " if $i; + if ($i > 2 && !(~unpack("C",substr($page,$offset-6,1)) & 0x30)) { + if ($i == 3) { + print "BLOB="; + $start += 8; # skip the space_id,page_number + } else { + print "$fields[$i - 1]="; + } + } else { + print "$fields[$i]="; + } + if ($end & 0x8000) { + print "NULL(", ($end & 0x7fff) - $start, " bytes)" + } else { + print "0x", unpack("H*", substr($page,$offset+$start,($end-$start) & 0x3fff)) + } + $start= $end & 0x3fff; } - $start= $end & 0x7f; } print ")\n"; } diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index cab9decd3d0..f15b9ccf9ef 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -5,6 +5,10 @@ SET @save_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +SET @old_instant= +(SELECT variable_value FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'); + CREATE TABLE t1 ( pk INT AUTO_INCREMENT PRIMARY KEY, c1 INT, @@ -222,7 +226,8 @@ connection ddl; SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; send ALTER TABLE t1 FORCE; -disconnect stop_purge; +connection stop_purge; +COMMIT; connection default; SET DEBUG_SYNC = 'now WAIT_FOR copied'; @@ -238,6 +243,34 @@ reap; connection default; SET DEBUG_SYNC = RESET; SELECT * FROM t1; +ALTER TABLE t1 DROP b, ALGORITHM=INSTANT; +connection stop_purge; +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +DELETE FROM t1; + +connection ddl; +SET DEBUG_SYNC='row_log_table_apply1_before SIGNAL copied WAIT_FOR logged'; +send ALTER TABLE t1 ADD COLUMN b INT NOT NULL DEFAULT 2 AFTER a, FORCE; + +disconnect stop_purge; + +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR copied'; +let $wait_all_purged = 1; +--source include/wait_all_purged.inc +INSERT INTO t1 SET a=1; +INSERT INTO t1 SET a=2,c=4; +SET DEBUG_SYNC = 'now SIGNAL logged'; + +connection ddl; +reap; +UPDATE t1 SET b = b + 1 WHERE a = 2; + +connection default; +SET DEBUG_SYNC = RESET; +SELECT * FROM t1; --echo # --echo # MDEV-15872 Crash in online ALTER TABLE...ADD PRIMARY KEY @@ -267,4 +300,32 @@ SET DEBUG_SYNC = RESET; SELECT * FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-17899 Assertion failures on rollback of instant ADD/DROP +--echo # + +SET @save_dbug = @@SESSION.debug_dbug; +SET debug_dbug='+d,ib_commit_inplace_fail_1'; +CREATE TABLE t1 (a int, b int) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,2); +--error ER_INTERNAL_ERROR +ALTER TABLE t1 DROP COLUMN b; +--error ER_INTERNAL_ERROR +ALTER TABLE t1 DROP COLUMN b; +--error ER_INTERNAL_ERROR +ALTER TABLE t1 ADD COLUMN c INT; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (a int, b int) ENGINE=InnoDB; +--error ER_INTERNAL_ERROR +ALTER TABLE t1 ADD COLUMN c INT; +DROP TABLE t1; + +SET debug_dbug = @save_dbug; + +SELECT variable_value-@old_instant instants +FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'; + SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/mysql-test/suite/innodb/t/instant_alter_limit.test b/mysql-test/suite/innodb/t/instant_alter_limit.test new file mode 100644 index 00000000000..ded14eee89b --- /dev/null +++ b/mysql-test/suite/innodb/t/instant_alter_limit.test @@ -0,0 +1,42 @@ +--source include/have_innodb.inc + +SET @old_instant= +(SELECT variable_value FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'); + +CREATE TABLE t(a INT PRIMARY KEY, b INT, c INT, d INT, e INT) +ENGINE=InnoDB; +INSERT INTO t VALUES(1,2,3,4,5); +--disable_query_log +let $n=253; +while ($n) { +dec $n; +ALTER TABLE t DROP b, DROP c, DROP d, DROP e, +ADD COLUMN b INT FIRST, ADD COLUMN c INT, ADD COLUMN d INT AFTER b, +ADD COLUMN e INT AFTER c, ALGORITHM=INSTANT; +} +--enable_query_log +SELECT * FROM t; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t DROP b, DROP c, DROP d, DROP e, +ADD COLUMN b INT, ALGORITHM=INSTANT; +ALTER TABLE t CHANGE COLUMN b beta INT AFTER a, ALGORITHM=INSTANT; +ALTER TABLE t DROP e, DROP c, DROP d, ALGORITHM=INSTANT; +SELECT * FROM t; +ALTER TABLE t DROP COLUMN beta, ALGORITHM=INSTANT; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +ALTER TABLE t ADD COLUMN b INT NOT NULL, ALGORITHM=INSTANT; + +SELECT variable_value-@old_instant instants +FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'; + +ALTER TABLE t ADD COLUMN b INT NOT NULL; + +SELECT variable_value-@old_instant instants +FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'; + +SELECT * FROM t; + +DROP TABLE t; diff --git a/mysql-test/suite/innodb/t/instant_alter_null.test b/mysql-test/suite/innodb/t/instant_alter_null.test new file mode 100644 index 00000000000..69fb1ae4495 --- /dev/null +++ b/mysql-test/suite/innodb/t/instant_alter_null.test @@ -0,0 +1,57 @@ +--source include/have_innodb.inc + +create table t (a int NOT NULL) engine=innodb row_format= compressed; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t modify a int NULL, algorithm=instant; +drop table t; + +create table t (a int NOT NULL) engine=innodb row_format= dynamic; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t modify a int NULL, algorithm=instant; +drop table t; + +create table t (a int NOT NULL) engine=innodb row_format= compact; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t modify a int NULL, algorithm=instant; +drop table t; + +create table t ( + id int primary key, + a int NOT NULL default 0, + b int NOT NULL default 0, + c int NOT NULL default 0, + index idx (a,b,c) +) engine=innodb row_format=redundant; + +--error ER_BAD_NULL_ERROR +insert into t (id, a) values (0, NULL); +--error ER_BAD_NULL_ERROR +insert into t (id, b) values (0, NULL); +--error ER_BAD_NULL_ERROR +insert into t (id, c) values (0, NULL); + +insert into t values (1,1,1,1); + +set @id = (select table_id from information_schema.innodb_sys_tables +where name = 'test/t'); + +--replace_column 1 TABLE_ID +select * from information_schema.innodb_sys_columns where table_id=@id; + +alter table t modify a int NULL, algorithm=instant; +insert into t values (2, NULL, 2, 2); + +alter table t modify b int NULL, algorithm=nocopy; +insert into t values (3, NULL, NULL, 3); + +alter table t modify c int NULL, algorithm=inplace; +insert into t values (4, NULL, NULL, NULL); + +--replace_column 1 TABLE_ID +select * from information_schema.innodb_sys_columns where table_id=@id; + +select * from t; + +check table t; + +drop table t; diff --git a/mysql-test/suite/innodb/t/instant_alter_purge.test b/mysql-test/suite/innodb/t/instant_alter_purge.test new file mode 100644 index 00000000000..152d200d977 --- /dev/null +++ b/mysql-test/suite/innodb/t/instant_alter_purge.test @@ -0,0 +1,75 @@ +--source include/have_innodb.inc +--source include/maybe_debug.inc +if ($have_debug) { +--source include/have_debug_sync.inc +} + +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency=1; + +--echo # +--echo # MDEV-17793 Crash in purge after instant DROP and emptying the table +--echo # + +connect (prevent_purge,localhost,root); +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +CREATE TABLE t1 (f1 INT, f2 INT) ENGINE=InnoDB; +INSERT INTO t1 () VALUES (); +ALTER TABLE t1 DROP f2, ADD COLUMN f2 INT; +ALTER TABLE t1 DROP f1; +DELETE FROM t1; + +connection prevent_purge; +COMMIT; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; + +ALTER TABLE t1 ADD COLUMN extra TINYINT UNSIGNED NOT NULL DEFAULT 42; +let $wait_all_purged= 1; +--source include/wait_all_purged.inc +ALTER TABLE t1 DROP extra; +disconnect prevent_purge; +let $wait_all_purged= 0; +--source include/wait_all_purged.inc +DROP TABLE t1; + +--echo # +--echo # MDEV-17813 Crash in instant ALTER TABLE due to purge +--echo # concurrently emptying table +--echo # +CREATE TABLE t1 (f2 INT) ENGINE=InnoDB; +INSERT INTO t1 SET f2=1; +ALTER TABLE t1 ADD COLUMN f1 INT; + +connect (purge_control,localhost,root); +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +connection default; +DELETE FROM t1; + +if ($have_debug) { +SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL go WAIT_FOR do'; +} +send ALTER TABLE t1 ADD COLUMN f3 INT; + +connection purge_control; +if ($have_debug) { +SET DEBUG_SYNC='now WAIT_FOR go'; +} +COMMIT; +--source include/wait_all_purged.inc +if ($have_debug) { +SET DEBUG_SYNC='now SIGNAL do'; +} +disconnect purge_control; + +connection default; +reap; +if ($have_debug) { +SET DEBUG_SYNC=RESET; +} +DROP TABLE t1; + +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/t/instant_alter_rollback.test b/mysql-test/suite/innodb/t/instant_alter_rollback.test index b68a6ad3880..cfece7e0738 100644 --- a/mysql-test/suite/innodb/t/instant_alter_rollback.test +++ b/mysql-test/suite/innodb/t/instant_alter_rollback.test @@ -8,28 +8,49 @@ FLUSH TABLES; --echo # --echo # MDEV-11369: Instant ADD COLUMN for InnoDB +--echo # MDEV-15562: Instant DROP COLUMN or changing the order of columns --echo # connect to_be_killed, localhost, root; +SET @old_instant= +(SELECT variable_value FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'); CREATE TABLE empty (id INT PRIMARY KEY, c2 INT UNIQUE) ENGINE=InnoDB; CREATE TABLE once LIKE empty; CREATE TABLE twice LIKE empty; +CREATE TABLE thrice LIKE empty; INSERT INTO once SET id=1,c2=1; INSERT INTO twice SET id=1,c2=1; +INSERT INTO thrice SET id=1,c2=1; ALTER TABLE empty ADD COLUMN (d1 INT DEFAULT 15); ALTER TABLE once ADD COLUMN (d1 INT DEFAULT 20); ALTER TABLE twice ADD COLUMN (d1 INT DEFAULT 20); +ALTER TABLE thrice ADD COLUMN (d1 INT DEFAULT 20); ALTER TABLE twice ADD COLUMN (d2 INT NOT NULL DEFAULT 10, d3 VARCHAR(15) NOT NULL DEFAULT 'var och en char'); +ALTER TABLE thrice ADD COLUMN +(d2 INT NOT NULL DEFAULT 10, + d3 TEXT NOT NULL DEFAULT 'con'); +ALTER TABLE thrice DROP c2, DROP d3, CHANGE d2 d3 INT NOT NULL FIRST; + +SELECT variable_value-@old_instant instants +FROM information_schema.global_status +WHERE variable_name = 'innodb_instant_alter_column'; BEGIN; INSERT INTO empty set id=0,c2=42; UPDATE once set c2=c2+1; UPDATE twice set c2=c2+1; +UPDATE thrice set d3=d3+1; INSERT INTO twice SET id=2,c2=0,d3=''; +INSERT INTO thrice SET id=2,d3=0; +DELETE FROM empty; +DELETE FROM once; +DELETE FROM twice; +DELETE FROM thrice; connection default; SET GLOBAL innodb_flush_log_at_trx_commit=1; @@ -48,4 +69,5 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency=@saved_frequency; SELECT * FROM empty; SELECT * FROM once; SELECT * FROM twice; -DROP TABLE empty, once, twice; +SELECT * FROM thrice; +DROP TABLE empty, once, twice, thrice; diff --git a/mysql-test/suite/innodb/t/instant_drop.test b/mysql-test/suite/innodb/t/instant_drop.test new file mode 100644 index 00000000000..cb1aabce94b --- /dev/null +++ b/mysql-test/suite/innodb/t/instant_drop.test @@ -0,0 +1,99 @@ +--source include/have_innodb.inc + +create table t1(f1 int not null, f2 int not null, f3 int not null)engine=innodb; +insert into t1 values(1, 2, 3),(4, 5, 6); +alter table t1 drop column f2, algorithm=instant; +select * from t1; +insert into t1 values(1,2); +select * from t1; +alter table t1 add column f4 int not null default 5, algorithm=instant; +select * from t1; +alter table t1 drop column f1, algorithm=instant; +select * from t1; +insert into t1 values(7, 9); +select * from t1; +alter table t1 add column f5 blob default repeat('aaa', 950), drop column f4, algorithm=instant; +select * from t1; +select f3 from t1; +update t1 set f3 = 10 where f3 > 2; +select * from t1; +delete from t1 where f3 = 10; +show create table t1; +select f3 from t1; +update t1 set f5 = 'world'; +select * from t1; +drop table t1; + +create table t1(f1 int, f2 int not null, index idx(f2))engine=innodb; +insert into t1 values(1, 2); +alter table t1 drop column f1, add column f3 varchar(100) default 'thiru', algorithm=instant; +select * from t1 force index (idx); +alter table t1 drop column f3, algorithm=instant; +select * from t1; +begin; +insert into t1 values(10); +select * from t1; +update t1 set f2 = 100; +select * from t1; +delete from t1 where f2 = 100; +select * from t1; +rollback; +select * from t1; +show create table t1; +drop table t1; + +create table t1(f1 int, f2 int not null)engine=innodb; +insert into t1 values(1, 2); +alter table t1 drop column f2, algorithm=instant; +insert into t1 values(NULL); +select * from t1; +drop table t1; + +create table t1(f1 int not null, f2 int not null)engine=innodb; +insert into t1 values(1, 2); +alter table t1 add column f5 int default 10, algorithm=instant; +alter table t1 add column f3 int not null default 100, algorithm=instant; +alter table t1 add column f4 int default 100, drop column f3, algorithm=instant; +insert into t1 values(2, 3, 20, 100); +select * from t1; +drop table t1; + +create table t1(f1 int not null, f2 int not null) engine=innodb; +insert into t1 values(1, 1); +alter table t1 drop column f2, add column f3 int default 3, algorithm=instant; +select * from t1; +update t1 set f3 = 19; +select * from t1; +alter table t1 drop column f1, add column f5 tinyint default 10 first, +algorithm=instant; +insert into t1 values(4, 10); +select * from t1; + +create table t2(f1 int, f2 int not null) engine=innodb; +insert into t2(f1, f2) values(1, 2); +alter table t2 drop column f2, add column f4 varchar(100) default repeat('a', 20), add column f5 int default 10, algorithm=instant; +select * from t2; +show create table t2; +alter table t2 add column f6 char(100) default repeat('a', 99), algorithm=instant; + +create table t3(f1 int, f2 int not null)engine=innodb; +insert into t3 values(1, 2); +alter table t3 drop column f2, add column f3 int default 1, add column f4 int default 4, algorithm=instant; + +--source include/restart_mysqld.inc +select * from t1; +alter table t1 add column f6 int default 9,drop column f5, algorithm = instant; +insert into t1 values(4, 9); +alter table t1 force, algorithm=inplace; +select * from t1; + +select * from t2; +alter table t2 force, algorithm=inplace; +select * from t2; +show create table t2; + +select * from t3; +alter table t3 add column f5 char(100) default repeat('a', 99), algorithm=instant; +--source include/restart_mysqld.inc +select * from t3; +drop table t1,t2,t3; diff --git a/mysql-test/suite/innodb/t/purge_thread_shutdown.test b/mysql-test/suite/innodb/t/purge_thread_shutdown.test index 8a9a834454c..5be29b7a6a3 100644 --- a/mysql-test/suite/innodb/t/purge_thread_shutdown.test +++ b/mysql-test/suite/innodb/t/purge_thread_shutdown.test @@ -32,7 +32,9 @@ delete from t1 where a=3; error ER_WRONG_VALUE_FOR_VAR; set global innodb_fast_shutdown=0; -let $me=`select connection_id()`; +# Get id with space prefix to ensure that replace_result doesn't replace +# the error code +let $me=`select concat(' ', connection_id())`; replace_result $me ID; error ER_CONNECTION_KILLED; eval kill $me; diff --git a/mysql-test/suite/innodb/t/system_tables.test b/mysql-test/suite/innodb/t/system_tables.test index 90cb8c59fbd..172628790f8 100644 --- a/mysql-test/suite/innodb/t/system_tables.test +++ b/mysql-test/suite/innodb/t/system_tables.test @@ -9,4 +9,4 @@ insert envois3 values ('2008-08-11 22:43:00'); --source include/restart_mysqld.inc select convert_tz(starttime,'UTC','Europe/Moscow') starttime from envois3; drop table envois3; -alter table mysql.time_zone_name engine=MyISAM; +alter table mysql.time_zone_name engine=Aria; diff --git a/mysql-test/suite/innodb/t/undo_truncate.opt b/mysql-test/suite/innodb/t/undo_truncate.opt deleted file mode 100644 index 1c897ab6cfc..00000000000 --- a/mysql-test/suite/innodb/t/undo_truncate.opt +++ /dev/null @@ -1 +0,0 @@ ---innodb-log-buffer-size=2m diff --git a/mysql-test/suite/innodb/t/undo_truncate.test b/mysql-test/suite/innodb/t/undo_truncate.test index 9b91c78e35a..af6ed2b4372 100644 --- a/mysql-test/suite/innodb/t/undo_truncate.test +++ b/mysql-test/suite/innodb/t/undo_truncate.test @@ -1,9 +1,5 @@ --source include/have_innodb.inc -# With 32k, truncation could happen on shutdown after the test, -# and the mtr.add_suppression() would not filter out the warning. -# With 64k, no truncation seems to happen. -# --source include/innodb_page_size.inc ---source include/innodb_page_size_small.inc +--source include/innodb_page_size.inc --source include/have_undo_tablespaces.inc SET @save_undo_logs = @@GLOBAL.innodb_undo_logs; diff --git a/mysql-test/suite/innodb/t/undo_truncate_recover.test b/mysql-test/suite/innodb/t/undo_truncate_recover.test index 56647bcc567..d31bc7821ac 100644 --- a/mysql-test/suite/innodb/t/undo_truncate_recover.test +++ b/mysql-test/suite/innodb/t/undo_truncate_recover.test @@ -38,13 +38,9 @@ update t1 set c = 'MariaDB'; update t1 set c = 'InnoDB'; eval set global debug_dbug = '+d,$SEARCH_PATTERN'; commit; -# FIXME: remove this work-around, and generate less log! -call mtr.add_suppression("InnoDB: The redo log transaction size "); SET GLOBAL innodb_fast_shutdown=0; --source include/shutdown_mysqld.inc --source include/search_pattern_in_file.inc -# FIXME: remove this work-around, and generate less log! ---let $restart_parameters= --innodb-buffer-pool-size=16m --source include/start_mysqld.inc drop table t1; diff --git a/mysql-test/suite/innodb_fts/r/fulltext_order_by.result b/mysql-test/suite/innodb_fts/r/fulltext_order_by.result index 503f117d02f..0d3a4a85b86 100644 --- a/mysql-test/suite/innodb_fts/r/fulltext_order_by.result +++ b/mysql-test/suite/innodb_fts/r/fulltext_order_by.result @@ -129,7 +129,7 @@ group by a.text, b.id, b.betreff order by match(b.betreff) against ('+abc' in boolean mode) desc; -ERROR 42000: Table 'b' from one of the SELECTs cannot be used in field list +ERROR 42000: Table 'b' from one of the SELECTs cannot be used in ORDER clause select a.text, b.id, b.betreff from t2 a inner join t3 b on a.id = b.forum inner join @@ -145,7 +145,7 @@ where match(c.beitrag) against ('+abc' in boolean mode) order by match(b.betreff) against ('+abc' in boolean mode) desc; -ERROR 42000: Table 'b' from one of the SELECTs cannot be used in field list +ERROR 42000: Table 'b' from one of the SELECTs cannot be used in ORDER clause select a.text, b.id, b.betreff from t2 a inner join t3 b on a.id = b.forum inner join diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-fic.result b/mysql-test/suite/innodb_fts/r/innodb-fts-fic.result index 36d3826be59..f998881f11b 100644 --- a/mysql-test/suite/innodb_fts/r/innodb-fts-fic.result +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-fic.result @@ -36,6 +36,8 @@ count 2 ANALYZE TABLE articles; Table Op Msg_type Msg_text +test.articles analyze status Engine-independent statistics collected +test.articles analyze Warning Engine-independent statistics are not collected for column 'body' test.articles analyze status OK SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE); diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-stopword.result b/mysql-test/suite/innodb_fts/r/innodb-fts-stopword.result index dea2f2360da..cad1acb3b01 100644 --- a/mysql-test/suite/innodb_fts/r/innodb-fts-stopword.result +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-stopword.result @@ -249,6 +249,8 @@ articles CREATE TABLE `articles` ( ALTER TABLE articles ADD FULLTEXT INDEX idx (title,body); ANALYZE TABLE articles; Table Op Msg_type Msg_text +test.articles analyze status Engine-independent statistics collected +test.articles analyze Warning Engine-independent statistics are not collected for column 'body' test.articles analyze status OK SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); id title body @@ -571,6 +573,8 @@ select @@innodb_ft_enable_stopword; 1 ANALYZE TABLE articles; Table Op Msg_type Msg_text +test.articles analyze status Engine-independent statistics collected +test.articles analyze Warning Engine-independent statistics are not collected for column 'body' test.articles analyze status OK SELECT * FROM articles WHERE MATCH(title,body) AGAINST ("where will"); id title body diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result b/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result index aec3d7f777d..431a95442e6 100644 --- a/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result +++ b/mysql-test/suite/innodb_fts/r/innodb_fts_misc_1.result @@ -37,9 +37,13 @@ DELETE FROM t1; ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a2`) REFERENCES `t1` (`a1`) ON UPDATE CASCADE) ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b1' test.t1 analyze status OK ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze Warning Engine-independent statistics are not collected for column 'b2' test.t2 analyze status OK SELECT id1 FROM t1 WHERE MATCH (a1,b1) AGAINST ('tutorial') ORDER BY id1; id1 diff --git a/mysql-test/suite/innodb_gis/r/alter_spatial_index.result b/mysql-test/suite/innodb_gis/r/alter_spatial_index.result index d94e67d0765..2253c62bebf 100644 --- a/mysql-test/suite/innodb_gis/r/alter_spatial_index.result +++ b/mysql-test/suite/innodb_gis/r/alter_spatial_index.result @@ -464,6 +464,7 @@ ST_GeomFromText('POLYGON((5010 5010,5020 5020,5030 5030,5040 5030,5020 5010,5010 ST_GeomFromText('POLYGON((5010 5010,5020 5020,5030 5030,5040 5030,5020 5010,5010 5010))')); ANALYZE TABLE tab; Table Op Msg_type Msg_text +test.tab analyze status Engine-independent statistics collected test.tab analyze status OK ALTER TABLE tab ADD SPATIAL INDEX idx2(c2 ASC); affected rows: 0 @@ -521,7 +522,7 @@ HEX(c8) ROLLBACK; ALTER TABLE tab add COLUMN c9 POINT NOT NULL AFTER c5, ALGORITHM = INPLACE, LOCK=NONE; -ERROR 0A000: LOCK=NONE is not supported. Reason: Do not support online operation on table with GIS index. Try LOCK=SHARED +ALTER TABLE tab DROP COLUMN c9, ALGORITHM=INSTANT; SHOW CREATE TABLE tab; Table Create Table tab CREATE TABLE `tab` ( @@ -586,6 +587,7 @@ tab 1 idx5 1 c5 A # 32 NULL SPATIAL testing spatial index on Geometry tab 1 idx6 1 c4 A # 10 NULL BTREE ANALYZE TABLE tab; Table Op Msg_type Msg_text +test.tab analyze status Engine-independent statistics collected test.tab analyze status OK SET @g1 = ST_GeomFromText('POLYGON((5010 5010,5020 5020,5030 5030,5040 5030,5020 5010,5010 5010))'); SET @g2 = ST_GeomFromText('LINESTRING(140 140,150 150,160 160)'); @@ -605,6 +607,7 @@ AND MBREquals(tab.c3,@g2) ORDER BY c1; c1 ST_Astext(c2) ST_AsText(c3) ST_Astext(c4) ANALYZE TABLE tab; Table Op Msg_type Msg_text +test.tab analyze status Engine-independent statistics collected test.tab analyze status OK SET @g1 = ST_GeomFromText('POLYGON((4010 4010,4020 4020,4030 4030,4040 4030,4020 4010,4010 4010))'); SET @g2 = ST_GeomFromText('LINESTRING(1 1,2 2,3 3)'); @@ -644,6 +647,7 @@ tab 1 idx5 1 c5 A # 32 NULL SPATIAL testing spatial index on Geometry tab 1 idx6 1 c4 A # 10 NULL BTREE ANALYZE TABLE tab; Table Op Msg_type Msg_text +test.tab analyze status Engine-independent statistics collected test.tab analyze status OK SET @g1 = ST_GeomFromText( 'POLYGON((0 0,0 30,30 40,40 50,50 30,0 0))'); SET @g2 = ST_GeomFromText('LINESTRING(1 1,2 2,3 3)'); @@ -678,6 +682,7 @@ ALTER TABLE tab ENGINE Myisam; ALTER TABLE tab ENGINE InnoDB; ANALYZE TABLE tab; Table Op Msg_type Msg_text +test.tab analyze status Engine-independent statistics collected test.tab analyze status OK SET @g1 = ST_GeomFromText('POLYGON((1010 1010,1020 1020,1030 1030,1040 1030,1020 1010,1010 1010))'); SET @g2 = ST_GeomFromText('LINESTRING(400 400,500 500,600 700)'); diff --git a/mysql-test/suite/innodb_gis/r/create_spatial_index.result b/mysql-test/suite/innodb_gis/r/create_spatial_index.result index 1af03c251bf..c69d67c411f 100644 --- a/mysql-test/suite/innodb_gis/r/create_spatial_index.result +++ b/mysql-test/suite/innodb_gis/r/create_spatial_index.result @@ -55,6 +55,7 @@ ST_GeomFromText('POLYGON((5010 5010,5020 5020,5030 5030,5040 5030,5020 5010,5010 ST_GeomFromText('POLYGON((5010 5010,5020 5020,5030 5030,5040 5030,5020 5010,5010 5010))')); ANALYZE TABLE tab; Table Op Msg_type Msg_text +test.tab analyze status Engine-independent statistics collected test.tab analyze status OK SET @g1 = ST_GeomFromText( 'POLYGON((7 1,6 2,6 3,10 3,10 1,7 1))'); EXPLAIN SELECT c1,ST_Astext(c4) FROM tab WHERE MBRContains(tab.c4, @g1) ORDER BY c1; @@ -483,6 +484,7 @@ ST_GeomFromText('POLYGON((5010 5010,5020 5020,5030 5030,5040 5030,5020 5010,5010 ST_GeomFromText('POLYGON((5010 5010,5020 5020,5030 5030,5040 5030,5020 5010,5010 5010))')); ANALYZE TABLE tab; Table Op Msg_type Msg_text +test.tab analyze status Engine-independent statistics collected test.tab analyze status OK SET @g1 = ST_GeomFromText( 'POLYGON((7 1,6 2,6 3,10 3,10 1,7 1))'); EXPLAIN SELECT c1,ST_Astext(c4) FROM tab WHERE MBRContains(tab.c4, @g1) ORDER BY c1; @@ -900,6 +902,7 @@ ST_GeomFromText('POLYGON((5010 5010,5020 5020,5030 5030,5040 5030,5020 5010,5010 ST_GeomFromText('POLYGON((5010 5010,5020 5020,5030 5030,5040 5030,5020 5010,5010 5010))')); ANALYZE TABLE tab; Table Op Msg_type Msg_text +test.tab analyze status Engine-independent statistics collected test.tab analyze status OK SET @g1 = ST_GeomFromText( 'POLYGON((7 1,6 2,6 3,10 3,10 1,7 1))'); EXPLAIN SELECT c1,ST_Astext(c4) FROM tab WHERE MBRContains(tab.c4, @g1) ORDER BY c1; diff --git a/mysql-test/suite/innodb_gis/r/innodb_gis_rtree.result b/mysql-test/suite/innodb_gis/r/innodb_gis_rtree.result index 5d4708dd111..2ef8757339e 100644 --- a/mysql-test/suite/innodb_gis/r/innodb_gis_rtree.result +++ b/mysql-test/suite/innodb_gis/r/innodb_gis_rtree.result @@ -744,6 +744,7 @@ Table Op Msg_type Msg_text test.t1 check status OK analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK drop table t1; CREATE TABLE t1 ( diff --git a/mysql-test/suite/innodb_gis/r/precise.result b/mysql-test/suite/innodb_gis/r/precise.result index 3c05b814602..6cc0368fbb4 100644 --- a/mysql-test/suite/innodb_gis/r/precise.result +++ b/mysql-test/suite/innodb_gis/r/precise.result @@ -216,7 +216,7 @@ st_u MULTIPOLYGON(((525400 18370,525000.9677614468 183300,525400 183300,525400 18370)),((525000 183300,525000 183700,525000.9677614468 183300,525000 183300)),((525265.58 183481.95,525263.95 183484.75,525260.7 183491.55,525276.79 183500,525278.39 183500.84,525278.63 183500.97,525280.98 183502.26,525283.17 183503.47,525289.11 183506.62,525296.42 183510.31,525296.57 183510.39,525298.67 183511.53,525302.81 183513.8,525304.5 183510.83,525307.85 183504.95,525304.45 183504.25,525301.75 183509.35,525283.55 183500,525282.2 183499.3,525282.3 183499.1,525280.35 183498.2,525275.5 183495.7,525276.5 183493.45,525278.97 183488.73,525265.58 183481.95),(525266.99 183484.33,525263.26 183491.55,525266.15 183493.04,525269.88 183485.82,525266.99 183484.33),(525272.06 183488.37,525268.94 183494.51,525271.94 183496.03,525275.06 183489.89,525272.06 183488.37))) SET @a=0x0000000001030000000200000005000000000000000000000000000000000000000000000000002440000000000000000000000000000024400000000000002440000000000000000000000000000024400000000000000000000000000000000000000000000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000400000000000000040000000000000F03F0000000000000040000000000000F03F000000000000F03F; SELECT ST_ASTEXT(ST_TOUCHES(@a, ST_GEOMFROMTEXT('point(0 0)'))) t; -ERROR HY000: Illegal parameter data type int for operation 'st_astext' +ERROR HY000: Illegal parameter data type boolean for operation 'st_astext' DROP TABLE IF EXISTS p1; CREATE PROCEDURE p1(dist DOUBLE, geom TEXT) BEGIN diff --git a/mysql-test/suite/innodb_gis/r/rt_precise.result b/mysql-test/suite/innodb_gis/r/rt_precise.result index 9e2c6adc2d9..c83b88b568c 100644 --- a/mysql-test/suite/innodb_gis/r/rt_precise.result +++ b/mysql-test/suite/innodb_gis/r/rt_precise.result @@ -18,6 +18,7 @@ count(*) 150 ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN SELECT fid, ST_AsText(g) FROM t1 WHERE ST_Within(g, ST_GeomFromText('Polygon((140 140,160 140,160 160,140 140))')); id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/suite/innodb_gis/r/rtree.result b/mysql-test/suite/innodb_gis/r/rtree.result index d6604314909..53719f12205 100644 --- a/mysql-test/suite/innodb_gis/r/rtree.result +++ b/mysql-test/suite/innodb_gis/r/rtree.result @@ -6,6 +6,7 @@ insert into t1 values (1, POINT(3.1,3.1)); insert into t1 values (1, POINT(5,5)); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK set @g1 = ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'); explain select ST_astext(t1.g) from t1 where MBRWithin(t1.g, @g1); @@ -150,6 +151,7 @@ insert into t1 values (4, "444", POINT(3.1,3.1)); insert into t1 values (5, "555", POINT(5,5)); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK set @g1 = ST_GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'); explain select ST_astext(t1.g) from t1 where MBRWithin(t1.g, @g1); diff --git a/mysql-test/suite/innodb_gis/r/rtree_estimate.result b/mysql-test/suite/innodb_gis/r/rtree_estimate.result index 251685df018..dafcc40aba8 100644 --- a/mysql-test/suite/innodb_gis/r/rtree_estimate.result +++ b/mysql-test/suite/innodb_gis/r/rtree_estimate.result @@ -20,6 +20,7 @@ POLYGON((5 5,20 5,20 21,5 21,5 5)) POLYGON((1.79769e308 1.79769e308,20 5,-1.79769e308 -1.79769e308,1.79769e308 1.79769e308)) ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN SELECT ST_AsText(g) FROM t1 WHERE MBRContains(g, @g1); id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/suite/innodb_gis/t/alter_spatial_index.test b/mysql-test/suite/innodb_gis/t/alter_spatial_index.test index 653e250017a..5843c6fc8f6 100644 --- a/mysql-test/suite/innodb_gis/t/alter_spatial_index.test +++ b/mysql-test/suite/innodb_gis/t/alter_spatial_index.test @@ -491,9 +491,8 @@ FROM tab LIMIT 1; SELECT HEX(c8) FROM tab; ROLLBACK; -# not instant, not supported ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE tab add COLUMN c9 POINT NOT NULL AFTER c5, ALGORITHM = INPLACE, LOCK=NONE; +ALTER TABLE tab DROP COLUMN c9, ALGORITHM=INSTANT; SHOW CREATE TABLE tab; diff --git a/mysql-test/suite/innodb_zip/r/index_large_prefix.result b/mysql-test/suite/innodb_zip/r/index_large_prefix.result index 58d35cf2603..4866c152640 100644 --- a/mysql-test/suite/innodb_zip/r/index_large_prefix.result +++ b/mysql-test/suite/innodb_zip/r/index_large_prefix.result @@ -337,7 +337,7 @@ create index idx4 on worklog5743(a1, a2); ERROR 42000: Specified key was too long; max key length is 3072 bytes show warnings; Level Code Message -Error 1071 Specified key was too long; max key length is 3072 bytes +Warning 1071 Specified key was too long; max key length is 3072 bytes Error 1071 Specified key was too long; max key length is 3072 bytes create index idx5 on worklog5743(a1, a5); ERROR 42000: Specified key was too long; max key length is 3072 bytes diff --git a/mysql-test/suite/innodb_zip/r/innodb-zip.result b/mysql-test/suite/innodb_zip/r/innodb-zip.result index 0da1d6bbe85..e0a454b75a4 100644 --- a/mysql-test/suite/innodb_zip/r/innodb-zip.result +++ b/mysql-test/suite/innodb_zip/r/innodb-zip.result @@ -121,9 +121,13 @@ disconnect a; disconnect b; analyze table t1; Table Op Msg_type Msg_text +mysqltest_innodb_zip.t1 analyze status Engine-independent statistics collected +mysqltest_innodb_zip.t1 analyze Warning Engine-independent statistics are not collected for column 'b' mysqltest_innodb_zip.t1 analyze status OK analyze table t2; Table Op Msg_type Msg_text +mysqltest_innodb_zip.t2 analyze status Engine-independent statistics collected +mysqltest_innodb_zip.t2 analyze Warning Engine-independent statistics are not collected for column 'b' mysqltest_innodb_zip.t2 analyze status OK SELECT table_schema, table_name, row_format, data_length, index_length FROM information_schema.tables WHERE engine='innodb' AND table_schema != 'mysql' order by table_name; table_schema table_name row_format data_length index_length diff --git a/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result b/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result index 394a2ea1f09..b3a4ad2b0ba 100644 --- a/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result +++ b/mysql-test/suite/innodb_zip/r/wl5522_debug_zip.result @@ -107,12 +107,6 @@ ALTER TABLE test_wl5522.t1 IMPORT TABLESPACE; ERROR HY000: Index for table 't1' is corrupt; try to repair it SET SESSION debug_dbug=@saved_debug_dbug; restore: t1 .ibd and .cfg files -SET SESSION debug_dbug="+d,ib_import_set_max_rowid_failure"; -ALTER TABLE test_wl5522.t1 IMPORT TABLESPACE; -ERROR HY000: Index for table 't1' is corrupt; try to repair it -SET SESSION debug_dbug=@saved_debug_dbug; -unlink: t1.ibd -unlink: t1.cfg DROP TABLE test_wl5522.t1; CREATE TABLE test_wl5522.t1 ( c1 BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, diff --git a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test index 986c0508891..c81eca69db8 100644 --- a/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test +++ b/mysql-test/suite/innodb_zip/t/wl5522_debug_zip.test @@ -282,20 +282,6 @@ do "$ENV{MTR_SUITE_DIR}/../innodb/include/innodb-util.pl"; ib_restore_tablespaces("test_wl5522", "t1"); EOF -# Test failure after importing the cluster index -SET SESSION debug_dbug="+d,ib_import_set_max_rowid_failure"; - ---error ER_NOT_KEYFILE -ALTER TABLE test_wl5522.t1 IMPORT TABLESPACE; - -SET SESSION debug_dbug=@saved_debug_dbug; - -# Left over from the failed IMPORT -perl; -do "$ENV{MTR_SUITE_DIR}/../innodb/include/innodb-util.pl"; -ib_unlink_tablespace("test_wl5522", "t1"); -EOF - DROP TABLE test_wl5522.t1; --disable_query_log diff --git a/mysql-test/suite/large_tests/r/rpl_slave_net_timeout.result b/mysql-test/suite/large_tests/r/rpl_slave_net_timeout.result index ad704c0c683..5f3ad54662b 100644 --- a/mysql-test/suite/large_tests/r/rpl_slave_net_timeout.result +++ b/mysql-test/suite/large_tests/r/rpl_slave_net_timeout.result @@ -17,7 +17,11 @@ include/start_slave.inc include/stop_slave.inc connection master; select event_time from (select event_time from mysql.general_log as t_1 where command_type like 'Connect' order by event_time desc limit 2) as t_2 order by event_time desc limit 1 into @ts_last; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select event_time from (select event_time from mysql.general_log as t_1 where command_type like 'Connect' order by event_time desc limit 2) as t_2 order by event_time asc limit 1 into @ts_prev; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead include/assert.inc [time between last reconnection and the reconnection before that should be >= slave_net_timeout] connection master; set @@global.general_log = @save_general_log; diff --git a/mysql-test/suite/maria/disabled.def b/mysql-test/suite/maria/disabled.def new file mode 100644 index 00000000000..fd72451f61b --- /dev/null +++ b/mysql-test/suite/maria/disabled.def @@ -0,0 +1,13 @@ +############################################################################## +# +# List the test cases that are to be disabled temporarily. +# +# Separate the test case name and the comment with ':'. +# +# <testcasename> : BUG#<xxxx> <date disabled> <disabler> <comment> +# +# Do not use any TAB characters for whitespace. +# +############################################################################## + +small_blocksize: Can't be used when Aria is used for privilege tables diff --git a/mysql-test/suite/maria/maria-autozerofill.result b/mysql-test/suite/maria/maria-autozerofill.result index 76ccc67ebb5..064ac9e6496 100644 --- a/mysql-test/suite/maria/maria-autozerofill.result +++ b/mysql-test/suite/maria/maria-autozerofill.result @@ -56,6 +56,7 @@ mysqltest.t3 optimize Note Zerofilling moved table ./mysqltest/t3 mysqltest.t3 optimize status OK analyze table t4; Table Op Msg_type Msg_text +mysqltest.t4 analyze status Engine-independent statistics collected mysqltest.t4 analyze Note Zerofilling moved table ./mysqltest/t4 mysqltest.t4 analyze status OK repair table t5; diff --git a/mysql-test/suite/maria/maria-gis-rtree-dynamic.result b/mysql-test/suite/maria/maria-gis-rtree-dynamic.result index 8bea5edb6fb..2f8c1b9408c 100644 --- a/mysql-test/suite/maria/maria-gis-rtree-dynamic.result +++ b/mysql-test/suite/maria/maria-gis-rtree-dynamic.result @@ -749,6 +749,7 @@ Table Op Msg_type Msg_text test.t1 check status OK analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK drop table t1; CREATE TABLE t1 ( diff --git a/mysql-test/suite/maria/maria-gis-rtree-trans.result b/mysql-test/suite/maria/maria-gis-rtree-trans.result index 4a2f97fbd41..1c0d9e756a4 100644 --- a/mysql-test/suite/maria/maria-gis-rtree-trans.result +++ b/mysql-test/suite/maria/maria-gis-rtree-trans.result @@ -749,6 +749,7 @@ Table Op Msg_type Msg_text test.t1 check status OK analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK drop table t1; CREATE TABLE t1 ( diff --git a/mysql-test/suite/maria/maria-gis-rtree.result b/mysql-test/suite/maria/maria-gis-rtree.result index 901a7bee397..e39430a2efb 100644 --- a/mysql-test/suite/maria/maria-gis-rtree.result +++ b/mysql-test/suite/maria/maria-gis-rtree.result @@ -749,6 +749,7 @@ Table Op Msg_type Msg_text test.t1 check status OK analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK drop table t1; CREATE TABLE t1 ( diff --git a/mysql-test/suite/maria/maria-recover.result b/mysql-test/suite/maria/maria-recover.result index 4d0b4317afe..8a33307b2b0 100644 --- a/mysql-test/suite/maria/maria-recover.result +++ b/mysql-test/suite/maria/maria-recover.result @@ -27,7 +27,7 @@ ThursdayMorningsMarket ThursdayMorningsMarketb Warnings: Error 145 t_corrupted2' is marked as crashed and should be repaired -Error 1034 1 client is using or hasn't closed the table properly +Warning 1034 1 client is using or hasn't closed the table properly Error 1034 Wrong base information on indexpage at page: 1 select * from t_corrupted2; a diff --git a/mysql-test/suite/maria/maria-recover.test b/mysql-test/suite/maria/maria-recover.test index 0f9f5e9cd26..893cd5e601d 100644 --- a/mysql-test/suite/maria/maria-recover.test +++ b/mysql-test/suite/maria/maria-recover.test @@ -2,6 +2,18 @@ --source include/have_maria.inc +# +# Ensure that we don't get warnings from mysql.proc (used by check_mysqld) +# + +--disable_query_log +--disable_warnings +--disable_result_log +select count(*) from mysql.proc; +--enable_result_log +--enable_warnings +--enable_query_log + --disable_query_log # Note: \\. matches a single period. We use '.' as directory separator to # account for Unix and Windows variation. diff --git a/mysql-test/suite/maria/maria-ucs2.result b/mysql-test/suite/maria/maria-ucs2.result index 7499b37279b..1a54ab78081 100644 --- a/mysql-test/suite/maria/maria-ucs2.result +++ b/mysql-test/suite/maria/maria-ucs2.result @@ -1,6 +1,6 @@ select * from INFORMATION_SCHEMA.ENGINES where ENGINE="ARIA"; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -Aria YES Crash-safe tables with MyISAM heritage NO NO NO +Aria YES Crash-safe tables with MyISAM heritage. Used for internal temporary tables and privilege tables NO NO NO set global storage_engine=aria; set session storage_engine=aria; drop table if exists t1; diff --git a/mysql-test/suite/maria/maria.result b/mysql-test/suite/maria/maria.result index fcfecd31eb9..76b14024bf4 100644 --- a/mysql-test/suite/maria/maria.result +++ b/mysql-test/suite/maria/maria.result @@ -1,7 +1,7 @@ call mtr.add_suppression("Can't find record in '.*'"); select * from INFORMATION_SCHEMA.ENGINES where ENGINE="ARIA"; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -Aria YES Crash-safe tables with MyISAM heritage NO NO NO +Aria YES Crash-safe tables with MyISAM heritage. Used for internal temporary tables and privilege tables NO NO NO set global storage_engine=aria; set session storage_engine=aria; set global aria_page_checksum=0; @@ -739,6 +739,7 @@ insert into t1 values (0),(1),(2),(3),(4); insert into t1 select NULL from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -759,6 +760,7 @@ insert into t1 values (11); delete from t1 where a=11; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -770,7 +772,7 @@ Table Op Msg_type Msg_text test.t1 check status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment -t1 1 a 1 a A 5 NULL NULL YES BTREE +t1 1 a 1 a A 10 NULL NULL YES BTREE set aria_stats_method=DEFAULT; show variables like 'aria_stats_method'; Variable_name Value @@ -779,6 +781,7 @@ insert into t1 values (11); delete from t1 where a=11; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -806,6 +809,7 @@ insert into t1 values ('bce','def1', 'yuu', NULL); insert into t1 values ('bce','def2', NULL, 'quux'); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -816,6 +820,7 @@ t1 1 a 4 d A 4 NULL NULL YES BTREE delete from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -1690,9 +1695,11 @@ create table t1 (a int, key(a)); insert into t1 values (1),(2),(3),(4),(NULL),(NULL),(NULL),(NULL); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status Table is already up to date show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/mysql-test/suite/maria/maria3.result b/mysql-test/suite/maria/maria3.result index 6099dc9c982..ba8b64f9514 100644 --- a/mysql-test/suite/maria/maria3.result +++ b/mysql-test/suite/maria/maria3.result @@ -1,6 +1,6 @@ select * from INFORMATION_SCHEMA.ENGINES where ENGINE="ARIA"; ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -Aria YES Crash-safe tables with MyISAM heritage NO NO NO +Aria YES Crash-safe tables with MyISAM heritage. Used for internal temporary tables and privilege tables NO NO NO set global storage_engine=aria; set session storage_engine=aria; set global aria_page_checksum=0; @@ -209,11 +209,13 @@ create table t2 like t1; insert into t2 select * from t1; analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date delete from t2; insert into t2 select * from t1; analyze table t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status Table is already up to date drop table t1,t2; create table t1 (a bigint auto_increment, primary key(a), b char(255), c varchar(20000)); diff --git a/mysql-test/suite/maria/system_tables.result b/mysql-test/suite/maria/system_tables.result new file mode 100644 index 00000000000..c9944482638 --- /dev/null +++ b/mysql-test/suite/maria/system_tables.result @@ -0,0 +1,14 @@ +CREATE TABLE t1 (i INT) ENGINE=Aria; +LOCK TABLE t1 WRITE; +connect con1,localhost,root,,test; +SET lock_wait_timeout= 2; +FLUSH TABLES; +FLUSH TABLES t1; +connection default; +CALL non_existing_sp; +ERROR 42000: PROCEDURE test.non_existing_sp does not exist +connection con1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +disconnect con1; +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/maria/system_tables.test b/mysql-test/suite/maria/system_tables.test new file mode 100644 index 00000000000..950989fa5ca --- /dev/null +++ b/mysql-test/suite/maria/system_tables.test @@ -0,0 +1,27 @@ +# +# Test related to Aria system tables +# + +# +# MDEV-16986 Unitialized mutex, SIGSEGV and assorted assertion failures in +# Aria code +# + +CREATE TABLE t1 (i INT) ENGINE=Aria; +LOCK TABLE t1 WRITE; + +--connect (con1,localhost,root,,test) +SET lock_wait_timeout= 2; +FLUSH TABLES; +--send FLUSH TABLES t1 +--connection default +--error ER_SP_DOES_NOT_EXIST +CALL non_existing_sp; +--connection con1 +--error ER_LOCK_WAIT_TIMEOUT +--reap + +# Cleanup +--disconnect con1 +--connection default +DROP TABLE t1; diff --git a/mysql-test/suite/multi_source/gtid_ignore_duplicates.result b/mysql-test/suite/multi_source/gtid_ignore_duplicates.result index 96627b42c97..e142ff8b981 100644 --- a/mysql-test/suite/multi_source/gtid_ignore_duplicates.result +++ b/mysql-test/suite/multi_source/gtid_ignore_duplicates.result @@ -492,21 +492,21 @@ SET GLOBAL slave_parallel_threads= @old_parallel; SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; connection server_1; DROP TABLE t1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; include/reset_master_slave.inc disconnect server_1; connection server_2; DROP TABLE t1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; include/reset_master_slave.inc disconnect server_2; connection server_3; DROP TABLE t1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; include/reset_master_slave.inc disconnect server_3; connection server_4; DROP TABLE t1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; include/reset_master_slave.inc disconnect server_4; diff --git a/mysql-test/suite/multi_source/gtid_ignore_duplicates.test b/mysql-test/suite/multi_source/gtid_ignore_duplicates.test index b61da0f0f33..3d2d151bd0d 100644 --- a/mysql-test/suite/multi_source/gtid_ignore_duplicates.test +++ b/mysql-test/suite/multi_source/gtid_ignore_duplicates.test @@ -432,24 +432,24 @@ SET GLOBAL gtid_ignore_duplicates= @old_ignore_duplicates; --connection server_1 DROP TABLE t1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; --source include/reset_master_slave.inc --disconnect server_1 --connection server_2 DROP TABLE t1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; --source include/reset_master_slave.inc --disconnect server_2 --connection server_3 DROP TABLE t1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; --source include/reset_master_slave.inc --disconnect server_3 --connection server_4 DROP TABLE t1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; --source include/reset_master_slave.inc --disconnect server_4 diff --git a/mysql-test/suite/parts/r/partition_alter1_1_2_innodb.result b/mysql-test/suite/parts/r/partition_alter1_1_2_innodb.result index 5f3610b7999..0e8db677cdf 100644 --- a/mysql-test/suite/parts/r/partition_alter1_1_2_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter1_1_2_innodb.result @@ -517,6 +517,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1009,6 +1010,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1516,6 +1518,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2017,6 +2020,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2516,6 +2520,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3026,6 +3031,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3538,6 +3544,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4038,6 +4045,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4531,6 +4539,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5023,6 +5032,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5530,6 +5540,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6031,6 +6042,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6530,6 +6542,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7040,6 +7053,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7552,6 +7566,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8052,6 +8067,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8562,6 +8578,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9070,6 +9087,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9593,6 +9611,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10110,6 +10129,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10625,6 +10645,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11151,6 +11172,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11679,6 +11701,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12195,6 +12218,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12704,6 +12728,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13212,6 +13237,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13735,6 +13761,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14252,6 +14279,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14767,6 +14795,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15293,6 +15322,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15821,6 +15851,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16337,6 +16368,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16832,6 +16864,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17325,6 +17358,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17833,6 +17867,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18335,6 +18370,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18835,6 +18871,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19346,6 +19383,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19859,6 +19897,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20360,6 +20399,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20854,6 +20894,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21347,6 +21388,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21855,6 +21897,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22357,6 +22400,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22857,6 +22901,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23368,6 +23413,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23881,6 +23927,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24382,6 +24429,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24876,6 +24924,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25369,6 +25418,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25877,6 +25927,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26379,6 +26430,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26879,6 +26931,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -27390,6 +27443,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -27903,6 +27957,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -28404,6 +28459,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter1_1_2_myisam.result b/mysql-test/suite/parts/r/partition_alter1_1_2_myisam.result index ce3dd51496e..0f12c15e4e9 100644 --- a/mysql-test/suite/parts/r/partition_alter1_1_2_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter1_1_2_myisam.result @@ -543,6 +543,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1066,6 +1067,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1610,6 +1612,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2144,6 +2147,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2680,6 +2684,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3227,6 +3232,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3776,6 +3782,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4315,6 +4322,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4833,6 +4841,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5356,6 +5365,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5900,6 +5910,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6434,6 +6445,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6970,6 +6982,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7517,6 +7530,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8066,6 +8080,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8605,6 +8620,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter1_1_innodb.result b/mysql-test/suite/parts/r/partition_alter1_1_innodb.result index 12f028782ed..919e6344615 100644 --- a/mysql-test/suite/parts/r/partition_alter1_1_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter1_1_innodb.result @@ -835,6 +835,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1327,6 +1328,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1834,6 +1836,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2335,6 +2338,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2836,6 +2840,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3346,6 +3351,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3858,6 +3864,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4358,6 +4365,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4851,6 +4859,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5343,6 +5352,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5850,6 +5860,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6351,6 +6362,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6852,6 +6864,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7362,6 +7375,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7874,6 +7888,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8374,6 +8389,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8884,6 +8900,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9392,6 +9409,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9915,6 +9933,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10432,6 +10451,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10949,6 +10969,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11475,6 +11496,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12003,6 +12025,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12519,6 +12542,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13028,6 +13052,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13536,6 +13561,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14059,6 +14085,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14576,6 +14603,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15093,6 +15121,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15619,6 +15648,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16147,6 +16177,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16663,6 +16694,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter1_1_myisam.result b/mysql-test/suite/parts/r/partition_alter1_1_myisam.result index a276e1593ee..05176399246 100644 --- a/mysql-test/suite/parts/r/partition_alter1_1_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter1_1_myisam.result @@ -702,6 +702,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1225,6 +1226,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1769,6 +1771,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2303,6 +2306,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2841,6 +2845,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3388,6 +3393,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3937,6 +3943,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4476,6 +4483,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4994,6 +5002,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5517,6 +5526,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6061,6 +6071,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6595,6 +6606,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7133,6 +7145,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7680,6 +7693,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8229,6 +8243,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8768,6 +8783,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter1_2_innodb.result b/mysql-test/suite/parts/r/partition_alter1_2_innodb.result index 36823665fa1..3f720024f72 100644 --- a/mysql-test/suite/parts/r/partition_alter1_2_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter1_2_innodb.result @@ -464,6 +464,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -904,6 +905,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1359,6 +1361,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1808,6 +1811,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2257,6 +2261,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2715,6 +2720,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3175,6 +3181,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3623,6 +3630,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4064,6 +4072,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4504,6 +4513,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4959,6 +4969,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5408,6 +5419,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5857,6 +5869,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6315,6 +6328,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6775,6 +6789,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7223,6 +7238,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7680,6 +7696,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8136,6 +8153,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8607,6 +8625,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9072,6 +9091,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9537,6 +9557,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10011,6 +10032,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10487,6 +10509,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10951,6 +10974,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11396,6 +11420,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11836,6 +11861,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12291,6 +12317,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12740,6 +12767,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13187,6 +13215,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13645,6 +13674,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14105,6 +14135,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14553,6 +14584,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14994,6 +15026,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15434,6 +15467,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15889,6 +15923,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16338,6 +16373,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16785,6 +16821,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17243,6 +17280,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17703,6 +17741,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18151,6 +18190,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18609,6 +18649,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19065,6 +19106,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19536,6 +19578,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20001,6 +20044,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20464,6 +20508,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20938,6 +20983,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21414,6 +21460,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21878,6 +21925,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22335,6 +22383,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22791,6 +22840,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23262,6 +23312,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23727,6 +23778,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24190,6 +24242,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24664,6 +24717,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25140,6 +25194,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25604,6 +25659,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26046,6 +26102,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26486,6 +26543,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26941,6 +26999,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -27390,6 +27449,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -27837,6 +27897,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -28295,6 +28356,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -28755,6 +28817,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -29203,6 +29266,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -29644,6 +29708,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -30084,6 +30149,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -30539,6 +30605,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -30988,6 +31055,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -31435,6 +31503,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -31893,6 +31962,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -32353,6 +32423,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -32801,6 +32872,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -33258,6 +33330,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -33714,6 +33787,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -34185,6 +34259,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -34650,6 +34725,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -35113,6 +35189,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -35587,6 +35664,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -36063,6 +36141,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -36527,6 +36606,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter1_2_myisam.result b/mysql-test/suite/parts/r/partition_alter1_2_myisam.result index b4e1ddc577b..ba6a7e7fbbd 100644 --- a/mysql-test/suite/parts/r/partition_alter1_2_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter1_2_myisam.result @@ -489,6 +489,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -960,6 +961,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1452,6 +1454,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1934,6 +1937,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2420,6 +2424,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2915,6 +2920,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3412,6 +3418,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3899,6 +3906,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4369,6 +4377,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4840,6 +4849,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5332,6 +5342,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5814,6 +5825,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6298,6 +6310,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6793,6 +6806,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7290,6 +7304,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7777,6 +7792,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8243,6 +8259,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8714,6 +8731,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9206,6 +9224,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9688,6 +9707,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10172,6 +10192,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10667,6 +10688,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11164,6 +11186,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11651,6 +11674,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12117,6 +12141,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12588,6 +12613,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13080,6 +13106,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13562,6 +13589,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14046,6 +14074,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14541,6 +14570,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15038,6 +15068,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15525,6 +15556,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter2_1_1_innodb.result b/mysql-test/suite/parts/r/partition_alter2_1_1_innodb.result index 586b24e4049..ff7d659613d 100644 --- a/mysql-test/suite/parts/r/partition_alter2_1_1_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter2_1_1_innodb.result @@ -481,6 +481,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -937,6 +938,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1408,6 +1410,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1873,6 +1876,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2338,6 +2342,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2812,6 +2817,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3288,6 +3294,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3752,6 +3759,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4248,6 +4256,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4742,6 +4751,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5251,6 +5261,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5754,6 +5765,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6257,6 +6269,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6769,6 +6782,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7283,6 +7297,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7785,6 +7800,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8280,6 +8296,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8774,6 +8791,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9283,6 +9301,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9786,6 +9805,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10289,6 +10309,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10801,6 +10822,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11315,6 +11337,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11817,6 +11840,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12327,6 +12351,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12835,6 +12860,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13358,6 +13384,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13875,6 +13902,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14392,6 +14420,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14918,6 +14947,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15446,6 +15476,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15962,6 +15993,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16471,6 +16503,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16979,6 +17012,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17502,6 +17536,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18019,6 +18054,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18536,6 +18572,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19062,6 +19099,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19590,6 +19628,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20106,6 +20145,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter2_1_2_innodb.result b/mysql-test/suite/parts/r/partition_alter2_1_2_innodb.result index 5a71f1063f5..a537b74201d 100644 --- a/mysql-test/suite/parts/r/partition_alter2_1_2_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter2_1_2_innodb.result @@ -477,6 +477,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -933,6 +934,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1404,6 +1406,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1869,6 +1872,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2332,6 +2336,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2806,6 +2811,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3282,6 +3288,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3746,6 +3753,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4243,6 +4251,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4738,6 +4747,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5248,6 +5258,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5752,6 +5763,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6254,6 +6266,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6767,6 +6780,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7282,6 +7296,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7785,6 +7800,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8281,6 +8297,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8776,6 +8793,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9286,6 +9304,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9790,6 +9809,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10292,6 +10312,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10805,6 +10826,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11320,6 +11342,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11823,6 +11846,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12333,6 +12357,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12841,6 +12866,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13364,6 +13390,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13881,6 +13908,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14396,6 +14424,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14922,6 +14951,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15450,6 +15480,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15966,6 +15997,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16475,6 +16507,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16983,6 +17016,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17506,6 +17540,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18023,6 +18058,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18538,6 +18574,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19064,6 +19101,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19592,6 +19630,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20108,6 +20147,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter2_1_maria.result b/mysql-test/suite/parts/r/partition_alter2_1_maria.result index 7196be3a602..0af69f09639 100644 --- a/mysql-test/suite/parts/r/partition_alter2_1_maria.result +++ b/mysql-test/suite/parts/r/partition_alter2_1_maria.result @@ -491,6 +491,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -962,6 +963,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1454,6 +1456,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1936,6 +1939,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2422,6 +2426,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2917,6 +2922,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3414,6 +3420,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3901,6 +3908,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4420,6 +4428,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4943,6 +4952,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5487,6 +5497,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6021,6 +6032,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6559,6 +6571,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7106,6 +7119,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7655,6 +7669,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8194,6 +8209,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8712,6 +8728,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9235,6 +9252,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9779,6 +9797,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10313,6 +10332,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10851,6 +10871,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11398,6 +11419,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11947,6 +11969,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12486,6 +12509,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12957,6 +12981,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13428,6 +13453,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13920,6 +13946,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14402,6 +14429,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14886,6 +14914,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15381,6 +15410,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15878,6 +15908,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16365,6 +16396,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16884,6 +16916,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17407,6 +17440,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17951,6 +17985,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18485,6 +18520,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19021,6 +19057,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19568,6 +19605,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20117,6 +20155,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20656,6 +20695,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21174,6 +21214,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21697,6 +21738,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22241,6 +22283,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22775,6 +22818,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23311,6 +23355,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23858,6 +23903,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24407,6 +24453,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24946,6 +24993,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter2_1_myisam.result b/mysql-test/suite/parts/r/partition_alter2_1_myisam.result index 59039b97f65..60cb5a2e733 100644 --- a/mysql-test/suite/parts/r/partition_alter2_1_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter2_1_myisam.result @@ -491,6 +491,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -962,6 +963,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1454,6 +1456,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1936,6 +1939,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2422,6 +2426,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2917,6 +2922,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3414,6 +3420,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3901,6 +3908,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4420,6 +4428,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4943,6 +4952,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5487,6 +5497,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6021,6 +6032,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6559,6 +6571,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7106,6 +7119,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7655,6 +7669,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8194,6 +8209,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8712,6 +8728,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9235,6 +9252,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9779,6 +9797,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10313,6 +10332,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10851,6 +10871,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11398,6 +11419,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11947,6 +11969,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12486,6 +12509,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12957,6 +12981,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13428,6 +13453,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13920,6 +13946,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14402,6 +14429,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14886,6 +14914,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15381,6 +15410,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15878,6 +15908,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16365,6 +16396,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16884,6 +16916,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17407,6 +17440,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17951,6 +17985,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18485,6 +18520,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19021,6 +19057,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19568,6 +19605,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20117,6 +20155,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20656,6 +20695,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21174,6 +21214,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21697,6 +21738,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22241,6 +22283,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22775,6 +22818,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23311,6 +23355,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23858,6 +23903,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24407,6 +24453,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24946,6 +24993,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter2_2_1_innodb.result b/mysql-test/suite/parts/r/partition_alter2_2_1_innodb.result index 1d90f8f6368..d0d4e1602fd 100644 --- a/mysql-test/suite/parts/r/partition_alter2_2_1_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter2_2_1_innodb.result @@ -483,6 +483,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -941,6 +942,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1414,6 +1416,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1879,6 +1882,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2346,6 +2350,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2820,6 +2825,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3298,6 +3304,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3764,6 +3771,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4261,6 +4269,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4757,6 +4766,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5268,6 +5278,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5771,6 +5782,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6276,6 +6288,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6788,6 +6801,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7304,6 +7318,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7808,6 +7823,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8305,6 +8321,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8801,6 +8818,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9312,6 +9330,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9815,6 +9834,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10320,6 +10340,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10832,6 +10853,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11348,6 +11370,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11852,6 +11875,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12364,6 +12388,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12874,6 +12899,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13399,6 +13425,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13916,6 +13943,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14435,6 +14463,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14961,6 +14990,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15491,6 +15521,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16009,6 +16040,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16520,6 +16552,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17030,6 +17063,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17555,6 +17589,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18072,6 +18107,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18591,6 +18627,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19117,6 +19154,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19647,6 +19685,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20165,6 +20204,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter2_2_2_innodb.result b/mysql-test/suite/parts/r/partition_alter2_2_2_innodb.result index 4b0a481340f..4332588fda7 100644 --- a/mysql-test/suite/parts/r/partition_alter2_2_2_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter2_2_2_innodb.result @@ -479,6 +479,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -938,6 +939,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1412,6 +1414,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1882,6 +1885,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2350,6 +2354,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2829,6 +2834,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3308,6 +3314,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3775,6 +3782,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4275,6 +4283,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4773,6 +4782,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5286,6 +5296,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5795,6 +5806,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6302,6 +6314,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6820,6 +6833,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7338,6 +7352,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7844,6 +7859,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8343,6 +8359,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8841,6 +8858,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9354,6 +9372,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9863,6 +9882,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10370,6 +10390,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10888,6 +10909,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11406,6 +11428,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11912,6 +11935,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12425,6 +12449,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12936,6 +12961,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13462,6 +13488,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13984,6 +14011,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14504,6 +14532,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15035,6 +15064,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15566,6 +15596,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16085,6 +16116,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16597,6 +16629,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17108,6 +17141,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17634,6 +17668,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18156,6 +18191,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18676,6 +18712,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19207,6 +19244,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19738,6 +19776,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20257,6 +20296,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter2_2_maria.result b/mysql-test/suite/parts/r/partition_alter2_2_maria.result index 66d5770e20e..9cc64b8239b 100644 --- a/mysql-test/suite/parts/r/partition_alter2_2_maria.result +++ b/mysql-test/suite/parts/r/partition_alter2_2_maria.result @@ -493,6 +493,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -966,6 +967,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1460,6 +1462,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1942,6 +1945,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2430,6 +2434,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2925,6 +2930,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3424,6 +3430,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3913,6 +3920,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4434,6 +4442,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4959,6 +4968,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5505,6 +5515,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6039,6 +6050,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6579,6 +6591,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7126,6 +7139,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7677,6 +7691,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8218,6 +8233,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8738,6 +8754,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9263,6 +9280,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9809,6 +9827,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10343,6 +10362,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10883,6 +10903,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11430,6 +11451,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11981,6 +12003,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12522,6 +12545,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12995,6 +13019,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13469,6 +13494,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13964,6 +13990,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14451,6 +14478,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14940,6 +14968,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15440,6 +15469,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15940,6 +15970,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16430,6 +16461,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16952,6 +16984,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17478,6 +17511,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18025,6 +18059,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18564,6 +18599,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19105,6 +19141,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19657,6 +19694,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20209,6 +20247,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20751,6 +20790,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21272,6 +21312,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21798,6 +21839,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22345,6 +22387,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22884,6 +22927,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23425,6 +23469,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23977,6 +24022,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24529,6 +24575,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25071,6 +25118,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter2_2_myisam.result b/mysql-test/suite/parts/r/partition_alter2_2_myisam.result index 69548fdb94b..32a840c1577 100644 --- a/mysql-test/suite/parts/r/partition_alter2_2_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter2_2_myisam.result @@ -493,6 +493,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -966,6 +967,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1460,6 +1462,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1942,6 +1945,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2430,6 +2434,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2925,6 +2930,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3424,6 +3430,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3913,6 +3920,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4434,6 +4442,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4959,6 +4968,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5505,6 +5515,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6039,6 +6050,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6579,6 +6591,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7126,6 +7139,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7677,6 +7691,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8218,6 +8233,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8738,6 +8754,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9263,6 +9280,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9809,6 +9827,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10343,6 +10362,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10883,6 +10903,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11430,6 +11451,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11981,6 +12003,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12522,6 +12545,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12995,6 +13019,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13469,6 +13494,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13964,6 +13990,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14451,6 +14478,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14940,6 +14968,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15440,6 +15469,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15940,6 +15970,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16430,6 +16461,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16952,6 +16984,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17478,6 +17511,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18025,6 +18059,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18564,6 +18599,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19105,6 +19141,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19657,6 +19694,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20209,6 +20247,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20751,6 +20790,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21272,6 +21312,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21798,6 +21839,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22345,6 +22387,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22884,6 +22927,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23425,6 +23469,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23977,6 +24022,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24529,6 +24575,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25071,6 +25118,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter4_innodb.result b/mysql-test/suite/parts/r/partition_alter4_innodb.result index 644a5f32f84..d88bdfcbe00 100644 --- a/mysql-test/suite/parts/r/partition_alter4_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter4_innodb.result @@ -60,6 +60,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -483,6 +484,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -519,6 +521,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -945,6 +948,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -989,6 +993,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -1418,6 +1423,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1460,6 +1466,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -1885,6 +1892,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1925,6 +1933,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -2352,6 +2361,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2396,6 +2406,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -2828,6 +2839,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2872,6 +2884,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -3306,6 +3319,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3346,6 +3360,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -3772,6 +3787,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3810,6 +3826,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -4233,6 +4250,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4269,6 +4287,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -4695,6 +4714,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4739,6 +4759,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -5168,6 +5189,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5210,6 +5232,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -5635,6 +5658,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5675,6 +5699,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -6102,6 +6127,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6146,6 +6172,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -6578,6 +6605,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6622,6 +6650,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -7056,6 +7085,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7096,6 +7126,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -7522,6 +7553,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7983,6 +8015,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8445,6 +8478,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8918,6 +8952,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9385,6 +9420,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9852,6 +9888,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10328,6 +10365,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10806,6 +10844,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11272,6 +11311,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11733,6 +11773,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12195,6 +12236,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12668,6 +12710,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13135,6 +13178,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13602,6 +13646,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14078,6 +14123,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14556,6 +14602,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15022,6 +15069,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15060,6 +15108,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -15483,6 +15532,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15519,6 +15569,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -15945,6 +15996,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15989,6 +16041,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -16418,6 +16471,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16460,6 +16514,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -16885,6 +16940,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16925,6 +16981,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -17352,6 +17409,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17396,6 +17454,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -17828,6 +17887,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17872,6 +17932,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -18306,6 +18367,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18346,6 +18408,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -18772,6 +18835,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19236,6 +19300,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19698,6 +19763,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20171,6 +20237,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20638,6 +20705,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21105,6 +21173,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21581,6 +21650,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22059,6 +22129,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22525,6 +22596,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22986,6 +23058,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23448,6 +23521,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23921,6 +23995,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24388,6 +24463,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24855,6 +24931,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25331,6 +25408,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25809,6 +25887,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26275,6 +26354,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26736,6 +26816,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -27198,6 +27279,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -27671,6 +27753,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -28138,6 +28221,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -28605,6 +28689,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -29081,6 +29166,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -29559,6 +29645,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -30025,6 +30112,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -30486,6 +30574,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -30948,6 +31037,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -31421,6 +31511,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -31888,6 +31979,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -32355,6 +32447,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -32831,6 +32924,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -33309,6 +33403,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -33775,6 +33870,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -34236,6 +34332,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -34698,6 +34795,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -35171,6 +35269,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -35638,6 +35737,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -36105,6 +36205,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -36581,6 +36682,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -37059,6 +37161,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -37525,6 +37628,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -37990,6 +38094,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -38453,6 +38558,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -38927,6 +39033,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -39395,6 +39502,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -39863,6 +39971,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -40340,6 +40449,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -40819,6 +40929,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -41286,6 +41397,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -41748,6 +41860,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -42211,6 +42324,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -42685,6 +42799,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -43153,6 +43268,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -43621,6 +43737,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -44098,6 +44215,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -44577,6 +44695,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -45044,6 +45163,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -45505,6 +45625,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -45967,6 +46088,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -46440,6 +46562,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -46907,6 +47030,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -47374,6 +47498,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -47850,6 +47975,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -48328,6 +48454,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -48794,6 +48921,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -49255,6 +49383,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -49717,6 +49846,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -50190,6 +50320,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -50657,6 +50788,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -51124,6 +51256,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -51600,6 +51733,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -52078,6 +52212,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -52544,6 +52679,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -53006,6 +53142,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -53469,6 +53606,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -53943,6 +54081,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -54411,6 +54550,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -54879,6 +55019,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -55356,6 +55497,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -55835,6 +55977,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -56302,6 +56445,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -56764,6 +56908,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -57224,6 +57369,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -57695,6 +57841,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -58160,6 +58307,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -58625,6 +58773,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -59099,6 +59248,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -59575,6 +59725,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -60039,6 +60190,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -60498,6 +60650,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -60958,6 +61111,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -61429,6 +61583,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -61894,6 +62049,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -62359,6 +62515,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -62833,6 +62990,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -63309,6 +63467,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -63773,6 +63932,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -64552,6 +64712,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -65012,6 +65173,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -65483,6 +65645,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -65948,6 +66111,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -66413,6 +66577,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -66887,6 +67052,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -67363,6 +67529,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -67827,6 +67994,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -68291,6 +68459,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -68753,6 +68922,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -69226,6 +69396,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -69693,6 +69864,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -70160,6 +70332,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -70636,6 +70809,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -71114,6 +71288,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -71580,6 +71755,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -72041,6 +72217,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -72503,6 +72680,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -72976,6 +73154,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -73443,6 +73622,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -73910,6 +74090,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -74386,6 +74567,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -74864,6 +75046,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -75330,6 +75513,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -75791,6 +75975,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -76253,6 +76438,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -76726,6 +76912,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -77193,6 +77380,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -77660,6 +77848,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -78136,6 +78325,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -78614,6 +78804,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -79080,6 +79271,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -79541,6 +79733,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -80003,6 +80196,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -80476,6 +80670,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -80943,6 +81138,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -81410,6 +81606,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -81886,6 +82083,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -82364,6 +82562,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -82830,6 +83029,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -83291,6 +83491,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -83753,6 +83954,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -84226,6 +84428,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -84693,6 +84896,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -85160,6 +85364,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -85636,6 +85841,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -86114,6 +86320,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -86580,6 +86787,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -87039,6 +87247,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -87493,6 +87702,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -87955,6 +88165,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -88415,6 +88626,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -88873,6 +89085,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -89335,6 +89548,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -89797,6 +90011,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -90255,6 +90470,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_alter4_myisam.result b/mysql-test/suite/parts/r/partition_alter4_myisam.result index 41723a268e1..90edd1b2210 100644 --- a/mysql-test/suite/parts/r/partition_alter4_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter4_myisam.result @@ -60,6 +60,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -493,6 +494,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -528,6 +530,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -970,6 +973,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1013,6 +1017,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -1464,6 +1469,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1505,6 +1511,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -1948,6 +1955,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1987,6 +1995,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -2436,6 +2445,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2479,6 +2489,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -2933,6 +2944,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2976,6 +2988,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -3432,6 +3445,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3471,6 +3485,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -3921,6 +3936,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3958,6 +3974,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -4391,6 +4408,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4426,6 +4444,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -4868,6 +4887,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4911,6 +4931,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -5362,6 +5383,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5403,6 +5425,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -5846,6 +5869,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5885,6 +5909,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -6334,6 +6359,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6377,6 +6403,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -6831,6 +6858,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6874,6 +6902,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -7330,6 +7359,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7369,6 +7399,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION part_1,part_2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -7819,6 +7850,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8289,6 +8321,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8766,6 +8799,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9260,6 +9294,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9744,6 +9779,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10232,6 +10268,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10729,6 +10766,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11228,6 +11266,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11717,6 +11756,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12187,6 +12227,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12664,6 +12705,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13158,6 +13200,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13642,6 +13685,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14130,6 +14174,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14627,6 +14672,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15126,6 +15172,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15615,6 +15662,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15652,6 +15700,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -16085,6 +16134,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16120,6 +16170,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -16562,6 +16613,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16605,6 +16657,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -17056,6 +17109,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17097,6 +17151,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -17540,6 +17595,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17579,6 +17635,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -18028,6 +18085,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18071,6 +18129,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -18525,6 +18584,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18568,6 +18628,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -19024,6 +19085,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19063,6 +19125,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1; ALTER TABLE t1 ANALYZE PARTITION ALL; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template @@ -19513,6 +19576,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19986,6 +20050,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20463,6 +20528,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20957,6 +21023,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21441,6 +21508,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21929,6 +21997,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22426,6 +22495,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22925,6 +22995,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23414,6 +23485,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23884,6 +23956,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24361,6 +24434,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24855,6 +24929,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25339,6 +25414,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25827,6 +25903,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26324,6 +26401,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26823,6 +26901,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -27312,6 +27391,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -27782,6 +27862,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -28259,6 +28340,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -28753,6 +28835,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -29237,6 +29320,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -29725,6 +29809,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -30222,6 +30307,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -30721,6 +30807,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -31210,6 +31297,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -31680,6 +31768,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -32157,6 +32246,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -32651,6 +32741,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -33135,6 +33226,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -33623,6 +33715,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -34120,6 +34213,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -34619,6 +34713,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -35108,6 +35203,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -35578,6 +35674,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -36055,6 +36152,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -36549,6 +36647,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -37033,6 +37132,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -37521,6 +37621,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -38018,6 +38119,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -38517,6 +38619,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -39006,6 +39109,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -39479,6 +39583,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -39956,6 +40061,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -40450,6 +40556,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -40934,6 +41041,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -41422,6 +41530,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -41919,6 +42028,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -42418,6 +42528,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -42907,6 +43018,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -43377,6 +43489,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -43854,6 +43967,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -44348,6 +44462,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -44832,6 +44947,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -45320,6 +45436,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -45817,6 +45934,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -46316,6 +46434,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -46805,6 +46924,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -47275,6 +47395,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -47752,6 +47873,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -48246,6 +48368,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -48730,6 +48853,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -49218,6 +49342,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -49715,6 +49840,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -50214,6 +50340,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -50703,6 +50830,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -51173,6 +51301,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -51650,6 +51779,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -52144,6 +52274,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -52628,6 +52759,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -53116,6 +53248,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -53613,6 +53746,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -54112,6 +54246,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -54601,6 +54736,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -55071,6 +55207,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -55548,6 +55685,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -56042,6 +56180,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -56526,6 +56665,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -57014,6 +57154,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -57511,6 +57652,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -58010,6 +58152,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -58499,6 +58642,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -58970,6 +59114,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -59445,6 +59590,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -59937,6 +60083,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -60419,6 +60566,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -60905,6 +61053,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -61400,6 +61549,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -61897,6 +62047,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -62384,6 +62535,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -62852,6 +63004,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -63327,6 +63480,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -63819,6 +63973,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -64301,6 +64456,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -64787,6 +64943,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -65282,6 +65439,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -65779,6 +65937,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -66266,6 +66425,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -67054,6 +67214,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -67529,6 +67690,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -68021,6 +68183,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -68503,6 +68666,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -68989,6 +69153,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -69484,6 +69649,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -69981,6 +70147,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -70468,6 +70635,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -70941,6 +71109,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -71418,6 +71587,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -71912,6 +72082,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -72396,6 +72567,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -72884,6 +73056,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -73381,6 +73554,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -73880,6 +74054,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -74369,6 +74544,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -74839,6 +75015,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -75316,6 +75493,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -75810,6 +75988,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -76294,6 +76473,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -76782,6 +76962,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -77279,6 +77460,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -77778,6 +77960,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -78267,6 +78450,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -78737,6 +78921,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -79214,6 +79399,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -79708,6 +79894,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -80192,6 +80379,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -80680,6 +80868,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -81177,6 +81366,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -81676,6 +81866,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -82165,6 +82356,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -82635,6 +82827,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -83112,6 +83305,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -83606,6 +83800,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -84090,6 +84285,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -84578,6 +84774,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -85075,6 +85272,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -85574,6 +85772,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -86063,6 +86262,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -86533,6 +86733,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -87010,6 +87211,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -87504,6 +87706,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -87988,6 +88191,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -88476,6 +88680,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -88973,6 +89178,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -89472,6 +89678,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -89961,6 +90168,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -90426,6 +90634,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -90886,6 +91095,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -91354,6 +91564,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -91820,6 +92031,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -92284,6 +92496,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -92752,6 +92965,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -93220,6 +93434,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -93684,6 +93899,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_basic_innodb.result b/mysql-test/suite/parts/r/partition_basic_innodb.result index 570a30bcd81..5ea1f98ddcb 100644 --- a/mysql-test/suite/parts/r/partition_basic_innodb.result +++ b/mysql-test/suite/parts/r/partition_basic_innodb.result @@ -486,6 +486,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -946,6 +947,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1424,6 +1426,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1894,6 +1897,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2366,6 +2370,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2847,6 +2852,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3334,6 +3340,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3806,6 +3813,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4265,6 +4273,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4725,6 +4734,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5203,6 +5213,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5673,6 +5684,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6143,6 +6155,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6624,6 +6637,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7107,6 +7121,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7579,6 +7594,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8079,6 +8095,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8576,6 +8593,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9091,6 +9109,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9598,6 +9617,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10107,6 +10127,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10625,6 +10646,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11149,6 +11171,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11658,6 +11681,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12153,6 +12177,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12650,6 +12675,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13165,6 +13191,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13672,6 +13699,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14181,6 +14209,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14699,6 +14728,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15223,6 +15253,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15732,6 +15763,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16243,6 +16275,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16756,6 +16789,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17287,6 +17321,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17810,6 +17845,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18335,6 +18371,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18869,6 +18906,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19409,6 +19447,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19934,6 +19973,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20434,6 +20474,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20931,6 +20972,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21446,6 +21488,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -21953,6 +21996,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22460,6 +22504,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -22978,6 +23023,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -23498,6 +23544,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24007,6 +24054,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24502,6 +24550,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -24999,6 +25048,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -25514,6 +25564,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26021,6 +26072,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -26528,6 +26580,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -27046,6 +27099,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -27566,6 +27620,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -28075,6 +28130,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -28586,6 +28642,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -29099,6 +29156,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -29630,6 +29688,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -30153,6 +30212,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -30676,6 +30736,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -31210,6 +31271,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -31746,6 +31808,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -32271,6 +32334,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_basic_myisam.result b/mysql-test/suite/parts/r/partition_basic_myisam.result index 3b84c0295f2..06bf043b382 100644 --- a/mysql-test/suite/parts/r/partition_basic_myisam.result +++ b/mysql-test/suite/parts/r/partition_basic_myisam.result @@ -490,6 +490,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -956,6 +957,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1443,6 +1445,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1920,6 +1923,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2401,6 +2405,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2891,6 +2896,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3387,6 +3393,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3869,6 +3876,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4331,6 +4339,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4797,6 +4806,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5284,6 +5294,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5761,6 +5772,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6240,6 +6252,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6730,6 +6743,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7222,6 +7236,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7704,6 +7719,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8223,6 +8239,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8742,6 +8759,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9282,6 +9300,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9812,6 +9831,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10346,6 +10366,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10889,6 +10910,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11438,6 +11460,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11973,6 +11996,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12492,6 +12516,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13011,6 +13036,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13551,6 +13577,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14081,6 +14108,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14613,6 +14641,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15156,6 +15185,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15701,6 +15731,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16236,6 +16267,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_basic_symlink_myisam.result b/mysql-test/suite/parts/r/partition_basic_symlink_myisam.result index 5e59c8f08ba..df141a93033 100644 --- a/mysql-test/suite/parts/r/partition_basic_symlink_myisam.result +++ b/mysql-test/suite/parts/r/partition_basic_symlink_myisam.result @@ -505,6 +505,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1000,6 +1001,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1511,6 +1513,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2012,6 +2015,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2517,6 +2521,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3027,6 +3032,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3559,6 +3565,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4065,6 +4072,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4538,6 +4546,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5033,6 +5042,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5544,6 +5554,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6045,6 +6056,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -6548,6 +6560,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7058,6 +7071,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -7590,6 +7604,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8096,6 +8111,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -8626,6 +8642,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9174,6 +9191,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -9738,6 +9756,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10292,6 +10311,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -10850,6 +10870,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11413,6 +11434,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -11998,6 +12020,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -12557,6 +12580,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13087,6 +13111,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -13635,6 +13660,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14199,6 +14225,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -14753,6 +14780,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15309,6 +15337,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -15872,6 +15901,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -16457,6 +16487,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17016,6 +17047,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -17540,6 +17572,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18078,6 +18111,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -18635,6 +18669,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19177,6 +19212,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -19723,6 +19759,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20279,6 +20316,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -20830,6 +20868,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_engine_innodb.result b/mysql-test/suite/parts/r/partition_engine_innodb.result index 002fe90c78a..38221951ae8 100644 --- a/mysql-test/suite/parts/r/partition_engine_innodb.result +++ b/mysql-test/suite/parts/r/partition_engine_innodb.result @@ -475,6 +475,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -933,6 +934,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1395,6 +1397,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1920,6 +1923,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2421,6 +2425,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2883,6 +2888,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3342,6 +3348,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3804,6 +3811,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4269,6 +4277,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4723,6 +4732,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5178,6 +5188,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_engine_myisam.result b/mysql-test/suite/parts/r/partition_engine_myisam.result index f940b250c19..683729fa2f3 100644 --- a/mysql-test/suite/parts/r/partition_engine_myisam.result +++ b/mysql-test/suite/parts/r/partition_engine_myisam.result @@ -485,6 +485,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -952,6 +953,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1427,6 +1429,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1965,6 +1968,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2479,6 +2483,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2954,6 +2959,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3422,6 +3428,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3897,6 +3904,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4375,6 +4383,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4836,6 +4845,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5300,6 +5310,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result index 88469a339ad..023195e9760 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result @@ -1020,6 +1020,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +MySQL_Test_DB.t1 analyze status Engine-independent statistics collected MySQL_Test_DB.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result index 585bd24dca6..0b5f96696b0 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result @@ -1020,6 +1020,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +MySQL_Test_DB.t1 analyze status Engine-independent statistics collected MySQL_Test_DB.t1 analyze note The storage engine for the table doesn't support analyze # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result index 59181388bd0..8461d4136e0 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result @@ -1020,6 +1020,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +MySQL_Test_DB.t1 analyze status Engine-independent statistics collected MySQL_Test_DB.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result index c4d63f663e1..4c541d9467e 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result @@ -987,6 +987,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +mysql_test_db.t1 analyze status Engine-independent statistics collected mysql_test_db.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result index d29dfd343a6..8f934506ee2 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result @@ -987,6 +987,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +mysql_test_db.t1 analyze status Engine-independent statistics collected mysql_test_db.t1 analyze note The storage engine for the table doesn't support analyze # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result index f26b975b75e..47e07ecc3a6 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result @@ -987,6 +987,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +mysql_test_db.t1 analyze status Engine-independent statistics collected mysql_test_db.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result index a1dad1b34b3..6cd4c4991b7 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result @@ -987,6 +987,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +mysql_test_db.t1 analyze status Engine-independent statistics collected mysql_test_db.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result index 88f59da8f13..d1b7a599923 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result @@ -987,6 +987,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +mysql_test_db.t1 analyze status Engine-independent statistics collected mysql_test_db.t1 analyze note The storage engine for the table doesn't support analyze # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result index a498d4667b1..ad83e95929a 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result @@ -987,6 +987,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +mysql_test_db.t1 analyze status Engine-independent statistics collected mysql_test_db.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/mysql-test/suite/parts/r/partition_recover_myisam.result b/mysql-test/suite/parts/r/partition_recover_myisam.result index 4b9e3f5c283..151ff802a82 100644 --- a/mysql-test/suite/parts/r/partition_recover_myisam.result +++ b/mysql-test/suite/parts/r/partition_recover_myisam.result @@ -18,10 +18,10 @@ a 11 Warnings: Error 145 Table 't1_will_crash' is marked as crashed and should be repaired -Error 1034 1 client is using or hasn't closed the table properly +Warning 1034 1 client is using or hasn't closed the table properly Error 1034 Size of indexfile is: 1024 Should be: 2048 -Error 1034 Size of datafile is: 77 Should be: 7 -Error 1034 Number of rows changed from 1 to 11 +Warning 1034 Size of datafile is: 77 Should be: 7 +Warning 1034 Number of rows changed from 1 to 11 DROP TABLE t1_will_crash; CREATE TABLE t1_will_crash (a INT, KEY (a)) ENGINE=MyISAM @@ -47,8 +47,8 @@ a 11 Warnings: Error 145 Table 't1_will_crash#P#p1' is marked as crashed and should be repaired -Error 1034 1 client is using or hasn't closed the table properly +Warning 1034 1 client is using or hasn't closed the table properly Error 1034 Size of indexfile is: 1024 Should be: 2048 -Error 1034 Size of datafile is: 28 Should be: 7 -Error 1034 Number of rows changed from 1 to 4 +Warning 1034 Size of datafile is: 28 Should be: 7 +Warning 1034 Number of rows changed from 1 to 4 DROP TABLE t1_will_crash; diff --git a/mysql-test/suite/parts/r/partition_repair_myisam.result b/mysql-test/suite/parts/r/partition_repair_myisam.result index 6e99f1d3632..0521263df12 100644 --- a/mysql-test/suite/parts/r/partition_repair_myisam.result +++ b/mysql-test/suite/parts/r/partition_repair_myisam.result @@ -322,7 +322,8 @@ FLUSH TABLES; # replacing p6 with a crashed MYD file (1) (splitted dynamic record) ANALYZE TABLE t1_will_crash; Table Op Msg_type Msg_text -test.t1_will_crash analyze status OK +test.t1_will_crash analyze Warning Engine-independent statistics are not collected for column 'c' +test.t1_will_crash analyze status Operation failed OPTIMIZE TABLE t1_will_crash; Table Op Msg_type Msg_text test.t1_will_crash optimize info Found row block followed by deleted block diff --git a/mysql-test/suite/parts/r/rpl_partition.result b/mysql-test/suite/parts/r/rpl_partition.result index 480ab219c34..dcd45ce4fe1 100644 --- a/mysql-test/suite/parts/r/rpl_partition.result +++ b/mysql-test/suite/parts/r/rpl_partition.result @@ -65,6 +65,10 @@ DELETE FROM t1 WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE PROCEDURE p2() BEGIN DECLARE ins_count INT DEFAULT 1000; @@ -86,6 +90,10 @@ DELETE FROM t2 WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE PROCEDURE p3() BEGIN DECLARE ins_count INT DEFAULT 1000; @@ -107,6 +115,10 @@ DELETE FROM t3 WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead begin; CALL p1(); commit; diff --git a/mysql-test/suite/perfschema/r/bad_option_1.result b/mysql-test/suite/perfschema/r/bad_option_1.result index 02fd04afd33..07632ce494e 100644 --- a/mysql-test/suite/perfschema/r/bad_option_1.result +++ b/mysql-test/suite/perfschema/r/bad_option_1.result @@ -1,2 +1,3 @@ +# Kill the server Found: unknown variable 'performance-schema-enabled=maybe' Found: Aborting diff --git a/mysql-test/suite/perfschema/r/bad_option_2.result b/mysql-test/suite/perfschema/r/bad_option_2.result index 7a5ab31aabd..c035666c01a 100644 --- a/mysql-test/suite/perfschema/r/bad_option_2.result +++ b/mysql-test/suite/perfschema/r/bad_option_2.result @@ -1 +1,2 @@ +# Kill the server FOUND 1 /ambiguous option '--performance-schema-max_=12'/ in bad_option_2.txt diff --git a/mysql-test/suite/perfschema/r/bad_option_3.result b/mysql-test/suite/perfschema/r/bad_option_3.result index ec717d6f7d2..580bea9ab6b 100644 --- a/mysql-test/suite/perfschema/r/bad_option_3.result +++ b/mysql-test/suite/perfschema/r/bad_option_3.result @@ -1,2 +1,3 @@ +# Kill the server Found: unknown option '-x' Found: Aborting diff --git a/mysql-test/suite/perfschema/r/bad_option_4.result b/mysql-test/suite/perfschema/r/bad_option_4.result index 812ee546200..5319612a82c 100644 --- a/mysql-test/suite/perfschema/r/bad_option_4.result +++ b/mysql-test/suite/perfschema/r/bad_option_4.result @@ -1,2 +1,3 @@ +# Kill the server Found: Can't change dir to.*bad_option_h_param Found: Aborting diff --git a/mysql-test/suite/perfschema/r/bad_option_5.result b/mysql-test/suite/perfschema/r/bad_option_5.result index b318b6e0482..19dfe288939 100644 --- a/mysql-test/suite/perfschema/r/bad_option_5.result +++ b/mysql-test/suite/perfschema/r/bad_option_5.result @@ -1,2 +1,3 @@ +# Kill the server Found: unknown option '-X' Found: Aborting diff --git a/mysql-test/suite/perfschema/r/dml_handler.result b/mysql-test/suite/perfschema/r/dml_handler.result index ab850aee933..ce0f87e7733 100644 --- a/mysql-test/suite/perfschema/r/dml_handler.result +++ b/mysql-test/suite/perfschema/r/dml_handler.result @@ -6,6 +6,8 @@ SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='performance_schema' ORDER BY TABLE_NAME; SELECT COUNT(*) FROM table_list INTO @table_count; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead # For each table in the performance schema, attempt HANDLER...OPEN, # which should fail with an error 1031, ER_ILLEGAL_HA. diff --git a/mysql-test/suite/perfschema/r/dml_setup_instruments.result b/mysql-test/suite/perfschema/r/dml_setup_instruments.result index ff184806e2e..307c5c5366a 100644 --- a/mysql-test/suite/perfschema/r/dml_setup_instruments.result +++ b/mysql-test/suite/perfschema/r/dml_setup_instruments.result @@ -22,13 +22,13 @@ NAME ENABLED TIMED wait/synch/rwlock/sql/LOCK_dboptions YES YES wait/synch/rwlock/sql/LOCK_grant YES YES wait/synch/rwlock/sql/LOCK_SEQUENCE YES YES +wait/synch/rwlock/sql/LOCK_ssl_refresh YES YES wait/synch/rwlock/sql/LOCK_system_variables_hash YES YES wait/synch/rwlock/sql/LOCK_sys_init_connect YES YES wait/synch/rwlock/sql/LOCK_sys_init_slave YES YES wait/synch/rwlock/sql/LOGGER::LOCK_logger YES YES wait/synch/rwlock/sql/MDL_context::LOCK_waiting_for YES YES wait/synch/rwlock/sql/MDL_lock::rwlock YES YES -wait/synch/rwlock/sql/Query_cache_query::lock YES YES select * from performance_schema.setup_instruments where name like 'Wait/Synch/Cond/sql/%' and name not in ( diff --git a/mysql-test/suite/perfschema/r/event_aggregate.result b/mysql-test/suite/perfschema/r/event_aggregate.result index 9ab62329fc9..7fa08534bb1 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate.result +++ b/mysql-test/suite/perfschema/r/event_aggregate.result @@ -235,38 +235,38 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 3 -localhost stage/sql/Closing tables 4 +localhost stage/sql/Closing tables 6 localhost stage/sql/Init 5 localhost stage/sql/Init for update 1 -localhost stage/sql/Opening tables 3 +localhost stage/sql/Opening tables 4 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -363,10 +363,10 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 0 user2 localhost stage/sql/Closing tables 0 user2 localhost stage/sql/Init 0 @@ -375,10 +375,10 @@ user2 localhost stage/sql/Opening tables 0 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 0 user2 stage/sql/Closing tables 0 user2 stage/sql/Init 0 @@ -387,24 +387,24 @@ user2 stage/sql/Opening tables 0 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 3 -localhost stage/sql/Closing tables 4 +localhost stage/sql/Closing tables 6 localhost stage/sql/Init 5 localhost stage/sql/Init for update 1 -localhost stage/sql/Opening tables 3 +localhost stage/sql/Opening tables 4 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -518,10 +518,10 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -530,10 +530,10 @@ user2 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -542,24 +542,24 @@ user2 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 6 -localhost stage/sql/Closing tables 8 +localhost stage/sql/Closing tables 10 localhost stage/sql/Init 10 localhost stage/sql/Init for update 2 -localhost stage/sql/Opening tables 6 +localhost stage/sql/Opening tables 7 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -677,10 +677,10 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -694,10 +694,10 @@ user3 localhost stage/sql/Opening tables 0 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -711,24 +711,24 @@ user3 stage/sql/Opening tables 0 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 6 -localhost stage/sql/Closing tables 8 +localhost stage/sql/Closing tables 10 localhost stage/sql/Init 10 localhost stage/sql/Init for update 2 -localhost stage/sql/Opening tables 6 +localhost stage/sql/Opening tables 7 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -863,10 +863,10 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -880,10 +880,10 @@ user3 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -897,24 +897,24 @@ user3 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 9 -localhost stage/sql/Closing tables 12 +localhost stage/sql/Closing tables 14 localhost stage/sql/Init 15 localhost stage/sql/Init for update 3 -localhost stage/sql/Opening tables 9 +localhost stage/sql/Opening tables 10 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1053,10 +1053,10 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -1075,10 +1075,10 @@ user4 localhost stage/sql/Opening tables 0 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -1097,24 +1097,24 @@ user4 stage/sql/Opening tables 0 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 9 -localhost stage/sql/Closing tables 12 +localhost stage/sql/Closing tables 14 localhost stage/sql/Init 15 localhost stage/sql/Init for update 3 -localhost stage/sql/Opening tables 9 +localhost stage/sql/Opening tables 10 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1270,10 +1270,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -1292,10 +1292,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -1314,24 +1314,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 20 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1478,10 +1478,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -1500,10 +1500,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -1522,24 +1522,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 21 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1684,10 +1684,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1706,10 +1706,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1728,24 +1728,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 22 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1887,10 +1887,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1909,10 +1909,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1931,24 +1931,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 23 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2087,10 +2087,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2109,10 +2109,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2131,24 +2131,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2288,10 +2288,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2310,10 +2310,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2332,24 +2332,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2488,10 +2488,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2510,10 +2510,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2532,24 +2532,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2688,10 +2688,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2710,10 +2710,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2732,24 +2732,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2888,10 +2888,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2910,10 +2910,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2932,24 +2932,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3088,10 +3088,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -3110,10 +3110,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -3132,24 +3132,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3288,10 +3288,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -3310,10 +3310,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -3332,24 +3332,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3510,10 +3510,10 @@ user4 localhost stage/sql/Opening tables 0 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -3532,24 +3532,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3732,24 +3732,24 @@ user4 stage/sql/Opening tables 0 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3939,17 +3939,17 @@ localhost stage/sql/Opening tables 0 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4146,10 +4146,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4346,10 +4346,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4546,10 +4546,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4746,10 +4746,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4946,10 +4946,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5146,10 +5146,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5310,10 +5310,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -5418,10 +5418,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -5506,10 +5506,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a.result index ece0402335d..19dec52aa47 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a.result @@ -217,31 +217,31 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 3 -localhost stage/sql/Closing tables 4 +localhost stage/sql/Closing tables 6 localhost stage/sql/Init 5 localhost stage/sql/Init for update 1 -localhost stage/sql/Opening tables 3 +localhost stage/sql/Opening tables 4 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -326,10 +326,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 0 user2 stage/sql/Closing tables 0 user2 stage/sql/Init 0 @@ -338,24 +338,24 @@ user2 stage/sql/Opening tables 0 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 3 -localhost stage/sql/Closing tables 4 +localhost stage/sql/Closing tables 6 localhost stage/sql/Init 5 localhost stage/sql/Init for update 1 -localhost stage/sql/Opening tables 3 +localhost stage/sql/Opening tables 4 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -452,10 +452,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -464,24 +464,24 @@ user2 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 6 -localhost stage/sql/Closing tables 8 +localhost stage/sql/Closing tables 10 localhost stage/sql/Init 10 localhost stage/sql/Init for update 2 -localhost stage/sql/Opening tables 6 +localhost stage/sql/Opening tables 7 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -578,10 +578,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -595,24 +595,24 @@ user3 stage/sql/Opening tables 0 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 6 -localhost stage/sql/Closing tables 8 +localhost stage/sql/Closing tables 10 localhost stage/sql/Init 10 localhost stage/sql/Init for update 2 -localhost stage/sql/Opening tables 6 +localhost stage/sql/Opening tables 7 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -721,10 +721,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -738,24 +738,24 @@ user3 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 9 -localhost stage/sql/Closing tables 12 +localhost stage/sql/Closing tables 14 localhost stage/sql/Init 15 localhost stage/sql/Init for update 3 -localhost stage/sql/Opening tables 9 +localhost stage/sql/Opening tables 10 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -864,10 +864,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -886,24 +886,24 @@ user4 stage/sql/Opening tables 0 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 9 -localhost stage/sql/Closing tables 12 +localhost stage/sql/Closing tables 14 localhost stage/sql/Init 15 localhost stage/sql/Init for update 3 -localhost stage/sql/Opening tables 9 +localhost stage/sql/Opening tables 10 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1024,10 +1024,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -1046,24 +1046,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 20 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1175,10 +1175,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -1197,24 +1197,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 21 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1324,10 +1324,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1346,24 +1346,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 22 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1470,10 +1470,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1492,24 +1492,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 23 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1613,10 +1613,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1635,24 +1635,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1757,10 +1757,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1779,24 +1779,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1900,10 +1900,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1922,24 +1922,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2043,10 +2043,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2065,24 +2065,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2186,10 +2186,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2208,24 +2208,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2329,10 +2329,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2351,24 +2351,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2472,10 +2472,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2494,24 +2494,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2615,10 +2615,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2637,24 +2637,24 @@ user4 stage/sql/Opening tables 3 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2780,24 +2780,24 @@ user4 stage/sql/Opening tables 0 execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2930,17 +2930,17 @@ localhost stage/sql/Opening tables 0 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3080,10 +3080,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3223,10 +3223,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3366,10 +3366,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3509,10 +3509,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3652,10 +3652,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3795,10 +3795,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3938,10 +3938,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4045,10 +4045,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4132,10 +4132,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result index 083e1bffdd2..3aa27664cac 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result @@ -185,26 +185,26 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 execute dump_stages_host; host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -280,10 +280,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 0 user2 stage/sql/Closing tables 0 user2 stage/sql/Init 0 @@ -294,17 +294,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -392,10 +392,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -406,17 +406,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -504,10 +504,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -523,17 +523,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -633,10 +633,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -652,17 +652,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -762,10 +762,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -786,17 +786,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -908,10 +908,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -932,17 +932,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1045,10 +1045,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -1069,17 +1069,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1180,10 +1180,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1204,17 +1204,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1312,10 +1312,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1336,17 +1336,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1441,10 +1441,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1465,17 +1465,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1571,10 +1571,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1595,17 +1595,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1700,10 +1700,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1724,17 +1724,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1829,10 +1829,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1853,17 +1853,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1958,10 +1958,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1982,17 +1982,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2087,10 +2087,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2111,17 +2111,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2216,10 +2216,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2240,17 +2240,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2345,10 +2345,10 @@ user host event_name count_star execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2369,17 +2369,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2498,17 +2498,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2627,17 +2627,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2763,10 +2763,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2892,10 +2892,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3021,10 +3021,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3150,10 +3150,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3279,10 +3279,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3408,10 +3408,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3537,10 +3537,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3630,10 +3630,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3703,10 +3703,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result index c9b2b768691..4d4a842948f 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result @@ -199,24 +199,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 3 -localhost stage/sql/Closing tables 4 +localhost stage/sql/Closing tables 6 localhost stage/sql/Init 5 localhost stage/sql/Init for update 1 -localhost stage/sql/Opening tables 3 +localhost stage/sql/Opening tables 4 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -289,24 +289,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 3 -localhost stage/sql/Closing tables 4 +localhost stage/sql/Closing tables 6 localhost stage/sql/Init 5 localhost stage/sql/Init for update 1 -localhost stage/sql/Opening tables 3 +localhost stage/sql/Opening tables 4 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -386,24 +386,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 6 -localhost stage/sql/Closing tables 8 +localhost stage/sql/Closing tables 10 localhost stage/sql/Init 10 localhost stage/sql/Init for update 2 -localhost stage/sql/Opening tables 6 +localhost stage/sql/Opening tables 7 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -479,24 +479,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 6 -localhost stage/sql/Closing tables 8 +localhost stage/sql/Closing tables 10 localhost stage/sql/Init 10 localhost stage/sql/Init for update 2 -localhost stage/sql/Opening tables 6 +localhost stage/sql/Opening tables 7 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -579,24 +579,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 9 -localhost stage/sql/Closing tables 12 +localhost stage/sql/Closing tables 14 localhost stage/sql/Init 15 localhost stage/sql/Init for update 3 -localhost stage/sql/Opening tables 9 +localhost stage/sql/Opening tables 10 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -675,24 +675,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 9 -localhost stage/sql/Closing tables 12 +localhost stage/sql/Closing tables 14 localhost stage/sql/Init 15 localhost stage/sql/Init for update 3 -localhost stage/sql/Opening tables 9 +localhost stage/sql/Opening tables 10 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -778,24 +778,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 20 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -872,24 +872,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 21 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -964,24 +964,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 22 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1053,24 +1053,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 23 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1139,24 +1139,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1226,24 +1226,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1312,24 +1312,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1398,24 +1398,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1484,24 +1484,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1570,24 +1570,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1656,24 +1656,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1742,24 +1742,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1828,24 +1828,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1921,17 +1921,17 @@ localhost stage/sql/Opening tables 0 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2014,10 +2014,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2100,10 +2100,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2186,10 +2186,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2272,10 +2272,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2358,10 +2358,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2444,10 +2444,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2530,10 +2530,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2616,10 +2616,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2702,10 +2702,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result index 89443515f31..db281652c0c 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result @@ -169,17 +169,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -245,17 +245,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -328,17 +328,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -407,17 +407,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -493,17 +493,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -575,17 +575,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -664,17 +664,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -744,17 +744,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -822,17 +822,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -897,17 +897,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -969,17 +969,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1042,17 +1042,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1114,17 +1114,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1186,17 +1186,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1258,17 +1258,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1330,17 +1330,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1402,17 +1402,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1474,17 +1474,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1546,17 +1546,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1618,17 +1618,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1697,10 +1697,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1769,10 +1769,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1841,10 +1841,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1913,10 +1913,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1985,10 +1985,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2057,10 +2057,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2129,10 +2129,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2201,10 +2201,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2273,10 +2273,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_h.result index 0ea5d90ea41..c8996fa2846 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_h.result @@ -203,33 +203,33 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 execute dump_stages_host; host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -317,10 +317,10 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 0 user2 localhost stage/sql/Closing tables 0 user2 localhost stage/sql/Init 0 @@ -329,10 +329,10 @@ user2 localhost stage/sql/Opening tables 0 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 0 user2 stage/sql/Closing tables 0 user2 stage/sql/Init 0 @@ -343,17 +343,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -458,10 +458,10 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -470,10 +470,10 @@ user2 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -484,17 +484,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -603,10 +603,10 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -620,10 +620,10 @@ user3 localhost stage/sql/Opening tables 0 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -639,17 +639,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -775,10 +775,10 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -792,10 +792,10 @@ user3 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -811,17 +811,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -951,10 +951,10 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -973,10 +973,10 @@ user4 localhost stage/sql/Opening tables 0 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -997,17 +997,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1154,10 +1154,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -1176,10 +1176,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 5 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -1200,17 +1200,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1348,10 +1348,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -1370,10 +1370,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 5 @@ -1394,17 +1394,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1540,10 +1540,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1562,10 +1562,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1586,17 +1586,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1729,10 +1729,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1751,10 +1751,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1775,17 +1775,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1915,10 +1915,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1937,10 +1937,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -1961,17 +1961,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2102,10 +2102,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2124,10 +2124,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2148,17 +2148,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2288,10 +2288,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2310,10 +2310,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2334,17 +2334,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2474,10 +2474,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2496,10 +2496,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2520,17 +2520,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2660,10 +2660,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2682,10 +2682,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2706,17 +2706,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2846,10 +2846,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2868,10 +2868,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -2892,17 +2892,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3032,10 +3032,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -3054,10 +3054,10 @@ user4 localhost stage/sql/Opening tables 3 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -3078,17 +3078,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3240,10 +3240,10 @@ user4 localhost stage/sql/Opening tables 0 execute dump_stages_user; user event_name count_star user1 stage/sql/Checking permissions 3 -user1 stage/sql/Closing tables 4 +user1 stage/sql/Closing tables 6 user1 stage/sql/Init 6 user1 stage/sql/Init for update 1 -user1 stage/sql/Opening tables 3 +user1 stage/sql/Opening tables 4 user2 stage/sql/Checking permissions 3 user2 stage/sql/Closing tables 4 user2 stage/sql/Init 6 @@ -3264,17 +3264,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3450,17 +3450,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3636,17 +3636,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3829,10 +3829,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4015,10 +4015,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4201,10 +4201,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4387,10 +4387,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4573,10 +4573,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4759,10 +4759,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4909,10 +4909,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -5003,10 +5003,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -5077,10 +5077,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_u.result b/mysql-test/suite/perfschema/r/event_aggregate_no_u.result index 52c674024bd..508a65d9ba0 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_u.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_u.result @@ -215,33 +215,33 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 execute dump_stages_user; user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 3 -localhost stage/sql/Closing tables 4 +localhost stage/sql/Closing tables 6 localhost stage/sql/Init 5 localhost stage/sql/Init for update 1 -localhost stage/sql/Opening tables 3 +localhost stage/sql/Opening tables 4 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -324,10 +324,10 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 0 user2 localhost stage/sql/Closing tables 0 user2 localhost stage/sql/Init 0 @@ -338,24 +338,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 3 -localhost stage/sql/Closing tables 4 +localhost stage/sql/Closing tables 6 localhost stage/sql/Init 5 localhost stage/sql/Init for update 1 -localhost stage/sql/Opening tables 3 +localhost stage/sql/Opening tables 4 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -450,10 +450,10 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -464,24 +464,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 6 -localhost stage/sql/Closing tables 8 +localhost stage/sql/Closing tables 10 localhost stage/sql/Init 10 localhost stage/sql/Init for update 2 -localhost stage/sql/Opening tables 6 +localhost stage/sql/Opening tables 7 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -576,10 +576,10 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -595,24 +595,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 6 -localhost stage/sql/Closing tables 8 +localhost stage/sql/Closing tables 10 localhost stage/sql/Init 10 localhost stage/sql/Init for update 2 -localhost stage/sql/Opening tables 6 +localhost stage/sql/Opening tables 7 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -719,10 +719,10 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -738,24 +738,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 9 -localhost stage/sql/Closing tables 12 +localhost stage/sql/Closing tables 14 localhost stage/sql/Init 15 localhost stage/sql/Init for update 3 -localhost stage/sql/Opening tables 9 +localhost stage/sql/Opening tables 10 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -862,10 +862,10 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -886,24 +886,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 9 -localhost stage/sql/Closing tables 12 +localhost stage/sql/Closing tables 14 localhost stage/sql/Init 15 localhost stage/sql/Init for update 3 -localhost stage/sql/Opening tables 9 +localhost stage/sql/Opening tables 10 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1022,10 +1022,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -1046,24 +1046,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 20 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1173,10 +1173,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -1197,24 +1197,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 21 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1322,10 +1322,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1346,24 +1346,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 22 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1468,10 +1468,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1492,24 +1492,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 23 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1611,10 +1611,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1635,24 +1635,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1755,10 +1755,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1779,24 +1779,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1898,10 +1898,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1922,24 +1922,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2041,10 +2041,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2065,24 +2065,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2184,10 +2184,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2208,24 +2208,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2327,10 +2327,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2351,24 +2351,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2470,10 +2470,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2494,24 +2494,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2637,24 +2637,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2780,24 +2780,24 @@ user event_name count_star execute dump_stages_host; host event_name count_star localhost stage/sql/Checking permissions 12 -localhost stage/sql/Closing tables 16 +localhost stage/sql/Closing tables 18 localhost stage/sql/Init 24 localhost stage/sql/Init for update 4 -localhost stage/sql/Opening tables 12 +localhost stage/sql/Opening tables 13 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2930,17 +2930,17 @@ localhost stage/sql/Opening tables 0 execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3080,10 +3080,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3223,10 +3223,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3366,10 +3366,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3509,10 +3509,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3652,10 +3652,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3795,10 +3795,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3902,10 +3902,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3989,10 +3989,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4076,10 +4076,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result index a493631d71f..579fadc51c0 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result @@ -183,10 +183,10 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -194,17 +194,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -278,10 +278,10 @@ wait/synch/rwlock/sql/LOCK_grant 1 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 0 user2 localhost stage/sql/Closing tables 0 user2 localhost stage/sql/Init 0 @@ -294,17 +294,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 3 -stage/sql/Closing tables 4 +stage/sql/Closing tables 6 stage/sql/Init 5 stage/sql/Init for update 1 -stage/sql/Opening tables 3 +stage/sql/Opening tables 4 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -390,10 +390,10 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -406,17 +406,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -502,10 +502,10 @@ wait/synch/rwlock/sql/LOCK_grant 2 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -523,17 +523,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 6 -stage/sql/Closing tables 8 +stage/sql/Closing tables 10 stage/sql/Init 10 stage/sql/Init for update 2 -stage/sql/Opening tables 6 +stage/sql/Opening tables 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -631,10 +631,10 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -652,17 +652,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -760,10 +760,10 @@ wait/synch/rwlock/sql/LOCK_grant 3 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -786,17 +786,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 9 -stage/sql/Closing tables 12 +stage/sql/Closing tables 14 stage/sql/Init 15 stage/sql/Init for update 3 -stage/sql/Opening tables 9 +stage/sql/Opening tables 10 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -906,10 +906,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 5 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -932,17 +932,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 20 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1043,10 +1043,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 5 @@ -1069,17 +1069,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 21 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1178,10 +1178,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1204,17 +1204,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 22 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1310,10 +1310,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1336,17 +1336,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 23 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1439,10 +1439,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1465,17 +1465,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1569,10 +1569,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1595,17 +1595,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1698,10 +1698,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1724,17 +1724,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1827,10 +1827,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1853,17 +1853,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1956,10 +1956,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -1982,17 +1982,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2085,10 +2085,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2111,17 +2111,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2214,10 +2214,10 @@ wait/synch/rwlock/sql/LOCK_grant 4 execute dump_stages_account; user host event_name count_star user1 localhost stage/sql/Checking permissions 3 -user1 localhost stage/sql/Closing tables 4 +user1 localhost stage/sql/Closing tables 6 user1 localhost stage/sql/Init 6 user1 localhost stage/sql/Init for update 1 -user1 localhost stage/sql/Opening tables 3 +user1 localhost stage/sql/Opening tables 4 user2 localhost stage/sql/Checking permissions 3 user2 localhost stage/sql/Closing tables 4 user2 localhost stage/sql/Init 6 @@ -2240,17 +2240,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2369,17 +2369,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2498,17 +2498,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2627,17 +2627,17 @@ host event_name count_star execute dump_stages_global; event_name count_star stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2763,10 +2763,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2892,10 +2892,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3021,10 +3021,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3150,10 +3150,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3279,10 +3279,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3408,10 +3408,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3501,10 +3501,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3574,10 +3574,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3647,10 +3647,10 @@ stage/sql/Opening tables 0 execute dump_stages_history; event_name count(event_name) stage/sql/Checking permissions 12 -stage/sql/Closing tables 16 +stage/sql/Closing tables 18 stage/sql/Init 24 stage/sql/Init for update 4 -stage/sql/Opening tables 12 +stage/sql/Opening tables 13 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/hostcache_ipv4_nameinfo_again_allow.result b/mysql-test/suite/perfschema/r/hostcache_ipv4_nameinfo_again_allow.result index a172dff7935..7963bed8213 100644 --- a/mysql-test/suite/perfschema/r/hostcache_ipv4_nameinfo_again_allow.result +++ b/mysql-test/suite/perfschema/r/hostcache_ipv4_nameinfo_again_allow.result @@ -118,7 +118,7 @@ Con4 is alive Con4 is alive select current_user(); current_user() -root@192.0.2.4 +root@santa.claus.ipv4.example.com disconnect con4; connection default; "Dumping performance_schema.host_cache" @@ -155,7 +155,7 @@ Con5 is alive Con5 is alive select current_user(); current_user() -root@192.0.2.4 +root@santa.claus.ipv4.example.com disconnect con5; connection default; "Dumping performance_schema.host_cache" diff --git a/mysql-test/suite/perfschema/r/hostcache_ipv6_nameinfo_again_allow.result b/mysql-test/suite/perfschema/r/hostcache_ipv6_nameinfo_again_allow.result index 4fdc6ef1b4c..baddc88b116 100644 --- a/mysql-test/suite/perfschema/r/hostcache_ipv6_nameinfo_again_allow.result +++ b/mysql-test/suite/perfschema/r/hostcache_ipv6_nameinfo_again_allow.result @@ -118,7 +118,7 @@ Con4 is alive Con4 is alive select current_user(); current_user() -root@2001:db8::6:6 +root@santa.claus.ipv6.example.com disconnect con4; connection default; "Dumping performance_schema.host_cache" @@ -155,7 +155,7 @@ Con5 is alive Con5 is alive select current_user(); current_user() -root@2001:db8::6:6 +root@santa.claus.ipv6.example.com disconnect con5; connection default; "Dumping performance_schema.host_cache" diff --git a/mysql-test/suite/perfschema/r/ortho_iter.result b/mysql-test/suite/perfschema/r/ortho_iter.result index 299551051c9..a1fb88e7059 100644 --- a/mysql-test/suite/perfschema/r/ortho_iter.result +++ b/mysql-test/suite/perfschema/r/ortho_iter.result @@ -95,6 +95,8 @@ close pfs_cursor; signal sqlstate '01000' set message_text='Done', mysql_errno=12000; end $ +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead show variables where `Variable_name` != "performance_schema_max_statement_classes" and `Variable_name` like "performance_schema%"; diff --git a/mysql-test/suite/perfschema/r/privilege_table_io.result b/mysql-test/suite/perfschema/r/privilege_table_io.result index 5443c178502..baa73d28c90 100644 --- a/mysql-test/suite/perfschema/r/privilege_table_io.result +++ b/mysql-test/suite/perfschema/r/privilege_table_io.result @@ -8,7 +8,6 @@ truncate table performance_schema.events_waits_history_long; flush status; flush tables; # We are forced to suppress here the server response. -optimize table mysql.host; optimize table mysql.user; optimize table mysql.db; optimize table mysql.proxies_priv; @@ -96,12 +95,11 @@ where event_name like 'wait/io/table/%' and object_schema in ("test", "mysql") order by thread_id, event_id; event_name short_source object_type object_schema pretty_name operation number_of_bytes -wait/io/table/sql/handler handler.cc: TABLE mysql host fetch NULL -wait/io/table/sql/handler handler.cc: TABLE mysql user fetch NULL -wait/io/table/sql/handler handler.cc: TABLE mysql user fetch NULL -wait/io/table/sql/handler handler.cc: TABLE mysql user fetch NULL -wait/io/table/sql/handler handler.cc: TABLE mysql user fetch NULL -wait/io/table/sql/handler handler.cc: TABLE mysql user fetch NULL +wait/io/table/sql/handler handler.cc: TABLE mysql global_priv fetch NULL +wait/io/table/sql/handler handler.cc: TABLE mysql global_priv fetch NULL +wait/io/table/sql/handler handler.cc: TABLE mysql global_priv fetch NULL +wait/io/table/sql/handler handler.cc: TABLE mysql global_priv fetch NULL +wait/io/table/sql/handler handler.cc: TABLE mysql global_priv fetch NULL wait/io/table/sql/handler handler.cc: TABLE mysql db fetch NULL wait/io/table/sql/handler handler.cc: TABLE mysql db fetch NULL wait/io/table/sql/handler handler.cc: TABLE mysql db fetch NULL @@ -112,6 +110,8 @@ wait/io/table/sql/handler handler.cc: TABLE mysql roles_mapping fetch NULL wait/io/table/sql/handler handler.cc: TABLE mysql tables_priv fetch NULL wait/io/table/sql/handler handler.cc: TABLE mysql procs_priv fetch NULL wait/io/table/sql/handler handler.cc: TABLE mysql servers fetch NULL +wait/io/table/sql/handler handler.cc: TABLE mysql table_stats fetch NULL +wait/io/table/sql/handler handler.cc: TABLE mysql column_stats fetch NULL wait/io/table/sql/handler handler.cc: TABLE test marker insert NULL wait/io/table/sql/handler handler.cc: TABLE test marker insert NULL wait/io/table/sql/handler handler.cc: TABLE test marker insert NULL diff --git a/mysql-test/suite/perfschema/r/selects.result b/mysql-test/suite/perfschema/r/selects.result index c14d152856f..d623d45a6e8 100644 --- a/mysql-test/suite/perfschema/r/selects.result +++ b/mysql-test/suite/perfschema/r/selects.result @@ -93,6 +93,8 @@ SELECT thread_id FROM performance_schema.threads WHERE PROCESSLIST_ID = conid INTO pid; END; | +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL t_ps_proc(connection_id(), @p_id); DROP FUNCTION IF EXISTS t_ps_proc; CREATE FUNCTION t_ps_func(conid INT) RETURNS int diff --git a/mysql-test/suite/perfschema/r/stage_mdl_global.result b/mysql-test/suite/perfschema/r/stage_mdl_global.result index 7d15b250bd9..11531124cae 100644 --- a/mysql-test/suite/perfschema/r/stage_mdl_global.result +++ b/mysql-test/suite/perfschema/r/stage_mdl_global.result @@ -22,7 +22,7 @@ call dump_one_thread('user2'); username event_name sql_text user2 statement/sql/insert insert into test.t1 values (1), (2), (3) username event_name nesting_event_type -user2 stage/sql/Waiting for global read lock STATEMENT +user2 stage/sql/Waiting for backup lock STATEMENT username event_name nesting_event_type user2 stage/sql/Init STATEMENT user2 stage/sql/Checking permissions STATEMENT diff --git a/mysql-test/suite/perfschema/r/table_schema.result b/mysql-test/suite/perfschema/r/table_schema.result index 5c4cf88e9a5..8caf2017fd2 100644 --- a/mysql-test/suite/perfschema/r/table_schema.result +++ b/mysql-test/suite/perfschema/r/table_schema.result @@ -799,6 +799,8 @@ def performance_schema users TOTAL_CONNECTIONS 3 NULL NO bigint NULL NULL 19 0 N select count(*) from information_schema.columns where table_schema="performance_schema" and data_type = "bigint" and column_name like "%number_of_bytes" into @count_byte_columns; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select @count_byte_columns > 0; @count_byte_columns > 0 1 @@ -806,12 +808,16 @@ select count(*) from information_schema.columns where table_schema="performance_schema" and data_type="bigint" and column_name like "%number_of_bytes" and column_type not like "%unsigned" into @count_byte_signed; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select (@count_byte_columns - @count_byte_signed) = 0; (@count_byte_columns - @count_byte_signed) = 0 1 select count(*) from information_schema.columns where table_schema="performance_schema" and data_type = "bigint" and column_name like "%object_instance_begin" into @count_object_columns; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select @count_object_columns > 0; @count_object_columns > 0 1 @@ -819,6 +825,8 @@ select count(*) from information_schema.columns where table_schema="performance_schema" and data_type="bigint" and column_name like "%object_instance_begin" and column_type like "%unsigned" into @count_object_unsigned; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select (@count_object_columns - @count_object_unsigned) = 0; (@count_object_columns - @count_object_unsigned) = 0 1 diff --git a/mysql-test/suite/perfschema/t/bad_option_1.test b/mysql-test/suite/perfschema/t/bad_option_1.test index 1c76dbdc512..bba0d6d5357 100644 --- a/mysql-test/suite/perfschema/t/bad_option_1.test +++ b/mysql-test/suite/perfschema/t/bad_option_1.test @@ -4,9 +4,13 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +--source include/kill_mysqld.inc + let $outfile= $MYSQLTEST_VARDIR/tmp/bad_option_1.txt; +--disable_warnings --error 0,1 --remove_file $outfile +--enable_warnings --error 7 --exec $MYSQLD_BOOTSTRAP_CMD --loose-console --performance-schema-enabled=maybe > $outfile 2>&1 @@ -32,3 +36,4 @@ perl; EOF --remove_file $outfile +--source include/start_mysqld.inc diff --git a/mysql-test/suite/perfschema/t/bad_option_2.test b/mysql-test/suite/perfschema/t/bad_option_2.test index ce3e5c3243b..d6c2b905167 100644 --- a/mysql-test/suite/perfschema/t/bad_option_2.test +++ b/mysql-test/suite/perfschema/t/bad_option_2.test @@ -4,9 +4,13 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +--source include/kill_mysqld.inc + let $outfile= $MYSQLTEST_VARDIR/tmp/bad_option_2.txt; +--disable_warnings --error 0,1 --remove_file $outfile +--enable_warnings --error 3 --exec $MYSQLD_BOOTSTRAP_CMD --loose-console --enable-getopt-prefix-matching --performance-schema-max_=12 > $outfile 2>&1 --let SEARCH_PATTERN=ambiguous option '--performance-schema-max_=12' @@ -14,3 +18,4 @@ let $outfile= $MYSQLTEST_VARDIR/tmp/bad_option_2.txt; --source include/search_pattern_in_file.inc --remove_file $outfile +--source include/start_mysqld.inc diff --git a/mysql-test/suite/perfschema/t/bad_option_3.test b/mysql-test/suite/perfschema/t/bad_option_3.test index 63565df14a2..a4efcbccd74 100644 --- a/mysql-test/suite/perfschema/t/bad_option_3.test +++ b/mysql-test/suite/perfschema/t/bad_option_3.test @@ -4,9 +4,13 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +--source include/kill_mysqld.inc + let $outfile= $MYSQLTEST_VARDIR/tmp/bad_option_3.txt; +--disable_warnings --error 0,1 --remove_file $outfile +--enable_warnings --error 2 --exec $MYSQLD_BOOTSTRAP_CMD --loose-console -a -x > $outfile 2>&1 @@ -32,3 +36,4 @@ perl; EOF --remove_file $outfile +--source include/start_mysqld.inc diff --git a/mysql-test/suite/perfschema/t/bad_option_4.test b/mysql-test/suite/perfschema/t/bad_option_4.test index 27a32c201a9..ee8705788bc 100644 --- a/mysql-test/suite/perfschema/t/bad_option_4.test +++ b/mysql-test/suite/perfschema/t/bad_option_4.test @@ -4,9 +4,13 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +--source include/kill_mysqld.inc + let $outfile= $MYSQLTEST_VARDIR/tmp/bad_option_4.txt; +--disable_warnings --error 0,1 --remove_file $outfile +--enable_warnings --error 1 --exec $MYSQLD_BOOTSTRAP_CMD --loose-console -a -h bad_option_h_param > $outfile 2>&1 @@ -32,3 +36,4 @@ perl; EOF --remove_file $outfile +--source include/start_mysqld.inc diff --git a/mysql-test/suite/perfschema/t/bad_option_5.test b/mysql-test/suite/perfschema/t/bad_option_5.test index ada8228b249..c9c6fc75d52 100644 --- a/mysql-test/suite/perfschema/t/bad_option_5.test +++ b/mysql-test/suite/perfschema/t/bad_option_5.test @@ -4,9 +4,13 @@ --source include/not_embedded.inc --source include/have_perfschema.inc +--source include/kill_mysqld.inc + let $outfile= $MYSQLTEST_VARDIR/tmp/bad_option_5.txt; +--disable_warnings --error 0,1 --remove_file $outfile +--enable_warnings --error 2 --exec $MYSQLD_BOOTSTRAP_CMD --loose-console -aXbroken > $outfile 2>&1 @@ -35,3 +39,4 @@ perl; EOF --remove_file $outfile +--source include/start_mysqld.inc diff --git a/mysql-test/suite/perfschema/t/privilege_table_io.test b/mysql-test/suite/perfschema/t/privilege_table_io.test index 6f729537072..a74805f5c7b 100644 --- a/mysql-test/suite/perfschema/t/privilege_table_io.test +++ b/mysql-test/suite/perfschema/t/privilege_table_io.test @@ -17,7 +17,6 @@ # Therefore we suppress the query_log here. --echo # We are forced to suppress here the server response. --disable_result_log -optimize table mysql.host; optimize table mysql.user; optimize table mysql.db; optimize table mysql.proxies_priv; diff --git a/mysql-test/suite/perfschema/t/stage_mdl_global.test b/mysql-test/suite/perfschema/t/stage_mdl_global.test index 8863d2da903..03c3d315899 100644 --- a/mysql-test/suite/perfschema/t/stage_mdl_global.test +++ b/mysql-test/suite/perfschema/t/stage_mdl_global.test @@ -9,7 +9,7 @@ flush tables with read lock; connect (con2, localhost, user2, , ); -# Will wait on con1, "Waiting for global read lock" +# Will wait on con1, "Waiting for backup lock" --send insert into test.t1 values (1), (2), (3); @@ -26,7 +26,7 @@ let $wait_condition= let $wait_condition= select count(*) = 1 from performance_schema.threads where `TYPE`='FOREGROUND' and PROCESSLIST_USER like 'user2' - and PROCESSLIST_STATE = 'Waiting for global read lock'; + and PROCESSLIST_STATE = 'Waiting for backup lock'; --source include/wait_condition.inc call dump_one_thread('user1'); diff --git a/mysql-test/suite/plugins/r/audit_null.result b/mysql-test/suite/plugins/r/audit_null.result index 75eb5a9f682..ada85b661ee 100644 --- a/mysql-test/suite/plugins/r/audit_null.result +++ b/mysql-test/suite/plugins/r/audit_null.result @@ -74,6 +74,9 @@ root[root] @ localhost [] >> create table t1 (a int) root[root] @ localhost [] test.t1 : create root[root] @ localhost [] >> insert t1 values (1), (2) root[root] @ localhost [] test.t1 : write +root[root] @ localhost [] mysql.table_stats : read +root[root] @ localhost [] mysql.column_stats : read +root[root] @ localhost [] mysql.index_stats : read root[root] @ localhost [] >> select * from t1 root[root] @ localhost [] test.t1 : read root[root] @ localhost [] >> rename table t1 to t2 @@ -90,6 +93,9 @@ root[root] @ localhost [] test.t2 : read root[root] @ localhost [] >> select * from v1 root[root] @ localhost [] test.t2 : read root[root] @ localhost [] test.t2 : read +root[root] @ localhost [] mysql.table_stats : read +root[root] @ localhost [] mysql.column_stats : read +root[root] @ localhost [] mysql.index_stats : read root[root] @ localhost [] >> drop view v1 root[root] @ localhost [] >> create temporary table t2 (a date) root[root] @ localhost [] >> insert t2 values ('2020-10-09') diff --git a/mysql-test/suite/plugins/r/audit_null_debug.result b/mysql-test/suite/plugins/r/audit_null_debug.result index 9d5c7c4a02c..3b18edf1d0b 100644 --- a/mysql-test/suite/plugins/r/audit_null_debug.result +++ b/mysql-test/suite/plugins/r/audit_null_debug.result @@ -1,3 +1,6 @@ +alter table mysql.plugin engine=myisam; +Warnings: +Warning 1478 Table storage engine 'MyISAM' does not support the create option 'TRANSACTIONAL=1' set @old_dbug=@@debug_dbug; call mtr.add_suppression("Index for table.*mysql.plugin.MYI"); call mtr.add_suppression("Index for table 'plugin' is corrupt; try to repair it"); @@ -13,3 +16,4 @@ SET debug_dbug=@old_dbug; uninstall plugin audit_null; ERROR 42000: PLUGIN audit_null does not exist delete from mysql.plugin where name='audit_null'; +alter table mysql.plugin engine=aria; diff --git a/mysql-test/suite/plugins/r/auth_ed25519.result b/mysql-test/suite/plugins/r/auth_ed25519.result index 4785bef3ef7..7b26530ed12 100644 --- a/mysql-test/suite/plugins/r/auth_ed25519.result +++ b/mysql-test/suite/plugins/r/auth_ed25519.result @@ -22,22 +22,41 @@ ed25519_password(NULL) NULL select * from information_schema.plugins where plugin_name='ed25519'; PLUGIN_NAME ed25519 -PLUGIN_VERSION 1.0 +PLUGIN_VERSION 1.1 PLUGIN_STATUS ACTIVE PLUGIN_TYPE AUTHENTICATION -PLUGIN_TYPE_VERSION 2.1 +PLUGIN_TYPE_VERSION 2.2 PLUGIN_LIBRARY auth_ed25519.so -PLUGIN_LIBRARY_VERSION 1.13 +PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_AUTHOR Sergei Golubchik PLUGIN_DESCRIPTION Elliptic curve ED25519 based authentication PLUGIN_LICENSE GPL LOAD_OPTION ON PLUGIN_MATURITY Stable -PLUGIN_AUTH_VERSION 1.0 +PLUGIN_AUTH_VERSION 1.1 create user test1@localhost identified via ed25519 using 'ZIgUREUg5PVgQ6LskhXmO+eZLS0nC8be6HPjYWR4YJY'; show grants for test1@localhost; Grants for test1@localhost GRANT USAGE ON *.* TO 'test1'@'localhost' IDENTIFIED VIA ed25519 USING 'ZIgUREUg5PVgQ6LskhXmO+eZLS0nC8be6HPjYWR4YJY' +drop user test1@localhost; +create user test1@localhost identified via ed25519 using password('foo'); +show grants for test1@localhost; +Grants for test1@localhost +GRANT USAGE ON *.* TO 'test1'@'localhost' IDENTIFIED VIA ed25519 USING 'vubFBzIrapbfHct1/J72dnUryz5VS7lA6XHH8sIx4TI' +select ed25519_password('foo'); +ed25519_password('foo') +vubFBzIrapbfHct1/J72dnUryz5VS7lA6XHH8sIx4TI +set password for test1@localhost = password('bar'); +show create user test1@localhost; +CREATE USER for test1@localhost +CREATE USER 'test1'@'localhost' IDENTIFIED VIA ed25519 USING 'pfzkeWMzkTefY1oshXS+/kATeN51M+4jxi3/cbyTd10' +select ed25519_password('bar'); +ed25519_password('bar') +pfzkeWMzkTefY1oshXS+/kATeN51M+4jxi3/cbyTd10 +set password for test1@localhost = 'ZIgUREUg5PVgQ6LskhXmO+eZLS0nC8be6HPjYWR4YJY'; +show create user test1@localhost; +CREATE USER for test1@localhost +CREATE USER 'test1'@'localhost' IDENTIFIED VIA ed25519 USING 'ZIgUREUg5PVgQ6LskhXmO+eZLS0nC8be6HPjYWR4YJY' connect(localhost,test1,public,test,PORT,SOCKET); connect con1, localhost, test1, public; ERROR 28000: Access denied for user 'test1'@'localhost' (using password: YES) diff --git a/mysql-test/suite/plugins/r/cracklib_password_check.result b/mysql-test/suite/plugins/r/cracklib_password_check.result index 6b4e30b3d81..1194e6eef5a 100644 --- a/mysql-test/suite/plugins/r/cracklib_password_check.result +++ b/mysql-test/suite/plugins/r/cracklib_password_check.result @@ -6,7 +6,7 @@ PLUGIN_STATUS ACTIVE PLUGIN_TYPE PASSWORD VALIDATION PLUGIN_TYPE_VERSION 1.0 PLUGIN_LIBRARY cracklib_password_check.so -PLUGIN_LIBRARY_VERSION 1.13 +PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_AUTHOR Sergei Golubchik PLUGIN_DESCRIPTION Password validation via CrackLib PLUGIN_LICENSE GPL diff --git a/mysql-test/suite/plugins/r/feedback_plugin_load.result b/mysql-test/suite/plugins/r/feedback_plugin_load.result index 8770ce19f49..330f4325f76 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_load.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_load.result @@ -20,7 +20,7 @@ WHERE VARIABLE_NAME LIKE 'Collation used %' ORDER BY VARIABLE_NAME; VARIABLE_VALUE>0 VARIABLE_NAME 1 Collation used binary -1 Collation used latin1_bin 1 Collation used latin1_swedish_ci +1 Collation used utf8mb4_bin 1 Collation used utf8_bin 1 Collation used utf8_general_ci diff --git a/mysql-test/suite/plugins/r/feedback_plugin_send.result b/mysql-test/suite/plugins/r/feedback_plugin_send.result index 935ea11d67b..b09af006e70 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_send.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_send.result @@ -20,8 +20,8 @@ WHERE VARIABLE_NAME LIKE 'Collation used %' ORDER BY VARIABLE_NAME; VARIABLE_VALUE>0 VARIABLE_NAME 1 Collation used binary -1 Collation used latin1_bin 1 Collation used latin1_swedish_ci +1 Collation used utf8mb4_bin 1 Collation used utf8_bin 1 Collation used utf8_general_ci set global sql_mode=ONLY_FULL_GROUP_BY; diff --git a/mysql-test/suite/plugins/r/pam.result b/mysql-test/suite/plugins/r/pam.result index 86303206b3b..a16cd7f3d43 100644 --- a/mysql-test/suite/plugins/r/pam.result +++ b/mysql-test/suite/plugins/r/pam.result @@ -20,6 +20,13 @@ Challenge input first. Enter: not very secret challenge Now, the magic number! PIN: **** +# +# athentication is unsuccessful +# +Challenge input first. +Enter: crash pam module +Now, the magic number! +PIN: *** drop user test_pam; drop user pam_test; uninstall plugin pam; diff --git a/mysql-test/suite/plugins/r/pam_v1.result b/mysql-test/suite/plugins/r/pam_v1.result new file mode 100644 index 00000000000..bf4c0242df2 --- /dev/null +++ b/mysql-test/suite/plugins/r/pam_v1.result @@ -0,0 +1,25 @@ +install plugin pam soname 'auth_pam_v1.so'; +create user test_pam identified via pam using 'mariadb_mtr'; +create user pam_test; +grant proxy on pam_test to test_pam; +# +# athentication is successful, challenge/pin are ok +# note that current_user() differs from user() +# +Challenge input first. +Enter: not very secret challenge +Now, the magic number! +PIN: **** +select user(), current_user(), database(); +user() current_user() database() +test_pam@localhost pam_test@% test +# +# athentication is unsuccessful +# +Challenge input first. +Enter: not very secret challenge +Now, the magic number! +PIN: **** +drop user test_pam; +drop user pam_test; +uninstall plugin pam; diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result index 01392760317..b63419a6e9f 100644 --- a/mysql-test/suite/plugins/r/server_audit.result +++ b/mysql-test/suite/plugins/r/server_audit.result @@ -261,11 +261,17 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create table t2 (id int)',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_excl_users=\'odin, dva, tri\'',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'SHOW WARNINGS',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,test,t1, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,table_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,column_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,index_stats, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t1 values (1), (2)',0 TIME,HOSTNAME,root,localhost,ID,ID,READ,test,t1, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t1',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_incl_users=\'odin, root, dva, tri\'',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,test,t2, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,table_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,column_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,index_stats, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t2 values (1), (2)',0 TIME,HOSTNAME,root,localhost,ID,ID,READ,test,t2, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t2',0 @@ -290,6 +296,9 @@ TIME,HOSTNAME,root,localhost,ID,0,CONNECT,test,,0 TIME,HOSTNAME,root,localhost,ID,ID,CREATE,test,t1, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create table t1 (id2 int)',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,test,t1, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,table_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,column_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,index_stats, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t1 values (1), (2)',0 TIME,HOSTNAME,root,localhost,ID,ID,READ,test,t1, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t1',0 @@ -302,6 +311,9 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,CREATE,sa_db,sa_t1, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table sa_t1(id int)',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,sa_db,sa_t1, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,table_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,column_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,index_stats, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'insert into sa_t1 values (1), (2)',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,table_stats, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,column_stats, @@ -315,34 +327,34 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0 TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT ALL ON sa_db TO u2 IDENTIFIED BY *****',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1 = PASSWORD(*****)',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table t1(id int)',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0 diff --git a/mysql-test/suite/plugins/r/show_all_plugins.result b/mysql-test/suite/plugins/r/show_all_plugins.result index dd6cbfce4c4..3bdaf39d0d0 100644 --- a/mysql-test/suite/plugins/r/show_all_plugins.result +++ b/mysql-test/suite/plugins/r/show_all_plugins.result @@ -4,8 +4,8 @@ Variable_name Value Opened_plugin_libraries 0 select * from information_schema.all_plugins where plugin_library='ha_example.so'; PLUGIN_NAME PLUGIN_VERSION PLUGIN_STATUS PLUGIN_TYPE PLUGIN_TYPE_VERSION PLUGIN_LIBRARY PLUGIN_LIBRARY_VERSION PLUGIN_AUTHOR PLUGIN_DESCRIPTION PLUGIN_LICENSE LOAD_OPTION PLUGIN_MATURITY PLUGIN_AUTH_VERSION -EXAMPLE 0.1 NOT INSTALLED STORAGE ENGINE MYSQL_VERSION_ID ha_example.so 1.13 Brian Aker, MySQL AB Example storage engine GPL OFF Experimental 0.1 -UNUSABLE 3.14 NOT INSTALLED DAEMON MYSQL_VERSION_ID ha_example.so 1.13 Sergei Golubchik Unusable Daemon GPL OFF Experimental 3.14.15.926 +EXAMPLE 0.1 NOT INSTALLED STORAGE ENGINE MYSQL_VERSION_ID ha_example.so 1.14 Brian Aker, MySQL AB Example storage engine GPL OFF Experimental 0.1 +UNUSABLE 3.14 NOT INSTALLED DAEMON MYSQL_VERSION_ID ha_example.so 1.14 Sergei Golubchik Unusable Daemon GPL OFF Experimental 3.14.15.926 show status like '%libraries%'; Variable_name Value Opened_plugin_libraries 1 diff --git a/mysql-test/suite/plugins/r/simple_password_check.result b/mysql-test/suite/plugins/r/simple_password_check.result index 672d0107492..2e706115bd1 100644 --- a/mysql-test/suite/plugins/r/simple_password_check.result +++ b/mysql-test/suite/plugins/r/simple_password_check.result @@ -6,7 +6,7 @@ PLUGIN_STATUS ACTIVE PLUGIN_TYPE PASSWORD VALIDATION PLUGIN_TYPE_VERSION 1.0 PLUGIN_LIBRARY simple_password_check.so -PLUGIN_LIBRARY_VERSION 1.13 +PLUGIN_LIBRARY_VERSION 1.14 PLUGIN_AUTHOR Sergei Golubchik PLUGIN_DESCRIPTION Simple password strength checks PLUGIN_LICENSE GPL @@ -135,9 +135,11 @@ grant select on *.* to foo2 identified with mysql_old_password using '2222222222 ERROR HY000: The MariaDB server is running with the --strict-password-validation option so it cannot execute this statement create user foo2 identified with mysql_native_password using ''; ERROR HY000: Your password does not satisfy the current policy requirements +grant select on *.* to foo2 identified with mysql_old_password using ''; +ERROR HY000: Your password does not satisfy the current policy requirements grant select on *.* to foo2 identified with mysql_old_password; -ERROR 28000: Can't find any matching row in the user table -update mysql.user set password='xxx' where user='foo1'; +ERROR HY000: Your password does not satisfy the current policy requirements +update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'xxx') where user='foo1'; set global strict_password_validation=0; set password for foo1 = ''; ERROR HY000: Your password does not satisfy the current policy requirements @@ -155,6 +157,7 @@ set global strict_password_validation=1; drop user foo1; create role r1; drop role r1; +flush privileges; uninstall plugin simple_password_check; create user foo1 identified by 'pwd'; drop user foo1; diff --git a/mysql-test/suite/plugins/r/thread_pool_server_audit.result b/mysql-test/suite/plugins/r/thread_pool_server_audit.result index cf09ccb3a51..eceb2280ed4 100644 --- a/mysql-test/suite/plugins/r/thread_pool_server_audit.result +++ b/mysql-test/suite/plugins/r/thread_pool_server_audit.result @@ -250,11 +250,17 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create table t2 (id int)',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_excl_users=\'odin, dva, tri\'',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'SHOW WARNINGS',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,test,t1, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,table_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,column_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,index_stats, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t1 values (1), (2)',0 TIME,HOSTNAME,root,localhost,ID,ID,READ,test,t1, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t1',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_incl_users=\'odin, root, dva, tri\'',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,test,t2, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,table_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,column_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,index_stats, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t2 values (1), (2)',0 TIME,HOSTNAME,root,localhost,ID,ID,READ,test,t2, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t2',0 @@ -279,6 +285,9 @@ TIME,HOSTNAME,root,localhost,ID,0,CONNECT,test,,0 TIME,HOSTNAME,root,localhost,ID,ID,CREATE,test,t1, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create table t1 (id2 int)',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,test,t1, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,table_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,column_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,index_stats, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t1 values (1), (2)',0 TIME,HOSTNAME,root,localhost,ID,ID,READ,test,t1, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t1',0 @@ -291,6 +300,9 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,CREATE,sa_db,sa_t1, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table sa_t1(id int)',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,sa_db,sa_t1, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,table_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,column_stats, +TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,index_stats, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'insert into sa_t1 values (1), (2)',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,table_stats, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,column_stats, @@ -304,34 +316,34 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0 TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT ALL ON sa_db TO u2 IDENTIFIED BY *****',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1 = PASSWORD(*****)',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0 -TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,procs_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping, +TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table t1(id int)',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0 diff --git a/mysql-test/suite/plugins/suite.pm b/mysql-test/suite/plugins/suite.pm index a2ac3957af0..cb42fb66705 100644 --- a/mysql-test/suite/plugins/suite.pm +++ b/mysql-test/suite/plugins/suite.pm @@ -12,7 +12,7 @@ sub cassandra_running() { sub skip_combinations { my %skip; - $skip{'t/pam.test'} = 'No pam setup for mtr' + $skip{'t/pam_init.inc'} = 'No pam setup for mtr' unless -e '/etc/pam.d/mariadb_mtr'; $skip{'t/cassandra.test'} = 'Cassandra is not running' unless cassandra_running(); diff --git a/mysql-test/suite/plugins/t/audit_null_debug.test b/mysql-test/suite/plugins/t/audit_null_debug.test index 0534108b107..da949b15f8a 100644 --- a/mysql-test/suite/plugins/t/audit_null_debug.test +++ b/mysql-test/suite/plugins/t/audit_null_debug.test @@ -5,6 +5,8 @@ if (!$ADT_NULL_SO) { skip No NULL_AUDIT plugin; } +alter table mysql.plugin engine=myisam; + set @old_dbug=@@debug_dbug; call mtr.add_suppression("Index for table.*mysql.plugin.MYI"); call mtr.add_suppression("Index for table 'plugin' is corrupt; try to repair it"); @@ -30,4 +32,4 @@ SET debug_dbug=@old_dbug; uninstall plugin audit_null; delete from mysql.plugin where name='audit_null'; - +alter table mysql.plugin engine=aria; diff --git a/mysql-test/suite/plugins/t/auth_ed25519.test b/mysql-test/suite/plugins/t/auth_ed25519.test index 3e02bdf97d2..b8a7b996f65 100644 --- a/mysql-test/suite/plugins/t/auth_ed25519.test +++ b/mysql-test/suite/plugins/t/auth_ed25519.test @@ -28,6 +28,15 @@ query_vertical select * from information_schema.plugins where plugin_name='ed255 let $pwd=`select ed25519_password("secret")`; eval create user test1@localhost identified via ed25519 using '$pwd'; show grants for test1@localhost; +drop user test1@localhost; +create user test1@localhost identified via ed25519 using password('foo'); +show grants for test1@localhost; +select ed25519_password('foo'); +set password for test1@localhost = password('bar'); +show create user test1@localhost; +select ed25519_password('bar'); +eval set password for test1@localhost = '$pwd'; +show create user test1@localhost; replace_result $MASTER_MYPORT PORT $MASTER_MYSOCK SOCKET; error ER_ACCESS_DENIED_ERROR; diff --git a/mysql-test/suite/plugins/t/feedback_plugin_load.test b/mysql-test/suite/plugins/t/feedback_plugin_load.test index 8b4aee28362..cfaf68ce96d 100644 --- a/mysql-test/suite/plugins/t/feedback_plugin_load.test +++ b/mysql-test/suite/plugins/t/feedback_plugin_load.test @@ -28,11 +28,11 @@ select * from information_schema.feedback where variable_name like 'feed%' and variable_name not like '%debug%'; # Embedded server does not use the table mysqld.user and thus -# does not automatically use latin1_bin on startup. Use it manually. +# does not automatically use utf8mb4 on startup. Use it manually. --disable_query_log if (`SELECT VERSION() LIKE '%embedded%'`) { - DO _latin1'test' COLLATE latin1_bin; + create temporary table t1 (a json); } --enable_query_log SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK diff --git a/mysql-test/suite/plugins/t/pam.test b/mysql-test/suite/plugins/t/pam.test index 8a95d6baed2..6bb282f68c0 100644 --- a/mysql-test/suite/plugins/t/pam.test +++ b/mysql-test/suite/plugins/t/pam.test @@ -1,4 +1,4 @@ - +let $PAM_PLUGIN_VERSION= $AUTH_PAM_SO; --source pam_init.inc --write_file $MYSQLTEST_VARDIR/tmp/pam_good.txt @@ -13,6 +13,12 @@ not very secret challenge select user(), current_user(), database(); EOF +--write_file $MYSQLTEST_VARDIR/tmp/pam_ugly.txt +crash pam module +666 +select user(), current_user(), database(); +EOF + --echo # --echo # athentication is successful, challenge/pin are ok --echo # note that current_user() differs from user() @@ -25,6 +31,12 @@ EOF --error 1 --exec $MYSQL_TEST -u test_pam --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/pam_bad.txt +--echo # +--echo # athentication is unsuccessful +--echo # +--error 1 +--exec $MYSQL_TEST -u test_pam --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/pam_ugly.txt + --remove_file $MYSQLTEST_VARDIR/tmp/pam_good.txt --remove_file $MYSQLTEST_VARDIR/tmp/pam_bad.txt drop user test_pam; diff --git a/mysql-test/suite/plugins/t/pam_cleartext.test b/mysql-test/suite/plugins/t/pam_cleartext.test index 29ed7430649..5d137e6b416 100644 --- a/mysql-test/suite/plugins/t/pam_cleartext.test +++ b/mysql-test/suite/plugins/t/pam_cleartext.test @@ -1,4 +1,4 @@ - +let $PAM_PLUGIN_VERSION= $AUTH_PAM_SO; --source pam_init.inc show variables like 'pam_use_%'; diff --git a/mysql-test/suite/plugins/t/pam_init.inc b/mysql-test/suite/plugins/t/pam_init.inc index 281666d51a6..131b787f6b9 100644 --- a/mysql-test/suite/plugins/t/pam_init.inc +++ b/mysql-test/suite/plugins/t/pam_init.inc @@ -1,11 +1,11 @@ --source include/not_embedded.inc -if (!$AUTH_PAM_SO) { +if (!$PAM_PLUGIN_VERSION) { skip No pam auth plugin; } -eval install plugin pam soname '$AUTH_PAM_SO'; +eval install plugin pam soname '$PAM_PLUGIN_VERSION'; create user test_pam identified via pam using 'mariadb_mtr'; create user pam_test; grant proxy on pam_test to test_pam; diff --git a/mysql-test/suite/plugins/t/pam_v1.test b/mysql-test/suite/plugins/t/pam_v1.test new file mode 100644 index 00000000000..d908e3a4b25 --- /dev/null +++ b/mysql-test/suite/plugins/t/pam_v1.test @@ -0,0 +1,34 @@ +let $PAM_PLUGIN_VERSION= $AUTH_PAM_V1_SO; +--source pam_init.inc + +--write_file $MYSQLTEST_VARDIR/tmp/pam_good.txt +not very secret challenge +9225 +select user(), current_user(), database(); +EOF + +--write_file $MYSQLTEST_VARDIR/tmp/pam_bad.txt +not very secret challenge +9224 +select user(), current_user(), database(); +EOF + +--echo # +--echo # athentication is successful, challenge/pin are ok +--echo # note that current_user() differs from user() +--echo # +--exec $MYSQL_TEST -u test_pam --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/pam_good.txt + +--echo # +--echo # athentication is unsuccessful +--echo # +--error 1 +--exec $MYSQL_TEST -u test_pam --plugin-dir=$plugindir < $MYSQLTEST_VARDIR/tmp/pam_bad.txt + +--remove_file $MYSQLTEST_VARDIR/tmp/pam_good.txt +--remove_file $MYSQLTEST_VARDIR/tmp/pam_bad.txt +drop user test_pam; +drop user pam_test; +let $count_sessions= 1; +--source include/wait_until_count_sessions.inc +uninstall plugin pam; diff --git a/mysql-test/suite/plugins/t/simple_password_check.test b/mysql-test/suite/plugins/t/simple_password_check.test index 4965ee492d2..b7d631ab4bb 100644 --- a/mysql-test/suite/plugins/t/simple_password_check.test +++ b/mysql-test/suite/plugins/t/simple_password_check.test @@ -83,11 +83,13 @@ create user foo2 identified with mysql_native_password using '111111111111111111 grant select on *.* to foo2 identified with mysql_old_password using '2222222222222222'; --error ER_NOT_VALID_PASSWORD create user foo2 identified with mysql_native_password using ''; ---error ER_PASSWORD_NO_MATCH +--error ER_NOT_VALID_PASSWORD +grant select on *.* to foo2 identified with mysql_old_password using ''; +--error ER_NOT_VALID_PASSWORD grant select on *.* to foo2 identified with mysql_old_password; # direct updates are not protected -update mysql.user set password='xxx' where user='foo1'; +update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'xxx') where user='foo1'; set global strict_password_validation=0; @@ -113,6 +115,8 @@ drop user foo1; create role r1; drop role r1; +flush privileges; + uninstall plugin simple_password_check; create user foo1 identified by 'pwd'; diff --git a/mysql-test/suite/roles/create_and_drop_role.result b/mysql-test/suite/roles/create_and_drop_role.result index a163ee82f42..21aecdb9bc0 100644 --- a/mysql-test/suite/roles/create_and_drop_role.result +++ b/mysql-test/suite/roles/create_and_drop_role.result @@ -7,7 +7,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp create role test_role1; create role test_role2, test_role3; select user, host, is_role from user where user like 'test%'; -user host is_role +User Host is_role test_role1 Y test_role2 Y test_role3 Y @@ -19,7 +19,7 @@ ERROR HY000: Operation CREATE ROLE failed for 'test_role1' create role test_role1, test_role2; ERROR HY000: Operation CREATE ROLE failed for 'test_role1' select user, host, is_role from user where user like 'test%'; -user host is_role +User Host is_role test_role1 Y test_role2 Y drop role test_role1; @@ -34,7 +34,7 @@ drop role dummy; ERROR HY000: Operation DROP ROLE failed for 'dummy' drop user dummy@''; select user, host, is_role from user where user like 'test%'; -user host is_role +User Host is_role disconnect mysql; connection default; create role ''; diff --git a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result index afe00ed7729..5902ae0e16c 100644 --- a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result +++ b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result @@ -15,7 +15,6 @@ create role test_role; create user test_user@localhost; grant test_role to test_user@localhost; set default role test_role for root@localhost; -ERROR HY000: Column count of mysql.user is wrong. Expected 46, found 45. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error drop role test_role; drop user test_user@localhost; alter table user add column default_role char(80) binary default '' not null diff --git a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test index ebd75c34ca1..9cf0d7b4aff 100644 --- a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test +++ b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test @@ -3,6 +3,7 @@ # that don't have 'default_role' column # source include/not_embedded.inc; +source include/switch_to_mysql_user.inc; connect (mysql, localhost, root,,); use mysql; @@ -29,8 +30,8 @@ after password_expired; create role test_role; create user test_user@localhost; grant test_role to test_user@localhost; ---replace_regex /10\d\d\d\d/MYSQL_VERSION_ID/ ---error ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE +#--replace_regex /10\d\d\d\d/MYSQL_VERSION_ID/ +#--error ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE set default role test_role for root@localhost; drop role test_role; drop user test_user@localhost; @@ -46,3 +47,5 @@ update user set is_role='N'; flush privileges; create role test_role; drop role test_role; + +source include/switch_to_mysql_global_priv.inc; diff --git a/mysql-test/suite/roles/default_create_user_not_role.result b/mysql-test/suite/roles/default_create_user_not_role.result index 171015f6e82..3f32329b80c 100644 --- a/mysql-test/suite/roles/default_create_user_not_role.result +++ b/mysql-test/suite/roles/default_create_user_not_role.result @@ -2,7 +2,7 @@ connect mysql, localhost, root,,; use mysql; create user 'test'@'localhost'; select user, host, is_role from user where user='test' and host='localhost'; -user host is_role +User Host is_role test localhost N drop user 'test'@'localhost'; disconnect mysql; diff --git a/mysql-test/suite/roles/flush_roles-17898.result b/mysql-test/suite/roles/flush_roles-17898.result index dbe6ea24afd..c142a496c10 100644 --- a/mysql-test/suite/roles/flush_roles-17898.result +++ b/mysql-test/suite/roles/flush_roles-17898.result @@ -1,12 +1,8 @@ use mysql; insert db (db,user,select_priv) values ('foo','dwr_foo','Y'), ('bar','dwr_bar','Y'); insert roles_mapping (user,role) values ('dwr_qux_dev','dwr_foo'),('dwr_qux_dev','dwr_bar'); -insert ignore user (user,show_db_priv,is_role) values ('dwr_foo','N','Y'), ('dwr_bar','N','Y'), ('dwr_qux_dev','Y','Y'); -Warnings: -Warning 1364 Field 'ssl_cipher' doesn't have a default value -Warning 1364 Field 'x509_issuer' doesn't have a default value -Warning 1364 Field 'x509_subject' doesn't have a default value -Warning 1364 Field 'authentication_string' doesn't have a default value +insert global_priv values ('','dwr_foo','{"is_role":true}'), ('','dwr_bar','{"is_role":true}'), +('','dwr_qux_dev','{"access":16384,"is_role":true}'); flush privileges; drop role dwr_foo; drop role dwr_bar; diff --git a/mysql-test/suite/roles/flush_roles-17898.test b/mysql-test/suite/roles/flush_roles-17898.test index 6a3b8d6f345..55611d31e7b 100644 --- a/mysql-test/suite/roles/flush_roles-17898.test +++ b/mysql-test/suite/roles/flush_roles-17898.test @@ -4,7 +4,8 @@ use mysql; insert db (db,user,select_priv) values ('foo','dwr_foo','Y'), ('bar','dwr_bar','Y'); insert roles_mapping (user,role) values ('dwr_qux_dev','dwr_foo'),('dwr_qux_dev','dwr_bar'); -insert ignore user (user,show_db_priv,is_role) values ('dwr_foo','N','Y'), ('dwr_bar','N','Y'), ('dwr_qux_dev','Y','Y'); +insert global_priv values ('','dwr_foo','{"is_role":true}'), ('','dwr_bar','{"is_role":true}'), + ('','dwr_qux_dev','{"access":16384,"is_role":true}'); flush privileges; drop role dwr_foo; drop role dwr_bar; diff --git a/mysql-test/suite/roles/grant_revoke_current.result b/mysql-test/suite/roles/grant_revoke_current.result index 436bec92a8f..681c0857edb 100644 --- a/mysql-test/suite/roles/grant_revoke_current.result +++ b/mysql-test/suite/roles/grant_revoke_current.result @@ -1,3 +1,4 @@ +select priv into @root_priv from mysql.global_priv where user='root' and host='localhost'; grant select on *.* to current_role; ERROR 0L000: Invalid definer revoke select on *.* from current_role; @@ -39,5 +40,5 @@ GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*34391 GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION GRANT USAGE ON *.* TO 'r1' set password=''; -update mysql.user set plugin=''; drop role r1; +update mysql.global_priv set priv=@root_priv; diff --git a/mysql-test/suite/roles/grant_revoke_current.test b/mysql-test/suite/roles/grant_revoke_current.test index bffc04087b1..65a0809ac9c 100644 --- a/mysql-test/suite/roles/grant_revoke_current.test +++ b/mysql-test/suite/roles/grant_revoke_current.test @@ -1,4 +1,5 @@ --source include/not_embedded.inc +select priv into @root_priv from mysql.global_priv where user='root' and host='localhost'; --error ER_MALFORMED_DEFINER grant select on *.* to current_role; @@ -25,7 +26,7 @@ show grants; grant r1 to current_user() identified by 'barfoo'; show grants; set password=''; -#cleanup after MDEV-16238 -update mysql.user set plugin=''; +#cleanup drop role r1; +update mysql.global_priv set priv=@root_priv; diff --git a/mysql-test/suite/roles/grant_role_auto_create_user.result b/mysql-test/suite/roles/grant_role_auto_create_user.result index 3f6139e84d0..61ce0359c0d 100644 --- a/mysql-test/suite/roles/grant_role_auto_create_user.result +++ b/mysql-test/suite/roles/grant_role_auto_create_user.result @@ -23,7 +23,7 @@ grant auto_create to foo@localhost; ERROR 28000: Can't find any matching row in the user table grant auto_create to bar@localhost identified by 'baz'; select user, host from mysql.user where user = 'bar'; -user host +User Host bar localhost set sql_mode = ''; connect con1,localhost,bar,baz,; diff --git a/mysql-test/suite/roles/i_s_applicable_roles_is_default.result b/mysql-test/suite/roles/i_s_applicable_roles_is_default.result index 63127f8b176..32498d11390 100644 --- a/mysql-test/suite/roles/i_s_applicable_roles_is_default.result +++ b/mysql-test/suite/roles/i_s_applicable_roles_is_default.result @@ -78,3 +78,4 @@ drop role role3; drop role role2; drop role role1; drop user foo; +update mysql.global_priv set priv=json_remove(priv, '$.default_role'); diff --git a/mysql-test/suite/roles/i_s_applicable_roles_is_default.test b/mysql-test/suite/roles/i_s_applicable_roles_is_default.test index 59ba1f8bf75..b6f6f9ba879 100644 --- a/mysql-test/suite/roles/i_s_applicable_roles_is_default.test +++ b/mysql-test/suite/roles/i_s_applicable_roles_is_default.test @@ -51,7 +51,6 @@ set default role role3; --sorted_result select * from information_schema.applicable_roles; - set default role none; --sorted_result select * from information_schema.applicable_roles; @@ -60,3 +59,4 @@ drop role role3; drop role role2; drop role role1; drop user foo; +update mysql.global_priv set priv=json_remove(priv, '$.default_role'); diff --git a/mysql-test/suite/roles/none_public.result b/mysql-test/suite/roles/none_public.result index 5dd1480e8c3..c253ae1478b 100644 --- a/mysql-test/suite/roles/none_public.result +++ b/mysql-test/suite/roles/none_public.result @@ -40,17 +40,9 @@ ERROR OP000: Invalid role specification `none` create definer=public view test.v1 as select 1; ERROR OP000: Invalid role specification `public` drop role role1; -optimize table mysql.user; -Table Op Msg_type Msg_text -mysql.user optimize status OK -insert ignore mysql.user (user, is_role) values ('none', 'Y'), ('public', 'Y'); -Warnings: -Warning 1364 Field 'ssl_cipher' doesn't have a default value -Warning 1364 Field 'x509_issuer' doesn't have a default value -Warning 1364 Field 'x509_subject' doesn't have a default value -Warning 1364 Field 'authentication_string' doesn't have a default value +insert mysql.global_priv values ('', 'none', '{"is_role":true}'), ('', 'public', '{"is_role":true}'); flush privileges; Warnings: Error 1959 Invalid role specification `none` Error 1959 Invalid role specification `public` -delete from mysql.user where is_role='Y'; +delete from mysql.global_priv where host=''; diff --git a/mysql-test/suite/roles/none_public.test b/mysql-test/suite/roles/none_public.test index 838a4955df5..a0ec2315cfc 100644 --- a/mysql-test/suite/roles/none_public.test +++ b/mysql-test/suite/roles/none_public.test @@ -50,8 +50,6 @@ create definer=public view test.v1 as select 1; drop role role1; -optimize table mysql.user; # to remove deleted rows and have stable row order -insert ignore mysql.user (user, is_role) values ('none', 'Y'), ('public', 'Y'); +insert mysql.global_priv values ('', 'none', '{"is_role":true}'), ('', 'public', '{"is_role":true}'); flush privileges; -delete from mysql.user where is_role='Y'; - +delete from mysql.global_priv where host=''; diff --git a/mysql-test/suite/roles/prepare_stmt_with_role.result b/mysql-test/suite/roles/prepare_stmt_with_role.result index 0352502c35c..758dca735e1 100644 --- a/mysql-test/suite/roles/prepare_stmt_with_role.result +++ b/mysql-test/suite/roles/prepare_stmt_with_role.result @@ -13,7 +13,7 @@ EXECUTE stmtCreateRole; # SELECT user, host,is_role FROM mysql.user WHERE user = 'developers'; -user host is_role +User Host is_role developers Y SHOW GRANTS; Grants for root@localhost @@ -73,7 +73,7 @@ EXECUTE stmtDropRole; # SELECT user, host,is_role FROM mysql.user WHERE user = 'developers'; -user host is_role +User Host is_role SELECT * FROM mysql.roles_mapping; Host User Role Admin_option SHOW GRANTS; @@ -89,7 +89,7 @@ GRANT USAGE ON *.* TO 'test_user'@'%' EXECUTE stmtCreateRole; SELECT user, host,is_role FROM mysql.user WHERE user = 'developers'; -user host is_role +User Host is_role developers Y SELECT * FROM mysql.roles_mapping; Host User Role Admin_option diff --git a/mysql-test/suite/roles/rename_user.result b/mysql-test/suite/roles/rename_user.result index 987d90a5820..9550e15953a 100644 --- a/mysql-test/suite/roles/rename_user.result +++ b/mysql-test/suite/roles/rename_user.result @@ -12,7 +12,7 @@ localhost root test_role2 Y localhost test_user test_role1 N rename user 'test_user'@'localhost' to 'test_user_rm'@'newhost'; select user, host from user where user like 'test%'; -user host +User Host test_role1 test_role2 test_user_rm newhost diff --git a/mysql-test/suite/roles/role_case_sensitive-10744.result b/mysql-test/suite/roles/role_case_sensitive-10744.result index b898310e83c..baec3c5f2a1 100644 --- a/mysql-test/suite/roles/role_case_sensitive-10744.result +++ b/mysql-test/suite/roles/role_case_sensitive-10744.result @@ -11,7 +11,7 @@ create role test_role; # Test if mysql.user has the roles created. # select user, host from mysql.user where is_role='y' and user like 'test%'; -user host +User Host test_ROLE test_role create database secret_db; diff --git a/mysql-test/suite/roles/set_default_role_clear.result b/mysql-test/suite/roles/set_default_role_clear.result index 7f54b5eabcc..70628059f65 100644 --- a/mysql-test/suite/roles/set_default_role_clear.result +++ b/mysql-test/suite/roles/set_default_role_clear.result @@ -10,7 +10,7 @@ set default role test_role; select user, host, default_role from mysql.user; ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user' select user, host, default_role from mysql.user where user='test_user'; -user host default_role +User Host default_role test_user localhost test_role show grants; Grants for test_user@localhost @@ -18,16 +18,16 @@ GRANT test_role TO 'test_user'@'localhost' GRANT USAGE ON *.* TO 'test_user'@'localhost' GRANT SELECT ON *.* TO 'test_role' select user, host, default_role from mysql.user where user='test_user'; -user host default_role +User Host default_role test_user localhost test_role set default role NONE; select user, host, default_role from mysql.user where user='test_user'; -user host default_role +User Host default_role test_user localhost set default role invalid_role; ERROR OP000: Invalid role specification `invalid_role` select user, host, default_role from mysql.user where user='test_user'; -user host default_role +User Host default_role test_user localhost select user, host, default_role from mysql.user; ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user' diff --git a/mysql-test/suite/roles/set_default_role_for.result b/mysql-test/suite/roles/set_default_role_for.result index 9880671ba09..706ba3fba7b 100644 --- a/mysql-test/suite/roles/set_default_role_for.result +++ b/mysql-test/suite/roles/set_default_role_for.result @@ -22,17 +22,17 @@ GRANT role_a TO 'user_a'@'localhost' GRANT USAGE ON *.* TO 'user_a'@'localhost' GRANT SELECT ON *.* TO 'role_a' select user, host, default_role from mysql.user where user like 'user_%'; -user host default_role +User Host default_role user_a localhost role_a user_b localhost role_b set default role NONE for current_user; select user, host, default_role from mysql.user where user like 'user_%'; -user host default_role +User Host default_role user_a localhost user_b localhost role_b set default role current_role for current_user; select user, host, default_role from mysql.user where user like 'user_%'; -user host default_role +User Host default_role user_a localhost role_a user_b localhost role_b set default role role_b for current_user; @@ -44,12 +44,6 @@ GRANT USAGE ON *.* TO 'user_b'@'localhost' GRANT INSERT, UPDATE ON *.* TO 'role_b' select user, host, default_role from mysql.user where user like 'user_%'; ERROR 42000: SELECT command denied to user 'user_b'@'localhost' for table 'user' -insert ignore into mysql.user (user, host) values ('someuser', 'somehost'); -Warnings: -Warning 1364 Field 'ssl_cipher' doesn't have a default value -Warning 1364 Field 'x509_issuer' doesn't have a default value -Warning 1364 Field 'x509_subject' doesn't have a default value -Warning 1364 Field 'authentication_string' doesn't have a default value set default role NONE for user_a@localhost; show grants; Grants for user_a@localhost @@ -60,6 +54,5 @@ select user, host, default_role from mysql.user where user like 'user_%'; ERROR 42000: SELECT command denied to user 'user_a'@'localhost' for table 'user' drop role role_a; drop role role_b; -delete from mysql.user where user = 'someuser' && host = 'somehost'; drop user user_a@localhost; drop user user_b@localhost; diff --git a/mysql-test/suite/roles/set_default_role_for.test b/mysql-test/suite/roles/set_default_role_for.test index 985eaa16e3d..eff999a522b 100644 --- a/mysql-test/suite/roles/set_default_role_for.test +++ b/mysql-test/suite/roles/set_default_role_for.test @@ -65,8 +65,6 @@ show grants; --error ER_TABLEACCESS_DENIED_ERROR select user, host, default_role from mysql.user where user like 'user_%'; -# Make sure the default role setting worked from root. -insert ignore into mysql.user (user, host) values ('someuser', 'somehost'); # Since we have update privileges on the mysql.user table, we should # be able to set a default role for a different user. set default role NONE for user_a@localhost; @@ -82,6 +80,5 @@ change_user 'root'; drop role role_a; drop role role_b; -delete from mysql.user where user = 'someuser' && host = 'somehost'; drop user user_a@localhost; drop user user_b@localhost; diff --git a/mysql-test/suite/roles/set_default_role_invalid.result b/mysql-test/suite/roles/set_default_role_invalid.result index 5bcaa9acb86..77c317c6a02 100644 --- a/mysql-test/suite/roles/set_default_role_invalid.result +++ b/mysql-test/suite/roles/set_default_role_invalid.result @@ -17,7 +17,7 @@ set default role test_role; select user, host, default_role from mysql.user; ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'user' select user, host, default_role from mysql.user where user='test_user'; -user host default_role +User Host default_role test_user localhost test_role show grants; Grants for test_user@localhost @@ -25,12 +25,12 @@ GRANT test_role TO 'test_user'@'localhost' GRANT USAGE ON *.* TO 'test_user'@'localhost' GRANT SELECT ON *.* TO 'test_role' select user, host, default_role from mysql.user where user='test_user'; -user host default_role +User Host default_role test_user localhost test_role set default role invalid_role; ERROR OP000: Invalid role specification `invalid_role` select user, host, default_role from mysql.user where user='test_user'; -user host default_role +User Host default_role test_user localhost test_role revoke test_role from test_user@localhost; select user, host, default_role from mysql.user where user='test_user'; diff --git a/mysql-test/suite/roles/set_default_role_new_connection.result b/mysql-test/suite/roles/set_default_role_new_connection.result index a59ecbd75f7..8590d33e16d 100644 --- a/mysql-test/suite/roles/set_default_role_new_connection.result +++ b/mysql-test/suite/roles/set_default_role_new_connection.result @@ -15,7 +15,7 @@ ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'us disconnect c1; connection default; select user, host, default_role from mysql.user where user = 'test_user'; -user host default_role +User Host default_role test_user localhost test_role connect c1, localhost, test_user,,; show grants; @@ -24,13 +24,13 @@ GRANT test_role TO 'test_user'@'localhost' GRANT USAGE ON *.* TO 'test_user'@'localhost' GRANT SELECT ON *.* TO 'test_role' select user, host, default_role from mysql.user where user = 'test_user'; -user host default_role +User Host default_role test_user localhost test_role set default role NONE; disconnect c1; connection default; select user, host, default_role from mysql.user where user = 'test_user'; -user host default_role +User Host default_role test_user localhost connect c1, localhost, test_user,,; show grants; @@ -42,7 +42,7 @@ ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'us disconnect c1; connection default; select user, host, default_role from mysql.user where user = 'test_user'; -user host default_role +User Host default_role test_user localhost set default role test_role for test_user@localhost; connect c1, localhost, test_user,,; @@ -52,7 +52,7 @@ GRANT test_role TO 'test_user'@'localhost' GRANT USAGE ON *.* TO 'test_user'@'localhost' GRANT SELECT ON *.* TO 'test_role' select user, host, default_role from mysql.user where user = 'test_user'; -user host default_role +User Host default_role test_user localhost test_role disconnect c1; connection default; diff --git a/mysql-test/suite/roles/set_default_role_ps-6960.result b/mysql-test/suite/roles/set_default_role_ps-6960.result index c186e7bccb0..505861e89df 100644 --- a/mysql-test/suite/roles/set_default_role_ps-6960.result +++ b/mysql-test/suite/roles/set_default_role_ps-6960.result @@ -1,3 +1,4 @@ +select priv into @root_priv from mysql.global_priv where user='root' and host='localhost'; create role r1; prepare stmt from "set password = '11111111111111111111111111111111111111111'"; execute stmt; @@ -6,4 +7,4 @@ execute stmt; set password = ''; set default role NONE; drop role r1; -update mysql.user set plugin=''; +update mysql.global_priv set priv=@root_priv where user='root' and host='localhost'; diff --git a/mysql-test/suite/roles/set_default_role_ps-6960.test b/mysql-test/suite/roles/set_default_role_ps-6960.test index 8af95c9e8a0..fd965c2aa75 100644 --- a/mysql-test/suite/roles/set_default_role_ps-6960.test +++ b/mysql-test/suite/roles/set_default_role_ps-6960.test @@ -4,6 +4,8 @@ --source include/not_embedded.inc +select priv into @root_priv from mysql.global_priv where user='root' and host='localhost'; + create role r1; prepare stmt from "set password = '11111111111111111111111111111111111111111'"; execute stmt; @@ -13,5 +15,6 @@ execute stmt; set password = ''; set default role NONE; drop role r1; -#cleanup after MDEV-16238 -update mysql.user set plugin=''; + +#cleanup +update mysql.global_priv set priv=@root_priv where user='root' and host='localhost'; diff --git a/mysql-test/suite/roles/set_role-database-recursive.result b/mysql-test/suite/roles/set_role-database-recursive.result index 479e553c3d1..2c8c21d97c3 100644 --- a/mysql-test/suite/roles/set_role-database-recursive.result +++ b/mysql-test/suite/roles/set_role-database-recursive.result @@ -5,7 +5,7 @@ grant test_role1 to test_user@localhost; grant test_role2 to test_user@localhost; grant test_role2 to test_role1; select user, host from mysql.user where user not like 'root'; -user host +User Host test_role1 test_role2 test_user localhost diff --git a/mysql-test/suite/roles/set_role-database-simple.result b/mysql-test/suite/roles/set_role-database-simple.result index e21a55edf2e..156a4453b69 100644 --- a/mysql-test/suite/roles/set_role-database-simple.result +++ b/mysql-test/suite/roles/set_role-database-simple.result @@ -2,7 +2,7 @@ create user 'test_user'@'localhost'; create role test_role1; grant test_role1 to test_user@localhost; select user, host from mysql.user where user not like 'root'; -user host +User Host test_role1 test_user localhost select * from mysql.roles_mapping; diff --git a/mysql-test/suite/roles/set_role-recursive.result b/mysql-test/suite/roles/set_role-recursive.result index 2b34c3eeebe..0b37b1a3fc8 100644 --- a/mysql-test/suite/roles/set_role-recursive.result +++ b/mysql-test/suite/roles/set_role-recursive.result @@ -4,7 +4,7 @@ grant test_role1 to test_user@localhost; create role test_role2; grant test_role2 to test_role1; select user, host from mysql.user where user not like 'root'; -user host +User Host test_role1 test_role2 test_user localhost diff --git a/mysql-test/suite/roles/set_role-routine-simple.result b/mysql-test/suite/roles/set_role-routine-simple.result index 3e17a78ad77..b86bf3045f3 100644 --- a/mysql-test/suite/roles/set_role-routine-simple.result +++ b/mysql-test/suite/roles/set_role-routine-simple.result @@ -6,7 +6,7 @@ grant test_role1 to test_user@localhost; grant test_role3 to test_user@localhost; grant test_role2 to test_role1; select user, host from mysql.user where user not like 'root'; -user host +User Host test_role1 test_role2 test_role3 diff --git a/mysql-test/suite/roles/set_role-simple.result b/mysql-test/suite/roles/set_role-simple.result index 9af698c7b09..dec5a0b4436 100644 --- a/mysql-test/suite/roles/set_role-simple.result +++ b/mysql-test/suite/roles/set_role-simple.result @@ -2,7 +2,7 @@ create user test_user@localhost; create role test_role1; grant test_role1 to test_user@localhost; select user, host from mysql.user where user not like 'root'; -user host +User Host test_role1 test_user localhost select * from mysql.roles_mapping; diff --git a/mysql-test/suite/roles/set_role-table-column-priv.result b/mysql-test/suite/roles/set_role-table-column-priv.result index 721bd3039a3..57c6ce01c9f 100644 --- a/mysql-test/suite/roles/set_role-table-column-priv.result +++ b/mysql-test/suite/roles/set_role-table-column-priv.result @@ -4,7 +4,7 @@ create role test_role2; grant test_role1 to test_user@localhost; grant test_role2 to test_role1; select user, host from mysql.user where user not like 'root'; -user host +User Host test_role1 test_role2 test_user localhost diff --git a/mysql-test/suite/roles/set_role-table-simple.result b/mysql-test/suite/roles/set_role-table-simple.result index f5688dbe62e..3ecc66ba7f0 100644 --- a/mysql-test/suite/roles/set_role-table-simple.result +++ b/mysql-test/suite/roles/set_role-table-simple.result @@ -4,7 +4,7 @@ create role test_role2; grant test_role1 to test_user@localhost; grant test_role2 to test_role1; select user, host from mysql.user where user not like 'root'; -user host +User Host test_role1 test_role2 test_user localhost diff --git a/mysql-test/suite/roles/show_grants.result b/mysql-test/suite/roles/show_grants.result index 5d46b038cf8..31df0113b8e 100644 --- a/mysql-test/suite/roles/show_grants.result +++ b/mysql-test/suite/roles/show_grants.result @@ -5,7 +5,7 @@ grant test_role1 to test_user@localhost; grant test_role2 to test_user@localhost; grant test_role2 to test_role1; select user, host from mysql.user where user not like 'root'; -user host +User Host test_role1 test_role2 test_user localhost diff --git a/mysql-test/suite/roles/show_grants_replicated.result b/mysql-test/suite/roles/show_grants_replicated.result index cb9df65dbbd..7b090c982f0 100644 --- a/mysql-test/suite/roles/show_grants_replicated.result +++ b/mysql-test/suite/roles/show_grants_replicated.result @@ -17,7 +17,7 @@ connection slave; # it's visible in mysql.user and I_S: # select user, host, is_role from mysql.user where user in ('u1', 'r1'); -user host is_role +User Host is_role r1 Y u1 % N select * from information_schema.applicable_roles; diff --git a/mysql-test/suite/rpl/disabled.def b/mysql-test/suite/rpl/disabled.def index d4617398c64..9f43bc3c339 100644 --- a/mysql-test/suite/rpl/disabled.def +++ b/mysql-test/suite/rpl/disabled.def @@ -19,3 +19,4 @@ rpl_row_mysqlbinlog : MDEV-11095 rpl_row_index_choice : MDEV-11666 rpl_parallel2 : fails after MDEV-16172 rpl_semi_sync_after_sync : fails after MDEV-16172 +rpl_auto_increment_update_failure : disabled for now diff --git a/mysql-test/suite/rpl/include/rpl_EE_err.test b/mysql-test/suite/rpl/include/rpl_EE_err.test index 0b3fec1f605..fa135d12436 100644 --- a/mysql-test/suite/rpl/include/rpl_EE_err.test +++ b/mysql-test/suite/rpl/include/rpl_EE_err.test @@ -15,7 +15,7 @@ -- source include/master-slave.inc eval create table t1 (a int) engine=$engine_type; -flush tables; +flush tables t1; let $MYSQLD_DATADIR= `select @@datadir`; remove_file $MYSQLD_DATADIR/test/t1.MYI ; drop table if exists t1; diff --git a/mysql-test/suite/rpl/include/rpl_mixed_dml.inc b/mysql-test/suite/rpl/include/rpl_mixed_dml.inc index 114cd53d244..bb1a2c173de 100644 --- a/mysql-test/suite/rpl/include/rpl_mixed_dml.inc +++ b/mysql-test/suite/rpl/include/rpl_mixed_dml.inc @@ -289,7 +289,6 @@ DROP TRIGGER tr1; --echo --echo --echo ******************** EVENTS ******************** -GRANT EVENT ON *.* TO 'root'@'localhost'; INSERT INTO t1 VALUES(1, 'test1'); CREATE EVENT e1 ON SCHEDULE EVERY '1' SECOND COMMENT 'e_second_comment' DO DELETE FROM t1; --source suite/rpl/include/rpl_mixed_check_event.inc diff --git a/mysql-test/suite/rpl/include/rpl_row_001.test b/mysql-test/suite/rpl/include/rpl_row_001.test deleted file mode 100644 index 4df2d793244..00000000000 --- a/mysql-test/suite/rpl/include/rpl_row_001.test +++ /dev/null @@ -1,96 +0,0 @@ -let $LOAD_FILE= $MYSQLTEST_VARDIR/std_data/words.dat; -CREATE TABLE t1 (word CHAR(20) NOT NULL); ---replace_result $LOAD_FILE LOAD_FILE -eval LOAD DATA INFILE '$LOAD_FILE' INTO TABLE t1; ---replace_result $LOAD_FILE LOAD_FILE -eval LOAD DATA INFILE '$LOAD_FILE' INTO TABLE t1; -SELECT * FROM t1 ORDER BY word LIMIT 10; - -# -# Save password row for root -# - -create temporary table tmp select * from mysql.user where host="localhost" and user="root"; - -# -# Test slave with wrong password -# - -save_master_pos; -connection slave; -sync_with_master; -STOP SLAVE; -connection master; -UPDATE mysql.user SET password=password('foo') WHERE host='localhost' AND user='root'; -connection slave; -START SLAVE; -connection master; -# -# Give slave time to do at last one failed connect retry -# This one must be short so that the slave will not stop retrying -real_sleep 2; -UPDATE mysql.user SET password=password('') WHERE host='localhost' AND user='root'; -# Give slave time to connect (will retry every second) - -sleep 2; - -CREATE TABLE t3(n INT); -INSERT INTO t3 VALUES(1),(2); -sync_slave_with_master; -SELECT * FROM t3 ORDER BY n; -SELECT SUM(LENGTH(word)) FROM t1; -connection master; -DROP TABLE t1,t3; -save_master_pos; -connection slave; -sync_with_master; - -# Test if the slave SQL thread can be more than 16K behind the slave -# I/O thread (> IO_SIZE) - -connection master; -# we'll use table-level locking to delay slave SQL thread -eval CREATE TABLE t1 (n INT) ENGINE=$engine_type; -sync_slave_with_master; -connection master; -RESET MASTER; -connection slave; -STOP SLAVE; -RESET SLAVE; - -connection master; -let $1=5000; -# Generate 16K of relay log -disable_query_log; -while ($1) -{ - eval INSERT INTO t1 VALUES($1); - dec $1; -} -enable_query_log; -SELECT COUNT(*) FROM t1; -save_master_pos; - -# Try to cause a large relay log lag on the slave by locking t1 -connection slave; -LOCK TABLES t1 READ; -START SLAVE; -UNLOCK TABLES; -sync_with_master; -SELECT COUNT(*) FROM t1; - -connection master; -DROP TABLE t1; -CREATE TABLE t1 (n INT); -INSERT INTO t1 VALUES(3456); -sync_slave_with_master; -SELECT n FROM t1; - -connection master; -DROP TABLE t1; - -# resttore old passwords -replace into mysql.user select * from tmp; -drop temporary table tmp; - -sync_slave_with_master; diff --git a/mysql-test/suite/rpl/include/rpl_row_annotate.test b/mysql-test/suite/rpl/include/rpl_row_annotate.test index 317a9c86539..8b4b704cef9 100644 --- a/mysql-test/suite/rpl/include/rpl_row_annotate.test +++ b/mysql-test/suite/rpl/include/rpl_row_annotate.test @@ -147,7 +147,7 @@ let $start_pos= `select @binlog_start_pos`; connection master; SET SESSION binlog_annotate_row_events = ON; INSERT DELAYED INTO test1.t4 VALUES (1,1); -FLUSH TABLES; +FLUSH TABLES test1.t4; SELECT * FROM test1.t4 ORDER BY a; sync_slave_with_master; diff --git a/mysql-test/suite/rpl/include/rpl_row_delayed_ins.test b/mysql-test/suite/rpl/include/rpl_row_delayed_ins.test index bad308ff814..03c7b5282a8 100644 --- a/mysql-test/suite/rpl/include/rpl_row_delayed_ins.test +++ b/mysql-test/suite/rpl/include/rpl_row_delayed_ins.test @@ -10,7 +10,7 @@ eval create table t1(a int not null primary key) engine=$engine_type; insert delayed into t1 values (1); insert delayed into t1 values (2); insert delayed into t1 values (3); -flush tables; +flush tables t1; SELECT * FROM t1 ORDER BY a; sync_slave_with_master; diff --git a/mysql-test/suite/rpl/r/rpl_EE_err.result b/mysql-test/suite/rpl/r/rpl_EE_err.result index 1f605935005..0b0ee84229f 100644 --- a/mysql-test/suite/rpl/r/rpl_EE_err.result +++ b/mysql-test/suite/rpl/r/rpl_EE_err.result @@ -1,7 +1,7 @@ include/master-slave.inc [connection master] create table t1 (a int) engine=myisam; -flush tables; +flush tables t1; drop table if exists t1; Warnings: Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory") diff --git a/mysql-test/suite/rpl/r/rpl_create_drop_user.result b/mysql-test/suite/rpl/r/rpl_create_drop_user.result index f8cc271e8cf..61b351b50df 100644 --- a/mysql-test/suite/rpl/r/rpl_create_drop_user.result +++ b/mysql-test/suite/rpl/r/rpl_create_drop_user.result @@ -17,15 +17,15 @@ CURRENT_USER u2@localhost disconnect user_a; connection master; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; -user password -u1 *D9553C4CE316A9845CE49E30A2D7E3857AF966C4 -u2 +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; +User Password plugin authentication_string +u1 *D9553C4CE316A9845CE49E30A2D7E3857AF966C4 mysql_native_password *D9553C4CE316A9845CE49E30A2D7E3857AF966C4 +u2 mysql_native_password connection slave; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; -user password -u1 *D9553C4CE316A9845CE49E30A2D7E3857AF966C4 -u2 +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; +User Password plugin authentication_string +u1 *D9553C4CE316A9845CE49E30A2D7E3857AF966C4 mysql_native_password *D9553C4CE316A9845CE49E30A2D7E3857AF966C4 +u2 mysql_native_password connection master; CREATE OR REPLACE USER u1@localhost IDENTIFIED BY 'abcdefghijk2'; connect user_a, localhost, u1,'abcdefghijk2',; @@ -35,25 +35,25 @@ CURRENT_USER u1@localhost disconnect user_a; connection master; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; -user password -u1 *A9A5EF53CE2EFAA6F4A746D63A917B2370971A7E -u2 +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; +User Password plugin authentication_string +u1 *A9A5EF53CE2EFAA6F4A746D63A917B2370971A7E mysql_native_password *A9A5EF53CE2EFAA6F4A746D63A917B2370971A7E +u2 mysql_native_password connection slave; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; -user password -u1 *A9A5EF53CE2EFAA6F4A746D63A917B2370971A7E -u2 +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; +User Password plugin authentication_string +u1 *A9A5EF53CE2EFAA6F4A746D63A917B2370971A7E mysql_native_password *A9A5EF53CE2EFAA6F4A746D63A917B2370971A7E +u2 mysql_native_password connection master; CREATE USER u1@localhost; ERROR HY000: Operation CREATE USER failed for 'u1'@'localhost' DROP USER u3@localhost; ERROR HY000: Operation DROP USER failed for 'u3'@'localhost' connection slave; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; -user password -u1 *A9A5EF53CE2EFAA6F4A746D63A917B2370971A7E -u2 +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; +User Password plugin authentication_string +u1 *A9A5EF53CE2EFAA6F4A746D63A917B2370971A7E mysql_native_password *A9A5EF53CE2EFAA6F4A746D63A917B2370971A7E +u2 mysql_native_password connection master; DROP USER IF EXISTS u1@localhost; DROP USER u2@localhost; @@ -61,6 +61,6 @@ DROP USER IF EXISTS u3@localhost; Warnings: Note 1974 Can't drop user 'u3'@'localhost'; it doesn't exist connection slave; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; -user password +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; +User Password plugin authentication_string include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result index d74fd07189c..b31eacfc236 100644 --- a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result +++ b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result @@ -25,8 +25,6 @@ connection slave; connection slave; SHOW TABLES in mysqltest; Tables_in_mysqltest -t -t1 SHOW EVENTS in mysqltest; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation mysqltest e root@localhost SYSTEM ONE TIME # NULL NULL NULL NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci diff --git a/mysql-test/suite/rpl/r/rpl_ddl.result b/mysql-test/suite/rpl/r/rpl_ddl.result index 68c5e91f42e..22ce9a288c1 100644 --- a/mysql-test/suite/rpl/r/rpl_ddl.result +++ b/mysql-test/suite/rpl/r/rpl_ddl.result @@ -1354,11 +1354,11 @@ MAX(f1) TEST-INFO: SLAVE: The INSERT is committed (Succeeded) connection master; SELECT user FROM mysql.user WHERE user = 'user1'; -user +User user1 connection slave; SELECT user FROM mysql.user WHERE user = 'user1'; -user +User user1 connection master; @@ -1399,11 +1399,11 @@ MAX(f1) TEST-INFO: SLAVE: The INSERT is committed (Succeeded) connection master; SELECT user FROM mysql.user WHERE user = 'rename1'; -user +User rename1 connection slave; SELECT user FROM mysql.user WHERE user = 'rename1'; -user +User rename1 connection master; @@ -1444,10 +1444,10 @@ MAX(f1) TEST-INFO: SLAVE: The INSERT is committed (Succeeded) connection master; SELECT user FROM mysql.user WHERE user = 'rename1'; -user +User connection slave; SELECT user FROM mysql.user WHERE user = 'rename1'; -user +User use test; connection master; DROP TEMPORARY TABLE mysqltest1.t22; diff --git a/mysql-test/suite/rpl/r/rpl_do_grant.result b/mysql-test/suite/rpl/r/rpl_do_grant.result index 9eca21b38e4..5fa1002f9ac 100644 --- a/mysql-test/suite/rpl/r/rpl_do_grant.result +++ b/mysql-test/suite/rpl/r/rpl_do_grant.result @@ -1,14 +1,6 @@ include/master-slave.inc [connection master] connection master; -delete from mysql.user where user=_binary'rpl_do_grant'; -delete from mysql.db where user=_binary'rpl_do_grant'; -flush privileges; -connection slave; -delete from mysql.user where user=_binary'rpl_ignore_grant'; -delete from mysql.db where user=_binary'rpl_ignore_grant'; -flush privileges; -connection master; create user rpl_do_grant@localhost; grant select on *.* to rpl_do_grant@localhost; grant drop on test.* to rpl_do_grant@localhost; @@ -20,11 +12,11 @@ GRANT DROP ON `test`.* TO 'rpl_do_grant'@'localhost' connection master; set password for rpl_do_grant@localhost=password("does it work?"); connection slave; -select authentication_string<>_binary'' from mysql.user where user=_binary'rpl_do_grant'; -authentication_string<>_binary'' +select authentication_string<>'' from mysql.user where user='rpl_do_grant'; +authentication_string<>'' 1 connection master; -update mysql.user set authentication_string='' where user='rpl_do_grant'; +update mysql.global_priv set priv=json_remove(priv, '$.authentication_string') where user='rpl_do_grant'; flush privileges; select authentication_string<>'' from mysql.user where user='rpl_do_grant'; authentication_string<>'' @@ -37,13 +29,8 @@ select authentication_string<>'' from mysql.user where user='rpl_do_grant'; authentication_string<>'' 1 connection master; -delete from mysql.user where user=_binary'rpl_do_grant'; -delete from mysql.db where user=_binary'rpl_do_grant'; -flush privileges; +drop user rpl_do_grant@localhost; connection slave; -delete from mysql.user where user=_binary'rpl_do_grant'; -delete from mysql.db where user=_binary'rpl_do_grant'; -flush privileges; connection master; show grants for rpl_do_grant@localhost; ERROR 42000: There is no such grant defined for user 'rpl_do_grant' on host 'localhost' @@ -328,4 +315,6 @@ Grantor root@localhost connection master; DROP USER user_bug27606@localhost; +select priv into @root_priv from mysql.global_priv where user='root' and host='127.0.0.1'; +update mysql.global_priv set priv=@root_priv where user='root' and host='localhost'; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_drop_db.result b/mysql-test/suite/rpl/r/rpl_drop_db.result index 1b132c20afc..3712527afe4 100644 --- a/mysql-test/suite/rpl/r/rpl_drop_db.result +++ b/mysql-test/suite/rpl/r/rpl_drop_db.result @@ -6,6 +6,8 @@ create database mysqltest1; create table mysqltest1.t1 (n int); insert into mysqltest1.t1 values (1); select * from mysqltest1.t1 into outfile 'mysqltest1/f1.txt'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create table mysqltest1.t2 (n int); create table mysqltest1.t3 (n int); drop database mysqltest1; diff --git a/mysql-test/suite/rpl/r/rpl_grant.result b/mysql-test/suite/rpl/r/rpl_grant.result index 0f546f7edc4..274a8505fb8 100644 --- a/mysql-test/suite/rpl/r/rpl_grant.result +++ b/mysql-test/suite/rpl/r/rpl_grant.result @@ -4,7 +4,7 @@ connection master; CREATE USER dummy@localhost; CREATE USER dummy1@localhost, dummy2@localhost; SELECT user, host FROM mysql.user WHERE user like 'dummy%'; -user host +User Host dummy localhost dummy1 localhost dummy2 localhost @@ -14,7 +14,7 @@ COUNT(*) connection slave; **** On Slave **** SELECT user,host FROM mysql.user WHERE user like 'dummy%'; -user host +User Host dummy localhost dummy1 localhost dummy2 localhost @@ -28,13 +28,13 @@ DROP USER nonexisting@localhost, dummy@localhost; ERROR HY000: Operation DROP USER failed for 'nonexisting'@'localhost' DROP USER dummy1@localhost, dummy2@localhost; SELECT user, host FROM mysql.user WHERE user like 'dummy%'; -user host +User Host SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%'; COUNT(*) 0 connection slave; SELECT user,host FROM mysql.user WHERE user like 'dummy%'; -user host +User Host SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%'; COUNT(*) 0 diff --git a/mysql-test/suite/rpl/r/rpl_gtid_ignored.result b/mysql-test/suite/rpl/r/rpl_gtid_ignored.result index ac608c3c2a3..de4a815ab60 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_ignored.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_ignored.result @@ -79,7 +79,7 @@ a 9 connection server_1; DROP TABLE t1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode; SET debug_sync = "reset"; connection server_2; diff --git a/mysql-test/suite/rpl/r/rpl_gtid_mdev4484.result b/mysql-test/suite/rpl/r/rpl_gtid_mdev4484.result index aaeb0c8f119..5dffdd9809c 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_mdev4484.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_mdev4484.result @@ -3,7 +3,7 @@ include/master-slave.inc connection slave; include/stop_slave.inc SET sql_log_bin=0; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; SET sql_log_bin=1; include/start_slave.inc connection master; @@ -16,36 +16,32 @@ INSERT INTO t1 VALUES (1); connection slave; connection slave; include/stop_slave.inc +SET @old_gtid_cleanup_batch_size= @@GLOBAL.gtid_cleanup_batch_size; +SET GLOBAL gtid_cleanup_batch_size= 2; SET @old_dbug= @@GLOBAL.debug_dbug; SET GLOBAL debug_dbug="+d,gtid_slave_pos_simulate_failed_delete"; SET sql_log_bin= 0; -CALL mtr.add_suppression("Can't find file"); +CALL mtr.add_suppression("<DEBUG> Error deleting old GTID row"); SET sql_log_bin= 1; include/start_slave.inc connection master; -INSERT INTO t1 VALUES (2); -connection slave; -include/wait_for_slave_sql_error.inc [errno=1942] -STOP SLAVE IO_THREAD; -SELECT domain_id, server_id, seq_no FROM mysql.gtid_slave_pos -ORDER BY domain_id, sub_id DESC LIMIT 1; -domain_id server_id seq_no -0 1 3 +connection slave; +SELECT COUNT(*), MAX(seq_no) INTO @pre_count, @pre_max_seq_no +FROM mysql.gtid_slave_pos; +SELECT IF(@pre_count >= 20, "OK", CONCAT("Error: too few rows seen while errors injected: ", @pre_count)); +IF(@pre_count >= 20, "OK", CONCAT("Error: too few rows seen while errors injected: ", @pre_count)) +OK SET GLOBAL debug_dbug= @old_dbug; -include/start_slave.inc connection master; -INSERT INTO t1 VALUES (3); -connection slave; -connection slave; -SELECT domain_id, server_id, seq_no FROM mysql.gtid_slave_pos -ORDER BY domain_id, sub_id DESC LIMIT 1; -domain_id server_id seq_no -0 1 4 -SELECT * FROM t1 ORDER BY i; -i -1 -2 -3 +connection slave; +connection slave; +SELECT IF(COUNT(*) >= 1, "OK", CONCAT("Error: too few rows seen after errors no longer injected: ", COUNT(*))) +FROM mysql.gtid_slave_pos +WHERE seq_no <= @pre_max_seq_no; +IF(COUNT(*) >= 1, "OK", CONCAT("Error: too few rows seen after errors no longer injected: ", COUNT(*))) +OK connection master; DROP TABLE t1; +connection slave; +SET GLOBAL gtid_cleanup_batch_size= @old_gtid_cleanup_batch_size; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result index ff845794c22..50f24d56e9a 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result @@ -159,7 +159,7 @@ a 8 9 SET sql_log_bin= 0; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; SET sql_log_bin= 1; include/start_slave.inc connection server_1; @@ -171,7 +171,7 @@ include/start_slave.inc *** MDEV-4692: mysql.gtid_slave_pos accumulates values for a domain *** SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; domain_id COUNT(*) -0 2 +0 3 1 2 connection server_1; INSERT INTO t1 VALUES (11); @@ -179,7 +179,7 @@ connection server_2; FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; domain_id COUNT(*) -0 2 +0 4 1 2 include/start_slave.inc connection server_1; @@ -189,8 +189,8 @@ connection server_2; FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; domain_id COUNT(*) -0 2 -1 2 +0 3 +1 1 *** MDEV-4650: show variables; ERROR 1946 (HY000): Failed to load replication slave GTID position *** connection server_2; SET sql_log_bin=0; diff --git a/mysql-test/suite/rpl/r/rpl_ignore_revoke.result b/mysql-test/suite/rpl/r/rpl_ignore_revoke.result index c86f2f4e4df..cc65d9dacfd 100644 --- a/mysql-test/suite/rpl/r/rpl_ignore_revoke.result +++ b/mysql-test/suite/rpl/r/rpl_ignore_revoke.result @@ -4,26 +4,26 @@ connection master; grant select on *.* to 'user_foo'@'%' identified by 'user_foopass'; revoke select on *.* from 'user_foo'@'%'; select select_priv from mysql.user where user='user_foo' /* master:must be N */; -select_priv +Select_priv N connection slave; grant select on *.* to 'user_foo'@'%' identified by 'user_foopass'; revoke select on *.* from 'user_foo'@'%'; select select_priv from mysql.user where user='user_foo' /* slave:must be N */; -select_priv +Select_priv N grant select on *.* to 'user_foo'@'%' identified by 'user_foopass'; select select_priv from mysql.user where user='user_foo' /* slave:must be Y */; -select_priv +Select_priv Y connection master; revoke select on *.* from 'user_foo'; select select_priv from mysql.user where user='user_foo' /* master:must be N */; -select_priv +Select_priv N connection slave; select select_priv from mysql.user where user='user_foo' /* slave:must get Y */; -select_priv +Select_priv Y connection slave; revoke select on *.* FROM 'user_foo'; diff --git a/mysql-test/suite/rpl/r/rpl_ignore_table.result b/mysql-test/suite/rpl/r/rpl_ignore_table.result index 4eeb333d10c..511eff51d22 100644 --- a/mysql-test/suite/rpl/r/rpl_ignore_table.result +++ b/mysql-test/suite/rpl/r/rpl_ignore_table.result @@ -1,7 +1,7 @@ include/master-slave.inc [connection master] call mtr.add_suppression("Can't find record in 't.'"); -call mtr.add_suppression("Can't find record in 'user'"); +call mtr.add_suppression("Can't find record in 'global_priv'"); call mtr.add_suppression("Can't find record in 'tables_priv'"); **** Test case for BUG#16487 **** connection master; @@ -32,12 +32,7 @@ to mysqltest3@localhost; create database mysqltest2; create table mysqltest2.t2 (id int); GRANT SELECT ON mysqltest2.t2 TO mysqltest4@localhost IDENTIFIED BY 'pass'; -insert into mysql.user (user, host) values ("mysqltest5", "somehost"); -Warnings: -Warning 1364 Field 'ssl_cipher' doesn't have a default value -Warning 1364 Field 'x509_issuer' doesn't have a default value -Warning 1364 Field 'x509_subject' doesn't have a default value -Warning 1364 Field 'authentication_string' doesn't have a default value +insert into mysql.global_priv (user, host) values ("mysqltest5", "somehost"); GRANT SELECT ON *.* TO mysqltest6@localhost; GRANT INSERT ON *.* TO mysqltest6@localhost; GRANT INSERT ON test.* TO mysqltest6@localhost; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_bug28430.result b/mysql-test/suite/rpl/r/rpl_innodb_bug28430.result index a666ae26c51..69215ecb545 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_bug28430.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_bug28430.result @@ -51,6 +51,10 @@ DELETE FROM test.regular_tbl WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE PROCEDURE test.proc_bykey() BEGIN DECLARE ins_count INT DEFAULT 1000; @@ -72,6 +76,10 @@ DELETE FROM test.bykey_tbl WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE PROCEDURE test.proc_byrange() BEGIN DECLARE ins_count INT DEFAULT 1000; @@ -93,6 +101,10 @@ DELETE FROM test.byrange_tbl WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead begin; CALL test.proc_norm(); commit; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_bug30888.result b/mysql-test/suite/rpl/r/rpl_innodb_bug30888.result index d4640a36a7d..da6888e76a0 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_bug30888.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_bug30888.result @@ -26,6 +26,10 @@ DELETE FROM test.regular_tbl WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL test.proc_norm(); connection slave; connection master; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index 00b50df4a68..89f59deae73 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -481,77 +481,78 @@ SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; ******************** CREATE USER ******************** CREATE USER 'user_test_rpl'@'localhost' IDENTIFIED BY PASSWORD '*1111111111111111111111111111111111111111'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 N +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 N +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N connection master; ******************** GRANT ******************** GRANT SELECT ON *.* TO 'user_test_rpl'@'localhost'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 Y +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 Y connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 Y +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 Y connection master; ******************** REVOKE ******************** REVOKE SELECT ON *.* FROM 'user_test_rpl'@'localhost'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 N +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 N +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N connection master; ******************** SET PASSWORD ******************** SET PASSWORD FOR 'user_test_rpl'@'localhost' = '*0000000000000000000000000000000000000000'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv localhost user_test_rpl *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv localhost user_test_rpl *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N connection master; ******************** RENAME USER ******************** RENAME USER 'user_test_rpl'@'localhost' TO 'user_test_rpl_2'@'localhost'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv localhost user_test_rpl_2 *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv localhost user_test_rpl_2 *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N connection master; ******************** DROP USER ******************** DROP USER 'user_test_rpl_2'@'localhost'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv connection master; INSERT INTO t1 VALUES(100, 'test'); ******************** ANALYZE ******************** ANALYZE TABLE t1; Table Op Msg_type Msg_text +test_rpl.t1 analyze status Engine-independent statistics collected test_rpl.t1 analyze status OK ******************** CHECK TABLE ******************** @@ -676,7 +677,6 @@ DROP TRIGGER tr1; ******************** EVENTS ******************** -GRANT EVENT ON *.* TO 'root'@'localhost'; INSERT INTO t1 VALUES(1, 'test1'); CREATE EVENT e1 ON SCHEDULE EVERY '1' SECOND COMMENT 'e_second_comment' DO DELETE FROM t1; SHOW EVENTS; @@ -1098,8 +1098,6 @@ master-bin.000001 # Query # # use `test_rpl`; DELETE FROM t2 master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Gtid # # GTID #-#-# master-bin.000001 # Query # # use `test_rpl`; DROP TRIGGER tr1 -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test_rpl`; GRANT EVENT ON *.* TO 'root'@'localhost' master-bin.000001 # Gtid # # BEGIN GTID #-#-# master-bin.000001 # Query # # use `test_rpl`; INSERT INTO t1 VALUES(1, 'test1') master-bin.000001 # Xid # # COMMIT /* XID */ diff --git a/mysql-test/suite/rpl/r/rpl_mdev10863.result b/mysql-test/suite/rpl/r/rpl_mdev10863.result index 6accd1ee830..0326316563c 100644 --- a/mysql-test/suite/rpl/r/rpl_mdev10863.result +++ b/mysql-test/suite/rpl/r/rpl_mdev10863.result @@ -46,6 +46,6 @@ SET GLOBAL slave_parallel_threads=@old_parallel_threads; SET GLOBAL max_relay_log_size= @old_max_relay; include/start_slave.inc connection server_1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; DROP TABLE t1; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_mdev12179.result b/mysql-test/suite/rpl/r/rpl_mdev12179.result index 8373eb43774..dcda036cdfb 100644 --- a/mysql-test/suite/rpl/r/rpl_mdev12179.result +++ b/mysql-test/suite/rpl/r/rpl_mdev12179.result @@ -49,7 +49,7 @@ a 1 include/stop_slave.inc SET sql_log_bin=0; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos; ALTER TABLE mysql.gtid_slave_pos_innodb ENGINE=InnoDB; INSERT INTO mysql.gtid_slave_pos_innodb SELECT * FROM mysql.gtid_slave_pos; @@ -77,7 +77,7 @@ SELECT table_name, engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; table_name engine -gtid_slave_pos MyISAM +gtid_slave_pos Aria gtid_slave_pos_innodb InnoDB SELECT @@gtid_pos_auto_engines; @@gtid_pos_auto_engines @@ -122,7 +122,7 @@ table_name engine gtid_slave_pos InnoDB include/stop_slave.inc SET sql_log_bin=0; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; SET sql_log_bin=1; connection server_1; INSERT INTO t1 VALUES (5); @@ -157,7 +157,7 @@ SELECT lower(table_name), engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; lower(table_name) engine -gtid_slave_pos MyISAM +gtid_slave_pos Aria gtid_slave_pos_innodb InnoDB include/stop_slave.inc SET sql_log_bin=0; @@ -202,7 +202,7 @@ SELECT table_name, engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; table_name engine -gtid_slave_pos MyISAM +gtid_slave_pos Aria SELECT domain_id, max(seq_no) FROM mysql.gtid_slave_pos GROUP BY domain_id; domain_id max(seq_no) 0 11 @@ -250,7 +250,7 @@ SELECT lower(table_name), engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; lower(table_name) engine -gtid_slave_pos MyISAM +gtid_slave_pos Aria gtid_slave_pos_innodb InnoDB SELECT domain_id, max(seq_no) FROM mysql.gtid_slave_pos GROUP BY domain_id; domain_id max(seq_no) @@ -259,6 +259,8 @@ connection server_2; *** Restart the slave server to prove 'gtid_slave_pos_innodb' autodiscovery *** connection server_2; SELECT max(seq_no) FROM mysql.gtid_slave_pos_InnoDB into @seq_no; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead connection server_1; INSERT INTO t2(a) SELECT 1+MAX(a) FROM t2; include/save_master_gtid.inc diff --git a/mysql-test/suite/rpl/r/rpl_misc_functions.result b/mysql-test/suite/rpl/r/rpl_misc_functions.result index 6c20623d62b..302cf2351c2 100644 --- a/mysql-test/suite/rpl/r/rpl_misc_functions.result +++ b/mysql-test/suite/rpl/r/rpl_misc_functions.result @@ -42,6 +42,8 @@ INSERT INTO t1 (col_a) VALUES (test_replication_sf()); INSERT INTO t1 (col_a) VALUES (test_replication_sf()); connection slave; select * from t1 into outfile "../../tmp/t1_slave.txt"; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead connection master; create temporary table t1_slave select * from t1 where 1=0; load data infile '../../tmp/t1_slave.txt' into table t1_slave; diff --git a/mysql-test/suite/rpl/r/rpl_mixed_implicit_commit_binlog.result b/mysql-test/suite/rpl/r/rpl_mixed_implicit_commit_binlog.result index f900a8b0e9a..e768c5c6f7c 100644 --- a/mysql-test/suite/rpl/r/rpl_mixed_implicit_commit_binlog.result +++ b/mysql-test/suite/rpl/r/rpl_mixed_implicit_commit_binlog.result @@ -30,6 +30,7 @@ test.tt_2 preload_keys note The storage engine for the table doesn't support pre INSERT INTO tt_1(ddl_case) VALUES (39); ANALYZE TABLE nt_1; Table Op Msg_type Msg_text +test.nt_1 analyze status Engine-independent statistics collected test.nt_1 analyze status Table is already up to date INSERT INTO tt_1(ddl_case) VALUES (38); CHECK TABLE nt_1; diff --git a/mysql-test/suite/rpl/r/rpl_mysql57_stm_temporal_round.result b/mysql-test/suite/rpl/r/rpl_mysql57_stm_temporal_round.result new file mode 100644 index 00000000000..bedd103c2a0 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_mysql57_stm_temporal_round.result @@ -0,0 +1,22 @@ +# +# MDEV-8894 Inserting fractional seconds into MySQL 5.6 master breaks consistency on MariaDB 10 slave +# +include/master-slave.inc +[connection master] +connection slave; +CREATE TABLE t1 (id SERIAL, a DATETIME(3)); +include/stop_slave.inc +connection master; +include/rpl_stop_server.inc [server_number=1] +include/rpl_start_server.inc [server_number=1] +connection slave; +CHANGE MASTER TO master_host='127.0.0.1', master_port=SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4; +include/start_slave.inc +connection master; +connection slave; +SELECT * FROM t1 ORDER BY id; +id a +1 2001-01-01 00:00:01.000 +include/stop_slave.inc +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_mysql80_stm_temporal_round.result b/mysql-test/suite/rpl/r/rpl_mysql80_stm_temporal_round.result new file mode 100644 index 00000000000..23b3217895a --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_mysql80_stm_temporal_round.result @@ -0,0 +1,23 @@ +# +# MDEV-8894 Inserting fractional seconds into MySQL 5.6 master breaks consistency on MariaDB 10 slave +# +include/master-slave.inc +[connection master] +connection slave; +CREATE TABLE t1 (id SERIAL, a DATETIME(3)); +include/stop_slave.inc +connection master; +include/rpl_stop_server.inc [server_number=1] +include/rpl_start_server.inc [server_number=1] +connection slave; +CHANGE MASTER TO master_host='127.0.0.1', master_port=SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4; +include/start_slave.inc +connection master; +connection slave; +SELECT * FROM t1 ORDER BY id; +id a +1 2001-01-01 00:00:01.000 +2 2001-01-01 00:00:00.999 +include/stop_slave.inc +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_parallel.result b/mysql-test/suite/rpl/r/rpl_parallel.result index d994e4fdef6..9258deadaca 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel.result +++ b/mysql-test/suite/rpl/r/rpl_parallel.result @@ -1517,6 +1517,7 @@ SET SESSION debug_dbug="+d,binlog_force_commit_id"; SET @commit_id= 10000; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK INSERT INTO t3 VALUES (120, 0); SET @commit_id= 10001; diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result index ca202a66b0e..bf7a8192f56 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result @@ -12,6 +12,8 @@ SET GLOBAL slave_parallel_threads=10; CHANGE MASTER TO master_use_gtid=slave_pos; SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; SET GLOBAL slave_parallel_mode='optimistic'; +SET @old_gtid_cleanup_batch_size= @@GLOBAL.gtid_cleanup_batch_size; +SET GLOBAL gtid_cleanup_batch_size= 1000000; connection server_1; INSERT INTO t1 VALUES(1,1); BEGIN; @@ -131,6 +133,11 @@ c 204 205 206 +SELECT IF(COUNT(*) >= 30, "OK", CONCAT("Error: too few old rows found: ", COUNT(*))) +FROM mysql.gtid_slave_pos; +IF(COUNT(*) >= 30, "OK", CONCAT("Error: too few old rows found: ", COUNT(*))) +OK +SET GLOBAL gtid_cleanup_batch_size=1; *** Test @@skip_parallel_replication. *** connection server_2; include/stop_slave.inc @@ -358,6 +365,7 @@ connection server_1; ALTER TABLE t2 COMMENT "123abc"; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK INSERT INTO t1 VALUES (1,2); INSERT INTO t1 VALUES (2,2); @@ -478,6 +486,7 @@ SET @old_server_id= @@SESSION.server_id; SET SESSION server_id= 100; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK SET SESSION server_id= @old_server_id; INSERT INTO t1 VALUES (37,0); @@ -651,9 +660,10 @@ DROP TABLE t1, t2, t3; include/save_master_gtid.inc connection server_2; include/sync_with_master_gtid.inc -Check that no more than the expected last four GTIDs are in mysql.gtid_slave_pos -select count(4) <= 4 from mysql.gtid_slave_pos order by domain_id, sub_id; -count(4) <= 4 +SELECT COUNT(*) <= 5*@@GLOBAL.gtid_cleanup_batch_size +FROM mysql.gtid_slave_pos; +COUNT(*) <= 5*@@GLOBAL.gtid_cleanup_batch_size 1 +SET GLOBAL gtid_cleanup_batch_size= @old_gtid_cleanup_batch_size; connection server_1; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_row_001.result b/mysql-test/suite/rpl/r/rpl_row_001.result index f7684d5ad97..976ac0996bf 100644 --- a/mysql-test/suite/rpl/r/rpl_row_001.result +++ b/mysql-test/suite/rpl/r/rpl_row_001.result @@ -1,44 +1,6 @@ include/master-slave.inc [connection master] -CREATE TABLE t1 (word CHAR(20) NOT NULL); -LOAD DATA INFILE 'LOAD_FILE' INTO TABLE t1; -LOAD DATA INFILE 'LOAD_FILE' INTO TABLE t1; -SELECT * FROM t1 ORDER BY word LIMIT 10; -word -Aarhus -Aarhus -Aarhus -Aarhus -Aaron -Aaron -Aaron -Aaron -Ababa -Ababa -create temporary table tmp select * from mysql.user where host="localhost" and user="root"; -connection slave; -STOP SLAVE; -connection master; -UPDATE mysql.user SET password=password('foo') WHERE host='localhost' AND user='root'; -connection slave; -START SLAVE; -connection master; -UPDATE mysql.user SET password=password('') WHERE host='localhost' AND user='root'; -CREATE TABLE t3(n INT); -INSERT INTO t3 VALUES(1),(2); -connection slave; -SELECT * FROM t3 ORDER BY n; -n -1 -2 -SELECT SUM(LENGTH(word)) FROM t1; -SUM(LENGTH(word)) -1022 -connection master; -DROP TABLE t1,t3; -connection slave; -connection master; -CREATE TABLE t1 (n INT) ENGINE=MYISAM; +CREATE TABLE t1 (n INT); connection slave; connection master; RESET MASTER; @@ -66,7 +28,5 @@ n 3456 connection master; DROP TABLE t1; -replace into mysql.user select * from tmp; -drop temporary table tmp; connection slave; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_row_annotate_do.result b/mysql-test/suite/rpl/r/rpl_row_annotate_do.result index 52f7b180fae..ba1922566bf 100644 --- a/mysql-test/suite/rpl/r/rpl_row_annotate_do.result +++ b/mysql-test/suite/rpl/r/rpl_row_annotate_do.result @@ -180,7 +180,7 @@ slave-bin.000001 # Rotate 2 # slave-bin.000002;pos=4 connection master; SET SESSION binlog_annotate_row_events = ON; INSERT DELAYED INTO test1.t4 VALUES (1,1); -FLUSH TABLES; +FLUSH TABLES test1.t4; SELECT * FROM test1.t4 ORDER BY a; a b 1 1 diff --git a/mysql-test/suite/rpl/r/rpl_row_annotate_dont.result b/mysql-test/suite/rpl/r/rpl_row_annotate_dont.result index c657cf2fbb5..65535d5d417 100644 --- a/mysql-test/suite/rpl/r/rpl_row_annotate_dont.result +++ b/mysql-test/suite/rpl/r/rpl_row_annotate_dont.result @@ -160,7 +160,7 @@ slave-bin.000001 # Rotate 2 # slave-bin.000002;pos=4 connection master; SET SESSION binlog_annotate_row_events = ON; INSERT DELAYED INTO test1.t4 VALUES (1,1); -FLUSH TABLES; +FLUSH TABLES test1.t4; SELECT * FROM test1.t4 ORDER BY a; a b 1 1 diff --git a/mysql-test/suite/rpl/r/rpl_row_delayed_ins.result b/mysql-test/suite/rpl/r/rpl_row_delayed_ins.result index 978c3d30dbd..4d439c202f5 100644 --- a/mysql-test/suite/rpl/r/rpl_row_delayed_ins.result +++ b/mysql-test/suite/rpl/r/rpl_row_delayed_ins.result @@ -5,7 +5,7 @@ create table t1(a int not null primary key) engine=myisam; insert delayed into t1 values (1); insert delayed into t1 values (2); insert delayed into t1 values (3); -flush tables; +flush tables t1; SELECT * FROM t1 ORDER BY a; a 1 diff --git a/mysql-test/suite/rpl/r/rpl_row_implicit_commit_binlog.result b/mysql-test/suite/rpl/r/rpl_row_implicit_commit_binlog.result index ef393873b97..a2f3bb44ae1 100644 --- a/mysql-test/suite/rpl/r/rpl_row_implicit_commit_binlog.result +++ b/mysql-test/suite/rpl/r/rpl_row_implicit_commit_binlog.result @@ -30,6 +30,7 @@ test.tt_2 preload_keys note The storage engine for the table doesn't support pre INSERT INTO tt_1(ddl_case) VALUES (39); ANALYZE TABLE nt_1; Table Op Msg_type Msg_text +test.nt_1 analyze status Engine-independent statistics collected test.nt_1 analyze status Table is already up to date INSERT INTO tt_1(ddl_case) VALUES (38); CHECK TABLE nt_1; diff --git a/mysql-test/suite/rpl/r/rpl_stm_000001.result b/mysql-test/suite/rpl/r/rpl_stm_000001.result index 0b9ed6fc09c..9ef2ca3bc53 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_000001.result +++ b/mysql-test/suite/rpl/r/rpl_stm_000001.result @@ -19,11 +19,16 @@ abandons connection slave; stop slave; connection master; -UPDATE mysql.user SET password=password('foo') WHERE host='localhost' AND user='root'; +create temporary table tmp select * from mysql.global_priv where host="localhost" and user="root"; +set password for root@"localhost" = password('foo'); connection slave; start slave; connection master; -UPDATE mysql.user SET password=password('') WHERE host='localhost' AND user='root'; +replace into mysql.global_priv select * from tmp; +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. REPLACE... SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave +drop temporary table tmp; +flush privileges; create table t3(n int); insert into t3 values(1),(2); connection slave; @@ -38,7 +43,7 @@ connection master; drop table t1,t3; connection slave; connection master; -create table t1 (n int) engine=myisam; +create table t1 (n int); connection slave; connection master; reset master; @@ -76,31 +81,4 @@ count(*) 5000 connection master1; drop table t1; -create table t1 (n int); -insert into t1 values(3456); -insert ignore into mysql.user (Host, User, Password) -VALUES ("10.10.10.%", "blafasel2", password("blafasel2")); -Warnings: -Warning 1364 Field 'ssl_cipher' doesn't have a default value -Warning 1364 Field 'x509_issuer' doesn't have a default value -Warning 1364 Field 'x509_subject' doesn't have a default value -Warning 1364 Field 'authentication_string' doesn't have a default value -select select_priv,user from mysql.user where user = _binary'blafasel2'; -select_priv user -N blafasel2 -update mysql.user set Select_priv = "Y" where User= _binary"blafasel2"; -select select_priv,user from mysql.user where user = _binary'blafasel2'; -select_priv user -Y blafasel2 -connection slave; -select n from t1; -n -3456 -select select_priv,user from mysql.user where user = _binary'blafasel2'; -select_priv user -Y blafasel2 -connection master1; -drop table t1; -delete from mysql.user where user="blafasel2"; -connection slave; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_stm_implicit_commit_binlog.result b/mysql-test/suite/rpl/r/rpl_stm_implicit_commit_binlog.result index f900a8b0e9a..e768c5c6f7c 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_implicit_commit_binlog.result +++ b/mysql-test/suite/rpl/r/rpl_stm_implicit_commit_binlog.result @@ -30,6 +30,7 @@ test.tt_2 preload_keys note The storage engine for the table doesn't support pre INSERT INTO tt_1(ddl_case) VALUES (39); ANALYZE TABLE nt_1; Table Op Msg_type Msg_text +test.nt_1 analyze status Engine-independent statistics collected test.nt_1 analyze status Table is already up to date INSERT INTO tt_1(ddl_case) VALUES (38); CHECK TABLE nt_1; diff --git a/mysql-test/suite/rpl/r/rpl_switch_stm_row_mixed.result b/mysql-test/suite/rpl/r/rpl_switch_stm_row_mixed.result index 2f7f1b07cb4..936f604be2e 100644 --- a/mysql-test/suite/rpl/r/rpl_switch_stm_row_mixed.result +++ b/mysql-test/suite/rpl/r/rpl_switch_stm_row_mixed.result @@ -140,7 +140,7 @@ create table t4 select * from t1 where 3 in (select 1 union select 2 union selec SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3); Warnings: -Warning 1292 Incorrect datetime value: '3' +Warning 1292 Truncated incorrect datetime value: '3' insert ignore into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4); create procedure foo() begin diff --git a/mysql-test/suite/rpl/r/rpl_temporal_round.result b/mysql-test/suite/rpl/r/rpl_temporal_round.result new file mode 100644 index 00000000000..df8cc431a74 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_temporal_round.result @@ -0,0 +1,50 @@ +include/master-slave.inc +[connection master] +SET sql_mode=TIME_ROUND_FRACTIONAL; +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); +CREATE TABLE t1 (id SERIAL, a TIMESTAMP(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES ('2011-01-01 23:59:59.999999'); +CREATE TABLE t2 (id SERIAL, a DATETIME(4)); +INSERT INTO t2 (a) VALUES (now(6)); +INSERT INTO t2 (a) VALUES ('2011-01-01 23:59:59.999999'); +CREATE TABLE t3 (id SERIAL, a TIME(4)); +INSERT INTO t3 (a) VALUES (now(6)); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +INSERT INTO t3 (a) VALUES ('2011-01-01 23:59:59.999999'); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +SELECT * FROM t1; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-02 00:00:00.0000 +SELECT * FROM t2; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-02 00:00:00.0000 +SELECT * FROM t3; +id a +1 24:00:00.0000 +2 24:00:00.0000 +connection slave; +connection slave; +SET time_zone='+00:00'; +SELECT * FROM t1; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-02 00:00:00.0000 +SELECT * FROM t2; +id a +1 2011-01-01 00:00:00.0000 +2 2011-01-02 00:00:00.0000 +SELECT * FROM t3; +id a +1 24:00:00.0000 +2 24:00:00.0000 +connection master; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result index e8e95ab7c4c..45070949f79 100644 --- a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result +++ b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result @@ -145,43 +145,43 @@ UNLOCK TABLE; DROP DATABASE mysqltest2; LOCK TABLE t1 WRITE; CREATE USER test_1@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("CREATE USER test_1@localhost with table locked"); UNLOCK TABLE; CREATE USER test_2@localhost; LOCK TABLE t1 WRITE; GRANT SELECT ON t1 TO test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("GRANT select on table to user with table locked"); GRANT ALL ON f2 TO test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("GRANT ALL ON f2 TO test_2 with table locked"); GRANT ALL ON p2 TO test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("GRANT ALL ON p2 TO test_2 with table locked"); GRANT USAGE ON *.* TO test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("GRANT USAGE ON *.* TO test_2 with table locked"); REVOKE ALL PRIVILEGES ON f2 FROM test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on function to user with table locked"); REVOKE ALL PRIVILEGES ON p2 FROM test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on procedure to user with table locked"); REVOKE ALL PRIVILEGES ON t1 FROM test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'tables_priv' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("REVOKE ALL PRIVILEGES on table to user with table locked"); REVOKE USAGE ON *.* FROM test_2@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("REVOKE USAGE ON *.* TO test_2 with table locked"); RENAME USER test_2@localhost TO test_3@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("RENAME USER test_2 TO test_3 with table locked"); UNLOCK TABLE; RENAME USER test_2@localhost TO test_3@localhost; LOCK TABLE t1 WRITE; DROP USER test_3@localhost; -ERROR HY000: Table 'user' was not locked with LOCK TABLES +ERROR HY000: Table 'db' was not locked with LOCK TABLES INSERT INTO t2 VALUES ("DROP USER test_3@localhost with table locked"); UNLOCK TABLE; CREATE DATABASE db; diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_user.test b/mysql-test/suite/rpl/t/rpl_create_drop_user.test index 5fcf0a14c36..c5f193a0d0c 100644 --- a/mysql-test/suite/rpl/t/rpl_create_drop_user.test +++ b/mysql-test/suite/rpl/t/rpl_create_drop_user.test @@ -15,9 +15,11 @@ SELECT CURRENT_USER; disconnect user_a; connection master; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; sync_slave_with_master; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; connection master; CREATE OR REPLACE USER u1@localhost IDENTIFIED BY 'abcdefghijk2'; @@ -26,9 +28,11 @@ connection user_a; SELECT CURRENT_USER; disconnect user_a; connection master; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; sync_slave_with_master; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; connection master; --error ER_CANNOT_USER @@ -38,7 +42,8 @@ CREATE USER u1@localhost; DROP USER u3@localhost; sync_slave_with_master; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; connection master; DROP USER IF EXISTS u1@localhost; @@ -46,6 +51,7 @@ DROP USER u2@localhost; DROP USER IF EXISTS u3@localhost; sync_slave_with_master; -SELECT user, password FROM mysql.user WHERE user LIKE 'u%' ORDER BY user; +--sorted_result +SELECT user,password,plugin,authentication_string FROM mysql.user WHERE user LIKE 'u%' ; --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_do_grant.test b/mysql-test/suite/rpl/t/rpl_do_grant.test index 0024c7039e4..1350585ff93 100644 --- a/mysql-test/suite/rpl/t/rpl_do_grant.test +++ b/mysql-test/suite/rpl/t/rpl_do_grant.test @@ -3,18 +3,6 @@ -- source include/master-slave.inc -# do not be influenced by other tests. -connection master; -delete from mysql.user where user=_binary'rpl_do_grant'; -delete from mysql.db where user=_binary'rpl_do_grant'; -flush privileges; -sync_slave_with_master; -# if these DELETE did nothing on the master, we need to do them manually on the -# slave. -delete from mysql.user where user=_binary'rpl_ignore_grant'; -delete from mysql.db where user=_binary'rpl_ignore_grant'; -flush privileges; - # test replication of GRANT connection master; create user rpl_do_grant@localhost; @@ -27,13 +15,13 @@ show grants for rpl_do_grant@localhost; connection master; set password for rpl_do_grant@localhost=password("does it work?"); sync_slave_with_master; -select authentication_string<>_binary'' from mysql.user where user=_binary'rpl_do_grant'; +select authentication_string<>'' from mysql.user where user='rpl_do_grant'; # # Bug#24158 SET PASSWORD in binary log fails under ANSI_QUOTES # connection master; -update mysql.user set authentication_string='' where user='rpl_do_grant'; +update mysql.global_priv set priv=json_remove(priv, '$.authentication_string') where user='rpl_do_grant'; flush privileges; select authentication_string<>'' from mysql.user where user='rpl_do_grant'; set sql_mode='ANSI_QUOTES'; @@ -42,18 +30,10 @@ set sql_mode=''; sync_slave_with_master; select authentication_string<>'' from mysql.user where user='rpl_do_grant'; - # clear what we have done, to not influence other tests. connection master; -delete from mysql.user where user=_binary'rpl_do_grant'; -delete from mysql.db where user=_binary'rpl_do_grant'; -flush privileges; +drop user rpl_do_grant@localhost; sync_slave_with_master; -# The mysql database is not replicated, so we have to do the deletes -# manually on the slave as well. -delete from mysql.user where user=_binary'rpl_do_grant'; -delete from mysql.db where user=_binary'rpl_do_grant'; -flush privileges; # End of 4.1 tests @@ -363,5 +343,8 @@ SELECT Grantor FROM mysql.tables_priv WHERE User='user_bug27606'; --connection master DROP USER user_bug27606@localhost; +select priv into @root_priv from mysql.global_priv where user='root' and host='127.0.0.1'; +update mysql.global_priv set priv=@root_priv where user='root' and host='localhost'; + --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_ignored.test b/mysql-test/suite/rpl/t/rpl_gtid_ignored.test index 6e927bd5a77..3c1324b2ea6 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_ignored.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_ignored.test @@ -129,7 +129,7 @@ SELECT * FROM t1 ORDER BY a; # Clean up. --connection server_1 DROP TABLE t1; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; SET GLOBAL gtid_strict_mode= @old_gtid_strict_mode; SET debug_sync = "reset"; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test b/mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test index e1f5696f5a1..5c17653da8a 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_mdev4484.test @@ -9,7 +9,7 @@ # back). So fix it to make sure we are consistent, in case an earlier test case # left it as InnoDB. SET sql_log_bin=0; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; SET sql_log_bin=1; --source include/start_slave.inc @@ -28,37 +28,79 @@ INSERT INTO t1 VALUES (1); # Inject an artificial error deleting entries, and check that the error handling code works. --connection slave --source include/stop_slave.inc +SET @old_gtid_cleanup_batch_size= @@GLOBAL.gtid_cleanup_batch_size; +SET GLOBAL gtid_cleanup_batch_size= 2; SET @old_dbug= @@GLOBAL.debug_dbug; SET GLOBAL debug_dbug="+d,gtid_slave_pos_simulate_failed_delete"; SET sql_log_bin= 0; -CALL mtr.add_suppression("Can't find file"); +CALL mtr.add_suppression("<DEBUG> Error deleting old GTID row"); SET sql_log_bin= 1; --source include/start_slave.inc --connection master -INSERT INTO t1 VALUES (2); +--disable_query_log +let $i = 20; +while ($i) { + eval INSERT INTO t1 VALUES ($i+10); + dec $i; +} +--enable_query_log +--save_master_pos --connection slave ---let $slave_sql_errno= 1942 ---source include/wait_for_slave_sql_error.inc -STOP SLAVE IO_THREAD; -SELECT domain_id, server_id, seq_no FROM mysql.gtid_slave_pos - ORDER BY domain_id, sub_id DESC LIMIT 1; +--sync_with_master + +# Now wait for the slave background thread to try to delete old rows and +# hit the error injection. +--let _TEST_MYSQLD_ERROR_LOG=$MYSQLTEST_VARDIR/log/mysqld.2.err +--perl + open F, '<', $ENV{'_TEST_MYSQLD_ERROR_LOG'} or die; + outer: while (1) { + inner: while (<F>) { + last outer if /<DEBUG> Error deleting old GTID row/; + } + # Easy way to do sub-second sleep without extra modules. + select(undef, undef, undef, 0.1); + } +EOF + +# Since we injected error in the cleanup code, the rows should remain in +# mysql.gtid_slave_pos. Check that we have at least 20 (more robust against +# non-deterministic cleanup and future changes than checking for exact number). +SELECT COUNT(*), MAX(seq_no) INTO @pre_count, @pre_max_seq_no + FROM mysql.gtid_slave_pos; +SELECT IF(@pre_count >= 20, "OK", CONCAT("Error: too few rows seen while errors injected: ", @pre_count)); SET GLOBAL debug_dbug= @old_dbug; ---source include/start_slave.inc --connection master -INSERT INTO t1 VALUES (3); +--disable_query_log +let $i = 20; +while ($i) { + eval INSERT INTO t1 VALUES ($i+40); + dec $i; +} +--enable_query_log --sync_slave_with_master --connection slave -SELECT domain_id, server_id, seq_no FROM mysql.gtid_slave_pos - ORDER BY domain_id, sub_id DESC LIMIT 1; -SELECT * FROM t1 ORDER BY i; - +# Now check that 1) rows are being deleted again after removing error +# injection, and 2) old rows are left that failed their delete while errors +# where injected (again compensating for non-deterministic deletion). +# Deletion is async and slightly non-deterministic, so we wait for at +# least 10 of the 20 new rows to be deleted. +let $wait_condition= + SELECT COUNT(*) <= 20-10 + FROM mysql.gtid_slave_pos + WHERE seq_no > @pre_max_seq_no; +--source include/wait_condition.inc +SELECT IF(COUNT(*) >= 1, "OK", CONCAT("Error: too few rows seen after errors no longer injected: ", COUNT(*))) + FROM mysql.gtid_slave_pos + WHERE seq_no <= @pre_max_seq_no; # Clean up --connection master DROP TABLE t1; +--connection slave +SET GLOBAL gtid_cleanup_batch_size= @old_gtid_cleanup_batch_size; --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test index 309debd87c5..53d62805c58 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test @@ -230,7 +230,7 @@ EOF --enable_reconnect --source include/wait_until_connected_again.inc SET sql_log_bin= 0; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; SET sql_log_bin= 1; # Do a second restart to get the mysql.gtid_slave_pos table loaded with # the right engine. diff --git a/mysql-test/suite/rpl/t/rpl_ignore_table.test b/mysql-test/suite/rpl/t/rpl_ignore_table.test index 3360b789475..a3fcfc95901 100644 --- a/mysql-test/suite/rpl/t/rpl_ignore_table.test +++ b/mysql-test/suite/rpl/t/rpl_ignore_table.test @@ -3,7 +3,7 @@ source include/have_collation.inc; source include/master-slave.inc; call mtr.add_suppression("Can't find record in 't.'"); -call mtr.add_suppression("Can't find record in 'user'"); +call mtr.add_suppression("Can't find record in 'global_priv'"); call mtr.add_suppression("Can't find record in 'tables_priv'"); # @@ -69,7 +69,7 @@ create table mysqltest2.t2 (id int); GRANT SELECT ON mysqltest2.t2 TO mysqltest4@localhost IDENTIFIED BY 'pass'; # Create a grant manually -insert into mysql.user (user, host) values ("mysqltest5", "somehost"); +insert into mysql.global_priv (user, host) values ("mysqltest5", "somehost"); # Partial replicate 3 with *.* GRANT SELECT ON *.* TO mysqltest6@localhost; diff --git a/mysql-test/suite/rpl/t/rpl_mdev10863.test b/mysql-test/suite/rpl/t/rpl_mdev10863.test index 81cdfd84dbe..73062df861e 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev10863.test +++ b/mysql-test/suite/rpl/t/rpl_mdev10863.test @@ -99,7 +99,7 @@ SET GLOBAL max_relay_log_size= @old_max_relay; --source include/start_slave.inc --connection server_1 -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; DROP TABLE t1; --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev12179.test b/mysql-test/suite/rpl/t/rpl_mdev12179.test index eb0f6c04b42..db1ec3d4d22 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev12179.test +++ b/mysql-test/suite/rpl/t/rpl_mdev12179.test @@ -44,7 +44,7 @@ SELECT * FROM t1 ORDER BY a; SET sql_log_bin=0; # Reset storage engine for mysql.gtid_slave_pos in case an earlier test # might have changed it to InnoDB. -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos; ALTER TABLE mysql.gtid_slave_pos_innodb ENGINE=InnoDB; INSERT INTO mysql.gtid_slave_pos_innodb SELECT * FROM mysql.gtid_slave_pos; @@ -128,7 +128,7 @@ SELECT table_name, engine FROM information_schema.tables --source include/stop_slave.inc SET sql_log_bin=0; -ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +ALTER TABLE mysql.gtid_slave_pos ENGINE=Aria; SET sql_log_bin=1; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect diff --git a/mysql-test/suite/rpl/t/rpl_mysql57_stm_temporal_round.test b/mysql-test/suite/rpl/t/rpl_mysql57_stm_temporal_round.test new file mode 100644 index 00000000000..675b7db0603 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mysql57_stm_temporal_round.test @@ -0,0 +1,58 @@ +--source include/have_binlog_format_statement.inc + +--echo # +--echo # MDEV-8894 Inserting fractional seconds into MySQL 5.6 master breaks consistency on MariaDB 10 slave +--echo # + +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection slave +CREATE TABLE t1 (id SERIAL, a DATETIME(3)); +--source include/stop_slave.inc + +--connection master +--let $datadir= `SELECT @@datadir` + +--let $rpl_server_number= 1 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master-bin.000001 + +# +# Simulate MySQL 5.7.x master +# +# mysql-5.7.11-stm-temporal-round-binlog.000001 was recorded against a +# table with this structure: +#CREATE TABLE t1 (id SERIAL, a DATETIME(3)); +# (note, the CREATE statement is not inside the binary log) +# +# using this command line: +# mysqld --log-bin --binlog-format=statement +# with the following single SQL statement: +# +#INSERT INTO t1 (a) VALUES ('2001-01-01 00:00:00.999999'); +# + +--copy_file $MYSQL_TEST_DIR/std_data/rpl/mysql-5.7.11-stm-temporal-round-binlog.000001 $datadir/master-bin.000001 + +--let $rpl_server_number= 1 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection slave +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4; + +--source include/start_slave.inc + +--connection master +--sync_slave_with_master +SELECT * FROM t1 ORDER BY id; + +--source include/stop_slave.inc +DROP TABLE t1; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mysql80_stm_temporal_round.test b/mysql-test/suite/rpl/t/rpl_mysql80_stm_temporal_round.test new file mode 100644 index 00000000000..ad6df9d9993 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_mysql80_stm_temporal_round.test @@ -0,0 +1,62 @@ +--source include/have_binlog_format_statement.inc + +--echo # +--echo # MDEV-8894 Inserting fractional seconds into MySQL 5.6 master breaks consistency on MariaDB 10 slave +--echo # + +--source include/have_innodb.inc +--source include/master-slave.inc + +--connection slave +CREATE TABLE t1 (id SERIAL, a DATETIME(3)); +--source include/stop_slave.inc + +--connection master +--let $datadir= `SELECT @@datadir` + +--let $rpl_server_number= 1 +--source include/rpl_stop_server.inc + +--remove_file $datadir/master-bin.000001 + +# +# Simulate MySQL 8.0.x master +# +# mysql-8.0.13-stm-temporal-round-binlog.000001 was recorded against a +# table with this structure: +#CREATE TABLE t1 (id SERIAL, a DATETIME(3)); +# (note, the CREATE statement is not inside the binary log) +# +# using this command line: +# mysqld --log-bin --binlog-format=statement --server-id=1 --character-set-server=latin1 +# with the following SQL script: +# +#SET NAMES latin1 COLLATE latin1_swedish_ci; +#SET sql_mode=''; +#INSERT INTO t1 (a) VALUES ('2001-01-01 00:00:00.999999'); +#SET sql_mode=TIME_TRUNCATE_FRACTIONAL; +#INSERT INTO t1 (a) VALUES ('2001-01-01 00:00:00.999999'); +# + +--copy_file $MYSQL_TEST_DIR/std_data/rpl/mysql-8.0.13-stm-temporal-round-binlog.000001 $datadir/master-bin.000001 + +--let $rpl_server_number= 1 +--source include/rpl_start_server.inc + +--source include/wait_until_connected_again.inc + +--connection slave +--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1 +eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4; + +--source include/start_slave.inc + +--connection master +--sync_slave_with_master +SELECT * FROM t1 ORDER BY id; + +--source include/stop_slave.inc +DROP TABLE t1; + +--let $rpl_only_running_threads= 1 +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test index e08472d5f51..0060cf4416c 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test @@ -21,6 +21,10 @@ SET GLOBAL slave_parallel_threads=10; CHANGE MASTER TO master_use_gtid=slave_pos; SET @old_parallel_mode=@@GLOBAL.slave_parallel_mode; SET GLOBAL slave_parallel_mode='optimistic'; +# Run the first part of the test with high batch size and see that +# old rows remain in the table. +SET @old_gtid_cleanup_batch_size= @@GLOBAL.gtid_cleanup_batch_size; +SET GLOBAL gtid_cleanup_batch_size= 1000000; --connection server_1 @@ -108,7 +112,12 @@ SELECT * FROM t3 ORDER BY c; SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; SELECT * FROM t3 ORDER BY c; -#SHOW STATUS LIKE 'Slave_retried_transactions'; +# Check that we have a bunch of old rows left-over - they were not deleted +# due to high @@gtid_cleanup_batch_size. Then set a low +# @@gtid_cleanup_batch_size so we can test that rows start being deleted. +SELECT IF(COUNT(*) >= 30, "OK", CONCAT("Error: too few old rows found: ", COUNT(*))) + FROM mysql.gtid_slave_pos; +SET GLOBAL gtid_cleanup_batch_size=1; --echo *** Test @@skip_parallel_replication. *** @@ -557,25 +566,18 @@ DROP TABLE t1, t2, t3; --connection server_2 --source include/sync_with_master_gtid.inc -# Check for left-over rows in table mysql.gtid_slave_pos (MDEV-12147). -# -# There was a bug when a transaction got a conflict and was rolled back. It -# might have also handled deletion of some old rows, and these deletions would -# then also be rolled back. And since the deletes were never re-tried, old no -# longer needed rows would accumulate in the table without limit. -# -# The earlier part of this test file have plenty of transactions being rolled -# back. But the last DROP TABLE statement runs on its own and should never -# conflict, thus at this point the mysql.gtid_slave_pos table should be clean. -# -# To support @@gtid_pos_auto_engines, when a row is inserted in the table, it -# is associated with the engine of the table at insertion time, and it will -# only be deleted during record_gtid from a table of the same engine. Since we -# alter the table from MyISAM to InnoDB at the start of this test, we should -# end up with 4 rows: two left-over from when the table was MyISAM, and two -# left-over from the InnoDB part. ---echo Check that no more than the expected last four GTIDs are in mysql.gtid_slave_pos -select count(4) <= 4 from mysql.gtid_slave_pos order by domain_id, sub_id; +# Check that old rows are deleted from mysql.gtid_slave_pos. +# Deletion is asynchronous, so use wait_condition.inc. +# Also, there is a small amount of non-determinism in the deletion of old +# rows, so it is not guaranteed that there can never be more than +# @@gtid_cleanup_batch_size rows in the table; so allow a bit of slack +# here. +let $wait_condition= + SELECT COUNT(*) <= 5*@@GLOBAL.gtid_cleanup_batch_size + FROM mysql.gtid_slave_pos; +--source include/wait_condition.inc +eval $wait_condition; +SET GLOBAL gtid_cleanup_batch_size= @old_gtid_cleanup_batch_size; --connection server_1 --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_001.test b/mysql-test/suite/rpl/t/rpl_row_001.test index 06d01f2476e..f66c61ffb6e 100644 --- a/mysql-test/suite/rpl/t/rpl_row_001.test +++ b/mysql-test/suite/rpl/t/rpl_row_001.test @@ -2,10 +2,50 @@ # By JBM 2005-02-15 Wrapped to allow reuse of test code# ######################################################## -- source include/have_binlog_format_row.inc -# Slow test, don't run during staging part --- source include/not_staging.inc -- source include/master-slave.inc -let $engine_type=MYISAM; --- source include/rpl_row_001.test +# Test if the slave SQL thread can be more than 16K behind the slave +# I/O thread (> IO_SIZE) + +# we'll use table-level locking to delay slave SQL thread +eval CREATE TABLE t1 (n INT); +sync_slave_with_master; +connection master; +RESET MASTER; +connection slave; +STOP SLAVE; +RESET SLAVE; + +connection master; +let $1=5000; +# Generate 16K of relay log +disable_query_log; +while ($1) +{ + eval INSERT INTO t1 VALUES($1); + dec $1; +} +enable_query_log; +SELECT COUNT(*) FROM t1; +save_master_pos; + +# Try to cause a large relay log lag on the slave by locking t1 +connection slave; +LOCK TABLES t1 READ; +START SLAVE; +UNLOCK TABLES; +sync_with_master; +SELECT COUNT(*) FROM t1; + +connection master; +DROP TABLE t1; +CREATE TABLE t1 (n INT); +INSERT INTO t1 VALUES(3456); +sync_slave_with_master; +SELECT n FROM t1; + +connection master; +DROP TABLE t1; + +sync_slave_with_master; --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_000001.test b/mysql-test/suite/rpl/t/rpl_stm_000001.test index 119fd6168e0..62b5c5b1cd0 100644 --- a/mysql-test/suite/rpl/t/rpl_stm_000001.test +++ b/mysql-test/suite/rpl/t/rpl_stm_000001.test @@ -4,7 +4,6 @@ -- source include/master-slave.inc CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); ---let $engine_type= myisam # Load some data into t1 create table t1 (word char(20) not null); @@ -19,7 +18,8 @@ select * from t1 limit 10; sync_slave_with_master; stop slave; connection master; -UPDATE mysql.user SET password=password('foo') WHERE host='localhost' AND user='root'; +create temporary table tmp select * from mysql.global_priv where host="localhost" and user="root"; +set password for root@"localhost" = password('foo'); connection slave; start slave; connection master; @@ -27,7 +27,9 @@ connection master; # Give slave time to do at last one failed connect retry # This one must be short so that the slave will not stop retrying real_sleep 2; -UPDATE mysql.user SET password=password('') WHERE host='localhost' AND user='root'; +replace into mysql.global_priv select * from tmp; +drop temporary table tmp; +flush privileges; # Give slave time to connect (will retry every second) sleep 2; @@ -45,7 +47,7 @@ sync_slave_with_master; connection master; # we'll use table-level locking to delay slave SQL thread -eval create table t1 (n int) engine=$engine_type; +eval create table t1 (n int); sync_slave_with_master; connection master; reset master; @@ -111,20 +113,6 @@ connection slave; select count(*) from t1; connection master1; drop table t1; -create table t1 (n int); -insert into t1 values(3456); -insert ignore into mysql.user (Host, User, Password) - VALUES ("10.10.10.%", "blafasel2", password("blafasel2")); -select select_priv,user from mysql.user where user = _binary'blafasel2'; -update mysql.user set Select_priv = "Y" where User= _binary"blafasel2"; -select select_priv,user from mysql.user where user = _binary'blafasel2'; -sync_slave_with_master; -select n from t1; -select select_priv,user from mysql.user where user = _binary'blafasel2'; -connection master1; -drop table t1; -delete from mysql.user where user="blafasel2"; -sync_slave_with_master; # End of 4.1 tests --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_temporal_round.test b/mysql-test/suite/rpl/t/rpl_temporal_round.test new file mode 100644 index 00000000000..c13c18bddb5 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temporal_round.test @@ -0,0 +1,35 @@ +--source include/master-slave.inc + +SET sql_mode=TIME_ROUND_FRACTIONAL; +SET time_zone='+00:00'; +SET timestamp=UNIX_TIMESTAMP('2010-12-31 23:59:59.999999'); + +CREATE TABLE t1 (id SERIAL, a TIMESTAMP(4)); +INSERT INTO t1 (a) VALUES (now(6)); +INSERT INTO t1 (a) VALUES ('2011-01-01 23:59:59.999999'); + +CREATE TABLE t2 (id SERIAL, a DATETIME(4)); +INSERT INTO t2 (a) VALUES (now(6)); +INSERT INTO t2 (a) VALUES ('2011-01-01 23:59:59.999999'); + +CREATE TABLE t3 (id SERIAL, a TIME(4)); +INSERT INTO t3 (a) VALUES (now(6)); +INSERT INTO t3 (a) VALUES ('2011-01-01 23:59:59.999999'); + +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +sync_slave_with_master; +connection slave; +SET time_zone='+00:00'; +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +connection master; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/sys_vars/r/innodb_fil_make_page_dirty_debug_basic.result b/mysql-test/suite/sys_vars/r/innodb_fil_make_page_dirty_debug_basic.result index abf2cdaf1c4..477eb7fcb61 100644 --- a/mysql-test/suite/sys_vars/r/innodb_fil_make_page_dirty_debug_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_fil_make_page_dirty_debug_basic.result @@ -17,6 +17,8 @@ ERROR HY000: Variable 'innodb_fil_make_page_dirty_debug' is a GLOBAL variable an create table t1 (f1 int primary key) engine = innodb; select space from information_schema.innodb_sys_tables where name = 'test/t1' into @space_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead set global innodb_saved_page_number_debug = 0; set global innodb_fil_make_page_dirty_debug = @space_id; drop table t1; diff --git a/mysql-test/suite/sys_vars/r/innodb_saved_page_number_debug_basic.result b/mysql-test/suite/sys_vars/r/innodb_saved_page_number_debug_basic.result index 20e2b78e640..b306749dcb0 100644 --- a/mysql-test/suite/sys_vars/r/innodb_saved_page_number_debug_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_saved_page_number_debug_basic.result @@ -17,6 +17,8 @@ ERROR HY000: Variable 'innodb_saved_page_number_debug' is a GLOBAL variable and create table t1 (f1 int primary key) engine = innodb; select space from information_schema.innodb_sys_tables where name = 'test/t1' into @space_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead set global innodb_saved_page_number_debug = 0; set global innodb_fil_make_page_dirty_debug = @space_id; drop table t1; diff --git a/mysql-test/suite/sys_vars/r/max_seeks_for_key_func.result b/mysql-test/suite/sys_vars/r/max_seeks_for_key_func.result index 1798bd5d6e0..f833f417290 100644 --- a/mysql-test/suite/sys_vars/r/max_seeks_for_key_func.result +++ b/mysql-test/suite/sys_vars/r/max_seeks_for_key_func.result @@ -70,6 +70,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 17 Using where; Using join buffer (flat, BNL join) ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SET MAX_SEEKS_FOR_KEY=1; EXPLAIN SELECT STRAIGHT_JOIN * FROM t1,t1 AS t2 WHERE t1.b = t2.b; diff --git a/mysql-test/suite/sys_vars/r/myisam_stats_method_func.result b/mysql-test/suite/sys_vars/r/myisam_stats_method_func.result index cae0e68765b..75fe06e2faf 100644 --- a/mysql-test/suite/sys_vars/r/myisam_stats_method_func.result +++ b/mysql-test/suite/sys_vars/r/myisam_stats_method_func.result @@ -20,6 +20,7 @@ INSERT INTO t1 SELECT NULL FROM t1; SET myisam_stats_method = nulls_unequal; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SHOW INDEX FROM t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -38,6 +39,7 @@ INSERT INTO t1 VALUES (11); DELETE FROM t1 WHERE a = 11; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SHOW INDEX FROM t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -49,7 +51,7 @@ Table Op Msg_type Msg_text test.t1 check status OK SHOW INDEX FROM t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment -t1 1 a 1 a A 5 NULL NULL YES BTREE +t1 1 a 1 a A 10 NULL NULL YES BTREE 'Set nulls to be ignored' SET myisam_stats_method = nulls_ignored; SHOW VARIABLES LIKE 'myisam_stats_method'; @@ -66,6 +68,7 @@ INSERT INTO t1 VALUES ('bce','def1', 'yuu', NULL); INSERT INTO t1 VALUES ('bce','def2', NULL, 'quux'); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SHOW INDEX FROM t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -76,6 +79,7 @@ t1 1 a 4 d A 4 NULL NULL YES BTREE DELETE FROM t1; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SHOW INDEX FROM t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result index 87c837986ac..bc22fe198a1 100644 --- a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result +++ b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result @@ -1,63 +1,63 @@ SET @start_global_value = @@global.optimizer_switch; SELECT @start_global_value; @start_global_value -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on select @@global.optimizer_switch; @@global.optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on select @@session.optimizer_switch; @@session.optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on show global variables like 'optimizer_switch'; Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on show session variables like 'optimizer_switch'; Variable_name Value -optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on select * from information_schema.global_variables where variable_name='optimizer_switch'; VARIABLE_NAME VARIABLE_VALUE -OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on select * from information_schema.session_variables where variable_name='optimizer_switch'; VARIABLE_NAME VARIABLE_VALUE -OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on set global optimizer_switch=10; set session optimizer_switch=5; select @@global.optimizer_switch; @@global.optimizer_switch -index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off +index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off select @@session.optimizer_switch; @@session.optimizer_switch -index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off +index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off set global optimizer_switch="index_merge_sort_union=on"; set session optimizer_switch="index_merge=off"; select @@global.optimizer_switch; @@global.optimizer_switch -index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off +index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off select @@session.optimizer_switch; @@session.optimizer_switch -index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off +index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off show global variables like 'optimizer_switch'; Variable_name Value -optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off +optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off show session variables like 'optimizer_switch'; Variable_name Value -optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off +optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off select * from information_schema.global_variables where variable_name='optimizer_switch'; VARIABLE_NAME VARIABLE_VALUE -OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off +OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off select * from information_schema.session_variables where variable_name='optimizer_switch'; VARIABLE_NAME VARIABLE_VALUE -OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off +OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off set session optimizer_switch="default"; select @@session.optimizer_switch; @@session.optimizer_switch -index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off +index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off set optimizer_switch = replace(@@optimizer_switch, '=off', '=on'); Warnings: Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release select @@optimizer_switch; @@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on set global optimizer_switch=1.1; ERROR 42000: Incorrect argument type to variable 'optimizer_switch' set global optimizer_switch=1e1; @@ -69,4 +69,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar' SET @@global.optimizer_switch = @start_global_value; SELECT @@global.optimizer_switch; @@global.optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on diff --git a/mysql-test/suite/sys_vars/r/optimizer_use_condition_selectivity_basic.result b/mysql-test/suite/sys_vars/r/optimizer_use_condition_selectivity_basic.result index a030bae3750..941b7699747 100644 --- a/mysql-test/suite/sys_vars/r/optimizer_use_condition_selectivity_basic.result +++ b/mysql-test/suite/sys_vars/r/optimizer_use_condition_selectivity_basic.result @@ -1,33 +1,33 @@ SET @start_global_value = @@global.optimizer_use_condition_selectivity; SELECT @start_global_value; @start_global_value -1 +4 SET @start_session_value = @@session.optimizer_use_condition_selectivity; SELECT @start_session_value; @start_session_value -1 +4 '#--------------------FN_DYNVARS_115_01-------------------------#' SET @@global.optimizer_use_condition_selectivity = DEFAULT; SELECT @@global.optimizer_use_condition_selectivity; @@global.optimizer_use_condition_selectivity -1 +4 SET @@session.optimizer_use_condition_selectivity = DEFAULT; SELECT @@session.optimizer_use_condition_selectivity; @@session.optimizer_use_condition_selectivity -1 +4 '#--------------------FN_DYNVARS_115_02-------------------------#' SET @@global.optimizer_use_condition_selectivity = DEFAULT; SELECT @@global.optimizer_use_condition_selectivity = 1; @@global.optimizer_use_condition_selectivity = 1 -1 +0 SET @@session.optimizer_use_condition_selectivity = DEFAULT; SELECT @@session.optimizer_use_condition_selectivity = 1; @@session.optimizer_use_condition_selectivity = 1 -1 +0 '#--------------------FN_DYNVARS_115_03-------------------------#' SELECT @@global.optimizer_use_condition_selectivity; @@global.optimizer_use_condition_selectivity -1 +4 SET @@global.optimizer_use_condition_selectivity = 0; Warnings: Warning 1292 Truncated incorrect optimizer_use_condition_selectiv value: '0' @@ -63,7 +63,7 @@ SELECT @@global.optimizer_use_condition_selectivity; '#--------------------FN_DYNVARS_115_04-------------------------#' SELECT @@session.optimizer_use_condition_selectivity; @@session.optimizer_use_condition_selectivity -1 +4 SET @@session.optimizer_use_condition_selectivity = 0; Warnings: Warning 1292 Truncated incorrect optimizer_use_condition_selectiv value: '0' @@ -134,8 +134,8 @@ SELECT @@local.optimizer_use_condition_selectivity = @@session.optimizer_use_con SET @@global.optimizer_use_condition_selectivity = @start_global_value; SELECT @@global.optimizer_use_condition_selectivity; @@global.optimizer_use_condition_selectivity -1 +4 SET @@session.optimizer_use_condition_selectivity = @start_session_value; SELECT @@session.optimizer_use_condition_selectivity; @@session.optimizer_use_condition_selectivity -1 +4 diff --git a/mysql-test/suite/sys_vars/r/secure_file_priv.result b/mysql-test/suite/sys_vars/r/secure_file_priv.result index eeeb9a58c0f..74f816df59d 100644 --- a/mysql-test/suite/sys_vars/r/secure_file_priv.result +++ b/mysql-test/suite/sys_vars/r/secure_file_priv.result @@ -6,6 +6,8 @@ INSERT INTO t1 VALUES ("one"),("two"),("three"),("four"),("five"); SHOW VARIABLES LIKE 'secure_file_priv'; Variable_name Value secure_file_priv +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead c1 one two diff --git a/mysql-test/suite/sys_vars/r/shared_memory_base_name_basic.result b/mysql-test/suite/sys_vars/r/shared_memory_base_name_basic.result deleted file mode 100644 index 356b3c9e879..00000000000 --- a/mysql-test/suite/sys_vars/r/shared_memory_base_name_basic.result +++ /dev/null @@ -1,21 +0,0 @@ -select @@global.shared_memory_base_name; -@@global.shared_memory_base_name -MYSQL_TMP_DIR/mysqld.1.sock -select @@session.shared_memory_base_name; -ERROR HY000: Variable 'shared_memory_base_name' is a GLOBAL variable -show global variables like 'shared_memory_base_name'; -Variable_name Value -shared_memory_base_name MYSQL_TMP_DIR/mysqld.1.sock -show session variables like 'shared_memory_base_name'; -Variable_name Value -shared_memory_base_name MYSQL_TMP_DIR/mysqld.1.sock -select * from information_schema.global_variables where variable_name='shared_memory_base_name'; -VARIABLE_NAME VARIABLE_VALUE -SHARED_MEMORY_BASE_NAME MYSQL_TMP_DIR/mysqld.1.sock -select * from information_schema.session_variables where variable_name='shared_memory_base_name'; -VARIABLE_NAME VARIABLE_VALUE -SHARED_MEMORY_BASE_NAME MYSQL_TMP_DIR/mysqld.1.sock -set global shared_memory_base_name=1; -ERROR HY000: Variable 'shared_memory_base_name' is a read only variable -set session shared_memory_base_name=1; -ERROR HY000: Variable 'shared_memory_base_name' is a read only variable diff --git a/mysql-test/suite/sys_vars/r/shared_memory_basic.result b/mysql-test/suite/sys_vars/r/shared_memory_basic.result deleted file mode 100644 index ab671af610c..00000000000 --- a/mysql-test/suite/sys_vars/r/shared_memory_basic.result +++ /dev/null @@ -1,21 +0,0 @@ -select @@global.shared_memory; -@@global.shared_memory -0 -select @@session.shared_memory; -ERROR HY000: Variable 'shared_memory' is a GLOBAL variable -show global variables like 'shared_memory'; -Variable_name Value -shared_memory OFF -show session variables like 'shared_memory'; -Variable_name Value -shared_memory OFF -select * from information_schema.global_variables where variable_name='shared_memory'; -VARIABLE_NAME VARIABLE_VALUE -SHARED_MEMORY OFF -select * from information_schema.session_variables where variable_name='shared_memory'; -VARIABLE_NAME VARIABLE_VALUE -SHARED_MEMORY OFF -set global shared_memory=1; -ERROR HY000: Variable 'shared_memory' is a read only variable -set session shared_memory=1; -ERROR HY000: Variable 'shared_memory' is a read only variable diff --git a/mysql-test/suite/sys_vars/r/sql_mode_basic.result b/mysql-test/suite/sys_vars/r/sql_mode_basic.result index a200f620a7c..d911e80b780 100644 --- a/mysql-test/suite/sys_vars/r/sql_mode_basic.result +++ b/mysql-test/suite/sys_vars/r/sql_mode_basic.result @@ -367,7 +367,15 @@ SELECT @@global.sql_mode; @@global.sql_mode REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT SET @@global.sql_mode = 17179869184; -ERROR 42000: Variable 'sql_mode' can't be set to the value of '17179869184' +SELECT @@global.sql_mode; +@@global.sql_mode +TIME_ROUND_FRACTIONAL +SET @@global.sql_mode = 34359738367; +SELECT @@global.sql_mode; +@@global.sql_mode +REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT,TIME_ROUND_FRACTIONAL +SET @@global.sql_mode = 34359738368; +ERROR 42000: Variable 'sql_mode' can't be set to the value of '34359738368' SET @@global.sql_mode = 0.4; ERROR 42000: Incorrect argument type to variable 'sql_mode' '#---------------------FN_DYNVARS_152_08----------------------#' diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index efc380a396b..1dac71788bd 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -2715,24 +2715,24 @@ ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SWITCH -SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on -GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on +GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on VARIABLE_SCOPE SESSION VARIABLE_TYPE FLAGSET VARIABLE_COMMENT Fine-tune the optimizer behavior NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default +ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY -SESSION_VALUE 1 -GLOBAL_VALUE 1 +SESSION_VALUE 4 +GLOBAL_VALUE 4 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 1 +DEFAULT_VALUE 4 VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples @@ -3066,9 +3066,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 200 +GLOBAL_VALUE 201 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 200 +DEFAULT_VALUE 201 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. @@ -3845,7 +3845,7 @@ VARIABLE_COMMENT Sets the sql mode NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT +ENUM_VALUE_LIST REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT,TIME_ROUND_FRACTIONAL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SQL_NOTES @@ -4226,6 +4226,20 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME TCP_NODELAY +SESSION_VALUE ON +GLOBAL_VALUE ON +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE ON +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Set option TCP_NODELAY (disable Nagle's algorithm) on socket +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME THREAD_CACHE_SIZE SESSION_VALUE NULL GLOBAL_VALUE 151 @@ -4493,17 +4507,17 @@ ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME USE_STAT_TABLES -SESSION_VALUE NEVER -GLOBAL_VALUE NEVER -GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE NEVER +SESSION_VALUE PREFERABLY +GLOBAL_VALUE PREFERABLY +GLOBAL_VALUE_ORIGIN CONFIG +DEFAULT_VALUE PREFERABLY_FOR_QUERIES VARIABLE_SCOPE SESSION VARIABLE_TYPE ENUM VARIABLE_COMMENT Specifies how to use system statistics tables NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NEVER,COMPLEMENTARY,PREFERABLY +ENUM_VALUE_LIST NEVER,COMPLEMENTARY,PREFERABLY,COMPLEMENTARY_FOR_QUERIES,PREFERABLY_FOR_QUERIES READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME WAIT_TIMEOUT diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 47df962b7c4..4c9b38c48b7 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -1202,6 +1202,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT NULL +VARIABLE_NAME GTID_CLEANUP_BATCH_SIZE +SESSION_VALUE NULL +GLOBAL_VALUE 64 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 64 +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE INT UNSIGNED +VARIABLE_COMMENT Normally does not need tuning. How many old rows must accumulate in the mysql.gtid_slave_pos table before a background job will be run to delete them. Can be increased to reduce number of commits if using many different engines with --gtid_pos_auto_engines, or to reduce CPU overhead if using a huge number of different gtid_domain_ids. Can be decreased to reduce number of old rows in the table. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 2147483647 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME GTID_CURRENT_POS SESSION_VALUE NULL GLOBAL_VALUE @@ -2925,24 +2939,24 @@ ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_SWITCH -SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on -GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on +GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on VARIABLE_SCOPE SESSION VARIABLE_TYPE FLAGSET VARIABLE_COMMENT Fine-tune the optimizer behavior NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default +ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY -SESSION_VALUE 1 -GLOBAL_VALUE 1 +SESSION_VALUE 4 +GLOBAL_VALUE 4 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 1 +DEFAULT_VALUE 4 VARIABLE_SCOPE SESSION VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples @@ -3276,9 +3290,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 200 +GLOBAL_VALUE 201 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 200 +DEFAULT_VALUE 201 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. @@ -4755,7 +4769,7 @@ VARIABLE_COMMENT Sets the sql mode NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT +ENUM_VALUE_LIST REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,IGNORE_BAD_TABLE_OPTIONS,ONLY_FULL_GROUP_BY,NO_UNSIGNED_SUBTRACTION,NO_DIR_IN_CREATE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,MYSQL323,MYSQL40,ANSI,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,HIGH_NOT_PRECEDENCE,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH,EMPTY_STRING_IS_NULL,SIMULTANEOUS_ASSIGNMENT,TIME_ROUND_FRACTIONAL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SQL_NOTES @@ -5178,6 +5192,20 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME TCP_NODELAY +SESSION_VALUE ON +GLOBAL_VALUE ON +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE ON +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Set option TCP_NODELAY (disable Nagle's algorithm) on socket +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME THREAD_CACHE_SIZE SESSION_VALUE NULL GLOBAL_VALUE 151 @@ -5543,17 +5571,17 @@ ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME USE_STAT_TABLES -SESSION_VALUE NEVER -GLOBAL_VALUE NEVER -GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE NEVER +SESSION_VALUE PREFERABLY +GLOBAL_VALUE PREFERABLY +GLOBAL_VALUE_ORIGIN CONFIG +DEFAULT_VALUE PREFERABLY_FOR_QUERIES VARIABLE_SCOPE SESSION VARIABLE_TYPE ENUM VARIABLE_COMMENT Specifies how to use system statistics tables NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST NEVER,COMPLEMENTARY,PREFERABLY +ENUM_VALUE_LIST NEVER,COMPLEMENTARY,PREFERABLY,COMPLEMENTARY_FOR_QUERIES,PREFERABLY_FOR_QUERIES READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME WAIT_TIMEOUT diff --git a/mysql-test/suite/sys_vars/r/tcp_nodelay.result b/mysql-test/suite/sys_vars/r/tcp_nodelay.result new file mode 100644 index 00000000000..ebb027e8cf6 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/tcp_nodelay.result @@ -0,0 +1,5 @@ +SET tcp_nodelay=0; +SET tcp_nodelay=1; +SET tcp_nodelay=default; +SET GLOBAL tcp_nodelay=0; +ERROR HY000: Variable 'tcp_nodelay' is a SESSION variable diff --git a/mysql-test/suite/sys_vars/r/use_stat_tables_basic.result b/mysql-test/suite/sys_vars/r/use_stat_tables_basic.result index 64f6d868fa6..1de75b65caf 100644 --- a/mysql-test/suite/sys_vars/r/use_stat_tables_basic.result +++ b/mysql-test/suite/sys_vars/r/use_stat_tables_basic.result @@ -1,16 +1,16 @@ SET @start_global_value = @@global.use_stat_tables; SELECT @start_global_value; @start_global_value -NEVER +PREFERABLY SET @start_session_value = @@session.use_stat_tables; SELECT @start_session_value; @start_session_value -NEVER +PREFERABLY SET @@global.use_stat_tables = 2; SET @@global.use_stat_tables = DEFAULT; SELECT @@global.use_stat_tables; @@global.use_stat_tables -NEVER +PREFERABLY_FOR_QUERIES SET @@global.use_stat_tables = 0; SELECT @@global.use_stat_tables; @@global.use_stat_tables @@ -87,9 +87,9 @@ USE_STAT_TABLES COMPLEMENTARY SET @@global.use_stat_tables = @start_global_value; SELECT @@global.use_stat_tables; @@global.use_stat_tables -NEVER +PREFERABLY SET @@session.use_stat_tables = @start_session_value; SELECT @@session.use_stat_tables; @@session.use_stat_tables -NEVER +PREFERABLY set sql_mode=''; diff --git a/mysql-test/suite/sys_vars/t/shared_memory_base_name_basic.test b/mysql-test/suite/sys_vars/t/shared_memory_base_name_basic.test deleted file mode 100644 index da165564791..00000000000 --- a/mysql-test/suite/sys_vars/t/shared_memory_base_name_basic.test +++ /dev/null @@ -1,25 +0,0 @@ ---source include/windows.inc ---source include/not_embedded.inc -# -# only global -# ---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR -select @@global.shared_memory_base_name; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -select @@session.shared_memory_base_name; ---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR -show global variables like 'shared_memory_base_name'; ---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR -show session variables like 'shared_memory_base_name'; ---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR -select * from information_schema.global_variables where variable_name='shared_memory_base_name'; ---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR -select * from information_schema.session_variables where variable_name='shared_memory_base_name'; - -# -# show that it's read-only -# ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set global shared_memory_base_name=1; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set session shared_memory_base_name=1; diff --git a/mysql-test/suite/sys_vars/t/shared_memory_basic.test b/mysql-test/suite/sys_vars/t/shared_memory_basic.test deleted file mode 100644 index 57be4ef7ecd..00000000000 --- a/mysql-test/suite/sys_vars/t/shared_memory_basic.test +++ /dev/null @@ -1,20 +0,0 @@ ---source include/windows.inc ---source include/not_embedded.inc -# -# only global -# -select @@global.shared_memory; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -select @@session.shared_memory; -show global variables like 'shared_memory'; -show session variables like 'shared_memory'; -select * from information_schema.global_variables where variable_name='shared_memory'; -select * from information_schema.session_variables where variable_name='shared_memory'; - -# -# show that it's read-only -# ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set global shared_memory=1; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set session shared_memory=1; diff --git a/mysql-test/suite/sys_vars/t/sql_mode_basic.test b/mysql-test/suite/sys_vars/t/sql_mode_basic.test index b4841ecd3ff..68be8ba969b 100644 --- a/mysql-test/suite/sys_vars/t/sql_mode_basic.test +++ b/mysql-test/suite/sys_vars/t/sql_mode_basic.test @@ -310,8 +310,14 @@ SELECT @@global.sql_mode; SET @@global.sql_mode = 17179869183; SELECT @@global.sql_mode; ---Error ER_WRONG_VALUE_FOR_VAR SET @@global.sql_mode = 17179869184; +SELECT @@global.sql_mode; + +SET @@global.sql_mode = 34359738367; +SELECT @@global.sql_mode; + +--Error ER_WRONG_VALUE_FOR_VAR +SET @@global.sql_mode = 34359738368; # use of decimal values diff --git a/mysql-test/suite/sys_vars/t/tcp_nodelay.test b/mysql-test/suite/sys_vars/t/tcp_nodelay.test new file mode 100644 index 00000000000..780bad68039 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/tcp_nodelay.test @@ -0,0 +1,7 @@ +--source include/not_embedded.inc +# A smoke test for tcp_nodelay option +SET tcp_nodelay=0; +SET tcp_nodelay=1; +SET tcp_nodelay=default; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SET GLOBAL tcp_nodelay=0; diff --git a/mysql-test/suite/vcol/r/update.result b/mysql-test/suite/vcol/r/update.result index 5a6355e1773..5b67c9dd0f7 100644 --- a/mysql-test/suite/vcol/r/update.result +++ b/mysql-test/suite/vcol/r/update.result @@ -122,7 +122,7 @@ select * from t; a b c d e 10 5 5 5 5 replace delayed t (a,b,d) values (10,6,6); -flush tables; +flush tables t; check table t; Table Op Msg_type Msg_text test.t check status OK @@ -130,7 +130,7 @@ select * from t; a b c d e 10 6 6 6 6 insert delayed t(a,b,d) values (10,6,6) on duplicate key update b=7, d=7; -flush tables; +flush tables t; check table t; Table Op Msg_type Msg_text test.t check status OK diff --git a/mysql-test/suite/vcol/r/update_binlog.result b/mysql-test/suite/vcol/r/update_binlog.result index d4102fc460a..c29200513b0 100644 --- a/mysql-test/suite/vcol/r/update_binlog.result +++ b/mysql-test/suite/vcol/r/update_binlog.result @@ -124,7 +124,7 @@ select * from t; a b c d e 10 5 5 5 5 replace delayed t (a,b,d) values (10,6,6); -flush tables; +flush tables t; check table t; Table Op Msg_type Msg_text test.t check status OK @@ -132,7 +132,7 @@ select * from t; a b c d e 10 6 6 6 6 insert delayed t(a,b,d) values (10,6,6) on duplicate key update b=7, d=7; -flush tables; +flush tables t; check table t; Table Op Msg_type Msg_text test.t check status OK @@ -304,7 +304,7 @@ select * from t; a b c d e 10 5 5 5 5 replace delayed t (a,b,d) values (10,6,6); -flush tables; +flush tables t; check table t; Table Op Msg_type Msg_text test.t check status OK @@ -312,7 +312,7 @@ select * from t; a b c d e 10 6 6 6 6 insert delayed t(a,b,d) values (10,6,6) on duplicate key update b=7, d=7; -flush tables; +flush tables t; check table t; Table Op Msg_type Msg_text test.t check status OK diff --git a/mysql-test/suite/vcol/r/vcol_keys_myisam.result b/mysql-test/suite/vcol/r/vcol_keys_myisam.result index bd013da9b03..0b257d12ca0 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_keys_myisam.result @@ -277,6 +277,7 @@ a b c d delete from t1 where b=12; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result index f3edfa9c026..9eb4616949c 100644 --- a/mysql-test/suite/vcol/r/vcol_misc.result +++ b/mysql-test/suite/vcol/r/vcol_misc.result @@ -182,16 +182,36 @@ a b c 2 3 y 0 1 y,n drop table t1,t2; -CREATE TABLE t1 ( +SET @old_debug= @@global.debug; +SET @old_debug= @@global.debug; +SET GLOBAL debug_dbug= "+d,write_delay_wakeup"; +CREATE TABLE t1 (a int, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, tsv TIMESTAMP AS (ADDDATE(ts, INTERVAL 1 DAY)) VIRTUAL ) ENGINE=MyISAM; -INSERT INTO t1 (tsv) VALUES (DEFAULT); -INSERT DELAYED INTO t1 (tsv) VALUES (DEFAULT); +# First test FLUSH TABLES +INSERT INTO t1 (a,tsv) VALUES (1,DEFAULT); +INSERT DELAYED INTO t1 (a,tsv) VALUES (2,DEFAULT); FLUSH TABLES; +SELECT COUNT(*) > 0 FROM t1; +COUNT(*) > 0 +1 +# Then test FLUSH TABLES t1; +INSERT INTO t1 (a,tsv) VALUES (3,DEFAULT); +INSERT DELAYED INTO t1 (a,tsv) VALUES (4,DEFAULT); +FLUSH TABLES t1; +SELECT COUNT(*) FROM t1; +COUNT(*) +4 +# Then test FLUSH TABLES WITH READ LOCK; +INSERT INTO t1 (a,tsv) VALUES (5,DEFAULT); +INSERT DELAYED INTO t1 (a,tsv) VALUES (6,DEFAULT); +FLUSH TABLES WITH READ LOCK; SELECT COUNT(*) FROM t1; COUNT(*) -2 +6 +set GLOBAL debug_dbug= @old_debug; +unlock tables; DROP TABLE t1; # # MDEV-4823 Server crashes in Item_func_not::fix_fields on diff --git a/mysql-test/suite/vcol/r/wrong_arena.result b/mysql-test/suite/vcol/r/wrong_arena.result index c105a069b7f..cd36801f601 100644 --- a/mysql-test/suite/vcol/r/wrong_arena.result +++ b/mysql-test/suite/vcol/r/wrong_arena.result @@ -7,9 +7,9 @@ d int as ((a,a) in ((1,1),(2,1),(NULL,1))), # cmp_item_datetime e int as ((a,1) in ((1,1),(2,1),(NULL,1))) # cmp_item_row::alloc_comparators() ); Warnings: -Warning 1292 Incorrect datetime value: '1' -Warning 1292 Incorrect datetime value: '2' -Warning 1292 Incorrect datetime value: '3' +Warning 1292 Truncated incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '2' +Warning 1292 Truncated incorrect datetime value: '3' show create table t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -20,21 +20,21 @@ t1 CREATE TABLE `t1` ( `e` int(11) GENERATED ALWAYS AS ((`a`,1) in ((1,1),(2,1),(NULL,1))) VIRTUAL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 Warnings: -Warning 1292 Incorrect datetime value: '1' -Warning 1292 Incorrect datetime value: '2' -Warning 1292 Incorrect datetime value: '3' +Warning 1292 Truncated incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '2' +Warning 1292 Truncated incorrect datetime value: '3' connect con1, localhost, root; insert t1 (a) values ('2010-10-10 10:10:10'); select * from t1; a b c d e 2010-10-10 10:10:10 1 0 0 NULL Warnings: -Warning 1292 Incorrect datetime value: '1' -Warning 1292 Incorrect datetime value: '1' -Warning 1292 Incorrect datetime value: '2' -Warning 1292 Incorrect datetime value: '1' -Warning 1292 Incorrect datetime value: '1' -Warning 1292 Incorrect datetime value: '2' +Warning 1292 Truncated incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '2' +Warning 1292 Truncated incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '2' disconnect con1; connection default; select * from t1; @@ -50,14 +50,14 @@ select * from t1; a b 2010-10-10 10:10:10 0000-00-00 00:00:00 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' disconnect con1; connection default; select * from t1; a b 2010-10-10 10:10:10 0000-00-00 00:00:00 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' drop table t1; create table t1 ( id int not null , diff --git a/mysql-test/suite/vcol/t/update.test b/mysql-test/suite/vcol/t/update.test index 53189ee3219..e1351986968 100644 --- a/mysql-test/suite/vcol/t/update.test +++ b/mysql-test/suite/vcol/t/update.test @@ -93,10 +93,10 @@ check table t; select * from t; insert t(a,b,d) select 10,4,4 on duplicate key update b=5, d=5; check table t; select * from t; replace delayed t (a,b,d) values (10,6,6); -flush tables; +flush tables t; check table t; select * from t; insert delayed t(a,b,d) values (10,6,6) on duplicate key update b=7, d=7; -flush tables; +flush tables t; check table t; select * from t; --write_file $MYSQLTEST_VARDIR/tmp/vblobs.txt 10 8 foo 8 foo diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index b351e1eb4a6..95b707e3e12 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -1,4 +1,5 @@ --source include/have_ucs2.inc +--source include/have_debug.inc let $MYSQLD_DATADIR= `select @@datadir`; @@ -184,19 +185,35 @@ drop table t1,t2; # Bug mdev-3938: INSERT DELAYED for a table with virtual columns # -CREATE TABLE t1 ( +SET @old_debug= @@global.debug; +SET @old_debug= @@global.debug; +SET GLOBAL debug_dbug= "+d,write_delay_wakeup"; +CREATE TABLE t1 (a int, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, tsv TIMESTAMP AS (ADDDATE(ts, INTERVAL 1 DAY)) VIRTUAL ) ENGINE=MyISAM; -INSERT INTO t1 (tsv) VALUES (DEFAULT); - -INSERT DELAYED INTO t1 (tsv) VALUES (DEFAULT); - +--echo # First test FLUSH TABLES +INSERT INTO t1 (a,tsv) VALUES (1,DEFAULT); +INSERT DELAYED INTO t1 (a,tsv) VALUES (2,DEFAULT); FLUSH TABLES; +# Count may be 1 or 2, depending on FLUSH happened before or after delayed +SELECT COUNT(*) > 0 FROM t1; +--echo # Then test FLUSH TABLES t1; +INSERT INTO t1 (a,tsv) VALUES (3,DEFAULT); +INSERT DELAYED INTO t1 (a,tsv) VALUES (4,DEFAULT); +FLUSH TABLES t1; SELECT COUNT(*) FROM t1; +--echo # Then test FLUSH TABLES WITH READ LOCK; + +INSERT INTO t1 (a,tsv) VALUES (5,DEFAULT); +INSERT DELAYED INTO t1 (a,tsv) VALUES (6,DEFAULT); +FLUSH TABLES WITH READ LOCK; +SELECT COUNT(*) FROM t1; +set GLOBAL debug_dbug= @old_debug; +unlock tables; DROP TABLE t1; --echo # diff --git a/mysql-test/suite/versioning/r/alter.result b/mysql-test/suite/versioning/r/alter.result index f1637d79543..350ebf260ac 100644 --- a/mysql-test/suite/versioning/r/alter.result +++ b/mysql-test/suite/versioning/r/alter.result @@ -195,6 +195,8 @@ a 2 1 select row_start from t where a=3 into @tm; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead alter table t add column b int; select @tm=row_start from t where a=3; @tm=row_start @@ -525,7 +527,7 @@ ERROR HY000: Table `t` is already system-versioned use mysql; create or replace table t (x int) with system versioning; ERROR HY000: System versioning tables in the `mysql` database are not suported -alter table user add system versioning; +alter table db add system versioning; ERROR HY000: System versioning tables in the `mysql` database are not suported use test; # MDEV-15956 Strange ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN upon ALTER on versioning column diff --git a/mysql-test/suite/versioning/r/commit_id.result b/mysql-test/suite/versioning/r/commit_id.result index abf2eaf91ba..8815613292e 100644 --- a/mysql-test/suite/versioning/r/commit_id.result +++ b/mysql-test/suite/versioning/r/commit_id.result @@ -10,6 +10,8 @@ insert into t1 values (); set @ts0= now(6); insert into t1 values (); select sys_trx_start from t1 where id = last_insert_id() into @tx0; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select transaction_id = @tx0 from mysql.transaction_registry order by transaction_id desc limit 1; transaction_id = @tx0 @@ -17,6 +19,8 @@ transaction_id = @tx0 set @ts1= now(6); insert into t1 values (); select sys_trx_start from t1 where id = last_insert_id() into @tx1; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select transaction_id = @tx1 from mysql.transaction_registry order by transaction_id desc limit 1; transaction_id = @tx1 @@ -24,6 +28,8 @@ transaction_id = @tx1 set @ts2= now(6); insert into t1 values (); select sys_trx_start from t1 where id = last_insert_id() into @tx2; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select transaction_id = @tx2 from mysql.transaction_registry order by transaction_id desc limit 1; transaction_id = @tx2 @@ -66,24 +72,32 @@ trt_trx_sees(0, @tx2) set transaction isolation level read uncommitted; insert into t1 values (); select sys_trx_start from t1 where id = last_insert_id() into @tx3; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select isolation_level = 'READ-UNCOMMITTED' from mysql.transaction_registry where transaction_id = @tx3; isolation_level = 'READ-UNCOMMITTED' 1 set transaction isolation level read committed; insert into t1 values (); select sys_trx_start from t1 where id = last_insert_id() into @tx4; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select isolation_level = 'READ-COMMITTED' from mysql.transaction_registry where transaction_id = @tx4; isolation_level = 'READ-COMMITTED' 1 set transaction isolation level serializable; insert into t1 values (); select sys_trx_start from t1 where id = last_insert_id() into @tx5; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select isolation_level = 'SERIALIZABLE' from mysql.transaction_registry where transaction_id = @tx5; isolation_level = 'SERIALIZABLE' 1 set transaction isolation level repeatable read; insert into t1 values (); select sys_trx_start from t1 where id = last_insert_id() into @tx6; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select isolation_level = 'REPEATABLE-READ' from mysql.transaction_registry where transaction_id = @tx6; isolation_level = 'REPEATABLE-READ' 1 diff --git a/mysql-test/suite/versioning/r/create.result b/mysql-test/suite/versioning/r/create.result index 231aae66482..18fe74d8171 100644 --- a/mysql-test/suite/versioning/r/create.result +++ b/mysql-test/suite/versioning/r/create.result @@ -273,8 +273,12 @@ t3 CREATE TABLE `t3` ( ## For versioned table insert into t1 values (1); select row_start from t1 into @row_start; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead insert into t0 (y) values (2); select st from t0 into @st; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead create or replace table t2 with system versioning as select * from t1; show create table t2; Table Create Table @@ -337,8 +341,12 @@ ERROR 42S21: Duplicate column name 'row_end' # Prepare checking for historical row delete from t1; select row_end from t1 for system_time all into @row_end; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead delete from t0; select en from t0 for system_time all into @en; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead ## Combinations of versioned + non-versioned create or replace table t2 (y int); insert into t2 values (3); @@ -359,10 +367,14 @@ insert into t2 (y) values (1), (2); delete from t2 where y = 2; create or replace table t3 select * from t2 for system_time all; select st, en from t3 where y = 1 into @st, @en; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select y from t2 for system_time all where st = @st and en = @en; y 1 select st, en from t3 where y = 2 into @st, @en; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select y from t2 for system_time all where st = @st and en = @en; y 2 diff --git a/mysql-test/suite/versioning/r/cte.result b/mysql-test/suite/versioning/r/cte.result index fc070a70120..44135a83eb6 100644 --- a/mysql-test/suite/versioning/r/cte.result +++ b/mysql-test/suite/versioning/r/cte.result @@ -138,7 +138,7 @@ where e.mgr = a.emp_id select name from emp where emp_id in (select emp_id from ancestors for system_time as of timestamp @ts_1); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 4 100.00 -1 PRIMARY emp ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join) +1 PRIMARY emp ALL PRIMARY NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) 4 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 4 100.00 2 DERIVED e ALL NULL NULL NULL NULL 4 100.00 Using where 3 RECURSIVE UNION e ALL mgr-fk NULL NULL NULL 4 100.00 Using where diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result index edf5632f027..8169ddeaa92 100644 --- a/mysql-test/suite/versioning/r/foreign.result +++ b/mysql-test/suite/versioning/r/foreign.result @@ -266,6 +266,8 @@ on update cascade ) engine=innodb; insert into parent (value) values (23); select id, value from parent into @id, @value; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead insert into child values (default, @id, @value); insert into subchild values (default, @id, @value); select parent_id from subchild; diff --git a/mysql-test/suite/versioning/r/insert.result b/mysql-test/suite/versioning/r/insert.result index 01d829d3430..2645d0184e8 100644 --- a/mysql-test/suite/versioning/r/insert.result +++ b/mysql-test/suite/versioning/r/insert.result @@ -54,6 +54,8 @@ drop view vt1_1; create or replace table t1( id bigint primary key, a int, b int) with system versioning; insert into t1 values(1, 1, 1); select row_start, row_end from t1 into @sys_start, @sys_end; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select id, a, b from t1; id a b 1 1 1 diff --git a/mysql-test/suite/versioning/r/load_data.result b/mysql-test/suite/versioning/r/load_data.result index 5e7b36c9a6a..1fcde73e565 100644 --- a/mysql-test/suite/versioning/r/load_data.result +++ b/mysql-test/suite/versioning/r/load_data.result @@ -1,6 +1,8 @@ CREATE TABLE t1 (a INT, b INT, c INT, vc INT AS (c), UNIQUE(a), UNIQUE(b)) WITH SYSTEM VERSIONING; INSERT IGNORE INTO t1 (a,b,c) VALUES (1,2,3); SELECT a, b, c FROM t1 INTO OUTFILE '15330.data'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead LOAD DATA INFILE '15330.data' IGNORE INTO TABLE t1 (a,b,c); Warnings: Warning 1062 Duplicate entry '1' for key 'a' diff --git a/mysql-test/suite/versioning/r/online.result b/mysql-test/suite/versioning/r/online.result index 21441acb6b2..580500544d6 100644 --- a/mysql-test/suite/versioning/r/online.result +++ b/mysql-test/suite/versioning/r/online.result @@ -112,5 +112,17 @@ update t set b=11; select count(*) from t for system_time all; count(*) 2 +# Start of 10.4 tests +create or replace table t (a int, b int) engine=innodb; +alter table t +add s bigint unsigned as row start, +add e bigint unsigned as row end, +add period for system_time(s, e), +add system versioning; +alter table t drop column b, algorithm=instant; +alter table t add index idx(a), lock=none; +alter table t drop column s, drop column e; +alter table t drop system versioning, lock=none; +ERROR 0A000: LOCK=NONE is not supported. Reason: Not implemented for system-versioned operations. Try LOCK=SHARED drop database test; create database test; diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index bfec0ce2d4b..f5106e03a14 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -139,6 +139,8 @@ x C D 1 1 1 set @str= concat('select row_start from t1 partition (pn) into @ts0'); prepare stmt from @str; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead execute stmt; drop prepare stmt; set @now= now(6); @@ -150,6 +152,8 @@ execute select_pn; x C D set @str= concat('select row_start from t1 partition (p0) into @ts1'); prepare stmt from @str; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead execute stmt; drop prepare stmt; select @ts0 = @ts1; @@ -165,6 +169,8 @@ x C D 2 1 1 set @str= concat('select row_start from t1 partition (pn) into @ts0'); prepare stmt from @str; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead execute stmt; drop prepare stmt; set @now= now(6); @@ -180,14 +186,20 @@ drop prepare select_p0; drop prepare select_pn; set @str= concat('select row_start from t1 partition (p0) where x = 2 into @ts1'); prepare stmt from @str; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead execute stmt; drop prepare stmt; set @str= concat('select row_end from t1 partition (p0) where x = 2 into @ts2'); prepare stmt from @str; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead execute stmt; drop prepare stmt; set @str= concat('select row_start from t1 partition (pn) into @ts3'); prepare stmt from @str; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead execute stmt; drop prepare stmt; select @ts0 = @ts1; @@ -349,6 +361,8 @@ create or replace table t2 (f int); create or replace trigger tr before insert on t2 for each row select table_rows from information_schema.tables where table_name = 't1' into @a; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead insert into t2 values (1); # MDEV-14740 Locking assertion for system_time partitioning create or replace table t1 (i int) with system versioning @@ -358,6 +372,8 @@ partition pn current); create or replace table t2 (f int); create or replace trigger tr before insert on t2 for each row select count(*) from t1 into @a; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead insert into t2 values (1); # MDEV-14741 Assertion `(trx)->start_file == 0' failed in row_truncate_table_for_mysql() create or replace table t1 (i int) with system versioning @@ -419,7 +435,7 @@ partition_name partition_ordinal_position partition_method timediff(partition_de p0 1 SYSTEM_TIME 00:00:00.000000 pn 2 SYSTEM_TIME NULL Warnings: -Warning 1292 Truncated incorrect time value: 'CURRENT' +Warning 1292 Incorrect time value: 'CURRENT' alter table t1 add partition (partition p1 history, partition p2 history); select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1'; partition_name partition_ordinal_position partition_method timediff(partition_description, @ts) @@ -428,7 +444,7 @@ p1 2 SYSTEM_TIME 01:00:00.000000 p2 3 SYSTEM_TIME 02:00:00.000000 pn 4 SYSTEM_TIME NULL Warnings: -Warning 1292 Truncated incorrect time value: 'CURRENT' +Warning 1292 Incorrect time value: 'CURRENT' alter table t1 drop partition p0; select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1'; partition_name partition_ordinal_position partition_method timediff(partition_description, @ts) @@ -436,7 +452,7 @@ p1 1 SYSTEM_TIME 01:00:00.000000 p2 2 SYSTEM_TIME 02:00:00.000000 pn 3 SYSTEM_TIME NULL Warnings: -Warning 1292 Truncated incorrect time value: 'CURRENT' +Warning 1292 Incorrect time value: 'CURRENT' alter table t1 drop partition p2; ERROR HY000: Can only drop oldest partitions when rotating by INTERVAL select partition_name,partition_ordinal_position,partition_method,timediff(partition_description, @ts) from information_schema.partitions where table_schema='test' and table_name='t1'; @@ -445,7 +461,7 @@ p1 1 SYSTEM_TIME 01:00:00.000000 p2 2 SYSTEM_TIME 02:00:00.000000 pn 3 SYSTEM_TIME NULL Warnings: -Warning 1292 Truncated incorrect time value: 'CURRENT' +Warning 1292 Incorrect time value: 'CURRENT' # # MDEV-15103 Assertion in ha_partition::part_records() for updating VIEW # diff --git a/mysql-test/suite/versioning/r/select,trx_id.rdiff b/mysql-test/suite/versioning/r/select,trx_id.rdiff new file mode 100644 index 00000000000..8906007a348 --- /dev/null +++ b/mysql-test/suite/versioning/r/select,trx_id.rdiff @@ -0,0 +1,11 @@ +--- select.result 2018-06-29 18:09:17.962447067 +0200 ++++ select.reject 2018-06-29 18:10:04.618808616 +0200 +@@ -17,6 +17,8 @@ + (8, 108), + (9, 109); + set @t0= now(6); ++Warnings: ++Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead + delete from t1 where x = 3; + delete from t1 where x > 7; + insert into t1(x, y) values(3, 33); diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result index be0781af002..be471ab8f30 100644 --- a/mysql-test/suite/versioning/r/select.result +++ b/mysql-test/suite/versioning/r/select.result @@ -21,6 +21,8 @@ delete from t1 where x = 3; delete from t1 where x > 7; insert into t1(x, y) values(3, 33); select sys_trx_start from t1 where x = 3 and y = 33 into @t1; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select x, y from t1; x y 0 100 @@ -330,6 +332,8 @@ insert into t1 values (1); set @ts= now(6); delete from t1; select sys_trx_start from t1 for system_time all into @trx_start; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead ## ensure @trx_start is much lower than unix timestamp select @trx_start < unix_timestamp(@ts) - 100 as trx_start_good; trx_start_good @@ -526,7 +530,11 @@ period for system_time (row_start, row_end) insert into t1 values (1); delete from t1; select row_start from t1 for system_time all into @t1; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select row_end from t1 for system_time all into @t2; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select * from t1 for system_time between @t1 and @t2; a 1 diff --git a/mysql-test/suite/versioning/r/select2,trx_id.rdiff b/mysql-test/suite/versioning/r/select2,trx_id.rdiff index a657b94c031..d23eb5afbc0 100644 --- a/mysql-test/suite/versioning/r/select2,trx_id.rdiff +++ b/mysql-test/suite/versioning/r/select2,trx_id.rdiff @@ -1,15 +1,15 @@ ---- select2.result -+++ select2,trx_id.result~ -@@ -22,6 +22,8 @@ - delete from t1 where x > 7; - insert into t1(x, y) values(3, 33); +--- select2.result 2018-06-29 17:51:17.142172085 +0200 ++++ select2,trx_id.reject 2018-06-29 18:03:49.034273090 +0200 +@@ -26,6 +26,8 @@ select sys_start from t1 where x = 3 and y = 33 into @t1; + Warnings: + Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead +set @x1= @t1; +select trt_commit_ts(@x1) into @t1; select x, y from t1; x y 0 100 -@@ -82,7 +84,7 @@ +@@ -86,7 +88,7 @@ 8 108 9 109 3 33 @@ -18,7 +18,7 @@ ASOF2_x y 0 100 1 101 -@@ -94,7 +96,7 @@ +@@ -98,7 +100,7 @@ 7 107 8 108 9 109 @@ -27,7 +27,7 @@ FROMTO2_x y 0 100 1 101 -@@ -106,7 +108,7 @@ +@@ -110,7 +112,7 @@ 7 107 8 108 9 109 diff --git a/mysql-test/suite/versioning/r/select2.result b/mysql-test/suite/versioning/r/select2.result index bb5c82ee444..22388359885 100644 --- a/mysql-test/suite/versioning/r/select2.result +++ b/mysql-test/suite/versioning/r/select2.result @@ -18,10 +18,14 @@ insert into t1 (x, y) values (9, 109); set @t0= now(6); select sys_start from t1 limit 1 into @x0; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead delete from t1 where x = 3; delete from t1 where x > 7; insert into t1(x, y) values(3, 33); select sys_start from t1 where x = 3 and y = 33 into @t1; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select x, y from t1; x y 0 100 @@ -331,7 +335,7 @@ x y select * from (select * from t1 for system_time all, t2 for system_time all) for system_time all as t; ERROR HY000: Table `t` is not system-versioned select * from (t1 for system_time all join t2 for system_time all) for system_time all; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'system_time all' at line 1 # MDEV-16043 Assertion thd->Item_change_list::is_empty() failed in mysql_parse upon SELECT from a view reading from a versioned table create or replace table t1 (a int) with system versioning; create or replace view v1 as select * from t1; diff --git a/mysql-test/suite/versioning/r/sysvars.result b/mysql-test/suite/versioning/r/sysvars.result index b23742462d1..79aa8fce746 100644 --- a/mysql-test/suite/versioning/r/sysvars.result +++ b/mysql-test/suite/versioning/r/sysvars.result @@ -53,7 +53,7 @@ Variable_name Value system_versioning_asof 1900-01-01 00:00:00.000000 set global system_versioning_asof= timestamp'1911-11-11 11:11:11.1111119'; Warnings: -Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119' +Note 1292 Truncated incorrect DATETIME value: '1911-11-11 11:11:11.1111119' show global variables like 'system_versioning_asof'; Variable_name Value system_versioning_asof 1911-11-11 11:11:11.111111 @@ -80,7 +80,7 @@ Variable_name Value system_versioning_asof 1900-01-01 00:00:00.000000 set system_versioning_asof= timestamp'1911-11-11 11:11:11.1111119'; Warnings: -Note 1292 Truncated incorrect datetime value: '1911-11-11 11:11:11.1111119' +Note 1292 Truncated incorrect DATETIME value: '1911-11-11 11:11:11.1111119' show variables like 'system_versioning_asof'; Variable_name Value system_versioning_asof 1911-11-11 11:11:11.111111 @@ -130,3 +130,14 @@ show status like "Feature_system_versioning"; Variable_name Value Feature_system_versioning 2 drop table t; +# +# MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP +# +SET sql_mode=TIME_ROUND_FRACTIONAL; +SET @@global.system_versioning_asof= timestamp'2001-12-31 23:59:59.9999999'; +Warnings: +Note 1292 Truncated incorrect DATETIME value: '2001-12-31 23:59:59.9999999' +SELECT @@global.system_versioning_asof; +@@global.system_versioning_asof +2002-01-01 00:00:00.000000 +SET @@global.system_versioning_asof= DEFAULT; diff --git a/mysql-test/suite/versioning/r/trx_id.result b/mysql-test/suite/versioning/r/trx_id.result index 7d5e908b85a..f8339c0a4b8 100644 --- a/mysql-test/suite/versioning/r/trx_id.result +++ b/mysql-test/suite/versioning/r/trx_id.result @@ -17,11 +17,15 @@ add period for system_time(s, e), add system versioning, algorithm=inplace; select s from t1 into @trx_start; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select count(*) = 1 from mysql.transaction_registry where transaction_id = @trx_start; count(*) = 1 1 create or replace table t1 (x int); select count(*) from mysql.transaction_registry into @tmp; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead alter table t1 add column s bigint unsigned as row start, add column e bigint unsigned as row end, @@ -40,11 +44,15 @@ add period for system_time(s, e), add system versioning, algorithm=copy; select s from t1 into @trx_start; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select count(*) = 1 from mysql.transaction_registry where transaction_id = @trx_start; count(*) = 1 1 create or replace table t1 (x int); select count(*) from mysql.transaction_registry into @tmp; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead alter table t1 add column s bigint unsigned as row start, add column e bigint unsigned as row end, @@ -96,8 +104,14 @@ set @ts2= sysdate(6); commit; set @ts3= sysdate(6); select sys_start from t1 where x = 1 into @trx_id1; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select sys_start from t1 where x = 2 into @trx_id2; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select sys_start from t1 where x = 3 into @trx_id3; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select @trx_id1 < @trx_id2, @trx_id2 < @trx_id3; @trx_id1 < @trx_id2 @trx_id2 < @trx_id3 1 1 @@ -178,6 +192,8 @@ set @ts1= now(6); insert into t1 values (1); commit; select row_start from t1 into @trx_id; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead select trt_begin_ts(@trx_id) <= @ts1 as BEGIN_TS_GOOD; BEGIN_TS_GOOD 1 diff --git a/mysql-test/suite/versioning/t/alter.test b/mysql-test/suite/versioning/t/alter.test index 05bd6019a32..01cb2d72f8d 100644 --- a/mysql-test/suite/versioning/t/alter.test +++ b/mysql-test/suite/versioning/t/alter.test @@ -450,7 +450,7 @@ use mysql; --error ER_VERS_DB_NOT_SUPPORTED create or replace table t (x int) with system versioning; --error ER_VERS_DB_NOT_SUPPORTED -alter table user add system versioning; +alter table db add system versioning; use test; --echo # MDEV-15956 Strange ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN upon ALTER on versioning column diff --git a/mysql-test/suite/versioning/t/online.test b/mysql-test/suite/versioning/t/online.test index 37405bb99ce..9de4937d8da 100644 --- a/mysql-test/suite/versioning/t/online.test +++ b/mysql-test/suite/versioning/t/online.test @@ -134,5 +134,19 @@ select count(*) from t for system_time all; update t set b=11; select count(*) from t for system_time all; +--echo # Start of 10.4 tests + +create or replace table t (a int, b int) engine=innodb; +alter table t + add s bigint unsigned as row start, + add e bigint unsigned as row end, + add period for system_time(s, e), + add system versioning; +alter table t drop column b, algorithm=instant; +alter table t add index idx(a), lock=none; +alter table t drop column s, drop column e; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table t drop system versioning, lock=none; + drop database test; create database test; diff --git a/mysql-test/suite/versioning/t/sysvars.test b/mysql-test/suite/versioning/t/sysvars.test index 160af12fe02..52fab81b8e6 100644 --- a/mysql-test/suite/versioning/t/sysvars.test +++ b/mysql-test/suite/versioning/t/sysvars.test @@ -87,3 +87,13 @@ select * from t for system_time between '0-0-0' and current_timestamp(6); show status like "Feature_system_versioning"; drop table t; + + +--echo # +--echo # MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP +--echo # + +SET sql_mode=TIME_ROUND_FRACTIONAL; +SET @@global.system_versioning_asof= timestamp'2001-12-31 23:59:59.9999999'; +SELECT @@global.system_versioning_asof; +SET @@global.system_versioning_asof= DEFAULT; diff --git a/mysql-test/suite/wsrep/disabled.def b/mysql-test/suite/wsrep/disabled.def index c7c8f2c6216..24d46cc39f0 100644 --- a/mysql-test/suite/wsrep/disabled.def +++ b/mysql-test/suite/wsrep/disabled.def @@ -1,2 +1,2 @@ wsrep.foreign_key : Sporadic failure "WSREP has not yet prepared node for application use" - +wsrep.pool_of_threads : Sporadic failure "WSREP has not yet prepared node for application use" diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index 45b72f0fade..045e220ac55 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -23,7 +23,7 @@ # ############################################################################## -# Based on bb-10.3-release 49a91a6cf89871082fd0a6b7d4b8482c429e942c +# Based on 10.3 9556d56da2a87b47f545ce4c9cbd09f7778ad527 #----------------------------------------------------------------------- @@ -36,18 +36,17 @@ archive-test_sql_discovery.discover : MDEV-16817 #----------------------------------------------------------------------- -auth_gssapi.basic : Modified in 10.3.11 - -#----------------------------------------------------------------------- - binlog.binlog_commit_wait : MDEV-10150 - Mismatch -binlog.binlog_flush_binlogs_delete_domain : Modified in 10.3.11 +binlog.binlog_flush_binlogs_delete_domain : MDEV-14431 - Wrong exit code +binlog.binlog_incident : Modified in 10.1.36 binlog.binlog_killed : MDEV-12925 - Wrong result binlog.binlog_xa_recover : MDEV-8517 - Extra checkpoint binlog.load_data_stm_view : MDEV-16948 - Wrong result +binlog_tmp_table_row : Added in 10.3.9 #----------------------------------------------------------------------- +binlog_encryption.binlog_incident : Modified in 10.1.36 binlog_encryption.binlog_xa_recover : MDEV-12908 - Extra checkpoint binlog_encryption.encrypted_master : MDEV-14201 - Extra warnings binlog_encryption.encrypted_master_switch_to_unencrypted : MDEV-14190 - Can't init tc log @@ -63,18 +62,11 @@ binlog_encryption.rpl_skip_replication : MDEV-13571 binlog_encryption.rpl_ssl : MDEV-14507 - Timeouts binlog_encryption.rpl_stm_relay_ign_space : MDEV-13278 - Wrong result (test assertion) binlog_encryption.rpl_sync : MDEV-13830 - Assertion failure -binlog_encryption.rpl_typeconv : MDEV-14362 - Lost connection to MySQL server during query; include file modified in 10.3.11 +binlog_encryption.rpl_typeconv : MDEV-14362 - Lost connection to MySQL server during query #----------------------------------------------------------------------- -compat/oracle.func_concat : Modified in 10.3.11 -compat/oracle.parser : Modified in 10.3.11 -compat/oracle.sp : Modified in 10.3.11 -compat/oracle.sp-code : Modified in 10.3.11 -compat/oracle.sp-cursor : Modified in 10.3.11 -compat/oracle.sp-cursor-rowtype : Modified in 10.3.11 -compat/oracle.sp-package : Modified in 10.3.11 -compat/oracle.sp-package-mysqldump : Modified in 10.3.11 +compat/oracle.events : Added in 10.3.9 compat/oracle.table_value_constr : Modified in 10.3.10 #----------------------------------------------------------------------- @@ -92,7 +84,7 @@ encryption.encrypt_and_grep : MDEV-13765 encryption.innochecksum : MDEV-13644 - Assertion failure encryption.innodb-checksum-algorithm : MDEV-12898 - Deadlock of threads; MDEV-16896 - Server crash encryption.innodb-compressed-blob : MDEV-14728 - Unable to get certificate -encryption.innodb-encryption-alter : MDEV-13566 - Lock wait timeout; modified in 10.3.11 +encryption.innodb-encryption-alter : MDEV-13566 - Lock wait timeout encryption.innodb_encryption_tables : MDEV-17339 - Crash on restart encryption.innodb-first-page-read : MDEV-14356 - Timeout in wait condition encryption.innodb-force-corrupt : MDEV-17286 - SSL error @@ -151,49 +143,45 @@ galera_3nodes.* : Suite is no #----------------------------------------------------------------------- -gcol.gcol_partition_innodb : Modified in 10.3.11 gcol.gcol_rollback : MDEV-16954 - Unknown storage engine 'InnoDB' +gcol.gcol_update : Include file modified in 10.3.9 gcol.innodb_virtual_basic : MDEV-16950 - Failing assertion +gcol.innodb_virtual_debug : MDEV-14134 - Crash, assertion failure gcol.innodb_virtual_debug_purge : MDEV-16952 - Wrong result; modified in 10.3.10 -gcol.innodb_virtual_fk_restart : MDEV-17466 - Assertion failure -gcol.innodb_virtual_index : Modifed in 10.3.11 - -#----------------------------------------------------------------------- - -heap.heap_btree : Modified in 10.3.11 +gcol.innodb_virtual_index : Include file modified in 10.3.9 +gcol.innodb_virtual_purge : Include file modified in 10.3.9 #----------------------------------------------------------------------- innodb.101_compatibility : MDEV-13891 - Wrong result -innodb.alter_algorithm : Modified in 10.3.11 +innodb.alter_algorithm : Modified in 10.3.10 innodb.alter_copy : MDEV-16181 - Assertion failure innodb.alter_crash : MDEV-16944 - The process cannot access the file -innodb.alter_inplace_perfschema : MDEV-17748 - Wrong result; Added in 10.3.11 -innodb.alter_kill : Modified in 10.3.11 -innodb.alter_not_null : Modified in 10.3.11 -innodb.auto_increment_dup : Modified in 10.3.11 +innodb.alter_kill : MDEV-16273 - Unknown storage engine 'InnoDB', MDEV-16946 - Wrong result +innodb.alter_not_null : Modified in 10.3.9 +innodb.alter_not_null_debug : Added in 10.3.9 innodb.autoinc_persist : MDEV-15282 - Assertion failure innodb.binlog_consistent : MDEV-10618 - Server fails to start -innodb.ddl_purge : Combinations changed in 10.3.11 +innodb.dml_purge : Include file modified in 10.3.9 innodb.doublewrite : MDEV-12905 - Server crash -innodb.drop_table_background : Modified in 10.2.19 -innodb.foreign_key : Modified in 10.3.11 +innodb.foreign_key : Modified in 10.3.10 innodb.foreign-keys : Modified in 10.3.10 innodb.group_commit_crash : MDEV-14191 - InnoDB registration failed innodb.group_commit_crash_no_optimize_thread : MDEV-13830 - Assertion failure -innodb.ibuf_not_empty : MDEV-17742 - Assertion failure +innodb.index_merge_threshold : Include files modified in 10.3.9 +innodb.innodb-16k : Modified in 10.3.9 innodb.innodb-32k-crash : MDEV-16953 - Corrupt log record found innodb.innodb-64k-crash : MDEV-13872 - Failure and crash on startup -innodb.innodb-alter : Modified in 10.3.11 -innodb.innodb-alter-debug : MDEV-13182 - InnoDB: adjusting FSP_SPACE_FLAGS; modified in 10.3.11 +innodb.innodb-alter-debug : MDEV-13182 - InnoDB: adjusting FSP_SPACE_FLAGS innodb.innodb-alter-table : MDEV-10619 - Testcase timeout innodb.innodb-alter-tempfile : MDEV-15285 - Table already exists innodb.innodb-blob : MDEV-12053 - Client crash +innodb.innodb-corrupted-table : Modified in 10.3.9 innodb.innodb-fk : MDEV-13832 - Assertion failure on shutdown innodb.innodb-get-fk : MDEV-13276 - Server crash -innodb.innodb-index : Modified in 10.3.11 innodb.innodb-index-online : MDEV-14809 - Cannot save statistics innodb.innodb-lock : Modified in 10.3.10 +innodb.innodb-mdev-7513 : Modified in 10.3.9 innodb.innodb-page_compression_bzip2 : Modified in 10.3.10 innodb.innodb-page_compression_default : MDEV-13644 - Assertion failure innodb.innodb-page_compression_lz4 : Modified in 10.3.10 @@ -203,7 +191,7 @@ innodb.innodb-page_compression_snappy : MDEV-13644 innodb.innodb-page_compression_tables : Modified in 10.3.10 innodb.innodb-page_compression_zip : MDEV-10641 - mutex problem; modified in 10.3.10 innodb.innodb-table-online : MDEV-13894 - Wrong result -innodb.innodb-wl5522 : MDEV-13644 - Assertion failure +innodb.innodb-wl5522 : MDEV-13644 - Assertion failure; modified in 10.3.9 innodb.innodb-wl5522-debug : MDEV-14200 - Wrong errno innodb.innodb_bug14147491 : MDEV-11808 - Index is corrupt innodb.innodb_bug30423 : MDEV-7311 - Wrong result @@ -219,140 +207,134 @@ innodb.innodb_max_recordsize_64k : MDEV-15203 innodb.innodb_monitor : MDEV-10939 - Testcase timeout innodb.innodb-page_compression_tables : MDEV-13644 - Assertion failure innodb.innodb_stats : MDEV-10682 - wrong result -innodb.innodb_stats_persistent : MDEV-17745 - Wrong result +innodb.innodb_stats_persistent : Include file modified in 10.3.9 innodb.innodb_stats_persistent_debug : MDEV-14801 - Operation failed innodb.innodb_sys_semaphore_waits : MDEV-10331 - Semaphore wait innodb.innodb_zip_innochecksum2 : MDEV-13882 - Extra warnings innodb.innodb_zip_innochecksum3 : MDEV-14486 - Resource temporarily unavailable -innodb.instant_alter : Modified in 10.3.11 +innodb.instant_alter : Modified in 10.3.10 +innodb.instant_alter_crash : Include file modified in 10.3.9 innodb.instant_alter_debug : Modified in 10.3.10 -innodb.instant_alter_rollback : Modified in 10.3.11 +innodb.instant_alter_rollback : Include file modified in 10.3.9 innodb.log_corruption : MDEV-13251 - Wrong result innodb.log_data_file_size : MDEV-14204 - Server failed to start innodb.log_file_name : MDEV-14193 - Exception -innodb.log_file_name_debug : Modified in 10.3.11 -innodb.log_file_size : MDEV-15668 - Not found pattern; modified in 10.3.11 -innodb.monitor : MDEV-16179 - Wrong result -innodb.purge_secondary : MDEV-15681 - Wrong result +innodb.log_file_size : MDEV-15668 - Not found pattern +innodb.monitor : MDEV-16179 - Wrong result; modified in 10.3.9 +innodb.purge_secondary : MDEV-15681 - Wrong result; include file modified in 10.3.9 innodb.purge_thread_shutdown : MDEV-13792 - Wrong result innodb.read_only_recovery : MDEV-13886 - Server crash innodb.recovery_shutdown : MDEV-15671 - Checksum mismatch in datafile -innodb.rename_table_debug : Added in 10.2.19 innodb.row_format_redundant : MDEV-15192 - Trying to access missing tablespace +innodb.strict_mode : Modified in 10.3.9 innodb.table_definition_cache_debug : MDEV-14206 - Extra warning -innodb.table_flags : MDEV-13572 - Wrong result; modified in 10.3.11 +innodb.table_flags : MDEV-13572 - Wrong result innodb.temp_table_savepoint : MDEV-16182 - Wrong result -innodb.temporary_table : MDEV-13265 - Wrong result +innodb.temporary_table : MDEV-13265 - Wrong result; modified in 10.3.9 innodb.truncate : Added in 10.3.10 innodb.truncate_crash : Added in 10.3.10 -innodb.truncate_debug : Opt file added in 10.2.19 innodb.truncate_foreign : Added in 10.3.10 -innodb.truncate_inject : Opt file added in 10.2.19 innodb.truncate_missing : Added in 10.3.10 -innodb.truncate_purge_debug : Opt file added in 10.2.19 -innodb.truncate_restart : Opt file added in 10.2.19 innodb.update_time : MDEV-14804 - Wrong result +innodb.undo_log : Include file modified in 10.3.9 innodb.undo_truncate : MDEV-17340 - Server hung; added in 10.3.10 -innodb.undo_truncate_recover : MDEV-13080 - Missing checkpoint; MDEV-17679 - Server has gone away; added in 10.3.10 +innodb.undo_truncate_recover : MDEV-13080 - Missing checkpoint; added in 10.3.10 innodb.xa_recovery : MDEV-15279 - mysqld got exception #----------------------------------------------------------------------- -innodb_fts.crash_recovery : Modified in 10.3.11 -innodb_fts.fts_kill_query : Modified in 10.0.37 +innodb_fts.fts_kill_query : Added in 10.3.9 innodb_fts.innodb-fts-fic : MDEV-14154 - Assertion failure innodb_fts.innodb_fts_misc_debug : MDEV-14156 - Unexpected warning +innodb_fts.innodb_fts_multiple_index : Modified in 10.3.9 innodb_fts.innodb_fts_plugin : MDEV-13888 - Errors in server log innodb_fts.innodb_fts_stopword_charset : MDEV-13259 - Table crashed innodb_fts.sync : MDEV-14808 - Wrong result +innodb_fts.sync_ddl : MDEV-17296 - Server crash; added in 10.3.9 #----------------------------------------------------------------------- +innodb_gis.create_spatial_index : Modified in 10.3.9 innodb_gis.kill_server : MDEV-16941 - Checksum mismatch +innodb_gis.rtree_compress : Include file modified in 10.3.9 innodb_gis.rtree_compress2 : MDEV-16269 - Wrong result -innodb_gis.rtree_concurrent_srch : MDEV-15284 - Wrong result with embedded; modified in 10.3.11 -innodb_gis.rtree_purge : MDEV-15275 - Timeout +innodb_gis.rtree_concurrent_srch : MDEV-15284 - Wrong result with embedded +innodb_gis.rtree_purge : MDEV-15275 - Timeout; include file modified in 10.3.9 innodb_gis.rtree_recovery : MDEV-15274 - Error on check innodb_gis.rtree_split : MDEV-14208 - Too many arguments -innodb_gis.rtree_undo : MDEV-14456 - Timeout in include file +innodb_gis.rtree_undo : MDEV-14456 - Timeout in include file; include file modified in 10.3.9 innodb_gis.types : MDEV-15679 - Table is marked as crashed #----------------------------------------------------------------------- innodb_zip.cmp_per_index : MDEV-14490 - Table is marked as crashed innodb_zip.innochecksum_3 : MDEV-13279 - Extra warnings -innodb_zip.restart : Opt file modified in 10.2.19 innodb_zip.wl5522_debug_zip : MDEV-11600 - Operating system error number 2 innodb_zip.wl6470_1 : MDEV-14240 - Assertion failure -innodb_zip.wl6501_1 : MDEV-10891 - Can't create UNIX socket; opt file added in 10.2.19 -innodb_zip.wl6501_crash_3 : Opt file added in 10.2.19 -innodb_zip.wl6501_crash_4 : Opt file added in 10.2.19 -innodb_zip.wl6501_crash_5 : Opt file added in 10.2.19 -innodb_zip.wl6501_scale_1 : Opt file added in 10.2.19 -innodb_zip.wl6501_scale_1 : MDEV-13254 - Timeout, MDEV-14104 - Error 192 #----------------------------------------------------------------------- -main.alter_table : Modified in 10.3.11 main.alter_table_trans : MDEV-12084 - timeout main.analyze_stmt_slow_query_log : MDEV-12237 - Wrong result main.auth_named_pipe : MDEV-14724 - System error 2 -main.auto_increment_ranges_innodb : Modified in 10.3.11 -main.bigint : Modified in 10.3.11 -main.case : Modified in 10.3.11 +main.bootstrap : Modified in 10.3.9 +main.check_constraint : Modified in 10.3.9 +main.column_compression : Modified in 10.3.9 main.connect : MDEV-16270, MDEV-17282 - Wrong result main.connect2 : MDEV-13885 - Server crash main.constraints : Modified in 10.3.10 main.count_distinct2 : MDEV-11768 - timeout main.create_delayed : MDEV-10605 - failed with timeout main.create_drop_event : MDEV-16271 - Wrong result -main.create_or_replace : Modified in 10.3.11 -main.cte_nonrecursive : Modified in 10.3.11 -main.cte_recursive : Modified in 10.3.11 -main.ctype_latin1 : Modified in 10.3.11 -main.ctype_uca : Modified in 10.3.11 -main.ctype_ucs : MDEV-17681 - Data too long for column +main.create_or_replace : Modified in 10.3.10 +main.create_replace_tmp : Added in 10.3.9 +main.cte_nonrecursive : Modified in 10.3.10 +main.cte_recursive : Modified in 10.3.10 +main.cte_recursive_not_embedded : Added in 10.3.9 +main.ctype_binary : Modified in 10.3.9 +main.ctype_eucjpms : Modified in 10.3.9 +main.ctype_euckr : Modified in 10.3.9 +main.ctype_gbk : Modified in 10.3.9 +main.ctype_latin1 : Modified in 10.3.9 +main.ctype_ucs : Modified in 10.3.9 +main.ctype_ujis : Modified in 10.3.9 main.ctype_upgrade : MDEV-16945 - Error upon mysql_upgrade -main.ctype_utf16le : MDEV-10675: timeout or extra warnings -main.ctype_utf16 : MDEV-10675: timeout or extra warnings -main.ctype_utf8mb4_innodb : MDEV-17744 - Timeout +main.ctype_utf16le : MDEV-10675: timeout or extra warnings; modified in 10.3.9 +main.ctype_utf16 : MDEV-10675: timeout or extra warnings; modified in 10.3.9 +main.ctype_utf32 : Modified in 10.3.9 +main.ctype_utf8mb4 : Modified in 10.3.9 +main.ctype_utf8 : Modified in 10.3.9 main.debug_sync : MDEV-10607 - internal error -main.derived_cond_pushdown : Modified in 10.3.11 -main.derived_opt : MDEV-11768 - timeout; modified in 10.3.11 -main.derived_split_innodb : Modified in 10.3.11 -main.distinct : MDEV-14194 - Crash; modified in 10.3.11 +main.derived : Modified in 10.3.9 +main.derived_cond_pushdown : Modified in 10.3.10 +main.derived_opt : MDEV-11768 - timeout +main.derived_split_innodb : Modified in 10.3.10 +main.distinct : MDEV-14194 - Crash main.drop_bad_db_type : MDEV-15676 - Wrong result main.events_2 : MDEV-13277 - Crash main.events_bugs : MDEV-12892 - Crash main.events_restart : MDEV-12236 - Server shutdown problem main.events_slowlog : MDEV-12821 - Wrong result -main.flush : Modified in 10.3.11 -main.func_concat : Modified in 10.3.11 -main.func_default : Modified in 10.3.11 +main.flush : Modified in 10.3.10 main.func_isnull : Modified in 10.3.10 -main.func_json : Modified in 10.3.11 -main.func_like : Modified in 10.3.11 -main.func_time : Modified in 10.3.11 +main.func_json : Modified in 10.3.10 +main.func_time : Modified in 10.3.10 main.gis : MDEV-13411 - wrong result on P8; modified in 10.3.10 main.gis-precise : Modified in 10.3.10 main.grant : Modified in 10.3.10 -main.group_by : Modified in 10.3.11 main.group_min_max : Modified in 10.3.10 main.host_cache_size_functionality : MDEV-10606 - sporadic failure on shutdown main.index_intersect_innodb : MDEV-10643 - failed with timeout main.index_merge_innodb : MDEV-7142 - Plan mismatch -main.index_merge_myisam : Modified in 10.3.11 main.innodb_mysql_lock : MDEV-7861 - Wrong result +main.invisible_field_debug : Modified in 10.3.9 main.join : Modified in 10.3.10 -main.join_cache : MDEV-17743 - Bad address from storage engine MyISAM -main.join_outer : Modified in 10.3.11 +main.join_cache : Modified in 10.3.9 +main.join_outer : Modified in 10.3.9 main.kill-2 : MDEV-13257 - Wrong result main.kill_processlist-6619 : MDEV-10793 - Wrong result -main.lock : Modified in 10.3.11 -main.lock_multi : Modified in 10.3.11 main.log_slow : MDEV-13263 - Wrong result main.log_tables-big : MDEV-13408 - wrong result -main.lowercase_fs_off : Modified in 10.3.11 main.mdev375 : MDEV-10607 - sporadic "can't connect" main.mdev-504 : MDEV-15171 - warning main.merge : MDEV-10607 - sporadic "can't connect" @@ -361,42 +343,33 @@ main.mysql_client_test_comp : MDEV-16641 main.mysql_client_test_nonblock : CONC-208 - Error on Power; MDEV-15096 - exec failed main.mysql_not_windows : Modified in 10.3.10 main.mysqld_option_err : MDEV-12747 - Timeout -main.mysqldump : MDEV-14800 - Stack smashing detected; modified in 10.3.11 -main.mysqldump-max : Modified in 10.3.11 -main.mysqldump-utf8mb4 : Added in 10.3.11 +main.mysqldump : MDEV-14800 - Stack smashing detected main.mysqlhotcopy_myisam : MDEV-10995 - Hang on debug main.mysqlslap : MDEV-11801 - timeout main.mysqltest : MDEV-13887 - Wrong result main.mysql_upgrade_noengine : MDEV-14355 - Wrong result main.mysql_upgrade_ssl : MDEV-13492 - Unknown SSL error -main.openssl_1 : MDEV-13492 - Unknown SSL error; modified in 10.3.11 +main.openssl_1 : MDEV-13492 - Unknown SSL error main.openssl_6975 : MDEV-17184 - Failures with OpenSSL 1.1.1 -main.opt_tvc : Modified in 10.3.11 +main.opt_tvc : Modified in 10.3.10 main.order_by_optimizer_innodb : MDEV-10683 - Wrong result -main.order_by_zerolength-4285 : Modified in 10.3.11 -main.parser : Modified in 10.3.11 main.partition_debug_sync : MDEV-15669 - Deadlock found when trying to get lock main.partition_error : Modified in 10.3.10 -main.partition_explicit_prune : Modified in 10.3.11 -main.partition_innodb : Modified in 10.3.11 main.partition_innodb_plugin : MDEV-12901 - Valgrind warnings -main.partition_pruning : Modified in 10.3.11 main.ps : MDEV-11017 - sporadic wrong Prepared_stmt_count; modified in 10.3.10 main.query_cache_debug : MDEV-15281 - Query cache is disabled main.query_cache : MDEV-16180 - Wrong result main.range : Modified in 10.3.10 main.range_debug : Added in 10.3.10 main.range_vs_index_merge_innodb : MDEV-15283 - Server has gone away +main.rename : Modified in 10.3.9 main.selectivity : Modified in 10.3.10 main.set_statement : MDEV-13183 - Wrong result main.shm : MDEV-12727 - Mismatch, ERROR 2013 main.show_explain : MDEV-10674 - Wrong result code main.sp : MDEV-7866 - Mismatch; modified in 10.3.10 -main.sp-cursor : Modified in 10.3.11 -main.sp-for-loop : Modified in 10.3.11 main.sp_notembedded : MDEV-10607 - internal error main.sp-security : MDEV-10607 - sporadic "can't connect"; modified in 10.3.10 -main.sql_safe_updates : Added in 10.3.11 main.ssl : MDEV-17184 - Failures with OpenSSL 1.1.1 main.ssl_ca : MDEV-10895 - SSL connection error on Power main.ssl_cert_verify : MDEV-13735 - Server crash @@ -409,29 +382,26 @@ main.stat_tables_par : MDEV-13266 main.status : MDEV-13255 - Wrong result main.subselect_extra_no_semijoin : Modified in 10.3.10 main.subselect_innodb : MDEV-10614 - Wrong result +main.subselect : Modified in 10.3.9 +main.subselect_sj2_mat : Modified in 10.3.9 +main.subselect_sj_mat : Modified in 10.3.9 main.table_value_constr : Modified in 10.3.10 main.tc_heuristic_recover : MDEV-14189 - Wrong result main.temp_table : Modified in 10.3.10 main.type_blob : MDEV-15195 - Wrong result -main.type_datetime : Modified in 10.3.11 +main.type_datetime : MDEV-14322 - wrong result main.type_datetime_hires : MDEV-10687 - Timeout main.type_float : Modified in 10.3.10 -main.type_newdecimal : Modified in 10.3.11 -main.type_year : Modified in 10.3.11 +main.union : Modified in 10.3.9 main.userstat : MDEV-12904 - SSL errors -main.win : Modified in 10.3.11 +main.win : Modified in 10.3.10 main.win_lead_lag : Modified in 10.3.10 -main.win_percent_cume : Modified in 10.3.11 -main.win_percentile : Modified in 10.3.11 -main.win_rank : Modified in 10.3.11 -main.win_std : Modified in 10.3.11 -main.xa : MDEV-11769 - lock wait timeout +main.xa : MDEV-11769 - lock wait timeout; modified in 10.3.9 #----------------------------------------------------------------------- maria.concurrent : Added in 10.3.10 maria.create : Added in 10.3.10 -maria.fulltext2 : Added in 10.3.11 maria.insert_select : MDEV-12757 - Timeout maria.insert_select-7314 : MDEV-16492 - Timeout maria.maria : MDEV-14430 - Extra warning; modified in 10.3.10 @@ -450,7 +420,8 @@ mariabackup.full_backup : MDEV-16571 mariabackup.huge_lsn : MDEV-15662 - Sequence number is in the future mariabackup.incremental_backup : MDEV-14192 - Assertion failure mariabackup.incremental_ddl_during_backup : Added in 10.3.10 -mariabackup.incremental_encrypted : MDEV-15667 - timeout +mariabackup.incremental_encrypted : MDEV-15667 - timeout; modified in 10.3.9 +mariabackup.innodb_log_optimize_ddl : Added in 10.3.9 mariabackup.log_checksum_mismatch : MDEV-16571 - Wrong result mariabackup.mdev-14447 : MDEV-15201 - Timeout mariabackup.mlog_index_load : MDEV-14192 - Assertion failure; added in 10.3.10 @@ -458,7 +429,7 @@ mariabackup.nolock_ddl_during_backup_end : Added in 10 mariabackup.partial_exclude : MDEV-15270 - Error on exec mariabackup.recreate_table_during_backup : Added in 10.3.10 mariabackup.rename_during_backup : Added in 10.3.10 -mariabackup.rename_during_mdl_lock : MDEV-14192 - Assertion failure; modified in 10.3.10 +mariabackup.rename_during_mdl_lock : Modified in 10.3.10 mariabackup.skip_innodb : Added in 10.3.10 mariabackup.truncate_during_backup : Added in 10.3.10 mariabackup.undo_space_id : Opt file modified in 10.3.10 @@ -468,7 +439,7 @@ mariabackup.xb_compressed_encrypted : MDEV-14812 mariabackup.xb_file_key_management : MDEV-16571 - Wrong result mariabackup.xb_history : MDEV-16268 - Error on exec mariabackup.xb_page_compress : MDEV-14810 - status: 1, errno: 11 -mariabackup.xb_partition : MDEV-14192 - Crash; MDEV-17584 - Crash upon shutdown +mariabackup.xb_partition : MDEV-14192 - Crash mariabackup.xb_rocksdb : MDEV-17338 - Server hung on shutdown mariabackup.xbstream : MDEV-14192 - Crash @@ -478,9 +449,17 @@ mroonga/storage.column_datetime_32bit_2038 : Wrong resul mroonga/storage.column_datetime_32bit_before_unix_epoch : Wrong result on Alpha mroonga/storage.column_datetime_32bit_max : Wrong result on Alpha mroonga/storage.column_datetime_32bit_out_of_range : Wrong result on Alpha +mroonga/storage.index_multiple_column_range_all_used_less_than : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.index_multiple_column_range_all_used_less_than_or_equal : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.index_multiple_column_range_partially_used_have_prefix_less_than : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.index_multiple_column_range_partially_used_have_prefix_less_than_or_equal : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.index_multiple_column_range_partially_used_no_prefix_less_than : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.index_multiple_column_range_partially_used_no_prefix_less_than_or_equal : MDEV-16127 - Wrong result with GCC 8 mroonga/storage.index_multiple_column_unique_date_32bit_equal : Wrong result on Alpha mroonga/storage.index_multiple_column_unique_date_order_32bit_desc : Wrong result on Alpha mroonga/storage.index_multiple_column_unique_datetime_index_read : MDEV-8643 - Valgrind +mroonga/storage.optimization_order_limit_optimized_datetime_less_than : MDEV-16127 - Wrong result with GCC 8 +mroonga/storage.optimization_order_limit_optimized_datetime_less_than_or_equal : MDEV-16127 - Wrong result with GCC 8 mroonga/storage.repair_table_no_index_file : MDEV-9364 - wrong result, MDEV-14807 - wrong error message mroonga/wrapper.repair_table_no_index_file : MDEV-14807 - Wrong error message @@ -504,6 +483,7 @@ parts.partition_exch_qa_10 : MDEV-11765 parts.partition_innodb_status_file : MDEV-12901 - Valgrind parts.partition_special_innodb : MDEV-16942 - Timeout parts.show_create : Modified in 10.3.10 +parts.truncate_locked : Added in 10.3.9 parts.update_and_cache : Added in 10.3.10 #----------------------------------------------------------------------- @@ -517,7 +497,6 @@ perfschema.bad_option_3 : MDEV-12728 perfschema.bad_option_5 : MDEV-14197 - Timeout perfschema.connect_attrs : MDEV-17283 - Wrong result perfschema.dml_file_instances : MDEV-15179 - Wrong result -perfschema.dml_threads : MDEV-17746 - Wrong errno perfschema.func_file_io : MDEV-5708 - fails for s390x perfschema.func_mutex : MDEV-5708 - fails for s390x perfschema.hostcache_ipv4_addrinfo_again_allow : MDEV-12759 - Crash @@ -570,7 +549,7 @@ rpl-tokudb.* : MDEV-14354 rpl-tokudb.rpl_tokudb_commit_after_flush : MDEV-16966 - Server crash rpl.last_insert_id : MDEV-10625 - warnings in error log -rpl.rpl_15919 : Added in 10.3.11 +rpl.rpl_15867 : Added in 10.3.9 rpl.rpl_auto_increment : MDEV-10417 - Fails on Mips rpl.rpl_auto_increment_bug45679 : MDEV-10417 - Fails on Mips rpl.rpl_auto_increment_update_failure : MDEV-10625 - warnings in error log @@ -581,7 +560,6 @@ rpl.rpl_ctype_latin1 : MDEV-14813 rpl.rpl_ddl : MDEV-10417 - Fails on Mips rpl.rpl_domain_id_filter_io_crash : MDEV-12729 - Timeout in include file, MDEV-13677 - Server crash rpl.rpl_domain_id_filter_restart : MDEV-10684 - Wrong result -rpl.rpl_drop_db : Modified in 10.3.11 rpl.rpl_drop_db_fail : MDEV-16898 - Slave fails to start rpl.rpl_extra_col_master_innodb : MDEV-16570 - Extra warning rpl.rpl_extra_col_master_myisam : MDEV-14203 - Extra warning @@ -601,27 +579,23 @@ rpl.rpl_insert_id : MDEV-15197 rpl.rpl_insert_id_pk : MDEV-16567 - Assertion failure rpl.rpl_insert_ignore : MDEV-14365 - Lost connection to MySQL server during query rpl.rpl_invoked_features : MDEV-10417 - Fails on Mips -rpl.rpl_lcase_tblnames_rewrite_db : Added in 10.3.11 -rpl.rpl_lower_case_table_names : Added in 10.3.11 rpl.rpl_mariadb_slave_capability : MDEV-11018 - Extra lines in binlog rpl.rpl_mdev6020 : MDEV-15272 - Server crash rpl.rpl_mixed_mixing_engines : MDEV-14489 - Sync slave with master failed rpl.rpl_non_direct_mixed_mixing_engines : MDEV-14489 - Sync slave with master failed rpl.rpl_non_direct_row_mixing_engines : MDEV-16561 - Timeout in master_pos_wait rpl.rpl_non_direct_stm_mixing_engines : MDEV-14489 - Failed sync_slave_with_master -rpl.rpl_old_master : Modified in 10.3.11 rpl.rpl_parallel : MDEV-10653 - Timeouts -rpl.rpl_parallel2 : MDEV-17390 - Operation cannot be performed rpl.rpl_parallel_conflicts : MDEV-15272 - Server crash rpl.rpl_parallel_mdev6589 : MDEV-12979 - Assertion failure rpl.rpl_parallel_multilevel2 : MDEV-14723 - Timeout -rpl.rpl_parallel_optimistic : MDEV-15278 - Failed to sync with master; modified in 10.3.11 -rpl.rpl_parallel_optimistic_nobinlog : MDEV-15278 - Failed to sync with master; cnf file modified in 10.3.11 +rpl.rpl_parallel_optimistic : MDEV-15278 - Failed to sync with master +rpl.rpl_parallel_optimistic_nobinlog : MDEV-15278 - Failed to sync with master rpl.rpl_parallel_retry : MDEV-11119 - Crash; MDEV-17109 - Timeout rpl.rpl_parallel_temptable : MDEV-10356 - Crash rpl.rpl_partition_innodb : MDEV-10417 - Fails on Mips rpl.rpl_password_boundaries : MDEV-11534 - Slave IO warnings -rpl.rpl_row_001 : MDEV-16653 - MTR's internal check fails +rpl.rpl_row_001 : MDEV-16653 - MTR's internal check fails; modified in 10.3.9 rpl.rpl_row_basic_11bugs : MDEV-12171 - Server failed to start rpl.rpl_row_basic_2myisam : MDEV-13875 - command "diff_files" failed rpl.rpl_row_drop_create_temp_table : MDEV-14487 - Wrong result @@ -629,7 +603,6 @@ rpl.rpl_row_img_blobs : MDEV-13875 rpl.rpl_row_img_eng_min : MDEV-13875 - diff_files failed rpl.rpl_row_img_eng_noblob : MDEV-13875 - command "diff_files" failed rpl.rpl_row_index_choice : MDEV-15196 - Slave crash -rpl.rpl_row_lcase_tblnames : Added in 10.3.11 rpl.rpl_row_sp001 : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_row_spatial : Added in 10.3.10 rpl.rpl_row_until : MDEV-14052 - Master will not send events with checksum @@ -637,6 +610,7 @@ rpl.rpl_semi_sync : MDEV-11220 rpl.rpl_semi_sync_after_sync : MDEV-14366 - Wrong result rpl.rpl_semi_sync_after_sync_row : MDEV-14366 - Wrong result rpl.rpl_semi_sync_event_after_sync : MDEV-11806 - warnings +rpl.rpl_semi_sync_master_shutdown : Added in 10.3.9 rpl.rpl_semi_sync_uninstall_plugin : MDEV-7140 - Assorted failures rpl.rpl_semi_sync_wait_point : MDEV-11807 - timeout in wait condition rpl.rpl_semisync_ali_issues : MDEV-16272 - Wrong result @@ -648,8 +622,7 @@ rpl.rpl_slave_load_tmpdir_not_exist : MDEV-14203 rpl.rpl_slow_query_log : MDEV-13250 - Test abort rpl.rpl_sp_effects : MDEV-13249 - Crash rpl.rpl_start_stop_slave : MDEV-13567 - Sync slave timeout -rpl.rpl_stm_000001 : MDEV-16274 - Connection attributes were truncated -rpl.rpl_stm_lcase_tblnames : Added in 10.3.11 +rpl.rpl_stm_000001 : MDEV-16274 - Connection attributes were truncated; modified in 10.3.9 rpl.rpl_stm_mixing_engines : MDEV-14489 - Sync slave with master failed rpl.rpl_stm_multi_query : MDEV-9501 - Failed registering on master rpl.rpl_stm_relay_ign_space : MDEV-14360 - Test assertion @@ -658,9 +631,7 @@ rpl.rpl_stm_stop_middle_group : MDEV-13791 rpl.rpl_sync : MDEV-13830 - Assertion failure rpl.rpl_temporal_mysql56_to_mariadb53 : MDEV-9501 - Failed registering on master rpl.rpl_temporary_error2 : MDEV-10634 - Wrong number of retries -rpl.rpl_typeconv : Include file modified in 10.3.11 rpl.sec_behind_master-5114 : MDEV-13878 - Wrong result -rpl.show_status_stop_slave_race-7126 : MDEV-17438 - Timeout rpl/extra/rpl_tests.* : MDEV-10994 - Not maintained @@ -675,6 +646,7 @@ sphinx.union-5539 : MDEV-10986 spider.* : MDEV-9329 - tests are too memory-consuming spider.basic_sql : MDEV-11186 - Internal check fails +spider.timestamp : Added in 10.3.9 spider/bg.direct_aggregate : MDEV-7098 - Packets out of order spider/bg.direct_aggregate_part : MDEV-7098 - Trying to unlock mutex that wasn't locked @@ -691,7 +663,6 @@ spider/handler.* : MDEV-10987, sql_sequence.auto_increment : Added in 10.3.10 sql_sequence.concurrent_create : MDEV-16635 - Server crash -sql_sequence.create : Modified in 10.3.11 sql_sequence.next : Modified in 10.3.10 #----------------------------------------------------------------------- @@ -706,15 +677,11 @@ stress.ddl_innodb : MDEV-10635 #----------------------------------------------------------------------- sys_vars.autocommit_func2 : MDEV-9329 - Fails on Ubuntu/s390x -sys_vars.delayed_insert_limit_func : MDEV-17683 - Wrong result; modified in 10.3.11 sys_vars.innodb_buffer_pool_dump_at_shutdown_basic : MDEV-14280 - Unexpected error -sys_vars.innodb_ft_result_cache_limit_32 : Added in 10.3.11 -sys_vars.innodb_ft_result_cache_limit_64 : Added in 10.3.11 -sys_vars.innodb_ft_result_cache_limit_basic : Modified in 10.3.11 +sys_vars.innodb_log_optimize_ddl_basic : Added in 10.3.9 sys_vars.keep_files_on_create_basic : MDEV-10676 - timeout sys_vars.log_slow_admin_statements_func : MDEV-12235 - Server crash sys_vars.rpl_init_slave_func : MDEV-10149 - Test assertion -sys_vars.sql_low_priority_updates_func : Modified in 10.3.11 sys_vars.slow_query_log_func : MDEV-14273 - Wrong result sys_vars.thread_cache_size_func : MDEV-11775 - Wrong result sys_vars.wait_timeout_func : MDEV-12896 - Wrong result @@ -727,7 +694,6 @@ tokudb.* : suite.pm an tokudb.change_column_all_1000_10 : MDEV-12640 - Lost connection tokudb.change_column_bin : MDEV-12640 - Lost connection tokudb.change_column_char : MDEV-12822 - Lost connection -tokudb.change_column_varbin : MDEV-17682 - Timeout tokudb.cluster_filter : MDEV-10678 - Wrong execution plan tokudb.cluster_filter_hidden : MDEV-10678 - Wrong execution plan tokudb.cluster_filter_unpack_varchar : MDEV-10636 - Wrong execution plan @@ -756,13 +722,13 @@ tokudb_backup.* : MDEV-11001 #----------------------------------------------------------------------- -tokudb_bugs.PS-3773 : Added in 10.0.37 -tokudb_bugs.alter_table_comment_rebuild_data : Added in 10.0.37 +tokudb_bugs.alter_table_comment_rebuild_data : Added in 10.1.36 tokudb_bugs.checkpoint_lock : MDEV-10637 - Wrong processlist output tokudb_bugs.checkpoint_lock_3 : MDEV-10637 - Wrong processlist output tokudb_bugs.frm_store : MDEV-12823 - Valgrind tokudb_bugs.frm_store2 : MDEV-12823 - Valgrind tokudb_bugs.frm_store3 : MDEV-12823 - Valgrind +tokudb_bugs.PS-3773 : Added in 10.1.36 tokudb_bugs.xa : MDEV-11804 - Lock wait timeout tokudb_bugs.xa-3 : MDEV-16953 - Corrupt log record found @@ -791,23 +757,19 @@ unit.my_atomic : MDEV-15670 vcol.index : Modified in 10.3.10 vcol.not_supported : MDEV-10639 - Testcase timeout -vcol.races : Added in 10.3.11 vcol.vcol_keys_innodb : MDEV-10639 - Testcase timeout vcol.vcol_misc : MDEV-16651 - Wrong error message #----------------------------------------------------------------------- -versioning.online : Modified in 10.3.11 versioning.truncate : Modified in 10.3.10 -versioning.trx_id : Modified in 10.3.11 -versioning.trx_id_versioning_attribute_persistence : Modified in 10.3.11 #----------------------------------------------------------------------- wsrep.foreign_key : MDEV-14725 - WSREP has not yet prepared node wsrep.mdev_6832 : MDEV-14195 - Check testcase failed wsrep.pool_of_threads : MDEV-17345 - WSREP has not yet prepared node for application use -wsrep.variables : MDEV-14311 - Wrong result; MDEV-17585 - Deadlock; modified in 10.3.11 +wsrep.variables : MDEV-14311 - Wrong result; modified in 10.3.10 #----------------------------------------------------------------------- diff --git a/mysys/errors.c b/mysys/errors.c index 0c6942c5b82..d8c6811fbbe 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -107,12 +107,12 @@ void init_glob_errs() void wait_for_free_space(const char *filename, int errors) { if (errors == 0) - my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH | ME_JUST_WARNING), + my_error(EE_DISK_FULL,MYF(ME_BELL | ME_ERROR_LOG | ME_WARNING), filename,my_errno,MY_WAIT_FOR_USER_TO_FIX_PANIC); if (!(errors % MY_WAIT_GIVE_USER_A_MESSAGE)) my_printf_error(EE_DISK_FULL, "Retry in %d secs. Message reprinted in %d secs", - MYF(ME_BELL | ME_NOREFRESH | ME_JUST_WARNING), + MYF(ME_BELL | ME_ERROR_LOG | ME_WARNING), MY_WAIT_FOR_USER_TO_FIX_PANIC, MY_WAIT_GIVE_USER_A_MESSAGE * MY_WAIT_FOR_USER_TO_FIX_PANIC ); (void) sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC); diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c index 478900ddb2a..6c5a76dc770 100644 --- a/mysys/mf_cache.c +++ b/mysys/mf_cache.c @@ -82,7 +82,7 @@ void close_cached_file(IO_CACHE *cache) #ifdef CANT_DELETE_OPEN_FILES if (cache->file_name) { - (void) my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT)); + (void) my_delete(cache->file_name, MYF(MY_WME)); my_free(cache->file_name); } #endif diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 4f22921aeff..6150473c2f0 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -1550,8 +1550,7 @@ int _my_b_async_read(IO_CACHE *info, uchar *Buffer, size_t Count) if (info->aio_result.result.aio_errno) { if (info->myflags & MY_WME) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(info->file), + my_error(EE_READ, MYF(ME_BELL), my_filename(info->file), info->aio_result.result.aio_errno); my_errno=info->aio_result.result.aio_errno; info->error= -1; @@ -1644,8 +1643,7 @@ int _my_b_async_read(IO_CACHE *info, uchar *Buffer, size_t Count) if (Count != use_length) { /* Didn't find hole block */ if (info->myflags & (MY_WME | MY_FAE | MY_FNABP) && Count != org_Count) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(info->file),my_errno); + my_error(EE_EOFERR, MYF(ME_BELL), my_filename(info->file), my_errno); info->error=(int) (read_length+left_length); return 1; } diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index edf8cd3be8a..a394f2f669a 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -576,7 +576,7 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, if (blocks < 8) { my_errno= ENOMEM; - my_error(EE_OUTOFMEMORY, MYF(ME_FATALERROR), + my_error(EE_OUTOFMEMORY, MYF(ME_FATAL), blocks * keycache->key_cache_block_size); goto err; } diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c index 0ff7066fd95..54b0d85b552 100644 --- a/mysys/mf_tempfile.c +++ b/mysys/mf_tempfile.c @@ -110,6 +110,33 @@ File create_temp_file(char *to, const char *dir, const char *prefix, } } #elif defined(HAVE_MKSTEMP) +#ifdef O_TMPFILE + { + static int O_TMPFILE_works= 1; + + if ((MyFlags & MY_TEMPORARY) && O_TMPFILE_works) + { + /* explictly don't use O_EXCL here has it has a different + meaning with O_TMPFILE + */ + if ((file= open(dir, mode | O_TMPFILE | O_CLOEXEC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) >= 0) + { + my_snprintf(to, FN_REFLEN, "%s/#sql/fd=%d", dir, file); + file=my_register_filename(file, to, FILE_BY_O_TMPFILE, + EE_CANTCREATEFILE, MyFlags); + } + else if (errno == EOPNOTSUPP || errno == EINVAL) + { + my_printf_error(EE_CANTCREATEFILE, "O_TMPFILE is not supported on %s " + "(disabling future attempts)", + MYF(ME_NOTE | ME_ERROR_LOG_ONLY), dir); + O_TMPFILE_works= 0; + } + } + } + if (file == -1) +#endif /* O_TMPFILE */ { char prefix_buff[30]; uint pfx_len; @@ -137,7 +164,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, { int tmp=my_errno; close(org_file); - (void) my_delete(to, MYF(MY_WME | ME_NOINPUT)); + (void) my_delete(to, MYF(MY_WME)); my_errno=tmp; } } diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index f519cbf105f..576142343f4 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -192,7 +192,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) length+=ALIGN_SIZE(sizeof(USED_MEM)); if (!(next = (USED_MEM*) my_malloc(length, - MYF(MY_WME | ME_FATALERROR | + MYF(MY_WME | ME_FATAL | MALLOC_FLAG(mem_root->block_size))))) { if (mem_root->error_handler) @@ -248,7 +248,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) get_size= MY_MAX(get_size, block_size); if (!(next = (USED_MEM*) my_malloc(get_size, - MYF(MY_WME | ME_FATALERROR | + MYF(MY_WME | ME_FATAL | MALLOC_FLAG(mem_root-> block_size))))) { @@ -492,3 +492,14 @@ void *memdup_root(MEM_ROOT *root, const void *str, size_t len) memcpy(pos,str,len); return pos; } + +LEX_CSTRING safe_lexcstrdup_root(MEM_ROOT *root, const LEX_CSTRING str) +{ + LEX_CSTRING res; + if (str.length) + res.str= strmake_root(root, str.str, str.length); + else + res.str= (const char *)""; + res.length= str.length; + return res; +} diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c index 51da6be7935..33ed230a4ce 100644 --- a/mysys/my_chsize.c +++ b/mysys/my_chsize.c @@ -96,6 +96,6 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags) err: DBUG_PRINT("error", ("errno: %d", errno)); if (MyFlags & MY_WME) - my_error(EE_CANT_CHSIZE, MYF(ME_BELL+ME_WAITTANG), my_errno); + my_error(EE_CANT_CHSIZE, MYF(ME_BELL), my_errno); DBUG_RETURN(1); } /* my_chsize */ diff --git a/mysys/my_copy.c b/mysys/my_copy.c index bd23dfc48cd..3360b41f64d 100644 --- a/mysys/my_copy.c +++ b/mysys/my_copy.c @@ -112,7 +112,7 @@ int my_copy(const char *from, const char *to, myf MyFlags) { my_errno= errno; if (MyFlags & MY_WME) - my_error(EE_CHANGE_PERMISSIONS, MYF(ME_BELL+ME_WAITTANG), to, errno); + my_error(EE_CHANGE_PERMISSIONS, MYF(ME_BELL), to, errno); if (MyFlags & MY_FAE) goto err; } @@ -122,7 +122,7 @@ int my_copy(const char *from, const char *to, myf MyFlags) { my_errno= errno; if (MyFlags & MY_WME) - my_error(EE_CANT_COPY_OWNERSHIP, MYF(ME_BELL+ME_WAITTANG), to, errno); + my_error(EE_CANT_COPY_OWNERSHIP, MYF(ME_BELL), to, errno); if (MyFlags & MY_FAE) goto err; } diff --git a/mysys/my_delete.c b/mysys/my_delete.c index beece473a01..cba24f90565 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -46,11 +46,9 @@ int my_delete(const char *name, myf MyFlags) { my_errno=errno; if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_DELETE,MYF(ME_BELL+ME_WAITTANG+(MyFlags & ME_NOINPUT)), - name,errno); + my_error(EE_DELETE, MYF(ME_BELL), name, errno); } - else if ((MyFlags & MY_SYNC_DIR) && - my_sync_dir_by_file(name, MyFlags)) + else if ((MyFlags & MY_SYNC_DIR) && my_sync_dir_by_file(name, MyFlags)) err= -1; DBUG_RETURN(err); } /* my_delete */ diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 59baeaec744..3dc38cbe29b 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -76,7 +76,7 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) DBUG_PRINT("error",("Got error %d on open",my_errno)); if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) my_error((flags & O_RDONLY) ? EE_FILENOTFOUND : EE_CANTCREATEFILE, - MYF(ME_BELL+ME_WAITTANG), filename, my_errno); + MYF(ME_BELL), filename, my_errno); DBUG_RETURN((FILE*) 0); } /* my_fopen */ @@ -182,8 +182,7 @@ int my_fclose(FILE *fd, myf MyFlags) { my_errno=errno; if (MyFlags & (MY_FAE | MY_WME)) - my_error(EE_BADCLOSE, MYF(ME_BELL+ME_WAITTANG), - name,errno); + my_error(EE_BADCLOSE, MYF(ME_BELL), name, errno); } else statistic_decrement(my_stream_opened, &THR_LOCK_open); @@ -217,7 +216,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) { my_errno=errno; if (MyFlags & (MY_FAE | MY_WME)) - my_error(EE_CANT_OPEN_STREAM, MYF(ME_BELL+ME_WAITTANG),errno); + my_error(EE_CANT_OPEN_STREAM, MYF(ME_BELL), errno); } else { diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c index bfcf24bfa2e..7d49564a01f 100644 --- a/mysys/my_fstream.c +++ b/mysys/my_fstream.c @@ -55,11 +55,11 @@ size_t my_fread(FILE *stream, uchar *Buffer, size_t Count, myf MyFlags) if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { if (ferror(stream)) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), + my_error(EE_READ, MYF(ME_BELL), my_filename(my_fileno(stream)),errno); else if (MyFlags & (MY_NABP | MY_FNABP)) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), + my_error(EE_EOFERR, MYF(ME_BELL), my_filename(my_fileno(stream)),errno); } my_errno=errno ? errno : -1; @@ -140,8 +140,8 @@ size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags) { if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { - my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG), - my_filename(my_fileno(stream)),errno); + my_error(EE_WRITE, MYF(ME_BELL), + my_filename(my_fileno(stream)), errno); } writtenbytes= (size_t) -1; /* Return that we got error */ break; diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c index 46710e79f62..978f34f2e89 100644 --- a/mysys/my_getwd.c +++ b/mysys/my_getwd.c @@ -64,7 +64,7 @@ int my_getwd(char * buf, size_t size, myf MyFlags) if (!getcwd(buf,(uint) (size-2)) && MyFlags & MY_WME) { my_errno=errno; - my_error(EE_GETWD,MYF(ME_BELL+ME_WAITTANG),errno); + my_error(EE_GETWD,MYF(ME_BELL),errno); DBUG_RETURN(-1); } #elif defined(HAVE_GETWD) @@ -104,7 +104,7 @@ int my_setwd(const char *dir, myf MyFlags) { my_errno=errno; if (MyFlags & MY_WME) - my_error(EE_SETWD,MYF(ME_BELL+ME_WAITTANG),start,errno); + my_error(EE_SETWD,MYF(ME_BELL),start,errno); } else { diff --git a/mysys/my_lib.c b/mysys/my_lib.c index dc6b7cfd292..7b734182499 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -185,7 +185,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) (void) closedir(dirp); my_dirend(&dirh->dir); if (MyFlags & (MY_FAE | MY_WME)) - my_error(EE_DIR, MYF(ME_BELL | ME_WAITTANG), path, my_errno); + my_error(EE_DIR, MYF(ME_BELL), path, my_errno); DBUG_RETURN(NULL); } /* my_dir */ @@ -308,7 +308,7 @@ error: _findclose(handle); my_dirend(&dirh->dir); if (MyFlags & (MY_FAE | MY_WME)) - my_error(EE_DIR,MYF(ME_BELL | ME_WAITTANG), path, errno); + my_error(EE_DIR,MYF(ME_BELL), path, errno); DBUG_RETURN(NULL); } /* my_dir */ @@ -358,7 +358,7 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags) error: if (my_flags & (MY_FAE+MY_WME)) { - my_error(EE_STAT, MYF(ME_BELL+ME_WAITTANG),path,my_errno); + my_error(EE_STAT, MYF(ME_BELL), path, my_errno); DBUG_RETURN((MY_STAT *) NULL); } DBUG_RETURN((MY_STAT *) NULL); diff --git a/mysys/my_lock.c b/mysys/my_lock.c index 34b1723e13c..fb3f1ceaba9 100644 --- a/mysys/my_lock.c +++ b/mysys/my_lock.c @@ -219,9 +219,9 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, if (MyFlags & MY_WME) { if (locktype == F_UNLCK) - my_error(EE_CANTUNLOCK,MYF(ME_BELL+ME_WAITTANG),my_errno); + my_error(EE_CANTUNLOCK,MYF(ME_BELL),my_errno); else - my_error(EE_CANTLOCK,MYF(ME_BELL+ME_WAITTANG),my_errno); + my_error(EE_CANTLOCK,MYF(ME_BELL),my_errno); } DBUG_PRINT("error",("my_errno: %d (%d)",my_errno,errno)); DBUG_RETURN(-1); diff --git a/mysys/my_lockmem.c b/mysys/my_lockmem.c index 3e27564f100..674f4700f79 100644 --- a/mysys/my_lockmem.c +++ b/mysys/my_lockmem.c @@ -43,7 +43,7 @@ uchar *my_malloc_lock(uint size,myf MyFlags) if (!(ptr=memalign(pagesize,size))) { if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_FATALERROR), size); + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATAL), size); DBUG_RETURN(0); } success = mlock((uchar*) ptr,size); diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index 6a3ec8da093..cdf59d4b8cc 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -106,8 +106,7 @@ void *my_malloc(size_t size, myf my_flags) if (my_flags & MY_FAE) error_handler_hook=fatal_error_handler_hook; if (my_flags & (MY_FAE+MY_WME)) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL + ME_WAITTANG + - ME_NOREFRESH + ME_FATALERROR),size); + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_ERROR_LOG+ME_FATAL),size); if (my_flags & MY_FAE) abort(); } @@ -175,7 +174,7 @@ void *my_realloc(void *oldpoint, size_t size, myf my_flags) DBUG_RETURN(oldpoint); my_errno=errno; if (my_flags & (MY_FAE+MY_WME)) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL + ME_WAITTANG + ME_FATALERROR), size); + my_error(EE_OUTOFMEMORY, MYF(ME_BELL + ME_FATAL), size); } else { diff --git a/mysys/my_mkdir.c b/mysys/my_mkdir.c index 5e9691f5b91..505c312ad56 100644 --- a/mysys/my_mkdir.c +++ b/mysys/my_mkdir.c @@ -36,7 +36,7 @@ int my_mkdir(const char *dir, int Flags, myf MyFlags) my_errno=errno; DBUG_PRINT("error",("error %d when creating direcory %s",my_errno,dir)); if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) - my_error(EE_CANT_MKDIR, MYF(ME_BELL+ME_WAITTANG), dir, my_errno); + my_error(EE_CANT_MKDIR, MYF(ME_BELL), dir, my_errno); DBUG_RETURN(-1); } DBUG_RETURN(0); diff --git a/mysys/my_once.c b/mysys/my_once.c index dfd5de81ac7..1a719a62fbf 100644 --- a/mysys/my_once.c +++ b/mysys/my_once.c @@ -59,7 +59,7 @@ void* my_once_alloc(size_t Size, myf MyFlags) { my_errno=errno; if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_FATALERROR), get_size); + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATAL), get_size); return((uchar*) 0); } DBUG_PRINT("test",("my_once_malloc %lu byte malloced", (ulong) get_size)); diff --git a/mysys/my_open.c b/mysys/my_open.c index 54e53089da9..4793e24373a 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -101,7 +101,7 @@ int my_close(File fd, myf MyFlags) DBUG_PRINT("error",("Got error %d on close",err)); my_errno=errno; if (MyFlags & (MY_FAE | MY_WME)) - my_error(EE_BADCLOSE, MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))), + my_error(EE_BADCLOSE, MYF(ME_BELL | (MyFlags & (ME_NOTE | ME_ERROR_LOG))), name,errno); } if (name) @@ -156,7 +156,7 @@ File my_register_filename(File fd, const char *FileName, enum file_type if (my_errno == EMFILE) error_message_number= EE_OUT_OF_FILERESOURCES; my_error(error_message_number, - MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))), + MYF(ME_BELL | (MyFlags & (ME_NOTE | ME_ERROR_LOG))), FileName, my_errno); } DBUG_RETURN(-1); diff --git a/mysys/my_pread.c b/mysys/my_pread.c index 2b3bfdc9e3d..2b7ce4bc0d6 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -96,11 +96,11 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, { if (readbytes == (size_t) -1) my_error(EE_READ, - MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))), + MYF(ME_BELL | (MyFlags & (ME_NOTE | ME_ERROR_LOG))), my_filename(Filedes),my_errno); else if (MyFlags & (MY_NABP | MY_FNABP)) my_error(EE_EOFERR, - MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))), + MYF(ME_BELL | (MyFlags & (ME_NOTE | ME_ERROR_LOG))), my_filename(Filedes),my_errno); } if (readbytes == (size_t) -1 || (MyFlags & (MY_FNABP | MY_NABP))) @@ -185,7 +185,7 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count, if (MyFlags & (MY_NABP | MY_FNABP)) { if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) - my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))), + my_error(EE_WRITE, MYF(ME_BELL | (MyFlags & (ME_NOTE | ME_ERROR_LOG))), my_filename(Filedes),my_errno); DBUG_RETURN(MY_FILE_ERROR); /* Error on write */ } diff --git a/mysys/my_read.c b/mysys/my_read.c index 89b368e9800..b0a03ac03b6 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -90,11 +90,11 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) { if (readbytes == (size_t) -1) my_error(EE_READ, - MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))), + MYF(ME_BELL | (MyFlags & (ME_NOTE | ME_ERROR_LOG))), my_filename(Filedes), got_errno); else if (MyFlags & (MY_NABP | MY_FNABP)) my_error(EE_EOFERR, - MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))), + MYF(ME_BELL | (MyFlags & (ME_NOTE | ME_ERROR_LOG))), my_filename(Filedes), got_errno); } if (readbytes == (size_t) -1 || diff --git a/mysys/my_redel.c b/mysys/my_redel.c index 9091c74e6b5..8bf81ae2876 100644 --- a/mysys/my_redel.c +++ b/mysys/my_redel.c @@ -102,7 +102,7 @@ int my_copystat(const char *from, const char *to, int MyFlags) { my_errno= errno; if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_CHANGE_PERMISSIONS, MYF(ME_BELL+ME_WAITTANG), from, errno); + my_error(EE_CHANGE_PERMISSIONS, MYF(ME_BELL), from, errno); return -1; } @@ -110,14 +110,14 @@ int my_copystat(const char *from, const char *to, int MyFlags) if (statbuf.st_nlink > 1 && MyFlags & MY_LINK_WARNING) { if (MyFlags & MY_LINK_WARNING) - my_error(EE_LINK_WARNING,MYF(ME_BELL+ME_WAITTANG),from,statbuf.st_nlink); + my_error(EE_LINK_WARNING,MYF(ME_BELL),from,statbuf.st_nlink); } /* Copy ownership */ if (chown(to, statbuf.st_uid, statbuf.st_gid)) { my_errno= errno; if (MyFlags & MY_WME) - my_error(EE_CHANGE_OWNERSHIP, MYF(ME_BELL+ME_WAITTANG), from, errno); + my_error(EE_CHANGE_OWNERSHIP, MYF(ME_BELL), from, errno); if (MyFlags & MY_FAE) return -1; } diff --git a/mysys/my_rename.c b/mysys/my_rename.c index 17f693629a8..f3831c2e73e 100644 --- a/mysys/my_rename.c +++ b/mysys/my_rename.c @@ -45,7 +45,7 @@ int my_rename(const char *from, const char *to, myf MyFlags) my_errno= errno; error = -1; if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG),from,to,my_errno); + my_error(EE_LINK, MYF(ME_BELL),from,to,my_errno); } else if (MyFlags & MY_SYNC_DIR) { diff --git a/mysys/my_setuser.c b/mysys/my_setuser.c index 14ab04dd10f..e35d6602aca 100644 --- a/mysys/my_setuser.c +++ b/mysys/my_setuser.c @@ -27,7 +27,7 @@ struct passwd *my_check_user(const char *user, myf MyFlags) my_errno= EPERM; if (MyFlags & MY_WME) my_printf_error(my_errno, "One can only use the --user switch if " - "running as root", MYF(ME_JUST_WARNING|ME_NOREFRESH)); + "running as root", MYF(ME_WARNING|ME_ERROR_LOG)); } } DBUG_RETURN(NULL); @@ -38,7 +38,7 @@ struct passwd *my_check_user(const char *user, myf MyFlags) { my_errno= EINVAL; my_printf_error(my_errno, "Please consult the Knowledge Base to find " - "out how to run mysqld as root!", MYF(ME_NOREFRESH)); + "out how to run mysqld as root!", MYF(ME_ERROR_LOG)); } DBUG_RETURN(NULL); } @@ -54,7 +54,7 @@ struct passwd *my_check_user(const char *user, myf MyFlags) { my_errno= EINVAL; my_printf_error(my_errno, "Can't change to run as user '%s'. Please " - "check that the user exists!", MYF(ME_NOREFRESH), user); + "check that the user exists!", MYF(ME_ERROR_LOG), user); DBUG_RETURN(NULL); } } @@ -74,7 +74,7 @@ int my_set_user(const char *user, struct passwd *user_info, myf MyFlags) { my_errno= errno; if (MyFlags & MY_WME) - my_printf_error(errno, "Cannot change uid/gid (errno: %d)", MYF(ME_NOREFRESH), + my_printf_error(errno, "Cannot change uid/gid (errno: %d)", MYF(ME_ERROR_LOG), errno); DBUG_RETURN(my_errno); } diff --git a/mysys/my_static.c b/mysys/my_static.c index f2a9fbb7335..7b69deea8e1 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -102,7 +102,7 @@ my_bool my_disable_copystat_in_redel=0; /* Typelib by all clients */ const char *sql_protocol_names_lib[] = -{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS }; +{ "TCP", "SOCKET", "PIPE", NullS }; TYPELIB sql_protocol_typelib ={ array_elements(sql_protocol_names_lib) - 1, "", sql_protocol_names_lib, NULL }; diff --git a/mysys/my_sync.c b/mysys/my_sync.c index cf8dfb6a8c8..575bbb9f748 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -122,7 +122,7 @@ int my_sync(File fd, myf my_flags) res= 0; } else if (my_flags & MY_WME) - my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno); + my_error(EE_SYNC, MYF(ME_BELL), my_filename(fd), my_errno); } else { diff --git a/mysys/my_write.c b/mysys/my_write.c index 43735c18f0a..f6e304f9a4e 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -107,7 +107,7 @@ size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags) { if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { - my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))), + my_error(EE_WRITE, MYF(ME_BELL | (MyFlags & (ME_NOTE | ME_ERROR_LOG))), my_filename(Filedes),my_errno); } DBUG_RETURN(MY_FILE_ERROR); /* Error on read */ diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 357923cf388..09c4984c069 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -731,7 +731,8 @@ static void *signal_hand(void *arg __attribute__((unused))) DBUG_PRINT("info",("Starting signal and alarm handling thread")); for(;;) { - while ((error=my_sigwait(&set,&sig)) == EINTR) + int code; + while ((error=my_sigwait(&set,&sig,&code)) == EINTR) printf("sigwait restarted\n"); if (error) { @@ -805,8 +806,7 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) /* Start signal thread and wait for it to start */ mysql_mutex_lock(&LOCK_thread_count); - mysql_thread_create(0, - &tid, &thr_attr, signal_hand, NULL); + mysql_thread_create(0, &tid, &thr_attr, signal_hand, NULL); mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); mysql_mutex_unlock(&LOCK_thread_count); DBUG_PRINT("info",("signal thread created")); diff --git a/plugin/auth_ed25519/server_ed25519.c b/plugin/auth_ed25519/server_ed25519.c index 23b4e7389c7..06c25558653 100644 --- a/plugin/auth_ed25519/server_ed25519.c +++ b/plugin/auth_ed25519/server_ed25519.c @@ -36,16 +36,6 @@ static int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) int pkt_len; unsigned long nonce[CRYPTO_LONGS + NONCE_LONGS]; unsigned char *pkt, *reply= (unsigned char*)nonce; - unsigned char pk[PASSWORD_LEN_BUF/4*3]; - char pw[PASSWORD_LEN_BUF]; - - /* prepare the pk */ - if (info->auth_string_length != PASSWORD_LEN) - return CR_AUTH_USER_CREDENTIALS; - memcpy(pw, info->auth_string, PASSWORD_LEN); - pw[PASSWORD_LEN]= '='; - if (my_base64_decode(pw, PASSWORD_LEN_BUF, pk, NULL, 0) != CRYPTO_PUBLICKEYBYTES) - return CR_AUTH_USER_CREDENTIALS; info->password_used= PASSWORD_USED_YES; @@ -62,17 +52,46 @@ static int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) return CR_AUTH_HANDSHAKE; memcpy(reply, pkt, CRYPTO_BYTES); - if (crypto_sign_open(reply, CRYPTO_BYTES + NONCE_BYTES, pk)) + if (crypto_sign_open(reply, CRYPTO_BYTES + NONCE_BYTES, + (unsigned char*)info->auth_string)) return CR_ERROR; return CR_OK; } +static int compute_password_digest(const char *pw, size_t pwlen, + char *d, size_t *dlen) +{ + unsigned char pk[CRYPTO_PUBLICKEYBYTES]; + if (*dlen < PASSWORD_LEN || pwlen == 0) + return 1; + *dlen= PASSWORD_LEN; + crypto_sign_keypair(pk, (unsigned char*)pw, pwlen); + my_base64_encode(pk, CRYPTO_PUBLICKEYBYTES, d); + return 0; +} + +static int digest_to_binary(const char *d, size_t dlen, + unsigned char *b, size_t *blen) +{ + char pw[PASSWORD_LEN_BUF]; + + if (*blen < CRYPTO_PUBLICKEYBYTES || dlen != PASSWORD_LEN) + return 1; + + *blen= CRYPTO_PUBLICKEYBYTES; + memcpy(pw, d, PASSWORD_LEN); + pw[PASSWORD_LEN]= '='; + return my_base64_decode(pw, PASSWORD_LEN_BUF, b, 0, 0) != CRYPTO_PUBLICKEYBYTES; +} + static struct st_mysql_auth info = { MYSQL_AUTHENTICATION_INTERFACE_VERSION, "client_ed25519", - auth + auth, + compute_password_digest, + digest_to_binary }; static int init(void *p __attribute__((unused))) @@ -97,10 +116,10 @@ maria_declare_plugin(ed25519) PLUGIN_LICENSE_GPL, init, deinit, - 0x0100, + 0x0101, NULL, NULL, - "1.0", + "1.1", MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; diff --git a/plugin/auth_examples/dialog_examples.c b/plugin/auth_examples/dialog_examples.c index 067244d6f7d..1c96c8d7faf 100644 --- a/plugin/auth_examples/dialog_examples.c +++ b/plugin/auth_examples/dialog_examples.c @@ -81,7 +81,8 @@ static struct st_mysql_auth two_handler= { MYSQL_AUTHENTICATION_INTERFACE_VERSION, "dialog", /* requires dialog client plugin */ - two_questions + two_questions, + NULL, NULL /* no PASSWORD() */ }; /* dialog demo where the number of questions is not known in advance */ @@ -118,7 +119,8 @@ static struct st_mysql_auth three_handler= { MYSQL_AUTHENTICATION_INTERFACE_VERSION, "dialog", /* requires dialog client plugin */ - three_attempts + three_attempts, + NULL, NULL /* no PASSWORD() */ }; mysql_declare_plugin(dialog) diff --git a/plugin/auth_examples/qa_auth_interface.c b/plugin/auth_examples/qa_auth_interface.c index 08ddbf7f30a..70050cf0d91 100644 --- a/plugin/auth_examples/qa_auth_interface.c +++ b/plugin/auth_examples/qa_auth_interface.c @@ -136,7 +136,8 @@ static struct st_mysql_auth qa_auth_test_handler= { MYSQL_AUTHENTICATION_INTERFACE_VERSION, "qa_auth_interface", /* requires test_plugin client's plugin */ - qa_auth_interface + qa_auth_interface, + NULL, NULL /* no PASSWORD() */ }; mysql_declare_plugin(test_plugin) diff --git a/plugin/auth_examples/qa_auth_server.c b/plugin/auth_examples/qa_auth_server.c index 59b926b63dc..0ed16b692cf 100644 --- a/plugin/auth_examples/qa_auth_server.c +++ b/plugin/auth_examples/qa_auth_server.c @@ -56,7 +56,8 @@ static struct st_mysql_auth qa_auth_test_handler= { MYSQL_AUTHENTICATION_INTERFACE_VERSION, "qa_auth_interface", /* requires test_plugin client's plugin */ - qa_auth_interface + qa_auth_interface, + NULL, NULL /* no PASSWORD() */ }; mysql_declare_plugin(test_plugin) diff --git a/plugin/auth_examples/test_plugin.c b/plugin/auth_examples/test_plugin.c index 8cc17894be4..e2d79d753f4 100644 --- a/plugin/auth_examples/test_plugin.c +++ b/plugin/auth_examples/test_plugin.c @@ -69,7 +69,8 @@ static struct st_mysql_auth auth_test_handler= { MYSQL_AUTHENTICATION_INTERFACE_VERSION, "auth_test_plugin", /* requires test_plugin client's plugin */ - auth_test_plugin + auth_test_plugin, + NULL, NULL /* no PASSWORD() */ }; /** @@ -99,7 +100,8 @@ static struct st_mysql_auth auth_cleartext_handler= { MYSQL_AUTHENTICATION_INTERFACE_VERSION, "mysql_clear_password", /* requires the clear text plugin */ - auth_cleartext_plugin + auth_cleartext_plugin, + NULL, NULL /* no PASSWORD() */ }; mysql_declare_plugin(test_plugin) diff --git a/plugin/auth_pam/CMakeLists.txt b/plugin/auth_pam/CMakeLists.txt index 51317527c77..fbf0979cd1e 100644 --- a/plugin/auth_pam/CMakeLists.txt +++ b/plugin/auth_pam/CMakeLists.txt @@ -8,6 +8,15 @@ IF(HAVE_PAM_APPL_H) IF(HAVE_STRNDUP) ADD_DEFINITIONS(-DHAVE_STRNDUP) ENDIF(HAVE_STRNDUP) - MYSQL_ADD_PLUGIN(auth_pam auth_pam.c LINK_LIBRARIES pam MODULE_ONLY) + ADD_DEFINITIONS(-D_GNU_SOURCE) + MYSQL_ADD_PLUGIN(auth_pam_v1 auth_pam_v1.c LINK_LIBRARIES pam MODULE_ONLY) + MYSQL_ADD_PLUGIN(auth_pam auth_pam.c LINK_LIBRARIES pam dl MODULE_ONLY) + MYSQL_ADD_EXECUTABLE(auth_pam_tool auth_pam_tool.c DESTINATION ${INSTALL_PLUGINDIR}/auth_pam_tool_dir COMPONENT Server) + TARGET_LINK_LIBRARIES(auth_pam_tool pam) + INSTALL(CODE "EXECUTE_PROCESS( + COMMAND chmod u=rwx,g=,o= auth_pam_tool_dir + COMMAND chmod u=rwxs,g=rx,o=rx auth_pam_tool_dir/auth_pam_tool + WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${INSTALL_PLUGINDIR}/)" + COMPONENT Server) ENDIF(HAVE_PAM_APPL_H) diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c index ffc3d6f5537..1ffc3285a3d 100644 --- a/plugin/auth_pam/auth_pam.c +++ b/plugin/auth_pam/auth_pam.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, 2012, Monty Program Ab + Copyright (c) 2011, 2018 MariaDB Corporation 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 @@ -14,36 +14,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#define _GNU_SOURCE 1 /* for strndup */ -#include <mysql/plugin_auth.h> -#include <stdio.h> +#include <unistd.h> #include <string.h> -#include <security/pam_appl.h> -#include <security/pam_modules.h> - -struct param { - unsigned char buf[10240], *ptr; - MYSQL_PLUGIN_VIO *vio; -}; - -/* It least solaris doesn't have strndup */ - -#ifndef HAVE_STRNDUP -char *strndup(const char *from, size_t length) -{ - char *ptr; - size_t max_length= strlen(from); - if (length > max_length) - length= max_length; - if ((ptr= (char*) malloc(length+1)) != 0) - { - memcpy((char*) ptr, (char*) from, length); - ptr[length]=0; - } - return ptr; -} -#endif +#include <mysql/plugin_auth.h> +#include "auth_pam_tool.h" +#include <my_global.h> #ifndef DBUG_OFF static char pam_debug = 0; @@ -52,158 +28,163 @@ static char pam_debug = 0; #define PAM_DEBUG(X) /* no-op */ #endif -static int conv(int n, const struct pam_message **msg, - struct pam_response **resp, void *data) +static char *opt_plugin_dir; /* To be dynamically linked. */ +static const char *tool_name= "auth_pam_tool_dir/auth_pam_tool"; +static const int tool_name_len= 31; + +static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { - struct param *param = (struct param *)data; - unsigned char *end = param->buf + sizeof(param->buf) - 1; - int i; + int p_to_c[2], c_to_p[2]; /* Parent-to-child and child-to-parent pipes. */ + pid_t proc_id; + int result= CR_ERROR; + unsigned char field; - *resp = 0; + PAM_DEBUG((stderr, "PAM: opening pipes.\n")); + if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0) + { + /* Error creating pipes. */ + return CR_ERROR; + } + PAM_DEBUG((stderr, "PAM: forking.\n")); + if ((proc_id= fork()) < 0) + { + /* Error forking. */ + close(p_to_c[0]); + close(c_to_p[1]); + goto error_ret; + } - for (i = 0; i < n; i++) + if (proc_id == 0) { - /* if there's a message - append it to the buffer */ - if (msg[i]->msg) + /* The 'sandbox' process started. */ + char toolpath[FN_REFLEN]; + size_t plugin_dir_len= strlen(opt_plugin_dir); + + PAM_DEBUG((stderr, "PAM: Child process prepares pipes.\n")); + + if (close(p_to_c[1]) < 0 || + close(c_to_p[0]) < 0 || + dup2(p_to_c[0], 0) < 0 || /* Parent's pipe to STDIN. */ + dup2(c_to_p[1], 1) < 0) /* Sandbox's pipe to STDOUT. */ { - int len = strlen(msg[i]->msg); - if (len > end - param->ptr) - len = end - param->ptr; - if (len > 0) - { - memcpy(param->ptr, msg[i]->msg, len); - param->ptr+= len; - *(param->ptr)++ = '\n'; - } + exit(-1); } - /* if the message style is *_PROMPT_*, meaning PAM asks a question, - send the accumulated text to the client, read the reply */ - if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF || - msg[i]->msg_style == PAM_PROMPT_ECHO_ON) + + PAM_DEBUG((stderr, "PAM: check tool directory: %s, %s.\n", + opt_plugin_dir, tool_name)); + if (plugin_dir_len + tool_name_len + 2 > sizeof(toolpath)) { - int pkt_len; - unsigned char *pkt; + /* Tool path too long. */ + exit(-1); + } - /* allocate the response array. - freeing it is the responsibility of the caller */ - if (*resp == 0) - { - *resp = calloc(sizeof(struct pam_response), n); - if (*resp == 0) - return PAM_BUF_ERR; - } + memcpy(toolpath, opt_plugin_dir, plugin_dir_len); + if (plugin_dir_len && toolpath[plugin_dir_len-1] != FN_LIBCHAR) + toolpath[plugin_dir_len++]= FN_LIBCHAR; + memcpy(toolpath+plugin_dir_len, tool_name, tool_name_len+1); - /* dialog plugin interprets the first byte of the packet - as the magic number. - 2 means "read the input with the echo enabled" - 4 means "password-like input, echo disabled" - C'est la vie. */ - param->buf[0] = msg[i]->msg_style == PAM_PROMPT_ECHO_ON ? 2 : 4; - PAM_DEBUG((stderr, "PAM: conv: send(%.*s)\n", (int)(param->ptr - param->buf - 1), param->buf)); - if (param->vio->write_packet(param->vio, param->buf, param->ptr - param->buf - 1)) - return PAM_CONV_ERR; - - pkt_len = param->vio->read_packet(param->vio, &pkt); - if (pkt_len < 0) - { - PAM_DEBUG((stderr, "PAM: conv: recv() ERROR\n")); - return PAM_CONV_ERR; - } - PAM_DEBUG((stderr, "PAM: conv: recv(%.*s)\n", pkt_len, pkt)); - /* allocate and copy the reply to the response array */ - if (!((*resp)[i].resp= strndup((char*) pkt, pkt_len))) - return PAM_CONV_ERR; - param->ptr = param->buf + 1; - } + PAM_DEBUG((stderr, "PAM: execute pam sandbox [%s].\n", toolpath)); + (void) execl(toolpath, toolpath, NULL); + PAM_DEBUG((stderr, "PAM: exec() failed.\n")); + exit(-1); } - return PAM_SUCCESS; -} -#define DO(X) if ((status = (X)) != PAM_SUCCESS) goto end + /* Parent process continues. */ -#if defined(SOLARIS) || defined(__sun) -typedef void** pam_get_item_3_arg; -#else -typedef const void** pam_get_item_3_arg; -#endif + PAM_DEBUG((stderr, "PAM: parent continues.\n")); + if (close(p_to_c[0]) < 0 || + close(c_to_p[1]) < 0) + goto error_ret; -static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) -{ - pam_handle_t *pamh = NULL; - int status; - const char *new_username= NULL; - struct param param; - /* The following is written in such a way to make also solaris happy */ - struct pam_conv pam_start_arg = { &conv, (char*) ¶m }; - /* - get the service name, as specified in + PAM_DEBUG((stderr, "PAM: parent sends user data [%s], [%s].\n", + info->user_name, info->auth_string)); - CREATE USER ... IDENTIFIED WITH pam AS "service" - */ - const char *service = info->auth_string && info->auth_string[0] - ? info->auth_string : "mysql"; +#ifndef DBUG_OFF + field= pam_debug; +#else + field= 0; +#endif + if (write(p_to_c[1], &field, 1) != 1 || + write_string(p_to_c[1], (const uchar *) info->user_name, + info->user_name_length) || + write_string(p_to_c[1], (const uchar *) info->auth_string, + info->auth_string_length)) + goto error_ret; + + for (;;) + { + PAM_DEBUG((stderr, "PAM: listening to the sandbox.\n")); + if (read(c_to_p[0], &field, 1) < 1) + { + PAM_DEBUG((stderr, "PAM: read failed.\n")); + goto error_ret; + } - param.ptr = param.buf + 1; - param.vio = vio; + if (field == AP_EOF) + { + PAM_DEBUG((stderr, "PAM: auth OK returned.\n")); + break; + } - PAM_DEBUG((stderr, "PAM: pam_start(%s, %s)\n", service, info->user_name)); - DO( pam_start(service, info->user_name, &pam_start_arg, &pamh) ); + switch (field) + { + case AP_AUTHENTICATED_AS: + PAM_DEBUG((stderr, "PAM: reading authenticated_as string.\n")); + if (read_string(c_to_p[0], info->authenticated_as, + sizeof(info->authenticated_as) - 1) < 0) + goto error_ret; + break; + + case AP_CONV: + { + unsigned char buf[10240]; + int buf_len; + unsigned char *pkt; - PAM_DEBUG((stderr, "PAM: pam_authenticate(0)\n")); - DO( pam_authenticate (pamh, 0) ); + PAM_DEBUG((stderr, "PAM: getting CONV string.\n")); + if ((buf_len= read_string(c_to_p[0], (char *) buf, sizeof(buf))) < 0) + goto error_ret; - PAM_DEBUG((stderr, "PAM: pam_acct_mgmt(0)\n")); - DO( pam_acct_mgmt(pamh, 0) ); + PAM_DEBUG((stderr, "PAM: sending CONV string.\n")); + if (vio->write_packet(vio, buf, buf_len)) + goto error_ret; - PAM_DEBUG((stderr, "PAM: pam_get_item(PAM_USER)\n")); - DO( pam_get_item(pamh, PAM_USER, (pam_get_item_3_arg) &new_username) ); + PAM_DEBUG((stderr, "PAM: reading CONV answer.\n")); + if ((buf_len= vio->read_packet(vio, &pkt)) < 0) + goto error_ret; - if (new_username && strcmp(new_username, info->user_name)) - strncpy(info->authenticated_as, new_username, - sizeof(info->authenticated_as)); - info->authenticated_as[sizeof(info->authenticated_as)-1]= 0; + PAM_DEBUG((stderr, "PAM: answering CONV.\n")); + if (write_string(p_to_c[1], pkt, buf_len)) + goto error_ret; + } + break; -end: - pam_end(pamh, status); - PAM_DEBUG((stderr, "PAM: status = %d user = %s\n", status, info->authenticated_as)); - return status == PAM_SUCCESS ? CR_OK : CR_ERROR; -} + default: + PAM_DEBUG((stderr, "PAM: unknown sandbox field.\n")); + goto error_ret; + } + } + result= CR_OK; -static struct st_mysql_auth info = -{ - MYSQL_AUTHENTICATION_INTERFACE_VERSION, - "dialog", - pam_auth -}; - -static char use_cleartext_plugin; -static MYSQL_SYSVAR_BOOL(use_cleartext_plugin, use_cleartext_plugin, - PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, - "Use mysql_cleartext_plugin on the client side instead of the dialog " - "plugin. This may be needed for compatibility reasons, but it only " - "supports simple PAM policies that don't require anything besides " - "a password", NULL, NULL, 0); +error_ret: + close(p_to_c[1]); + close(c_to_p[0]); -#ifndef DBUG_OFF -static MYSQL_SYSVAR_BOOL(debug, pam_debug, PLUGIN_VAR_OPCMDARG, - "Log all PAM activity", NULL, NULL, 0); -#endif + PAM_DEBUG((stderr, "PAM: auth result %d.\n", result)); + return result; +} -static struct st_mysql_sys_var* vars[] = { - MYSQL_SYSVAR(use_cleartext_plugin), -#ifndef DBUG_OFF - MYSQL_SYSVAR(debug), -#endif - NULL -}; +#include "auth_pam_common.c" static int init(void *p __attribute__((unused))) { if (use_cleartext_plugin) info.client_auth_plugin= "mysql_clear_password"; + if (!(opt_plugin_dir= dlsym(RTLD_DEFAULT, "opt_plugin_dir"))) + return 1; return 0; } @@ -212,15 +193,15 @@ maria_declare_plugin(pam) MYSQL_AUTHENTICATION_PLUGIN, &info, "pam", - "Sergei Golubchik", + "MariaDB Corp", "PAM based authentication", PLUGIN_LICENSE_GPL, init, NULL, - 0x0100, + 0x0200, NULL, vars, - "1.0", - MariaDB_PLUGIN_MATURITY_STABLE + "2.0", + MariaDB_PLUGIN_MATURITY_BETA } maria_declare_plugin_end; diff --git a/plugin/auth_pam/auth_pam_base.c b/plugin/auth_pam/auth_pam_base.c new file mode 100644 index 00000000000..68be0e92b71 --- /dev/null +++ b/plugin/auth_pam/auth_pam_base.c @@ -0,0 +1,179 @@ +/* + Copyright (c) 2011, 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +/* + This file contains code to interact with the PAM module. + To be included into auth_pam_tool.c and auth_pam_v2.c, + + Before the #include these sould be defined: + + struct param { + unsigned char buf[10240], *ptr; + MYSQL_PLUGIN_VIO *vio; + ... other arbitrary fields allowed. + }; + static int write_packet(struct param *param, const unsigned char *buf, + int buf_len) + static int read_packet(struct param *param, unsigned char **pkt) +*/ + +#include <stdio.h> +#include <string.h> +#include <security/pam_appl.h> +#include <security/pam_modules.h> + +/* It least solaris doesn't have strndup */ + +#ifndef HAVE_STRNDUP +char *strndup(const char *from, size_t length) +{ + char *ptr; + size_t max_length= strlen(from); + if (length > max_length) + length= max_length; + if ((ptr= (char*) malloc(length+1)) != 0) + { + memcpy((char*) ptr, (char*) from, length); + ptr[length]=0; + } + return ptr; +} +#endif + +#ifndef DBUG_OFF +static char pam_debug = 0; +#define PAM_DEBUG(X) do { if (pam_debug) { fprintf X; } } while(0) +#else +#define PAM_DEBUG(X) /* no-op */ +#endif + +static int conv(int n, const struct pam_message **msg, + struct pam_response **resp, void *data) +{ + struct param *param = (struct param *)data; + unsigned char *end = param->buf + sizeof(param->buf) - 1; + int i; + + *resp = 0; + + for (i = 0; i < n; i++) + { + /* if there's a message - append it to the buffer */ + if (msg[i]->msg) + { + int len = strlen(msg[i]->msg); + if (len > end - param->ptr) + len = end - param->ptr; + if (len > 0) + { + memcpy(param->ptr, msg[i]->msg, len); + param->ptr+= len; + *(param->ptr)++ = '\n'; + } + } + /* if the message style is *_PROMPT_*, meaning PAM asks a question, + send the accumulated text to the client, read the reply */ + if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF || + msg[i]->msg_style == PAM_PROMPT_ECHO_ON) + { + int pkt_len; + unsigned char *pkt; + + /* allocate the response array. + freeing it is the responsibility of the caller */ + if (*resp == 0) + { + *resp = calloc(sizeof(struct pam_response), n); + if (*resp == 0) + return PAM_BUF_ERR; + } + + /* dialog plugin interprets the first byte of the packet + as the magic number. + 2 means "read the input with the echo enabled" + 4 means "password-like input, echo disabled" + C'est la vie. */ + param->buf[0] = msg[i]->msg_style == PAM_PROMPT_ECHO_ON ? 2 : 4; + PAM_DEBUG((stderr, "PAM: conv: send(%.*s)\n", + (int)(param->ptr - param->buf - 1), param->buf)); + if (write_packet(param, param->buf, param->ptr - param->buf - 1)) + return PAM_CONV_ERR; + + pkt_len = read_packet(param, &pkt); + if (pkt_len < 0) + { + PAM_DEBUG((stderr, "PAM: conv: recv() ERROR\n")); + return PAM_CONV_ERR; + } + PAM_DEBUG((stderr, "PAM: conv: recv(%.*s)\n", pkt_len, pkt)); + /* allocate and copy the reply to the response array */ + if (!((*resp)[i].resp= strndup((char*) pkt, pkt_len))) + return PAM_CONV_ERR; + param->ptr = param->buf + 1; + } + } + return PAM_SUCCESS; +} + +#define DO(X) if ((status = (X)) != PAM_SUCCESS) goto end + +#if defined(SOLARIS) || defined(__sun) +typedef void** pam_get_item_3_arg; +#else +typedef const void** pam_get_item_3_arg; +#endif + +static int pam_auth_base(struct param *param, MYSQL_SERVER_AUTH_INFO *info) +{ + pam_handle_t *pamh = NULL; + int status; + const char *new_username= NULL; + /* The following is written in such a way to make also solaris happy */ + struct pam_conv pam_start_arg = { &conv, (char*) param }; + + /* + get the service name, as specified in + + CREATE USER ... IDENTIFIED WITH pam AS "service" + */ + const char *service = info->auth_string && info->auth_string[0] + ? info->auth_string : "mysql"; + + param->ptr = param->buf + 1; + + PAM_DEBUG((stderr, "PAM: pam_start(%s, %s)\n", service, info->user_name)); + DO( pam_start(service, info->user_name, &pam_start_arg, &pamh) ); + + PAM_DEBUG((stderr, "PAM: pam_authenticate(0)\n")); + DO( pam_authenticate (pamh, 0) ); + + PAM_DEBUG((stderr, "PAM: pam_acct_mgmt(0)\n")); + DO( pam_acct_mgmt(pamh, 0) ); + + PAM_DEBUG((stderr, "PAM: pam_get_item(PAM_USER)\n")); + DO( pam_get_item(pamh, PAM_USER, (pam_get_item_3_arg) &new_username) ); + + if (new_username && strcmp(new_username, info->user_name)) + strncpy(info->authenticated_as, new_username, + sizeof(info->authenticated_as)); + info->authenticated_as[sizeof(info->authenticated_as)-1]= 0; + +end: + pam_end(pamh, status); + PAM_DEBUG((stderr, "PAM: status = %d user = %s\n", status, info->authenticated_as)); + return status == PAM_SUCCESS ? CR_OK : CR_ERROR; +} + diff --git a/plugin/auth_pam/auth_pam_common.c b/plugin/auth_pam/auth_pam_common.c new file mode 100644 index 00000000000..135feb611a6 --- /dev/null +++ b/plugin/auth_pam/auth_pam_common.c @@ -0,0 +1,51 @@ +/* + Copyright (c) 2011, 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +/* + In this file we gather the plugin interface definitions + that are same in all the PAM plugin versions. + To be included into auth_pam.c and auth_pam_v1.c. +*/ + +static struct st_mysql_auth info = +{ + MYSQL_AUTHENTICATION_INTERFACE_VERSION, + "dialog", + pam_auth, + NULL, NULL /* no PASSWORD() */ +}; + +static char use_cleartext_plugin; +static MYSQL_SYSVAR_BOOL(use_cleartext_plugin, use_cleartext_plugin, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Use mysql_cleartext_plugin on the client side instead of the dialog " + "plugin. This may be needed for compatibility reasons, but it only " + "supports simple PAM policies that don't require anything besides " + "a password", NULL, NULL, 0); + +#ifndef DBUG_OFF +static MYSQL_SYSVAR_BOOL(debug, pam_debug, PLUGIN_VAR_OPCMDARG, + "Log all PAM activity", NULL, NULL, 0); +#endif + + +static struct st_mysql_sys_var* vars[] = { + MYSQL_SYSVAR(use_cleartext_plugin), +#ifndef DBUG_OFF + MYSQL_SYSVAR(debug), +#endif + NULL +}; diff --git a/plugin/auth_pam/auth_pam_tool.c b/plugin/auth_pam/auth_pam_tool.c new file mode 100644 index 00000000000..3f7015952a0 --- /dev/null +++ b/plugin/auth_pam/auth_pam_tool.c @@ -0,0 +1,121 @@ +/* + Copyright (c) 2011, 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +#include <stdlib.h> +#include <unistd.h> +#include <mysql/plugin_auth_common.h> + +struct param { + unsigned char buf[10240], *ptr; +}; + + +#include "auth_pam_tool.h" + + +static int write_packet(struct param *param __attribute__((unused)), + const unsigned char *buf, int buf_len) +{ + unsigned char b= AP_CONV; + return write(1, &b, 1) < 1 || + write_string(1, buf, buf_len); +} + + +static int read_packet(struct param *param, unsigned char **pkt) +{ + *pkt= (unsigned char *) param->buf; + return read_string(0, (char *) param->buf, (int) sizeof(param->buf)) - 1; +} + + +typedef struct st_mysql_server_auth_info +{ + /** + User name as sent by the client and shown in USER(). + NULL if the client packet with the user name was not received yet. + */ + char *user_name; + + /** + A corresponding column value from the mysql.user table for the + matching account name + */ + char *auth_string; + + /** + Matching account name as found in the mysql.user table. + A plugin can override it with another name that will be + used by MySQL for authorization, and shown in CURRENT_USER() + */ + char authenticated_as[MYSQL_USERNAME_LENGTH+1]; +} MYSQL_SERVER_AUTH_INFO; + + +#include "auth_pam_base.c" + + +int main(int argc, char **argv) +{ + struct param param; + MYSQL_SERVER_AUTH_INFO info; + unsigned char field; + int res; + char a_buf[MYSQL_USERNAME_LENGTH + 1 + 1024]; + + if (read(0, &field, 1) < 1) + return -1; +#ifndef DBUG_OFF + pam_debug= field; +#endif + + PAM_DEBUG((stderr, "PAM: sandbox started [%s].\n", argv[0])); + + info.user_name= a_buf; + if ((res= read_string(0, info.user_name, sizeof(a_buf))) < 0) + return -1; + PAM_DEBUG((stderr, "PAM: sandbox username [%s].\n", info.user_name)); + + info.auth_string= info.user_name + res + 1; + if (read_string(0, info.auth_string, sizeof(a_buf) - 1 - res) < 0) + return -1; + + PAM_DEBUG((stderr, "PAM: sandbox auth string [%s].\n", info.auth_string)); + + if ((res= pam_auth_base(¶m, &info)) != CR_OK) + { + PAM_DEBUG((stderr, "PAM: auth failed, sandbox closed.\n")); + return -1; + } + + if (info.authenticated_as[0]) + { + PAM_DEBUG((stderr, "PAM: send authenticated_as field.\n")); + field= AP_AUTHENTICATED_AS; + if (write(1, &field, 1) < 1 || + write_string(1, (unsigned char *) info.authenticated_as, + strlen(info.authenticated_as))) + return -1; + } + + PAM_DEBUG((stderr, "PAM: send OK result.\n")); + field= AP_EOF; + if (write(1, &field, 1) != 1) + return -1; + + PAM_DEBUG((stderr, "PAM: sandbox closed.\n")); + return 0; +} diff --git a/plugin/auth_pam/auth_pam_tool.h b/plugin/auth_pam/auth_pam_tool.h new file mode 100644 index 00000000000..60ae016db72 --- /dev/null +++ b/plugin/auth_pam/auth_pam_tool.h @@ -0,0 +1,81 @@ +/* + Copyright (c) 2011, 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +/* + This file contains definitions and functions for + the interface between the auth_pam.so (PAM plugin version 2) + and the auth_pam_tool executable. + To be included both in auth_pam.c and auth_pam_tool.c. +*/ + +#define AP_AUTHENTICATED_AS 'A' +#define AP_CONV 'C' +#define AP_EOF 'E' + + +static int read_length(int file) +{ + unsigned char hdr[2]; + + if (read(file, hdr, 2) < 2) + return -1; + + return (((int) hdr[0]) << 8) + (int) hdr[1]; +} + + +static void store_length(int len, unsigned char *p_len) +{ + p_len[0]= (unsigned char) ((len >> 8) & 0xFF); + p_len[1]= (unsigned char) (len & 0xFF); +} + + +/* + Returns the length of the string read, + or -1 on error. +*/ + +static int read_string(int file, char *s, int s_size) +{ + int len; + + len= read_length(file); + + if (len < 0 || len > s_size-1 || + read(file, s, len) < len) + return -1; + + s[len]= 0; + + return len; +} + + +/* + Returns 0 on success. +*/ + +static int write_string(int file, const unsigned char *s, int s_len) +{ + unsigned char hdr[2]; + store_length(s_len, hdr); + return write(file, hdr, 2) < 2 || + write(file, s, s_len) < s_len; +} + + +#define MAX_PAM_SERVICE_NAME 1024 diff --git a/plugin/auth_pam/auth_pam_v1.c b/plugin/auth_pam/auth_pam_v1.c new file mode 100644 index 00000000000..ab352b1492b --- /dev/null +++ b/plugin/auth_pam/auth_pam_v1.c @@ -0,0 +1,71 @@ +/* + Copyright (c) 2011, 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +#include <mysql/plugin_auth.h> + +struct param { + unsigned char buf[10240], *ptr; + MYSQL_PLUGIN_VIO *vio; +}; + +static int write_packet(struct param *param, const unsigned char *buf, + int buf_len) +{ + return param->vio->write_packet(param->vio, buf, buf_len); +} + +static int read_packet(struct param *param, unsigned char **pkt) +{ + return param->vio->read_packet(param->vio, pkt); +} + +#include "auth_pam_base.c" + +static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) +{ + struct param param; + param.vio = vio; + return pam_auth_base(¶m, info); +} + + +#include "auth_pam_common.c" + + +static int init(void *p __attribute__((unused))) +{ + if (use_cleartext_plugin) + info.client_auth_plugin= "mysql_clear_password"; + return 0; +} + +maria_declare_plugin(pam) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &info, + "pam", + "Sergei Golubchik", + "PAM based authentication", + PLUGIN_LICENSE_GPL, + init, + NULL, + 0x0100, + NULL, + vars, + "1.0", + MariaDB_PLUGIN_MATURITY_STABLE +} +maria_declare_plugin_end; diff --git a/plugin/auth_pam/testing/pam_mariadb_mtr.c b/plugin/auth_pam/testing/pam_mariadb_mtr.c index 473ec246fe0..44af584d7f0 100644 --- a/plugin/auth_pam/testing/pam_mariadb_mtr.c +++ b/plugin/auth_pam/testing/pam_mariadb_mtr.c @@ -58,7 +58,17 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, if (strlen(r1) == atoi(r2) % 100) retval = PAM_SUCCESS; else + { + /* Produce the crash for testing purposes. */ + if ((strlen(r1) == 16) && + memcmp(r1, "crash pam module", 16) == 0 && + atoi(r2) == 666) + { + r1= 0; + *((struct pam_message *) r1)= msg[0]; + } retval = PAM_AUTH_ERR; + } if (argc > 0 && argv[0]) pam_set_item(pamh, PAM_USER, argv[0]); diff --git a/plugin/auth_socket/auth_socket.c b/plugin/auth_socket/auth_socket.c index f04b1d9d2a1..2fc29e9ba1c 100644 --- a/plugin/auth_socket/auth_socket.c +++ b/plugin/auth_socket/auth_socket.c @@ -102,7 +102,8 @@ static struct st_mysql_auth socket_auth_handler= { MYSQL_AUTHENTICATION_INTERFACE_VERSION, 0, - socket_auth + socket_auth, + NULL, NULL /* no PASSWORD() */ }; maria_declare_plugin(auth_socket) diff --git a/plugin/aws_key_management/CMakeLists.txt b/plugin/aws_key_management/CMakeLists.txt index aa93fc3aa03..4620290000e 100644 --- a/plugin/aws_key_management/CMakeLists.txt +++ b/plugin/aws_key_management/CMakeLists.txt @@ -120,6 +120,12 @@ ELSE() SET(GIT_TAG "1.2.11") ENDIF() + IF(MSVC_CRT_TYPE MATCHES "/MD") + SET(FORCE_SHARED_CRT ON) + ELSE() + SET(FORCE_SHARED_CRT OFF) + ENDIF() + SET(AWS_SDK_PATCH_COMMAND ) ExternalProject_Add( aws_sdk_cpp @@ -131,7 +137,7 @@ ELSE() CMAKE_ARGS -DBUILD_ONLY=kms -DBUILD_SHARED_LIBS=OFF - -DFORCE_SHARED_CRT=OFF + -DFORCE_SHARED_CRT=${FORCE_SHARED_CRT} -DENABLE_TESTING=OFF "-DCMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG} ${PIC_FLAG}" "-DCMAKE_CXX_FLAGS_RELWITHDEBINFO=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${PIC_FLAG}" diff --git a/plugin/aws_key_management/aws_key_management_plugin.cc b/plugin/aws_key_management/aws_key_management_plugin.cc index eb330103291..00a2e5f8778 100644 --- a/plugin/aws_key_management/aws_key_management_plugin.cc +++ b/plugin/aws_key_management/aws_key_management_plugin.cc @@ -110,7 +110,7 @@ static void print_kms_error(const char *func, const Aws::Client::AWSError<Aws::K { my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin : KMS Client API '%s' failed : %s - %s", - ME_ERROR_LOG, + ME_ERROR_LOG_ONLY, func, err.GetExceptionName().c_str(), err.GetMessage().c_str()); } @@ -237,7 +237,7 @@ static int aws_init() client = new KMSClient(clientConfiguration); if (!client) { - my_printf_error(ER_UNKNOWN_ERROR, "Can not initialize KMS client", ME_ERROR_LOG | ME_WARNING); + my_printf_error(ER_UNKNOWN_ERROR, "Can't initialize KMS client", ME_ERROR_LOG_ONLY | ME_WARNING); return -1; } return 0; @@ -339,12 +339,12 @@ static int load_key(KEY_INFO *info) if (!ret) { - my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: loaded key %u, version %u, key length %u bit", ME_ERROR_LOG | ME_NOTE, + my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: loaded key %u, version %u, key length %u bit", ME_ERROR_LOG_ONLY | ME_NOTE, info->key_id, info->key_version,(uint)info->length*8); } else { - my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: key %u, version %u could not be decrypted", ME_ERROR_LOG | ME_WARNING, + my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: key %u, version %u could not be decrypted", ME_ERROR_LOG_ONLY | ME_WARNING, info->key_id, info->key_version); } return ret; @@ -443,13 +443,13 @@ static int read_and_decrypt_key(const char *path, KEY_INFO *info) ifstream ifs(path, ios::binary | ios::ate); if (!ifs.good()) { - my_printf_error(ER_UNKNOWN_ERROR, "can't open file %s", ME_ERROR_LOG, path); + my_printf_error(ER_UNKNOWN_ERROR, "can't open file %s", ME_ERROR_LOG_ONLY, path); return(-1); } size_t pos = (size_t)ifs.tellg(); if (!pos || pos == SIZE_T_MAX) { - my_printf_error(ER_UNKNOWN_ERROR, "invalid key file %s", ME_ERROR_LOG, path); + my_printf_error(ER_UNKNOWN_ERROR, "invalid key file %s", ME_ERROR_LOG_ONLY, path); return(-1); } std::vector<char> contents(pos); @@ -470,7 +470,7 @@ static int read_and_decrypt_key(const char *path, KEY_INFO *info) if (len > sizeof(info->data)) { - my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: encoding key too large for %s", ME_ERROR_LOG, path); + my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: encoding key too large for %s", ME_ERROR_LOG_ONLY, path); return(ENCRYPTION_KEY_BUFFER_TOO_SMALL); } memcpy(info->data, plaintext.GetUnderlyingData(), len); @@ -527,19 +527,19 @@ static int generate_and_save_datakey(uint keyid, uint version) int fd= open(filename, O_WRONLY |O_CREAT|O_BINARY, IF_WIN(_S_IREAD, S_IRUSR| S_IRGRP| S_IROTH)); if (fd < 0) { - my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: Can't create file %s", ME_ERROR_LOG, filename); + my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: Can't create file %s", ME_ERROR_LOG_ONLY, filename); return(-1); } unsigned int len= (unsigned int)byteBuffer.GetLength(); if (write(fd, byteBuffer.GetUnderlyingData(), len) != len) { - my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: can't write to %s", ME_ERROR_LOG, filename); + my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: can't write to %s", ME_ERROR_LOG_ONLY, filename); close(fd); unlink(filename); return(-1); } close(fd); - my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: generated encrypted datakey for key id=%u, version=%u", ME_ERROR_LOG | ME_NOTE, + my_printf_error(ER_UNKNOWN_ERROR, "AWS KMS plugin: generated encrypted datakey for key id=%u, version=%u", ME_ERROR_LOG_ONLY | ME_NOTE, keyid, version); return(0); } @@ -552,13 +552,13 @@ static int rotate_single_key(uint key_id) if (!ver) { - my_printf_error(ER_UNKNOWN_ERROR, "key %u does not exist", MYF(ME_JUST_WARNING), key_id); + my_printf_error(ER_UNKNOWN_ERROR, "key %u does not exist", MYF(ME_WARNING), key_id); return -1; } else if (generate_and_save_datakey(key_id, ver + 1)) { my_printf_error(ER_UNKNOWN_ERROR, "Could not generate datakey for key id= %u, ver= %u", - MYF(ME_JUST_WARNING), key_id, ver); + MYF(ME_WARNING), key_id, ver); return -1; } else @@ -569,7 +569,7 @@ static int rotate_single_key(uint key_id) if (load_key(&info)) { my_printf_error(ER_UNKNOWN_ERROR, "Could not load datakey for key id= %u, ver= %u", - MYF(ME_JUST_WARNING), key_id, ver); + MYF(ME_WARNING), key_id, ver); return -1; } } @@ -594,7 +594,7 @@ static void update_rotate(MYSQL_THD, struct st_mysql_sys_var *, void *, const vo if (!master_key_id[0]) { my_printf_error(ER_UNKNOWN_ERROR, - "aws_key_management_master_key_id must be set to generate new data keys", MYF(ME_JUST_WARNING)); + "aws_key_management_master_key_id must be set to generate new data keys", MYF(ME_WARNING)); return; } mtx.lock(); diff --git a/plugin/cracklib_password_check/cracklib_password_check.c b/plugin/cracklib_password_check/cracklib_password_check.c index 22d5eee21f2..d64ef990983 100644 --- a/plugin/cracklib_password_check/cracklib_password_check.c +++ b/plugin/cracklib_password_check/cracklib_password_check.c @@ -21,7 +21,8 @@ static char *dictionary; -static int crackme(MYSQL_CONST_LEX_STRING *username, MYSQL_CONST_LEX_STRING *password) +static int crackme(const MYSQL_CONST_LEX_STRING *username, + const MYSQL_CONST_LEX_STRING *password) { char *user= alloca(username->length + 1); char *host; diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc index 92f186a1e2a..b025879b6ee 100644 --- a/plugin/feedback/sender_thread.cc +++ b/plugin/feedback/sender_thread.cc @@ -117,11 +117,12 @@ static int prepare_for_fill(TABLE_LIST *tables) tables->init_one_table(&INFORMATION_SCHEMA_NAME, &tbl_name, 0, TL_READ); tables->schema_table= i_s_feedback; + tables->select_lex= thd->lex->first_select_lex(); + DBUG_ASSERT(tables->select_lex); tables->table= create_schema_table(thd, tables); if (!tables->table) return 1; - tables->select_lex= thd->lex->current_select; tables->table->pos_in_table_list= tables; return 0; diff --git a/plugin/metadata_lock_info/metadata_lock_info.cc b/plugin/metadata_lock_info/metadata_lock_info.cc index e32bbc55f3e..37c0ca3a460 100644 --- a/plugin/metadata_lock_info/metadata_lock_info.cc +++ b/plugin/metadata_lock_info/metadata_lock_info.cc @@ -21,7 +21,7 @@ #include "sql_show.h" static const LEX_STRING metadata_lock_info_lock_name[] = { - { C_STRING_WITH_LEN("Global read lock") }, + { C_STRING_WITH_LEN("Backup lock") }, { C_STRING_WITH_LEN("Schema metadata lock") }, { C_STRING_WITH_LEN("Table metadata lock") }, { C_STRING_WITH_LEN("Stored function metadata lock") }, @@ -29,23 +29,9 @@ static const LEX_STRING metadata_lock_info_lock_name[] = { { C_STRING_WITH_LEN("Stored package body metadata lock") }, { C_STRING_WITH_LEN("Trigger metadata lock") }, { C_STRING_WITH_LEN("Event metadata lock") }, - { C_STRING_WITH_LEN("Commit lock") }, { C_STRING_WITH_LEN("User lock") }, }; -static const LEX_STRING metadata_lock_info_lock_mode[] = { - { C_STRING_WITH_LEN("MDL_INTENTION_EXCLUSIVE") }, - { C_STRING_WITH_LEN("MDL_SHARED") }, - { C_STRING_WITH_LEN("MDL_SHARED_HIGH_PRIO") }, - { C_STRING_WITH_LEN("MDL_SHARED_READ") }, - { C_STRING_WITH_LEN("MDL_SHARED_WRITE") }, - { C_STRING_WITH_LEN("MDL_SHARED_UPGRADABLE") }, - { C_STRING_WITH_LEN("MDL_SHARED_READ_ONLY") }, - { C_STRING_WITH_LEN("MDL_SHARED_NO_WRITE") }, - { C_STRING_WITH_LEN("MDL_SHARED_NO_READ_WRITE") }, - { C_STRING_WITH_LEN("MDL_EXCLUSIVE") }, -}; - static ST_FIELD_INFO i_s_metadata_lock_info_fields_info[] = { {"THREAD_ID", 20, MYSQL_TYPE_LONGLONG, 0, @@ -71,22 +57,21 @@ struct st_i_s_metadata_param int i_s_metadata_lock_info_fill_row( MDL_ticket *mdl_ticket, - void *arg + void *arg, + bool granted ) { st_i_s_metadata_param *param = (st_i_s_metadata_param *) arg; THD *thd = param->thd; TABLE *table = param->table; DBUG_ENTER("i_s_metadata_lock_info_fill_row"); MDL_context *mdl_ctx = mdl_ticket->get_ctx(); - enum_mdl_type mdl_ticket_type = mdl_ticket->get_type(); MDL_key *mdl_key = mdl_ticket->get_key(); MDL_key::enum_mdl_namespace mdl_namespace = mdl_key->mdl_namespace(); + if (!granted) + DBUG_RETURN(0); table->field[0]->store((longlong) mdl_ctx->get_thread_id(), TRUE); table->field[1]->set_notnull(); - table->field[1]->store( - metadata_lock_info_lock_mode[(int) mdl_ticket_type].str, - metadata_lock_info_lock_mode[(int) mdl_ticket_type].length, - system_charset_info); + table->field[1]->store(mdl_ticket->get_type_name(), system_charset_info); table->field[2]->set_null(); table->field[3]->set_notnull(); table->field[3]->store( @@ -122,8 +107,6 @@ static int i_s_metadata_lock_info_init( compile_time_assert(sizeof(metadata_lock_info_lock_name)/sizeof(LEX_STRING) == MDL_key::NAMESPACE_END); - compile_time_assert(sizeof(metadata_lock_info_lock_mode)/sizeof(LEX_STRING) - == MDL_TYPE_END); ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *) p; DBUG_ENTER("i_s_metadata_lock_info_init"); diff --git a/plugin/metadata_lock_info/mysql-test/metadata_lock_info/r/global_read_lock.result b/plugin/metadata_lock_info/mysql-test/metadata_lock_info/r/global_read_lock.result index 5803d7d1290..12afd5010cc 100644 --- a/plugin/metadata_lock_info/mysql-test/metadata_lock_info/r/global_read_lock.result +++ b/plugin/metadata_lock_info/mysql-test/metadata_lock_info/r/global_read_lock.result @@ -3,8 +3,7 @@ lock_mode lock_duration lock_type table_schema table_name FLUSH TABLES WITH READ LOCK; SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info; lock_mode lock_duration lock_type table_schema table_name -MDL_SHARED NULL Commit lock -MDL_SHARED NULL Global read lock +MDL_BACKUP_FTWRL2 NULL Backup lock UNLOCK TABLES; SELECT lock_mode, lock_duration, lock_type, table_schema, table_name FROM information_schema.metadata_lock_info; lock_mode lock_duration lock_type table_schema table_name diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 72d5a91d59d..a9b4ff200d9 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -733,7 +733,7 @@ static int user_coll_fill(struct user_coll *c, char *users, internal_stop_logging= 1; CLIENT_ERROR(1, "User '%.*s' was removed from the" " server_audit_excl_users.", - MYF(ME_JUST_WARNING), (int) cmp_length, users); + MYF(ME_WARNING), (int) cmp_length, users); internal_stop_logging= 0; blank_user(cmp_user); refill_cmp_coll= 1; @@ -742,7 +742,7 @@ static int user_coll_fill(struct user_coll *c, char *users, { internal_stop_logging= 1; CLIENT_ERROR(1, "User '%.*s' is in the server_audit_incl_users, " - "so wasn't added.", MYF(ME_JUST_WARNING), (int) cmp_length, users); + "so wasn't added.", MYF(ME_WARNING), (int) cmp_length, users); internal_stop_logging= 0; remove_user(users); continue; @@ -1050,7 +1050,7 @@ static int start_logging() "Could not create file '%s'.", alt_fname); is_active= 0; CLIENT_ERROR(1, "SERVER AUDIT plugin can't create file '%s'.", - MYF(ME_JUST_WARNING), alt_fname); + MYF(ME_WARNING), alt_fname); return 1; } error_header(); @@ -2593,7 +2593,7 @@ static void update_file_path(MYSQL_THD thd, { error_header(); fprintf(stderr, "Logging was disabled..\n"); - CLIENT_ERROR(1, "Logging was disabled.", MYF(ME_JUST_WARNING)); + CLIENT_ERROR(1, "Logging was disabled.", MYF(ME_WARNING)); } goto exit_func; } @@ -2763,7 +2763,7 @@ static void update_logging(MYSQL_THD thd, start_logging(); if (!logging) { - CLIENT_ERROR(1, "Logging was disabled.", MYF(ME_JUST_WARNING)); + CLIENT_ERROR(1, "Logging was disabled.", MYF(ME_WARNING)); } } else diff --git a/plugin/simple_password_check/simple_password_check.c b/plugin/simple_password_check/simple_password_check.c index 5a76c3d3005..2d298f0efa9 100644 --- a/plugin/simple_password_check/simple_password_check.c +++ b/plugin/simple_password_check/simple_password_check.c @@ -22,8 +22,8 @@ static unsigned min_length, min_digits, min_letters, min_others; -static int validate(MYSQL_CONST_LEX_STRING *username, - MYSQL_CONST_LEX_STRING *password) +static int validate(const MYSQL_CONST_LEX_STRING *username, + const MYSQL_CONST_LEX_STRING *password) { unsigned digits=0 , uppers=0 , lowers=0, others=0, length= (unsigned)password->length; const char *ptr= password->str, *end= ptr + length; diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 464c00d57da..fcb13be5c25 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -31,7 +31,7 @@ ENDIF() IF(CAT_EXECUTABLE) SET(CAT_COMMAND COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_SOURCE_DIR} - ${CAT_EXECUTABLE} mysql_system_tables.sql mysql_system_tables_fix.sql mysql_performance_tables.sql > + ${CAT_EXECUTABLE} mysql_system_tables_fix.sql mysql_system_tables.sql mysql_performance_tables.sql > ${CMAKE_CURRENT_BINARY_DIR}/mysql_fix_privilege_tables.sql ) ELSEIF(WIN32) @@ -39,7 +39,7 @@ ELSEIF(WIN32) native_outfile ) SET(CAT_COMMAND COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_SOURCE_DIR} - cmd /c copy /b mysql_system_tables.sql + mysql_system_tables_fix.sql + mysql_performance_tables.sql + cmd /c copy /b mysql_system_tables_fix.sql + mysql_system_tables.sql + mysql_performance_tables.sql ${native_outfile} ) ELSE() MESSAGE(FATAL_ERROR "Cannot concatenate files") diff --git a/scripts/fill_help_tables.sql b/scripts/fill_help_tables.sql index f8055867b5c..1dc2ca1f9cb 100644 --- a/scripts/fill_help_tables.sql +++ b/scripts/fill_help_tables.sql @@ -31,6 +31,7 @@ delete from help_category; delete from help_keyword; delete from help_relation; +lock tables help_topic write, help_category write, help_keyword write, help_relation write; insert into help_category (help_category_id,name,parent_category_id,url) values (1,'Geographic',0,''); insert into help_category (help_category_id,name,parent_category_id,url) values (2,'Polygon properties',34,''); insert into help_category (help_category_id,name,parent_category_id,url) values (3,'WKT',34,''); @@ -2073,3 +2074,4 @@ insert into help_relation (help_topic_id,help_keyword_id) values (209,461); insert into help_relation (help_topic_id,help_keyword_id) values (468,461); insert into help_relation (help_topic_id,help_keyword_id) values (201,462); insert into help_relation (help_topic_id,help_keyword_id) values (468,463); +unlock tables; diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index fb3b32251ed..82a8e175753 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -237,7 +237,7 @@ cannot_find_file() fi echo - echo "If you compiled from source, you need to either run 'make install' to" + echo "If you compiledx from source, you need to either run 'make install' to" echo "copy the software into the correct location ready for operation." echo "If you don't want to do a full install, you can use the --srcdir" echo "option to only install the mysql database and privilege tables" @@ -313,6 +313,7 @@ then srcpkgdatadir="$srcdir/scripts" buildpkgdatadir="$builddir/scripts" plugindir="$builddir/plugin/auth_socket" + pamtooldir="$builddir/plugin/auth_pam" elif test -n "$basedir" then bindir="$basedir/bin" # only used in the help text @@ -342,6 +343,7 @@ then exit 1 fi plugindir=`find_in_dirs --dir auth_socket.so $basedir/lib*/plugin $basedir/lib*/mysql/plugin` + pamtooldir=$plugindir else basedir="@prefix@" bindir="@bindir@" @@ -350,6 +352,7 @@ else srcpkgdatadir="@pkgdatadir@" buildpkgdatadir="@pkgdatadir@" plugindir="@pkgplugindir@" + pamtooldir="@pkgplugindir@" fi # Set up paths to SQL scripts required for bootstrap @@ -450,9 +453,33 @@ done if test -n "$user" then + chown $user "$pamtooldir/auth_pam_tool_dir" + if test $? -ne 0 + then + echo "Cannot change ownership of the '$pamtooldir/auth_pam_tool_dir' directory" + echo " to the '$user' user. Check that you have the necessary permissions and try again." + exit 1 + fi + if test -z "$srcdir" + then + chown 0 "$pamtooldir/auth_pam_tool_dir/auth_pam_tool" + if test $? -ne 0 + then + echo "Couldn't set an owner to '$pamtooldir/auth_pam_tool_dir/auth_pam_tool'." + echo " It must be root, the PAM authentication plugin doesn't work otherwise.." + echo + fi + fi args="$args --user=$user" fi +if test -f "$ldata/mysql/user.frm" +then + echo "mysql.user table already exists!" + echo "Run mysql_upgrade, not mysql_install_db" + exit 0 +fi + # When doing a "cross bootstrap" install, no reference to the current # host should be added to the system tables. So we filter out any # lines which contain the current host name. diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh index 57e4d43dfad..1bd21513d4d 100644 --- a/scripts/mysql_secure_installation.sh +++ b/scripts/mysql_secure_installation.sh @@ -304,7 +304,7 @@ set_root_password() { fi esc_pass=`basic_single_escape "$password1"` - do_query "UPDATE mysql.user SET Password=PASSWORD('$esc_pass') WHERE User='root';" + do_query "UPDATE mysql.global_priv SET priv=json_set(priv, '$.plugin', 'mysql_native_password', '$.authentication_string', PASSWORD('$esc_pass')) WHERE User='root';" if [ $? -eq 0 ]; then echo "Password updated successfully!" echo "Reloading privilege tables.." @@ -324,7 +324,7 @@ set_root_password() { } remove_anonymous_users() { - do_query "DELETE FROM mysql.user WHERE User='';" + do_query "DELETE FROM mysql.global_priv WHERE User='';" if [ $? -eq 0 ]; then echo " ... Success!" else @@ -336,7 +336,7 @@ remove_anonymous_users() { } remove_remote_root() { - do_query "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');" + do_query "DELETE FROM mysql.global_priv WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');" if [ $? -eq 0 ]; then echo " ... Success!" else diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index 9f8af61752f..f788f5d67d5 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -21,70 +21,118 @@ set sql_mode=''; set @orig_storage_engine=@@storage_engine; -set storage_engine=myisam; +set storage_engine=Aria; set system_versioning_alter_history=keep; set @have_innodb= (select count(engine) from information_schema.engines where engine='INNODB' and support != 'NO'); -SET @innodb_or_myisam=IF(@have_innodb <> 0, 'InnoDB', 'MyISAM'); +SET @innodb_or_aria=IF(@have_innodb <> 0, 'InnoDB', 'Aria'); -CREATE TABLE IF NOT EXISTS db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_history_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; +CREATE TABLE IF NOT EXISTS db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_history_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; -- Remember for later if db table already existed set @had_db_table= @@warning_count != 0; -CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; - -CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_history_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) DEFAULT 0 NOT NULL, plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, authentication_string TEXT NOT NULL, password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, default_role char(80) binary DEFAULT '' NOT NULL, max_statement_time decimal(12,6) DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; +CREATE TABLE IF NOT EXISTS global_priv (Host char(60) binary DEFAULT '', User char(80) binary DEFAULT '', Priv JSON NOT NULL DEFAULT '{}' CHECK(JSON_VALID(Priv)), PRIMARY KEY Host (Host,User)) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; + +CREATE DEFINER=root@localhost SQL SECURITY DEFINER VIEW IF NOT EXISTS user AS SELECT + Host, + User, + IF(JSON_VALUE(Priv, '$.plugin') IN ('mysql_native_password', 'mysql_old_password'), IFNULL(JSON_VALUE(Priv, '$.authentication_string'), ''), '') AS Password, + IF(JSON_VALUE(Priv, '$.access') & 1, 'Y', 'N') AS Select_priv, + IF(JSON_VALUE(Priv, '$.access') & 2, 'Y', 'N') AS Insert_priv, + IF(JSON_VALUE(Priv, '$.access') & 4, 'Y', 'N') AS Update_priv, + IF(JSON_VALUE(Priv, '$.access') & 8, 'Y', 'N') AS Delete_priv, + IF(JSON_VALUE(Priv, '$.access') & 16, 'Y', 'N') AS Create_priv, + IF(JSON_VALUE(Priv, '$.access') & 32, 'Y', 'N') AS Drop_priv, + IF(JSON_VALUE(Priv, '$.access') & 64, 'Y', 'N') AS Reload_priv, + IF(JSON_VALUE(Priv, '$.access') & 128, 'Y', 'N') AS Shutdown_priv, + IF(JSON_VALUE(Priv, '$.access') & 256, 'Y', 'N') AS Process_priv, + IF(JSON_VALUE(Priv, '$.access') & 512, 'Y', 'N') AS File_priv, + IF(JSON_VALUE(Priv, '$.access') & 1024, 'Y', 'N') AS Grant_priv, + IF(JSON_VALUE(Priv, '$.access') & 2048, 'Y', 'N') AS References_priv, + IF(JSON_VALUE(Priv, '$.access') & 4096, 'Y', 'N') AS Index_priv, + IF(JSON_VALUE(Priv, '$.access') & 8192, 'Y', 'N') AS Alter_priv, + IF(JSON_VALUE(Priv, '$.access') & 16384, 'Y', 'N') AS Show_db_priv, + IF(JSON_VALUE(Priv, '$.access') & 32768, 'Y', 'N') AS Super_priv, + IF(JSON_VALUE(Priv, '$.access') & 65536, 'Y', 'N') AS Create_tmp_table_priv, + IF(JSON_VALUE(Priv, '$.access') & 131072, 'Y', 'N') AS Lock_tables_priv, + IF(JSON_VALUE(Priv, '$.access') & 262144, 'Y', 'N') AS Execute_priv, + IF(JSON_VALUE(Priv, '$.access') & 524288, 'Y', 'N') AS Repl_slave_priv, + IF(JSON_VALUE(Priv, '$.access') & 1048576, 'Y', 'N') AS Repl_client_priv, + IF(JSON_VALUE(Priv, '$.access') & 2097152, 'Y', 'N') AS Create_view_priv, + IF(JSON_VALUE(Priv, '$.access') & 4194304, 'Y', 'N') AS Show_view_priv, + IF(JSON_VALUE(Priv, '$.access') & 8388608, 'Y', 'N') AS Create_routine_priv, + IF(JSON_VALUE(Priv, '$.access') & 16777216, 'Y', 'N') AS Alter_routine_priv, + IF(JSON_VALUE(Priv, '$.access') & 33554432, 'Y', 'N') AS Create_user_priv, + IF(JSON_VALUE(Priv, '$.access') & 67108864, 'Y', 'N') AS Event_priv, + IF(JSON_VALUE(Priv, '$.access') & 134217728, 'Y', 'N') AS Trigger_priv, + IF(JSON_VALUE(Priv, '$.access') & 268435456, 'Y', 'N') AS Create_tablespace_priv, + IF(JSON_VALUE(Priv, '$.access') & 536870912, 'Y', 'N') AS Delete_history_priv, + ELT(IFNULL(JSON_VALUE(Priv, '$.ssl_type'), 0) + 1, '', 'ANY','X509', 'SPECIFIED') AS ssl_type, + IFNULL(JSON_VALUE(Priv, '$.ssl_cipher'), '') AS ssl_cipher, + IFNULL(JSON_VALUE(Priv, '$.x509_issuer'), '') AS x509_issuer, + IFNULL(JSON_VALUE(Priv, '$.x509_subject'), '') AS x509_subject, + CAST(IFNULL(JSON_VALUE(Priv, '$.max_questions'), 0) AS UNSIGNED) AS max_questions, + CAST(IFNULL(JSON_VALUE(Priv, '$.max_updates'), 0) AS UNSIGNED) AS max_updates, + CAST(IFNULL(JSON_VALUE(Priv, '$.max_connections'), 0) AS UNSIGNED) AS max_connections, + CAST(IFNULL(JSON_VALUE(Priv, '$.max_user_connections'), 0) AS SIGNED) AS max_user_connections, + IFNULL(JSON_VALUE(Priv, '$.plugin'), '') AS plugin, + IFNULL(JSON_VALUE(Priv, '$.authentication_string'), '') AS authentication_string, + 'N' AS password_expired, + ELT(IFNULL(JSON_VALUE(Priv, '$.is_role'), 0) + 1, 'N', 'Y') AS is_role, + IFNULL(JSON_VALUE(Priv, '$.default_role'), '') AS default_role, + CAST(IFNULL(JSON_VALUE(Priv, '$.max_statement_time'), 0.0) AS DECIMAL(12,6)) AS max_statement_time + FROM global_priv; -- Remember for later if user table already existed set @had_user_table= @@warning_count != 0; -CREATE TABLE IF NOT EXISTS roles_mapping ( Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Role char(80) binary DEFAULT '' NOT NULL, Admin_option enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, UNIQUE (Host, User, Role)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Granted roles'; +CREATE TABLE IF NOT EXISTS roles_mapping ( Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Role char(80) binary DEFAULT '' NOT NULL, Admin_option enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, UNIQUE (Host, User, Role)) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Granted roles'; -CREATE TABLE IF NOT EXISTS func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; +CREATE TABLE IF NOT EXISTS func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; -CREATE TABLE IF NOT EXISTS plugin ( name varchar(64) DEFAULT '' NOT NULL, dl varchar(128) DEFAULT '' NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci comment='MySQL plugins'; +CREATE TABLE IF NOT EXISTS plugin ( name varchar(64) DEFAULT '' NOT NULL, dl varchar(128) DEFAULT '' NOT NULL, PRIMARY KEY (name) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_general_ci comment='MySQL plugins'; -CREATE TABLE IF NOT EXISTS servers ( Server_name char(64) NOT NULL DEFAULT '', Host char(64) NOT NULL DEFAULT '', Db char(64) NOT NULL DEFAULT '', Username char(80) NOT NULL DEFAULT '', Password char(64) NOT NULL DEFAULT '', Port INT(4) NOT NULL DEFAULT '0', Socket char(64) NOT NULL DEFAULT '', Wrapper char(64) NOT NULL DEFAULT '', Owner char(64) NOT NULL DEFAULT '', PRIMARY KEY (Server_name)) CHARACTER SET utf8 comment='MySQL Foreign Servers table'; +CREATE TABLE IF NOT EXISTS servers ( Server_name char(64) NOT NULL DEFAULT '', Host char(64) NOT NULL DEFAULT '', Db char(64) NOT NULL DEFAULT '', Username char(80) NOT NULL DEFAULT '', Password char(64) NOT NULL DEFAULT '', Port INT(4) NOT NULL DEFAULT '0', Socket char(64) NOT NULL DEFAULT '', Wrapper char(64) NOT NULL DEFAULT '', Owner char(64) NOT NULL DEFAULT '', PRIMARY KEY (Server_name)) engine=Aria transactional=1 CHARACTER SET utf8 comment='MySQL Foreign Servers table'; -CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger','Delete versioning rows') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; +CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger','Delete versioning rows') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; -CREATE TABLE IF NOT EXISTS columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; +CREATE TABLE IF NOT EXISTS columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; -CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url text not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics'; +CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url text not null, primary key (help_topic_id), unique index (name) ) engine=Aria transactional=0 CHARACTER SET utf8 comment='help topics'; -CREATE TABLE IF NOT EXISTS help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url text not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories'; +CREATE TABLE IF NOT EXISTS help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url text not null, primary key (help_category_id), unique index (name) ) engine=Aria transactional=0 CHARACTER SET utf8 comment='help categories'; -CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; +CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=Aria transactional=0 CHARACTER SET utf8 comment='keyword-topic relation'; -CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; +CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=Aria transactional=0 CHARACTER SET utf8 comment='help keywords'; -CREATE TABLE IF NOT EXISTS time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; +CREATE TABLE IF NOT EXISTS time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Time zone names'; -CREATE TABLE IF NOT EXISTS time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; +CREATE TABLE IF NOT EXISTS time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Time zones'; -CREATE TABLE IF NOT EXISTS time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; +CREATE TABLE IF NOT EXISTS time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Time zone transitions'; -CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; +CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Time zone transition types'; -CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; +CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=Aria transactional=1 CHARACTER SET utf8 comment='Leap seconds information for time zones'; -CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob NOT NULL, body longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', 'EMPTY_STRING_IS_NULL', 'SIMULTANEOUS_ASSIGNMENT') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, aggregate enum('NONE', 'GROUP') DEFAULT 'NONE' NOT NULL, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures'; +CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob NOT NULL, body longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', 'EMPTY_STRING_IS_NULL', 'SIMULTANEOUS_ASSIGNMENT', 'TIME_ROUND_FRACTIONAL') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, aggregate enum('NONE', 'GROUP') DEFAULT 'NONE' NOT NULL, PRIMARY KEY (db,name,type)) engine=Aria transactional=1 character set utf8 comment='Stored Procedures'; -CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; +CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE','PACKAGE','PACKAGE BODY') NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; -- Create general_log if CSV is enabled. @@ -103,7 +151,7 @@ PREPARE stmt FROM @str; EXECUTE stmt; DROP PREPARE stmt; -CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events'; +CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(141) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED','SLAVESIDE_DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','IGNORE_BAD_TABLE_OPTIONS','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH','EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT','TIME_ROUND_FRACTIONAL') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', originator INTEGER UNSIGNED NOT NULL, time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db, name) ) engine=Aria transactional=1 DEFAULT CHARSET=utf8 COMMENT 'Events'; SET @create_innodb_table_stats="CREATE TABLE IF NOT EXISTS innodb_table_stats ( database_name VARCHAR(64) NOT NULL, @@ -170,7 +218,7 @@ SET @cmd="CREATE TABLE IF NOT EXISTS slave_relay_log_info ( Id INTEGER UNSIGNED NOT NULL COMMENT 'Internal Id that uniquely identifies this record.', PRIMARY KEY(Id)) DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT 'Relay Log Information'"; -SET @str=CONCAT(@cmd, ' ENGINE=', @innodb_or_myisam); +SET @str=CONCAT(@cmd, ' ENGINE=', @innodb_or_aria); -- Don't create the table; MariaDB will have another implementation #PREPARE stmt FROM @str; #EXECUTE stmt; @@ -202,7 +250,7 @@ SET @cmd= "CREATE TABLE IF NOT EXISTS slave_master_info ( Enabled_auto_position BOOLEAN NOT NULL COMMENT 'Indicates whether GTIDs will be used to retrieve events from the master.', PRIMARY KEY(Host, Port)) DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT 'Master Information'"; -SET @str=CONCAT(@cmd, ' ENGINE=', @innodb_or_myisam); +SET @str=CONCAT(@cmd, ' ENGINE=', @innodb_or_aria); -- Don't create the table; MariaDB will have another implementation #PREPARE stmt FROM @str; #EXECUTE stmt; @@ -223,26 +271,33 @@ SET @cmd= "CREATE TABLE IF NOT EXISTS slave_worker_info ( Checkpoint_group_bitmap BLOB NOT NULL, PRIMARY KEY(Id)) DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT 'Worker Information'"; -SET @str=CONCAT(@cmd, ' ENGINE=', @innodb_or_myisam); +SET @str=CONCAT(@cmd, ' ENGINE=', @innodb_or_aria); -- Don't create the table; MariaDB will have another implementation #PREPARE stmt FROM @str; #EXECUTE stmt; #DROP PREPARE stmt; -CREATE TABLE IF NOT EXISTS proxies_priv (Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Proxied_host char(60) binary DEFAULT '' NOT NULL, Proxied_user char(80) binary DEFAULT '' NOT NULL, With_grant BOOL DEFAULT 0 NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY Host (Host,User,Proxied_host,Proxied_user), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User proxy privileges'; +CREATE TABLE IF NOT EXISTS proxies_priv (Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Proxied_host char(60) binary DEFAULT '' NOT NULL, Proxied_user char(80) binary DEFAULT '' NOT NULL, With_grant BOOL DEFAULT 0 NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY Host (Host,User,Proxied_host,Proxied_user), KEY Grantor (Grantor) ) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='User proxy privileges'; -- Remember for later if proxies_priv table already existed set @had_proxies_priv_table= @@warning_count != 0; +-- The following needs to be done both for new installations +-- and for upgrades +CREATE TEMPORARY TABLE tmp_proxies_priv LIKE proxies_priv; +INSERT INTO tmp_proxies_priv VALUES ('localhost', 'root', '', '', TRUE, '', now()); +INSERT INTO proxies_priv SELECT * FROM tmp_proxies_priv WHERE @had_proxies_priv_table=0; +DROP TABLE tmp_proxies_priv; + -- -- Tables unique for MariaDB -- -CREATE TABLE IF NOT EXISTS table_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, cardinality bigint(21) unsigned DEFAULT NULL, PRIMARY KEY (db_name,table_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Tables'; +CREATE TABLE IF NOT EXISTS table_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, cardinality bigint(21) unsigned DEFAULT NULL, PRIMARY KEY (db_name,table_name) ) engine=Aria transactional=0 CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Tables'; -CREATE TABLE IF NOT EXISTS column_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, column_name varchar(64) NOT NULL, min_value varbinary(255) DEFAULT NULL, max_value varbinary(255) DEFAULT NULL, nulls_ratio decimal(12,4) DEFAULT NULL, avg_length decimal(12,4) DEFAULT NULL, avg_frequency decimal(12,4) DEFAULT NULL, hist_size tinyint unsigned, hist_type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB'), histogram varbinary(255), PRIMARY KEY (db_name,table_name,column_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Columns'; +CREATE TABLE IF NOT EXISTS column_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, column_name varchar(64) NOT NULL, min_value varbinary(255) DEFAULT NULL, max_value varbinary(255) DEFAULT NULL, nulls_ratio decimal(12,4) DEFAULT NULL, avg_length decimal(12,4) DEFAULT NULL, avg_frequency decimal(12,4) DEFAULT NULL, hist_size tinyint unsigned, hist_type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB'), histogram varbinary(255), PRIMARY KEY (db_name,table_name,column_name) ) engine=Aria transactional=0 CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Columns'; -CREATE TABLE IF NOT EXISTS index_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, index_name varchar(64) NOT NULL, prefix_arity int(11) unsigned NOT NULL, avg_frequency decimal(12,4) DEFAULT NULL, PRIMARY KEY (db_name,table_name,index_name,prefix_arity) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Indexes'; +CREATE TABLE IF NOT EXISTS index_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, index_name varchar(64) NOT NULL, prefix_arity int(11) unsigned NOT NULL, avg_frequency decimal(12,4) DEFAULT NULL, PRIMARY KEY (db_name,table_name,index_name,prefix_arity) ) engine=Aria transactional=0 CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Indexes'; -- Note: This definition must be kept in sync with the one used in -- build_gtid_pos_create_query() in sql/slave.cc @@ -253,7 +308,7 @@ SET @cmd= "CREATE TABLE IF NOT EXISTS gtid_slave_pos ( seq_no BIGINT UNSIGNED NOT NULL, PRIMARY KEY (domain_id, sub_id)) CHARSET=latin1 COMMENT='Replication slave GTID position'"; -SET @str=CONCAT(@cmd, ' ENGINE=', @innodb_or_myisam); +SET @str=CONCAT(@cmd, ' ENGINE=', @innodb_or_aria); PREPARE stmt FROM @str; EXECUTE stmt; DROP PREPARE stmt; @@ -262,6 +317,7 @@ set storage_engine=@orig_storage_engine; -- -- Drop some tables not used anymore in MariaDB ---- +-- drop table if exists mysql.ndb_binlog_index; +drop table if exists mysql.host; diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql index 4761fe51dcc..f14dcf01594 100644 --- a/scripts/mysql_system_tables_data.sql +++ b/scripts/mysql_system_tables_data.sql @@ -25,28 +25,28 @@ -- add escape character in front of wildcard character to convert "_" or "%" to -- a plain character SELECT LOWER( REPLACE((SELECT REPLACE(@@hostname,'_','\_')),'%','\%') )INTO @current_hostname; +SELECT json_object('access',cast(-1 as unsigned)) INTO @all_privileges; --- Fill "user" table with default users allowing root access --- from local machine if "user" table didn't exist before -CREATE TEMPORARY TABLE tmp_user_nopasswd LIKE user; -CREATE TEMPORARY TABLE tmp_user_socket LIKE user; +-- Fill "global_priv" table with default users allowing root access +-- from local machine if "global_priv" table didn't exist before +CREATE TEMPORARY TABLE tmp_user_nopasswd LIKE global_priv; +CREATE TEMPORARY TABLE tmp_user_socket LIKE global_priv; -- Classic passwordless root account. -INSERT INTO tmp_user_nopasswd VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N', 'N','', 0); -REPLACE INTO tmp_user_nopasswd SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0 FROM dual WHERE @current_hostname != 'localhost'; -REPLACE INTO tmp_user_nopasswd VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0); -REPLACE INTO tmp_user_nopasswd VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N', '', 0); +INSERT INTO tmp_user_nopasswd VALUES ('localhost','root',@all_privileges); +REPLACE INTO tmp_user_nopasswd SELECT @current_hostname,'root',@all_privileges FROM dual WHERE @current_hostname != 'localhost'; +REPLACE INTO tmp_user_nopasswd VALUES ('127.0.0.1','root',@all_privileges); +REPLACE INTO tmp_user_nopasswd VALUES ('::1','root',@all_privileges); -- More secure root account using unix socket auth. -INSERT INTO tmp_user_socket VALUES ('localhost',IFNULL(@auth_root_socket, 'root'),'','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'unix_socket','','N', 'N','', 0); +INSERT INTO tmp_user_socket VALUES ('localhost',IFNULL(@auth_root_socket, 'root'),@all_privileges); IF @auth_root_socket is not null THEN IF not exists(select 1 from information_schema.plugins where plugin_name='unix_socket') THEN INSTALL SONAME 'auth_socket'; END IF; END IF; -INSERT INTO user SELECT * FROM tmp_user_nopasswd WHERE @had_user_table=0 AND @skip_auth_root_nopasswd IS NULL; -INSERT INTO user SELECT * FROM tmp_user_socket WHERE @had_user_table=0 AND @auth_root_socket IS NOT NULL; +INSERT INTO global_priv SELECT * FROM tmp_user_nopasswd WHERE @had_user_table=0 AND @skip_auth_root_nopasswd IS NULL; +INSERT INTO global_priv SELECT * FROM tmp_user_socket WHERE @had_user_table=0 AND @auth_root_socket IS NOT NULL; DROP TABLE tmp_user_nopasswd, tmp_user_socket; CREATE TEMPORARY TABLE tmp_proxies_priv LIKE proxies_priv; -INSERT INTO tmp_proxies_priv VALUES ('localhost', 'root', '', '', TRUE, '', now()); -REPLACE INTO tmp_proxies_priv SELECT @current_hostname, 'root', '', '', TRUE, '', now() FROM DUAL WHERE @current_hostname != 'localhost'; +INSERT INTO tmp_proxies_priv SELECT @current_hostname, 'root', '', '', TRUE, '', now() FROM DUAL WHERE @current_hostname != 'localhost'; INSERT INTO proxies_priv SELECT * FROM tmp_proxies_priv WHERE @had_proxies_priv_table=0; DROP TABLE tmp_proxies_priv; diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 945b569e52a..82ec2faa12d 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -25,9 +25,11 @@ # adding a 'SHOW WARNINGS' after the statement. set sql_mode=''; -set storage_engine=MyISAM; +set storage_engine=Aria; set enforce_storage_engine=NULL; +set @have_innodb= (select count(engine) from information_schema.engines where engine='INNODB' and support != 'NO'); + ALTER TABLE user add File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; # Detect whether or not we had the Grant_priv column @@ -38,10 +40,6 @@ ALTER TABLE user add Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N add References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, add Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, add Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; -ALTER TABLE host add Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - add References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - add Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - add Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; ALTER TABLE db add Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, add References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, add Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, @@ -50,8 +48,6 @@ ALTER TABLE db add Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' # Fix privileges for old tables UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; UPDATE db SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; -UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0; - # # The second alter changes ssl_type to new 4.0.2 format # Adding columns needed by GRANT .. REQUIRE (openssl) @@ -75,7 +71,7 @@ ALTER TABLE tables_priv MODIFY User char(80) binary NOT NULL default '', MODIFY Table_name char(64) NOT NULL default '', MODIFY Grantor char(141) COLLATE utf8_bin NOT NULL default '', - ENGINE=MyISAM, + ENGINE=Aria, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; ALTER TABLE tables_priv @@ -103,7 +99,7 @@ ALTER TABLE columns_priv MODIFY User char(80) binary NOT NULL default '', MODIFY Table_name char(64) NOT NULL default '', MODIFY Column_name char(64) NOT NULL default '', - ENGINE=MyISAM, + ENGINE=Aria, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin, COMMENT='Column privileges'; @@ -155,15 +151,11 @@ ADD max_connections int(11) unsigned NOT NULL DEFAULT 0 AFTER max_updates; ALTER TABLE db ADD Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ADD Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; -ALTER TABLE host -ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, -ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL; alter table user change max_questions max_questions int(11) unsigned DEFAULT 0 NOT NULL; alter table db comment='Database privileges'; -alter table host comment='Host privileges; Merged with database privileges'; alter table user comment='Users and global privileges'; alter table func comment='User defined functions'; @@ -172,7 +164,7 @@ alter table func comment='User defined functions'; ALTER TABLE user MODIFY Host char(60) NOT NULL default '', MODIFY User char(80) binary NOT NULL default '', - ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; + ENGINE=Aria, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; # In MySQL 5.7.6 the Password column is removed. Recreate it to preserve the number # of columns MariaDB expects in the user table. @@ -208,7 +200,7 @@ ALTER TABLE db MODIFY Host char(60) NOT NULL default '', MODIFY Db char(64) NOT NULL default '', MODIFY User char(80) binary NOT NULL default '', - ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; + ENGINE=Aria, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; ALTER TABLE db MODIFY Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, MODIFY Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, @@ -223,26 +215,9 @@ ALTER TABLE db MODIFY Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, MODIFY Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; -ALTER TABLE host - MODIFY Host char(60) NOT NULL default '', - MODIFY Db char(64) NOT NULL default '', - ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; -ALTER TABLE host - MODIFY Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, - MODIFY Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; ALTER TABLE func - ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; + ENGINE=Aria, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; ALTER TABLE func MODIFY type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL; @@ -300,8 +275,6 @@ SELECT @hadCreateViewPriv:=1 FROM user WHERE Create_view_priv LIKE '%'; ALTER TABLE db ADD Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Lock_tables_priv; ALTER TABLE db MODIFY Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Lock_tables_priv; -ALTER TABLE host ADD Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Lock_tables_priv; -ALTER TABLE host MODIFY Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Lock_tables_priv; ALTER TABLE user ADD Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Repl_client_priv; ALTER TABLE user MODIFY Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Repl_client_priv; @@ -312,9 +285,6 @@ ALTER TABLE user MODIFY Create_view_priv enum('N','Y') COLLATE utf8_general_ci D ALTER TABLE db ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; ALTER TABLE db MODIFY Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; -ALTER TABLE host ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; -ALTER TABLE host MODIFY Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; - ALTER TABLE user ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; ALTER TABLE user MODIFY Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; @@ -335,9 +305,6 @@ SELECT @hadCreateRoutinePriv:=1 FROM user WHERE Create_routine_priv LIKE '%'; ALTER TABLE db ADD Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv; ALTER TABLE db MODIFY Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv; -ALTER TABLE host ADD Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv; -ALTER TABLE host MODIFY Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv; - ALTER TABLE user ADD Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv; ALTER TABLE user MODIFY Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Show_view_priv; @@ -347,24 +314,17 @@ ALTER TABLE user MODIFY Create_routine_priv enum('N','Y') COLLATE utf8_general_c ALTER TABLE db ADD Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv; ALTER TABLE db MODIFY Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv; -ALTER TABLE host ADD Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv; -ALTER TABLE host MODIFY Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv; - ALTER TABLE user ADD Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv; ALTER TABLE user MODIFY Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_routine_priv; ALTER TABLE db ADD Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Alter_routine_priv; ALTER TABLE db MODIFY Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Alter_routine_priv; -ALTER TABLE host ADD Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Alter_routine_priv; -ALTER TABLE host MODIFY Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Alter_routine_priv; - # # Assign create/alter routine privileges to people who have create privileges # UPDATE user SET Create_routine_priv=Create_priv, Alter_routine_priv=Alter_priv where user<>"" AND @hadCreateRoutinePriv = 0; UPDATE db SET Create_routine_priv=Create_priv, Alter_routine_priv=Alter_priv, Execute_priv=Select_priv where user<>"" AND @hadCreateRoutinePriv = 0; -UPDATE host SET Create_routine_priv=Create_priv, Alter_routine_priv=Alter_priv, Execute_priv=Select_priv where @hadCreateRoutinePriv = 0; # # Add max_user_connections resource limit @@ -392,7 +352,7 @@ UPDATE user LEFT JOIN db USING (Host,User) SET Create_user_priv='Y' # ALTER TABLE procs_priv - ENGINE=MyISAM, + ENGINE=Aria, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin; ALTER TABLE procs_priv @@ -459,7 +419,8 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL, 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', 'EMPTY_STRING_IS_NULL', - 'SIMULTANEOUS_ASSIGNMENT' + 'SIMULTANEOUS_ASSIGNMENT', + 'TIME_ROUND_FRACTIONAL' ) DEFAULT '' NOT NULL, DEFAULT CHARACTER SET utf8; @@ -595,7 +556,8 @@ ALTER TABLE event MODIFY sql_mode 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH', 'EMPTY_STRING_IS_NULL', - 'SIMULTANEOUS_ASSIGNMENT' + 'SIMULTANEOUS_ASSIGNMENT', + 'TIME_ROUND_FRACTIONAL' ) DEFAULT '' NOT NULL AFTER on_completion; ALTER TABLE event MODIFY name char(64) CHARACTER SET utf8 NOT NULL default ''; @@ -642,9 +604,6 @@ SELECT @hadTriggerPriv :=1 FROM user WHERE Trigger_priv LIKE '%'; ALTER TABLE user ADD Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Event_priv; ALTER TABLE user MODIFY Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Event_priv; -ALTER TABLE host ADD Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; -ALTER TABLE host MODIFY Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; - ALTER TABLE db ADD Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; ALTER TABLE db MODIFY Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; @@ -692,30 +651,18 @@ ALTER TABLE user ADD max_statement_time decimal(12,6) DEFAULT 0 NOT NULL; ALTER TABLE user MODIFY password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; ALTER TABLE user MODIFY is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; --- Need to pre-fill mysql.proxies_priv with access for root even when upgrading from --- older versions - -CREATE TEMPORARY TABLE tmp_proxies_priv LIKE proxies_priv; -INSERT INTO tmp_proxies_priv VALUES ('localhost', 'root', '', '', TRUE, '', now()); -INSERT INTO proxies_priv SELECT * FROM tmp_proxies_priv WHERE @had_proxies_priv_table=0; -DROP TABLE tmp_proxies_priv; - -- Checking for any duplicate hostname and username combination are exists. -- If exits we will throw error. -DROP PROCEDURE IF EXISTS mysql.count_duplicate_host_names; DELIMITER // -CREATE PROCEDURE mysql.count_duplicate_host_names() -BEGIN +BEGIN NOT ATOMIC SET @duplicate_hosts=(SELECT count(*) FROM mysql.user GROUP BY user, lower(host) HAVING count(*) > 1 LIMIT 1); IF @duplicate_hosts > 1 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Multiple accounts exist for @user_name, @host_name that differ only in Host lettercase; remove all except one of them'; END IF; END // DELIMITER ; -CALL mysql.count_duplicate_host_names(); -- Get warnings (if any) SHOW WARNINGS; -DROP PROCEDURE mysql.count_duplicate_host_names; # Convering the host name to lower case for existing users UPDATE user SET host=LOWER( host ) WHERE LOWER( host ) <> host; @@ -780,3 +727,86 @@ ALTER TABLE help_topic MODIFY url TEXT NOT NULL; # MDEV-7383 - varbinary on mix/max of column_stats alter table column_stats modify min_value varbinary(255) DEFAULT NULL, modify max_value varbinary(255) DEFAULT NULL; + +-- +-- Ensure that all tables are of type Aria and transactional +-- + +ALTER TABLE user ENGINE=Aria transactional=1; +ALTER TABLE db ENGINE=Aria transactional=1; +ALTER TABLE func ENGINE=Aria transactional=1; +ALTER TABLE procs_priv ENGINE=Aria transactional=1; +ALTER TABLE tables_priv ENGINE=Aria transactional=1; +ALTER TABLE columns_priv ENGINE=Aria transactional=1; +ALTER TABLE roles_mapping ENGINE=Aria transactional=1; +ALTER TABLE plugin ENGINE=Aria transactional=1; +ALTER TABLE servers ENGINE=Aria transactional=1; +ALTER TABLE time_zone_name ENGINE=Aria transactional=1; +ALTER TABLE time_zone ENGINE=Aria transactional=1; +ALTER TABLE time_zone_transition ENGINE=Aria transactional=1; +ALTER TABLE time_zone_transition_type ENGINE=Aria transactional=1; +ALTER TABLE time_zone_leap_second ENGINE=Aria transactional=1; +ALTER TABLE proc ENGINE=Aria transactional=1; +ALTER TABLE event ENGINE=Aria transactional=1; +ALTER TABLE proxies_priv ENGINE=Aria transactional=1; + +-- The following tables doesn't have to be transactional +ALTER TABLE help_topic ENGINE=Aria transactional=0; +ALTER TABLE help_category ENGINE=Aria transactional=0; +ALTER TABLE help_relation ENGINE=Aria transactional=0; +ALTER TABLE help_keyword ENGINE=Aria transactional=0; +ALTER TABLE table_stats ENGINE=Aria transactional=0; +ALTER TABLE column_stats ENGINE=Aria transactional=0; +ALTER TABLE index_stats ENGINE=Aria transactional=0; + +DELIMITER // +IF 'BASE TABLE' = (select table_type from information_schema.tables where table_name='user') THEN + CREATE TABLE IF NOT EXISTS global_priv (Host char(60) binary DEFAULT '', User char(80) binary DEFAULT '', Priv JSON NOT NULL DEFAULT '{}' CHECK(JSON_VALID(Priv)), PRIMARY KEY Host (Host,User)) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges' + SELECT Host, User, JSON_COMPACT(JSON_OBJECT('access', + 1*('Y'=Select_priv)+ + 2*('Y'=Insert_priv)+ + 4*('Y'=Update_priv)+ + 8*('Y'=Delete_priv)+ + 16*('Y'=Create_priv)+ + 32*('Y'=Drop_priv)+ + 64*('Y'=Reload_priv)+ + 128*('Y'=Shutdown_priv)+ + 256*('Y'=Process_priv)+ + 512*('Y'=File_priv)+ + 1024*('Y'=Grant_priv)+ + 2048*('Y'=References_priv)+ + 4096*('Y'=Index_priv)+ + 8192*('Y'=Alter_priv)+ + 16384*('Y'=Show_db_priv)+ + 32768*('Y'=Super_priv)+ + 65536*('Y'=Create_tmp_table_priv)+ + 131072*('Y'=Lock_tables_priv)+ + 262144*('Y'=Execute_priv)+ + 524288*('Y'=Repl_slave_priv)+ + 1048576*('Y'=Repl_client_priv)+ + 2097152*('Y'=Create_view_priv)+ + 4194304*('Y'=Show_view_priv)+ + 8388608*('Y'=Create_routine_priv)+ + 16777216*('Y'=Alter_routine_priv)+ + 33554432*('Y'=Create_user_priv)+ + 67108864*('Y'=Event_priv)+ + 134217728*('Y'=Trigger_priv)+ + 268435456*('Y'=Create_tablespace_priv)+ + 536870912*('Y'=Delete_history_priv), + 'ssl_type', ssl_type-1, + 'ssl_cipher', ssl_cipher, + 'x509_issuer', x509_issuer, + 'x509_subject', x509_subject, + 'max_questions', max_questions, + 'max_updates', max_updates, + 'max_connections', max_connections, + 'max_user_connections', max_user_connections, + 'max_statement_time', max_statement_time, + 'plugin', if(plugin>'',plugin,if(length(password)=16,'mysql_old_password','mysql_native_password')), + 'authentication_string', if(plugin>'',authentication_string,password), + 'default_role', default_role, + 'is_role', 'Y'=is_role)) as Priv + FROM user; + DROP TABLE user; +END IF// +DELIMITER ; diff --git a/scripts/mysql_test_db.sql b/scripts/mysql_test_db.sql index c1bb3661ec3..9f8a0cf604c 100644 --- a/scripts/mysql_test_db.sql +++ b/scripts/mysql_test_db.sql @@ -24,8 +24,8 @@ INSERT INTO db SELECT * FROM tmp_db WHERE @had_db_table=0; DROP TABLE tmp_db; -- Anonymous user with no privileges. -CREATE TEMPORARY TABLE tmp_user_anonymous LIKE user; +CREATE TEMPORARY TABLE tmp_user_anonymous LIKE global_priv; INSERT INTO tmp_user_anonymous (host,user) VALUES ('localhost',''); INSERT INTO tmp_user_anonymous (host,user) SELECT @current_hostname,'' FROM dual WHERE @current_hostname != 'localhost'; -INSERT INTO user SELECT * FROM tmp_user_anonymous WHERE @had_user_table=0; +INSERT INTO global_priv SELECT * FROM tmp_user_anonymous WHERE @had_user_table=0; DROP TABLE tmp_user_anonymous; diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 80a881ca5dc..6417ee7f704 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -328,11 +328,11 @@ EOF exit 255 # unknown error fi - # second, we transfer InnoDB log files + # second, we transfer InnoDB and Aria log files rsync ${STUNNEL:+--rsh="$STUNNEL"} \ --owner --group --perms --links --specials \ --ignore-times --inplace --dirs --delete --quiet \ - $WHOLE_FILE_OPT -f '+ /ib_logfile[0-9]*' -f '- **' "$WSREP_LOG_DIR/" \ + $WHOLE_FILE_OPT -f '+ /ib_logfile[0-9]*' -f '+ /aria_log.*' -f '+ /aria_log_control' -f '- **' "$WSREP_LOG_DIR/" \ rsync://$WSREP_SST_OPT_ADDR-log_dir >&2 || RC=$? if [ $RC -ne 0 ]; then @@ -353,7 +353,7 @@ EOF rsync ${STUNNEL:+--rsh="$STUNNEL"} \ --owner --group --perms --links --specials \ --ignore-times --inplace --recursive --delete --quiet \ - $WHOLE_FILE_OPT --exclude '*/ib_logfile*' "$WSREP_SST_OPT_DATA"/{}/ \ + $WHOLE_FILE_OPT --exclude '*/ib_logfile*' --exclude "*/aria_log.*" --exclude "*/aria_log_control" "$WSREP_SST_OPT_DATA"/{}/ \ rsync://$WSREP_SST_OPT_ADDR/{} >&2 || RC=$? cd "$OLD_PWD" diff --git a/sql-common/client.c b/sql-common/client.c index 1d354cefb0b..69404e43613 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -121,10 +121,6 @@ char *mysql_unix_port= 0; const char *unknown_sqlstate= "HY000"; const char *not_error_sqlstate= "00000"; const char *cant_connect_sqlstate= "08001"; -#ifdef HAVE_SMEM -char *shared_memory_base_name= 0; -const char *def_shared_memory_base_name= default_shared_memory_base_name; -#endif static void mysql_close_free_options(MYSQL *mysql); static void mysql_close_free(MYSQL *mysql); @@ -320,248 +316,6 @@ HANDLE create_named_pipe(MYSQL *mysql, uint connect_timeout, char **arg_host, #endif -/* - Create new shared memory connection, return handler of connection - - SYNOPSIS - create_shared_memory() - mysql Pointer of mysql structure - net Pointer of net structure - connect_timeout Timeout of connection -*/ - -#ifdef HAVE_SMEM -HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) -{ - ulong smem_buffer_length = shared_memory_buffer_length + 4; - /* - event_connect_request is event object for start connection actions - event_connect_answer is event object for confirm, that server put data - handle_connect_file_map is file-mapping object, use for create shared - memory - handle_connect_map is pointer on shared memory - handle_map is pointer on shared memory for client - event_server_wrote, - event_server_read, - event_client_wrote, - event_client_read are events for transfer data between server and client - handle_file_map is file-mapping object, use for create shared memory - */ - HANDLE event_connect_request = NULL; - HANDLE event_connect_answer = NULL; - HANDLE handle_connect_file_map = NULL; - char *handle_connect_map = NULL; - - char *handle_map = NULL; - HANDLE event_server_wrote = NULL; - HANDLE event_server_read = NULL; - HANDLE event_client_wrote = NULL; - HANDLE event_client_read = NULL; - HANDLE event_conn_closed = NULL; - HANDLE handle_file_map = NULL; - ulong connect_number; - char connect_number_char[22], *p; - char *tmp= NULL; - char *suffix_pos; - DWORD error_allow = 0; - DWORD error_code = 0; - DWORD event_access_rights= SYNCHRONIZE | EVENT_MODIFY_STATE; - char *shared_memory_base_name = mysql->options.shared_memory_base_name; - static const char *name_prefixes[] = {"","Global\\"}; - const char *prefix; - uint i; - - /* - If this is NULL, somebody freed the MYSQL* options. mysql_close() - is a good candidate. We don't just silently (re)set it to - def_shared_memory_base_name as that would create really confusing/buggy - behavior if the user passed in a different name on the command-line or - in a my.cnf. - */ - DBUG_ASSERT(shared_memory_base_name != NULL); - - /* - get enough space base-name + '_' + longest suffix we might ever send - */ - if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE)))) - goto err; - - /* - The name of event and file-mapping events create agree next rule: - shared_memory_base_name+unique_part - Where: - shared_memory_base_name is unique value for each server - unique_part is uniquel value for each object (events and file-mapping) - */ - for (i = 0; i< array_elements(name_prefixes); i++) - { - prefix= name_prefixes[i]; - suffix_pos = strxmov(tmp, prefix , shared_memory_base_name, "_", NullS); - strmov(suffix_pos, "CONNECT_REQUEST"); - event_connect_request= OpenEvent(event_access_rights, FALSE, tmp); - if (event_connect_request) - { - break; - } - } - if (!event_connect_request) - { - error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR; - goto err; - } - strmov(suffix_pos, "CONNECT_ANSWER"); - if (!(event_connect_answer= OpenEvent(event_access_rights,FALSE,tmp))) - { - error_allow = CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR; - goto err; - } - strmov(suffix_pos, "CONNECT_DATA"); - if (!(handle_connect_file_map= OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp))) - { - error_allow = CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR; - goto err; - } - if (!(handle_connect_map= MapViewOfFile(handle_connect_file_map, - FILE_MAP_WRITE,0,0,sizeof(DWORD)))) - { - error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR; - goto err; - } - - /* Send to server request of connection */ - if (!SetEvent(event_connect_request)) - { - error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR; - goto err; - } - - /* Wait of answer from server */ - if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) != - WAIT_OBJECT_0) - { - error_allow = CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR; - goto err; - } - - /* Get number of connection */ - connect_number = uint4korr(handle_connect_map);/*WAX2*/ - p= int10_to_str(connect_number, connect_number_char, 10); - - /* - The name of event and file-mapping events create agree next rule: - shared_memory_base_name+unique_part+number_of_connection - - Where: - shared_memory_base_name is uniquel value for each server - unique_part is uniquel value for each object (events and file-mapping) - number_of_connection is number of connection between server and client - */ - suffix_pos = strxmov(tmp, prefix , shared_memory_base_name, "_", connect_number_char, - "_", NullS); - strmov(suffix_pos, "DATA"); - if ((handle_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_FILE_MAP_ERROR; - goto err2; - } - if ((handle_map = MapViewOfFile(handle_file_map,FILE_MAP_WRITE,0,0, - smem_buffer_length)) == NULL) - { - error_allow = CR_SHARED_MEMORY_MAP_ERROR; - goto err2; - } - - strmov(suffix_pos, "SERVER_WROTE"); - if ((event_server_wrote = OpenEvent(event_access_rights,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_EVENT_ERROR; - goto err2; - } - - strmov(suffix_pos, "SERVER_READ"); - if ((event_server_read = OpenEvent(event_access_rights,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_EVENT_ERROR; - goto err2; - } - - strmov(suffix_pos, "CLIENT_WROTE"); - if ((event_client_wrote = OpenEvent(event_access_rights,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_EVENT_ERROR; - goto err2; - } - - strmov(suffix_pos, "CLIENT_READ"); - if ((event_client_read = OpenEvent(event_access_rights,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_EVENT_ERROR; - goto err2; - } - - strmov(suffix_pos, "CONNECTION_CLOSED"); - if ((event_conn_closed = OpenEvent(event_access_rights,FALSE,tmp)) == NULL) - { - error_allow = CR_SHARED_MEMORY_EVENT_ERROR; - goto err2; - } - /* - Set event that server should send data - */ - SetEvent(event_server_read); - -err2: - if (error_allow == 0) - { - net->vio= vio_new_win32shared_memory(handle_file_map,handle_map, - event_server_wrote, - event_server_read,event_client_wrote, - event_client_read,event_conn_closed); - } - else - { - error_code = GetLastError(); - if (event_server_read) - CloseHandle(event_server_read); - if (event_server_wrote) - CloseHandle(event_server_wrote); - if (event_client_read) - CloseHandle(event_client_read); - if (event_client_wrote) - CloseHandle(event_client_wrote); - if (event_conn_closed) - CloseHandle(event_conn_closed); - if (handle_map) - UnmapViewOfFile(handle_map); - if (handle_file_map) - CloseHandle(handle_file_map); - } -err: - my_free(tmp); - if (error_allow) - error_code = GetLastError(); - if (event_connect_request) - CloseHandle(event_connect_request); - if (event_connect_answer) - CloseHandle(event_connect_answer); - if (handle_connect_map) - UnmapViewOfFile(handle_connect_map); - if (handle_connect_file_map) - CloseHandle(handle_connect_file_map); - if (error_allow) - { - if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR) - set_mysql_extended_error(mysql, error_allow, unknown_sqlstate, - ER(error_allow), suffix_pos, error_code); - else - set_mysql_extended_error(mysql, error_allow, unknown_sqlstate, - ER(error_allow), error_code); - return(INVALID_HANDLE_VALUE); - } - return(handle_map); -} -#endif - /** Read a packet from server. Give error message if socket was down or packet is an error message @@ -981,7 +735,7 @@ static const char *default_options[]= "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", "character-sets-dir", "default-character-set", "interactive-timeout", "connect-timeout", "local-infile", "disable-local-infile", - "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name", + "ssl-cipher", "max-allowed-packet", "protocol", "multi-results", "multi-statements", "multi-queries", "secure-auth", "report-data-truncation", "plugin-dir", "default-auth", "bind-address", "ssl-crl", "ssl-crlpath", @@ -994,7 +748,7 @@ enum option_id { OPT_ssl_key, OPT_ssl_cert, OPT_ssl_ca, OPT_ssl_capath, OPT_character_sets_dir, OPT_default_character_set, OPT_interactive_timeout, OPT_connect_timeout, OPT_local_infile, OPT_disable_local_infile, - OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name, + OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth, OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth, OPT_bind_address, OPT_ssl_crl, OPT_ssl_crlpath, @@ -1235,13 +989,6 @@ void mysql_read_default_options(struct st_mysql_options *options, options->protocol= UINT_MAX32; } break; - case OPT_shared_memory_base_name: -#ifdef HAVE_SMEM - if (options->shared_memory_base_name != def_shared_memory_base_name) - my_free(options->shared_memory_base_name); - options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME)); -#endif - break; case OPT_multi_results: options->client_flag|= CLIENT_MULTI_RESULTS; break; @@ -1632,10 +1379,6 @@ mysql_init(MYSQL *mysql) mysql->options.client_flag|= CLIENT_LOCAL_FILES; #endif -#ifdef HAVE_SMEM - mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name; -#endif - mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION; mysql->options.report_data_truncation= TRUE; /* default */ @@ -2840,12 +2583,6 @@ void mpvio_info(Vio *vio, MYSQL_PLUGIN_VIO_INFO *info) info->protocol= MYSQL_VIO_PIPE; info->handle= vio->hPipe; return; - case VIO_TYPE_SHARED_MEMORY: - info->protocol= MYSQL_VIO_MEMORY; -#ifdef HAVE_SMEM - info->handle= vio->handle_file_map; /* or what ? */ -#endif - return; #endif default: DBUG_ASSERT(0); } @@ -3180,42 +2917,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, /* Part 0: Grab a socket and connect it to the server */ -#if defined(HAVE_SMEM) - if ((!mysql->options.protocol || - mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) && - (!host || !strcmp(host,LOCAL_HOST)) && - mysql->options.shared_memory_base_name) - { - DBUG_PRINT("info", ("Using shared memory")); - if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) == - INVALID_HANDLE_VALUE) - { - DBUG_PRINT("error", - ("host: '%s' socket: '%s' shared memory: %s have_tcpip: %d", - host ? host : "<null>", - unix_socket ? unix_socket : "<null>", - mysql->options.shared_memory_base_name, - (int) have_tcpip)); - if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) - goto error; - /* - Try also with PIPE or TCP/IP. Clear the error from - create_shared_memory(). - */ - - net_clear_error(net); - } - else - { - mysql->options.protocol=MYSQL_PROTOCOL_MEMORY; - unix_socket = 0; - host=mysql->options.shared_memory_base_name; - my_snprintf(host_info=buff, sizeof(buff)-1, - ER(CR_SHARED_MEMORY_CONNECTION), host); - } - } -#endif /* HAVE_SMEM */ #if defined(HAVE_SYS_UN_H) if (!net->vio && (!mysql->options.protocol || @@ -3828,10 +3530,6 @@ static void mysql_close_free_options(MYSQL *mysql) #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) mysql_ssl_free(mysql); #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ -#ifdef HAVE_SMEM - if (mysql->options.shared_memory_base_name != def_shared_memory_base_name) - my_free(mysql->options.shared_memory_base_name); -#endif /* HAVE_SMEM */ if (mysql->options.extension) { struct mysql_async_context *ctxt= mysql->options.extension->async_context; @@ -4314,13 +4012,6 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) case MYSQL_OPT_PROTOCOL: mysql->options.protocol= *(uint*) arg; break; - case MYSQL_SHARED_MEMORY_BASE_NAME: -#ifdef HAVE_SMEM - if (mysql->options.shared_memory_base_name != def_shared_memory_base_name) - my_free(mysql->options.shared_memory_base_name); - mysql->options.shared_memory_base_name=my_strdup(arg,MYF(MY_WME)); -#endif - break; case MYSQL_OPT_USE_REMOTE_CONNECTION: case MYSQL_OPT_USE_EMBEDDED_CONNECTION: case MYSQL_OPT_GUESS_CONNECTION: @@ -4458,8 +4149,8 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) } } break; + case MYSQL_SHARED_MEMORY_BASE_NAME: default: - break; DBUG_RETURN(1); } DBUG_RETURN(0); diff --git a/sql-common/my_time.c b/sql-common/my_time.c index c4731d6b601..2aa657ca14e 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -58,6 +58,18 @@ uint calc_days_in_year(uint year) 366 : 365); } + +#ifndef DBUG_OFF + +static const ulonglong C_KNOWN_FLAGS= C_TIME_NO_ZERO_IN_DATE | + C_TIME_NO_ZERO_DATE | + C_TIME_INVALID_DATES; + +#define C_FLAGS_OK(flags) (((flags) & ~C_KNOWN_FLAGS) == 0) + +#endif + + /** @brief Check datetime value for validity according to flags. @@ -82,13 +94,14 @@ uint calc_days_in_year(uint year) my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date, ulonglong flags, int *was_cut) { + DBUG_ASSERT(C_FLAGS_OK(flags)); if (ltime->time_type == MYSQL_TIMESTAMP_TIME) return FALSE; if (not_zero_date) { - if (((flags & TIME_NO_ZERO_IN_DATE) && + if (((flags & C_TIME_NO_ZERO_IN_DATE) && (ltime->month == 0 || ltime->day == 0)) || ltime->neg || - (!(flags & TIME_INVALID_DATES) && + (!(flags & C_TIME_INVALID_DATES) && ltime->month && ltime->day > days_in_month[ltime->month-1] && (ltime->month != 2 || calc_days_in_year(ltime->year) != 366 || ltime->day != 29))) @@ -97,12 +110,13 @@ my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date, return TRUE; } } - else if (flags & TIME_NO_ZERO_DATE) + else if (flags & C_TIME_NO_ZERO_DATE) { /* We don't set *was_cut here to signal that the problem was a zero date and not an invalid date */ + *was_cut|= MYSQL_TIME_WARN_ZERO_DATE; return TRUE; } return FALSE; @@ -145,7 +159,8 @@ static int get_punct(const char **str, const char *end) return 1; } -static int get_date_time_separator(uint *number_of_fields, ulonglong flags, +static int get_date_time_separator(uint *number_of_fields, + my_bool punct_is_date_time_separator, const char **str, const char *end) { const char *s= *str; @@ -164,11 +179,11 @@ static int get_date_time_separator(uint *number_of_fields, ulonglong flags, but cast("11:11:11.12.12.12" as time) should give 11:11:11.12 that is, a punctuation character can be accepted as a date/time separator - only if TIME_DATETIME_ONLY (see str_to_time) is not set. + only if "punct_is_date_time_separator" is set. */ if (my_ispunct(&my_charset_latin1, *s)) { - if (flags & TIME_DATETIME_ONLY) + if (!punct_is_date_time_separator) { /* see above, returning 1 is not enough, we need hard abort here */ *number_of_fields= 0; @@ -241,25 +256,220 @@ static void get_microseconds(ulong *val, MYSQL_TIME_STATUS *status, *val= (ulong) (tmp * log_10_int[6 - (*str - start)]); else *val= tmp; + if (str[0] < end && my_isdigit(&my_charset_latin1, str[0][0])) + { + /* + We don't need the exact nanoseconds value. + Knowing the first digit is enough for rounding. + */ + status->nanoseconds= 100 * (uint)(str[0][0] - '0'); + } if (skip_digits(str, end)) status->warnings|= MYSQL_TIME_NOTE_TRUNCATED; } +static int check_time_range_internal(MYSQL_TIME *ltime, + ulong max_hour, ulong err_hour, + uint dec, int *warning); + +int check_time_range(MYSQL_TIME *ltime, uint dec, int *warning) +{ + return check_time_range_internal(ltime, TIME_MAX_HOUR, UINT_MAX32, + dec, warning); +} + + +static my_bool +set_neg(my_bool neg, MYSQL_TIME_STATUS *st, MYSQL_TIME *ltime) +{ + if ((ltime->neg= neg) && ltime->time_type != MYSQL_TIMESTAMP_TIME) + { + st->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE; + return TRUE; + } + return FALSE; +} + + + /* Remove trailing spaces and garbage */ +static my_bool get_suffix(const char *str, size_t length, size_t *new_length) +{ + /* + QQ: perhaps 'T' should be considered as a date/time delimiter only + if it's followed by a digit. Learn ISO 8601 details. + */ + my_bool garbage= FALSE; + for ( ; length > 0 ; length--) + { + char ch= str[length - 1]; + if (my_isdigit(&my_charset_latin1, ch) || + my_ispunct(&my_charset_latin1, ch)) + break; + if (my_isspace(&my_charset_latin1, ch)) + continue; + if (ch == 'T') + { + /* 'T' has a meaning only after a digit. Otherwise it's a garbage */ + if (length >= 2 && my_isdigit(&my_charset_latin1, str[length - 2])) + break; + } + garbage= TRUE; + } + *new_length= length; + return garbage; +} + + +static size_t get_prefix(const char *str, size_t length, const char **endptr) +{ + const char *str0= str, *end= str + length; + for (; str < end && my_isspace(&my_charset_latin1, *str) ; str++) + { } + *endptr= str; + return str - str0; +} + + +static size_t get_sign(my_bool *neg, const char *str, size_t length, + const char **endptr) +{ + const char *str0= str; + if (length) + { + if ((*neg= (*str == '-')) || (*str == '+')) + str++; + } + else + *neg= FALSE; + *endptr= str; + return str - str0; +} + + +static my_bool find_body(my_bool *neg, const char *str, size_t length, + MYSQL_TIME *to, int *warn, + const char **new_str, size_t *new_length) +{ + size_t sign_length; + *warn= 0; + length-= get_prefix(str, length, &str); + sign_length= get_sign(neg, str, length, &str); + length-= sign_length; + /* There can be a space after a sign again: '- 10:20:30' or '- 1 10:20:30' */ + length-= get_prefix(str, length, &str); + if (get_suffix(str, length, &length)) + *warn|= MYSQL_TIME_WARN_TRUNCATED; + *new_str= str; + *new_length= length; + if (!length || !my_isdigit(&my_charset_latin1, *str)) + { + *warn|= MYSQL_TIME_WARN_EDOM; + set_zero_time(to, MYSQL_TIMESTAMP_ERROR); + return TRUE; + } + return FALSE; +} + + +typedef struct +{ + uint count_punct; + uint count_colon; + uint count_iso_date_time_separator; +} MYSQL_TIME_USED_CHAR_STATISTICS; + + +static void +mysql_time_used_char_statistics_init(MYSQL_TIME_USED_CHAR_STATISTICS *to, + const char *str, const char *end) +{ + const char *s; + bzero((void *) to, sizeof(MYSQL_TIME_USED_CHAR_STATISTICS)); + for (s= str; s < end; s++) + { + if (my_ispunct(&my_charset_latin1, *s)) + to->count_punct++; + if (*s == ':') + to->count_colon++; + if (*s == 'T') + to->count_iso_date_time_separator++; + } +} + + +static my_bool +is_datetime_body_candidate(const char *str, size_t length, + my_bool allow_dates_delimited, + my_bool allow_dates_numeric) +{ + static uint min_date_length= 5; /* '1-1-1' -> '0001-01-01' */ + uint pos, count_punct= 0; + uint date_time_separator_length= MY_TEST(!allow_dates_delimited); + if (length >= 12) + return TRUE; + /* + The shortest possible DATE is '1-1-1', which is 5 characters. + To make a full datetime it should be at least followed by a space or a 'T'. + To make a date it should be just not less that 5 characters. + */ + if (length < min_date_length + date_time_separator_length && + !allow_dates_numeric) + return FALSE; + for (pos= 0; pos < length; pos++) + { + if (str[pos] == 'T') /* Date/time separator */ + return TRUE; + if (str[pos] == ' ') + { + /* + We found a space. If can be a DATE/TIME separator: + TIME('1-1-1 1:1:1.0) -> '0001-01-01 01:01:01.0' + + But it can be also a DAY/TIME separator: + TIME('1 11') -> 35:00:00 = 1 day 11 hours + TIME('1 111') -> 135:00:00 = 1 day 111 hours + TIME('11 11') -> 275:00:00 = 11 days 11 hours + TIME('111 11') -> 838:59:59 = 111 days 11 hours with overflow + TIME('1111 11') -> 838:59:59 = 1111 days 11 hours with overflow + */ + return count_punct > 0; /* Can be a DATE if already had separators*/ + } + if (my_ispunct(&my_charset_latin1, str[pos])) + { + if (allow_dates_delimited && str[pos] != ':') + return TRUE; + count_punct++; + } + } + return allow_dates_numeric && count_punct == 0; +} + + +static my_bool +str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length, + MYSQL_TIME *l_time, + ulong max_hour, ulong err_hour, + MYSQL_TIME_STATUS *status, + const char **endptr); + + /* Convert a timestamp string to a MYSQL_TIME value. SYNOPSIS - str_to_datetime() + str_to_datetime_or_date_body() str String to parse length Length of string l_time Date is stored here flags Bitmap of following items - TIME_FUZZY_DATE TIME_DATETIME_ONLY Set if we only allow full datetimes. TIME_NO_ZERO_IN_DATE Don't allow partial dates TIME_NO_ZERO_DATE Don't allow 0000-00-00 date TIME_INVALID_DATES Allow 2000-02-31 + punct_is_date_time_separator + Allow punctuation as a date/time separator, + or return a hard error. status Conversion status @@ -292,32 +502,22 @@ static void get_microseconds(ulong *val, MYSQL_TIME_STATUS *status, #define MAX_DATE_PARTS 8 -my_bool -str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time, - ulonglong flags, MYSQL_TIME_STATUS *status) +static my_bool +str_to_datetime_or_date_body(const char *str, size_t length, MYSQL_TIME *l_time, + ulonglong flags, + my_bool punct_is_date_time_separator, + MYSQL_TIME_STATUS *status, + uint *number_of_fields, + const char **endptr) { const char *end=str+length, *pos; - uint number_of_fields= 0, digits, year_length, not_zero_date; - DBUG_ENTER("str_to_datetime"); + uint digits, year_length, not_zero_date; + int warn= 0; + DBUG_ENTER("str_to_datetime_or_date_body"); + DBUG_ASSERT(C_FLAGS_OK(flags)); bzero(l_time, sizeof(*l_time)); - - if (flags & TIME_TIME_ONLY) - { - my_bool ret= str_to_time(str, length, l_time, flags, status); - DBUG_RETURN(ret); - } - - my_time_status_init(status); - - /* Skip space at start */ - for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++) - ; - if (str == end || ! my_isdigit(&my_charset_latin1, *str)) - { - status->warnings= MYSQL_TIME_WARN_TRUNCATED; - l_time->time_type= MYSQL_TIMESTAMP_NONE; - DBUG_RETURN(1); - } + *number_of_fields= 0; + *endptr= str; /* Calculate number of digits in first part. @@ -345,49 +545,53 @@ str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time, (only numbers like [YY]YYMMDD[T][hhmmss[.uuuuuu]]) */ year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2; - if (get_digits(&l_time->year, &number_of_fields, &str, end, year_length) - || get_digits(&l_time->month, &number_of_fields, &str, end, 2) - || get_digits(&l_time->day, &number_of_fields, &str, end, 2) + if (get_digits(&l_time->year, number_of_fields, &str, end, year_length) + || get_digits(&l_time->month, number_of_fields, &str, end, 2) + || get_digits(&l_time->day, number_of_fields, &str, end, 2) || get_maybe_T(&str, end) - || get_digits(&l_time->hour, &number_of_fields, &str, end, 2) - || get_digits(&l_time->minute, &number_of_fields, &str, end, 2) - || get_digits(&l_time->second, &number_of_fields, &str, end, 2)) - status->warnings|= MYSQL_TIME_WARN_TRUNCATED; + || get_digits(&l_time->hour, number_of_fields, &str, end, 2) + || get_digits(&l_time->minute, number_of_fields, &str, end, 2) + || get_digits(&l_time->second, number_of_fields, &str, end, 2)) + warn|= MYSQL_TIME_WARN_TRUNCATED; } else { const char *start= str; - if (get_number(&l_time->year, &number_of_fields, &str, end)) - status->warnings|= MYSQL_TIME_WARN_TRUNCATED; + if (get_number(&l_time->year, number_of_fields, &str, end)) + warn|= MYSQL_TIME_WARN_TRUNCATED; year_length= (uint)(str - start); - if (!status->warnings && + if (!warn && (get_punct(&str, end) - || get_number(&l_time->month, &number_of_fields, &str, end) + || get_number(&l_time->month, number_of_fields, &str, end) || get_punct(&str, end) - || get_number(&l_time->day, &number_of_fields, &str, end) - || get_date_time_separator(&number_of_fields, flags, &str, end) - || get_number(&l_time->hour, &number_of_fields, &str, end) + || get_number(&l_time->day, number_of_fields, &str, end) + || get_date_time_separator(number_of_fields, + punct_is_date_time_separator, &str, end) + || get_number(&l_time->hour, number_of_fields, &str, end) || get_punct(&str, end) - || get_number(&l_time->minute, &number_of_fields, &str, end) + || get_number(&l_time->minute, number_of_fields, &str, end) || get_punct(&str, end) - || get_number(&l_time->second, &number_of_fields, &str, end))) - status->warnings|= MYSQL_TIME_WARN_TRUNCATED; + || get_number(&l_time->second, number_of_fields, &str, end))) + warn|= MYSQL_TIME_WARN_TRUNCATED; } + status->warnings|= warn; + *endptr= str; /* we're ok if date part is correct. even if the rest is truncated */ - if (number_of_fields < 3) + if (*number_of_fields < 3) { l_time->time_type= MYSQL_TIMESTAMP_NONE; status->warnings|= MYSQL_TIME_WARN_TRUNCATED; DBUG_RETURN(TRUE); } - if (!status->warnings && str < end && *str == '.') + if (!warn && str < end && *str == '.') { str++; get_microseconds(&l_time->second_part, status, - &number_of_fields, &str, end); + number_of_fields, &str, end); + *endptr= str; } not_zero_date = l_time->year || l_time->month || l_time->day || @@ -407,23 +611,16 @@ str_to_datetime(const char *str, size_t length, MYSQL_TIME *l_time, if (check_date(l_time, not_zero_date, flags, &status->warnings)) goto err; - l_time->time_type= (number_of_fields <= 3 ? + l_time->time_type= (*number_of_fields <= 3 ? MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME); - for (; str != end ; str++) - { - if (!my_isspace(&my_charset_latin1,*str)) - { - status->warnings= MYSQL_TIME_WARN_TRUNCATED; - break; - } - } + if (str != end) + status->warnings= MYSQL_TIME_WARN_TRUNCATED; DBUG_RETURN(FALSE); err: - bzero((char*) l_time, sizeof(*l_time)); - l_time->time_type= MYSQL_TIMESTAMP_ERROR; + set_zero_time(l_time, MYSQL_TIMESTAMP_ERROR); DBUG_RETURN(TRUE); } @@ -432,7 +629,7 @@ err: Convert a time string to a MYSQL_TIME struct. SYNOPSIS - str_to_time() + str_to_datetime_or_date_or_time_body() str A string in full TIMESTAMP format or [-] DAYS [H]H:MM:SS, [H]H:MM:SS, [M]M:SS, [H]HMMSS, [M]MSS or [S]S @@ -457,45 +654,280 @@ err: TRUE on error */ -my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time, - ulonglong fuzzydate, MYSQL_TIME_STATUS *status) +static my_bool +str_to_datetime_or_date_or_time_body(const char *str, size_t length, + MYSQL_TIME *l_time, + ulonglong fuzzydate, + MYSQL_TIME_STATUS *status, + ulong time_max_hour, + ulong time_err_hour, + my_bool allow_dates_delimited, + my_bool allow_dates_numeric) { - ulong date[5]; - ulonglong value; - const char *end=str+length, *end_of_days; - my_bool found_days,found_hours, neg= 0; - uint UNINIT_VAR(state); - - my_time_status_init(status); - for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++) - length--; - if (str != end && *str == '-') - { - neg=1; - str++; - length--; - } - if (str == end) - { - status->warnings|= MYSQL_TIME_WARN_TRUNCATED; - goto err; - } + const char *endptr; + DBUG_ASSERT(C_FLAGS_OK(fuzzydate)); /* Check first if this is a full TIMESTAMP */ - if (length >= 12) + if (is_datetime_body_candidate(str, length, + allow_dates_delimited, + allow_dates_numeric)) { /* Probably full timestamp */ - (void) str_to_datetime(str, length, l_time, - (fuzzydate & ~TIME_TIME_ONLY) | TIME_DATETIME_ONLY, - status); - if (l_time->time_type >= MYSQL_TIMESTAMP_ERROR) - return l_time->time_type == MYSQL_TIMESTAMP_ERROR; + int warn_copy= status->warnings; /* could already be set by find_body() */ + uint number_of_fields; + (void) str_to_datetime_or_date_body(str, length, l_time, fuzzydate, + FALSE, status, + &number_of_fields, &endptr); + DBUG_ASSERT(endptr >= str); + DBUG_ASSERT(endptr <= str + length); + switch (l_time->time_type) { + case MYSQL_TIMESTAMP_DATETIME: + return FALSE; + case MYSQL_TIMESTAMP_DATE: + { + /* + Successfully parsed as DATE, but it can also be a TIME: + '24:02:03' - continue and parse as TIME + '24:02:03 garbage /////' - continue and parse as TIME + '24:02:03T' - return DATE + '24-02-03' - return DATE + '24/02/03' - return DATE + '11111' - return DATE + */ + MYSQL_TIME_USED_CHAR_STATISTICS used_chars; + mysql_time_used_char_statistics_init(&used_chars, str, endptr); + if (used_chars.count_iso_date_time_separator || !used_chars.count_colon) + return FALSE; + } + break; + case MYSQL_TIMESTAMP_ERROR: + { + MYSQL_TIME_USED_CHAR_STATISTICS used_chars; + /* + Check if it parsed as DATETIME but then failed as out of range: + '2011-02-32 8:46:06.23434' - return error + */ + if (number_of_fields > 3) + return TRUE; + /* + Check if it parsed as DATE but then failed as out of range: + '100000:02:03' - continue and parse as TIME + '100000:02:03T' - return error + '100000/02/03' - return error + '100000-02-03' - return error + */ + mysql_time_used_char_statistics_init(&used_chars, str, endptr); + if (used_chars.count_iso_date_time_separator || !used_chars.count_colon) + return TRUE; + } + break; + case MYSQL_TIMESTAMP_NONE: + { + if (allow_dates_numeric && endptr >= str + length) + { + /* + For backward compatibility this parses as DATE and fails: + EXTRACT(DAY FROM '1111') -- return error + EXTRACT(DAY FROM '1') -- return error + */ + MYSQL_TIME_USED_CHAR_STATISTICS used_chars; + mysql_time_used_char_statistics_init(&used_chars, str, endptr); + if (!used_chars.count_iso_date_time_separator && + !used_chars.count_colon && + !used_chars.count_punct) + return TRUE; + } + /* + - '256 10:30:30' - continue and parse as TIME + - '4294967296:59:59.123456456' - continue and parse as TIME + */ + } + break; + case MYSQL_TIMESTAMP_TIME: + DBUG_ASSERT(0); + break; + } + my_time_status_init(status); + status->warnings= warn_copy; + } + + if (!str_to_DDhhmmssff_internal(FALSE, str, length, l_time, + time_max_hour, time_err_hour, + status, &endptr)) + return FALSE; + + set_zero_time(l_time, MYSQL_TIMESTAMP_ERROR); + return TRUE; +} + + +/* + Convert a string with INTERVAL DAY TO SECOND to MYSQL_TIME. + Input format: [-][DD ]hh:mm:ss.ffffff + + If the input string appears to be a DATETIME, error is returned. +*/ +my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *ltime, + ulong max_hour, MYSQL_TIME_STATUS *status) +{ + my_bool neg; + const char *endptr; + + my_time_status_init(status); + if (find_body(&neg, str, length, ltime, &status->warnings, &str, &length)) + return TRUE; + + /* Reject anything that might be parsed as a full TIMESTAMP */ + if (is_datetime_body_candidate(str, length, FALSE, FALSE)) + { + uint number_of_fields; + (void) str_to_datetime_or_date_body(str, length, ltime, 0, FALSE, + status, &number_of_fields, &endptr); + if (ltime->time_type > MYSQL_TIMESTAMP_ERROR) + { + status->warnings|= MYSQL_TIME_WARN_TRUNCATED; + ltime->time_type= MYSQL_TIMESTAMP_NONE; + return TRUE; + } my_time_status_init(status); } + /* + Scan DDhhmmssff then reject anything that can remind date/datetime. + For example, in case of '2001-01-01', str_to_DDhhmmssff_internal() + will scan only '2001'. + */ + if (str_to_DDhhmmssff_internal(neg, str, length, ltime, max_hour, + UINT_MAX32, status, &endptr) || + (endptr < str + length && endptr[0] == '-')) + return TRUE; + return FALSE; +} + + +my_bool +str_to_datetime_or_date_or_time(const char *str, size_t length, + MYSQL_TIME *to, ulonglong mode, + MYSQL_TIME_STATUS *status, + ulong time_max_hour, + ulong time_err_hour) +{ + my_bool neg; + DBUG_ASSERT(C_FLAGS_OK(mode)); + my_time_status_init(status); + return + find_body(&neg, str, length, to, &status->warnings, &str, &length) || + str_to_datetime_or_date_or_time_body(str, length, to, mode, status, + time_max_hour, time_err_hour, + FALSE, FALSE) || + set_neg(neg, status, to); +} + + +my_bool +str_to_datetime_or_date_or_interval_hhmmssff(const char *str, size_t length, + MYSQL_TIME *to, ulonglong mode, + MYSQL_TIME_STATUS *status, + ulong time_max_hour, + ulong time_err_hour) +{ + my_bool neg; + DBUG_ASSERT(C_FLAGS_OK(mode)); + my_time_status_init(status); + return + find_body(&neg, str, length, to, &status->warnings, &str, &length) || + str_to_datetime_or_date_or_time_body(str, length, to, mode, status, + time_max_hour, time_err_hour, + TRUE, FALSE) || + set_neg(neg, status, to); +} + + +my_bool +str_to_datetime_or_date_or_interval_day(const char *str, size_t length, + MYSQL_TIME *to, ulonglong mode, + MYSQL_TIME_STATUS *status, + ulong time_max_hour, + ulong time_err_hour) +{ + my_bool neg; + DBUG_ASSERT(C_FLAGS_OK(mode)); + my_time_status_init(status); + /* + For backward compatibility we allow to parse non-delimited + values as DATE rather than as TIME: + EXTRACT(DAY FROM '11111') + */ + return + find_body(&neg, str, length, to, &status->warnings, &str, &length) || + str_to_datetime_or_date_or_time_body(str, length, to, mode, status, + time_max_hour, time_err_hour, + TRUE, TRUE) || + set_neg(neg, status, to); +} + + +my_bool +str_to_datetime_or_date(const char *str, size_t length, MYSQL_TIME *l_time, + ulonglong flags, MYSQL_TIME_STATUS *status) +{ + my_bool neg; + uint number_of_fields; + const char *endptr; + DBUG_ASSERT(C_FLAGS_OK(flags)); + my_time_status_init(status); + return + find_body(&neg, str, length, l_time, &status->warnings, &str, &length) || + str_to_datetime_or_date_body(str, length, l_time, flags, TRUE, + status, &number_of_fields, &endptr) || + set_neg(neg, status, l_time); +} + + + +/** + Convert a string to INTERVAL DAY TO SECOND. + Input format: [DD ]hh:mm:ss.ffffff + + Datetime or date formats are not understood. + + Optional leading spaces and signs must be scanned by the caller. + "str" should point to the first digit. + + @param neg - set the value to be negative + @param str - the input string + @param length - length of "str" + @param[OUT] l_time - write the result here + @param max_hour - if the result hour value appears to be greater than + max_hour, then cut to result to 'max_hour:59:59.999999' + @param err_hour - if the hour appears to be greater than err_hour, + return an error (without cut) + @param status + @param endptr +*/ +static my_bool +str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length, + MYSQL_TIME *l_time, + ulong max_hour, ulong err_hour, + MYSQL_TIME_STATUS *status, const char **endptr) +{ + ulong date[5]; + ulonglong value; + const char *end=str + length, *end_of_days; + my_bool found_days, found_hours; + uint UNINIT_VAR(state); + + *endptr= str; l_time->neg= neg; - /* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */ + /* Not a timestamp. Try to get this as a DAYS TO SECOND string */ for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++) + { value=value*10L + (long) (*str - '0'); + if (value >= 42949672955959ULL) /* i.e. UINT_MAX32 : 59 : 59 */ + { + status->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE; + goto err; + } + } /* Skip all space after 'days' */ end_of_days= str; @@ -514,6 +946,11 @@ my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time, my_isdigit(&my_charset_latin1, str[1])) { date[0]= 0; /* Assume we found hours */ + if (value >= UINT_MAX32) + { + status->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE; + goto err; + } date[1]= (ulong) value; state=2; found_hours=1; @@ -523,6 +960,7 @@ my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time, { /* String given as one number; assume HHMMSS format */ date[0]= 0; + DBUG_ASSERT(value <= ((ulonglong) UINT_MAX32) * 10000ULL); date[1]= (ulong) (value/10000); date[2]= (ulong) (value/100 % 100); date[3]= (ulong) (value % 100); @@ -557,7 +995,7 @@ my_bool str_to_time(const char *str, size_t length, MYSQL_TIME *l_time, fractional: /* Get fractional second part */ - if (!status->warnings && str < end && *str == '.') + if (str < end && *str == '.') { uint number_of_fields= 0; str++; @@ -605,6 +1043,11 @@ fractional: goto err; } + if ((ulonglong) date[0] * 24 + date[1] > (ulonglong) UINT_MAX32) + { + status->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE; + goto err; + } l_time->year= 0; /* For protocol::store_time */ l_time->month= 0; l_time->day= 0; @@ -614,27 +1057,20 @@ fractional: l_time->second_part= date[4]; l_time->time_type= MYSQL_TIMESTAMP_TIME; + *endptr= str; + /* Check if the value is valid and fits into MYSQL_TIME range */ - if (check_time_range(l_time, 6, &status->warnings)) + if (check_time_range_internal(l_time, max_hour, err_hour, + 6, &status->warnings)) return TRUE; /* Check if there is garbage at end of the MYSQL_TIME specification */ if (str != end) - { - do - { - if (!my_isspace(&my_charset_latin1,*str)) - { - status->warnings|= MYSQL_TIME_WARN_TRUNCATED; - break; - } - } while (++str != end); - } + status->warnings|= MYSQL_TIME_WARN_TRUNCATED; return FALSE; err: - bzero((char*) l_time, sizeof(*l_time)); - l_time->time_type= MYSQL_TIMESTAMP_ERROR; + *endptr= str; return TRUE; } @@ -643,8 +1079,11 @@ err: Check 'time' value to lie in the MYSQL_TIME range SYNOPSIS: - check_time_range() + check_time_range_internal() time pointer to MYSQL_TIME value + ulong max_hour - maximum allowed hour value. if the hour is greater, + cut the time value to 'max_hour:59:59.999999' + ulong err_hour - if hour is greater than this value, return an error uint dec warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range @@ -658,13 +1097,16 @@ err: 1 time value is invalid */ -int check_time_range(struct st_mysql_time *my_time, uint dec, int *warning) +int check_time_range_internal(struct st_mysql_time *my_time, + ulong max_hour, ulong err_hour, + uint dec, int *warning) { - longlong hour; + ulonglong hour; static ulong max_sec_part[TIME_SECOND_PART_DIGITS+1]= {000000, 900000, 990000, 999000, 999900, 999990, 999999}; - if (my_time->minute >= 60 || my_time->second >= 60) + if (my_time->minute >= 60 || my_time->second >= 60 || + my_time->hour > err_hour) { *warning|= MYSQL_TIME_WARN_TRUNCATED; return 1; @@ -675,14 +1117,14 @@ int check_time_range(struct st_mysql_time *my_time, uint dec, int *warning) if (dec == AUTO_SEC_PART_DIGITS) dec= TIME_SECOND_PART_DIGITS; - if (hour <= TIME_MAX_HOUR && - (hour != TIME_MAX_HOUR || my_time->minute != TIME_MAX_MINUTE || + if (hour <= max_hour && + (hour != max_hour || my_time->minute != TIME_MAX_MINUTE || my_time->second != TIME_MAX_SECOND || my_time->second_part <= max_sec_part[dec])) return 0; my_time->day= 0; - my_time->hour= TIME_MAX_HOUR; + my_time->hour= max_hour; my_time->minute= TIME_MAX_MINUTE; my_time->second= TIME_MAX_SECOND; my_time->second_part= max_sec_part[dec]; @@ -1031,6 +1473,46 @@ static char* fmt_number(uint val, char *out, uint digits) } +static int my_mmssff_to_str(const MYSQL_TIME *ltime, char *to, uint fsp) +{ + char *pos= to; + if (fsp == AUTO_SEC_PART_DIGITS) + fsp= ltime->second_part ? TIME_SECOND_PART_DIGITS : 0; + DBUG_ASSERT(fsp <= TIME_SECOND_PART_DIGITS); + pos= fmt_number(ltime->minute, pos, 2); + *pos++= ':'; + pos= fmt_number(ltime->second, pos, 2); + if (fsp) + { + *pos++= '.'; + pos= fmt_number((uint)sec_part_shift(ltime->second_part, fsp), pos, fsp); + } + return (int) (pos - to); +} + + +int my_interval_DDhhmmssff_to_str(const MYSQL_TIME *ltime, char *to, uint fsp) +{ + uint hour= ltime->day * 24 + ltime->hour; + char *pos= to; + DBUG_ASSERT(!ltime->year); + DBUG_ASSERT(!ltime->month); + + if(ltime->neg) + *pos++= '-'; + if (hour >= 24) + { + pos= longlong10_to_str((longlong) hour / 24, pos, 10); + *pos++= ' '; + } + pos= fmt_number(hour % 24, pos, 2); + *pos++= ':'; + pos+= my_mmssff_to_str(ltime, pos, fsp); + *pos= 0; + return (int) (pos-to); +} + + /* Functions to convert time/date/datetime value to a string, using default format. @@ -1048,11 +1530,6 @@ int my_time_to_str(const MYSQL_TIME *l_time, char *to, uint digits) uint hour= day * 24 + l_time->hour; char*pos= to; - if (digits == AUTO_SEC_PART_DIGITS) - digits= l_time->second_part ? TIME_SECOND_PART_DIGITS : 0; - - DBUG_ASSERT(digits <= TIME_SECOND_PART_DIGITS); - if(l_time->neg) *pos++= '-'; @@ -1063,17 +1540,7 @@ int my_time_to_str(const MYSQL_TIME *l_time, char *to, uint digits) pos= fmt_number(hour, pos, 2); *pos++= ':'; - pos= fmt_number(l_time->minute, pos, 2); - *pos++= ':'; - pos= fmt_number(l_time->second, pos, 2); - - if (digits) - { - *pos++= '.'; - pos= fmt_number((uint)sec_part_shift(l_time->second_part, digits), - pos, digits); - } - + pos+= my_mmssff_to_str(l_time, pos, digits); *pos= 0; return (int) (pos-to); } @@ -1095,12 +1562,6 @@ int my_date_to_str(const MYSQL_TIME *l_time, char *to) int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint digits) { char *pos= to; - - if (digits == AUTO_SEC_PART_DIGITS) - digits= l_time->second_part ? TIME_SECOND_PART_DIGITS : 0; - - DBUG_ASSERT(digits <= TIME_SECOND_PART_DIGITS); - pos= fmt_number(l_time->year, pos, 4); *pos++='-'; pos= fmt_number(l_time->month, pos, 2); @@ -1109,17 +1570,7 @@ int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint digits) *pos++=' '; pos= fmt_number(l_time->hour, pos, 2); *pos++= ':'; - pos= fmt_number(l_time->minute, pos, 2); - *pos++= ':'; - pos= fmt_number(l_time->second, pos, 2); - - if (digits) - { - *pos++='.'; - pos= fmt_number((uint) sec_part_shift(l_time->second_part, digits), pos, - digits); - } - + pos+= my_mmssff_to_str(l_time, pos, digits); *pos= 0; return (int)(pos - to); } @@ -1185,7 +1636,7 @@ int my_timeval_to_str(const struct timeval *tm, char *to, uint dec) representation and form value of DATETIME type as side-effect. SYNOPSIS - number_to_datetime() + number_to_datetime_or_date() nr - datetime value as number time_res - pointer for structure for broken-down representation flags - flags to use in validating date, as in str_to_datetime() @@ -1206,10 +1657,12 @@ int my_timeval_to_str(const struct timeval *tm, char *to, uint dec) Datetime value in YYYYMMDDHHMMSS format. */ -longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res, - ulonglong flags, int *was_cut) +longlong number_to_datetime_or_date(longlong nr, ulong sec_part, + MYSQL_TIME *time_res, + ulonglong flags, int *was_cut) { long part1,part2; + DBUG_ASSERT(C_FLAGS_OK(flags)); *was_cut= 0; time_res->time_type=MYSQL_TIMESTAMP_DATE; @@ -1279,8 +1732,8 @@ longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res, } /* Don't want to have was_cut get set if NO_ZERO_DATE was violated. */ - if (nr || !(flags & TIME_NO_ZERO_DATE)) - *was_cut= 1; + if (nr || !(flags & C_TIME_NO_ZERO_DATE)) + *was_cut= MYSQL_TIME_WARN_TRUNCATED; return -1; err: @@ -1289,7 +1742,7 @@ longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res, enum enum_mysql_timestamp_type save= time_res->time_type; bzero((char*) time_res, sizeof(*time_res)); time_res->time_type= save; /* Restore range */ - *was_cut= 1; /* Found invalid date */ + *was_cut= MYSQL_TIME_WARN_TRUNCATED; /* Found invalid date */ } return -1; } @@ -1310,22 +1763,20 @@ longlong number_to_datetime(longlong nr, ulong sec_part, MYSQL_TIME *time_res, 0 time value is valid, but was possibly truncated -1 time value is invalid */ -int number_to_time(my_bool neg, ulonglong nr, ulong sec_part, - MYSQL_TIME *ltime, int *was_cut) +int number_to_time_only(my_bool neg, ulonglong nr, ulong sec_part, + ulong max_hour, MYSQL_TIME *ltime, int *was_cut) { - if (nr > 9999999 && nr < 99991231235959ULL && neg == 0) - return number_to_datetime(nr, sec_part, ltime, - TIME_INVALID_DATES, was_cut) < 0 ? -1 : 0; - + static const ulonglong TIME_MAX_mmss= TIME_MAX_MINUTE*100 + TIME_MAX_SECOND; + ulonglong time_max_value= max_hour * 10000ULL + TIME_MAX_mmss; *was_cut= 0; ltime->year= ltime->month= ltime->day= 0; ltime->time_type= MYSQL_TIMESTAMP_TIME; ltime->neg= neg; - if (nr > TIME_MAX_VALUE) + if (nr > time_max_value) { - nr= TIME_MAX_VALUE; + nr= time_max_value; sec_part= TIME_MAX_SECOND_PART; *was_cut= MYSQL_TIME_WARN_OUT_OF_RANGE; } diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index c6910f469f9..697b794f39f 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -136,7 +136,7 @@ SET (SQL_SOURCE opt_split.cc ${WSREP_SOURCES} table_cache.cc encryption.cc temporary_tables.cc - proxy_protocol.cc + proxy_protocol.cc backup.cc ${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc @@ -152,6 +152,7 @@ IF (CMAKE_SYSTEM_NAME MATCHES "Linux" OR ADD_DEFINITIONS(-DHAVE_POOL_OF_THREADS) IF(WIN32) SET(SQL_SOURCE ${SQL_SOURCE} threadpool_win.cc) + SET(SQL_SOURCE ${SQL_SOURCE} handle_connections_win.cc) ENDIF() SET(SQL_SOURCE ${SQL_SOURCE} threadpool_generic.cc) diff --git a/sql/backup.cc b/sql/backup.cc new file mode 100644 index 00000000000..e022a7c2c04 --- /dev/null +++ b/sql/backup.cc @@ -0,0 +1,356 @@ +/* Copyright (c) 2018, MariaDB Corporation + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* + Implementation of BACKUP STAGE, an interface for external backup tools. + + TODO: + - At backup_start() we call ha_prepare_for_backup() for all active + storage engines. If someone tries to load a new storage engine + that requires prepare_for_backup() for it to work, that storage + engines has to be blocked from loading until backup finishes. + As we currently don't have any loadable storage engine that + requires this and we have not implemented that part. + This can easily be done by adding a + PLUGIN_CANT_BE_LOADED_WHILE_BACKUP_IS_RUNNING flag to + maria_declare_plugin and check this before calling + plugin_initialize() +*/ + +#include "mariadb.h" +#include "sql_class.h" +#include "sql_base.h" // flush_tables +#include "sql_insert.h" // kill_delayed_threads +#include "sql_handler.h" // mysql_ha_cleanup_no_free +#include <my_sys.h> + +static const char *stage_names[]= +{"START", "FLUSH", "BLOCK_DDL", "BLOCK_COMMIT", "END", 0}; + +TYPELIB backup_stage_names= +{ array_elements(stage_names)-1, "", stage_names, 0 }; + +static MDL_ticket *backup_flush_ticket; + +static bool backup_start(THD *thd); +static bool backup_flush(THD *thd); +static bool backup_block_ddl(THD *thd); +static bool backup_block_commit(THD *thd); + +/** + Run next stage of backup +*/ + +void backup_init() +{ + backup_flush_ticket= 0; +} + +bool run_backup_stage(THD *thd, backup_stages stage) +{ + backup_stages next_stage; + DBUG_ENTER("run_backup_stage"); + + if (thd->current_backup_stage == BACKUP_FINISHED) + { + if (stage != BACKUP_START) + { + my_error(ER_BACKUP_NOT_RUNNING, MYF(0)); + DBUG_RETURN(1); + } + next_stage= BACKUP_START; + } + else + { + if ((uint) thd->current_backup_stage >= (uint) stage) + { + my_error(ER_BACKUP_WRONG_STAGE, MYF(0), stage_names[stage], + stage_names[thd->current_backup_stage]); + DBUG_RETURN(1); + } + if (stage == BACKUP_END) + { + /* + If end is given, jump directly to stage end. This is to allow one + to abort backup quickly. + */ + next_stage= stage; + } + else + { + /* Go trough all not used stages until we reach 'stage' */ + next_stage= (backup_stages) ((uint) thd->current_backup_stage + 1); + } + } + + do + { + bool res; + backup_stages previous_stage= thd->current_backup_stage; + thd->current_backup_stage= next_stage; + switch (next_stage) { + case BACKUP_START: + if (!(res= backup_start(thd))) + break; + /* Reset backup stage to start for next backup try */ + previous_stage= BACKUP_FINISHED; + break; + case BACKUP_FLUSH: + res= backup_flush(thd); + break; + case BACKUP_WAIT_FOR_FLUSH: + res= backup_block_ddl(thd); + break; + case BACKUP_LOCK_COMMIT: + res= backup_block_commit(thd); + break; + case BACKUP_END: + res= backup_end(thd); + break; + case BACKUP_FINISHED: + DBUG_ASSERT(0); + res= 0; + } + if (res) + { + thd->current_backup_stage= previous_stage; + my_error(ER_BACKUP_STAGE_FAILED, MYF(0), stage_names[(uint) stage]); + DBUG_RETURN(1); + } + next_stage= (backup_stages) ((uint) next_stage + 1); + } while ((uint) next_stage <= (uint) stage); + + DBUG_RETURN(0); +} + + +/** + Start the backup + + - Wait for previous backup to stop running + - Start service to log changed tables (TODO) + - Block purge of redo files (Required at least for Aria) + - An handler can optionally do a checkpoint of all tables, + to speed up the recovery stage of the backup. +*/ + +static bool backup_start(THD *thd) +{ + MDL_request mdl_request; + DBUG_ENTER("backup_start"); + + thd->current_backup_stage= BACKUP_FINISHED; // For next test + if (thd->has_read_only_protection()) + DBUG_RETURN(1); + thd->current_backup_stage= BACKUP_START; + + if (thd->locked_tables_mode) + { + my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); + DBUG_RETURN(1); + } + + mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_START, MDL_EXPLICIT); + if (thd->mdl_context.acquire_lock(&mdl_request, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(1); + + backup_flush_ticket= mdl_request.ticket; + + ha_prepare_for_backup(); + DBUG_RETURN(0); +} + +/** + backup_flush() + + - FLUSH all changes for not active non transactional tables, except + for statistics and log tables. Close the tables, to ensure they + are marked as closed after backup. + + - BLOCK all NEW write locks for all non transactional tables + (except statistics and log tables). Already granted locks are + not affected (Running statements with non transaction tables will + continue running). + + - The following DDL's doesn't have to be blocked as they can't set + the table in a non consistent state: + CREATE, RENAME, DROP +*/ + +static bool backup_flush(THD *thd) +{ + DBUG_ENTER("backup_flush"); + /* + Lock all non transactional normal tables to be used in new DML's + */ + if (thd->mdl_context.upgrade_shared_lock(backup_flush_ticket, + MDL_BACKUP_FLUSH, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(1); + + /* + Free unused tables and table shares so that mariabackup knows what + is safe to copy + */ + tc_purge(false); + tdc_purge(true); + + DBUG_RETURN(0); +} + +/** + backup_block_ddl() + + - Kill all insert delay handlers, to ensure that all non transactional + tables are closed (can be improved in the future). + + - Close handlers as other threads may wait for these, which can cause deadlocks. + + - Wait for all statements using write locked non-transactional tables to end. + + - Mark all not used active non transactional tables (except + statistics and log tables) to be closed with + handler->extra(HA_EXTRA_FLUSH) + + - Block TRUNCATE TABLE, CREATE TABLE, DROP TABLE and RENAME + TABLE. Block also start of a new ALTER TABLE and the final rename + phase of ALTER TABLE. Running ALTER TABLES are not blocked. Both normal + and inline ALTER TABLE'S should be blocked when copying is completed but + before final renaming of the tables / new table is activated. + This will probably require a callback from the InnoDB code. +*/ + +static bool backup_block_ddl(THD *thd) +{ + DBUG_ENTER("backup_block_ddl"); + + kill_delayed_threads(); + mysql_ha_cleanup_no_free(thd); + + /* Wait until all non trans statements has ended */ + if (thd->mdl_context.upgrade_shared_lock(backup_flush_ticket, + MDL_BACKUP_WAIT_FLUSH, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(1); + + /* + Remove not used tables from the table share. Flush all changes to + non transaction tables and mark those that are not in use in write + operations as closed. From backup purposes it's not critical if + flush_tables() returns an error. It's ok to continue with next + backup stage even if we got an error. + */ + (void) flush_tables(thd, FLUSH_NON_TRANS_TABLES); + + /* + block new DDL's, in addition to all previous blocks + We didn't do this lock above, as we wanted DDL's to be executed while + we wait for non transactional tables (which may take a while). + */ + if (thd->mdl_context.upgrade_shared_lock(backup_flush_ticket, + MDL_BACKUP_WAIT_DDL, + thd->variables.lock_wait_timeout)) + { + /* + Could be a timeout. Downgrade lock to what is was before this function + was called so that this function can be called again + */ + backup_flush_ticket->downgrade_lock(MDL_BACKUP_FLUSH); + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} + +/** + backup_block_commit() + + Block commits, writes to log and statistics tables and binary log +*/ + +static bool backup_block_commit(THD *thd) +{ + DBUG_ENTER("backup_block_commit"); + if (thd->mdl_context.upgrade_shared_lock(backup_flush_ticket, + MDL_BACKUP_WAIT_COMMIT, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(1); + flush_tables(thd, FLUSH_SYS_TABLES); + DBUG_RETURN(0); +} + +/** + backup_end() + + Safe to run, even if backup has not been run by this thread. + This is for example the case when a THD ends. +*/ + +bool backup_end(THD *thd) +{ + DBUG_ENTER("backup_end"); + + if (thd->current_backup_stage != BACKUP_FINISHED) + { + ha_end_backup(); + thd->current_backup_stage= BACKUP_FINISHED; + thd->mdl_context.release_lock(backup_flush_ticket); + } + DBUG_RETURN(0); +} + + +/** + backup_set_alter_copy_lock() + + @param thd + @param table From table that is part of ALTER TABLE. This is only used + for the assert to ensure we use this function correctly. + + Downgrades the MDL_BACKUP_DDL lock to MDL_BACKUP_ALTER_COPY to allow + copy of altered table to proceed under MDL_BACKUP_WAIT_DDL + + Note that in some case when using non transactional tables, + the lock may be of type MDL_BACKUP_DML. +*/ + +void backup_set_alter_copy_lock(THD *thd, TABLE *table) +{ + MDL_ticket *ticket= thd->mdl_backup_ticket; + + /* Ticket maybe NULL in case of LOCK TABLES or for temporary tables*/ + DBUG_ASSERT(ticket || thd->locked_tables_mode || + table->s->tmp_table != NO_TMP_TABLE); + if (ticket) + ticket->downgrade_lock(MDL_BACKUP_ALTER_COPY); +} + +/** + backup_reset_alter_copy_lock + + Upgrade the lock of the original ALTER table MDL_BACKUP_DDL + Can fail if MDL lock was killed +*/ + +bool backup_reset_alter_copy_lock(THD *thd) +{ + bool res= 0; + MDL_ticket *ticket= thd->mdl_backup_ticket; + + /* Ticket maybe NULL in case of LOCK TABLES or for temporary tables*/ + if (ticket) + res= thd->mdl_context.upgrade_shared_lock(ticket, MDL_BACKUP_DDL, + thd->variables.lock_wait_timeout); + return res; +} diff --git a/sql/backup.h b/sql/backup.h new file mode 100644 index 00000000000..e6f290ae9c8 --- /dev/null +++ b/sql/backup.h @@ -0,0 +1,31 @@ +#ifndef BACKUP_INCLUDED +#define BACKUP_INCLUDED +/* Copyright (c) 2018, MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +enum backup_stages +{ + BACKUP_START, BACKUP_FLUSH, BACKUP_WAIT_FOR_FLUSH, BACKUP_LOCK_COMMIT, + BACKUP_END, BACKUP_FINISHED +}; + +extern TYPELIB backup_stage_names; + +void backup_init(); +bool run_backup_stage(THD *thd, backup_stages stage); +bool backup_end(THD *thd); +void backup_set_alter_copy_lock(THD *thd, TABLE *altered_table); +bool backup_reset_alter_copy_lock(THD *thd); +#endif /* BACKUP_INCLUDED */ diff --git a/sql/compat56.cc b/sql/compat56.cc index d1cb8b0042c..1285de9fd12 100644 --- a/sql/compat56.cc +++ b/sql/compat56.cc @@ -20,6 +20,19 @@ #include "myisampack.h" #include "my_time.h" + +static const int my_max_usec_value[7] +{ + 0, + 900000, + 990000, + 999000, + 999900, + 999990, + 999999 +}; + + /*** MySQL56 TIME low-level memory and disk representation routines ***/ /* @@ -397,19 +410,21 @@ void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec) case 0: default: tm->tv_usec= 0; - break; + return; case 1: case 2: tm->tv_usec= ((int) ptr[4]) * 10000; break; case 3: case 4: - tm->tv_usec= mi_sint2korr(ptr + 4) * 100; + tm->tv_usec= (uint) mi_uint2korr(ptr + 4) * 100; break; case 5: case 6: - tm->tv_usec= mi_sint3korr(ptr + 4); + tm->tv_usec= (uint) mi_uint3korr(ptr + 4); } + // The binary data my be corrupt. Cut fractional seconds to the valid range. + set_if_smaller(tm->tv_usec, my_max_usec_value[dec]); } diff --git a/sql/compat56.h b/sql/compat56.h index bb5e2670f7d..ff887ebf1bb 100644 --- a/sql/compat56.h +++ b/sql/compat56.h @@ -19,6 +19,15 @@ /** MySQL56 routines and macros **/ + +/* + Buffer size for a native TIMESTAMP representation, for use with NativBuffer. + 4 bytes for seconds + 3 bytes for microseconds + 1 byte for the trailing '\0' (class Native reserves extra 1 byte for '\0') +*/ +#define STRING_BUFFER_TIMESTAMP_BINARY_SIZE 8 /* 4 + 3 + 1 */ + #define MY_PACKED_TIME_GET_INT_PART(x) ((x) >> 24) #define MY_PACKED_TIME_GET_FRAC_PART(x) ((x) % (1LL << 24)) #define MY_PACKED_TIME_MAKE(i, f) ((((longlong) (i)) << 24) + (f)) diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 86a710f87c6..db056a9f08e 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -479,14 +479,24 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) uint not_used; if (!starts_null) { - table->field[ET_FIELD_STARTS]->get_date(&time, TIME_NO_ZERO_DATE); + /* + The expected data type for these columns in mysql.events: + starts, ends, execute_at, last_executed + is DATETIME. No nanosecond truncation should normally be needed, + unless the DBA changes them, e.g. to VARCHAR, DECIMAL, etc. + For this unexpected case let's use the default round mode, + according to the current session settings. + */ + table->field[ET_FIELD_STARTS]->get_date(&time, TIME_NO_ZERO_DATE | + thd->temporal_round_mode()); starts= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } ends_null= table->field[ET_FIELD_ENDS]->is_null(); if (!ends_null) { - table->field[ET_FIELD_ENDS]->get_date(&time, TIME_NO_ZERO_DATE); + table->field[ET_FIELD_ENDS]->get_date(&time, TIME_NO_ZERO_DATE | + thd->temporal_round_mode()); ends= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } @@ -502,8 +512,8 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) DBUG_ASSERT(!(starts_null && ends_null && !expression && execute_at_null)); if (!expression && !execute_at_null) { - if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time, - TIME_NO_ZERO_DATE)) + if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time, TIME_NO_ZERO_DATE | + thd->temporal_round_mode())) DBUG_RETURN(TRUE); execute_at= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } @@ -535,8 +545,8 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table) if (!table->field[ET_FIELD_LAST_EXECUTED]->is_null()) { - table->field[ET_FIELD_LAST_EXECUTED]->get_date(&time, - TIME_NO_ZERO_DATE); + table->field[ET_FIELD_LAST_EXECUTED]->get_date(&time, TIME_NO_ZERO_DATE | + thd->temporal_round_mode()); last_executed= my_tz_OFFSET0->TIME_to_gmt_sec(&time,¬_used); } @@ -654,7 +664,7 @@ my_time_t add_interval(MYSQL_TIME *ltime, const Time_zone *time_zone, interval_type scale, INTERVAL interval) { - if (date_add_interval(ltime, scale, interval)) + if (date_add_interval(current_thd, ltime, scale, interval)) return 0; uint not_used; @@ -758,8 +768,8 @@ bool get_next_time(const Time_zone *time_zone, my_time_t *next, if (seconds) { - longlong seconds_diff; - long microsec_diff; + ulonglong seconds_diff; + ulong microsec_diff; bool negative= calc_time_diff(&local_now, &local_start, 1, &seconds_diff, µsec_diff); if (!negative) diff --git a/sql/event_parse_data.cc b/sql/event_parse_data.cc index b2ff80626db..00d625879de 100644 --- a/sql/event_parse_data.cc +++ b/sql/event_parse_data.cc @@ -216,7 +216,13 @@ Event_parse_data::init_execute_at(THD *thd) (starts_null && ends_null))); DBUG_ASSERT(starts_null && ends_null); - if (item_execute_at->get_date(<ime, TIME_NO_ZERO_DATE)) + /* + The expected data type is DATETIME. No nanoseconds truncation should + normally be needed. Using the default rounding mode. + See more comments in event_data_object.cc. + */ + if (item_execute_at->get_date(thd, <ime, TIME_NO_ZERO_DATE | + thd->temporal_round_mode())) goto wrong_value; ltime_utc= TIME_to_timestamp(thd,<ime,¬_used); @@ -275,7 +281,7 @@ Event_parse_data::init_interval(THD *thd) if (item_expression->fix_fields(thd, &item_expression)) goto wrong_value; - if (get_interval_value(item_expression, interval, &interval_tmp)) + if (get_interval_value(thd, item_expression, interval, &interval_tmp)) goto wrong_value; expression= 0; @@ -378,7 +384,8 @@ Event_parse_data::init_starts(THD *thd) if (item_starts->fix_fields(thd, &item_starts)) goto wrong_value; - if (item_starts->get_date(<ime, TIME_NO_ZERO_DATE)) + if (item_starts->get_date(thd, <ime, TIME_NO_ZERO_DATE | + thd->temporal_round_mode())) goto wrong_value; ltime_utc= TIME_to_timestamp(thd, <ime, ¬_used); @@ -433,7 +440,8 @@ Event_parse_data::init_ends(THD *thd) goto error_bad_params; DBUG_PRINT("info", ("convert to TIME")); - if (item_ends->get_date(<ime, TIME_NO_ZERO_DATE)) + if (item_ends->get_date(thd, <ime, TIME_NO_ZERO_DATE | + thd->temporal_round_mode())) goto error_bad_params; ltime_utc= TIME_to_timestamp(thd, <ime, ¬_used); @@ -472,7 +480,7 @@ Event_parse_data::report_bad_value(const char *item_name, Item *bad_item) { char buff[120]; String str(buff,(uint32) sizeof(buff), system_charset_info); - String *str2= bad_item->fixed? bad_item->val_str(&str):NULL; + String *str2= bad_item->is_fixed() ? bad_item->val_str(&str) : NULL; my_error(ER_WRONG_VALUE, MYF(0), item_name, str2? str2->c_ptr_safe():"NULL"); } diff --git a/sql/events.cc b/sql/events.cc index c3a578f1097..196c8df591d 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -336,7 +336,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data) if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); if (lock_object_name(thd, MDL_key::EVENT, parse_data->dbname.str, parse_data->name.str)) @@ -401,7 +401,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data) my_message_sql(ER_STARTUP, "Event Error: An error occurred while creating query " "string, before writing it into binary log.", - MYF(ME_NOREFRESH)); + MYF(ME_ERROR_LOG)); ret= true; } else @@ -419,10 +419,10 @@ Events::create_event(THD *thd, Event_parse_data *parse_data) thd->restore_stmt_binlog_format(save_binlog_format); DBUG_RETURN(ret); - -WSREP_ERROR_LABEL: - DBUG_RETURN(TRUE); - +#ifdef WITH_WSREP +wsrep_error_label: + DBUG_RETURN(true); +#endif } @@ -550,9 +550,10 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, thd->restore_stmt_binlog_format(save_binlog_format); DBUG_RETURN(ret); - -WSREP_ERROR_LABEL: - DBUG_RETURN(TRUE); +#ifdef WITH_WSREP +wsrep_error_label: + DBUG_RETURN(true); +#endif } @@ -617,9 +618,10 @@ Events::drop_event(THD *thd, const LEX_CSTRING *dbname, thd->restore_stmt_binlog_format(save_binlog_format); DBUG_RETURN(ret); - -WSREP_ERROR_LABEL: - DBUG_RETURN(TRUE); +#ifdef WITH_WSREP +wsrep_error_label: + DBUG_RETURN(true); +#endif } @@ -824,12 +826,13 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) */ if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS) { - DBUG_ASSERT(thd->lex->select_lex.db.str); - if (!is_infoschema_db(&thd->lex->select_lex.db) && // There is no events in I_S - check_access(thd, EVENT_ACL, thd->lex->select_lex.db.str, + DBUG_ASSERT(thd->lex->first_select_lex()->db.str); + if (!is_infoschema_db(&thd->lex->first_select_lex()->db) && // There is no events in I_S + check_access(thd, EVENT_ACL, thd->lex->first_select_lex()->db.str, NULL, NULL, 0, 0)) DBUG_RETURN(1); - db= normalize_db_name(thd->lex->select_lex.db.str, db_tmp, sizeof(db_tmp)); + db= normalize_db_name(thd->lex->first_select_lex()->db.str, + db_tmp, sizeof(db_tmp)); } ret= db_repository->fill_schema_events(thd, tables, db); @@ -924,7 +927,7 @@ Events::init(THD *thd, bool opt_noacl_or_bootstrap) my_message(ER_STARTUP, "Event Scheduler: An error occurred when initializing " "system tables. Disabling the Event Scheduler.", - MYF(ME_NOREFRESH)); + MYF(ME_ERROR_LOG)); /* Disable the scheduler since the system tables are not up to date */ opt_event_scheduler= EVENTS_OFF; goto end; @@ -946,7 +949,7 @@ Events::init(THD *thd, bool opt_noacl_or_bootstrap) { my_message_sql(ER_STARTUP, "Event Scheduler: Error while loading from mysql.event table.", - MYF(ME_NOREFRESH)); + MYF(ME_ERROR_LOG)); res= TRUE; /* fatal error: request unireg_abort */ goto end; } @@ -1163,7 +1166,7 @@ Events::load_events_from_db(THD *thd) { my_message_sql(ER_STARTUP, "Event Scheduler: Failed to open table mysql.event", - MYF(ME_NOREFRESH)); + MYF(ME_ERROR_LOG)); DBUG_RETURN(TRUE); } @@ -1189,7 +1192,7 @@ Events::load_events_from_db(THD *thd) "Event Scheduler: " "Error while loading events from mysql.event. " "The table probably contains bad data or is corrupted", - MYF(ME_NOREFRESH)); + MYF(ME_ERROR_LOG)); delete et; goto end; } @@ -1228,9 +1231,9 @@ Events::load_events_from_db(THD *thd) } my_printf_error(ER_STARTUP, "Event Scheduler: Loaded %d event%s", - MYF(ME_NOREFRESH | + MYF(ME_ERROR_LOG | (global_system_variables.log_warnings) ? - ME_JUST_INFO: 0), + ME_NOTE: 0), count, (count == 1) ? "" : "s"); ret= FALSE; diff --git a/sql/field.cc b/sql/field.cc index fbaf3c6ea91..dd125a06bad 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -33,11 +33,6 @@ #include "rpl_rli.h" // Pull in Relay_log_info #include "slave.h" // Pull in rpl_master_has_bug() #include "strfunc.h" // find_type2, find_set -#include "sql_time.h" // str_to_datetime_with_warn, - // str_to_time_with_warn, - // TIME_to_timestamp, - // make_time, make_date, - // make_truncated_value_warning #include "tztime.h" // struct Time_zone #include "filesort.h" // change_double_for_sort #include "log_event.h" // class Table_map_log_event @@ -75,8 +70,7 @@ const char field_separator=','; (!table->write_set || \ bitmap_is_set(table->write_set, field_index) || \ (!(ptr >= table->record[0] && \ - ptr < table->record[0] + table->s->reclength))) || \ - (table->vcol_set && bitmap_is_set(table->vcol_set, field_index))) + ptr < table->record[0] + table->s->reclength)))) #define FLAGSTR(S,F) ((S) & (F) ? #F " " : "") @@ -93,15 +87,14 @@ const int FIELDTYPE_LAST= 254; const int FIELDTYPE_NUM= FIELDTYPE_TEAR_FROM + (FIELDTYPE_LAST - FIELDTYPE_TEAR_TO); -static inline int field_type2index (enum_field_types field_type) +static inline int merge_type2index(enum_field_types merge_type) { - DBUG_ASSERT(real_type_to_type(field_type) < FIELDTYPE_TEAR_FROM || - real_type_to_type(field_type) > FIELDTYPE_TEAR_TO); - DBUG_ASSERT(field_type <= FIELDTYPE_LAST); - field_type= real_type_to_type(field_type); - if (field_type < FIELDTYPE_TEAR_FROM) - return field_type; - return FIELDTYPE_TEAR_FROM + (field_type - FIELDTYPE_TEAR_TO) - 1; + DBUG_ASSERT(merge_type < FIELDTYPE_TEAR_FROM || + merge_type > FIELDTYPE_TEAR_TO); + DBUG_ASSERT(merge_type <= FIELDTYPE_LAST); + if (merge_type < FIELDTYPE_TEAR_FROM) + return merge_type; + return FIELDTYPE_TEAR_FROM + (merge_type - FIELDTYPE_TEAR_TO) - 1; } @@ -926,31 +919,37 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]= } }; -/** - Return type of which can carry value of both given types in UNION result. - - @param a type for merging - @param b type for merging - - @return - type of field -*/ - -enum_field_types Field::field_type_merge(enum_field_types a, - enum_field_types b) -{ - return field_types_merge_rules[field_type2index(a)] - [field_type2index(b)]; -} const Type_handler * Type_handler::aggregate_for_result_traditional(const Type_handler *a, const Type_handler *b) { - enum_field_types ta= a->real_field_type(); - enum_field_types tb= b->real_field_type(); - return - Type_handler::get_handler_by_real_type(Field::field_type_merge(ta, tb)); + if (a == b) + { + /* + If two traditional handlers are equal, quickly return "a". + Some handlers (e.g. Type_handler_bool) pretend to be traditional, + but in fact they are not traditional in full extent, they are + only sub-types for now (and don't have a corresponding Field_xxx yet). + Here we preserve such handlers during aggregation. + As a result, COALESCE(true,true) preserves the "boolean" data type. + + Need to do this conversion for deprecated data types, + similar to what field_type_merge_rules[][] does. + */ + switch (a->field_type()) { + case MYSQL_TYPE_DECIMAL: return &type_handler_newdecimal; + case MYSQL_TYPE_DATE: return &type_handler_newdate; + case MYSQL_TYPE_VAR_STRING: return &type_handler_varchar; + default: break; + } + return a; + } + enum_field_types ta= a->traditional_merge_field_type(); + enum_field_types tb= b->traditional_merge_field_type(); + enum_field_types res= field_types_merge_rules[merge_type2index(ta)] + [merge_type2index(tb)]; + return Type_handler::get_handler_by_real_type(res); } @@ -1832,12 +1831,9 @@ int Field::store(const char *to, size_t length, CHARSET_INFO *cs, } -int Field::store_timestamp(my_time_t ts, ulong sec_part) +int Field::store_timestamp_dec(const timeval &ts, uint dec) { - MYSQL_TIME ltime; - THD *thd= get_thd(); - thd->timestamp_to_TIME(<ime, ts, sec_part, 0); - return store_time_dec(<ime, decimals()); + return store_time_dec(Datetime(get_thd(), ts).get_mysql_time(), dec); } /** @@ -1937,14 +1933,6 @@ Field::unpack(uchar* to, const uchar *from, const uchar *from_end, } -my_decimal *Field::val_decimal(my_decimal *decimal) -{ - /* This never have to be called */ - DBUG_ASSERT(0); - return 0; -} - - void Field_num::add_zerofill_and_unsigned(String &res) const { if (unsigned_flag) @@ -2076,17 +2064,16 @@ my_decimal* Field_int::val_decimal(my_decimal *decimal_value) } -bool Field_int::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) +bool Field_int::get_date(MYSQL_TIME *ltime,date_mode_t fuzzydate) { ASSERT_COLUMN_MARKED_FOR_READ; - longlong nr= val_int(); - bool neg= !(flags & UNSIGNED_FLAG) && nr < 0; - return int_to_datetime_with_warn(neg, neg ? -nr : nr, ltime, fuzzydate, - table->s, field_name.str); + Longlong_hybrid nr(val_int(), (flags & UNSIGNED_FLAG)); + return int_to_datetime_with_warn(get_thd(), nr, ltime, + fuzzydate, table->s, field_name.str); } -bool Field_vers_trx_id::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate, ulonglong trx_id) +bool Field_vers_trx_id::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate, ulonglong trx_id) { ASSERT_COLUMN_MARKED_FOR_READ; DBUG_ASSERT(ltime); @@ -2266,15 +2253,13 @@ uint Field::fill_cache_field(CACHE_FIELD *copy) } -bool Field::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) +bool Field::get_date(MYSQL_TIME *to, date_mode_t mode) { - char buff[40]; - String tmp(buff,sizeof(buff),&my_charset_bin),*res; - if (!(res=val_str(&tmp)) || - str_to_datetime_with_warn(res->charset(), res->ptr(), res->length(), - ltime, fuzzydate)) - return 1; - return 0; + StringBuffer<40> tmp; + Temporal::Warn_push warn(get_thd(), NULL, NullS, to, mode); + Temporal_hybrid *t= new(to) Temporal_hybrid(get_thd(), &warn, + val_str(&tmp), mode); + return !t->is_valid_temporal(); } /** @@ -2344,6 +2329,36 @@ Field *Field::new_key_field(MEM_ROOT *root, TABLE *new_table, } +/** + Create field for temporary table from given field. + + @param thd Thread handler + @param table Temporary table + @param maybe_null_arg If the result field should be NULL-able, + even if the original field is NOT NULL, e.g. for: + - OUTER JOIN fields + - WITH ROLLUP fields + - arguments of aggregate functions, e.g. SUM(column1) + @retval NULL, on error + @retval pointer to the new field created, on success. +*/ + +Field *Field::create_tmp_field(MEM_ROOT *mem_root, TABLE *new_table, + bool maybe_null_arg) +{ + Field *new_field; + + if ((new_field= make_new_field(mem_root, new_table, new_table == table))) + { + new_field->init_for_tmp_table(this, new_table); + new_field->flags|= flags & NO_DEFAULT_VALUE_FLAG; + if (maybe_null_arg) + new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join + } + return new_field; +} + + /* This is used to generate a field in TABLE from TABLE_SHARE */ Field *Field::clone(MEM_ROOT *root, TABLE *new_table) @@ -3149,7 +3164,7 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value, Otherwise sets maximal number that can be stored in the field. @param decimal_value my_decimal - @param [OUT] native_error the error returned by my_decimal2binary(). + @param [OUT] native_error the error returned by my_decimal::to_binary(). @retval 0 ok @@ -3187,8 +3202,8 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value, } #endif - *native_error= my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, - decimal_value, ptr, precision, dec); + *native_error= decimal_value->to_binary(ptr, precision, dec, + E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW); if (unlikely(*native_error == E_DEC_OVERFLOW)) { @@ -3196,7 +3211,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value, DBUG_PRINT("info", ("overflow")); set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1); set_value_on_overflow(&buff, decimal_value->sign()); - my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec); + buff.to_binary(ptr, precision, dec); error= 1; } DBUG_EXECUTE("info", print_decimal_buff(decimal_value, (uchar *) ptr, @@ -3361,37 +3376,6 @@ int Field_new_decimal::store_time_dec(const MYSQL_TIME *ltime, uint dec_arg) } -double Field_new_decimal::val_real(void) -{ - ASSERT_COLUMN_MARKED_FOR_READ; - double dbl; - my_decimal decimal_value; - my_decimal2double(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), &dbl); - return dbl; -} - - -longlong Field_new_decimal::val_int(void) -{ - ASSERT_COLUMN_MARKED_FOR_READ; - longlong i; - my_decimal decimal_value; - my_decimal2int(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), - unsigned_flag, &i); - return i; -} - - -ulonglong Field_new_decimal::val_uint(void) -{ - ASSERT_COLUMN_MARKED_FOR_READ; - longlong i; - my_decimal decimal_value; - my_decimal2int(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), true, &i); - return i; -} - - my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value) { ASSERT_COLUMN_MARKED_FOR_READ; @@ -3404,28 +3388,6 @@ my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value) } -String *Field_new_decimal::val_str(String *val_buffer, - String *val_ptr __attribute__((unused))) -{ - ASSERT_COLUMN_MARKED_FOR_READ; - my_decimal decimal_value; - uint fixed_precision= zerofill ? precision : 0; - my_decimal2string(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), - fixed_precision, dec, '0', val_buffer); - val_buffer->set_charset(&my_charset_numeric); - return val_buffer; -} - - -bool Field_new_decimal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) -{ - my_decimal value; - return decimal_to_datetime_with_warn(val_decimal(&value), - ltime, fuzzydate, table->s, - field_name.str); -} - - int Field_new_decimal::cmp(const uchar *a,const uchar*b) { return memcmp(a, b, bin_size); @@ -3580,8 +3542,8 @@ Item *Field_new_decimal::get_equal_const_item(THD *thd, const Context &ctx, if (const_item->field_type() != MYSQL_TYPE_NEWDECIMAL || const_item->decimal_scale() != decimals()) { - my_decimal *val, val_buffer, val_buffer2; - if (!(val= const_item->val_decimal(&val_buffer))) + VDec val(const_item); + if (val.is_null()) { DBUG_ASSERT(0); return const_item; @@ -3591,9 +3553,9 @@ Item *Field_new_decimal::get_equal_const_item(THD *thd, const Context &ctx, See comments about truncation in the same place in Field_time::get_equal_const_item(). */ - my_decimal_round(E_DEC_FATAL_ERROR, val, decimals(), true, &val_buffer2); - return new (thd->mem_root) Item_decimal(thd, field_name.str, - &val_buffer2, + my_decimal tmp; + val.round_to(&tmp, decimals(), TRUNCATE); + return new (thd->mem_root) Item_decimal(thd, field_name.str, &tmp, decimals(), field_length); } break; @@ -4833,13 +4795,6 @@ Converter_double_to_longlong::push_warning(THD *thd, } -int Field_real::store_decimal(const my_decimal *dm) -{ - double dbl; - my_decimal2double(E_DEC_FATAL_ERROR, dm, &dbl); - return store(dbl); -} - int Field_real::store_time_dec(const MYSQL_TIME *ltime, uint dec_arg) { return store(TIME_to_double(ltime)); @@ -4872,11 +4827,11 @@ my_decimal *Field_real::val_decimal(my_decimal *decimal_value) } -bool Field_real::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) +bool Field_real::get_date(MYSQL_TIME *ltime,date_mode_t fuzzydate) { ASSERT_COLUMN_MARKED_FOR_READ; double nr= val_real(); - return double_to_datetime_with_warn(nr, ltime, fuzzydate, + return double_to_datetime_with_warn(get_thd(), nr, ltime, fuzzydate, table->s, field_name.str); } @@ -5056,7 +5011,7 @@ int Field_timestamp::save_in_field(Field *to) { ulong sec_part; my_time_t ts= get_timestamp(&sec_part); - return to->store_timestamp(ts, sec_part); + return to->store_timestamp_dec(Timeval(ts, sec_part), decimals()); } my_time_t Field_timestamp::get_timestamp(const uchar *pos, @@ -5068,135 +5023,168 @@ my_time_t Field_timestamp::get_timestamp(const uchar *pos, } -int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time, - const ErrConv *str, - int was_cut, - bool have_smth_to_conv) +bool Field_timestamp::val_native(Native *to) +{ + ASSERT_COLUMN_MARKED_FOR_READ; + my_time_t sec= (my_time_t) sint4korr(ptr); + return Timestamp_or_zero_datetime(Timestamp(sec, 0), sec == 0). + to_native(to, 0); +} + + +int Field_timestamp::store_TIME_with_warning(THD *thd, const Datetime *dt, + const ErrConv *str, int was_cut) { ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; - uint error = 0; - my_time_t timestamp; + static const Timestamp zero(0, 0); - if (MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) || !have_smth_to_conv) - { - error= 1; - set_datetime_warning(WARN_DATA_TRUNCATED, - str, MYSQL_TIMESTAMP_DATETIME, 1); - } - else if (MYSQL_TIME_WARN_HAVE_NOTES(was_cut)) + // Handle totally bad values + if (!dt->is_valid_datetime()) { - error= 3; - set_datetime_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, - str, MYSQL_TIMESTAMP_DATETIME, 1); + set_datetime_warning(WARN_DATA_TRUNCATED, str, "datetime", 1); + store_TIMESTAMP(zero); + return 1; } - /* Only convert a correct date (not a zero date) */ - if (have_smth_to_conv && l_time->month) + + // Handle values that do not need DATETIME to TIMESTAMP conversion + if (!dt->get_mysql_time()->month) { - uint conversion_error; - timestamp= TIME_to_timestamp(thd, l_time, &conversion_error); - if (timestamp == 0 && l_time->second_part == 0) - conversion_error= ER_WARN_DATA_OUT_OF_RANGE; - if (unlikely(conversion_error)) - { - set_datetime_warning(conversion_error, - str, MYSQL_TIMESTAMP_DATETIME, !error); - error= 1; - } + /* + Zero date is allowed by the current sql_mode. Store zero timestamp. + Return success or a warning about non-fatal truncation, e.g.: + INSERT INTO t1 (ts) VALUES ('0000-00-00 00:00:00 some tail'); + */ + store_TIMESTAMP(zero); + return store_TIME_return_code_with_warnings(was_cut, str, "datetime"); } - else + + // Convert DATETIME to TIMESTAMP + uint conversion_error; + const MYSQL_TIME *l_time= dt->get_mysql_time(); + my_time_t timestamp= TIME_to_timestamp(thd, l_time, &conversion_error); + if (timestamp == 0 && l_time->second_part == 0) { - timestamp= 0; - l_time->second_part= 0; + set_datetime_warning(ER_WARN_DATA_OUT_OF_RANGE, str, "datetime", 1); + store_TIMESTAMP(zero); + return 1; // date was fine but pointed to a DST gap } - store_TIME(timestamp, l_time->second_part); - return error; -} + // Store the value + DBUG_ASSERT(!dt->fraction_remainder(decimals())); + store_TIMESTAMP(Timestamp(timestamp, l_time->second_part)); -static bool -copy_or_convert_to_datetime(THD *thd, const MYSQL_TIME *from, MYSQL_TIME *to) -{ - if (from->time_type == MYSQL_TIMESTAMP_TIME) - return time_to_datetime(thd, from, to); - *to= *from; - return false; + // Calculate return value and send warnings if needed + if (unlikely(conversion_error)) // e.g. DATETIME in the DST gap + { + set_datetime_warning(conversion_error, str, "datetime", 1); + return 1; + } + return store_TIME_return_code_with_warnings(was_cut, str, "datetime"); } -sql_mode_t Field_timestamp::sql_mode_for_timestamp(THD *thd) const +date_conv_mode_t Timestamp::sql_mode_for_timestamp(THD *thd) { // We don't want to store invalid or fuzzy datetime values in TIMESTAMP - return (thd->variables.sql_mode & MODE_NO_ZERO_DATE) | MODE_NO_ZERO_IN_DATE; + return date_conv_mode_t((thd->variables.sql_mode & MODE_NO_ZERO_DATE) | + MODE_NO_ZERO_IN_DATE); } int Field_timestamp::store_time_dec(const MYSQL_TIME *ltime, uint dec) { - int unused; + int warn; ErrConvTime str(ltime); THD *thd= get_thd(); - MYSQL_TIME l_time; - bool valid= !copy_or_convert_to_datetime(thd, ltime, &l_time) && - !check_date(&l_time, pack_time(&l_time) != 0, - sql_mode_for_timestamp(thd), &unused); - return store_TIME_with_warning(thd, &l_time, &str, false, valid); + Datetime dt(thd, &warn, ltime, Timestamp::DatetimeOptions(thd), decimals()); + return store_TIME_with_warning(thd, &dt, &str, warn); } int Field_timestamp::store(const char *from,size_t len,CHARSET_INFO *cs) { - MYSQL_TIME l_time; - MYSQL_TIME_STATUS status; - bool have_smth_to_conv; ErrConvString str(from, len, cs); THD *thd= get_thd(); - - have_smth_to_conv= !str_to_datetime(cs, from, len, &l_time, - sql_mode_for_timestamp(thd), &status); - return store_TIME_with_warning(thd, &l_time, &str, - status.warnings, have_smth_to_conv); + MYSQL_TIME_STATUS st; + Datetime dt(thd, &st, from, len, cs, Timestamp::DatetimeOptions(thd), decimals()); + return store_TIME_with_warning(thd, &dt, &str, st.warnings); } int Field_timestamp::store(double nr) { - MYSQL_TIME l_time; int error; ErrConvDouble str(nr); THD *thd= get_thd(); - - longlong tmp= double_to_datetime(nr, &l_time, sql_mode_for_timestamp(thd), - &error); - return store_TIME_with_warning(thd, &l_time, &str, error, tmp != -1); + Datetime dt(thd, &error, nr, Timestamp::DatetimeOptions(thd), decimals()); + return store_TIME_with_warning(thd, &dt, &str, error); } int Field_timestamp::store(longlong nr, bool unsigned_val) { - MYSQL_TIME l_time; int error; - ErrConvInteger str(nr, unsigned_val); + Longlong_hybrid tmp(nr, unsigned_val); + ErrConvInteger str(tmp); THD *thd= get_thd(); + Datetime dt(&error, tmp, Timestamp::DatetimeOptions(thd)); + return store_TIME_with_warning(thd, &dt, &str, error); +} + - longlong tmp= number_to_datetime(nr, 0, &l_time, sql_mode_for_timestamp(thd), - &error); - return store_TIME_with_warning(thd, &l_time, &str, error, tmp != -1); +int Field_timestamp::store_timestamp_dec(const timeval &ts, uint dec) +{ + int warn= 0; + time_round_mode_t mode= Datetime::default_round_mode(get_thd()); + store_TIMESTAMP(Timestamp(ts).round(decimals(), mode, &warn)); + if (warn) + { + /* + We're here if rounding would overflow outside of the supported TIMESTAMP + range, so truncation happened instead: + CREATE TABLE t1 (a TIMESTAMP(6)); + INSERT INTO t1 VALUES ('maximum-possible-timestamp.999999'); + ALTER TABLE t1 MODIFY a TIMESTAMP(5); + SELECT * FROM t1; --> 'maximum-possible-timestamp.99999' (5 digits) + Raise a warning, like DATETIME does for '9999-12-31 23:59:59.999999'. + */ + set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + } + if (ts.tv_sec == 0 && ts.tv_usec == 0 && + get_thd()->variables.sql_mode & (ulonglong) TIME_NO_ZERO_DATE) + return zero_time_stored_return_code_with_warning(); + return 0; } -int Field_timestamp::store_timestamp(my_time_t ts, ulong sec_part) +int Field_timestamp::zero_time_stored_return_code_with_warning() { - store_TIME(ts, sec_part); - if (ts == 0 && sec_part == 0 && - get_thd()->variables.sql_mode & TIME_NO_ZERO_DATE) + if (get_thd()->variables.sql_mode & (ulonglong) TIME_NO_ZERO_DATE) { ErrConvString s( STRING_WITH_LEN("0000-00-00 00:00:00.000000") - (decimals() ? 6 - decimals() : 7), system_charset_info); - set_datetime_warning(WARN_DATA_TRUNCATED, &s, MYSQL_TIMESTAMP_DATETIME, 1); + set_datetime_warning(WARN_DATA_TRUNCATED, &s, "datetime", 1); return 1; } return 0; + +} + + +int Field_timestamp::store_native(const Native &value) +{ + if (!value.length()) // Zero datetime + { + reset(); + return zero_time_stored_return_code_with_warning(); + } + /* + The exact second precision is not important here. + Field_timestamp*::store_timestamp_dec() do not use the "dec" parameter. + Passing TIME_SECOND_PART_DIGITS is OK. + */ + return store_timestamp_dec(Timestamp(value).tv(), TIME_SECOND_PART_DIGITS); } @@ -5209,7 +5197,7 @@ double Field_timestamp::val_real(void) longlong Field_timestamp::val_int(void) { MYSQL_TIME ltime; - if (get_date(<ime, TIME_NO_ZERO_DATE)) + if (get_date(<ime, Datetime::Options(TIME_NO_ZERO_DATE, get_thd()))) return 0; return ltime.year * 10000000000LL + ltime.month * 100000000LL + @@ -5229,7 +5217,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr) to= (char*) val_buffer->ptr(); val_buffer->length(field_length); - if (get_date(<ime, TIME_NO_ZERO_DATE)) + if (get_date(<ime, Datetime::Options(TIME_NO_ZERO_DATE, get_thd()))) { /* Zero time is "000000" */ val_ptr->set(zero_timestamp, field_length, &my_charset_numeric); return val_ptr; @@ -5297,11 +5285,11 @@ Field_timestamp::validate_value_in_record(THD *thd, const uchar *record) const DBUG_ASSERT(!is_null_in_record(record)); ulong sec_part; return !get_timestamp(ptr_in_record(record), &sec_part) && !sec_part && - (sql_mode_for_dates(thd) & TIME_NO_ZERO_DATE) != 0; + bool(sql_mode_for_dates(thd) & TIME_NO_ZERO_DATE) != false; } -bool Field_timestamp::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Field_timestamp::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { ulong sec_part; my_time_t ts= get_timestamp(&sec_part); @@ -5312,7 +5300,7 @@ bool Field_timestamp::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) bool Field_timestamp::send_binary(Protocol *protocol) { MYSQL_TIME ltime; - Field_timestamp::get_date(<ime, 0); + Field_timestamp::get_date(<ime, date_mode_t(0)); return protocol->store(<ime, 0); } @@ -5351,7 +5339,7 @@ void Field_timestamp::sql_type(String &res) const int Field_timestamp::set_time() { set_notnull(); - store_TIME(get_thd()->query_start(), 0); + store_TIMESTAMP(Timestamp(get_thd()->query_start(), 0)); return 0; } @@ -5442,10 +5430,10 @@ static longlong read_lowendian(const uchar *from, uint bytes) } } -void Field_timestamp_hires::store_TIME(my_time_t timestamp, ulong sec_part) +void Field_timestamp_hires::store_TIMEVAL(const timeval &tv) { - mi_int4store(ptr, timestamp); - store_bigendian(sec_part_shift(sec_part, dec), ptr+4, sec_part_bytes(dec)); + mi_int4store(ptr, tv.tv_sec); + store_bigendian(sec_part_shift(tv.tv_usec, dec), ptr+4, sec_part_bytes(dec)); } my_time_t Field_timestamp_hires::get_timestamp(const uchar *pos, @@ -5456,10 +5444,22 @@ my_time_t Field_timestamp_hires::get_timestamp(const uchar *pos, return mi_uint4korr(pos); } + +bool Field_timestamp_hires::val_native(Native *to) +{ + ASSERT_COLUMN_MARKED_FOR_READ; + struct timeval tm; + tm.tv_sec= mi_uint4korr(ptr); + tm.tv_usec= (ulong) sec_part_unshift(read_bigendian(ptr+4, sec_part_bytes(dec)), dec); + return Timestamp_or_zero_datetime(Timestamp(tm), tm.tv_sec == 0). + to_native(to, dec); +} + + double Field_timestamp_with_dec::val_real(void) { MYSQL_TIME ltime; - if (get_date(<ime, TIME_NO_ZERO_DATE)) + if (get_date(<ime, Datetime::Options(TIME_NO_ZERO_DATE, get_thd()))) return 0; return ltime.year * 1e10 + ltime.month * 1e8 + @@ -5470,29 +5470,17 @@ double Field_timestamp_with_dec::val_real(void) my_decimal *Field_timestamp_with_dec::val_decimal(my_decimal *d) { MYSQL_TIME ltime; - get_date(<ime, 0); + get_date(<ime, date_mode_t(0)); return TIME_to_my_decimal(<ime, d); } int Field_timestamp::store_decimal(const my_decimal *d) { - ulonglong nr; - ulong sec_part; int error; - MYSQL_TIME ltime; - longlong tmp; THD *thd= get_thd(); ErrConvDecimal str(d); - - if (my_decimal2seconds(d, &nr, &sec_part)) - { - tmp= -1; - error= 2; - } - else - tmp= number_to_datetime(nr, sec_part, <ime, sql_mode_for_timestamp(thd), - &error); - return store_TIME_with_warning(thd, <ime, &str, error, tmp != -1); + Datetime dt(thd, &error, d, Timestamp::DatetimeOptions(thd), decimals()); + return store_TIME_with_warning(thd, &dt, &str, error); } int Field_timestamp_with_dec::set_time() @@ -5500,14 +5488,15 @@ int Field_timestamp_with_dec::set_time() THD *thd= get_thd(); set_notnull(); // Avoid writing microseconds into binlog for FSP=0 - store_TIME(thd->query_start(), decimals() ? thd->query_start_sec_part() : 0); + ulong msec= decimals() ? thd->query_start_sec_part() : 0; + store_TIMESTAMP(Timestamp(thd->query_start(), msec).trunc(decimals())); return 0; } bool Field_timestamp_with_dec::send_binary(Protocol *protocol) { MYSQL_TIME ltime; - Field_timestamp::get_date(<ime, 0); + Field_timestamp::get_date(<ime, date_mode_t(0)); return protocol->store(<ime, dec); } @@ -5536,12 +5525,8 @@ void Field_timestamp_with_dec::make_send_field(Send_field *field) ** MySQL-5.6 compatible TIMESTAMP(N) **************************************************************/ -void Field_timestampf::store_TIME(my_time_t timestamp, ulong sec_part) +void Field_timestampf::store_TIMEVAL(const timeval &tm) { - struct timeval tm; - tm.tv_sec= timestamp; - tm.tv_usec= sec_part; - my_timeval_trunc(&tm, dec); my_timestamp_to_binary(&tm, ptr, dec); } @@ -5577,6 +5562,19 @@ my_time_t Field_timestampf::get_timestamp(const uchar *pos, } +bool Field_timestampf::val_native(Native *to) +{ + ASSERT_COLUMN_MARKED_FOR_READ; + // Check if it's '0000-00-00 00:00:00' rather than a real timestamp + if (ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) + { + to->length(0); + return false; + } + return Field::val_native(to); +} + + /*************************************************************/ uint Field_temporal::is_equal(Create_field *new_field) { @@ -5587,7 +5585,7 @@ uint Field_temporal::is_equal(Create_field *new_field) void Field_temporal::set_warnings(Sql_condition::enum_warning_level trunc_level, const ErrConv *str, int was_cut, - timestamp_type ts_type) + const char *typestr) { /* error code logic: @@ -5600,9 +5598,9 @@ void Field_temporal::set_warnings(Sql_condition::enum_warning_level trunc_level, a DATE field and non-zero time part is thrown away. */ if (was_cut & MYSQL_TIME_WARN_TRUNCATED) - set_datetime_warning(trunc_level, WARN_DATA_TRUNCATED, str, ts_type, 1); + set_datetime_warning(trunc_level, WARN_DATA_TRUNCATED, str, typestr, 1); if (was_cut & MYSQL_TIME_WARN_OUT_OF_RANGE) - set_datetime_warning(ER_WARN_DATA_OUT_OF_RANGE, str, ts_type, 1); + set_datetime_warning(ER_WARN_DATA_OUT_OF_RANGE, str, typestr, 1); } @@ -5616,107 +5614,68 @@ void Field_temporal::set_warnings(Sql_condition::enum_warning_level trunc_level, 3 Datetime value that was cut (warning level NOTE) This is used by opt_range.cc:get_mm_leaf(). */ -int Field_temporal_with_date::store_TIME_with_warning(MYSQL_TIME *ltime, - const ErrConv *str, - int was_cut, - int have_smth_to_conv) +int Field_datetime::store_TIME_with_warning(const Datetime *dt, + const ErrConv *str, + int was_cut) { - Sql_condition::enum_warning_level trunc_level= Sql_condition::WARN_LEVEL_WARN; - int ret= 2; - ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; - - if (was_cut == 0 && have_smth_to_conv == 0) // special case: zero date - { - was_cut= MYSQL_TIME_WARN_OUT_OF_RANGE; - } - else if (!have_smth_to_conv) - { - bzero(ltime, sizeof(*ltime)); - was_cut= MYSQL_TIME_WARN_TRUNCATED; - ret= 1; - } - else if (!MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) && - (MYSQL_TIME_WARN_HAVE_NOTES(was_cut) || - (type_handler()->mysql_timestamp_type() == MYSQL_TIMESTAMP_DATE && - (ltime->hour || ltime->minute || ltime->second || ltime->second_part)))) - { - trunc_level= Sql_condition::WARN_LEVEL_NOTE; - was_cut|= MYSQL_TIME_WARN_TRUNCATED; - ret= 3; - } - set_warnings(trunc_level, str, was_cut, - type_handler()->mysql_timestamp_type()); - store_TIME(ltime); - return was_cut ? ret : 0; + // Handle totally bad values + if (!dt->is_valid_datetime()) + return store_invalid_with_warning(str, was_cut, "datetime"); + // Store the value + DBUG_ASSERT(!dt->fraction_remainder(decimals())); + store_datetime(*dt); + // Caclulate return value and send warnings if needed + return store_TIME_return_code_with_warnings(was_cut, str, "datetime"); } -int Field_temporal_with_date::store(const char *from, size_t len, CHARSET_INFO *cs) +int Field_datetime::store(const char *from, size_t len, CHARSET_INFO *cs) { - MYSQL_TIME ltime; - MYSQL_TIME_STATUS status; - THD *thd= get_thd(); + MYSQL_TIME_STATUS st; ErrConvString str(from, len, cs); - bool func_res= !str_to_datetime(cs, from, len, <ime, - sql_mode_for_dates(thd), - &status); - return store_TIME_with_warning(<ime, &str, status.warnings, func_res); + THD *thd= get_thd(); + Datetime dt(thd, &st, from, len, cs, Datetime::Options(thd), decimals()); + return store_TIME_with_warning(&dt, &str, st.warnings); } - -int Field_temporal_with_date::store(double nr) +int Field_datetime::store(double nr) { - int error= 0; - MYSQL_TIME ltime; - THD *thd= get_thd(); + int error; ErrConvDouble str(nr); - - longlong tmp= double_to_datetime(nr, <ime, - (uint) sql_mode_for_dates(thd), &error); - return store_TIME_with_warning(<ime, &str, error, tmp != -1); + THD *thd= get_thd(); + Datetime dt(thd, &error, nr, Datetime::Options(thd), decimals()); + return store_TIME_with_warning(&dt, &str, error); } -int Field_temporal_with_date::store(longlong nr, bool unsigned_val) +int Field_datetime::store(longlong nr, bool unsigned_val) { int error; - MYSQL_TIME ltime; - longlong tmp; + Longlong_hybrid tmp(nr, unsigned_val); + ErrConvInteger str(tmp); THD *thd= get_thd(); - ErrConvInteger str(nr, unsigned_val); - - tmp= number_to_datetime(nr, 0, <ime, sql_mode_for_dates(thd), &error); - - return store_TIME_with_warning(<ime, &str, error, tmp != -1); + Datetime dt(&error, tmp, Datetime::Options(thd)); + return store_TIME_with_warning(&dt, &str, error); } - -int Field_temporal_with_date::store_time_dec(const MYSQL_TIME *ltime, uint dec) +int Field_datetime::store_time_dec(const MYSQL_TIME *ltime, uint dec) { - int error= 0, have_smth_to_conv= 1; + int error; ErrConvTime str(ltime); - MYSQL_TIME l_time; + THD *thd= get_thd(); + Datetime dt(thd, &error, ltime, Datetime::Options(thd), decimals()); + return store_TIME_with_warning(&dt, &str, error); +} - if (copy_or_convert_to_datetime(get_thd(), ltime, &l_time)) - { - /* - Set have_smth_to_conv and error in a way to have - store_TIME_with_warning do bzero(). - */ - have_smth_to_conv= false; - error= MYSQL_TIME_WARN_OUT_OF_RANGE; - } - else - { - /* - We don't perform range checking here since values stored in TIME - structure always fit into DATETIME range. - */ - have_smth_to_conv= !check_date(&l_time, pack_time(&l_time) != 0, - sql_mode_for_dates(get_thd()), &error); - } - return store_TIME_with_warning(&l_time, &str, error, have_smth_to_conv); + +int Field_datetime::store_decimal(const my_decimal *d) +{ + int error; + ErrConvDecimal str(d); + THD *thd= get_thd(); + Datetime tm(thd, &error, d, Datetime::Options(thd), decimals()); + return store_TIME_with_warning(&tm, &str, error); } @@ -5726,14 +5685,14 @@ Field_temporal_with_date::validate_value_in_record(THD *thd, { DBUG_ASSERT(!is_null_in_record(record)); MYSQL_TIME ltime; - return get_TIME(<ime, ptr_in_record(record), sql_mode_for_dates(thd)); + return get_TIME(<ime, ptr_in_record(record), Datetime::Options(thd)); } my_decimal *Field_temporal::val_decimal(my_decimal *d) { MYSQL_TIME ltime; - if (get_date(<ime, 0)) + if (get_date(<ime, date_mode_t(0))) { bzero(<ime, sizeof(ltime)); ltime.time_type= type_handler()->mysql_timestamp_type(); @@ -5766,7 +5725,8 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd, const_item->field_type() != MYSQL_TYPE_TIMESTAMP) || const_item->decimals != decimals()) { - Datetime dt(thd, const_item, 0); + Datetime::Options opt(TIME_CONV_NONE, thd); + Datetime dt(thd, const_item, opt, decimals()); if (!dt.is_valid_datetime()) return NULL; /* @@ -5781,7 +5741,7 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd, case ANY_SUBST: if (!is_temporal_type_with_date(const_item->field_type())) { - Datetime dt(thd, const_item, TIME_FUZZY_DATES | TIME_INVALID_DATES); + Datetime dt(thd, const_item, Datetime::Options_cmp(thd)); if (!dt.is_valid_datetime()) return NULL; return new (thd->mem_root) @@ -5802,36 +5762,18 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd, ** In number context: HHMMSS ** Stored as a 3 byte unsigned int ****************************************************************************/ -int Field_time::store_TIME_with_warning(MYSQL_TIME *ltime, - const ErrConv *str, - int was_cut, - int have_smth_to_conv) +int Field_time::store_TIME_with_warning(const Time *t, + const ErrConv *str, int warn) { ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; - - if (!have_smth_to_conv) - { - bzero(ltime, sizeof(*ltime)); - store_TIME(ltime); - set_warnings(Sql_condition::WARN_LEVEL_WARN, str, MYSQL_TIME_WARN_TRUNCATED); - return 1; - } - if (ltime->year != 0 || ltime->month != 0) - { - ltime->year= ltime->month= ltime->day= 0; - was_cut|= MYSQL_TIME_NOTE_TRUNCATED; - } - my_time_trunc(ltime, decimals()); - store_TIME(ltime); - if (!MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) && - MYSQL_TIME_WARN_HAVE_NOTES(was_cut)) - { - set_warnings(Sql_condition::WARN_LEVEL_NOTE, str, - was_cut | MYSQL_TIME_WARN_TRUNCATED); - return 3; - } - set_warnings(Sql_condition::WARN_LEVEL_WARN, str, was_cut); - return was_cut ? 2 : 0; + // Handle totally bad values + if (!t->is_valid_time()) + return store_invalid_with_warning(str, warn, "time"); + // Store the value + DBUG_ASSERT(!t->fraction_remainder(decimals())); + store_TIME(*t); + // Calculate return value and send warnings if needed + return store_TIME_return_code_with_warnings(warn, str, "time"); } @@ -5848,88 +5790,56 @@ void Field_time::store_TIME(const MYSQL_TIME *ltime) int Field_time::store(const char *from,size_t len,CHARSET_INFO *cs) { - MYSQL_TIME ltime; - MYSQL_TIME_STATUS status; ErrConvString str(from, len, cs); - bool have_smth_to_conv= - !str_to_time(cs, from, len, <ime, sql_mode_for_dates(get_thd()), - &status); - - return store_TIME_with_warning(<ime, &str, - status.warnings, have_smth_to_conv); -} - - -/** - subtract a given number of days from DATETIME, return TIME - - optimized version of calc_time_diff() - - @note it might generate TIME values outside of the valid TIME range! -*/ -static void calc_datetime_days_diff(MYSQL_TIME *ltime, long days) -{ - long daydiff= calc_daynr(ltime->year, ltime->month, ltime->day) - days; - ltime->year= ltime->month= 0; - if (daydiff >=0 ) - { - ltime->day= daydiff; - ltime->time_type= MYSQL_TIMESTAMP_TIME; - } - else - { - longlong timediff= ((((daydiff * 24LL + - ltime->hour) * 60LL + - ltime->minute) * 60LL + - ltime->second) * 1000000LL + - ltime->second_part); - unpack_time(timediff, ltime, MYSQL_TIMESTAMP_TIME); - } + MYSQL_TIME_STATUS st; + THD *thd= get_thd(); + /* + Unlike number-to-time conversion, we need to additionally pass + MODE_NO_ZERO_DATE here (if it presents in the current sql_mode): + SET sql_mode='STRICT_ALL_TABLES,NO_ZERO_DATE'; + INSERT INTO t1 VALUES ('0000-00-00 00:00:00'); -- error + INSERT INTO t1 VALUES (0); -- ok + In the first INSERT we have a zero date. + In the second INSERT we don't have a zero date (it is just a zero time). + */ + Time::Options opt(sql_mode_for_dates(thd), thd); + Time tm(thd, &st, from, len, cs, opt, decimals()); + return store_TIME_with_warning(&tm, &str, st.warnings); } int Field_time::store_time_dec(const MYSQL_TIME *ltime, uint dec) { - MYSQL_TIME l_time= *ltime; ErrConvTime str(ltime); - int was_cut= 0; - - if (curdays && l_time.time_type != MYSQL_TIMESTAMP_TIME) - calc_datetime_days_diff(&l_time, curdays); - - int have_smth_to_conv= !check_time_range(&l_time, decimals(), &was_cut); - return store_TIME_with_warning(&l_time, &str, was_cut, have_smth_to_conv); + int warn; + Time tm(&warn, ltime, curdays, Time::Options(get_thd()), decimals()); + return store_TIME_with_warning(&tm, &str, warn); } int Field_time::store(double nr) { - MYSQL_TIME ltime; ErrConvDouble str(nr); int was_cut; - bool neg= nr < 0; - if (neg) - nr= -nr; - int have_smth_to_conv= !number_to_time(neg, (ulonglong) nr, - (ulong)((nr - floor(nr)) * TIME_SECOND_PART_FACTOR), - <ime, &was_cut); - - return store_TIME_with_warning(<ime, &str, was_cut, have_smth_to_conv); + Time tm(get_thd(), &was_cut, nr, Time::Options(get_thd()), decimals()); + return store_TIME_with_warning(&tm, &str, was_cut); } int Field_time::store(longlong nr, bool unsigned_val) { - MYSQL_TIME ltime; - ErrConvInteger str(nr, unsigned_val); + Longlong_hybrid tmp(nr, unsigned_val); + ErrConvInteger str(tmp); int was_cut; - if (nr < 0 && unsigned_val) - nr= 99991231235959LL + 1; - int have_smth_to_conv= !number_to_time(nr < 0, - (ulonglong) (nr < 0 ? -nr : nr), - 0, <ime, &was_cut); - - return store_TIME_with_warning(<ime, &str, was_cut, have_smth_to_conv); + THD *thd= get_thd(); + /* + Need fractional digit truncation if nr overflows to '838:59:59.999999'. + The constructor used below will always truncate (never round). + We don't need to care to overwrite the default session rounding mode + from HALF_UP to TRUNCATE. + */ + Time tm(thd, &was_cut, tmp, Time::Options(thd), decimals()); + return store_TIME_with_warning(&tm, &str, was_cut); } @@ -5980,7 +5890,7 @@ String *Field_time::val_str(String *str, { ASSERT_COLUMN_MARKED_FOR_READ; MYSQL_TIME ltime; - get_date(<ime, TIME_TIME_ONLY); + get_date(<ime, Datetime::Options(TIME_TIME_ONLY, get_thd())); str->alloc(field_length + 1); str->length(my_time_to_str(<ime, const_cast<char*>(str->ptr()), decimals())); str->set_charset(&my_charset_numeric); @@ -5988,9 +5898,10 @@ String *Field_time::val_str(String *str, } -bool Field_time::check_zero_in_date_with_warn(ulonglong fuzzydate) +bool Field_time::check_zero_in_date_with_warn(date_mode_t fuzzydate) { - if (!(fuzzydate & TIME_TIME_ONLY) && (fuzzydate & TIME_NO_ZERO_IN_DATE)) + date_conv_mode_t tmp= date_conv_mode_t(fuzzydate); + if (!(tmp & TIME_TIME_ONLY) && (tmp & TIME_NO_ZERO_IN_DATE)) { THD *thd= get_thd(); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -6010,7 +5921,7 @@ bool Field_time::check_zero_in_date_with_warn(ulonglong fuzzydate) DATE_FORMAT(time, "%l.%i %p") */ -bool Field_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Field_time::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { if (check_zero_in_date_with_warn(fuzzydate)) return true; @@ -6035,7 +5946,7 @@ bool Field_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) bool Field_time::send_binary(Protocol *protocol) { MYSQL_TIME ltime; - get_date(<ime, TIME_TIME_ONLY); + get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd())); return protocol->store_time(<ime, decimals()); } @@ -6084,16 +5995,10 @@ void Field_time_hires::store_TIME(const MYSQL_TIME *ltime) int Field_time::store_decimal(const my_decimal *d) { - ulonglong nr; - ulong sec_part; ErrConvDecimal str(d); - MYSQL_TIME ltime; int was_cut; - bool neg= my_decimal2seconds(d, &nr, &sec_part); - - int have_smth_to_conv= !number_to_time(neg, nr, sec_part, <ime, &was_cut); - - return store_TIME_with_warning(<ime, &str, was_cut, have_smth_to_conv); + Time tm(get_thd(), &was_cut, d, Time::Options(get_thd()), decimals()); + return store_TIME_with_warning(&tm, &str, was_cut); } @@ -6133,14 +6038,27 @@ bool Field_time::can_be_substituted_to_equal_item(const Context &ctx, Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx, Item *const_item) { + /* + Old mode conversion from DATETIME with non-zero YYYYMMDD part + to TIME works very inconsistently. Possible variants: + - truncate the YYYYMMDD part + - add (MM*33+DD)*24 to hours + - add (MM*31+DD)*24 to hours + Let's disallow propagation of DATETIME with non-zero YYYYMMDD + as an equal constant for a TIME field. + */ + Time::datetime_to_time_mode_t mode= + (thd->variables.old_behavior & OLD_MODE_ZERO_DATE_TIME_CAST) ? + Time::DATETIME_TO_TIME_YYYYMMDD_00000000_ONLY : + Time::DATETIME_TO_TIME_MINUS_CURRENT_DATE; + switch (ctx.subst_constraint()) { case ANY_SUBST: if (const_item->field_type() != MYSQL_TYPE_TIME) { - MYSQL_TIME ltime; // Get the value of const_item with conversion from DATETIME to TIME - ulonglong fuzzydate= Time::comparison_flags_for_get_date(); - if (const_item->get_time_with_conversion(thd, <ime, fuzzydate)) + Time tm(get_thd(), const_item, Time::Options_cmp(thd, mode)); + if (!tm.is_valid_time()) return NULL; /* Replace a DATE/DATETIME constant to a TIME constant: @@ -6152,8 +6070,9 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx, (assuming CURRENT_DATE is '2015-08-30' */ - return new (thd->mem_root) Item_time_literal(thd, <ime, - ltime.second_part ? + return new (thd->mem_root) Item_time_literal(thd, tm.get_mysql_time(), + tm.get_mysql_time()-> + second_part ? TIME_SECOND_PART_DIGITS : 0); } @@ -6162,9 +6081,6 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx, if (const_item->field_type() != MYSQL_TYPE_TIME || const_item->decimals != decimals()) { - MYSQL_TIME ltime; - if (const_item->get_time_with_conversion(thd, <ime, TIME_TIME_ONLY)) - return NULL; /* Note, the value returned in "ltime" can have more fractional digits that decimals(). The Item_time_literal constructor will @@ -6179,7 +6095,12 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx, The optimized WHERE will return with "Impossible WHERE", without having to do the full table scan. */ - return new (thd->mem_root) Item_time_literal(thd, <ime, decimals()); + Time tm(thd, const_item, Time::Options(TIME_TIME_ONLY, thd, mode), + decimals()); + if (!tm.is_valid_time()) + return NULL; + return new (thd->mem_root) Item_time_literal(thd, tm.get_mysql_time(), + decimals()); } break; } @@ -6191,7 +6112,7 @@ longlong Field_time_with_dec::val_int(void) { ASSERT_COLUMN_MARKED_FOR_READ; MYSQL_TIME ltime; - get_date(<ime, TIME_TIME_ONLY); + get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd())); longlong val= TIME_to_ulonglong_time(<ime); return ltime.neg ? -val : val; } @@ -6200,11 +6121,11 @@ double Field_time_with_dec::val_real(void) { ASSERT_COLUMN_MARKED_FOR_READ; MYSQL_TIME ltime; - get_date(<ime, TIME_TIME_ONLY); + get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd())); return TIME_to_double(<ime); } -bool Field_time_hires::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Field_time_hires::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { if (check_zero_in_date_with_warn(fuzzydate)) return true; @@ -6256,7 +6177,7 @@ void Field_timef::store_TIME(const MYSQL_TIME *ltime) my_time_packed_to_binary(tmp, ptr, dec); } -bool Field_timef::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Field_timef::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { if (check_zero_in_date_with_warn(fuzzydate)) return true; @@ -6346,7 +6267,8 @@ int Field_year::store_time_dec(const MYSQL_TIME *ltime, uint dec_arg) if (Field_year::store(ltime->year, 0)) return 1; - set_datetime_warning(WARN_DATA_TRUNCATED, &str, ltime->time_type, 1); + const char *typestr= Temporal::type_name_by_timestamp_type(ltime->time_type); + set_datetime_warning(WARN_DATA_TRUNCATED, &str, typestr, 1); return 0; } @@ -6390,12 +6312,13 @@ String *Field_year::val_str(String *val_buffer, } -bool Field_year::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) +bool Field_year::get_date(MYSQL_TIME *ltime,date_mode_t fuzzydate) { int tmp= (int) ptr[0]; if (tmp || field_length != 4) tmp+= 1900; - return int_to_datetime_with_warn(false, tmp * 10000, + return int_to_datetime_with_warn(get_thd(), + Longlong_hybrid(tmp * 10000, true), ltime, fuzzydate, table->s, field_name.str); } @@ -6408,6 +6331,71 @@ void Field_year::sql_type(String &res) const } +/*****************************************************************************/ + +int Field_date_common::store_TIME_with_warning(const Datetime *dt, + const ErrConv *str, + int was_cut) +{ + ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; + // Handle totally bad values + if (!dt->is_valid_datetime()) + return store_invalid_with_warning(str, was_cut, "date"); + // Store the value + if (!dt->hhmmssff_is_zero()) + was_cut|= MYSQL_TIME_NOTE_TRUNCATED; + store_datetime(*dt); + // Caclulate return value and send warnings if needed + return store_TIME_return_code_with_warnings(was_cut, str, "date"); +} + +int Field_date_common::store(const char *from, size_t len, CHARSET_INFO *cs) +{ + MYSQL_TIME_STATUS st; + ErrConvString str(from, len, cs); + THD *thd= get_thd(); + Datetime dt(thd, &st, from, len, cs, Date::Options(thd), 0); + return store_TIME_with_warning(&dt, &str, st.warnings); +} + +int Field_date_common::store(double nr) +{ + int error; + ErrConvDouble str(nr); + THD *thd= get_thd(); + Datetime dt(thd, &error, nr, Date::Options(thd), 0); + return store_TIME_with_warning(&dt, &str, error); +} + +int Field_date_common::store(longlong nr, bool unsigned_val) +{ + int error; + Longlong_hybrid tmp(nr, unsigned_val); + ErrConvInteger str(tmp); + THD *thd= get_thd(); + Datetime dt(&error, tmp, Date::Options(thd)); + return store_TIME_with_warning(&dt, &str, error); +} + +int Field_date_common::store_time_dec(const MYSQL_TIME *ltime, uint dec) +{ + int error; + ErrConvTime str(ltime); + THD *thd= get_thd(); + Datetime dt(thd, &error, ltime, Date::Options(thd), 0); + return store_TIME_with_warning(&dt, &str, error); +} + +int Field_date_common::store_decimal(const my_decimal *d) +{ + int error; + ErrConvDecimal str(d); + THD *thd= get_thd(); + Datetime tm(thd, &error, d, Date::Options(thd), 0); + return store_TIME_with_warning(&tm, &str, error); +} + + /**************************************************************************** ** date type ** In string context: YYYY-MM-DD @@ -6415,7 +6403,7 @@ void Field_year::sql_type(String &res) const ** Stored as a 4 byte unsigned int ****************************************************************************/ -void Field_date::store_TIME(MYSQL_TIME *ltime) +void Field_date::store_TIME(const MYSQL_TIME *ltime) { uint tmp= ltime->year*10000L + ltime->month*100+ltime->day; int4store(ptr,tmp); @@ -6451,7 +6439,7 @@ longlong Field_date::val_int(void) bool Field_date::get_TIME(MYSQL_TIME *ltime, const uchar *pos, - ulonglong fuzzydate) const + date_mode_t fuzzydate) const { ASSERT_COLUMN_MARKED_FOR_READ; int32 tmp= sint4korr(pos); @@ -6468,7 +6456,7 @@ String *Field_date::val_str(String *val_buffer, String *val_ptr __attribute__((unused))) { MYSQL_TIME ltime; - get_TIME(<ime, ptr, 0); + get_TIME(<ime, ptr, date_mode_t(0)); val_buffer->alloc(MAX_DATE_STRING_REP_LENGTH); uint length= (uint) my_date_to_str(<ime, const_cast<char*>(val_buffer->ptr())); @@ -6508,7 +6496,7 @@ void Field_date::sql_type(String &res) const ** In number context: YYYYMMDD ****************************************************************************/ -void Field_newdate::store_TIME(MYSQL_TIME *ltime) +void Field_newdate::store_TIME(const MYSQL_TIME *ltime) { uint tmp= ltime->year*16*32 + ltime->month*32+ltime->day; int3store(ptr,tmp); @@ -6518,7 +6506,7 @@ void Field_newdate::store_TIME(MYSQL_TIME *ltime) bool Field_newdate::send_binary(Protocol *protocol) { MYSQL_TIME tm; - Field_newdate::get_date(&tm,0); + Field_newdate::get_date(&tm, date_mode_t(0)); return protocol->store_date(&tm); } @@ -6570,7 +6558,7 @@ String *Field_newdate::val_str(String *val_buffer, bool Field_newdate::get_TIME(MYSQL_TIME *ltime, const uchar *pos, - ulonglong fuzzydate) const + date_mode_t fuzzydate) const { ASSERT_COLUMN_MARKED_FOR_READ; uint32 tmp=(uint32) uint3korr(pos); @@ -6613,8 +6601,14 @@ Item *Field_newdate::get_equal_const_item(THD *thd, const Context &ctx, case ANY_SUBST: if (!is_temporal_type_with_date(const_item->field_type())) { - // Get the value of const_item with conversion from TIME to DATETIME - Datetime dt(thd, const_item, TIME_FUZZY_DATES | TIME_INVALID_DATES); + /* + DATE is compared to DATETIME-alike non-temporal values + (such as VARCHAR, DECIMAL) as DATETIME, e.g.: + WHERE date_column=20010101235959.0000009 + So here we convert the constant to DATETIME normally. + In case if TIME_ROUND_FRACTIONAL is enabled, nanoseconds will round. + */ + Datetime dt(thd, const_item, Datetime::Options_cmp(thd)); if (!dt.is_valid_datetime()) return NULL; /* @@ -6641,10 +6635,17 @@ Item *Field_newdate::get_equal_const_item(THD *thd, const Context &ctx, case IDENTITY_SUBST: if (const_item->field_type() != MYSQL_TYPE_DATE) { - Date d(thd, const_item, 0); - if (!d.is_valid_date()) + /* + DATE is compared to non-temporal as DATETIME. + We need to convert to DATETIME first, taking into account the + current session rounding mode (even though this is IDENTITY_SUBSTS!), + then convert the result to DATE. + */ + Datetime dt(thd, const_item, Datetime::Options(TIME_CONV_NONE, thd)); + if (!dt.is_valid_datetime()) return NULL; - return new (thd->mem_root) Item_date_literal(thd, d.get_mysql_time()); + return new (thd->mem_root) + Item_date_literal(thd, Date(&dt).get_mysql_time()); } break; } @@ -6659,7 +6660,7 @@ Item *Field_newdate::get_equal_const_item(THD *thd, const Context &ctx, ** Stored as a 8 byte unsigned int. Should sometimes be change to a 6 byte int. ****************************************************************************/ -void Field_datetime::store_TIME(MYSQL_TIME *ltime) +void Field_datetime::store_TIME(const MYSQL_TIME *ltime) { ulonglong tmp= TIME_to_ulonglong_datetime(ltime); int8store(ptr,tmp); @@ -6668,7 +6669,7 @@ void Field_datetime::store_TIME(MYSQL_TIME *ltime) bool Field_datetime::send_binary(Protocol *protocol) { MYSQL_TIME tm; - Field_datetime::get_date(&tm, 0); + Field_datetime::get_date(&tm, date_mode_t(0)); return protocol->store(&tm, 0); } @@ -6734,7 +6735,7 @@ String *Field_datetime::val_str(String *val_buffer, } bool Field_datetime::get_TIME(MYSQL_TIME *ltime, const uchar *pos, - ulonglong fuzzydate) const + date_mode_t fuzzydate) const { ASSERT_COLUMN_MARKED_FOR_READ; longlong tmp= sint8korr(pos); @@ -6793,48 +6794,23 @@ void Field_datetime::sql_type(String &res) const int Field_datetime::set_time() { THD *thd= table->in_use; - MYSQL_TIME now_time; - thd->variables.time_zone->gmt_sec_to_TIME(&now_time, thd->query_start()); - now_time.second_part= thd->query_start_sec_part(); set_notnull(); - store_TIME(&now_time); - thd->time_zone_used= 1; + // Here we always truncate (not round), no matter what sql_mode is + store_datetime(Datetime(thd, thd->query_start_timeval()).trunc(decimals())); return 0; } -void Field_datetime_hires::store_TIME(MYSQL_TIME *ltime) +void Field_datetime_hires::store_TIME(const MYSQL_TIME *ltime) { ulonglong packed= sec_part_shift(pack_time(ltime), dec); store_bigendian(packed, ptr, Field_datetime_hires::pack_length()); } -int Field_temporal_with_date::store_decimal(const my_decimal *d) -{ - ulonglong nr; - ulong sec_part; - int error; - MYSQL_TIME ltime; - longlong tmp; - THD *thd= get_thd(); - ErrConvDecimal str(d); - - if (my_decimal2seconds(d, &nr, &sec_part)) - { - tmp= -1; - error= 2; - } - else - tmp= number_to_datetime(nr, sec_part, <ime, sql_mode_for_dates(thd), - &error); - - return store_TIME_with_warning(<ime, &str, error, tmp != -1); -} - bool Field_datetime_with_dec::send_binary(Protocol *protocol) { MYSQL_TIME ltime; - get_date(<ime, 0); + get_date(<ime, date_mode_t(0)); return protocol->store(<ime, dec); } @@ -6842,14 +6818,14 @@ bool Field_datetime_with_dec::send_binary(Protocol *protocol) double Field_datetime_with_dec::val_real(void) { MYSQL_TIME ltime; - get_date(<ime, 0); + get_date(<ime, date_mode_t(0)); return TIME_to_double(<ime); } longlong Field_datetime_with_dec::val_int(void) { MYSQL_TIME ltime; - get_date(<ime, 0); + get_date(<ime, date_mode_t(0)); return TIME_to_ulonglong_datetime(<ime); } @@ -6858,7 +6834,7 @@ String *Field_datetime_with_dec::val_str(String *str, String *unused __attribute__((unused))) { MYSQL_TIME ltime; - get_date(<ime, 0); + get_date(<ime, date_mode_t(0)); str->alloc(field_length+1); str->length(field_length); my_datetime_to_str(<ime, (char*) str->ptr(), dec); @@ -6868,7 +6844,7 @@ String *Field_datetime_with_dec::val_str(String *str, bool Field_datetime_hires::get_TIME(MYSQL_TIME *ltime, const uchar *pos, - ulonglong fuzzydate) const + date_mode_t fuzzydate) const { ASSERT_COLUMN_MARKED_FOR_READ; ulonglong packed= read_bigendian(pos, Field_datetime_hires::pack_length()); @@ -6901,15 +6877,14 @@ int Field_datetimef::reset() return 0; } -void Field_datetimef::store_TIME(MYSQL_TIME *ltime) +void Field_datetimef::store_TIME(const MYSQL_TIME *ltime) { - my_time_trunc(ltime, decimals()); longlong tmp= TIME_to_longlong_datetime_packed(ltime); my_datetime_packed_to_binary(tmp, ptr, dec); } bool Field_datetimef::get_TIME(MYSQL_TIME *ltime, const uchar *pos, - ulonglong fuzzydate) const + date_mode_t fuzzydate) const { ASSERT_COLUMN_MARKED_FOR_READ; longlong tmp= my_datetime_packed_from_binary(pos, dec); @@ -7096,9 +7071,8 @@ uint Field_str::is_equal(Create_field *new_field) int Field_longstr::store_decimal(const my_decimal *d) { - char buff[DECIMAL_MAX_STR_LENGTH+1]; - String str(buff, sizeof(buff), &my_charset_numeric); - my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str); + StringBuffer<DECIMAL_MAX_STR_LENGTH+1> str; + d->to_string(&str); return store(str.ptr(), str.length(), str.charset()); } @@ -7315,11 +7289,12 @@ void Field_string::sql_type(String &res) const size_t length; length= cs->cset->snprintf(cs,(char*) res.ptr(), - res.alloced_length(), "%s(%d)", + res.alloced_length(), "%s(%d)%s", (type() == MYSQL_TYPE_VAR_STRING ? (has_charset() ? "varchar" : "varbinary") : (has_charset() ? "char" : "binary")), - (int) field_length / charset()->mbmaxlen); + (int) field_length / charset()->mbmaxlen, + type() == MYSQL_TYPE_VAR_STRING ? "/*old*/" : ""); res.length(length); if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) && has_charset() && (charset()->state & MY_CS_BINSORT)) @@ -10593,322 +10568,90 @@ uint pack_length_to_packflag(uint type) } -Field *make_field(TABLE_SHARE *share, - MEM_ROOT *mem_root, - uchar *ptr, uint32 field_length, - uchar *null_pos, uchar null_bit, - uint pack_flag, - const Type_handler *handler, - CHARSET_INFO *field_charset, - Field::geometry_type geom_type, uint srid, - Field::utype unireg_check, - TYPELIB *interval, - const LEX_CSTRING *field_name, - uint32 flags) +uint Column_definition_attributes::pack_flag_to_pack_length() const { - uchar *UNINIT_VAR(bit_ptr); - uchar UNINIT_VAR(bit_offset); + uint type= f_packtype(pack_flag); // 0..15 + DBUG_ASSERT(type < 16); + switch (type) { + case MYSQL_TYPE_TINY: return 1; + case MYSQL_TYPE_SHORT: return 2; + case MYSQL_TYPE_LONG: return 4; + case MYSQL_TYPE_LONGLONG: return 8; + case MYSQL_TYPE_INT24: return 3; + } + return 0; // This should not happen +} + +Field *Column_definition_attributes::make_field(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const Record_addr *rec, + const Type_handler *handler, + const LEX_CSTRING *field_name, + uint32 flags) + const +{ + DBUG_ASSERT(length <= UINT_MAX32); DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s", - handler->name().ptr(), field_length, interval, + handler->name().ptr(), (uint) length, interval, FLAGSTR(pack_flag, FIELDFLAG_BINARY), FLAGSTR(pack_flag, FIELDFLAG_INTERVAL), FLAGSTR(pack_flag, FIELDFLAG_NUMBER), FLAGSTR(pack_flag, FIELDFLAG_PACK), FLAGSTR(pack_flag, FIELDFLAG_BLOB))); - if (handler == &type_handler_row) - { - DBUG_ASSERT(field_length == 0); - DBUG_ASSERT(f_maybe_null(pack_flag)); - return new (mem_root) Field_row(ptr, field_name); - } - - if (handler->real_field_type() == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag)) - { - bit_ptr= null_pos; - bit_offset= null_bit; - if (f_maybe_null(pack_flag)) // if null field - { - bit_ptr+= (null_bit == 7); // shift bit_ptr and bit_offset - bit_offset= (bit_offset + 1) & 7; - } - } - - if (!f_maybe_null(pack_flag)) - { - null_pos=0; - null_bit=0; - } - else - { - null_bit= ((uchar) 1) << null_bit; - } - - - if (f_is_alpha(pack_flag)) - { - if (!f_is_packed(pack_flag)) - { - enum_field_types field_type= handler->real_field_type(); - if (field_type == MYSQL_TYPE_STRING || - field_type == MYSQL_TYPE_DECIMAL || // 3.23 or 4.0 string - field_type == MYSQL_TYPE_VAR_STRING) - return new (mem_root) - Field_string(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - field_charset); - if (field_type == MYSQL_TYPE_VARCHAR) - { - if (unireg_check == Field::TMYSQL_COMPRESSED) - return new (mem_root) - Field_varstring_compressed( - ptr, field_length, - HA_VARCHAR_PACKLENGTH(field_length), - null_pos, null_bit, - unireg_check, field_name, - share, field_charset, zlib_compression_method); - - return new (mem_root) - Field_varstring(ptr,field_length, - HA_VARCHAR_PACKLENGTH(field_length), - null_pos,null_bit, - unireg_check, field_name, - share, - field_charset); - } - return 0; // Error - } - - // MYSQL_TYPE_VAR_STRING is handled above - DBUG_ASSERT(f_packtype(pack_flag) != MYSQL_TYPE_VAR_STRING); - const Type_handler *tmp; - tmp= Type_handler::get_handler_by_real_type((enum_field_types) - f_packtype(pack_flag)); - uint pack_length= tmp->calc_pack_length(field_length); - -#ifdef HAVE_SPATIAL - if (f_is_geom(pack_flag)) - { - status_var_increment(current_thd->status_var.feature_gis); - return new (mem_root) - Field_geom(ptr,null_pos,null_bit, - unireg_check, field_name, share, - pack_length, geom_type, srid); - } -#endif - if (f_is_blob(pack_flag)) - { - if (unireg_check == Field::TMYSQL_COMPRESSED) - return new (mem_root) - Field_blob_compressed(ptr, null_pos, null_bit, - unireg_check, field_name, share, - pack_length, field_charset, zlib_compression_method); - - return new (mem_root) - Field_blob(ptr,null_pos,null_bit, - unireg_check, field_name, share, - pack_length, field_charset); - } - if (interval) - { - if (f_is_enum(pack_flag)) - return new (mem_root) - Field_enum(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - pack_length, interval, field_charset); - else - return new (mem_root) - Field_set(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - pack_length, interval, field_charset); - } - } - - switch (handler->real_field_type()) { - case MYSQL_TYPE_DECIMAL: - return new (mem_root) - Field_decimal(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - f_decimals(pack_flag), - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_NEWDECIMAL: - return new (mem_root) - Field_new_decimal(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - f_decimals(pack_flag), - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_FLOAT: - { - int decimals= f_decimals(pack_flag); - if (decimals == FLOATING_POINT_DECIMALS) - decimals= NOT_FIXED_DEC; - return new (mem_root) - Field_float(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - decimals, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag)== 0); - } - case MYSQL_TYPE_DOUBLE: - { - int decimals= f_decimals(pack_flag); - if (decimals == FLOATING_POINT_DECIMALS) - decimals= NOT_FIXED_DEC; - return new (mem_root) - Field_double(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - decimals, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag)== 0); - } - case MYSQL_TYPE_TINY: - return new (mem_root) - Field_tiny(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_SHORT: - return new (mem_root) - Field_short(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_INT24: - return new (mem_root) - Field_medium(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_LONG: - return new (mem_root) - Field_long(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - case MYSQL_TYPE_LONGLONG: - if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG)) - { - return new (mem_root) - Field_vers_trx_id(ptr, field_length, null_pos, null_bit, - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - } - else - { - return new (mem_root) - Field_longlong(ptr,field_length,null_pos,null_bit, - unireg_check, field_name, - f_is_zerofill(pack_flag) != 0, - f_is_dec(pack_flag) == 0); - } - case MYSQL_TYPE_TIMESTAMP: - { - uint dec= field_length > MAX_DATETIME_WIDTH ? - field_length - MAX_DATETIME_WIDTH - 1: 0; - return new_Field_timestamp(mem_root, ptr, null_pos, null_bit, unireg_check, - field_name, share, dec); - } - case MYSQL_TYPE_TIMESTAMP2: - { - uint dec= field_length > MAX_DATETIME_WIDTH ? - field_length - MAX_DATETIME_WIDTH - 1: 0; - return new (mem_root) - Field_timestampf(ptr, null_pos, null_bit, unireg_check, - field_name, share, dec); - } - case MYSQL_TYPE_YEAR: - return new (mem_root) - Field_year(ptr,field_length,null_pos,null_bit, - unireg_check, field_name); - case MYSQL_TYPE_DATE: - return new (mem_root) - Field_date(ptr,null_pos,null_bit, - unireg_check, field_name); - case MYSQL_TYPE_NEWDATE: - return new (mem_root) - Field_newdate(ptr,null_pos,null_bit, - unireg_check, field_name); - case MYSQL_TYPE_TIME: - { - uint dec= field_length > MIN_TIME_WIDTH ? - field_length - MIN_TIME_WIDTH - 1: 0; - return new_Field_time(mem_root, ptr, null_pos, null_bit, unireg_check, - field_name, dec); - } - case MYSQL_TYPE_TIME2: - { - uint dec= field_length > MIN_TIME_WIDTH ? - field_length - MIN_TIME_WIDTH - 1: 0; - return new (mem_root) - Field_timef(ptr, null_pos, null_bit, unireg_check, - field_name, dec); - } - case MYSQL_TYPE_DATETIME: - { - uint dec= field_length > MAX_DATETIME_WIDTH ? - field_length - MAX_DATETIME_WIDTH - 1: 0; - return new_Field_datetime(mem_root, ptr, null_pos, null_bit, unireg_check, - field_name, dec); - } - case MYSQL_TYPE_DATETIME2: - { - uint dec= field_length > MAX_DATETIME_WIDTH ? - field_length - MAX_DATETIME_WIDTH - 1: 0; - return new (mem_root) - Field_datetimef(ptr, null_pos, null_bit, unireg_check, - field_name, dec); - } - case MYSQL_TYPE_NULL: - return new (mem_root) - Field_null(ptr, field_length, unireg_check, field_name, - field_charset); - case MYSQL_TYPE_BIT: - return (f_bit_as_char(pack_flag) ? - new (mem_root) - Field_bit_as_char(ptr, field_length, null_pos, null_bit, - unireg_check, field_name) : - new (mem_root) - Field_bit(ptr, field_length, null_pos, null_bit, bit_ptr, - bit_offset, unireg_check, field_name)); - - default: // Impossible (Wrong version) - break; - } - return 0; + Record_addr addr(rec->ptr(), f_maybe_null(pack_flag) ? rec->null() : + Bit_addr()); + /* + Special code for the BIT-alike data types + who store data bits together with NULL-bits. + */ + Bit_addr bit(rec->null()); + if (f_maybe_null(pack_flag)) + bit.inc(); + return handler->make_table_field_from_def(share, mem_root, field_name, + addr, bit, this, flags); } + bool Field_vers_trx_id::test_if_equality_guarantees_uniqueness(const Item* item) const { - return item->type() == Item::DATE_ITEM; + return item->is_of_type(Item::CONST_ITEM, TIME_RESULT); } +Column_definition_attributes::Column_definition_attributes(const Field *field) + :length(field->character_octet_length() / field->charset()->mbmaxlen), + unireg_check(field->unireg_check), + interval(NULL), + charset(field->charset()), // May be NULL ptr + srid(0), + geom_type(Field::GEOM_GEOMETRY), + pack_flag(0) +{} + + /** Create a field suitable for create of table. */ Column_definition::Column_definition(THD *thd, Field *old_field, Field *orig_field) + :Column_definition_attributes(old_field) { on_update= NULL; field_name= old_field->field_name; - length= old_field->field_length; flags= old_field->flags; - unireg_check=old_field->unireg_check; pack_length=old_field->pack_length(); key_length= old_field->key_length(); set_handler(old_field->type_handler()); - charset= old_field->charset(); // May be NULL ptr comment= old_field->comment; decimals= old_field->decimals(); vcol_info= old_field->vcol_info; option_list= old_field->option_list; - pack_flag= 0; compression_method_ptr= 0; versioning= VERSIONING_NOT_SET; invisible= old_field->invisible; + interval_list.empty(); // prepare_interval_field() needs this + char_length= (uint) length; if (orig_field) { @@ -10926,66 +10669,9 @@ Column_definition::Column_definition(THD *thd, Field *old_field, check_constraint= 0; } - switch (real_field_type()) { - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - length/= charset->mbmaxlen; - key_length/= charset->mbmaxlen; - break; - case MYSQL_TYPE_STRING: - /* Change CHAR -> VARCHAR if dynamic record length */ - if (old_field->type() == MYSQL_TYPE_VAR_STRING) - set_handler(&type_handler_varchar); - /* fall through */ - - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_VAR_STRING: - /* This is corrected in create_length_to_internal_length */ - length= (length+charset->mbmaxlen-1) / charset->mbmaxlen - - MY_TEST(old_field->compression_method()); - break; -#ifdef HAVE_SPATIAL - case MYSQL_TYPE_GEOMETRY: - geom_type= ((Field_geom*)old_field)->geom_type; - srid= ((Field_geom*)old_field)->srid; - break; -#endif - case MYSQL_TYPE_YEAR: - if (length != 4) - { - char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1]; - my_snprintf(buff, sizeof(buff), "YEAR(%llu)", length); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_WARN_DEPRECATED_SYNTAX, - ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX), - buff, "YEAR(4)"); - } - break; - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - /* - Floating points are stored with FLOATING_POINT_DECIMALS but internally - in MariaDB used with NOT_FIXED_DEC, which is >= FLOATING_POINT_DECIMALS. - */ - if (decimals >= FLOATING_POINT_DECIMALS) - decimals= NOT_FIXED_DEC; - break; - default: - break; - } - - if (flags & (ENUM_FLAG | SET_FLAG)) - interval= ((Field_enum*) old_field)->typelib; - else - interval=0; + type_handler()->Column_definition_reuse_fix_attributes(thd, this, old_field); - interval_list.empty(); // prepare_interval_field() needs this - - char_length= (uint)length; + type_handler()->Column_definition_implicit_upgrade(this); /* Copy the default (constant/function) from the column object orig_field, if @@ -11067,11 +10753,11 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field, uint32 Field_blob::char_length() const { - return Field_blob::octet_length(); + return Field_blob::character_octet_length(); } -uint32 Field_blob::octet_length() const +uint32 Field_blob::character_octet_length() const { switch (packlength) { @@ -11233,13 +10919,14 @@ Field::set_warning(Sql_condition::enum_warning_level level, uint code, void Field::set_datetime_warning(Sql_condition::enum_warning_level level, uint code, const ErrConv *str, - timestamp_type ts_type, int cuted_increment) + const char *typestr, int cuted_increment) const { THD *thd= get_thd(); if (thd->really_abort_on_warning() && level >= Sql_condition::WARN_LEVEL_WARN) - make_truncated_value_warning(thd, level, str, ts_type, - table->s, field_name.str); + thd->push_warning_truncated_value_for_field(level, typestr, + str->ptr(), table->s, + field_name.str); else set_warning(level, code, cuted_increment); } diff --git a/sql/field.h b/sql/field.h index 1d01dc72290..e762e45c024 100644 --- a/sql/field.h +++ b/sql/field.h @@ -48,6 +48,9 @@ class Item_equal; class Virtual_tmp_table; class Qualified_column_ident; class Table_ident; +class SEL_ARG; +class RANGE_OPT_PARAM; +struct KEY_PART; enum enum_check_fields { @@ -467,31 +470,6 @@ inline bool is_temporal_type_with_date(enum_field_types type) } -/** - Convert temporal real types as retuned by field->real_type() - to field type as returned by field->type(). - - @param real_type Real type. - @retval Field type. -*/ -inline enum_field_types real_type_to_type(enum_field_types real_type) -{ - switch (real_type) - { - case MYSQL_TYPE_TIME2: - return MYSQL_TYPE_TIME; - case MYSQL_TYPE_DATETIME2: - return MYSQL_TYPE_DATETIME; - case MYSQL_TYPE_TIMESTAMP2: - return MYSQL_TYPE_TIMESTAMP; - case MYSQL_TYPE_NEWDATE: - return MYSQL_TYPE_DATE; - /* Note: NEWDECIMAL is a type, not only a real_type */ - default: return real_type; - } -} - - enum enum_vcol_info_type { VCOL_GENERATED_VIRTUAL, VCOL_GENERATED_STORED, @@ -632,7 +610,9 @@ protected: static void do_field_int(Copy_field *copy); static void do_field_real(Copy_field *copy); static void do_field_string(Copy_field *copy); - static void do_field_temporal(Copy_field *copy); + static void do_field_date(Copy_field *copy); + static void do_field_temporal(Copy_field *copy, date_mode_t fuzzydate); + static void do_field_datetime(Copy_field *copy); static void do_field_timestamp(Copy_field *copy); static void do_field_decimal(Copy_field *copy); public: @@ -804,7 +784,21 @@ public: virtual int store(longlong nr, bool unsigned_val)=0; virtual int store_decimal(const my_decimal *d)=0; virtual int store_time_dec(const MYSQL_TIME *ltime, uint dec); - virtual int store_timestamp(my_time_t timestamp, ulong sec_part); + virtual int store_timestamp_dec(const timeval &ts, uint dec); + int store_timestamp(my_time_t timestamp, ulong sec_part) + { + return store_timestamp_dec(Timeval(timestamp, sec_part), + TIME_SECOND_PART_DIGITS); + } + /** + Store a value represented in native format + */ + virtual int store_native(const Native &value) + { + DBUG_ASSERT(0); + reset(); + return 0; + } int store_time(const MYSQL_TIME *ltime) { return store_time_dec(ltime, TIME_SECOND_PART_DIGITS); } int store(const char *to, size_t length, CHARSET_INFO *cs, @@ -836,7 +830,7 @@ public: return nr < 0 ? 0 : (ulonglong) nr; } virtual bool val_bool(void)= 0; - virtual my_decimal *val_decimal(my_decimal *); + virtual my_decimal *val_decimal(my_decimal *)=0; inline String *val_str(String *str) { return val_str(str, str); } /* val_str(buf1, buf2) gets two buffers and should use them as follows: @@ -851,6 +845,11 @@ public: This trickery is used to decrease a number of malloc calls. */ virtual String *val_str(String*,String *)=0; + virtual bool val_native(Native *to) + { + DBUG_ASSERT(!is_null()); + return to->copy((const char *) ptr, pack_length()); + } String *val_int_as_str(String *val_buffer, bool unsigned_flag); /* Return the field value as a LEX_CSTRING, without padding to full length @@ -873,6 +872,10 @@ public: to be quoted when used in constructing an SQL query. */ virtual bool str_needs_quotes() { return FALSE; } + const Type_handler *type_handler_for_comparison() const + { + return type_handler()->type_handler_for_comparison(); + } Item_result result_type () const { return type_handler()->result_type(); @@ -881,7 +884,6 @@ public: { return type_handler()->cmp_type(); } - static enum_field_types field_type_merge(enum_field_types, enum_field_types); virtual bool eq(Field *field) { return (ptr == field->ptr && null_ptr == field->null_ptr && @@ -1246,6 +1248,12 @@ public: virtual Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uint32 length, uchar *new_null_ptr, uint new_null_bit); + Field *create_tmp_field(MEM_ROOT *root, TABLE *new_table, + bool maybe_null_arg); + Field *create_tmp_field(MEM_ROOT *root, TABLE *new_table) + { + return create_tmp_field(root, new_table, maybe_null()); + } Field *clone(MEM_ROOT *mem_root, TABLE *new_table); Field *clone(MEM_ROOT *mem_root, TABLE *new_table, my_ptrdiff_t diff, bool stat_flag= FALSE); @@ -1356,8 +1364,7 @@ public: } void copy_from_tmp(int offset); uint fill_cache_field(struct st_cache_field *copy); - virtual bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_time(MYSQL_TIME *ltime) { return get_date(ltime, TIME_TIME_ONLY); } + virtual bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); virtual TYPELIB *get_typelib() const { return NULL; } virtual CHARSET_INFO *charset(void) const { return &my_charset_bin; } virtual CHARSET_INFO *charset_for_protocol(void) const @@ -1380,13 +1387,13 @@ protected: return set_warning(Sql_condition::WARN_LEVEL_NOTE, code, cuted_increment); } void set_datetime_warning(Sql_condition::enum_warning_level, uint code, - const ErrConv *str, timestamp_type ts_type, + const ErrConv *str, const char *typestr, int cuted_increment) const; void set_datetime_warning(uint code, - const ErrConv *str, timestamp_type ts_type, + const ErrConv *str, const char *typestr, int cuted_increment) const { - set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, code, str, ts_type, + set_datetime_warning(Sql_condition::WARN_LEVEL_WARN, code, str, typestr, cuted_increment); } void set_warning_truncated_wrong_value(const char *type, const char *value); @@ -1396,6 +1403,59 @@ protected: } int warn_if_overflow(int op_result); Copy_func *get_identical_copy_func() const; + bool can_optimize_scalar_range(const RANGE_OPT_PARAM *param, + const KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, + const Item *value) const; + uchar *make_key_image(MEM_ROOT *mem_root, const KEY_PART *key_part); + SEL_ARG *get_mm_leaf_int(RANGE_OPT_PARAM *param, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value, + bool unsigned_field); + /* + Make a leaf tree for the cases when the value was stored + to the field exactly, without any truncation, rounding or adjustments. + For example, if we stored an INT value into an INT column, + and value->save_in_field_no_warnings() returned 0, + we know that the value was stored exactly. + */ + SEL_ARG *stored_field_make_mm_leaf_exact(RANGE_OPT_PARAM *param, + KEY_PART *key_part, + scalar_comparison_op op, + Item *value); + /* + Make a leaf tree for the cases when we don't know if + the value was stored to the field without any data loss, + or was modified to a smaller or a greater value. + Used for the data types whose methods Field::store*() + silently adjust the value. This is the most typical case. + */ + SEL_ARG *stored_field_make_mm_leaf(RANGE_OPT_PARAM *param, + KEY_PART *key_part, + scalar_comparison_op op, Item *value); + /* + Make a leaf tree when an INT value was stored into a field of INT type, + and some truncation happened. Tries to adjust the range search condition + when possible, e.g. "tinytint < 300" -> "tinyint <= 127". + Can also return SEL_ARG_IMPOSSIBLE(), and NULL (not sargable). + */ + SEL_ARG *stored_field_make_mm_leaf_bounded_int(RANGE_OPT_PARAM *param, + KEY_PART *key_part, + scalar_comparison_op op, + Item *value, + bool unsigned_field); + /* + Make a leaf tree when some truncation happened during + value->save_in_field_no_warning(this), and we cannot yet adjust the range + search condition for the current combination of the field and the value + data types. + Returns SEL_ARG_IMPOSSIBLE() for "=" and "<=>". + Returns NULL (not sargable) for other comparison operations. + */ + SEL_ARG *stored_field_make_mm_leaf_truncated(RANGE_OPT_PARAM *prm, + scalar_comparison_op, + Item *value); public: void set_table_name(String *alias) { @@ -1406,6 +1466,19 @@ public: orig_table= table= table_arg; set_table_name(&table_arg->alias); } + virtual void init_for_tmp_table(Field *org_field, TABLE *new_table) + { + init(new_table); + orig_table= org_field->orig_table; + vcol_info= 0; + cond_selectivity= 1.0; + next_equal_field= NULL; + option_list= NULL; + option_struct= NULL; + if (org_field->type() == MYSQL_TYPE_VAR_STRING || + org_field->type() == MYSQL_TYPE_VARCHAR) + new_table->s->db_create_options|= HA_OPTION_PACK_RECORD; + } void init_for_make_new_field(TABLE *new_table_arg, TABLE *orig_table_arg) { init(new_table_arg); @@ -1432,12 +1505,21 @@ public: /* convert decimal to longlong with overflow check */ longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag, int *err); + /* + Maximum number of bytes in character representation. + - For string types it is equal to the field capacity, in bytes. + - For non-string types it represents the longest possible string length + after conversion to string. + */ + virtual uint32 character_octet_length() const + { + return field_length; + } /* The max. number of characters */ virtual uint32 char_length() const { return field_length / charset()->mbmaxlen; } - virtual geometry_type get_geometry_type() { /* shouldn't get here. */ @@ -1555,6 +1637,10 @@ public: const Item *item, bool is_eq_func) const; + virtual SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value)= 0; + bool can_optimize_outer_join_table_elimination(const Item_bool_func *cond, const Item *item) const { @@ -1716,6 +1802,9 @@ public: { return pos_in_interval_val_real(min, max); } + SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value); }; @@ -1753,6 +1842,7 @@ public: enum Derivation derivation(void) const { return field_derivation; } bool binary() const { return field_charset == &my_charset_bin; } uint32 max_display_length() const { return field_length; } + uint32 character_octet_length() const { return field_length; } uint32 char_length() const { return field_length / field_charset->mbmaxlen; } Information_schema_character_attributes information_schema_character_attributes() const @@ -1772,6 +1862,9 @@ public: return pos_in_interval_val_str(min, max, length_size()); } bool test_if_equality_guarantees_uniqueness(const Item *const_item) const; + SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value); }; /* base class for Field_string, Field_varstring and Field_blob */ @@ -1884,9 +1977,9 @@ public: return Field_num::memcpy_field_possible(from) && field_length >= from->field_length; } - int store_decimal(const my_decimal *); + int store_decimal(const my_decimal *dec) { return store(dec->to_double()); } int store_time_dec(const MYSQL_TIME *ltime, uint dec); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); my_decimal *val_decimal(my_decimal *); bool val_bool() { return val_real() != 0e0; } uint32 max_display_length() const { return field_length; } @@ -1967,8 +2060,8 @@ public: } int save_in_field(Field *to) { - my_decimal buff; - return to->store_decimal(val_decimal(&buff)); + my_decimal tmp(ptr, precision, dec); + return to->store_decimal(&tmp); } bool memcpy_field_possible(const Field *from) const { @@ -1984,17 +2077,34 @@ public: int store(longlong nr, bool unsigned_val); int store_time_dec(const MYSQL_TIME *ltime, uint dec); int store_decimal(const my_decimal *); - double val_real(void); - longlong val_int(void); - ulonglong val_uint(void); + double val_real(void) + { + return my_decimal(ptr, precision, dec).to_double(); + } + longlong val_int(void) + { + return my_decimal(ptr, precision, dec).to_longlong(unsigned_flag); + } + ulonglong val_uint(void) + { + return (ulonglong) my_decimal(ptr, precision, dec).to_longlong(true); + } my_decimal *val_decimal(my_decimal *); - String *val_str(String*, String *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + String *val_str(String *val_buffer, String *val_ptr __attribute__((unused))) + { + uint fixed_precision= zerofill ? precision : 0; + return my_decimal(ptr, precision, dec). + to_string(val_buffer, fixed_precision, dec, '0'); + } + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) + { + my_decimal nr(ptr, precision, dec); + return decimal_to_datetime_with_warn(get_thd(), &nr, ltime, + fuzzydate, table->s, field_name.str); + } bool val_bool() { - my_decimal decimal_value; - my_decimal *val= val_decimal(&decimal_value); - return val ? !my_decimal_is_zero(val) : 0; + return my_decimal(ptr, precision, dec).to_bool(); } int cmp(const uchar *, const uchar *); void sort_string(uchar *buff, uint length); @@ -2039,7 +2149,7 @@ public: return nr < 0 && !unsigned_flag ? 0 : (ulonglong) nr; } int store_time_dec(const MYSQL_TIME *ltime, uint dec); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); virtual const Type_limits_int *type_limits_int() const= 0; uint32 max_display_length() const { @@ -2069,6 +2179,12 @@ public: uint32 prec= type_limits_int()->precision(); return Information_schema_numeric_attributes(prec, 0); } + SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value) + { + return get_mm_leaf_int(param, key_part, cond, op, value, unsigned_flag); + } }; @@ -2316,8 +2432,8 @@ public: {} const Type_handler *type_handler() const { return &type_handler_vers_trx_id; } uint size_of() const { return sizeof(*this); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate, ulonglong trx_id); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate, ulonglong trx_id); + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { return get_date(ltime, fuzzydate, (ulonglong) val_int()); } @@ -2417,6 +2533,11 @@ public: if (dec_arg >= FLOATING_POINT_DECIMALS) dec_arg= NOT_FIXED_DEC; } + void init_for_tmp_table(Field *org_field, TABLE *new_table) + { + Field::init_for_tmp_table(org_field, new_table); + not_fixed= true; + } const Type_handler *type_handler() const { return &type_handler_double; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; } int store(const char *to,size_t length,CHARSET_INFO *charset); @@ -2495,6 +2616,35 @@ class Field_temporal: public Field { protected: Item *get_equal_const_item_datetime(THD *thd, const Context &ctx, Item *const_item); + void set_warnings(Sql_condition::enum_warning_level trunc_level, + const ErrConv *str, int was_cut, const char *typestr); + int store_TIME_return_code_with_warnings(int warn, const ErrConv *str, + const char *typestr) + { + if (!MYSQL_TIME_WARN_HAVE_WARNINGS(warn) && + MYSQL_TIME_WARN_HAVE_NOTES(warn)) + { + set_warnings(Sql_condition::WARN_LEVEL_NOTE, str, + warn | MYSQL_TIME_WARN_TRUNCATED, typestr); + return 3; + } + set_warnings(Sql_condition::WARN_LEVEL_WARN, str, warn, typestr); + return warn ? 2 : 0; + } + int store_invalid_with_warning(const ErrConv *str, int was_cut, + const char *typestr) + { + DBUG_ASSERT(was_cut); + reset(); + Sql_condition::enum_warning_level level= Sql_condition::WARN_LEVEL_WARN; + if (was_cut & MYSQL_TIME_WARN_ZERO_DATE) + { + set_warnings(level, str, MYSQL_TIME_WARN_OUT_OF_RANGE, typestr); + return 2; + } + set_warnings(level, str, MYSQL_TIME_WARN_TRUNCATED, typestr); + return 1; + } public: Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, utype unireg_check_arg, @@ -2510,7 +2660,8 @@ public: int save_in_field(Field *to) { MYSQL_TIME ltime; - if (get_date(<ime, 0)) + // For temporal types no truncation needed. Rounding mode is not important. + if (get_date(<ime, TIME_CONV_NONE | TIME_FRAC_NONE)) return to->reset(); return to->store_time_dec(<ime, decimals()); } @@ -2529,8 +2680,6 @@ public: return (Field::eq_def(field) && decimals() == field->decimals()); } my_decimal *val_decimal(my_decimal*); - void set_warnings(Sql_condition::enum_warning_level trunc_level, - const ErrConv *str, int was_cut, timestamp_type ts_type); double pos_in_interval(Field *min, Field *max) { return pos_in_interval_val_real(min, max); @@ -2545,6 +2694,9 @@ public: { return true; } + SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value); }; @@ -2557,18 +2709,20 @@ public: */ class Field_temporal_with_date: public Field_temporal { protected: - int store_TIME_with_warning(MYSQL_TIME *ltime, const ErrConv *str, - int was_cut, int have_smth_to_conv); - virtual void store_TIME(MYSQL_TIME *ltime) = 0; + virtual void store_TIME(const MYSQL_TIME *ltime) = 0; + void store_datetime(const Datetime &dt) + { + return store_TIME(dt.get_mysql_time()); + } virtual bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, - ulonglong fuzzydate) const = 0; + date_mode_t fuzzydate) const = 0; bool validate_MMDD(bool not_zero_date, uint month, uint day, - ulonglong fuzzydate) const + date_mode_t fuzzydate) const { if (!not_zero_date) - return fuzzydate & TIME_NO_ZERO_DATE; + return bool(fuzzydate & TIME_NO_ZERO_DATE); if (!month || !day) - return fuzzydate & TIME_NO_ZERO_IN_DATE; + return bool(fuzzydate & TIME_NO_ZERO_IN_DATE); return false; } public: @@ -2579,20 +2733,23 @@ public: :Field_temporal(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg) {} - int store(const char *to, size_t length, CHARSET_INFO *charset); - int store(double nr); - int store(longlong nr, bool unsigned_val); - int store_time_dec(const MYSQL_TIME *ltime, uint dec); - int store_decimal(const my_decimal *); bool validate_value_in_record(THD *thd, const uchar *record) const; }; class Field_timestamp :public Field_temporal { protected: - sql_mode_t sql_mode_for_timestamp(THD *thd) const; - int store_TIME_with_warning(THD *, MYSQL_TIME *, const ErrConv *, - int warnings, bool have_smth_to_conv); + int store_TIME_with_warning(THD *, const Datetime *, + const ErrConv *, int warn); + virtual void store_TIMEVAL(const timeval &tv) + { + int4store(ptr, tv.tv_sec); + } + void store_TIMESTAMP(const Timestamp &ts) + { + store_TIMEVAL(ts.tv()); + } + int zero_time_stored_return_code_with_warning(); public: Field_timestamp(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, @@ -2607,7 +2764,7 @@ public: int store(longlong nr, bool unsigned_val); int store_time_dec(const MYSQL_TIME *ltime, uint dec); int store_decimal(const my_decimal *); - int store_timestamp(my_time_t timestamp, ulong sec_part); + int store_timestamp_dec(const timeval &ts, uint dec); int save_in_field(Field *to); double val_real(void); longlong val_int(void); @@ -2632,11 +2789,19 @@ public: { return get_timestamp(ptr, sec_part); } - virtual void store_TIME(my_time_t timestamp, ulong sec_part) + /* + This method is used by storage/perfschema and + Item_func_now_local::save_in_field(). + */ + void store_TIME(my_time_t ts, ulong sec_part) { - int4store(ptr,timestamp); + int warn; + time_round_mode_t mode= Datetime::default_round_mode(get_thd()); + store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn)); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); + int store_native(const Native &value); + bool val_native(Native *to); uchar *pack(uchar *to, const uchar *from, uint max_length __attribute__((unused))) { @@ -2704,6 +2869,7 @@ class Field_timestamp_hires :public Field_timestamp_with_dec { { return Type_handler_timestamp::sec_part_bytes(dec); } + void store_TIMEVAL(const timeval &tv); public: Field_timestamp_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, @@ -2715,8 +2881,8 @@ public: { DBUG_ASSERT(dec); } + bool val_native(Native *to); my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const; - void store_TIME(my_time_t timestamp, ulong sec_part); int cmp(const uchar *,const uchar *); uint32 pack_length() const { return 4 + sec_part_bytes(dec); } uint size_of() const { return sizeof(*this); } @@ -2732,6 +2898,7 @@ class Field_timestampf :public Field_timestamp_with_dec { *metadata_ptr= (uchar) decimals(); return 1; } + void store_TIMEVAL(const timeval &tv); public: Field_timestampf(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, @@ -2760,12 +2927,12 @@ public: } void set_max(); bool is_max(); - void store_TIME(my_time_t timestamp, ulong sec_part); my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const; my_time_t get_timestamp(ulong *sec_part) const { return get_timestamp(ptr, sec_part); } + bool val_native(Native *to); uint size_of() const { return sizeof(*this); } }; @@ -2778,7 +2945,10 @@ public: :Field_tiny(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, 1, 1) {} - const Type_handler *type_handler() const { return &type_handler_year; } + const Type_handler *type_handler() const + { + return field_length == 2 ? &type_handler_year2 : &type_handler_year; + } Copy_func *get_copy_func(const Field *from) const { if (eq_def(from)) @@ -2792,7 +2962,7 @@ public: return do_field_string; } case TIME_RESULT: - return do_field_temporal; + return do_field_date; case DECIMAL_RESULT: return do_field_decimal; case REAL_RESULT: @@ -2813,7 +2983,7 @@ public: double val_real(void); longlong val_int(void); String *val_str(String*,String *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); bool send_binary(Protocol *protocol); Information_schema_numeric_attributes information_schema_numeric_attributes() const @@ -2825,18 +2995,44 @@ public: }; -class Field_date :public Field_temporal_with_date { - void store_TIME(MYSQL_TIME *ltime); - bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; +class Field_date_common: public Field_temporal_with_date +{ +protected: + int store_TIME_with_warning(const Datetime *ltime, const ErrConv *str, + int was_cut); +public: + Field_date_common(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, + enum utype unireg_check_arg, + const LEX_CSTRING *field_name_arg) + :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, + null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg) + {} + Copy_func *get_copy_func(const Field *from) const; + SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value); + int store(const char *to, size_t length, CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr, bool unsigned_val); + int store_time_dec(const MYSQL_TIME *ltime, uint dec); + int store_decimal(const my_decimal *); +}; + + +class Field_date :public Field_date_common +{ + void store_TIME(const MYSQL_TIME *ltime); + bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const; public: Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) - :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg) {} + :Field_date_common(ptr_arg, null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg) {} const Type_handler *type_handler() const { return &type_handler_date; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { return Field_date::get_TIME(ltime, ptr, fuzzydate); } double val_real(void); longlong val_int(void); @@ -2860,14 +3056,15 @@ public: }; -class Field_newdate :public Field_temporal_with_date { - void store_TIME(MYSQL_TIME *ltime); - bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; +class Field_newdate :public Field_date_common +{ + void store_TIME(const MYSQL_TIME *ltime); + bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const; public: Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg) - :Field_temporal_with_date(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg) + :Field_date_common(ptr_arg, null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg) {} const Type_handler *type_handler() const { return &type_handler_newdate; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; } @@ -2880,7 +3077,7 @@ public: void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 3; } void sql_type(String &str) const; - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { return Field_newdate::get_TIME(ltime, ptr, fuzzydate); } uint size_of() const { return sizeof(*this); } Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item); @@ -2896,14 +3093,12 @@ class Field_time :public Field_temporal { long curdays; protected: virtual void store_TIME(const MYSQL_TIME *ltime); - int store_TIME_with_warning(MYSQL_TIME *ltime, const ErrConv *str, - int was_cut, int have_smth_to_conv); - void set_warnings(Sql_condition::enum_warning_level level, - const ErrConv *str, int was_cut) + void store_TIME(const Time &t) { - Field_temporal::set_warnings(level, str, was_cut, MYSQL_TIMESTAMP_TIME); + return store_TIME(t.get_mysql_time()); } - bool check_zero_in_date_with_warn(ulonglong fuzzydate); + int store_TIME_with_warning(const Time *ltime, const ErrConv *str, int warn); + bool check_zero_in_date_with_warn(date_mode_t fuzzydate); static void do_field_time(Copy_field *copy); public: Field_time(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg, @@ -2937,7 +3132,7 @@ public: double val_real(void); longlong val_int(void); String *val_str(String*,String *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); bool send_binary(Protocol *protocol); int cmp(const uchar *,const uchar *); void sort_string(uchar *buff,uint length); @@ -2998,7 +3193,7 @@ public: ((TIME_MAX_VALUE_SECONDS+1LL)*TIME_SECOND_PART_FACTOR), dec); } int reset(void); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); int cmp(const uchar *,const uchar *); void sort_string(uchar *buff,uint length); uint32 pack_length() const { return Type_handler_time::hires_bytes(dec); } @@ -3049,14 +3244,17 @@ public: return memcmp(a_ptr, b_ptr, pack_length()); } int reset(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate); uint size_of() const { return sizeof(*this); } }; class Field_datetime :public Field_temporal_with_date { - void store_TIME(MYSQL_TIME *ltime); - bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; + void store_TIME(const MYSQL_TIME *ltime); + bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const; +protected: + int store_TIME_with_warning(const Datetime *ltime, const ErrConv *str, + int was_cut); public: Field_datetime(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, @@ -3070,6 +3268,11 @@ public: } const Type_handler *type_handler() const { return &type_handler_datetime; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; } + int store(const char *to, size_t length, CHARSET_INFO *charset); + int store(double nr); + int store(longlong nr, bool unsigned_val); + int store_time_dec(const MYSQL_TIME *ltime, uint dec); + int store_decimal(const my_decimal *); double val_real(void); longlong val_int(void); String *val_str(String*,String *); @@ -3078,7 +3281,7 @@ public: void sort_string(uchar *buff,uint length); uint32 pack_length() const { return 8; } void sql_type(String &str) const; - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { return Field_datetime::get_TIME(ltime, ptr, fuzzydate); } int set_time(); int evaluate_update_default_function() @@ -3148,8 +3351,8 @@ public: DATETIME(1..6) */ class Field_datetime_hires :public Field_datetime_with_dec { - void store_TIME(MYSQL_TIME *ltime); - bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; + void store_TIME(const MYSQL_TIME *ltime); + bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const; public: Field_datetime_hires(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, @@ -3161,7 +3364,7 @@ public: } int cmp(const uchar *,const uchar *); uint32 pack_length() const { return Type_handler_datetime::hires_bytes(dec); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { return Field_datetime_hires::get_TIME(ltime, ptr, fuzzydate); } uint size_of() const { return sizeof(*this); } }; @@ -3171,8 +3374,8 @@ public: DATETIME(0..6) - MySQL56 version */ class Field_datetimef :public Field_datetime_with_dec { - void store_TIME(MYSQL_TIME *ltime); - bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; + void store_TIME(const MYSQL_TIME *ltime); + bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, date_mode_t fuzzydate) const; int save_field_metadata(uchar *metadata_ptr) { *metadata_ptr= (uchar) decimals(); @@ -3203,7 +3406,7 @@ public: return memcmp(a_ptr, b_ptr, pack_length()); } int reset(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) { return Field_datetimef::get_TIME(ltime, ptr, fuzzydate); } uint size_of() const { return sizeof(*this); } }; @@ -3476,6 +3679,7 @@ private: str.append(STRING_WITH_LEN(" /*!100301 COMPRESSED*/")); } uint32 max_display_length() const { return field_length - 1; } + uint32 character_octet_length() const { return field_length - 1; } uint32 char_length() const { return (field_length - 1) / field_charset->mbmaxlen; @@ -3608,7 +3812,7 @@ public: Information_schema_character_attributes information_schema_character_attributes() const { - uint32 octets= Field_blob::octet_length(); + uint32 octets= Field_blob::character_octet_length(); uint32 chars= octets / field_charset->mbminlen; return Information_schema_character_attributes(octets, chars); } @@ -3774,7 +3978,7 @@ public: { return charset() == &my_charset_bin ? FALSE : TRUE; } uint32 max_display_length() const; uint32 char_length() const; - uint32 octet_length() const; + uint32 character_octet_length() const; uint is_equal(Create_field *new_field); friend void TABLE::remember_blob_values(String *blob_storage); @@ -4182,6 +4386,12 @@ public: } void hash(ulong *nr, ulong *nr2); + SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value) + { + return get_mm_leaf_int(param, key_part, cond, op, value, true); + } private: virtual size_t do_last_null_byte() const; int save_field_metadata(uchar *first_byte); @@ -4226,21 +4436,53 @@ public: extern const LEX_CSTRING null_clex_str; -Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, - uchar *ptr, uint32 field_length, - uchar *null_pos, uchar null_bit, - uint pack_flag, const Type_handler *handler, - CHARSET_INFO *cs, - Field::geometry_type geom_type, uint srid, - Field::utype unireg_check, - TYPELIB *interval, const LEX_CSTRING *field_name, - uint32 flags); +class Column_definition_attributes +{ +public: + /* + At various stages in execution this can be length of field in bytes or + max number of characters. + */ + ulonglong length; + Field::utype unireg_check; + TYPELIB *interval; // Which interval to use + CHARSET_INFO *charset; + uint32 srid; + Field::geometry_type geom_type; + uint pack_flag; + Column_definition_attributes() + :length(0), + unireg_check(Field::NONE), + interval(NULL), + charset(&my_charset_bin), + srid(0), + geom_type(Field::GEOM_GEOMETRY), + pack_flag(0) + { } + Column_definition_attributes(const Field *field); + Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, + const Record_addr *rec, + const Type_handler *handler, + const LEX_CSTRING *field_name, + uint32 flags) const; + uint temporal_dec(uint intlen) const + { + return (uint) (length > intlen ? length - intlen - 1 : 0); + } + uint pack_flag_to_pack_length() const; + void frm_pack_basic(uchar *buff) const; + void frm_pack_charset(uchar *buff) const; + void frm_unpack_basic(const uchar *buff); + bool frm_unpack_charset(TABLE_SHARE *share, const uchar *buff); +}; + /* Create field class for CREATE TABLE */ class Column_definition: public Sql_alloc, - public Type_handler_hybrid_field_type + public Type_handler_hybrid_field_type, + public Column_definition_attributes { /** Create "interval" from "interval_list". @@ -4295,11 +4537,6 @@ public: WITHOUT_VERSIONING }; Item *on_update; // ON UPDATE NOW() - /* - At various stages in execution this can be length of field in bytes or - max number of characters. - */ - ulonglong length; field_visibility_t invisible; /* The value of `length' as set by parser: is the number of characters @@ -4307,15 +4544,9 @@ public: */ uint32 char_length; uint decimals, flags, pack_length, key_length; - Field::utype unireg_check; - TYPELIB *interval; // Which interval to use List<String> interval_list; - CHARSET_INFO *charset; - uint32 srid; - Field::geometry_type geom_type; engine_option_value *option_list; - uint pack_flag; /* This is additinal data provided for any computed(virtual) field. @@ -4333,11 +4564,9 @@ public: :Type_handler_hybrid_field_type(&type_handler_null), compression_method_ptr(0), comment(null_clex_str), - on_update(NULL), length(0), invisible(VISIBLE), decimals(0), - flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE), - interval(0), charset(&my_charset_bin), - srid(0), geom_type(Field::GEOM_GEOMETRY), - option_list(NULL), pack_flag(0), + on_update(NULL), invisible(VISIBLE), decimals(0), + flags(0), pack_length(0), key_length(0), + option_list(NULL), vcol_info(0), default_value(0), check_constraint(0), versioning(VERSIONING_NOT_SET) { @@ -4467,20 +4696,18 @@ public: } Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, - uchar *ptr, uchar *null_pos, uchar null_bit, + const Record_addr *addr, const LEX_CSTRING *field_name_arg) const { - return ::make_field(share, mem_root, ptr, - (uint32)length, null_pos, null_bit, - pack_flag, type_handler(), charset, - geom_type, srid, unireg_check, interval, - field_name_arg, flags); + return Column_definition_attributes::make_field(share, mem_root, addr, + type_handler(), + field_name_arg, flags); } Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *field_name_arg) const { - return make_field(share, mem_root, (uchar *) 0, (uchar *) "", 0, - field_name_arg); + Record_addr addr(true); + return make_field(share, mem_root, &addr, field_name_arg); } /* Return true if default is an expression that must be saved explicitely */ bool has_default_expression(); @@ -4802,7 +5029,7 @@ bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name, #define FIELDFLAG_DEC_SHIFT 8 #define FIELDFLAG_MAX_DEC 63U -#define MTYP_TYPENR(type) (type & 127U) /* Remove bits from type */ +#define MTYP_TYPENR(type) ((type) & 127U) // Remove bits from type #define f_is_dec(x) ((x) & FIELDFLAG_DECIMAL) #define f_is_num(x) ((x) & FIELDFLAG_NUMBER) diff --git a/sql/field_conv.cc b/sql/field_conv.cc index dddb2182051..2f56be60dd6 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -413,8 +413,8 @@ void Field::do_field_real(Copy_field *copy) void Field::do_field_decimal(Copy_field *copy) { - my_decimal value; - copy->to_field->store_decimal(copy->from_field->val_decimal(&value)); + my_decimal value(copy->from_field); + copy->to_field->store_decimal(&value); } @@ -425,24 +425,32 @@ void Field::do_field_timestamp(Copy_field *copy) } -void Field::do_field_temporal(Copy_field *copy) +void Field::do_field_temporal(Copy_field *copy, date_mode_t fuzzydate) { MYSQL_TIME ltime; // TODO: we now need to check result - if (copy->from_field->get_date(<ime, 0)) + if (copy->from_field->get_date(<ime, fuzzydate)) copy->to_field->reset(); else copy->to_field->store_time_dec(<ime, copy->from_field->decimals()); } +void Field::do_field_datetime(Copy_field *copy) +{ + return do_field_temporal(copy, Datetime::Options(TIME_CONV_NONE, current_thd)); +} + + +void Field::do_field_date(Copy_field *copy) +{ + return do_field_temporal(copy, Date::Options(TIME_CONV_NONE)); +} + + void Field_time::do_field_time(Copy_field *copy) { - MYSQL_TIME ltime; - if (copy->from_field->get_date(<ime, TIME_TIME_ONLY)) - copy->to_field->reset(); - else - copy->to_field->store_time_dec(<ime, copy->from_field->decimals()); + return do_field_temporal(copy, Time::Options(current_thd)); } @@ -720,13 +728,20 @@ void Copy_field::set(Field *to,Field *from,bool save) Field::Copy_func *Field_timestamp::get_copy_func(const Field *from) const { Field::Copy_func *copy= Field_temporal::get_copy_func(from); - if (copy == do_field_temporal && from->type() == MYSQL_TYPE_TIMESTAMP) + if (copy == do_field_datetime && from->type() == MYSQL_TYPE_TIMESTAMP) return do_field_timestamp; else return copy; } +Field::Copy_func *Field_date_common::get_copy_func(const Field *from) const +{ + Field::Copy_func *copy= Field_temporal::get_copy_func(from); + return copy == do_field_datetime ? do_field_date : copy; +} + + Field::Copy_func *Field_temporal::get_copy_func(const Field *from) const { /* If types are not 100 % identical then convert trough get_date() */ @@ -739,7 +754,7 @@ Field::Copy_func *Field_temporal::get_copy_func(const Field *from) const if (!eq_def(from) || (table->in_use->variables.sql_mode & (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE))) - return do_field_temporal; + return do_field_datetime; return get_identical_copy_func(); } diff --git a/sql/filesort.cc b/sql/filesort.cc index a4be9e4acfa..c76295e666a 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -60,9 +60,7 @@ static bool save_index(Sort_param *param, uint count, static uint suffix_length(ulong string_length); static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset); -static SORT_ADDON_FIELD *get_addon_fields(ulong max_length_for_sort_data, - Field **ptabfield, - uint sortlength, +static SORT_ADDON_FIELD *get_addon_fields(TABLE *table, uint sortlength, LEX_STRING *addon_buf); static void unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff, uchar *buff_end); @@ -71,7 +69,6 @@ static bool check_if_pq_applicable(Sort_param *param, SORT_INFO *info, ha_rows records, size_t memory_available); void Sort_param::init_for_filesort(uint sortlen, TABLE *table, - ulong max_length_for_sort_data, ha_rows maxrows, bool sort_positions) { DBUG_ASSERT(addon_field == 0 && addon_buf.length == 0); @@ -85,8 +82,7 @@ void Sort_param::init_for_filesort(uint sortlen, TABLE *table, Get the descriptors of all fields whose values are appended to sorted fields and get its total length in addon_buf.length */ - addon_field= get_addon_fields(max_length_for_sort_data, - table->field, sort_length, &addon_buf); + addon_field= get_addon_fields(table, sort_length, &addon_buf); } if (addon_field) { @@ -190,9 +186,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, param.init_for_filesort(sortlength(thd, filesort->sortorder, s_length, &multi_byte_charset), - table, - thd->variables.max_length_for_sort_data, - max_rows, filesort->sort_positions); + table, max_rows, filesort->sort_positions); sort->addon_buf= param.addon_buf; sort->addon_field= param.addon_field; @@ -258,7 +252,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, } if (memory_available < min_sort_memory) { - my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR + ME_FATALERROR)); + my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR_LOG + ME_FATAL)); goto err; } tracker->report_sort_buffer_size(sort->sort_buffer_size()); @@ -710,7 +704,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, uchar *ref_pos, *next_pos, ref_buff[MAX_REFLENGTH]; TABLE *sort_form; handler *file; - MY_BITMAP *save_read_set, *save_write_set, *save_vcol_set; + MY_BITMAP *save_read_set, *save_write_set; Item *sort_cond; ha_rows retval; DBUG_ENTER("find_all_keys"); @@ -745,13 +739,11 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, /* Remember original bitmaps */ save_read_set= sort_form->read_set; save_write_set= sort_form->write_set; - save_vcol_set= sort_form->vcol_set; /* Set up temporary column read map for columns used by sort */ DBUG_ASSERT(save_read_set != &sort_form->tmp_set); bitmap_clear_all(&sort_form->tmp_set); - sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set, - &sort_form->tmp_set); + sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set); register_used_fields(param); if (quick_select) select->quick->add_used_key_part_to_set(); @@ -809,16 +801,12 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, */ MY_BITMAP *tmp_read_set= sort_form->read_set; MY_BITMAP *tmp_write_set= sort_form->write_set; - MY_BITMAP *tmp_vcol_set= sort_form->vcol_set; if (select->cond->with_subquery()) - sort_form->column_bitmaps_set(save_read_set, save_write_set, - save_vcol_set); + sort_form->column_bitmaps_set(save_read_set, save_write_set); write_record= (select->skip_record(thd) > 0); if (select->cond->with_subquery()) - sort_form->column_bitmaps_set(tmp_read_set, - tmp_write_set, - tmp_vcol_set); + sort_form->column_bitmaps_set(tmp_read_set, tmp_write_set); } else write_record= true; @@ -864,7 +852,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, } /* Signal we should use orignal column read and write maps */ - sort_form->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set); + sort_form->column_bitmaps_set(save_read_set, save_write_set); if (unlikely(thd->is_error())) DBUG_RETURN(HA_POS_ERROR); @@ -872,8 +860,8 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos)); if (unlikely(error != HA_ERR_END_OF_FILE)) { - file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); // purecov: inspected - DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ + file->print_error(error,MYF(ME_ERROR_LOG)); + DBUG_RETURN(HA_POS_ERROR); } if (indexpos && idx && write_keys(param, fs_info, idx, buffpek_pointers, tempfile)) @@ -885,7 +873,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, DBUG_RETURN(retval); err: - sort_form->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set); + sort_form->column_bitmaps_set(save_read_set, save_write_set); DBUG_RETURN(HA_POS_ERROR); } /* find_all_keys */ @@ -1063,7 +1051,10 @@ Type_handler_temporal_result::make_sort_key(uchar *to, Item *item, Sort_param *param) const { MYSQL_TIME buf; - if (item->get_date_result(&buf, TIME_INVALID_DATES)) + // This is a temporal type. No nanoseconds. Rounding mode is not important. + DBUG_ASSERT(item->cmp_type() == TIME_RESULT); + static const Temporal::Options opt(TIME_INVALID_DATES, TIME_FRAC_NONE); + if (item->get_date_result(current_thd, &buf, opt)) { DBUG_ASSERT(item->maybe_null); DBUG_ASSERT(item->null_value); @@ -1077,6 +1068,28 @@ Type_handler_temporal_result::make_sort_key(uchar *to, Item *item, void +Type_handler_timestamp_common::make_sort_key(uchar *to, Item *item, + const SORT_FIELD_ATTR *sort_field, + Sort_param *param) const +{ + uint binlen= my_timestamp_binary_length(item->decimals); + Timestamp_or_zero_datetime_native_null native(current_thd, item); + if (native.is_null() || native.is_zero_datetime()) + { + // NULL or '0000-00-00 00:00:00' + bzero(to, item->maybe_null ? binlen + 1 : binlen); + } + else + { + DBUG_ASSERT(native.length() == binlen); + if (item->maybe_null) + *to++= 1; + memcpy((char *) to, native.ptr(), binlen); + } +} + + +void Type_handler::make_sort_key_longlong(uchar *to, bool maybe_null, bool null_value, @@ -1122,9 +1135,8 @@ Type_handler_decimal_result::make_sort_key(uchar *to, Item *item, } *to++= 1; } - my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to, - item->max_length - (item->decimals ? 1 : 0), - item->decimals); + dec_val->to_binary(to, item->max_length - (item->decimals ? 1 : 0), + item->decimals); } @@ -1884,6 +1896,15 @@ Type_handler_temporal_result::sortlength(THD *thd, void +Type_handler_timestamp_common::sortlength(THD *thd, + const Type_std_attributes *item, + SORT_FIELD_ATTR *sortorder) const +{ + sortorder->length= my_timestamp_binary_length(item->decimals); +} + + +void Type_handler_int_result::sortlength(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *sortorder) const @@ -1970,6 +1991,30 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, return length; } +bool filesort_use_addons(TABLE *table, uint sortlength, + uint *length, uint *fields, uint *null_fields) +{ + Field **pfield, *field; + *length= *fields= *null_fields= 0; + + for (pfield= table->field; (field= *pfield) ; pfield++) + { + if (!bitmap_is_set(table->read_set, field->field_index)) + continue; + if (field->flags & BLOB_FLAG) + return false; + (*length)+= field->max_packed_col_length(field->pack_length()); + if (field->maybe_null()) + (*null_fields)++; + (*fields)++; + } + if (!*fields) + return false; + (*length)+= (*null_fields+7)/8; + + return *length + sortlength < + table->in_use->variables.max_length_for_sort_data; +} /** Get descriptors of fields appended to sorted fields and @@ -1977,7 +2022,7 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, The function first finds out what fields are used in the result set. Then it calculates the length of the buffer to store the values of - these fields together with the value of sort values. + these fields together with the value of sort values. If the calculated length is not greater than max_length_for_sort_data the function allocates memory for an array of descriptors containing layouts for the values of the non-sorted fields in the buffer and @@ -1999,16 +2044,13 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, */ static SORT_ADDON_FIELD * -get_addon_fields(ulong max_length_for_sort_data, - Field **ptabfield, uint sortlength, LEX_STRING *addon_buf) +get_addon_fields(TABLE *table, uint sortlength, LEX_STRING *addon_buf) { Field **pfield; Field *field; SORT_ADDON_FIELD *addonf; - uint length= 0; - uint fields= 0; - uint null_fields= 0; - MY_BITMAP *read_set= (*ptabfield)->table->read_set; + uint length, fields, null_fields; + MY_BITMAP *read_set= table->read_set; DBUG_ENTER("get_addon_fields"); /* @@ -2017,40 +2059,28 @@ get_addon_fields(ulong max_length_for_sort_data, Note for future refinement: This this a too strong condition. Actually we need only the fields referred in the - result set. And for some of them it makes sense to use + result set. And for some of them it makes sense to use the values directly from sorted fields. But beware the case when item->cmp_type() != item->result_type() */ addon_buf->str= 0; addon_buf->length= 0; - for (pfield= ptabfield; (field= *pfield) ; pfield++) - { - if (!bitmap_is_set(read_set, field->field_index)) - continue; - if (field->flags & BLOB_FLAG) - DBUG_RETURN(0); - length+= field->max_packed_col_length(field->pack_length()); - if (field->maybe_null()) - null_fields++; - fields++; - } - if (!fields) - DBUG_RETURN(0); - length+= (null_fields+7)/8; + // see remove_const() for HA_SLOW_RND_POS explanation + if (table->file->ha_table_flags() & HA_SLOW_RND_POS) + sortlength= 0; - if (length+sortlength > max_length_for_sort_data || - !my_multi_malloc(MYF(MY_WME | MY_THREAD_SPECIFIC), - &addonf, sizeof(SORT_ADDON_FIELD) * (fields+1), - &addon_buf->str, length, - NullS)) + if (!filesort_use_addons(table, sortlength, &length, &fields, &null_fields) || + !my_multi_malloc(MYF(MY_WME | MY_THREAD_SPECIFIC), &addonf, + sizeof(SORT_ADDON_FIELD) * (fields+1), + &addon_buf->str, length, NullS)) DBUG_RETURN(0); addon_buf->length= length; length= (null_fields+7)/8; null_fields= 0; - for (pfield= ptabfield; (field= *pfield) ; pfield++) + for (pfield= table->field; (field= *pfield) ; pfield++) { if (!bitmap_is_set(read_set, field->field_index)) continue; @@ -2072,7 +2102,7 @@ get_addon_fields(ulong max_length_for_sort_data, addonf++; } addonf->field= 0; // Put end marker - + DBUG_PRINT("info",("addon_length: %d",length)); DBUG_RETURN(addonf-fields); } diff --git a/sql/filesort.h b/sql/filesort.h index bd1d81f91ef..359f44a3907 100644 --- a/sql/filesort.h +++ b/sql/filesort.h @@ -161,6 +161,9 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, Filesort_tracker* tracker, JOIN *join=NULL, table_map first_table_bit=0); +bool filesort_use_addons(TABLE *table, uint sortlength, + uint *length, uint *fields, uint *null_fields); + void change_double_for_sort(double nr,uchar *to); #endif /* FILESORT_INCLUDED */ diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 1349571a3f8..d566652f5f8 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5281,7 +5281,7 @@ bool ha_partition::init_record_priority_queue() /* Initialize priority queue, initialized to reading forward. */ int (*cmp_func)(void *, uchar *, uchar *); void *cmp_arg= (void*) this; - if (!m_using_extended_keys && !(table_flags() & HA_CMP_REF_IS_EXPENSIVE)) + if (!m_using_extended_keys && !(table_flags() & HA_SLOW_CMP_REF)) cmp_func= cmp_key_rowid_part_id; else cmp_func= cmp_key_part_id; @@ -6815,7 +6815,7 @@ FT_INFO *ha_partition::ft_init_ext(uint flags, uint inx, String *key) sizeof(FT_INFO *) * m_tot_parts, NullS))) { - my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL)); DBUG_RETURN(NULL); } ft_target->part_ft_info= tmp_ft_info; @@ -10689,8 +10689,6 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool do_repair) { /* Only need to read the partitioning fields. */ bitmap_union(table->read_set, &m_part_info->full_part_field_set); - if (table->vcol_set) - bitmap_union(table->vcol_set, &m_part_info->full_part_field_set); } if ((result= m_file[read_part_id]->ha_rnd_init(1))) diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 202f27840dc..f79d71a7355 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1040,10 +1040,6 @@ public: with hidden primary key) (No handler has this limitation currently) - HA_WANTS_PRIMARY_KEY: - Can't define a table without primary key except sequences - (Only InnoDB has this when using innodb_force_primary_key == ON) - HA_STATS_RECORDS_IS_EXACT: Does the counter of records after the info call specify an exact value or not. If it does this flag is set. diff --git a/sql/handle_connections_win.cc b/sql/handle_connections_win.cc new file mode 100644 index 00000000000..b37b4dedad1 --- /dev/null +++ b/sql/handle_connections_win.cc @@ -0,0 +1,555 @@ +/* Copyright (c) 2018 MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +/* Accepting connections on Windows */ + +#include <my_global.h> +#include <sql_class.h> +#include <sql_connect.h> +#include <mysqld.h> +#include <mswsock.h> +#include <mysql/psi/mysql_socket.h> +#include <sddl.h> + +#include <handle_connections_win.h> + +/* From mysqld.cc */ +extern HANDLE hEventShutdown; +extern MYSQL_SOCKET base_ip_sock, extra_ip_sock; +extern PTP_CALLBACK_ENVIRON get_threadpool_win_callback_environ(); +extern void tp_win_callback_prolog(); +static SECURITY_ATTRIBUTES pipe_security; + +/** + Abstract base class for accepting new connection, + asynchronously (i.e the accept() operation can be posted, + and result is retrieved later) , and creating a new connection. +*/ + +struct Listener +{ + /** Windows handle of the Listener. + Subclasses would use SOCKET or named pipe handle + */ + HANDLE m_handle; + /** Required for all async IO*/ + OVERLAPPED m_overlapped; + + /** Create new listener + @param handle - @see m_handle + @param wait_handle - usually, event handle or INVALID_HANDLE_VALUE + @see wait_handle + */ + Listener(HANDLE handle, HANDLE wait_handle): + m_handle(handle), m_overlapped() + { + m_overlapped.hEvent= wait_handle; + } + + /** + if not NULL, this handle can be be used in WaitForSingle/MultipleObject(s). + This handle will be closed when object is destroyed. + + If NULL, the completion notification happens in threadpool. + */ + HANDLE wait_handle() + { + return m_overlapped.hEvent; + } + + /* Start waiting for new client connection. */ + virtual void begin_accept()= 0; + + /** + Completion callback,called whenever IO posted by begin_accept is finisjed + Listener needs to create a new THD then (or, call scheduler so it creates one) + + @param success - whether IO completed successfull + */ + virtual void completion_callback(bool success)= 0; + + /** + Completion callback for Listener, that uses events for waiting + to IO. Not suitable for threadpool etc. Retrieves the status of + completed IO from the OVERLAPPED structure + */ + void completion_callback() + { + DBUG_ASSERT(wait_handle() && (wait_handle() != INVALID_HANDLE_VALUE)); + DWORD bytes; + return completion_callback( + GetOverlappedResult(wait_handle(), &m_overlapped, &bytes, FALSE)); + } + + /** Cancel an in-progress IO. Useful for threadpool-bound IO */ + void cancel() + { + CancelIoEx(m_handle, &m_overlapped); + } + + /* Destructor. Closes wait handle, if it was passed in constructor */ + virtual ~Listener() + { + if (m_overlapped.hEvent) + CloseHandle(m_overlapped.hEvent); + }; +}; + +/* Winsock extension finctions. */ +static LPFN_ACCEPTEX my_AcceptEx; +static LPFN_GETACCEPTEXSOCKADDRS my_GetAcceptExSockaddrs; + +/** + Listener that handles socket connections. + Can be threadpool-bound (i.e the completion is executed in threadpool thread), + or use events for waits. + + Threadpool-bound listener should be used with theradpool scheduler, for better + performance. +*/ +struct Socket_Listener: public Listener +{ + /** Client socket passed to AcceptEx() call.*/ + SOCKET m_client_socket; + + /** Buffer for sockaddrs passed to AcceptEx()/GetAcceptExSockaddrs() */ + char m_buffer[2 * sizeof(sockaddr_storage) + 32]; + + /* Threadpool IO struct.*/ + PTP_IO m_tp_io; + + /** + Callback for Windows threadpool's StartThreadpoolIo() function. + */ + static void CALLBACK tp_accept_completion_callback( + PTP_CALLBACK_INSTANCE, PVOID context, PVOID , ULONG io_result, + ULONG_PTR, PTP_IO io) + { + tp_win_callback_prolog(); + Listener *listener= (Listener *)context; + + if (io_result == ERROR_OPERATION_ABORTED) + { + /* ERROR_OPERATION_ABORTED caused by CancelIoEx()*/ + CloseThreadpoolIo(io); + delete listener; + return; + } + listener->completion_callback(io_result == 0); + } + + /** + Constructor + @param listen_socket - listening socket + @PTP_CALLBACK_ENVIRON callback_environ - threadpool environment, or NULL + if threadpool is not used for completion callbacks. + */ + Socket_Listener(MYSQL_SOCKET listen_socket, PTP_CALLBACK_ENVIRON callback_environ) : + Listener((HANDLE)listen_socket.fd,0), + m_client_socket(INVALID_SOCKET) + { + if (callback_environ) + { + /* Accept executed in threadpool. */ + m_tp_io= CreateThreadpoolIo(m_handle, + tp_accept_completion_callback, this, callback_environ); + } + else + { + /* Completion signaled via event. */ + m_tp_io= 0; + m_overlapped.hEvent= CreateEvent(0, FALSE , FALSE, 0); + } + } + + /* + Use AcceptEx to asynchronously wait for new connection; + */ + void begin_accept() + { +retry : + m_client_socket= socket(server_socket_ai_family, SOCK_STREAM, IPPROTO_TCP); + if (m_client_socket == INVALID_SOCKET) + { + sql_perror("socket() call failed."); + unireg_abort(1); + } + + DWORD bytes_received; + if (m_tp_io) + StartThreadpoolIo(m_tp_io); + + BOOL ret= my_AcceptEx( + (SOCKET)m_handle, + m_client_socket, + m_buffer, + 0, + sizeof(sockaddr_storage) + 16, + sizeof(sockaddr_storage) + 16, + &bytes_received, + &m_overlapped); + + DWORD last_error= ret? 0: WSAGetLastError(); + if (last_error == WSAECONNRESET) + { + if (m_tp_io) + CancelThreadpoolIo(m_tp_io); + goto retry; + } + + if (ret || last_error == ERROR_IO_PENDING || abort_loop) + return; + + sql_print_error("my_AcceptEx failed, last error %u", last_error); + abort(); + } + + /* Create new socket connection.*/ + void completion_callback(bool success) + { + if (!success) + { + /* my_AcceptEx() returned error */ + closesocket(m_client_socket); + begin_accept(); + return; + } + + MYSQL_SOCKET s_client{m_client_socket}; + MYSQL_SOCKET s_listen{(SOCKET)m_handle}; + +#ifdef HAVE_PSI_SOCKET_INTERFACE + /* Parse socket addresses buffer filled by AcceptEx(), + only needed for PSI instrumentation. */ + sockaddr *local_addr, *remote_addr; + int local_addr_len, remote_addr_len; + + my_GetAcceptExSockaddrs(m_buffer, + 0, sizeof(sockaddr_storage) + 16, sizeof(sockaddr_storage) + 16, + &local_addr, &local_addr_len, &remote_addr, &remote_addr_len); + + s_client.m_psi= PSI_SOCKET_CALL(init_socket) + (key_socket_client_connection, (const my_socket*)&s_listen.fd, remote_addr, remote_addr_len); +#endif + + /* Start accepting new connection. After this point, do not use + any member data, they could be used by a different (threadpool) thread. */ + begin_accept(); + + /* Some chores post-AcceptEx() that we need to create a normal socket.*/ + if (setsockopt(s_client.fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, + (char *)&s_listen.fd, sizeof(s_listen.fd))) + { + if (!abort_loop) + { + sql_perror("setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed."); + abort(); + } + } + + /* Create a new connection.*/ + handle_accepted_socket(s_client, s_listen); + } + + ~Socket_Listener() + { + if (m_client_socket != INVALID_SOCKET) + closesocket(m_client_socket); + } + + /* + Retrieve the pointer to the Winsock extension functions + AcceptEx and GetAcceptExSockaddrs. + */ + static void init_winsock_extensions() + { + SOCKET s= mysql_socket_getfd(base_ip_sock); + if (s == INVALID_SOCKET) + s= mysql_socket_getfd(extra_ip_sock); + if (s == INVALID_SOCKET) + { + /* --skip-networking was used*/ + return; + } + GUID guid_AcceptEx= WSAID_ACCEPTEX; + GUID guid_GetAcceptExSockaddrs= WSAID_GETACCEPTEXSOCKADDRS; + + GUID *guids[]= { &guid_AcceptEx, &guid_GetAcceptExSockaddrs }; + void *funcs[]= { &my_AcceptEx, &my_GetAcceptExSockaddrs }; + DWORD bytes; + for (int i= 0; i < array_elements(guids); i++) + { + if (WSAIoctl(s, + SIO_GET_EXTENSION_FUNCTION_POINTER, + guids[i], sizeof(GUID), + funcs[i], sizeof(void *), + &bytes, 0, 0) == -1) + { + sql_print_error("WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER) failed"); + unireg_abort(1); + } + } + } +}; + + +/** + Pipe Listener. + Only event notification mode is implemented, no threadpool +*/ +struct Pipe_Listener : public Listener +{ + PTP_CALLBACK_ENVIRON m_tp_env; + Pipe_Listener(): + Listener(INVALID_HANDLE_VALUE, CreateEvent(0, FALSE, FALSE, 0)), + m_tp_env(get_threadpool_win_callback_environ()) + { + } + + /* + Creates local named pipe instance \\.\pipe\$socket for named pipe connection. + */ + static HANDLE create_named_pipe() + { + static bool first_instance= true; + static char pipe_name[512]; + DWORD open_mode= PIPE_ACCESS_DUPLEX | + FILE_FLAG_OVERLAPPED; + + if (first_instance) + { + snprintf(pipe_name, sizeof(pipe_name), "\\\\.\\pipe\\%s", mysqld_unix_port); + open_mode |= FILE_FLAG_FIRST_PIPE_INSTANCE; + if (!ConvertStringSecurityDescriptorToSecurityDescriptorA( + "S:(ML;; NW;;; LW) D:(A;; FRFW;;; WD)", + 1, &pipe_security.lpSecurityDescriptor, NULL)) + { + sql_perror("Can't start server : Initialize security descriptor"); + unireg_abort(1); + } + pipe_security.nLength= sizeof(SECURITY_ATTRIBUTES); + pipe_security.bInheritHandle= FALSE; + } + HANDLE pipe_handle= CreateNamedPipe(pipe_name, + open_mode, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, + (int)global_system_variables.net_buffer_length, + (int)global_system_variables.net_buffer_length, + NMPWAIT_USE_DEFAULT_WAIT, + &pipe_security); + if (pipe_handle == INVALID_HANDLE_VALUE) + { + sql_perror("Create named pipe failed"); + sql_print_error("Aborting\n"); + exit(1); + } + first_instance= false; + return pipe_handle; + } + + static void create_pipe_connection(HANDLE pipe) + { + CONNECT *connect; + if (!(connect= new CONNECT) || !(connect->vio= vio_new_win32pipe(pipe))) + { + CloseHandle(pipe); + delete connect; + statistic_increment(aborted_connects, &LOCK_status); + statistic_increment(connection_errors_internal, &LOCK_status); + return; + } + connect->host= my_localhost; + create_new_thread(connect); + } + + /* Threadpool callback.*/ + static void CALLBACK tp_create_pipe_connection( + PTP_CALLBACK_INSTANCE,void *Context) + { + tp_win_callback_prolog(); + create_pipe_connection(Context); + } + + void begin_accept() + { + m_handle= create_named_pipe(); + BOOL connected= ConnectNamedPipe(m_handle, &m_overlapped); + if (connected) + { + /* Overlapped ConnectNamedPipe should return zero. */ + sql_perror("Overlapped ConnectNamedPipe() already connected."); + abort(); + } + DWORD last_error= GetLastError(); + switch (last_error) + { + case ERROR_PIPE_CONNECTED: + /* Client is already connected, so signal an event.*/ + { + /* + Cleanup overlapped (so that subsequent GetOverlappedResult() + does not show results of previous IO + */ + HANDLE e= m_overlapped.hEvent; + memset(&m_overlapped, 0, sizeof(m_overlapped)); + m_overlapped.hEvent = e; + } + if (!SetEvent(m_overlapped.hEvent)) + { + sql_perror("SetEvent() failed for connected pipe."); + abort(); + } + break; + case ERROR_IO_PENDING: + break; + default: + sql_perror("ConnectNamedPipe() failed."); + abort(); + break; + } + } + + void completion_callback(bool success) + { + if (!success) + { +#ifdef DBUG_OFF + sql_print_warning("ConnectNamedPipe completed with %u", GetLastError()); +#endif + CloseHandle(m_handle); + m_handle= INVALID_HANDLE_VALUE; + begin_accept(); + return; + } + HANDLE pipe= m_handle; + begin_accept(); + // If threadpool is on, create connection in threadpool thread + if (!m_tp_env || !TrySubmitThreadpoolCallback(tp_create_pipe_connection, pipe, m_tp_env)) + create_pipe_connection(pipe); + } + + ~Pipe_Listener() + { + if (m_handle != INVALID_HANDLE_VALUE) + { + CloseHandle(m_handle); + } + } + + static void cleanup() + { + LocalFree(pipe_security.lpSecurityDescriptor); + } +}; + +/** + Accept new client connections on Windows. + + Since we deal with pipe and sockets, they cannot be put into a select/loop. + But we can use asynchronous IO, and WaitForMultipleObject() loop. + + In addition, for slightly better performance, if we're using threadpool, + socket connections are accepted directly in the threadpool. + + The mode of operation is therefore + + 1. There is WaitForMultipleObject() loop that waits for shutdown notification + (hEventShutdown),and possibly pipes and sockets(e.g if threadpool is not used) + This loop ends when shutdown notification is detected. + + 2. If threadpool is used, new socket connections are accepted there. +*/ + + +#define MAX_WAIT_HANDLES 32 +#define NUM_PIPE_LISTENERS 24 +#define SHUTDOWN_IDX 0 +#define LISTENER_START_IDX 1 + +void handle_connections_win() +{ + Listener* all_listeners[MAX_WAIT_HANDLES]= {}; + HANDLE wait_events[MAX_WAIT_HANDLES]= {}; + int n_listeners= 0; + int n_waits= 0; + + Socket_Listener::init_winsock_extensions(); + + /* Listen for TCP connections on "extra-port" (no threadpool).*/ + if (extra_ip_sock.fd != INVALID_SOCKET) + all_listeners[n_listeners++]= new Socket_Listener(extra_ip_sock, 0); + + /* Listen for named pipe connections */ + if (mysqld_unix_port[0] && !opt_bootstrap && opt_enable_named_pipe) + { + /* + Use several listeners for pipe, to reduce ERROR_PIPE_BUSY on client side. + */ + for (int i= 0; i < NUM_PIPE_LISTENERS; i++) + all_listeners[n_listeners++]= new Pipe_Listener(); + } + + if (base_ip_sock.fd != INVALID_SOCKET) + { + /* Wait for TCP connections.*/ + SetFileCompletionNotificationModes((HANDLE)base_ip_sock.fd, FILE_SKIP_SET_EVENT_ON_HANDLE); + all_listeners[n_listeners++]= new Socket_Listener(base_ip_sock, get_threadpool_win_callback_environ()); + } + + if (!n_listeners && !opt_bootstrap) + { + sql_print_error("Either TCP connections or named pipe connections must be enabled."); + unireg_abort(1); + } + + wait_events[SHUTDOWN_IDX]= hEventShutdown; + n_waits = 1; + + for (int i= 0; i < n_listeners; i++) + { + HANDLE wait_handle= all_listeners[i]->wait_handle(); + if(wait_handle) + { + DBUG_ASSERT((i == 0) || (all_listeners[i-1]->wait_handle() != 0)); + wait_events[n_waits++]= wait_handle; + } + all_listeners[i]->begin_accept(); + } + + for (;;) + { + DWORD idx = WaitForMultipleObjects(n_waits ,wait_events, FALSE, INFINITE); + DBUG_ASSERT((int)idx >= 0 && (int)idx < n_waits); + + if (idx == SHUTDOWN_IDX) + break; + + all_listeners[idx - LISTENER_START_IDX]->completion_callback(); + } + + /* Cleanup */ + for (int i= 0; i < n_listeners; i++) + { + Listener *listener= all_listeners[i]; + if (listener->wait_handle()) + delete listener; + else + // Threadpool-bound listener will be deleted in threadpool + // Do not call destructor, because callback maybe running. + listener->cancel(); + } + Pipe_Listener::cleanup(); +}
\ No newline at end of file diff --git a/sql/handle_connections_win.h b/sql/handle_connections_win.h new file mode 100644 index 00000000000..a81f4346fb2 --- /dev/null +++ b/sql/handle_connections_win.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2018 MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + +/** + Handles incoming socket and pipe connections, on Windows. + Creates new (THD) connections.. +*/ +extern void handle_connections_win(); diff --git a/sql/handler.cc b/sql/handler.cc index 897d468f2ba..001055cd475 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -296,7 +296,7 @@ handler *get_ha_partition(partition_info *part_info) } else { - my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), + my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), static_cast<int>(sizeof(ha_partition))); } DBUG_RETURN(((handler*) partition)); @@ -683,7 +683,7 @@ int ha_init() binary log (which is considered a transaction-capable storage engine in counting total_ha) */ - opt_using_transactions= total_ha>(ulong)opt_bin_log; + opt_using_transactions= total_ha > (ulong) opt_bin_log; savepoint_alloc_size+= sizeof(SAVEPOINT); DBUG_RETURN(error); } @@ -693,7 +693,6 @@ int ha_end() int error= 0; DBUG_ENTER("ha_end"); - /* This should be eventualy based on the graceful shutdown flag. So if flag is equal to HA_PANIC_CLOSE, the deallocate @@ -823,6 +822,43 @@ void ha_kill_query(THD* thd, enum thd_kill_levels level) } +/***************************************************************************** + Backup functions +******************************************************************************/ + +static my_bool plugin_prepare_for_backup(THD *unused1, plugin_ref plugin, + void *not_used) +{ + handlerton *hton= plugin_hton(plugin); + if (hton->state == SHOW_OPTION_YES && hton->prepare_for_backup) + hton->prepare_for_backup(); + return FALSE; +} + +void ha_prepare_for_backup() +{ + plugin_foreach_with_mask(0, plugin_prepare_for_backup, + MYSQL_STORAGE_ENGINE_PLUGIN, + PLUGIN_IS_DELETED|PLUGIN_IS_READY, 0); +} + +static my_bool plugin_end_backup(THD *unused1, plugin_ref plugin, + void *not_used) +{ + handlerton *hton= plugin_hton(plugin); + if (hton->state == SHOW_OPTION_YES && hton->end_backup) + hton->end_backup(); + return FALSE; +} + +void ha_end_backup() +{ + plugin_foreach_with_mask(0, plugin_end_backup, + MYSQL_STORAGE_ENGINE_PLUGIN, + PLUGIN_IS_DELETED|PLUGIN_IS_READY, 0); +} + + /* ======================================================================== ======================= TRANSACTIONS ===================================*/ @@ -1395,8 +1431,7 @@ int ha_commit_trans(THD *thd, bool all) We allow the owner of FTWRL to COMMIT; we assume that it knows what it does. */ - mdl_request.init(MDL_key::COMMIT, "", "", MDL_INTENTION_EXCLUSIVE, - MDL_EXPLICIT); + mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT, MDL_EXPLICIT); if (!WSREP(thd) && thd->mdl_context.acquire_lock(&mdl_request, @@ -2544,7 +2579,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, dummy_share.table_name= *alias; dummy_table.alias.set(alias->str, alias->length, table_alias_charset); file->change_table_ptr(&dummy_table, &dummy_share); - file->print_error(error, MYF(intercept ? ME_JUST_WARNING : 0)); + file->print_error(error, MYF(intercept ? ME_WARNING : 0)); } if (intercept) error= 0; @@ -3601,7 +3636,7 @@ void handler::print_error(int error, myf errflag) if (ha_thd()->transaction_rollback_request) { /* Ensure this becomes a true error */ - errflag&= ~(ME_JUST_WARNING | ME_JUST_INFO); + errflag&= ~(ME_WARNING | ME_NOTE); } int textno= -1; // impossible value @@ -3736,14 +3771,14 @@ void handler::print_error(int error, myf errflag) { textno=ER_RECORD_FILE_FULL; /* Write the error message to error log */ - errflag|= ME_NOREFRESH; + errflag|= ME_ERROR_LOG; break; } case HA_ERR_INDEX_FILE_FULL: { textno=ER_INDEX_FILE_FULL; /* Write the error message to error log */ - errflag|= ME_NOREFRESH; + errflag|= ME_ERROR_LOG; break; } case HA_ERR_LOCK_WAIT_TIMEOUT: @@ -3870,14 +3905,14 @@ void handler::print_error(int error, myf errflag) if (unlikely(fatal_error)) { /* Ensure this becomes a true error */ - errflag&= ~(ME_JUST_WARNING | ME_JUST_INFO); + errflag&= ~(ME_WARNING | ME_NOTE); if ((debug_assert_if_crashed_table || global_system_variables.log_warnings > 1)) { /* Log error to log before we crash or if extended warnings are requested */ - errflag|= ME_NOREFRESH; + errflag|= ME_ERROR_LOG; } } @@ -4049,7 +4084,8 @@ static bool update_frm_version(TABLE *table) int4store(version, MYSQL_VERSION_ID); - if ((result= (int)mysql_file_pwrite(file, (uchar*) version, 4, 51L, MYF_RW))) + if ((result= (int)mysql_file_pwrite(file, (uchar*) version, 4, 51L, + MYF(MY_WME+MY_NABP)))) goto err; table->s->mysql_version= MYSQL_VERSION_ID; @@ -4971,7 +5007,7 @@ int ha_create_table(THD *thd, const char *path, { if (!thd->is_error()) my_error(ER_CANT_CREATE_TABLE, MYF(0), db, table_name, error); - table.file->print_error(error, MYF(ME_JUST_WARNING)); + table.file->print_error(error, MYF(ME_WARNING)); PSI_CALL_drop_table_share(temp_table, share.db.str, (uint)share.db.length, share.table_name.str, (uint)share.table_name.length); } @@ -6869,6 +6905,10 @@ int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info) DBUG_RETURN(res); } +/***************************************************************************** + VERSIONING functions +******************************************************************************/ + bool Vers_parse_info::is_start(const char *name) const { DBUG_ASSERT(name); diff --git a/sql/handler.h b/sql/handler.h index 788ac4dd474..a0739d75aaf 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -115,7 +115,13 @@ enum enum_alter_inplace_result { #define HA_NO_BLOBS (1ULL << 9) /* Doesn't support blobs */ #define HA_CAN_INDEX_BLOBS (1ULL << 10) #define HA_AUTO_PART_KEY (1ULL << 11) /* auto-increment in multi-part key */ -#define HA_REQUIRE_PRIMARY_KEY (1ULL << 12) /* .. and can't create a hidden one */ +/* + The engine requires every table to have a user-specified PRIMARY KEY. + Do not set the flag if the engine can generate a hidden primary key internally. + This flag is ignored if a SEQUENCE is created (which, in turn, needs + HA_CAN_TABLES_WITHOUT_ROLLBACK flag) +*/ +#define HA_REQUIRE_PRIMARY_KEY (1ULL << 12) #define HA_STATS_RECORDS_IS_EXACT (1ULL << 13) /* stats.records is exact */ /* INSERT_DELAYED only works with handlers that uses MySQL internal table @@ -299,10 +305,19 @@ enum enum_alter_inplace_result { #define HA_CAN_MULTISTEP_MERGE (1LL << 53) /* calling cmp_ref() on the engine is expensive */ -#define HA_CMP_REF_IS_EXPENSIVE (1ULL << 54) +#define HA_SLOW_CMP_REF (1ULL << 54) +#define HA_CMP_REF_IS_EXPENSIVE HA_SLOW_CMP_REF + +/** + Some engines are unable to provide an efficient implementation for rnd_pos(). + Server will try to avoid it, if possible -/* Engine wants primary keys for everything except sequences */ -#define HA_WANTS_PRIMARY_KEY (1ULL << 55) + TODO better to do it with cost estimates, not with an explicit flag +*/ +#define HA_SLOW_RND_POS (1ULL << 55) + +/* Safe for online backup */ +#define HA_CAN_ONLINE_BACKUPS (1ULL << 56) /* bits in index_flags(index_number) for what you can do with index */ #define HA_READ_NEXT 1 /* TODO really use this flag */ @@ -1601,6 +1616,10 @@ struct handlerton @return transaction commit ID @retval 0 if no system-versioned data was affected by the transaction */ ulonglong (*prepare_commit_versioned)(THD *thd, ulonglong *trx_id); + + /* backup */ + void (*prepare_for_backup)(void); + void (*end_backup)(void); }; @@ -3253,7 +3272,7 @@ public: /* True if changes to the table is persistent (no rollback) - This is manly used to decide how to log changes to the table in + This is mainly used to decide how to log changes to the table in the binary log. */ bool has_transactions() @@ -4664,6 +4683,7 @@ public: { DBUG_ASSERT(ht); return partition_ht()->flags & HTON_NATIVE_SYS_VERSIONING; } virtual void update_partition(uint part_id) {} + protected: Handler_share *get_ha_share_ptr(); void set_ha_share_ptr(Handler_share *arg_ha_share); @@ -4742,6 +4762,8 @@ int ha_create_table(THD *thd, const char *path, HA_CREATE_INFO *create_info, LEX_CUSTRING *frm); int ha_delete_table(THD *thd, handlerton *db_type, const char *path, const LEX_CSTRING *db, const LEX_CSTRING *alias, bool generate_warning); +void ha_prepare_for_backup(); +void ha_end_backup(); /* statistics and info */ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat); diff --git a/sql/init.h b/sql/init.h index e8dec0c1e2e..e96bb478cee 100644 --- a/sql/init.h +++ b/sql/init.h @@ -17,6 +17,6 @@ #define INIT_INCLUDED void unireg_init(ulong options); -ATTRIBUTE_NORETURN void unireg_end(void); +void unireg_end(void); #endif /* INIT_INCLUDED */ diff --git a/sql/item.cc b/sql/item.cc index a26f1eac5ba..ed9c78e5525 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -115,63 +115,20 @@ void Item::push_note_converted_to_positive_complement(THD *thd) } -longlong Item::val_datetime_packed_result() +longlong Item::val_datetime_packed_result(THD *thd) { MYSQL_TIME ltime, tmp; - if (get_date_result(<ime, TIME_FUZZY_DATES | TIME_INVALID_DATES)) + if (get_date_result(thd, <ime, Datetime::Options_cmp(thd))) return 0; if (ltime.time_type != MYSQL_TIMESTAMP_TIME) return pack_time(<ime); - if ((null_value= time_to_datetime_with_warn(current_thd, <ime, &tmp, 0))) + if ((null_value= time_to_datetime_with_warn(thd, <ime, &tmp, + TIME_CONV_NONE))) return 0; return pack_time(&tmp); } -/** - Get date/time/datetime. - If DATETIME or DATE result is returned, it's converted to TIME. -*/ -bool Item::get_time_with_conversion(THD *thd, MYSQL_TIME *ltime, - ulonglong fuzzydate) -{ - if (get_date(ltime, fuzzydate)) - return true; - if (ltime->time_type != MYSQL_TIMESTAMP_TIME) - { - MYSQL_TIME ltime2; - if ((thd->variables.old_behavior & OLD_MODE_ZERO_DATE_TIME_CAST) && - (ltime->year || ltime->day || ltime->month)) - { - /* - Old mode conversion from DATETIME with non-zero YYYYMMDD part - to TIME works very inconsistently. Possible variants: - - truncate the YYYYMMDD part - - add (MM*33+DD)*24 to hours - - add (MM*31+DD)*24 to hours - Let's return TRUE here, to disallow equal field propagation. - Note, If we start to use this method in more pieces of the code other - than equal field propagation, we should probably return - TRUE only if some flag in fuzzydate is set. - */ - return true; - } - if (datetime_to_time_with_warn(thd, ltime, <ime2, TIME_SECOND_PART_DIGITS)) - { - /* - If the time difference between CURRENT_DATE and ltime - did not fit into the supported TIME range, then we set the - difference to the maximum possible value in the supported TIME range - */ - DBUG_ASSERT(0); - return (null_value= true); - } - *ltime= ltime2; - } - return false; -} - - /* For the items which don't have its own fast val_str_ascii() implementation we provide a generic slower version, @@ -253,36 +210,6 @@ String *Item::val_string_from_int(String *str) } -String *Item::val_string_from_decimal(String *str) -{ - my_decimal dec_buf, *dec= val_decimal(&dec_buf); - if (null_value) - return 0; - my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, FALSE, &dec_buf); - my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, 0, 0, 0, str); - return str; -} - - -/* - All val_xxx_from_date() must call this method, to expose consistent behaviour - regarding SQL_MODE when converting DATE/DATETIME to other data types. -*/ -bool Item::get_temporal_with_sql_mode(MYSQL_TIME *ltime) -{ - return get_date(ltime, field_type() == MYSQL_TYPE_TIME - ? TIME_TIME_ONLY - : sql_mode_for_dates(current_thd)); -} - - -bool Item::is_null_from_temporal() -{ - MYSQL_TIME ltime; - return get_temporal_with_sql_mode(<ime); -} - - longlong Item::val_int_from_str(int *error) { char buff[MAX_FIELD_WIDTH]; @@ -333,21 +260,6 @@ longlong Item::val_int_unsigned_typecast_from_int() } -String *Item::val_string_from_date(String *str) -{ - MYSQL_TIME ltime; - if (get_temporal_with_sql_mode(<ime) || - str->alloc(MAX_DATE_STRING_REP_LENGTH)) - { - null_value= 1; - return (String *) 0; - } - str->length(my_TIME_to_str(<ime, const_cast<char*>(str->ptr()), decimals)); - str->set_charset(&my_charset_numeric); - return str; -} - - my_decimal *Item::val_decimal_from_real(my_decimal *decimal_value) { double nr= val_real(); @@ -379,93 +291,10 @@ my_decimal *Item::val_decimal_from_string(my_decimal *decimal_value) } -my_decimal *Item::val_decimal_from_date(my_decimal *decimal_value) -{ - DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - if (get_temporal_with_sql_mode(<ime)) - { - my_decimal_set_zero(decimal_value); - null_value= 1; // set NULL, stop processing - return 0; - } - return date2my_decimal(<ime, decimal_value); -} - - -my_decimal *Item::val_decimal_from_time(my_decimal *decimal_value) -{ - DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - if (get_time(<ime)) - { - my_decimal_set_zero(decimal_value); - return 0; - } - return date2my_decimal(<ime, decimal_value); -} - - -longlong Item::val_int_from_date() -{ - DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - if (get_temporal_with_sql_mode(<ime)) - return 0; - longlong v= TIME_to_ulonglong(<ime); - return ltime.neg ? -v : v; -} - - -double Item::val_real_from_date() -{ - DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - if (get_temporal_with_sql_mode(<ime)) - return 0; - return TIME_to_double(<ime); -} - - -double Item::val_real_from_decimal() -{ - /* Note that fix_fields may not be called for Item_avg_field items */ - double result; - my_decimal value_buff, *dec_val= val_decimal(&value_buff); - if (null_value) - return 0.0; - my_decimal2double(E_DEC_FATAL_ERROR, dec_val, &result); - return result; -} - - -longlong Item::val_int_from_decimal() -{ - /* Note that fix_fields may not be called for Item_avg_field items */ - longlong result; - my_decimal value, *dec_val= val_decimal(&value); - if (null_value) - return 0; - my_decimal2int(E_DEC_FATAL_ERROR, dec_val, unsigned_flag, &result); - return result; -} - - -longlong Item::val_int_unsigned_typecast_from_decimal() -{ - longlong result; - my_decimal tmp, *dec= val_decimal(&tmp); - if (null_value) - return 0; - my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &result); - return result; -} - - int Item::save_time_in_field(Field *field, bool no_conversions) { MYSQL_TIME ltime; - if (get_time(<ime)) + if (get_time(field->table->in_use, <ime)) return set_field_to_null_with_conversions(field, no_conversions); field->set_notnull(); return field->store_time_dec(<ime, decimals); @@ -475,7 +304,8 @@ int Item::save_time_in_field(Field *field, bool no_conversions) int Item::save_date_in_field(Field *field, bool no_conversions) { MYSQL_TIME ltime; - if (get_date(<ime, sql_mode_for_dates(field->table->in_use))) + THD *thd= field->table->in_use; + if (get_date(thd, <ime, Datetime::Options(thd))) return set_field_to_null_with_conversions(field, no_conversions); field->set_notnull(); return field->store_time_dec(<ime, decimals); @@ -515,11 +345,11 @@ int Item::save_str_value_in_field(Field *field, String *result) Item::Item(THD *thd): is_expensive_cache(-1), rsize(0), name(null_clex_str), orig_name(0), - fixed(0), is_autogenerated_name(TRUE) + is_autogenerated_name(TRUE) { DBUG_ASSERT(thd); marker= 0; - maybe_null=null_value=with_sum_func=with_window_func=with_field=0; + maybe_null= null_value= with_window_func= with_field= false; in_rollup= 0; with_param= 0; @@ -572,11 +402,9 @@ Item::Item(THD *thd, Item *item): maybe_null(item->maybe_null), in_rollup(item->in_rollup), null_value(item->null_value), - with_sum_func(item->with_sum_func), with_param(item->with_param), with_window_func(item->with_window_func), with_field(item->with_field), - fixed(item->fixed), is_autogenerated_name(item->is_autogenerated_name) { next= thd->free_list; // Put in free list @@ -646,7 +474,6 @@ void Item::cleanup() { DBUG_ENTER("Item::cleanup"); DBUG_PRINT("enter", ("this: %p", this)); - fixed= 0; marker= 0; join_tab_idx= MAX_TABLES; if (orig_name) @@ -666,7 +493,7 @@ void Item::cleanup() bool Item::cleanup_processor(void *arg) { - if (fixed) + if (is_fixed()) cleanup(); return FALSE; } @@ -758,7 +585,8 @@ Item_ident::Item_ident(THD *thd, TABLE_LIST *view_arg, :Item_result_field(thd), orig_db_name(NullS), orig_table_name(view_arg->table_name.str), orig_field_name(*field_name_arg), - context(&view_arg->view->select_lex.context), + /* TODO: suspicious use of first_select_lex */ + context(&view_arg->view->first_select_lex()->context), db_name(NullS), table_name(view_arg->alias.str), field_name(*field_name_arg), alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX), @@ -952,12 +780,15 @@ bool Item_field::register_field_in_read_map(void *arg) { TABLE *table= (TABLE *) arg; int res= 0; + if (table && table != field->table) + return res; + if (field->vcol_info && - !bitmap_fast_test_and_set(field->table->vcol_set, field->field_index)) + !bitmap_fast_test_and_set(field->table->read_set, field->field_index)) { res= field->vcol_info->expr->walk(&Item::register_field_in_read_map,1,arg); } - if (field->table == table || !table) + else bitmap_set_bit(field->table->read_set, field->field_index); return res; } @@ -1185,7 +1016,7 @@ bool Item::check_type_scalar(const char *opname) const This hack in Item_outer_ref should probably be refactored eventually. Discuss with Sanja. */ - DBUG_ASSERT(fixed || type() == REF_ITEM); + DBUG_ASSERT(is_fixed() || type() == REF_ITEM); const Type_handler *handler= type_handler(); if (handler->is_scalar_type()) return false; @@ -1334,7 +1165,6 @@ Item *Item_cache::safe_charset_converter(THD *thd, CHARSET_INFO *tocs) unlikely(!(cache= new (thd->mem_root) Item_cache_str(thd, conv)))) return NULL; // Safe conversion is not possible, or OEM cache->setup(thd, conv); - cache->fixed= false; // Make Item::fix_fields() happy return cache; } @@ -1385,7 +1215,7 @@ Item *Item::const_charset_converter(THD *thd, CHARSET_INFO *tocs, const char *func_name) { DBUG_ASSERT(const_item()); - DBUG_ASSERT(fixed); + DBUG_ASSERT(is_fixed()); StringBuffer<64>tmp; String *s= val_str(&tmp); MEM_ROOT *mem_root= thd->mem_root; @@ -1453,116 +1283,35 @@ Item *Item_param::safe_charset_converter(THD *thd, CHARSET_INFO *tocs) As a extra convenience the time structure is reset on error or NULL values! */ -bool Item::get_date_from_int(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item::get_date_from_int(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - longlong value= val_int(); - bool neg= !unsigned_flag && value < 0; - if (null_value || int_to_datetime_with_warn(neg, neg ? -value : value, - ltime, fuzzydate, - field_table_or_null(), - field_name_or_null())) - return null_value|= make_zero_date(ltime, fuzzydate); - return null_value= false; -} - - -bool Item::get_date_from_year(MYSQL_TIME *ltime, ulonglong fuzzydate) -{ - longlong value= val_int(); - DBUG_ASSERT(unsigned_flag || value >= 0); - if (max_length == 2) - { - if (value < 70) - value+= 2000; - else if (value <= 1900) - value+= 1900; - } - value*= 10000; /* make it YYYYMMHH */ - if (null_value || int_to_datetime_with_warn(false, value, - ltime, fuzzydate, - field_table_or_null(), - field_name_or_null())) - return null_value|= make_zero_date(ltime, fuzzydate); - return null_value= false; -} - - -bool Item::get_date_from_real(MYSQL_TIME *ltime, ulonglong fuzzydate) -{ - double value= val_real(); - if (null_value || double_to_datetime_with_warn(value, ltime, fuzzydate, + Longlong_hybrid value(val_int(), unsigned_flag); + return null_value || int_to_datetime_with_warn(thd, value, + ltime, fuzzydate, field_table_or_null(), - field_name_or_null())) - return null_value|= make_zero_date(ltime, fuzzydate); - return null_value= false; -} - - -bool Item::get_date_from_decimal(MYSQL_TIME *ltime, ulonglong fuzzydate) -{ - my_decimal value, *res; - if (!(res= val_decimal(&value)) || - decimal_to_datetime_with_warn(res, ltime, fuzzydate, - field_table_or_null(), - field_name_or_null())) - return null_value|= make_zero_date(ltime, fuzzydate); - return null_value= false; + field_name_or_null()); } -bool Item::get_date_from_string(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item::get_date_from_real(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - char buff[40]; - String tmp(buff,sizeof(buff), &my_charset_bin),*res; - if (!(res=val_str(&tmp)) || - str_to_datetime_with_warn(res->charset(), res->ptr(), res->length(), - ltime, fuzzydate)) - return null_value|= make_zero_date(ltime, fuzzydate); - return null_value= false; + double value= val_real(); + return null_value || double_to_datetime_with_warn(thd, value, + ltime, fuzzydate, + field_table_or_null(), + field_name_or_null()); } -bool Item::make_zero_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item::get_date_from_string(THD *thd, MYSQL_TIME *to, date_mode_t mode) { - /* - if the item was not null and convertion failed, we return a zero date - if allowed, otherwise - null. - */ - bzero((char*) ltime,sizeof(*ltime)); - if (fuzzydate & TIME_TIME_ONLY) - { - /* - In the following scenario: - - The caller expected to get a TIME value - - Item returned a not NULL string or numeric value - - But then conversion from string or number to TIME failed - we need to change the default time_type from MYSQL_TIMESTAMP_DATE - (which was set in bzero) to MYSQL_TIMESTAMP_TIME and therefore - return TIME'00:00:00' rather than DATE'0000-00-00'. - If we don't do this, methods like Item::get_time_with_conversion() - will erroneously subtract CURRENT_DATE from '0000-00-00 00:00:00' - and return TIME'-838:59:59' instead of TIME'00:00:00' as a result. - */ - ltime->time_type= MYSQL_TIMESTAMP_TIME; - } - return !(fuzzydate & TIME_FUZZY_DATES); + StringBuffer<40> tmp; + Temporal::Warn_push warn(thd, field_table_or_null(), field_name_or_null(), + to, mode); + Temporal_hybrid *t= new(to) Temporal_hybrid(thd, &warn, val_str(&tmp), mode); + return !t->is_valid_temporal(); } -bool Item::get_seconds(ulonglong *sec, ulong *sec_part) -{ - if (decimals == 0) - { // optimize for an important special case - longlong val= val_int(); - bool neg= val < 0 && !unsigned_flag; - *sec= neg ? -val : val; - *sec_part= 0; - return neg; - } - my_decimal tmp, *dec= val_decimal(&tmp); - if (!dec) - return 0; - return my_decimal2seconds(dec, sec, sec_part); -} const MY_LOCALE *Item::locale_from_val_str() { @@ -1706,7 +1455,7 @@ Query_fragment::Query_fragment(THD *thd, sp_head *sphead, *****************************************************************************/ Item_sp_variable::Item_sp_variable(THD *thd, const LEX_CSTRING *sp_var_name) - :Item(thd), m_thd(0), m_name(*sp_var_name) + :Item_fixed_hybrid(thd), m_thd(0), m_name(*sp_var_name) #ifndef DBUG_OFF , m_sp(0) #endif @@ -1718,7 +1467,7 @@ bool Item_sp_variable::fix_fields_from_item(THD *thd, Item **, const Item *it) { m_thd= thd; /* NOTE: this must be set before any this_xxx() */ - DBUG_ASSERT(it->fixed); + DBUG_ASSERT(it->is_fixed()); max_length= it->max_length; decimals= it->decimals; @@ -1789,6 +1538,12 @@ String *Item_sp_variable::val_str(String *sp) } +bool Item_sp_variable::val_native(THD *thd, Native *to) +{ + return val_native_from_item(thd, this_item(), to); +} + + my_decimal *Item_sp_variable::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed); @@ -1799,11 +1554,11 @@ my_decimal *Item_sp_variable::val_decimal(my_decimal *decimal_value) } -bool Item_sp_variable::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_sp_variable::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed); Item *it= this_item(); - bool val= it->get_date(ltime, fuzzydate); + bool val= it->get_date(thd, ltime, fuzzydate); null_value= it->null_value; return val; } @@ -1839,10 +1594,10 @@ Item_splocal::Item_splocal(THD *thd, Rewritable_query_parameter(pos_in_q, len_in_q), Type_handler_hybrid_field_type(handler), m_rcontext_handler(rh), - m_var_idx(sp_var_idx) + m_var_idx(sp_var_idx), + m_type(handler == &type_handler_row ? ROW_ITEM : CONST_ITEM) { maybe_null= TRUE; - m_type= sp_map_item_type(handler); } @@ -2180,10 +1935,10 @@ my_decimal *Item_name_const::val_decimal(my_decimal *decimal_value) return val; } -bool Item_name_const::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_name_const::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed); - bool rc= value_item->get_date(ltime, fuzzydate); + bool rc= value_item->get_date(thd, ltime, fuzzydate); null_value= value_item->null_value; return rc; } @@ -2195,54 +1950,25 @@ bool Item_name_const::is_null() Item_name_const::Item_name_const(THD *thd, Item *name_arg, Item *val): - Item(thd), value_item(val), name_item(name_arg) + Item_fixed_hybrid(thd), value_item(val), name_item(name_arg) { Item::maybe_null= TRUE; - valid_args= true; - if (!name_item->basic_const_item()) - goto err; - - if (value_item->basic_const_item()) - return; // ok - - if (value_item->type() == FUNC_ITEM) - { - Item_func *value_func= (Item_func *) value_item; - if (value_func->functype() != Item_func::COLLATE_FUNC && - value_func->functype() != Item_func::NEG_FUNC) - goto err; - - if (value_func->key_item()->basic_const_item()) - return; // ok - } - -err: - valid_args= false; - my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST"); } Item::Type Item_name_const::type() const { /* - As - 1. one can try to create the Item_name_const passing non-constant - arguments, although it's incorrect and - 2. the type() method can be called before the fix_fields() to get - type information for a further type cast, e.g. - if (item->type() == FIELD_ITEM) - ((Item_field *) item)->... - we return NULL_ITEM in the case to avoid wrong casting. - - valid_args guarantees value_item->basic_const_item(); if type is - FUNC_ITEM, then we have a fudged item_func_neg() on our hands - and return the underlying type. + + We are guarenteed that value_item->basic_const_item(), if not + an error is thrown that WRONG ARGUMENTS are supplied to + NAME_CONST function. + If type is FUNC_ITEM, then we have a fudged item_func_neg() + on our hands and return the underlying type. For Item_func_set_collation() e.g. NAME_CONST('name', 'value' COLLATE collation) we return its 'value' argument type. */ - if (!valid_args) - return NULL_ITEM; Item::Type value_type= value_item->type(); if (value_type == FUNC_ITEM) { @@ -2385,7 +2111,7 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array, else { /* Not a SUM() function */ - if (unlikely((!with_sum_func && !(split_flags & SPLIT_SUM_SELECT)))) + if (unlikely((!with_sum_func() && !(split_flags & SPLIT_SUM_SELECT)))) { /* This is not a SUM function and there are no SUM functions inside. @@ -2393,7 +2119,7 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array, */ return; } - if (likely(with_sum_func || + if (likely(with_sum_func() || (type() == FUNC_ITEM && (((Item_func *) this)->functype() == Item_func::ISNOTNULLTEST_FUNC || @@ -2768,7 +2494,7 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, else thd->change_item_tree(arg, conv); - if (conv->fix_fields(thd, arg)) + if (conv->fix_fields_if_needed(thd, arg)) { res= TRUE; break; // we cannot return here, we need to restore "arena". @@ -2917,7 +2643,7 @@ bool Item_sp::execute(THD *thd, bool *null_value, Item **args, uint arg_count) if (unlikely(execute_impl(thd, args, arg_count))) { *null_value= 1; - context->process_error(thd); + process_error(thd); if (thd->killed) thd->send_kill_message(); return true; @@ -2950,7 +2676,7 @@ Item_sp::execute_impl(THD *thd, Item **args, uint arg_count) DBUG_ENTER("Item_sp::execute_impl"); - if (context->security_ctx) + if (context && context->security_ctx) { /* Set view definer security context */ thd->security_ctx= context->security_ctx; @@ -3129,7 +2855,10 @@ Item_field::Item_field(THD *thd, Field *f) have_privileges(0), any_privileges(0) { set_field(f); - + /* + field_name and table_name should not point to garbage + if this item is to be reused + */ orig_table_name= table_name; orig_field_name= field_name; with_field= 1; @@ -3446,7 +3175,7 @@ String *Item_field::str_result(String *str) return result_field->val_str(str,&str_value); } -bool Item_field::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) +bool Item_field::get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate) { if ((null_value=field->is_null()) || field->get_date(ltime,fuzzydate)) { @@ -3456,7 +3185,7 @@ bool Item_field::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) return 0; } -bool Item_field::get_date_result(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_field::get_date_result(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { if (result_field->is_null() || result_field->get_date(ltime,fuzzydate)) { @@ -3467,6 +3196,18 @@ bool Item_field::get_date_result(MYSQL_TIME *ltime, ulonglong fuzzydate) } +bool Item_field::val_native(THD *thd, Native *to) +{ + return val_native_from_field(field, to); +} + + +bool Item_field::val_native_result(THD *thd, Native *to) +{ + return val_native_from_field(result_field, to); +} + + void Item_field::save_result(Field *to) { save_field_in_field(result_field, &null_value, to, TRUE); @@ -3665,6 +3406,48 @@ longlong Item_field::val_int_endpoint(bool left_endp, bool *incl_endp) return null_value? LONGLONG_MIN : res; } + +bool Item_basic_value::eq(const Item *item, bool binary_cmp) const +{ + const Item_const *c0, *c1; + const Type_handler *h0, *h1; + /* + - Test get_item_const() for NULL filters out Item_param + bound in a way that needs a data type conversion + (e.g. non-integer value in a LIMIT clause). + Item_param::get_item_const() return NULL in such cases. + - Test for type_handler_for_comparison() equality makes sure + that values of different data type groups do not get detected + as equal (e.g. numbers vs strings, time vs datetime). + - Test for cast_to_int_type_handler() equality distinguishes + values with dual properties. For example, VARCHAR 'abc' and hex + hybrid 0x616263 are equal in string context, but they are not equal + if the hybrid appears in integer context (it behaves as integer then). + Here we have no full information about the context, so treat them + as not equal. + QQ: We could pass Value_source::Context here instead of + "bool binary_cmp", to make substitution more delicate. + See Field::get_equal_const_item(). + */ + bool res= (c0= get_item_const()) && + (c1= item->get_item_const()) && + (h0= type_handler())->type_handler_for_comparison() == + (h1= item->type_handler())->type_handler_for_comparison() && + h0->cast_to_int_type_handler()->type_handler_for_comparison() == + h1->cast_to_int_type_handler()->type_handler_for_comparison() && + h0->Item_const_eq(c0, c1, binary_cmp); + DBUG_EXECUTE_IF("Item_basic_value", + push_warning_printf(current_thd, + Sql_condition::WARN_LEVEL_NOTE, + ER_UNKNOWN_ERROR, "%seq=%d a=%s b=%s", + binary_cmp ? "bin_" : "", (int) res, + DbugStringItemTypeValue(current_thd, this).c_ptr(), + DbugStringItemTypeValue(current_thd, item).c_ptr() + );); + return res; +} + + /** Create an item from a string we KNOW points to a valid longlong end \\0 terminated number string. @@ -3684,7 +3467,6 @@ Item_int::Item_int(THD *thd, const char *str_arg, size_t length): the field name. */ name.length= !str_arg[max_length] ? max_length : strlen(str_arg); - fixed= 1; } @@ -3696,8 +3478,6 @@ my_decimal *Item_int::val_decimal(my_decimal *decimal_value) String *Item_int::val_str(String *str) { - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); str->set_int(value, unsigned_flag, collation.collation); return str; } @@ -3734,8 +3514,6 @@ Item_uint::Item_uint(THD *thd, const char *str_arg, longlong i, uint length): String *Item_uint::val_str(String *str) { - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); str->set((ulonglong) value, collation.collation); return str; } @@ -3757,7 +3535,6 @@ Item_decimal::Item_decimal(THD *thd, const char *str_arg, size_t length, name.str= str_arg; name.length= safe_strlen(str_arg); decimals= (uint8) decimal_value.frac; - fixed= 1; max_length= my_decimal_precision_to_length_no_truncation(decimal_value.intg + decimals, decimals, @@ -3769,7 +3546,6 @@ Item_decimal::Item_decimal(THD *thd, longlong val, bool unsig): { int2my_decimal(E_DEC_FATAL_ERROR, val, unsig, &decimal_value); decimals= (uint8) decimal_value.frac; - fixed= 1; max_length= my_decimal_precision_to_length_no_truncation(decimal_value.intg + decimals, decimals, @@ -3782,7 +3558,6 @@ Item_decimal::Item_decimal(THD *thd, double val, int precision, int scale): { double2my_decimal(E_DEC_FATAL_ERROR, val, &decimal_value); decimals= (uint8) decimal_value.frac; - fixed= 1; max_length= my_decimal_precision_to_length_no_truncation(decimal_value.intg + decimals, decimals, @@ -3799,16 +3574,14 @@ Item_decimal::Item_decimal(THD *thd, const char *str, const my_decimal *val_arg, name.length= safe_strlen(str); decimals= (uint8) decimal_par; max_length= length; - fixed= 1; } -Item_decimal::Item_decimal(THD *thd, my_decimal *value_par): +Item_decimal::Item_decimal(THD *thd, const my_decimal *value_par): Item_num(thd) { my_decimal2decimal(value_par, &decimal_value); decimals= (uint8) decimal_value.frac; - fixed= 1; max_length= my_decimal_precision_to_length_no_truncation(decimal_value.intg + decimals, decimals, @@ -3817,63 +3590,15 @@ Item_decimal::Item_decimal(THD *thd, my_decimal *value_par): Item_decimal::Item_decimal(THD *thd, const uchar *bin, int precision, int scale): - Item_num(thd) + Item_num(thd), + decimal_value(bin, precision, scale) { - binary2my_decimal(E_DEC_FATAL_ERROR, bin, - &decimal_value, precision, scale); decimals= (uint8) decimal_value.frac; - fixed= 1; max_length= my_decimal_precision_to_length_no_truncation(precision, decimals, unsigned_flag); } -longlong Item_decimal::val_int() -{ - longlong result; - my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &result); - return result; -} - -double Item_decimal::val_real() -{ - double result; - my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &result); - return result; -} - -String *Item_decimal::val_str(String *result) -{ - result->set_charset(&my_charset_numeric); - my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, result); - return result; -} - -void Item_decimal::print(String *str, enum_query_type query_type) -{ - my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, &str_value); - str->append(str_value); -} - - -bool Item_decimal::eq(const Item *item, bool binary_cmp) const -{ - if (type() == item->type() && item->basic_const_item()) - { - /* - We need to cast off const to call val_decimal(). This should - be OK for a basic constant. Additionally, we can pass 0 as - a true decimal constant will return its internal decimal - storage and ignore the argument. - */ - Item *arg= (Item*) item; - my_decimal *value= arg->val_decimal(0); - return !my_decimal_cmp(&decimal_value, value); - } - return 0; -} - - void Item_decimal::set_decimal_value(my_decimal *value_par) { my_decimal2decimal(value_par, &decimal_value); @@ -3895,8 +3620,6 @@ Item *Item_decimal::clone_item(THD *thd) String *Item_float::val_str(String *str) { - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); str->set_real(value, decimals, &my_charset_numeric); return str; } @@ -3904,8 +3627,6 @@ String *Item_float::val_str(String *str) my_decimal *Item_float::val_decimal(my_decimal *decimal_value) { - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_value); return (decimal_value); } @@ -3966,7 +3687,6 @@ void Item_string::print(String *str, enum_query_type query_type) double Item_string::val_real() { - DBUG_ASSERT(fixed == 1); return double_from_string_with_check(&str_value); } @@ -3977,7 +3697,6 @@ double Item_string::val_real() */ longlong Item_string::val_int() { - DBUG_ASSERT(fixed == 1); return longlong_from_string_with_check(&str_value); } @@ -3990,23 +3709,17 @@ my_decimal *Item_string::val_decimal(my_decimal *decimal_value) double Item_null::val_real() { - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; } longlong Item_null::val_int() { - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); null_value=1; return 0; } /* ARGSUSED */ String *Item_null::val_str(String *str) { - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); null_value=1; return 0; } @@ -4017,11 +3730,9 @@ my_decimal *Item_null::val_decimal(my_decimal *decimal_value) } -bool Item_null::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_null::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); - make_zero_date(ltime, fuzzydate); + set_zero_time(ltime, MYSQL_TIMESTAMP_NONE); return (null_value= true); } @@ -4070,8 +3781,6 @@ Item_param::Item_param(THD *thd, const LEX_CSTRING *name_arg, */ Type_handler_hybrid_field_type(&type_handler_null), state(NO_VALUE), - /* Don't pretend to be a literal unless value for this item is set. */ - item_type(PARAM_ITEM), m_empty_string_is_null(false), indicator(STMT_INDICATOR_NONE), m_out_param_info(NULL), @@ -4130,7 +3839,6 @@ void Item_param::sync_clones() c->Type_geometry_attributes::operator=(*this); c->state= state; - c->item_type= item_type; c->m_empty_string_is_null= m_empty_string_is_null; c->value.PValue_simple::operator=(value); @@ -4165,7 +3873,6 @@ void Item_param::set_null() max_length= 0; decimals= 0; state= NULL_VALUE; - fix_type(Item::NULL_ITEM); DBUG_VOID_RETURN; } @@ -4180,7 +3887,6 @@ void Item_param::set_int(longlong i, uint32 max_length_arg) decimals= 0; maybe_null= 0; null_value= 0; - fix_type(Item::INT_ITEM); DBUG_VOID_RETURN; } @@ -4195,7 +3901,6 @@ void Item_param::set_double(double d) decimals= NOT_FIXED_DEC; maybe_null= 0; null_value= 0; - fix_type(Item::REAL_ITEM); DBUG_VOID_RETURN; } @@ -4228,7 +3933,6 @@ void Item_param::set_decimal(const char *str, ulong length) decimals, unsigned_flag); maybe_null= 0; null_value= 0; - fix_type(Item::DECIMAL_ITEM); DBUG_VOID_RETURN; } @@ -4246,7 +3950,6 @@ void Item_param::set_decimal(const my_decimal *dv, bool unsigned_arg) decimals, unsigned_flag); maybe_null= 0; null_value= 0; - fix_type(Item::DECIMAL_ITEM); } @@ -4258,7 +3961,6 @@ void Item_param::fix_temporal(uint32 max_length_arg, uint decimals_arg) decimals= decimals_arg; maybe_null= 0; null_value= 0; - fix_type(Item::DATE_ITEM); } @@ -4343,7 +4045,6 @@ bool Item_param::set_str(const char *str, ulong length, null_value= 0; /* max_length and decimals are set after charset conversion */ /* sic: str may be not null-terminated, don't add DBUG_PRINT here */ - fix_type(Item::STRING_ITEM); DBUG_RETURN(FALSE); } @@ -4377,7 +4078,6 @@ bool Item_param::set_longdata(const char *str, ulong length) state= LONG_DATA_VALUE; maybe_null= 0; null_value= 0; - fix_type(Item::STRING_ITEM); DBUG_RETURN(FALSE); } @@ -4441,7 +4141,7 @@ bool Item_param::set_from_item(THD *thd, Item *item) } } struct st_value tmp; - if (!item->save_in_value(&tmp)) + if (!item->save_in_value(thd, &tmp)) { const Type_handler *h= item->type_handler(); set_handler(h); @@ -4479,16 +4179,6 @@ void Item_param::reset() state= NO_VALUE; maybe_null= 1; null_value= 0; - fixed= false; - /* - Don't reset item_type to PARAM_ITEM: it's only needed to guard - us from item optimizations at prepare stage, when item doesn't yet - contain a literal of some kind. - In all other cases when this object is accessed its value is - set (this assumption is guarded by 'state' and - DBUG_ASSERTS(state != NO_VALUE) in all Item_param::get_* - methods). - */ DBUG_VOID_RETURN; } @@ -4554,7 +4244,7 @@ void Item_param::invalid_default_param() const } -bool Item_param::get_date(MYSQL_TIME *res, ulonglong fuzzydate) +bool Item_param::get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) { /* LIMIT clause parameter should not call get_date() @@ -4568,7 +4258,7 @@ bool Item_param::get_date(MYSQL_TIME *res, ulonglong fuzzydate) *res= value.time; return 0; } - return type_handler()->Item_get_date(this, res, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, res, fuzzydate); } @@ -4580,11 +4270,7 @@ double Item_param::PValue::val_real() const case INT_RESULT: return (double) integer; case DECIMAL_RESULT: - { - double result; - my_decimal2double(E_DEC_FATAL_ERROR, &m_decimal, &result); - return result; - } + return m_decimal.to_double(); case STRING_RESULT: return double_from_string_with_check(&m_string); case TIME_RESULT: @@ -4609,11 +4295,7 @@ longlong Item_param::PValue::val_int(const Type_std_attributes *attr) const case INT_RESULT: return integer; case DECIMAL_RESULT: - { - longlong i; - my_decimal2int(E_DEC_FATAL_ERROR, &m_decimal, attr->unsigned_flag, &i); - return i; - } + return m_decimal.to_longlong(attr->unsigned_flag); case STRING_RESULT: return longlong_from_string_with_check(&m_string); case TIME_RESULT: @@ -4663,7 +4345,7 @@ String *Item_param::PValue::val_str(String *str, str->set(integer, &my_charset_bin); return str; case DECIMAL_RESULT: - if (my_decimal2string(E_DEC_FATAL_ERROR, &m_decimal, 0, 0, 0, str) <= 1) + if (m_decimal.to_string_native(str, 0, 0, 0) <= 1) return str; return NULL; case TIME_RESULT: @@ -4704,8 +4386,7 @@ const String *Item_param::value_query_val_str(THD *thd, String *str) const str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin); return str; case DECIMAL_RESULT: - if (my_decimal2string(E_DEC_FATAL_ERROR, &value.m_decimal, - 0, 0, 0, str) > 1) + if (value.m_decimal.to_string_native(str, 0, 0, 0) > 1) return &my_null_string; return str; case TIME_RESULT: @@ -4810,11 +4491,20 @@ bool Item_param::convert_str_value(THD *thd) bool Item_param::basic_const_item() const { - DBUG_ASSERT(fixed || state == NO_VALUE); - if (state == NO_VALUE || - (state == SHORT_DATA_VALUE && type_handler()->cmp_type() == TIME_RESULT)) - return FALSE; - return TRUE; + switch (state) { + case LONG_DATA_VALUE: + case NULL_VALUE: + return true; + case SHORT_DATA_VALUE: + return type_handler()->cmp_type() != TIME_RESULT; + case DEFAULT_VALUE: + case IGNORE_VALUE: + invalid_default_param(); + return false; + case NO_VALUE: + break; + } + return false; } @@ -4875,48 +4565,6 @@ Item_param::clone_item(THD *thd) } -bool Item_param::value_eq(const Item *item, bool binary_cmp) const -{ - switch (value.type_handler()->cmp_type()) { - case INT_RESULT: - return int_eq(value.integer, item); - case REAL_RESULT: - return real_eq(value.real, item); - case STRING_RESULT: - return str_eq(&value.m_string, item, binary_cmp); - case DECIMAL_RESULT: - case TIME_RESULT: - case ROW_RESULT: - break; - } - return false; -} - - -bool -Item_param::eq(const Item *item, bool binary_cmp) const -{ - if (!basic_const_item()) - return FALSE; - - // There's no "default". See comments in Item_param::save_in_field(). - switch (state) { - case IGNORE_VALUE: - case DEFAULT_VALUE: - invalid_default_param(); - return false; - case NULL_VALUE: - return null_eq(item); - case SHORT_DATA_VALUE: - case LONG_DATA_VALUE: - return value_eq(item, binary_cmp); - case NO_VALUE: - return false; - } - DBUG_ASSERT(0); // Garbage - return FALSE; -} - /* End of Item_param related */ void Item_param::print(String *str, enum_query_type query_type) @@ -4970,12 +4618,10 @@ Item_param::set_param_type_and_swap_value(Item_param *src) { Type_std_attributes::set(src); set_handler(src->type_handler()); - item_type= src->item_type; maybe_null= src->maybe_null; null_value= src->null_value; state= src->state; - fixed= src->fixed; value.swap(src->value); } @@ -4985,7 +4631,6 @@ void Item_param::set_default() { m_is_settable_routine_parameter= false; state= DEFAULT_VALUE; - fixed= true; /* When Item_param is set to DEFAULT_VALUE: - its val_str() and val_decimal() return NULL @@ -5001,7 +4646,6 @@ void Item_param::set_ignore() { m_is_settable_routine_parameter= false; state= IGNORE_VALUE; - fixed= true; null_value= true; } @@ -5030,7 +4674,7 @@ Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it) correctly fetches the value from the client-server protocol, using set_param_func(). */ - if (arg->save_in_value(&tmp) || + if (arg->save_in_value(thd, &tmp) || set_value(thd, arg, &tmp, arg->type_handler())) { set_null(); @@ -5176,17 +4820,6 @@ my_decimal *Item_copy_string::val_decimal(my_decimal *decimal_value) Functions to convert item to field (for send_result_set_metadata) */ -/* ARGSUSED */ -bool Item::fix_fields(THD *thd, Item **ref) -{ - - // We do not check fields which are fixed during construction - DBUG_ASSERT(fixed == 0 || basic_const_item()); - fixed= 1; - return FALSE; -} - - void Item_ref_null_helper::save_val(Field *to) { DBUG_ASSERT(fixed == 1); @@ -5240,9 +4873,15 @@ String* Item_ref_null_helper::val_str(String* s) } -bool Item_ref_null_helper::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_ref_null_helper::val_native(THD *thd, Native *to) +{ + return (owner->was_null|= val_native_from_item(thd, *ref, to)); +} + + +bool Item_ref_null_helper::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return (owner->was_null|= null_value= (*ref)->get_date_result(ltime, fuzzydate)); + return (owner->was_null|= null_value= (*ref)->get_date_result(thd, ltime, fuzzydate)); } @@ -5535,7 +5174,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) ref->alias_name_used= TRUE; /* If this is a non-aggregated field inside HAVING, search in GROUP BY. */ - if (select->having_fix_field && !ref->with_sum_func && group_list) + if (select->having_fix_field && !ref->with_sum_func() && group_list) { group_by_ref= find_field_in_group_list(ref, group_list); @@ -5577,7 +5216,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) ref->name.str, "forward reference in item list"); return NULL; } - DBUG_ASSERT((*select_ref)->fixed); + DBUG_ASSERT((*select_ref)->is_fixed()); return &select->ref_pointer_array[counter]; } if (group_by_ref) @@ -5700,7 +5339,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) Name_resolution_context *outer_context= 0; SELECT_LEX *select= 0; /* Currently derived tables cannot be correlated */ - if (current_sel->master_unit()->first_select()->linkage != + if (current_sel->master_unit()->first_select()->get_linkage() != DERIVED_TABLE_TYPE) outer_context= context->outer_context; @@ -5854,7 +5493,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) return -1; /* Some error occurred (e.g. ambiguous names). */ if (ref != not_found_item) { - DBUG_ASSERT(*ref && (*ref)->fixed); + DBUG_ASSERT(*ref && (*ref)->is_fixed()); prev_subselect_item->used_tables_and_const_cache_join(*ref); break; } @@ -5896,7 +5535,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) Item_ref *rf; /* Should have been checked in resolve_ref_in_select_and_group(). */ - DBUG_ASSERT(*ref && (*ref)->fixed); + DBUG_ASSERT(*ref && (*ref)->is_fixed()); /* Here, a subset of actions performed by Item_ref::set_properties is not enough. So we pass ptr to NULL into Item_[direct]_ref @@ -6472,7 +6111,7 @@ Item *Item_field::replace_equal_field(THD *thd, uchar *arg) comparison context, and it's safe to replace it to the constant from item_equal. */ - DBUG_ASSERT(type_handler()->type_handler_for_comparison()->cmp_type() == + DBUG_ASSERT(type_handler_for_comparison()->cmp_type() == item_equal->compare_type_handler()->cmp_type()); return const_item2; } @@ -6844,12 +6483,11 @@ int Item::save_real_in_field(Field *field, bool no_conversions) int Item::save_decimal_in_field(Field *field, bool no_conversions) { - my_decimal decimal_value; - my_decimal *value= val_decimal(&decimal_value); - if (null_value) + VDec value(this); + if (value.is_null()) return set_field_to_null_with_conversions(field, no_conversions); field->set_notnull(); - return field->store_decimal(value); + return field->store_decimal(value.ptr()); } @@ -6916,14 +6554,18 @@ Item_string::make_string_literal_concat(THD *thd, const LEX_CSTRING *str) */ Item *Item_string::make_odbc_literal(THD *thd, const LEX_CSTRING *typestr) { - enum_field_types type= odbc_temporal_literal_type(typestr); - Item *res= type == MYSQL_TYPE_STRING ? this : - create_temporal_literal(thd, val_str(NULL), type, false); + Item_literal *res; + const Type_handler *h; + if (collation.repertoire == MY_REPERTOIRE_ASCII && + str_value.length() < MAX_DATE_STRING_REP_LENGTH * 4 && + (h= Type_handler::odbc_literal_type_handler(typestr)) && + (res= h->create_literal_item(thd, val_str(NULL), false))) + return res; /* - create_temporal_literal() returns NULL if failed to parse the string, + h->create_literal_item() returns NULL if failed to parse the string, or the string format did not match the type, e.g.: {d'2001-01-01 10:10:10'} */ - return res ? res : this; + return this; } @@ -7126,7 +6768,6 @@ Item_float::Item_float(THD *thd, const char *str_arg, size_t length): name.length= strlen(str_arg); decimals=(uint8) nr_of_decimals(str_arg, str_arg+length); max_length=(uint32)length; - fixed= 1; } @@ -7182,7 +6823,6 @@ void Item_hex_constant::hex_string_init(THD *thd, const char *str, size_t str_le } *ptr=0; // Keep purify happy collation.set(&my_charset_bin, DERIVATION_COERCIBLE); - fixed= 1; unsigned_flag= 1; } @@ -7261,19 +6901,9 @@ Item_bin_string::Item_bin_string(THD *thd, const char *str, size_t str_length): ptr[0]= 0; collation.set(&my_charset_bin, DERIVATION_COERCIBLE); - fixed= 1; } -bool Item_temporal_literal::eq(const Item *item, bool binary_cmp) const -{ - return - item->basic_const_item() && type() == item->type() && - field_type() == ((Item_temporal_literal *) item)->field_type() && - !my_time_compare(&cached_time, - &((Item_temporal_literal *) item)->cached_time); -} - void Item_date_literal::print(String *str, enum_query_type query_type) { str->append("DATE'"); @@ -7290,12 +6920,11 @@ Item *Item_date_literal::clone_item(THD *thd) } -bool Item_date_literal::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_date_literal::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - DBUG_ASSERT(fixed); - fuzzy_date |= sql_mode_for_dates(current_thd); + fuzzydate |= sql_mode_for_dates(thd); *ltime= cached_time; - return (null_value= check_date_with_warn(ltime, fuzzy_date, + return (null_value= check_date_with_warn(thd, ltime, fuzzydate, MYSQL_TIMESTAMP_ERROR)); } @@ -7316,12 +6945,11 @@ Item *Item_datetime_literal::clone_item(THD *thd) } -bool Item_datetime_literal::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_datetime_literal::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - DBUG_ASSERT(fixed); - fuzzy_date |= sql_mode_for_dates(current_thd); + fuzzydate |= sql_mode_for_dates(thd); *ltime= cached_time; - return (null_value= check_date_with_warn(ltime, fuzzy_date, + return (null_value= check_date_with_warn(thd, ltime, fuzzydate, MYSQL_TIMESTAMP_ERROR)); } @@ -7342,13 +6970,12 @@ Item *Item_time_literal::clone_item(THD *thd) } -bool Item_time_literal::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_time_literal::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - DBUG_ASSERT(fixed); *ltime= cached_time; - if (fuzzy_date & TIME_TIME_ONLY) + if (fuzzydate & TIME_TIME_ONLY) return (null_value= false); - return (null_value= check_date_with_warn(ltime, fuzzy_date, + return (null_value= check_date_with_warn(thd, ltime, fuzzydate, MYSQL_TIMESTAMP_ERROR)); } @@ -7464,7 +7091,7 @@ void Item_field::update_null_value() no_errors= thd->no_errors; thd->no_errors= 1; - Item::update_null_value(); + type_handler()->Item_update_null_value(this); thd->no_errors= no_errors; } @@ -7515,6 +7142,231 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg) } +/** + @brief + Prepare AND/OR formula for extraction of a pushable condition + + @param checker the checker callback function to be applied to the nodes + of the tree of the object + @param arg parameter to be passed to the checker + + @details + This method recursively traverses this AND/OR condition and for each + subformula of the condition it checks whether it can be usable for the + extraction of a pushable condition. The criteria of pushability of + a subformula is checked by the callback function 'checker' with one + parameter arg. The subformulas that are not usable are marked with + the flag NO_EXTRACTION_FL. + @note + This method is called before any call of build_pushable_cond. + The flag NO_EXTRACTION_FL set in a subformula allows to avoid building + clones for the subformulas that are not used in the pushable condition. + @note + This method is called for pushdown conditions into materialized + derived tables/views optimization. + Item::pushable_cond_checker_for_derived() is passed as the actual callback + function. + Also it is called for pushdown conditions in materialized IN subqueries. + Item::pushable_cond_checker_for_subquery is passed as the actual + callback function. +*/ + +void Item::check_pushable_cond(Pushdown_checker checker, uchar *arg) +{ + clear_extraction_flag(); + if (type() == Item::COND_ITEM) + { + bool and_cond= ((Item_cond*) this)->functype() == Item_func::COND_AND_FUNC; + List_iterator<Item> li(*((Item_cond*) this)->argument_list()); + uint count= 0; + Item *item; + while ((item=li++)) + { + item->check_pushable_cond(checker, arg); + if (item->get_extraction_flag() != NO_EXTRACTION_FL) + count++; + else if (!and_cond) + break; + } + if ((and_cond && count == 0) || item) + { + set_extraction_flag(NO_EXTRACTION_FL); + if (and_cond) + li.rewind(); + while ((item= li++)) + item->clear_extraction_flag(); + } + } + else if (!((this->*checker) (arg))) + set_extraction_flag(NO_EXTRACTION_FL); +} + + +/** + @brief + Build condition extractable from this condition for pushdown + + @param thd the thread handle + @param checker the checker callback function to be applied to the + equal items of multiple equality items + @param arg parameter to be passed to the checker + + @details + This method finds out what condition that can be pushed down can be + extracted from this condition. If such condition C exists the + method builds the item for it. The method uses the flag NO_EXTRACTION_FL + set by the preliminary call of the method check_pushable_cond() to figure + out whether a subformula is pushable or not. + In the case when this item is a multiple equality a checker method is + called to find the equal fields to build a new equality that can be + pushed down. + @note + The built condition C is always implied by the condition cond + (cond => C). The method tries to build the most restrictive such + condition (i.e. for any other condition C' such that cond => C' + we have C => C'). + @note + The build item is not ready for usage: substitution for the field items + has to be done and it has to be re-fixed. + @note + This method is called for pushdown conditions into materialized + derived tables/views optimization. + Item::pushable_equality_checker_for_derived() is passed as the actual + callback function. + Also it is called for pushdown conditions into materialized IN subqueries. + Item::pushable_equality_checker_for_subquery() is passed as the actual + callback function. + + @retval + the built condition pushable into if such a condition exists + NULL if there is no such a condition +*/ + +Item *Item::build_pushable_cond(THD *thd, + Pushdown_checker checker, + uchar *arg) +{ + bool is_multiple_equality= type() == Item::FUNC_ITEM && + ((Item_func*) this)->functype() == Item_func::MULT_EQUAL_FUNC; + + if (get_extraction_flag() == NO_EXTRACTION_FL) + return 0; + + if (type() == Item::COND_ITEM) + { + bool cond_and= false; + Item_cond *new_cond; + if (((Item_cond*) this)->functype() == Item_func::COND_AND_FUNC) + { + cond_and= true; + new_cond= new (thd->mem_root) Item_cond_and(thd); + } + else + new_cond= new (thd->mem_root) Item_cond_or(thd); + if (!new_cond) + return 0; + List_iterator<Item> li(*((Item_cond*) this)->argument_list()); + Item *item; + bool is_fix_needed= false; + + while ((item=li++)) + { + if (item->get_extraction_flag() == NO_EXTRACTION_FL) + { + if (!cond_and) + return 0; + continue; + } + Item *fix= item->build_pushable_cond(thd, checker, arg); + if (!fix && !cond_and) + return 0; + if (!fix) + continue; + + if (fix->type() == Item::COND_ITEM && + ((Item_cond*) fix)->functype() == Item_func::COND_AND_FUNC) + is_fix_needed= true; + + if (new_cond->argument_list()->push_back(fix, thd->mem_root)) + return 0; + } + if (is_fix_needed && new_cond->fix_fields(thd, 0)) + return 0; + + switch (new_cond->argument_list()->elements) + { + case 0: + return 0; + case 1: + return new_cond->argument_list()->head(); + default: + return new_cond; + } + } + else if (is_multiple_equality) + { + Item *new_cond= NULL; + int i= 0; + Item_equal *item_equal= (Item_equal *) this; + Item *left_item = item_equal->get_const(); + Item_equal_fields_iterator it(*item_equal); + Item *item; + Item *right_item; + if (!left_item) + { + while ((item=it++)) + { + left_item= ((item->*checker) (arg)) ? item : NULL; + if (left_item) + break; + } + } + if (!left_item) + return 0; + while ((item=it++)) + { + right_item= ((item->*checker) (arg)) ? item : NULL; + if (!right_item) + continue; + Item_func_eq *eq= 0; + Item *left_item_clone= left_item->build_clone(thd); + Item *right_item_clone= item->build_clone(thd); + if (left_item_clone && right_item_clone) + { + left_item_clone->set_item_equal(NULL); + right_item_clone->set_item_equal(NULL); + eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone, + left_item_clone); + } + if (eq) + { + i++; + switch (i) + { + case 1: + new_cond= eq; + break; + case 2: + new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq); + break; + default: + if (((Item_cond_and*)new_cond)->argument_list()->push_back(eq, + thd->mem_root)) + return 0; + break; + } + } + } + if (new_cond && new_cond->fix_fields(thd, &new_cond)) + return 0; + return new_cond; + } + else if (get_extraction_flag() != NO_EXTRACTION_FL) + return build_clone(thd); + return 0; +} + + static Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel) { @@ -7649,18 +7501,18 @@ Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd, } static -Grouping_tmp_field *find_matching_grouping_field(Item *item, - st_select_lex *sel) +Field_pair *find_matching_grouping_field(Item *item, + st_select_lex *sel) { DBUG_ASSERT(item->type() == Item::FIELD_ITEM || (item->type() == Item::REF_ITEM && ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF)); - List_iterator<Grouping_tmp_field> li(sel->grouping_tmp_fields); - Grouping_tmp_field *gr_field; + List_iterator<Field_pair> li(sel->grouping_tmp_fields); + Field_pair *gr_field; Item_field *field_item= (Item_field *) (item->real_item()); while ((gr_field= li++)) { - if (field_item->field == gr_field->tmp_field) + if (field_item->field == gr_field->field) return gr_field; } Item_equal *item_equal= item->get_item_equal(); @@ -7674,7 +7526,7 @@ Grouping_tmp_field *find_matching_grouping_field(Item *item, li.rewind(); while ((gr_field= li++)) { - if (field_item->field == gr_field->tmp_field) + if (field_item->field == gr_field->field) return gr_field; } } @@ -7683,15 +7535,14 @@ Grouping_tmp_field *find_matching_grouping_field(Item *item, } -Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd, - uchar *arg) +Item *Item_field::grouping_field_transformer_for_where(THD *thd, uchar *arg) { st_select_lex *sel= (st_select_lex *)arg; - Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel); + Field_pair *gr_field= find_matching_grouping_field(this, sel); if (gr_field) { Item *producing_clone= - gr_field->producing_item->build_clone(thd); + gr_field->corresponding_item->build_clone(thd); if (producing_clone) producing_clone->marker|= SUBSTITUTION_FL; return producing_clone; @@ -7701,8 +7552,8 @@ Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd, Item * -Item_direct_view_ref::derived_grouping_field_transformer_for_where(THD *thd, - uchar *arg) +Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd, + uchar *arg) { if ((*ref)->marker & SUBSTITUTION_FL) { @@ -7712,8 +7563,8 @@ Item_direct_view_ref::derived_grouping_field_transformer_for_where(THD *thd, if (!item_equal) return this; st_select_lex *sel= (st_select_lex *)arg; - Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel); - return gr_field->producing_item->build_clone(thd); + Field_pair *gr_field= find_matching_grouping_field(this, sel); + return gr_field->corresponding_item->build_clone(thd); } void Item_field::print(String *str, enum_query_type query_type) @@ -7749,7 +7600,7 @@ Item_ref::Item_ref(THD *thd, Name_resolution_context *context_arg, /* This constructor used to create some internals references over fixed items */ - if ((set_properties_only= (ref && *ref && (*ref)->fixed))) + if ((set_properties_only= (ref && *ref && (*ref)->is_fixed()))) set_properties(); } @@ -7798,7 +7649,7 @@ Item_ref::Item_ref(THD *thd, TABLE_LIST *view_arg, Item **item, /* This constructor is used to create some internal references over fixed items */ - if ((set_properties_only= (ref && *ref && (*ref)->fixed))) + if ((set_properties_only= (ref && *ref && (*ref)->is_fixed()))) set_properties(); } @@ -7924,7 +7775,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) goto error; /* Some error occurred (e.g. ambiguous names). */ if (ref != not_found_item) { - DBUG_ASSERT(*ref && (*ref)->fixed); + DBUG_ASSERT(*ref && (*ref)->is_fixed()); prev_subselect_item->used_tables_and_const_cache_join(*ref); break; } @@ -8047,7 +7898,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) goto error; } /* Should be checked in resolve_ref_in_select_and_group(). */ - DBUG_ASSERT(*ref && (*ref)->fixed); + DBUG_ASSERT(*ref && (*ref)->is_fixed()); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, this, this); /* @@ -8072,13 +7923,13 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) */ if (!((*ref)->type() == REF_ITEM && ((Item_ref *)(*ref))->ref_type() == OUTER_REF) && - (((*ref)->with_sum_func && name.str && - !(current_sel->linkage != GLOBAL_OPTIONS_TYPE && + (((*ref)->with_sum_func() && name.str && + !(current_sel->get_linkage() != GLOBAL_OPTIONS_TYPE && current_sel->having_fix_field)) || - !(*ref)->fixed)) + !(*ref)->is_fixed())) { my_error(ER_ILLEGAL_REFERENCE, MYF(0), - name.str, ((*ref)->with_sum_func? + name.str, ((*ref)->with_sum_func() ? "reference to group function": "forward reference in item list")); goto error; @@ -8104,7 +7955,7 @@ void Item_ref::set_properties() We have to remember if we refer to a sum function, to ensure that split_sum_func() doesn't try to change the reference. */ - with_sum_func= (*ref)->with_sum_func; + copy_with_sum_func(*ref); with_param= (*ref)->with_param; with_window_func= (*ref)->with_window_func; with_field= (*ref)->with_field; @@ -8288,6 +8139,14 @@ String *Item_ref::str_result(String* str) } +bool Item_ref::val_native_result(THD *thd, Native *to) +{ + return result_field ? + val_native_from_field(result_field, to) : + val_native(thd, to); +} + + my_decimal *Item_ref::val_decimal_result(my_decimal *decimal_value) { if (result_field) @@ -8376,9 +8235,15 @@ bool Item_ref::is_null() } -bool Item_ref::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) +bool Item_ref::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) +{ + return (null_value=(*ref)->get_date_result(thd, ltime, fuzzydate)); +} + + +bool Item_ref::val_native(THD *thd, Native *to) { - return (null_value=(*ref)->get_date_result(ltime,fuzzydate)); + return val_native_from_item(thd, *ref, to); } @@ -8513,9 +8378,15 @@ bool Item_direct_ref::is_null() } -bool Item_direct_ref::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) +bool Item_direct_ref::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return (null_value=(*ref)->get_date(ltime,fuzzydate)); + return (null_value=(*ref)->get_date(thd, ltime, fuzzydate)); +} + + +bool Item_direct_ref::val_native(THD *thd, Native *to) +{ + return val_native_from_item(thd, *ref, to); } @@ -8527,10 +8398,10 @@ Item_cache_wrapper::~Item_cache_wrapper() Item_cache_wrapper::Item_cache_wrapper(THD *thd, Item *item_arg): Item_result_field(thd), orig_item(item_arg), expr_cache(NULL), expr_value(NULL) { - DBUG_ASSERT(orig_item->fixed); + DBUG_ASSERT(orig_item->is_fixed()); Type_std_attributes::set(orig_item); maybe_null= orig_item->maybe_null; - with_sum_func= orig_item->with_sum_func; + copy_with_sum_func(orig_item); with_param= orig_item->with_param; with_field= orig_item->with_field; name= item_arg->name; @@ -8589,7 +8460,7 @@ void Item_cache_wrapper::print(String *str, enum_query_type query_type) bool Item_cache_wrapper::fix_fields(THD *thd __attribute__((unused)), Item **it __attribute__((unused))) { - DBUG_ASSERT(orig_item->fixed); + DBUG_ASSERT(orig_item->is_fixed()); DBUG_ASSERT(fixed); return FALSE; } @@ -8808,6 +8679,28 @@ String *Item_cache_wrapper::val_str(String* str) /** + Get the native value of the possibly cached item +*/ + +bool Item_cache_wrapper::val_native(THD *thd, Native* to) +{ + Item *cached_value; + DBUG_ENTER("Item_cache_wrapper::val_native"); + if (!expr_cache) + DBUG_RETURN(val_native_from_item(thd, orig_item, to)); + + if ((cached_value= check_cache())) + DBUG_RETURN(val_native_from_item(thd, cached_value, to)); + + cache(); + if ((null_value= expr_value->null_value)) + DBUG_RETURN(true); + DBUG_RETURN(expr_value->val_native(thd, to)); +} + + + +/** Get the decimal value of the possibly cached item */ @@ -8892,18 +8785,18 @@ bool Item_cache_wrapper::is_null() Get the date value of the possibly cached item */ -bool Item_cache_wrapper::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_cache_wrapper::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { Item *cached_value; DBUG_ENTER("Item_cache_wrapper::get_date"); if (!expr_cache) - DBUG_RETURN((null_value= orig_item->get_date(ltime, fuzzydate))); + DBUG_RETURN((null_value= orig_item->get_date(thd, ltime, fuzzydate))); if ((cached_value= check_cache())) - DBUG_RETURN((null_value= cached_value->get_date(ltime, fuzzydate))); + DBUG_RETURN((null_value= cached_value->get_date(thd, ltime, fuzzydate))); cache(); - DBUG_RETURN((null_value= expr_value->get_date(ltime, fuzzydate))); + DBUG_RETURN((null_value= expr_value->get_date(thd, ltime, fuzzydate))); } @@ -8919,7 +8812,7 @@ int Item_cache_wrapper::save_in_field(Field *to, bool no_conversions) Item* Item_cache_wrapper::get_tmp_table_item(THD *thd) { - if (!orig_item->with_sum_func && !orig_item->const_item()) + if (!orig_item->with_sum_func() && !orig_item->const_item()) return new (thd->mem_root) Item_temptable_field(thd, result_field); return copy_or_same(thd); } @@ -8949,7 +8842,7 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) /* view fild reference must be defined */ DBUG_ASSERT(*ref); /* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */ - if ((*ref)->fixed) + if ((*ref)->is_fixed()) { Item *ref_item= (*ref)->real_item(); if (ref_item->type() == Item::FIELD_ITEM) @@ -9250,7 +9143,6 @@ bool Item_default_value::fix_fields(THD *thd, Item **items) } thd->column_usage= save_column_usage; - real_arg= arg->real_item(); if (real_arg->type() != FIELD_ITEM) { @@ -9346,10 +9238,10 @@ my_decimal *Item_default_value::val_decimal(my_decimal *decimal_value) return Item_field::val_decimal(decimal_value); } -bool Item_default_value::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) +bool Item_default_value::get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate) { calculate(); - return Item_field::get_date(ltime, fuzzydate); + return Item_field::get_date(thd, ltime, fuzzydate); } bool Item_default_value::send(Protocol *protocol, st_value *buffer) @@ -9452,7 +9344,7 @@ my_decimal *Item_ignore_value::val_decimal(my_decimal *decimal_value) return 0; } -bool Item_ignore_value::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_ignore_value::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(0); // never should be called null_value= 1; @@ -9476,7 +9368,7 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items) { DBUG_ASSERT(fixed == 0); /* We should only check that arg is in first table */ - if (!arg->fixed) + if (!arg->is_fixed()) { bool res; TABLE_LIST *orig_next_table= context->last_name_resolution_table; @@ -9688,7 +9580,7 @@ void Item_trigger_field::cleanup() Since special nature of Item_trigger_field we should not do most of things from Item_field::cleanup() or Item_ident::cleanup() here. */ - Item::cleanup(); + Item_fixed_hybrid::cleanup(); } @@ -9747,73 +9639,14 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) { - Item_result res_type=item_cmp_type(field->result_type(), - item->result_type()); - /* - We have to check field->cmp_type() instead of res_type, - as result_type() - and thus res_type - can never be TIME_RESULT (yet). - */ - if (field->cmp_type() == TIME_RESULT) - { - MYSQL_TIME field_time, item_time, item_time2, *item_time_cmp= &item_time; - if (field->type() == MYSQL_TYPE_TIME) - { - field->get_time(&field_time); - item->get_time(&item_time); - } - else - { - field->get_date(&field_time, TIME_INVALID_DATES); - item->get_date(&item_time, TIME_INVALID_DATES); - if (item_time.time_type == MYSQL_TIMESTAMP_TIME) - if (time_to_datetime(thd, &item_time, item_time_cmp= &item_time2)) - return 1; - } - return my_time_compare(&field_time, item_time_cmp); - } - if (res_type == STRING_RESULT) - { - char item_buff[MAX_FIELD_WIDTH]; - char field_buff[MAX_FIELD_WIDTH]; - - String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin); - String field_tmp(field_buff,sizeof(field_buff),&my_charset_bin); - String *item_result= item->val_str(&item_tmp); - /* - Some implementations of Item::val_str(String*) actually modify - the field Item::null_value, hence we can't check it earlier. - */ - if (item->null_value) - return 0; - String *field_result= field->val_str(&field_tmp); - return sortcmp(field_result, item_result, field->charset()); - } - if (res_type == INT_RESULT) - return 0; // Both are of type int - if (res_type == DECIMAL_RESULT) + Type_handler_hybrid_field_type cmp(field->type_handler_for_comparison()); + if (cmp.aggregate_for_comparison(item->type_handler_for_comparison())) { - my_decimal item_buf, *item_val, - field_buf, *field_val; - item_val= item->val_decimal(&item_buf); - if (item->null_value) - return 0; - field_val= field->val_decimal(&field_buf); - return my_decimal_cmp(field_val, item_val); - } - /* - The patch for Bug#13463415 started using this function for comparing - BIGINTs. That uncovered a bug in Visual Studio 32bit optimized mode. - Prefixing the auto variables with volatile fixes the problem.... - */ - volatile double result= item->val_real(); - if (item->null_value) + // At fix_fields() time we checked that "field" and "item" are comparable + DBUG_ASSERT(0); return 0; - volatile double field_result= field->val_real(); - if (field_result < result) - return -1; - else if (field_result > result) - return 1; - return 0; + } + return cmp.type_handler()->stored_field_cmp_to_item(thd, field, item); } @@ -9876,7 +9709,6 @@ bool Item_cache_int::cache_value() String *Item_cache_int::val_str(String *str) { - DBUG_ASSERT(fixed == 1); if (!has_value()) return NULL; str->set_int(value, unsigned_flag, default_charset()); @@ -9886,7 +9718,6 @@ String *Item_cache_int::val_str(String *str) my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val) { - DBUG_ASSERT(fixed == 1); if (!has_value()) return NULL; int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_val); @@ -9895,7 +9726,6 @@ my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val) double Item_cache_int::val_real() { - DBUG_ASSERT(fixed == 1); if (!has_value()) return 0.0; return (double) value; @@ -9903,7 +9733,6 @@ double Item_cache_int::val_real() longlong Item_cache_int::val_int() { - DBUG_ASSERT(fixed == 1); if (!has_value()) return 0; return value; @@ -9943,88 +9772,12 @@ Item_cache_temporal::Item_cache_temporal(THD *thd, const Type_handler *handler) } -longlong Item_cache_temporal::val_datetime_packed() -{ - DBUG_ASSERT(fixed == 1); - if (Item_cache_temporal::field_type() == MYSQL_TYPE_TIME) - return Item::val_datetime_packed(); // TIME-to-DATETIME conversion needed - if ((!value_cached && !cache_value()) || null_value) - { - null_value= TRUE; - return 0; - } - return value; -} - - -longlong Item_cache_temporal::val_time_packed() -{ - DBUG_ASSERT(fixed == 1); - if (Item_cache_temporal::field_type() != MYSQL_TYPE_TIME) - return Item::val_time_packed(); // DATETIME-to-TIME conversion needed - if ((!value_cached && !cache_value()) || null_value) - { - null_value= TRUE; - return 0; - } - return value; -} - - -String *Item_cache_temporal::val_str(String *str) -{ - DBUG_ASSERT(fixed == 1); - if (!has_value()) - { - null_value= true; - return NULL; - } - return val_string_from_date(str); -} - - -my_decimal *Item_cache_temporal::val_decimal(my_decimal *decimal_value) -{ - DBUG_ASSERT(fixed == 1); - if ((!value_cached && !cache_value()) || null_value) - { - null_value= true; - return NULL; - } - return val_decimal_from_date(decimal_value); -} - - -longlong Item_cache_temporal::val_int() -{ - DBUG_ASSERT(fixed == 1); - if ((!value_cached && !cache_value()) || null_value) - { - null_value= true; - return 0; - } - return val_int_from_date(); -} - - -double Item_cache_temporal::val_real() -{ - DBUG_ASSERT(fixed == 1); - if ((!value_cached && !cache_value()) || null_value) - { - null_value= true; - return 0; - } - return val_real_from_date(); -} - - bool Item_cache_temporal::cache_value() { if (!example) return false; value_cached= true; - value= example->val_datetime_packed_result(); + value= example->val_datetime_packed_result(current_thd); null_value= example->null_value; return true; } @@ -10035,16 +9788,14 @@ bool Item_cache_time::cache_value() if (!example) return false; value_cached= true; - value= example->val_time_packed_result(); + value= example->val_time_packed_result(current_thd); null_value= example->null_value; return true; } -bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_cache_temporal::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - ErrConvInteger str(value); - if (!has_value()) { bzero((char*) ltime,sizeof(*ltime)); @@ -10059,7 +9810,8 @@ bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) int Item_cache_temporal::save_in_field(Field *field, bool no_conversions) { MYSQL_TIME ltime; - if (get_date(<ime, 0)) + // This is a temporal type. No nanoseconds, so round mode is not important. + if (get_date(field->get_thd(), <ime, TIME_CONV_NONE | TIME_FRAC_NONE)) return set_field_to_null_with_conversions(field, no_conversions); field->set_notnull(); int error= field->store_time_dec(<ime, decimals); @@ -10102,24 +9854,80 @@ Item *Item_cache_temporal::convert_to_basic_const_item(THD *thd) Item *Item_cache_datetime::make_literal(THD *thd) { MYSQL_TIME ltime; - unpack_time(val_datetime_packed(), <ime, MYSQL_TIMESTAMP_DATETIME); + unpack_time(val_datetime_packed(thd), <ime, MYSQL_TIMESTAMP_DATETIME); return new (thd->mem_root) Item_datetime_literal(thd, <ime, decimals); } Item *Item_cache_date::make_literal(THD *thd) { MYSQL_TIME ltime; - unpack_time(val_datetime_packed(), <ime, MYSQL_TIMESTAMP_DATE); + unpack_time(val_datetime_packed(thd), <ime, MYSQL_TIMESTAMP_DATE); return new (thd->mem_root) Item_date_literal(thd, <ime); } Item *Item_cache_time::make_literal(THD *thd) { MYSQL_TIME ltime; - unpack_time(val_time_packed(), <ime, MYSQL_TIMESTAMP_TIME); + unpack_time(val_time_packed(thd), <ime, MYSQL_TIMESTAMP_TIME); return new (thd->mem_root) Item_time_literal(thd, <ime, decimals); } + +int Item_cache_timestamp::save_in_field(Field *field, bool no_conversions) +{ + if (!has_value()) + return set_field_to_null_with_conversions(field, no_conversions); + return m_native.save_in_field(field, decimals); +} + + +bool Item_cache_timestamp::val_native(THD *thd, Native *to) +{ + if (!has_value()) + { + null_value= true; + return true; + } + return null_value= to->copy(m_native); +} + + +Datetime Item_cache_timestamp::to_datetime(THD *thd) +{ + DBUG_ASSERT(is_fixed() == 1); + if (!has_value()) + { + null_value= true; + return Datetime(); + } + return Datetime(thd, Timestamp_or_zero_datetime(m_native).tv()); +} + + +bool Item_cache_timestamp::get_date(THD *thd, MYSQL_TIME *ltime, + date_mode_t fuzzydate) +{ + if (!has_value()) + { + set_zero_time(ltime, MYSQL_TIMESTAMP_DATETIME); + return true; + } + Timestamp_or_zero_datetime tm(m_native); + return (null_value= tm.to_TIME(thd, ltime, fuzzydate)); +} + + +bool Item_cache_timestamp::cache_value() +{ + if (!example) + return false; + value_cached= true; + null_value= example->val_native_with_conversion_result(current_thd, &m_native, + type_handler()); + return true; +} + + bool Item_cache_real::cache_value() { if (!example) @@ -10133,7 +9941,6 @@ bool Item_cache_real::cache_value() double Item_cache_real::val_real() { - DBUG_ASSERT(fixed == 1); if (!has_value()) return 0.0; return value; @@ -10141,7 +9948,6 @@ double Item_cache_real::val_real() longlong Item_cache_real::val_int() { - DBUG_ASSERT(fixed == 1); if (!has_value()) return 0; return Converter_double_to_longlong(value, unsigned_flag).result(); @@ -10150,7 +9956,6 @@ longlong Item_cache_real::val_int() String* Item_cache_real::val_str(String *str) { - DBUG_ASSERT(fixed == 1); if (!has_value()) return NULL; str->set_real(value, decimals, default_charset()); @@ -10160,7 +9965,6 @@ String* Item_cache_real::val_str(String *str) my_decimal *Item_cache_real::val_decimal(my_decimal *decimal_val) { - DBUG_ASSERT(fixed == 1); if (!has_value()) return NULL; double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val); @@ -10195,38 +9999,22 @@ bool Item_cache_decimal::cache_value() double Item_cache_decimal::val_real() { - DBUG_ASSERT(fixed); - double res; - if (!has_value()) - return 0.0; - my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res); - return res; + return !has_value() ? 0.0 : decimal_value.to_double(); } longlong Item_cache_decimal::val_int() { - DBUG_ASSERT(fixed); - longlong res; - if (!has_value()) - return 0; - my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &res); - return res; + return !has_value() ? 0 : decimal_value.to_longlong(unsigned_flag); } String* Item_cache_decimal::val_str(String *str) { - DBUG_ASSERT(fixed); - if (!has_value()) - return NULL; - my_decimal_round(E_DEC_FATAL_ERROR, &decimal_value, decimals, FALSE, - &decimal_value); - my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, str); - return str; + return !has_value() ? NULL : + decimal_value.to_string_round(str, decimals, &decimal_value); } my_decimal *Item_cache_decimal::val_decimal(my_decimal *val) { - DBUG_ASSERT(fixed); if (!has_value()) return NULL; return &decimal_value; @@ -10243,9 +10031,8 @@ Item *Item_cache_decimal::convert_to_basic_const_item(THD *thd) new_item= (Item*) new (thd->mem_root) Item_null(thd); else { - my_decimal decimal_value; - my_decimal *result= val_decimal(&decimal_value); - new_item= (Item*) new (thd->mem_root) Item_decimal(thd, result); + VDec tmp(this); + new_item= (Item*) new (thd->mem_root) Item_decimal(thd, tmp.ptr()); } return new_item; } @@ -10278,7 +10065,6 @@ bool Item_cache_str::cache_value() double Item_cache_str::val_real() { - DBUG_ASSERT(fixed == 1); if (!has_value()) return 0.0; return value ? double_from_string_with_check(value) : 0.0; @@ -10287,7 +10073,6 @@ double Item_cache_str::val_real() longlong Item_cache_str::val_int() { - DBUG_ASSERT(fixed == 1); if (!has_value()) return 0; return value ? longlong_from_string_with_check(value) : 0; @@ -10296,7 +10081,6 @@ longlong Item_cache_str::val_int() String* Item_cache_str::val_str(String *str) { - DBUG_ASSERT(fixed == 1); if (!has_value()) return 0; return value; @@ -10305,7 +10089,6 @@ String* Item_cache_str::val_str(String *str) my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val) { - DBUG_ASSERT(fixed == 1); if (!has_value()) return NULL; return value ? decimal_from_string_with_check(decimal_val, value) : 0; @@ -10489,7 +10272,7 @@ String *Item_type_holder::val_str(String*) return 0; } -bool Item_type_holder::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_type_holder::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(0); // should never be called return true; @@ -10498,7 +10281,7 @@ bool Item_type_holder::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) void Item_result_field::cleanup() { DBUG_ENTER("Item_result_field::cleanup()"); - Item::cleanup(); + Item_fixed_hybrid::cleanup(); result_field= 0; DBUG_VOID_RETURN; } diff --git a/sql/item.h b/sql/item.h index adfc8e4bc6e..4f73230bfdd 100644 --- a/sql/item.h +++ b/sql/item.h @@ -100,7 +100,10 @@ class sp_head; class Protocol; struct TABLE_LIST; void item_init(void); /* Init item functions */ +class Item_basic_value; +class Item_result_field; class Item_field; +class Item_ref; class Item_param; class user_var_entry; class JOIN; @@ -108,6 +111,7 @@ struct KEY_FIELD; struct SARGABLE_PARAM; class RANGE_OPT_PARAM; class SEL_TREE; +class With_sum_func_cache; enum precedence { LOWEST_PRECEDENCE, @@ -597,6 +601,7 @@ typedef bool (Item::*Item_processor) (void *arg); typedef bool (Item::*Item_analyzer) (uchar **argp); typedef Item* (Item::*Item_transformer) (THD *thd, uchar *arg); typedef void (*Cond_traverser) (const Item *item, void *arg); +typedef bool (Item::*Pushdown_checker) (uchar *arg); struct st_cond_statistic; @@ -629,6 +634,85 @@ public: String_copier_for_item(THD *thd): m_thd(thd) { } }; + +/** + A helper class describing what kind of Item created a temporary field. + - If m_field is set, then the temporary field was created from Field + (e.g. when the Item was Item_field, or Item_ref pointing to Item_field) + - If m_default_field is set, then there is a usable DEFAULT value. + (e.g. when the Item is Item_field) + - If m_item_result_field is set, then the temporary field was created + from certain sub-types of Item_result_field (e.g. Item_func) + See create_tmp_field() in sql_select.cc for details. +*/ + +class Tmp_field_src +{ + Field *m_field; + Field *m_default_field; + Item_result_field *m_item_result_field; +public: + Tmp_field_src() + :m_field(0), + m_default_field(0), + m_item_result_field(0) + { } + Field *field() const { return m_field; } + Field *default_field() const { return m_default_field; } + Item_result_field *item_result_field() const { return m_item_result_field; } + void set_field(Field *field) { m_field= field; } + void set_default_field(Field *field) { m_default_field= field; } + void set_item_result_field(Item_result_field *item) + { m_item_result_field= item; } +}; + + +/** + Parameters for create_tmp_field_ex(). + See create_tmp_field() in sql_select.cc for details. +*/ + +class Tmp_field_param +{ + bool m_group; + bool m_modify_item; + bool m_table_cant_handle_bit_fields; + bool m_make_copy_field; +public: + Tmp_field_param(bool group, + bool modify_item, + bool table_cant_handle_bit_fields, + bool make_copy_field) + :m_group(group), + m_modify_item(modify_item), + m_table_cant_handle_bit_fields(table_cant_handle_bit_fields), + m_make_copy_field(make_copy_field) + { } + bool group() const { return m_group; } + bool modify_item() const { return m_modify_item; } + bool table_cant_handle_bit_fields() const + { return m_table_cant_handle_bit_fields; } + bool make_copy_field() const { return m_make_copy_field; } + void set_modify_item(bool to) { m_modify_item= to; } +}; + + +class Item_const +{ +public: + virtual ~Item_const() {} + virtual const Type_all_attributes *get_type_all_attributes_from_const() const= 0; + virtual bool const_is_null() const { return false; } + virtual const longlong *const_ptr_longlong() const { return NULL; } + virtual const double *const_ptr_double() const { return NULL; } + virtual const my_decimal *const_ptr_my_decimal() const { return NULL; } + virtual const MYSQL_TIME *const_ptr_mysql_time() const { return NULL; } + virtual const String *const_ptr_string() const { return NULL; } +}; + + +/****************************************************************************/ + class Item: public Value_source, public Type_all_attributes { @@ -653,16 +737,26 @@ public: static void operator delete(void *ptr, MEM_ROOT *mem_root) {} enum Type {FIELD_ITEM= 0, FUNC_ITEM, SUM_FUNC_ITEM, - WINDOW_FUNC_ITEM, STRING_ITEM, - INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM, - COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, - PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, - FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, + WINDOW_FUNC_ITEM, + /* + NOT NULL literal-alike constants, which do not change their + value during an SQL statement execution, but can optionally + change their value between statements: + - Item_literal - real NOT NULL constants + - Item_param - can change between statements + - Item_splocal - can change between statements + - Item_user_var_as_out_param - hack + Note, Item_user_var_as_out_param actually abuses the type code. + It should be moved out of the Item tree eventually. + */ + CONST_ITEM, + NULL_ITEM, // Item_null or Item_param bound to NULL + COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, + PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, + FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER, - PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM, - XPATH_NODESET, XPATH_NODESET_CMP, - VIEW_FIXER_ITEM, EXPR_CACHE_ITEM, - DATE_ITEM}; + PARAM_ITEM, TRIGGER_FIELD_ITEM, + EXPR_CACHE_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; @@ -704,11 +798,34 @@ protected: */ Field *tmp_table_field_from_field_type(TABLE *table) { + DBUG_ASSERT(is_fixed()); const Type_handler *h= type_handler()->type_handler_for_tmp_table(this); return h->make_and_init_table_field(&name, Record_addr(maybe_null), *this, table); } + /** + Create a temporary field for a simple Item, which does not + need any special action after the field creation: + - is not an Item_field descendant (and not a reference to Item_field) + - is not an Item_result_field descendant + - does not need to copy any DEFAULT value to the result Field + - does not need to set Field::is_created_from_null_item for the result + See create_tmp_field_ex() for details on parameters and return values. + */ + Field *create_tmp_field_ex_simple(TABLE *table, + Tmp_field_src *src, + const Tmp_field_param *param) + { + DBUG_ASSERT(!param->make_copy_field()); + DBUG_ASSERT(!is_result_field()); + DBUG_ASSERT(type() != NULL_ITEM); + return tmp_table_field_from_field_type(table); + } Field *create_tmp_field_int(TABLE *table, uint convert_int_length); + Field *tmp_table_field_from_field_type_maybe_null(TABLE *table, + Tmp_field_src *src, + const Tmp_field_param *param, + bool is_explicit_null); void push_note_converted_to_negative_complement(THD *thd); void push_note_converted_to_positive_complement(THD *thd); @@ -716,21 +833,21 @@ protected: /* Helper methods, to get an Item value from another Item */ double val_real_from_item(Item *item) { - DBUG_ASSERT(fixed == 1); + DBUG_ASSERT(is_fixed()); double value= item->val_real(); null_value= item->null_value; return value; } longlong val_int_from_item(Item *item) { - DBUG_ASSERT(fixed == 1); + DBUG_ASSERT(is_fixed()); longlong value= item->val_int(); null_value= item->null_value; return value; } String *val_str_from_item(Item *item, String *str) { - DBUG_ASSERT(fixed == 1); + DBUG_ASSERT(is_fixed()); String *res= item->val_str(str); if (res) res->set_charset(collation.collation); @@ -738,33 +855,48 @@ protected: res= NULL; return res; } + bool val_native_from_item(THD *thd, Item *item, Native *to) + { + DBUG_ASSERT(is_fixed()); + null_value= item->val_native(thd, to); + DBUG_ASSERT(null_value == item->null_value); + return null_value; + } + bool val_native_from_field(Field *field, Native *to) + { + if ((null_value= field->is_null())) + return true; + return (null_value= field->val_native(to)); + } + bool val_native_with_conversion_from_item(THD *thd, Item *item, Native *to, + const Type_handler *handler) + { + DBUG_ASSERT(is_fixed()); + return null_value= item->val_native_with_conversion(thd, to, handler); + } my_decimal *val_decimal_from_item(Item *item, my_decimal *decimal_value) { - DBUG_ASSERT(fixed == 1); + DBUG_ASSERT(is_fixed()); my_decimal *value= item->val_decimal(decimal_value); if ((null_value= item->null_value)) value= NULL; return value; } - bool get_date_from_item(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date_from_item(THD *thd, Item *item, + MYSQL_TIME *ltime, date_mode_t fuzzydate) { - bool rc= item->get_date(ltime, fuzzydate); + bool rc= item->get_date(thd, ltime, fuzzydate); null_value= MY_TEST(rc || item->null_value); return rc; } - /* - This method is used if the item was not null but convertion to - TIME/DATE/DATETIME failed. We return a zero date if allowed, - otherwise - null. - */ - bool make_zero_date(MYSQL_TIME *ltime, ulonglong fuzzydate); - public: + /* Cache val_str() into the own buffer, e.g. to evaluate constant expressions with subqueries in the ORDER/GROUP clauses. */ String *val_str() { return val_str(&str_value); } + virtual Item_func *get_item_func() { return NULL; } const MY_LOCALE *locale_from_val_str(); @@ -784,14 +916,12 @@ public: bool in_rollup; /* If used in GROUP BY list of a query with ROLLUP */ bool null_value; /* if item is null */ - bool with_sum_func; /* True if item contains a sum func */ bool with_param; /* True if contains an SP parameter */ bool with_window_func; /* True if item contains a window func */ /** True if any item except Item_sum contains a field. Set during parsing. */ bool with_field; - bool fixed; /* If item fixed with fix_fields */ bool is_autogenerated_name; /* indicate was name of this Item autogenerated or set by user */ // alloc & destruct is done as start of select on THD::mem_root @@ -821,7 +951,7 @@ public: bool fix_fields_if_needed(THD *thd, Item **ref) { - return fixed ? false : fix_fields(thd, ref); + return is_fixed() ? false : fix_fields(thd, ref); } bool fix_fields_if_needed_for_scalar(THD *thd, Item **ref) { @@ -835,7 +965,27 @@ public: { return fix_fields_if_needed_for_scalar(thd, ref); } - virtual bool fix_fields(THD *, Item **); + /* + By default we assume that an Item is fixed by the contstructor. + */ + virtual bool fix_fields(THD *, Item **) + { + /* + This should not normally be called, because usually before + fix_fields() we check is_fixed() to be false. + But historically we allow fix_fields() to be called for Items + who return basic_const_item()==true. + */ + DBUG_ASSERT(is_fixed()); + DBUG_ASSERT(basic_const_item()); + return false; + } + virtual bool is_fixed() const { return true; } + virtual void unfix_fields() + { + DBUG_ASSERT(0); + } + /* Fix after some tables has been pulled out. Basically re-calculate all attributes that are dependent on the tables. @@ -855,11 +1005,14 @@ public: but rather uses intermediate type conversion items. Then the method is supposed to be applied recursively. */ - virtual inline void quick_fix_field() { fixed= 1; } + virtual void quick_fix_field() + { + DBUG_ASSERT(0); + } - bool save_in_value(struct st_value *value) + bool save_in_value(THD *thd, struct st_value *value) { - return type_handler()->Item_save_in_value(this, value); + return type_handler()->Item_save_in_value(thd, this, value); } /* Function returns 1 on overflow and -1 on fatal errors */ @@ -884,6 +1037,21 @@ public: return type_handler()->field_type(); } virtual const Type_handler *type_handler() const= 0; + /** + Detects if an Item has a fixed data type which is known + even before fix_fields(). + Currently it's important only to find Items with a fixed boolean + data type. More item types can be marked in the future as having + a fixed data type (e.g. all literals, all fixed type functions, etc). + + @retval NULL if the Item type is not known before fix_fields() + @retval the pointer to the data type handler, if the data type + is known before fix_fields(). + */ + virtual const Type_handler *fixed_type_handler() const + { + return NULL; + } const Type_handler *type_handler_for_comparison() const { return type_handler()->type_handler_for_comparison(); @@ -892,13 +1060,9 @@ public: { return type_handler(); } - virtual const Type_handler *cast_to_int_type_handler() const - { - return type_handler(); - } - virtual const Type_handler *type_handler_for_system_time() const + const Type_handler *cast_to_int_type_handler() const { - return real_type_handler(); + return real_type_handler()->cast_to_int_type_handler(); } /* result_type() of an item specifies how the value should be returned */ Item_result result_type() const @@ -954,6 +1118,10 @@ public: return type_handler()->Item_get_cache(thd, this); } virtual enum Type type() const =0; + bool is_of_type(Type t, Item_result cmp) const + { + return type() == t && cmp_type() == cmp; + } /* real_type() is the type of base item. This is same as type() for most items, except Item_ref() and Item_cache_wrapper() where it @@ -1018,6 +1186,12 @@ public: If value is not null null_value flag will be reset to FALSE. */ virtual double val_real()=0; + Double_null to_double_null() + { + // val_real() must be caleed on a separate line. See to_longlong_null() + double nr= val_real(); + return Double_null(nr, null_value); + } /* Return integer representation of item. @@ -1033,6 +1207,20 @@ public: { return Longlong_hybrid(val_int(), unsigned_flag); } + Longlong_null to_longlong_null() + { + longlong nr= val_int(); + /* + C++ does not guarantee the order of parameter evaluation, + so to make sure "null_value" is passed to the constructor + after the val_int() call, val_int() is caled on a separate line. + */ + return Longlong_null(nr, null_value); + } + Longlong_hybrid_null to_longlong_hybrid_null() + { + return Longlong_hybrid_null(to_longlong_null(), unsigned_flag); + } /** Get a value for CAST(x AS SIGNED). Too large positive unsigned integer values are converted @@ -1054,7 +1242,6 @@ public: { return cast_to_int_type_handler()->Item_val_int_unsigned_typecast(this); } - longlong val_int_unsigned_typecast_from_decimal(); longlong val_int_unsigned_typecast_from_int(); longlong val_int_unsigned_typecast_from_str(); /* @@ -1108,6 +1295,60 @@ public: */ virtual String *val_str(String *str)=0; + + bool val_native_with_conversion(THD *thd, Native *to, const Type_handler *th) + { + return th->Item_val_native_with_conversion(thd, this, to); + } + bool val_native_with_conversion_result(THD *thd, Native *to, + const Type_handler *th) + { + return th->Item_val_native_with_conversion_result(thd, this, to); + } + + virtual bool val_native(THD *thd, Native *to) + { + /* + The default implementation for the Items that do not need native format: + - Item_basic_value + - Item_ident_for_show + - Item_copy + - Item_exists_subselect + - Item_sum_field + - Item_sum_or_func (default implementation) + - Item_proc + - Item_type_holder (as val_xxx() are never called for it); + - TODO: Item_name_const will need val_native() in the future, + when we add this syntax: + TIMESTAMP WITH LOCAL TIMEZONE'2001-01-01 00:00:00' + + These hybrid Item types override val_native(): + - Item_field + - Item_param + - Item_sp_variable + - Item_ref + - Item_cache_wrapper + - Item_direct_ref + - Item_direct_view_ref + - Item_ref_null_helper + - Item_sum_or_func + Note, these hybrid type Item_sum_or_func descendants + override the default implementation: + * Item_sum_hybrid + * Item_func_hybrid_field_type + * Item_func_min_max + * Item_func_sp + * Item_func_last_value + * Item_func_rollup_const + */ + DBUG_ASSERT(0); + return null_value= true; + } + virtual bool val_native_result(THD *thd, Native *to) + { + return val_native(thd, to); + } + /* Returns string representation of this item in ASCII format. @@ -1220,7 +1461,7 @@ public: { return type_handler()->Item_val_bool(this); } - virtual String *val_nodeset(String*) { return 0; } + virtual String *val_raw(String*) { return 0; } /* save_val() is method of val_* family which stores value in the given @@ -1235,28 +1476,15 @@ public: /* Helper functions, see item_sum.cc */ String *val_string_from_real(String *str); String *val_string_from_int(String *str); - String *val_string_from_decimal(String *str); - String *val_string_from_date(String *str); my_decimal *val_decimal_from_real(my_decimal *decimal_value); my_decimal *val_decimal_from_int(my_decimal *decimal_value); my_decimal *val_decimal_from_string(my_decimal *decimal_value); - my_decimal *val_decimal_from_date(my_decimal *decimal_value); - my_decimal *val_decimal_from_time(my_decimal *decimal_value); - longlong val_int_from_decimal(); - longlong val_int_from_date(); longlong val_int_from_real() { - DBUG_ASSERT(fixed == 1); + DBUG_ASSERT(is_fixed()); return Converter_double_to_longlong_with_warn(val_real(), false).result(); } longlong val_int_from_str(int *error); - double val_real_from_decimal(); - double val_real_from_date(); - - // Get TIME, DATE or DATETIME using proper sql_mode flags for the field type - bool get_temporal_with_sql_mode(MYSQL_TIME *ltime); - // Check NULL value for a TIME, DATE or DATETIME expression - bool is_null_from_temporal(); int save_time_in_field(Field *field, bool no_conversions); int save_date_in_field(Field *field, bool no_conversions); @@ -1317,6 +1545,14 @@ public: a constant expression. Used in the optimizer to propagate basic constants. */ virtual bool basic_const_item() const { return 0; } + /* + Test if "this" is an ORDER position (rather than an expression). + Notes: + - can be called before fix_fields(). + - local SP variables (even of integer types) are always expressions, not + positions. (And they can't be used before fix_fields is called for them). + */ + virtual bool is_order_clause_position() const { return false; } /* cloning of constant items (0 if it is not const) */ virtual Item *clone_item(THD *thd) { return 0; } virtual Item* build_clone(THD *thd) { return get_copy(thd); } @@ -1364,14 +1600,14 @@ public: /** TIME or DATETIME precision of the item: 0..6 */ - uint time_precision() + uint time_precision(THD *thd) { - return const_item() ? type_handler()->Item_time_precision(this) : + return const_item() ? type_handler()->Item_time_precision(thd, this) : MY_MIN(decimals, TIME_SECOND_PART_DIGITS); } - uint datetime_precision() + uint datetime_precision(THD *thd) { - return const_item() ? type_handler()->Item_datetime_precision(this) : + return const_item() ? type_handler()->Item_datetime_precision(thd, this) : MY_MIN(decimals, TIME_SECOND_PART_DIGITS); } virtual longlong val_int_min() const @@ -1469,78 +1705,33 @@ public: void split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, Item **ref, uint flags); - virtual bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)= 0; - bool get_date_from_int(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_from_year(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_from_real(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_from_decimal(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_from_string(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_time(MYSQL_TIME *ltime) - { return get_date(ltime, Time::flags_for_get_date()); } - /* - Get time with automatic DATE/DATETIME to TIME conversion, - by subtracting CURRENT_DATE. - - Performce a reverse operation to CAST(time AS DATETIME) - Suppose: - - we have a set of items (typically with the native MYSQL_TYPE_TIME type) - whose item->get_date() return TIME1 value, and - - CAST(AS DATETIME) for the same Items return DATETIME1, - after applying time-to-datetime conversion to TIME1. - - then all items (typically of the native MYSQL_TYPE_{DATE|DATETIME} types) - whose get_date() return DATETIME1 must also return TIME1 from - get_time_with_conversion() - - @param thd - the thread, its variables.old_mode is checked - to decide if use simple YYYYMMDD truncation (old mode), - or perform full DATETIME-to-TIME conversion with - CURRENT_DATE subtraction. - @param[out] ltime - store the result here - @param fuzzydate - flags to be used for the get_date() call. - Normally, should include TIME_TIME_ONLY, to let - the called low-level routines, e.g. str_to_date(), - know that we prefer TIME rather that DATE/DATETIME - and do less conversion outside of the low-level - routines. - - @returns true - on error, e.g. get_date() returned NULL value, - or get_date() returned DATETIME/DATE with non-zero - YYYYMMDD part. - @returns false - on success - */ - bool get_time_with_conversion(THD *thd, MYSQL_TIME *ltime, - ulonglong fuzzydate); + virtual bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)= 0; + bool get_date_from_int(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool get_date_from_real(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool get_date_from_string(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool get_time(THD *thd, MYSQL_TIME *ltime) + { return get_date(thd, ltime, Time::Options(thd)); } // Get a DATE or DATETIME value in numeric packed format for comparison - virtual longlong val_datetime_packed() + virtual longlong val_datetime_packed(THD *thd) { - ulonglong fuzzydate= TIME_FUZZY_DATES | TIME_INVALID_DATES; - Datetime dt(current_thd, this, fuzzydate); - return dt.is_valid_datetime() ? pack_time(dt.get_mysql_time()) : 0; + return Datetime(thd, this, Datetime::Options_cmp(thd)).to_packed(); } // Get a TIME value in numeric packed format for comparison - virtual longlong val_time_packed() + virtual longlong val_time_packed(THD *thd) { - Time tm(this, Time::comparison_flags_for_get_date()); - return tm.is_valid_time() ? pack_time(tm.get_mysql_time()) : 0; + return Time(thd, this, Time::Options_cmp(thd)).to_packed(); } - longlong val_datetime_packed_result(); - longlong val_time_packed_result() + longlong val_datetime_packed_result(THD *thd); + longlong val_time_packed_result(THD *thd) { MYSQL_TIME ltime; - ulonglong fuzzydate= Time::comparison_flags_for_get_date(); - return get_date_result(<ime, fuzzydate) ? 0 : pack_time(<ime); + return get_date_result(thd, <ime, Time::Options_cmp(thd)) ? 0 : + pack_time(<ime); } - // Get a temporal value in packed DATE/DATETIME or TIME format - longlong val_temporal_packed(enum_field_types f_type) - { - return f_type == MYSQL_TYPE_TIME ? val_time_packed() : - val_datetime_packed(); - } - bool get_seconds(ulonglong *sec, ulong *sec_part); - virtual bool get_date_result(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date(ltime,fuzzydate); } + virtual bool get_date_result(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date(thd, ltime,fuzzydate); } + /* The method allows to determine nullness of a complex expression without fully evaluating it, instead of calling val/result*() then @@ -1555,35 +1746,7 @@ public: */ virtual void update_null_value () { - switch (cmp_type()) { - case INT_RESULT: - (void) val_int(); - break; - case REAL_RESULT: - (void) val_real(); - break; - case DECIMAL_RESULT: - { - my_decimal tmp; - (void) val_decimal(&tmp); - } - break; - case TIME_RESULT: - { - MYSQL_TIME ltime; - (void) get_temporal_with_sql_mode(<ime); - } - break; - case STRING_RESULT: - { - StringBuffer<MAX_FIELD_WIDTH> tmp; - (void) val_str(&tmp); - } - break; - case ROW_RESULT: - DBUG_ASSERT(0); - null_value= true; - } + return type_handler()->Item_update_null_value(this); } /* @@ -1601,10 +1764,9 @@ public: set field of temporary table for Item which can be switched on temporary table during query processing (grouping and so on) */ - virtual void set_result_field(Field *field) {} virtual bool is_result_field() { return 0; } - virtual bool is_bool_type() { return false; } virtual bool is_json_type() { return false; } + virtual bool is_bool_literal() const { return false; } /* This is to handle printing of default values */ virtual bool need_parentheses_in_default() { return false; } virtual void save_in_result_field(bool no_conversions) {} @@ -1715,7 +1877,15 @@ public: or can be converted to such an exression using equalities. Not to be used for AND/OR formulas. */ - virtual bool excl_dep_on_grouping_fields(st_select_lex *sel) { return false; } + virtual bool excl_dep_on_grouping_fields(st_select_lex *sel) + { return false; } + /* + TRUE if the expression depends only on fields from the left part of + IN subquery or can be converted to such an expression using equalities. + Not to be used for AND/OR formulas. + */ + virtual bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) + { return false; } virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; } virtual bool find_function_processor (void *arg) { return 0; } @@ -1875,11 +2045,17 @@ public: return Type_handler::type_handler_long_or_longlong(max_char_length()); } - virtual Field *create_tmp_field(bool group, TABLE *table) - { - return tmp_table_field_from_field_type(table); - } - + /** + Create field for temporary table. + @param table Temporary table + @param [OUT] src Who created the fields + @param param Create parameters + @retval NULL (on error) + @retval a pointer to a newly create Field (on success) + */ + virtual Field *create_tmp_field_ex(TABLE *table, + Tmp_field_src *src, + const Tmp_field_param *param)= 0; virtual Item_field *field_for_view_update() { return 0; } virtual Item *neg_transformer(THD *thd) { return NULL; } @@ -1891,8 +2067,12 @@ public: { return this; } virtual Item *derived_field_transformer_for_where(THD *thd, uchar *arg) { return this; } - virtual Item *derived_grouping_field_transformer_for_where(THD *thd, - uchar *arg) + virtual Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) + { return this; } + /* Now is not used. */ + virtual Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg) + { return this; } + virtual Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg) { return this; } virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg) { return this; } @@ -1946,6 +2126,7 @@ public: delete this; } + virtual const Item_const *get_item_const() const { return NULL; } virtual Item_splocal *get_item_splocal() { return 0; } virtual Rewritable_query_parameter *get_rewritable_query_parameter() { return 0; } @@ -2019,13 +2200,16 @@ public: /* Return TRUE if the item points to a column of an outer-joined table. */ - virtual bool is_outer_field() const { DBUG_ASSERT(fixed); return FALSE; } + virtual bool is_outer_field() const { DBUG_ASSERT(is_fixed()); return FALSE; } /** Checks if this item or any of its decendents contains a subquery. This is a replacement of the former Item::has_subquery() and Item::with_subselect. */ - virtual bool with_subquery() const { DBUG_ASSERT(fixed); return false; } + virtual bool with_subquery() const { DBUG_ASSERT(is_fixed()); return false; } + + virtual bool with_sum_func() const { return false; } + virtual With_sum_func_cache* get_with_sum_func_cache() { return NULL; } Item* set_expr_cache(THD *thd); @@ -2089,6 +2273,33 @@ public: { marker &= ~EXTRACTION_MASK; } + void check_pushable_cond(Pushdown_checker excl_dep_func, uchar *arg); + bool pushable_cond_checker_for_derived(uchar *arg) + { + return excl_dep_on_table(*((table_map *)arg)); + } + bool pushable_cond_checker_for_subquery(uchar *arg) + { + return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg); + } + Item *get_corresponding_field_in_insubq(Item_in_subselect *subq_pred); + Item *build_pushable_cond(THD *thd, + Pushdown_checker checker, + uchar *arg); + /* + Checks if this item depends only on the arg table + */ + bool pushable_equality_checker_for_derived(uchar *arg) + { + return (used_tables() == *((table_map *)arg)); + } + /* + Checks if this item consists in the left part of arg IN subquery predicate + */ + bool pushable_equality_checker_for_subquery(uchar *arg) + { + return get_corresponding_field_in_insubq((Item_in_subselect *)arg); + } }; MEM_ROOT *get_thd_memroot(THD *thd); @@ -2103,6 +2314,66 @@ inline Item* get_item_copy (THD *thd, T* item) } +#ifndef DBUG_OFF +/** + A helper class to print the data type and the value for an Item + in debug builds. +*/ +class DbugStringItemTypeValue: public StringBuffer<128> +{ +public: + DbugStringItemTypeValue(THD *thd, const Item *item) + { + append('('); + append(item->type_handler()->name().ptr()); + append(')'); + const_cast<Item*>(item)->print(this, QT_EXPLAIN); + } +}; +#endif + +class With_sum_func_cache +{ +protected: + bool m_with_sum_func; // True if the owner item contains a sum func +public: + With_sum_func_cache() + :m_with_sum_func(false) + { } + With_sum_func_cache(const Item *a) + :m_with_sum_func(a->with_sum_func()) + { } + With_sum_func_cache(const Item *a, const Item *b) + :m_with_sum_func(a->with_sum_func() || b->with_sum_func()) + { } + With_sum_func_cache(const Item *a, const Item *b, const Item *c) + :m_with_sum_func(a->with_sum_func() || b->with_sum_func() || + c->with_sum_func()) + { } + With_sum_func_cache(const Item *a, const Item *b, const Item *c, + const Item *d) + :m_with_sum_func(a->with_sum_func() || b->with_sum_func() || + c->with_sum_func() || d->with_sum_func()) + { } + With_sum_func_cache(const Item *a, const Item *b, const Item *c, + const Item *d, const Item *e) + :m_with_sum_func(a->with_sum_func() || b->with_sum_func() || + c->with_sum_func() || d->with_sum_func() || + e->with_sum_func()) + { } + void set_with_sum_func() { m_with_sum_func= true; } + void reset_with_sum_func() { m_with_sum_func= false; } + void copy_with_sum_func(const Item *item) + { + m_with_sum_func= item->with_sum_func(); + } + void join_with_sum_func(const Item *item) + { + m_with_sum_func|= item->with_sum_func(); + } +}; + + /* This class is a replacement for the former member Item::with_subselect. Determines if the descendant Item is a subselect or some of @@ -2226,6 +2497,17 @@ protected: } return true; } + bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) + { + for (uint i= 0; i < arg_count; i++) + { + if (args[i]->const_item()) + continue; + if (!args[i]->excl_dep_on_in_subq_left_part(subq_pred)) + return false; + } + return true; + } public: Item_args(void) :args(NULL), arg_count(0) @@ -2277,6 +2559,30 @@ public: { args[arg_count++]= item; } + /** + Extract row elements from the given position. + For example, for this input: (1,2),(3,4),(5,6) + pos=0 will extract (1,3,5) + pos=1 will extract (2,4,6) + @param thd - current thread, to allocate memory on its mem_root + @param rows - an array of compatible ROW-type items + @param pos - the element position to extract + */ + bool alloc_and_extract_row_elements(THD *thd, const Item_args *rows, uint pos) + { + DBUG_ASSERT(rows->argument_count() > 0); + DBUG_ASSERT(rows->arguments()[0]->cols() > pos); + if (alloc_arguments(thd, rows->argument_count())) + return true; + for (uint i= 0; i < rows->argument_count(); i++) + { + DBUG_ASSERT(rows->arguments()[0]->cols() == rows->arguments()[i]->cols()); + Item *arg= rows->arguments()[i]->element_index(pos); + add_argument(arg); + } + DBUG_ASSERT(argument_count() == rows->argument_count()); + return false; + } inline Item **arguments() const { return args; } inline uint argument_count() const { return arg_count; } inline void remove_arguments() { arg_count=0; } @@ -2311,27 +2617,39 @@ public: class Item_string; -/** - A common class for Item_basic_constant and Item_param -*/ -class Item_basic_value :public Item +class Item_fixed_hybrid: public Item { - bool is_basic_value(const Item *item, Type type_arg) const - { - return item->basic_const_item() && item->type() == type_arg; - } - bool is_basic_value(Type type_arg) const +public: + bool fixed; // If item was fixed with fix_fields +public: + Item_fixed_hybrid(THD *thd): Item(thd), fixed(false) + { } + Item_fixed_hybrid(THD *thd, Item_fixed_hybrid *item) + :Item(thd, item), fixed(item->fixed) + { } + bool fix_fields(THD *thd, Item **ref) { - return basic_const_item() && type() == type_arg; + DBUG_ASSERT(!fixed); + fixed= true; + return false; } - bool str_eq(const String *value, - const String *other, CHARSET_INFO *cs, bool binary_cmp) const + void cleanup() { - return binary_cmp ? - value->bin_eq(other) : - collation.collation == cs && value->eq(other, collation.collation); + Item::cleanup(); + fixed= false; } + void quick_fix_field() { fixed= true; } + void unfix_fields() { fixed= false; } + bool is_fixed() const { return fixed; } +}; + +/** + A common class for Item_basic_constant and Item_param +*/ +class Item_basic_value :public Item, + public Item_const +{ protected: // Value metadata, e.g. to make string processing easier class Metadata: private MY_STRING_METADATA @@ -2368,66 +2686,40 @@ protected: fix_charset_and_length(str.charset(), dv, Metadata(&str)); } Item_basic_value(THD *thd): Item(thd) {} - /* - In the xxx_eq() methods below we need to cast off "const" to - call val_xxx(). This is OK for Item_basic_constant and Item_param. - */ - bool null_eq(const Item *item) const - { - DBUG_ASSERT(is_basic_value(NULL_ITEM)); - return item->type() == NULL_ITEM; - } - bool str_eq(const String *value, const Item *item, bool binary_cmp) const - { - DBUG_ASSERT(is_basic_value(STRING_ITEM)); - return is_basic_value(item, STRING_ITEM) && - str_eq(value, ((Item_basic_value*)item)->val_str(NULL), - item->collation.collation, binary_cmp); - } - bool real_eq(double value, const Item *item) const - { - DBUG_ASSERT(is_basic_value(REAL_ITEM)); - return is_basic_value(item, REAL_ITEM) && - value == ((Item_basic_value*)item)->val_real(); - } - bool int_eq(longlong value, const Item *item) const +public: + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) { - DBUG_ASSERT(is_basic_value(INT_ITEM)); - return is_basic_value(item, INT_ITEM) && - value == ((Item_basic_value*)item)->val_int() && - (value >= 0 || item->unsigned_flag == unsigned_flag); + + /* + create_tmp_field_ex() for this type of Items is called for: + - CREATE TABLE ... SELECT + - In ORDER BY: SELECT max(a) FROM t1 GROUP BY a ORDER BY 'const'; + - In CURSORS: + DECLARE c CURSOR FOR SELECT 'test'; + OPEN c; + */ + return tmp_table_field_from_field_type_maybe_null(table, src, param, + type() == Item::NULL_ITEM); } + bool eq(const Item *item, bool binary_cmp) const; + const Type_all_attributes *get_type_all_attributes_from_const() const + { return this; } }; class Item_basic_constant :public Item_basic_value { - table_map used_table_map; public: - Item_basic_constant(THD *thd): Item_basic_value(thd), used_table_map(0) {}; - void set_used_tables(table_map map) { used_table_map= map; } - table_map used_tables() const { return used_table_map; } - bool check_vcol_func_processor(void *arg) { return FALSE;} + Item_basic_constant(THD *thd): Item_basic_value(thd) {}; + bool check_vcol_func_processor(void *arg) { return false; } + const Item_const *get_item_const() const { return this; } virtual Item_basic_constant *make_string_literal_concat(THD *thd, const LEX_CSTRING *) { DBUG_ASSERT(0); return this; } - /* to prevent drop fixed flag (no need parent cleanup call) */ - void cleanup() - { - /* - Restore the original field name as it might not have been allocated - in the statement memory. If the name is auto generated, it must be - done again between subsequent executions of a prepared statement. - */ - if (orig_name) - { - name.str= orig_name; - name.length= strlen(orig_name); - } - } }; @@ -2438,7 +2730,7 @@ public: - CASE expression (Item_case_expr); *****************************************************************************/ -class Item_sp_variable :public Item +class Item_sp_variable :public Item_fixed_hybrid { protected: /* @@ -2470,7 +2762,8 @@ public: longlong val_int(); String *val_str(String *sp); my_decimal *val_decimal(my_decimal *decimal_value); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool val_native(THD *thd, Native *to); bool is_null(); public: @@ -2478,6 +2771,11 @@ public: inline bool const_item() const; + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + return create_tmp_field_ex_simple(table, src, param); + } inline int save_in_field(Field *field, bool no_conversions); inline bool send(Protocol *protocol, st_value *buffer); bool check_vcol_func_processor(void *arg) @@ -2581,6 +2879,20 @@ public: */ Field *create_field_for_create_select(TABLE *table) { return create_table_field_from_handler(table); } + + bool is_valid_limit_clause_variable_with_error() const + { + /* + In case if the variable has an anchored data type, e.g.: + DECLARE a TYPE OF t1.a; + type_handler() is set to &type_handler_null and this + function detects such variable as not valid in LIMIT. + */ + if (type_handler()->is_limit_clause_valid_type()) + return true; + my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0)); + return false; + } }; @@ -2727,11 +3039,10 @@ inline enum Item::Type Item_case_expr::type() const extract a common base with class Item_ref, too. */ -class Item_name_const : public Item +class Item_name_const : public Item_fixed_hybrid { Item *value_item; Item *name_item; - bool valid_args; public: Item_name_const(THD *thd, Item *name_arg, Item *val); @@ -2742,7 +3053,7 @@ public: longlong val_int(); String *val_str(String *sp); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool is_null(); virtual void print(String *str, enum_query_type query_type); @@ -2756,6 +3067,17 @@ public: return TRUE; } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + /* + We can get to here when using a CURSOR for a query with NAME_CONST(): + DECLARE c CURSOR FOR SELECT NAME_CONST('x','y') FROM t1; + OPEN c; + */ + return tmp_table_field_from_field_type_maybe_null(table, src, param, + type() == Item::NULL_ITEM); + } int save_in_field(Field *field, bool no_conversions) { return value_item->save_in_field(field, no_conversions); @@ -2773,15 +3095,27 @@ public: { return get_item_copy<Item_name_const>(thd, this); } }; -class Item_num: public Item_basic_constant + +class Item_literal: public Item_basic_constant +{ +public: + Item_literal(THD *thd): Item_basic_constant(thd) + { } + enum Type type() const { return CONST_ITEM; } + bool check_partition_func_processor(void *int_arg) { return false;} + bool const_item() const { return true; } + bool basic_const_item() const { return true; } +}; + + +class Item_num: public Item_literal { public: - Item_num(THD *thd): Item_basic_constant(thd) { collation.set_numeric(); } + Item_num(THD *thd): Item_literal(thd) { collation.set_numeric(); } Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs); - bool check_partition_func_processor(void *int_arg) { return FALSE;} - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } }; @@ -2790,24 +3124,26 @@ public: class st_select_lex; -class Item_result_field :public Item /* Item with result field */ +class Item_result_field :public Item_fixed_hybrid /* Item with result field */ { public: Field *result_field; /* Save result here */ - Item_result_field(THD *thd): Item(thd), result_field(0) {} + Item_result_field(THD *thd): Item_fixed_hybrid(thd), result_field(0) {} // Constructor used for Item_sum/Item_cond_and/or (see Item comment) Item_result_field(THD *thd, Item_result_field *item): - Item(thd, item), result_field(item->result_field) + Item_fixed_hybrid(thd, item), result_field(item->result_field) {} ~Item_result_field() {} /* Required with gcc 2.95 */ Field *get_tmp_table_field() { return result_field; } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param); + void get_tmp_field_src(Tmp_field_src *src, const Tmp_field_param *param); /* This implementation of used_tables() used by Item_avg_field and Item_variance_field which work when only temporary table left, so theu return table map of the temporary table. */ table_map used_tables() const { return 1; } - void set_result_field(Field *field) { result_field= field; } bool is_result_field() { return true; } void save_in_result_field(bool no_conversions) { @@ -2900,11 +3236,17 @@ public: Type_std_attributes::set(par_field->type_std_attributes()); } enum Type type() const { return FIELD_ITEM; } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + DBUG_ASSERT(0); + return 0; + } double val_real() { return field->val_real(); } longlong val_int() { return field->val_int(); } String *val_str(String *str) { return field->val_str(str); } my_decimal *val_decimal(my_decimal *dec) { return field->val_decimal(dec); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { return field->get_date(ltime, fuzzydate); } @@ -2962,6 +3304,8 @@ public: void save_result(Field *to); double val_result(); longlong val_int_result(); + bool val_native(THD *thd, Native *to); + bool val_native_result(THD *thd, Native *to); String *str_result(String* tmp); my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); @@ -3005,24 +3349,25 @@ public: const Type_handler *handler= field->type_handler(); return handler->type_handler_for_item_field(); } - const Type_handler *cast_to_int_type_handler() const - { - return field->type_handler()->cast_to_int_type_handler(); - } const Type_handler *real_type_handler() const { if (field->is_created_from_null_item) return &type_handler_null; return field->type_handler(); } + Field *create_tmp_field_from_item_field(TABLE *new_table, + Item_ref *orig_item, + const Tmp_field_param *param); + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param); TYPELIB *get_typelib() const { return field->get_typelib(); } enum_monotonicity_info get_monotonicity_info() const { return MONOTONIC_STRICT_INCREASING; } longlong val_int_endpoint(bool left_endp, bool *incl_endp); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool get_date_result(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate); bool is_null() { return field->is_null(); } void update_null_value(); void update_table_bitmaps() @@ -3032,13 +3377,7 @@ public: TABLE *tab= field->table; tab->covering_keys.intersect(field->part_of_key); if (tab->read_set) - bitmap_fast_test_and_set(tab->read_set, field->field_index); - /* - Do not mark a self-referecing virtual column. - Such virtual columns are reported as invalid. - */ - if (field->vcol_info && tab->vcol_set) - tab->mark_virtual_col(field); + tab->mark_column_with_deps(field); } } void update_used_tables() @@ -3115,10 +3454,13 @@ public: virtual Item *update_value_transformer(THD *thd, uchar *select_arg); Item *derived_field_transformer_for_having(THD *thd, uchar *arg); Item *derived_field_transformer_for_where(THD *thd, uchar *arg); - Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg); + Item *grouping_field_transformer_for_where(THD *thd, uchar *arg); + Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg); + Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg); virtual void print(String *str, enum_query_type query_type); bool excl_dep_on_table(table_map tab_map); bool excl_dep_on_grouping_fields(st_select_lex *sel); + bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred); bool cleanup_excluding_fields_processor(void *arg) { return field ? 0 : cleanup_processor(arg); } bool cleanup_excluding_const_fields_processor(void *arg) @@ -3223,22 +3565,21 @@ public: max_length= 0; name.str= name_par ? name_par : "NULL"; name.length= strlen(name.str); - fixed= 1; collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII); } enum Type type() const { return NULL_ITEM; } - bool eq(const Item *item, bool binary_cmp) const { return null_eq(item); } double val_real(); longlong val_int(); String *val_str(String *str); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); int save_in_field(Field *field, bool no_conversions); int save_safe_in_field(Field *field); bool send(Protocol *protocol, st_value *buffer); const Type_handler *type_handler() const { return &type_handler_null; } bool basic_const_item() const { return 1; } Item *clone_item(THD *thd); + bool const_is_null() const { return true; } bool is_null() { return 1; } virtual inline void print(String *str, enum_query_type query_type) @@ -3264,6 +3605,12 @@ public: { return result_field->type(); } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + DBUG_ASSERT(0); + return NULL; + } void save_in_result_field(bool no_conversions) { save_in_field(result_field, no_conversions); @@ -3331,8 +3678,8 @@ class Item_param :public Item_basic_value, All Item_param::set_xxx() make sure to do so. In the state with an assigned value: - Item_param::basic_const_item() returns true - - Item::type() returns NULL_ITEM, INT_ITEM, REAL_ITEM, DECIMAL_ITEM, - DATE_ITEM, STRING_ITEM, depending on the value assigned. + - Item::type() returns NULL_ITEM or CONST_ITEM, + depending on the value assigned. So in this state Item_param behaves in many cases like a literal. When Item_param::cleanup() is called: @@ -3355,14 +3702,6 @@ class Item_param :public Item_basic_value, DEFAULT_VALUE, IGNORE_VALUE } state; - enum Type item_type; - - void fix_type(Type type) - { - item_type= type; - fixed= true; - } - void fix_temporal(uint32 max_length_arg, uint decimals_arg); struct CONVERSION_INFO @@ -3461,7 +3800,6 @@ class Item_param :public Item_basic_value, PValue value; const String *value_query_val_str(THD *thd, String* str) const; - bool value_eq(const Item *item, bool binary_cmp) const; Item *value_clone_item(THD *thd); bool can_return_value() const; @@ -3485,10 +3823,58 @@ public: enum Type type() const { - DBUG_ASSERT(fixed || state == NO_VALUE); - return item_type; + // Don't pretend to be a constant unless value for this item is set. + switch (state) { + case NO_VALUE: return PARAM_ITEM; + case NULL_VALUE: return NULL_ITEM; + case SHORT_DATA_VALUE: return CONST_ITEM; + case LONG_DATA_VALUE: return CONST_ITEM; + case DEFAULT_VALUE: return PARAM_ITEM; + case IGNORE_VALUE: return PARAM_ITEM; + } + DBUG_ASSERT(0); + return PARAM_ITEM; + } + + bool is_order_clause_position() const + { + return state == SHORT_DATA_VALUE && + type_handler()->is_order_clause_position_type(); + } + + const Item_const *get_item_const() const + { + switch (state) { + case SHORT_DATA_VALUE: + case LONG_DATA_VALUE: + case NULL_VALUE: + return this; + case IGNORE_VALUE: + case DEFAULT_VALUE: + case NO_VALUE: + break; + } + return NULL; } + bool const_is_null() const { return state == NULL_VALUE; } + bool can_return_const_value(Item_result type) const + { + return can_return_value() && + value.type_handler()->cmp_type() == type && + type_handler()->cmp_type() == type; + } + const longlong *const_ptr_longlong() const + { return can_return_const_value(INT_RESULT) ? &value.integer : NULL; } + const double *const_ptr_double() const + { return can_return_const_value(REAL_RESULT) ? &value.real : NULL; } + const my_decimal *const_ptr_my_decimal() const + { return can_return_const_value(DECIMAL_RESULT) ? &value.m_decimal : NULL; } + const MYSQL_TIME *const_ptr_mysql_time() const + { return can_return_const_value(TIME_RESULT) ? &value.time : NULL; } + const String *const_ptr_string() const + { return can_return_const_value(STRING_RESULT) ? &value.m_string : NULL; } + double val_real() { return can_return_value() ? value.val_real() : 0e0; @@ -3505,7 +3891,12 @@ public: { return can_return_value() ? value.val_str(str, this) : NULL; } - bool get_date(MYSQL_TIME *tm, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *tm, date_mode_t fuzzydate); + bool val_native(THD *thd, Native *to) + { + return Item_param::type_handler()->Item_param_val_native(thd, this, to); + } + int save_in_field(Field *field, bool no_conversions); void set_default(); @@ -3582,8 +3973,14 @@ public: so no one will use parameters value in fix_fields still parameter is constant during execution. */ + bool const_item() const + { + return state != NO_VALUE; + } virtual table_map used_tables() const - { return state != NO_VALUE ? (table_map)0 : PARAM_TABLE_BIT; } + { + return state != NO_VALUE ? (table_map)0 : PARAM_TABLE_BIT; + } virtual void print(String *str, enum_query_type query_type); bool is_null() { DBUG_ASSERT(state != NO_VALUE); return state == NULL_VALUE; } @@ -3613,12 +4010,6 @@ public: */ Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs); Item *clone_item(THD *thd); - /* - Implement by-value equality evaluation if parameter value - is set and is a basic constant (integer, real or string). - Otherwise return FALSE. - */ - bool eq(const Item *item, bool binary_cmp) const; void set_param_type_and_swap_value(Item_param *from); Rewritable_query_parameter *get_rewritable_query_parameter() @@ -3666,50 +4057,44 @@ public: longlong value; Item_int(THD *thd, int32 i,size_t length= MY_INT32_NUM_DECIMAL_DIGITS): Item_num(thd), value((longlong) i) - { max_length=(uint32)length; fixed= 1; } + { max_length=(uint32)length; } Item_int(THD *thd, longlong i,size_t length= MY_INT64_NUM_DECIMAL_DIGITS): Item_num(thd), value(i) - { max_length=(uint32)length; fixed= 1; } + { max_length=(uint32)length; } Item_int(THD *thd, ulonglong i, size_t length= MY_INT64_NUM_DECIMAL_DIGITS): Item_num(thd), value((longlong)i) - { max_length=(uint32)length; fixed= 1; unsigned_flag= 1; } + { max_length=(uint32)length; unsigned_flag= 1; } Item_int(THD *thd, const char *str_arg,longlong i,size_t length): Item_num(thd), value(i) { max_length=(uint32)length; name.str= str_arg; name.length= safe_strlen(name.str); - fixed= 1; } Item_int(THD *thd, const char *str_arg,longlong i,size_t length, bool flag): Item_num(thd), value(i) { max_length=(uint32)length; name.str= str_arg; name.length= safe_strlen(name.str); - fixed= 1; unsigned_flag= flag; } Item_int(THD *thd, const char *str_arg, size_t length=64); - enum Type type() const { return INT_ITEM; } const Type_handler *type_handler() const { return type_handler_long_or_longlong(); } - Field *create_tmp_field(bool group, TABLE *table) - { return tmp_table_field_from_field_type(table); } Field *create_field_for_create_select(TABLE *table) { return tmp_table_field_from_field_type(table); } - longlong val_int() { DBUG_ASSERT(fixed == 1); return value; } - longlong val_int_min() const { DBUG_ASSERT(fixed == 1); return value; } - double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; } + const longlong *const_ptr_longlong() const { return &value; } + longlong val_int() { return value; } + longlong val_int_min() const { return value; } + double val_real() { return (double) value; } my_decimal *val_decimal(my_decimal *); String *val_str(String*); int save_in_field(Field *field, bool no_conversions); - bool basic_const_item() const { return 1; } + bool is_order_clause_position() const { return true; } Item *clone_item(THD *thd); virtual void print(String *str, enum_query_type query_type); Item *neg(THD *thd); uint decimal_precision() const { return (uint) (max_length - MY_TEST(value < 0)); } - bool eq(const Item *item, bool binary_cmp) const - { return int_eq(value, item); } Item *get_copy(THD *thd) { return get_item_copy<Item_int>(thd, this); } }; @@ -3725,8 +4110,20 @@ class Item_bool :public Item_int public: Item_bool(THD *thd, const char *str_arg, longlong i): Item_int(thd, str_arg, i, 1) {} - bool is_bool_type() { return true; } + Item_bool(THD *thd, bool i) :Item_int(thd, (longlong) i, 1) { } + bool is_bool_literal() const { return true; } Item *neg_transformer(THD *thd); + const Type_handler *type_handler() const + { return &type_handler_bool; } + const Type_handler *fixed_type_handler() const + { return &type_handler_bool; } + void quick_fix_field() + { + /* + We can get here when Item_bool is created instead of a constant + predicate at various condition optimization stages in sql_select. + */ + } }; @@ -3736,8 +4133,7 @@ public: Item_uint(THD *thd, const char *str_arg, size_t length); Item_uint(THD *thd, ulonglong i): Item_int(thd, i, 10) {} Item_uint(THD *thd, const char *str_arg, longlong i, uint length); - double val_real() - { DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); } + double val_real() { return ulonglong2double((ulonglong)value); } String *val_str(String*); Item *clone_item(THD *thd); virtual void print(String *str, enum_query_type query_type); @@ -3758,7 +4154,7 @@ public: longlong val_int(); double val_real() { return (double)val_int(); } void set(longlong packed, enum_mysql_timestamp_type ts_type); - bool get_date(MYSQL_TIME *to, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) { *to= ltime; return false; @@ -3776,24 +4172,26 @@ public: CHARSET_INFO *charset); Item_decimal(THD *thd, const char *str, const my_decimal *val_arg, uint decimal_par, uint length); - Item_decimal(THD *thd, my_decimal *value_par); + Item_decimal(THD *thd, const my_decimal *value_par); Item_decimal(THD *thd, longlong val, bool unsig); Item_decimal(THD *thd, double val, int precision, int scale); Item_decimal(THD *thd, const uchar *bin, int precision, int scale); - enum Type type() const { return DECIMAL_ITEM; } const Type_handler *type_handler() const { return &type_handler_newdecimal; } - longlong val_int(); - double val_real(); - String *val_str(String*); + longlong val_int() { return decimal_value.to_longlong(unsigned_flag); } + double val_real() { return decimal_value.to_double(); } + String *val_str(String *to) { return decimal_value.to_string(to); } my_decimal *val_decimal(my_decimal *val) { return &decimal_value; } + const my_decimal *const_ptr_my_decimal() const { return &decimal_value; } int save_in_field(Field *field, bool no_conversions); - bool basic_const_item() const { return 1; } Item *clone_item(THD *thd); - virtual void print(String *str, enum_query_type query_type); + virtual void print(String *str, enum_query_type query_type) + { + decimal_value.to_string(&str_value); + str->append(str_value); + } Item *neg(THD *thd); uint decimal_precision() const { return decimal_value.precision(); } - bool eq(const Item *, bool binary_cmp) const; void set_decimal_value(my_decimal *value_par); Item *get_copy(THD *thd) { return get_item_copy<Item_decimal>(thd, this); } @@ -3813,21 +4211,18 @@ public: name.length= safe_strlen(str); decimals=(uint8) decimal_par; max_length= length; - fixed= 1; } Item_float(THD *thd, double value_par, uint decimal_par): Item_num(thd), presentation(0), value(value_par) { decimals= (uint8) decimal_par; - fixed= 1; } int save_in_field(Field *field, bool no_conversions); - enum Type type() const { return REAL_ITEM; } const Type_handler *type_handler() const { return &type_handler_double; } - double val_real() { DBUG_ASSERT(fixed == 1); return value; } + const double *const_ptr_double() const { return &value; } + double val_real() { return value; } longlong val_int() { - DBUG_ASSERT(fixed == 1); if (value <= (double) LONGLONG_MIN) { return LONGLONG_MIN; @@ -3840,12 +4235,9 @@ public: } String *val_str(String*); my_decimal *val_decimal(my_decimal *); - bool basic_const_item() const { return 1; } Item *clone_item(THD *thd); Item *neg(THD *thd); virtual void print(String *str, enum_query_type query_type); - bool eq(const Item *item, bool binary_cmp) const - { return real_eq(value, item); } Item *get_copy(THD *thd) { return get_item_copy<Item_float>(thd, this); } }; @@ -3872,14 +4264,12 @@ public: }; -class Item_string :public Item_basic_constant +class Item_string :public Item_literal { protected: void fix_from_value(Derivation dv, const Metadata metadata) { fix_charset_and_length(str_value.charset(), dv, metadata); - // it is constant => can be used without fix_fields (and frequently used) - fixed= 1; } void fix_and_set_name_from_value(THD *thd, Derivation dv, const Metadata metadata) @@ -3890,41 +4280,41 @@ protected: protected: /* Just create an item and do not fill string representation */ Item_string(THD *thd, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE): - Item_basic_constant(thd) + Item_literal(thd) { collation.set(cs, dv); max_length= 0; set_name(thd, NULL, 0, system_charset_info); decimals= NOT_FIXED_DEC; - fixed= 1; } public: - Item_string(THD *thd, CHARSET_INFO *csi, const char *str_arg, uint length_arg): - Item_basic_constant(thd) + Item_string(THD *thd, CHARSET_INFO *csi, const char *str_arg, uint length_arg) + :Item_literal(thd) { collation.set(csi, DERIVATION_COERCIBLE); set_name(thd, NULL, 0, system_charset_info); decimals= NOT_FIXED_DEC; - fixed= 1; str_value.copy(str_arg, length_arg, csi); max_length= str_value.numchars() * csi->mbmaxlen; } // Constructors with the item name set from its value Item_string(THD *thd, const char *str, uint length, CHARSET_INFO *cs, - Derivation dv, uint repertoire): Item_basic_constant(thd) + Derivation dv, uint repertoire) + :Item_literal(thd) { str_value.set_or_copy_aligned(str, length, cs); fix_and_set_name_from_value(thd, dv, Metadata(&str_value, repertoire)); } Item_string(THD *thd, const char *str, size_t length, - CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE): - Item_basic_constant(thd) + CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) + :Item_literal(thd) { str_value.set_or_copy_aligned(str, length, cs); fix_and_set_name_from_value(thd, dv, Metadata(&str_value)); } Item_string(THD *thd, const String *str, CHARSET_INFO *tocs, uint *conv_errors, - Derivation dv, uint repertoire): Item_basic_constant(thd) + Derivation dv, uint repertoire) + :Item_literal(thd) { if (str_value.copy(str, tocs, conv_errors)) str_value.set("", 0, tocs); // EOM ? @@ -3933,16 +4323,16 @@ public: } // Constructors with an externally provided item name Item_string(THD *thd, const char *name_par, const char *str, size_t length, - CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE): - Item_basic_constant(thd) + CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) + :Item_literal(thd) { str_value.set_or_copy_aligned(str, length, cs); fix_from_value(dv, Metadata(&str_value)); set_name(thd, name_par,safe_strlen(name_par), system_charset_info); } Item_string(THD *thd, const char *name_par, const char *str, size_t length, - CHARSET_INFO *cs, Derivation dv, uint repertoire): - Item_basic_constant(thd) + CHARSET_INFO *cs, Derivation dv, uint repertoire) + :Item_literal(thd) { str_value.set_or_copy_aligned(str, length, cs); fix_from_value(dv, Metadata(&str_value, repertoire)); @@ -3952,26 +4342,23 @@ public: { str_value.print(to); } - enum Type type() const { return STRING_ITEM; } double val_real(); longlong val_int(); + const String *const_ptr_string() const + { + return &str_value; + } String *val_str(String*) { - DBUG_ASSERT(fixed == 1); return (String*) &str_value; } my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return get_date_from_string(ltime, fuzzydate); + return get_date_from_string(thd, ltime, fuzzydate); } int save_in_field(Field *field, bool no_conversions); const Type_handler *type_handler() const { return &type_handler_varchar; } - bool basic_const_item() const { return 1; } - bool eq(const Item *item, bool binary_cmp) const - { - return str_eq(&str_value, item, binary_cmp); - } Item *clone_item(THD *thd); Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) { @@ -3983,7 +4370,6 @@ public: max_length= str_value.numchars() * collation.collation->mbmaxlen; } virtual void print(String *str, enum_query_type query_type); - bool check_partition_func_processor(void *int_arg) {return FALSE;} /** Return TRUE if character-set-introducer was explicitly specified in the @@ -4012,34 +4398,6 @@ public: String *check_well_formed_result(bool send_error) { return Item::check_well_formed_result(&str_value, send_error); } - enum_field_types odbc_temporal_literal_type(const LEX_CSTRING *type_str) const - { - /* - If string is a reasonably short pure ASCII string literal, - try to parse known ODBC style date, time or timestamp literals, - e.g: - SELECT {d'2001-01-01'}; - SELECT {t'10:20:30'}; - SELECT {ts'2001-01-01 10:20:30'}; - */ - if (collation.repertoire == MY_REPERTOIRE_ASCII && - str_value.length() < MAX_DATE_STRING_REP_LENGTH * 4) - { - if (type_str->length == 1) - { - if (type_str->str[0] == 'd') /* {d'2001-01-01'} */ - return MYSQL_TYPE_DATE; - else if (type_str->str[0] == 't') /* {t'10:20:30'} */ - return MYSQL_TYPE_TIME; - } - else if (type_str->length == 2) /* {ts'2001-01-01 10:20:30'} */ - { - if (type_str->str[0] == 't' && type_str->str[1] == 's') - return MYSQL_TYPE_DATETIME; - } - } - return MYSQL_TYPE_STRING; // Not a temporal literal - } Item_basic_constant *make_string_literal_concat(THD *thd, const LEX_CSTRING *); Item *make_odbc_literal(THD *thd, const LEX_CSTRING *typestr); @@ -4226,38 +4584,30 @@ public: /** Item_hex_constant -- a common class for hex literals: X'HHHH' and 0xHHHH */ -class Item_hex_constant: public Item_basic_constant +class Item_hex_constant: public Item_literal { private: void hex_string_init(THD *thd, const char *str, size_t str_length); public: - Item_hex_constant(THD *thd): Item_basic_constant(thd) + Item_hex_constant(THD *thd): Item_literal(thd) { hex_string_init(thd, "", 0); } Item_hex_constant(THD *thd, const char *str, size_t str_length): - Item_basic_constant(thd) + Item_literal(thd) { hex_string_init(thd, str, str_length); } - enum Type type() const { return VARBIN_ITEM; } const Type_handler *type_handler() const { return &type_handler_varchar; } virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) { return const_charset_converter(thd, tocs, true); } - bool check_partition_func_processor(void *int_arg) {return FALSE;} - bool basic_const_item() const { return 1; } - bool eq(const Item *item, bool binary_cmp) const - { - return item->basic_const_item() && item->type() == type() && - item->cast_to_int_type_handler() == cast_to_int_type_handler() && - str_value.bin_eq(&((Item_hex_constant*)item)->str_value); - } - String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + const String *const_ptr_string() const { return &str_value; } + String *val_str(String*) { return &str_value; } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } }; @@ -4273,22 +4623,18 @@ public: Item_hex_hybrid(THD *thd): Item_hex_constant(thd) {} Item_hex_hybrid(THD *thd, const char *str, size_t str_length): Item_hex_constant(thd, str, str_length) {} + const Type_handler *type_handler() const { return &type_handler_hex_hybrid; } uint decimal_precision() const; double val_real() { - DBUG_ASSERT(fixed == 1); return (double) (ulonglong) Item_hex_hybrid::val_int(); } longlong val_int() { - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); return longlong_from_hex_hybrid(str_value.ptr(), str_value.length()); } my_decimal *val_decimal(my_decimal *decimal_value) { - // following assert is redundant, because fixed=1 assigned in constructor - DBUG_ASSERT(fixed == 1); longlong value= Item_hex_hybrid::val_int(); int2my_decimal(E_DEC_FATAL_ERROR, value, TRUE, decimal_value); return decimal_value; @@ -4298,14 +4644,6 @@ public: field->set_notnull(); return field->store_hex_hybrid(str_value.ptr(), str_value.length()); } - const Type_handler *cast_to_int_type_handler() const - { - return &type_handler_longlong; - } - const Type_handler *type_handler_for_system_time() const - { - return &type_handler_longlong; - } void print(String *str, enum_query_type query_type); Item *get_copy(THD *thd) { return get_item_copy<Item_hex_hybrid>(thd, this); } @@ -4329,12 +4667,10 @@ public: Item_hex_constant(thd, str, str_length) {} longlong val_int() { - DBUG_ASSERT(fixed == 1); return longlong_from_string_with_check(&str_value); } double val_real() { - DBUG_ASSERT(fixed == 1); return double_from_string_with_check(&str_value); } my_decimal *val_decimal(my_decimal *decimal_value) @@ -4360,7 +4696,55 @@ public: }; -class Item_temporal_literal :public Item_basic_constant +class Item_timestamp_literal: public Item_literal +{ + Timestamp_or_zero_datetime m_value; +public: + Item_timestamp_literal(THD *thd) + :Item_literal(thd) + { } + const Type_handler *type_handler() const { return &type_handler_timestamp2; } + int save_in_field(Field *field, bool no_conversions) + { + Timestamp_or_zero_datetime_native native(m_value, decimals); + return native.save_in_field(field, decimals); + } + longlong val_int() + { + return m_value.to_datetime(current_thd).to_longlong(); + } + double val_real() + { + return m_value.to_datetime(current_thd).to_double(); + } + String *val_str(String *to) + { + return m_value.to_datetime(current_thd).to_string(to, decimals); + } + my_decimal *val_decimal(my_decimal *to) + { + return m_value.to_datetime(current_thd).to_decimal(to); + } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { + bool res= m_value.to_TIME(thd, ltime, fuzzydate); + DBUG_ASSERT(!res); + return res; + } + bool val_native(THD *thd, Native *to) + { + return m_value.to_native(to, decimals); + } + void set_value(const Timestamp_or_zero_datetime &value) + { + m_value= value; + } + Item *get_copy(THD *thd) + { return get_item_copy<Item_timestamp_literal>(thd, this); } +}; + + +class Item_temporal_literal :public Item_literal { protected: MYSQL_TIME cached_time; @@ -4370,37 +4754,21 @@ public: @param ltime DATE value. */ Item_temporal_literal(THD *thd, const MYSQL_TIME *ltime) - :Item_basic_constant(thd) + :Item_literal(thd) { collation.set(&my_charset_numeric, DERIVATION_NUMERIC, MY_REPERTOIRE_ASCII); decimals= 0; cached_time= *ltime; } Item_temporal_literal(THD *thd, const MYSQL_TIME *ltime, uint dec_arg): - Item_basic_constant(thd) + Item_literal(thd) { collation.set(&my_charset_numeric, DERIVATION_NUMERIC, MY_REPERTOIRE_ASCII); decimals= dec_arg; cached_time= *ltime; } - bool basic_const_item() const { return true; } - bool const_item() const { return true; } - enum Type type() const { return DATE_ITEM; } - bool eq(const Item *item, bool binary_cmp) const; - - bool check_partition_func_processor(void *int_arg) {return FALSE;} - bool is_null() - { return is_null_from_temporal(); } - bool get_date_with_sql_mode(MYSQL_TIME *to); - String *val_str(String *str) - { return val_string_from_date(str); } - longlong val_int() - { return val_int_from_date(); } - double val_real() - { return val_real_from_date(); } - my_decimal *val_decimal(my_decimal *decimal_value) - { return val_decimal_from_date(decimal_value); } + const MYSQL_TIME *const_ptr_mysql_time() const { return &cached_time; } int save_in_field(Field *field, bool no_conversions) { return save_date_in_field(field, no_conversions); } }; @@ -4416,7 +4784,6 @@ public: :Item_temporal_literal(thd, ltime) { max_length= MAX_DATE_WIDTH; - fixed= 1; /* If date has zero month or day, it can return NULL in case of NO_ZERO_DATE or NO_ZERO_IN_DATE. @@ -4429,7 +4796,11 @@ public: const Type_handler *type_handler() const { return &type_handler_newdate; } void print(String *str, enum_query_type query_type); Item *clone_item(THD *thd); - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + longlong val_int() { return Date(this).to_longlong(); } + double val_real() { return Date(this).to_double(); } + String *val_str(String *to) { return Date(this).to_string(to); } + my_decimal *val_decimal(my_decimal *to) { return Date(this).to_decimal(to); } + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); Item *get_copy(THD *thd) { return get_item_copy<Item_date_literal>(thd, this); } }; @@ -4445,12 +4816,15 @@ public: Item_temporal_literal(thd, ltime, dec_arg) { max_length= MIN_TIME_WIDTH + (decimals ? decimals + 1 : 0); - fixed= 1; } const Type_handler *type_handler() const { return &type_handler_time2; } void print(String *str, enum_query_type query_type); Item *clone_item(THD *thd); - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + longlong val_int() { return Time(this).to_longlong(); } + double val_real() { return Time(this).to_double(); } + String *val_str(String *to) { return Time(this).to_string(to, decimals); } + my_decimal *val_decimal(my_decimal *to) { return Time(this).to_decimal(to); } + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); Item *get_copy(THD *thd) { return get_item_copy<Item_time_literal>(thd, this); } }; @@ -4466,14 +4840,23 @@ public: Item_temporal_literal(thd, ltime, dec_arg) { max_length= MAX_DATETIME_WIDTH + (decimals ? decimals + 1 : 0); - fixed= 1; // See the comment on maybe_null in Item_date_literal maybe_null= !ltime->month || !ltime->day; } const Type_handler *type_handler() const { return &type_handler_datetime2; } void print(String *str, enum_query_type query_type); Item *clone_item(THD *thd); - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + longlong val_int() { return Datetime(this).to_longlong(); } + double val_real() { return Datetime(this).to_double(); } + String *val_str(String *to) + { + return Datetime(this).to_string(to, decimals); + } + my_decimal *val_decimal(my_decimal *to) + { + return Datetime(this).to_decimal(to); + } + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); Item *get_copy(THD *thd) { return get_item_copy<Item_datetime_literal>(thd, this); } }; @@ -4510,7 +4893,7 @@ class Item_date_literal_for_invalid_dates: public Item_date_literal public: Item_date_literal_for_invalid_dates(THD *thd, const MYSQL_TIME *ltime) :Item_date_literal(thd, ltime) { } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { *ltime= cached_time; return (null_value= false); @@ -4528,7 +4911,7 @@ public: Item_datetime_literal_for_invalid_dates(THD *thd, const MYSQL_TIME *ltime, uint dec_arg) :Item_datetime_literal(thd, ltime, dec_arg) { } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { *ltime= cached_time; return (null_value= false); @@ -4723,8 +5106,10 @@ struct st_sp_security_context; class Item_sp { -public: +protected: + // Can be NULL in some non-SELECT queries Name_resolution_context *context; +public: sp_name *m_name; sp_head *m_sp; TABLE *dummy_table; @@ -4746,9 +5131,15 @@ public: bool execute_impl(THD *thd, Item **args, uint arg_count); bool init_result_field(THD *thd, uint max_length, uint maybe_null, bool *null_value, LEX_CSTRING *name); + void process_error(THD *thd) + { + if (context) + context->process_error(thd); + } }; -class Item_ref :public Item_ident +class Item_ref :public Item_ident, + protected With_sum_func_cache { protected: void set_properties(); @@ -4784,7 +5175,8 @@ public: /* Constructor need to process subselect with temporary tables (see Item) */ Item_ref(THD *thd, Item_ref *item) - :Item_ident(thd, item), set_properties_only(0), ref(item->ref) {} + :Item_ident(thd, item), With_sum_func_cache(*item), + set_properties_only(0), ref(item->ref) {} enum Type type() const { return REF_ITEM; } enum Type real_type() const { return ref ? (*ref)->type() : REF_ITEM; } @@ -4800,11 +5192,13 @@ public: my_decimal *val_decimal(my_decimal *); bool val_bool(); String *val_str(String* tmp); + bool val_native(THD *thd, Native *to); bool is_null(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); double val_result(); longlong val_int_result(); String *str_result(String* tmp); + bool val_native_result(THD *thd, Native *to); my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); bool is_null_result(); @@ -4822,6 +5216,8 @@ public: Field *get_tmp_table_field() { return result_field ? result_field : (*ref)->get_tmp_table_field(); } Item *get_tmp_table_item(THD *thd); + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param); table_map used_tables() const; void update_used_tables(); COND *build_equal_items(THD *thd, COND_EQUAL *inherited, @@ -4951,6 +5347,8 @@ public: } bool excl_dep_on_grouping_fields(st_select_lex *sel) { return (*ref)->excl_dep_on_grouping_fields(sel); } + bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) + { return (*ref)->excl_dep_on_in_subq_left_part(subq_pred); } bool cleanup_excluding_fields_processor(void *arg) { Item *item= real_item(); @@ -4967,6 +5365,8 @@ public: return 0; return cleanup_processor(arg); } + bool with_sum_func() const { return m_with_sum_func; } + With_sum_func_cache* get_with_sum_func_cache() { return this; } }; @@ -5003,10 +5403,11 @@ public: double val_real(); longlong val_int(); String *val_str(String* tmp); + bool val_native(THD *thd, Native *to); my_decimal *val_decimal(my_decimal *); bool val_bool(); bool is_null(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); virtual Ref_Type ref_type() { return DIRECT_REF; } Item *get_copy(THD *thd) { return get_item_copy<Item_direct_ref>(thd, this); } @@ -5054,7 +5455,8 @@ class Expression_cache_tracker; */ class Item_cache_wrapper :public Item_result_field, - public With_subquery_cache + public With_subquery_cache, + protected With_sum_func_cache { private: /* Pointer on the cached expression */ @@ -5082,6 +5484,8 @@ public: enum Type type() const { return EXPR_CACHE_ITEM; } enum Type real_type() const { return orig_item->type(); } bool with_subquery() const { DBUG_ASSERT(fixed); return m_with_subquery; } + bool with_sum_func() const { return m_with_sum_func; } + With_sum_func_cache* get_with_sum_func_cache() { return this; } bool set_cache(THD *thd); Expression_cache_tracker* init_tracker(MEM_ROOT *mem_root); @@ -5096,10 +5500,11 @@ public: double val_real(); longlong val_int(); String *val_str(String* tmp); + bool val_native(THD *thd, Native *to); my_decimal *val_decimal(my_decimal *); bool val_bool(); bool is_null(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool send(Protocol *protocol, st_value *buffer); void save_org_in_field(Field *field, fast_field_copier data __attribute__ ((__unused__))) @@ -5257,10 +5662,12 @@ public: } bool excl_dep_on_table(table_map tab_map); bool excl_dep_on_grouping_fields(st_select_lex *sel); + bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred); Item *derived_field_transformer_for_having(THD *thd, uchar *arg); Item *derived_field_transformer_for_where(THD *thd, uchar *arg); - Item *derived_grouping_field_transformer_for_where(THD *thd, - uchar *arg); + Item *grouping_field_transformer_for_where(THD *thd, uchar *arg); + Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg); + Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg); void save_val(Field *to) { @@ -5290,6 +5697,12 @@ public: else return Item_direct_ref::val_str(tmp); } + bool val_native(THD *thd, Native *to) + { + if (check_null_ref()) + return true; + return Item_direct_ref::val_native(thd, to); + } my_decimal *val_decimal(my_decimal *tmp) { if (check_null_ref()) @@ -5311,14 +5724,14 @@ public: else return Item_direct_ref::is_null(); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { if (check_null_ref()) { bzero((char*) ltime,sizeof(*ltime)); return 1; } - return Item_direct_ref::get_date(ltime, fuzzydate); + return Item_direct_ref::get_date(thd, ltime, fuzzydate); } bool send(Protocol *protocol, st_value *buffer); void save_org_in_field(Field *field, @@ -5434,7 +5847,8 @@ public: String* val_str(String* s); my_decimal *val_decimal(my_decimal *); bool val_bool(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool val_native(THD *thd, Native *to); virtual void print(String *str, enum_query_type query_type); table_map used_tables() const; Item *get_copy(THD *thd) @@ -5526,12 +5940,12 @@ protected: */ Item_copy(THD *thd, Item *i): Item(thd) { + DBUG_ASSERT(i->is_fixed()); item= i; null_value=maybe_null=item->maybe_null; Type_std_attributes::set(item); name= item->name; set_handler(item->type_handler()); - fixed= item->fixed; } public: @@ -5552,6 +5966,12 @@ public: const Type_handler *type_handler() const { return Type_handler_hybrid_field_type::type_handler(); } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + DBUG_ASSERT(0); + return NULL; + } void make_send_field(THD *thd, Send_field *field) { item->make_send_field(thd, field); } table_map used_tables() const { return (table_map) 1L; } @@ -5593,8 +6013,8 @@ public: my_decimal *val_decimal(my_decimal *); double val_real(); longlong val_int(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_string(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_string(thd, ltime, fuzzydate); } void copy(); int save_in_field(Field *field, bool no_conversions); Item *get_copy(THD *thd) @@ -5602,6 +6022,62 @@ public: }; +/** + We need a separate class Item_copy_timestamp because + TIMESTAMP->string->TIMESTAMP conversion is not round trip safe + near the DST change, e.g. '2010-10-31 02:25:26' can mean: + - my_time_t(1288477526) - summer time in Moscow + - my_time_t(1288481126) - winter time in Moscow, one hour later +*/ +class Item_copy_timestamp: public Item_copy +{ + Timestamp_or_zero_datetime m_value; +public: + Item_copy_timestamp(THD *thd, Item *arg): Item_copy(thd, arg) { } + const Type_handler *type_handler() const { return &type_handler_timestamp2; } + void copy() + { + Timestamp_or_zero_datetime_native_null tmp(current_thd, item, false); + null_value= tmp.is_null(); + m_value= tmp.is_null() ? Timestamp_or_zero_datetime() : + Timestamp_or_zero_datetime(tmp); + } + int save_in_field(Field *field, bool no_conversions) + { + Timestamp_or_zero_datetime_native native(m_value, decimals); + return native.save_in_field(field, decimals); + } + longlong val_int() + { + return m_value.to_datetime(current_thd).to_longlong(); + } + double val_real() + { + return m_value.to_datetime(current_thd).to_double(); + } + String *val_str(String *to) + { + return m_value.to_datetime(current_thd).to_string(to, decimals); + } + my_decimal *val_decimal(my_decimal *to) + { + return m_value.to_datetime(current_thd).to_decimal(to); + } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { + bool res= m_value.to_TIME(thd, ltime, fuzzydate); + DBUG_ASSERT(!res); + return res; + } + bool val_native(THD *thd, Native *to) + { + return m_value.to_native(to, decimals); + } + Item *get_copy(THD *thd) + { return get_item_copy<Item_copy_timestamp>(thd, this); } +}; + + /* Cached_item_XXX objects are not exactly caches. They do the following: @@ -5735,7 +6211,7 @@ public: double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *decimal_value); - bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate); bool send(Protocol *protocol, st_value *buffer); int save_in_field(Field *field_arg, bool no_conversions); bool save_in_param(THD *thd, Item_param *param) @@ -5792,7 +6268,7 @@ public: double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *decimal_value); - bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate); bool send(Protocol *protocol, st_value *buffer); }; @@ -5938,7 +6414,7 @@ public: for any value. */ -class Item_cache: public Item_basic_constant, +class Item_cache: public Item, public Type_handler_hybrid_field_type { protected: @@ -5957,25 +6433,27 @@ protected: cache_value() will set this flag to TRUE. */ bool value_cached; + + table_map used_table_map; public: Item_cache(THD *thd): - Item_basic_constant(thd), + Item(thd), Type_handler_hybrid_field_type(&type_handler_string), example(0), cached_field(0), - value_cached(0) + value_cached(0), + used_table_map(0) { - fixed= 1; maybe_null= 1; null_value= 1; } protected: Item_cache(THD *thd, const Type_handler *handler): - Item_basic_constant(thd), + Item(thd), Type_handler_hybrid_field_type(handler), example(0), cached_field(0), - value_cached(0) + value_cached(0), + used_table_map(0) { - fixed= 1; maybe_null= 1; null_value= 1; } @@ -5990,10 +6468,18 @@ public: cached_field= ((Item_field *)item)->field; return 0; }; + + void set_used_tables(table_map map) { used_table_map= map; } + table_map used_tables() const { return used_table_map; } enum Type type() const { return CACHE_ITEM; } const Type_handler *type_handler() const { return Type_handler_hybrid_field_type::type_handler(); } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + return create_tmp_field_ex_simple(table, src, param); + } virtual void keep_array() {} virtual void print(String *str, enum_query_type query_type); @@ -6024,7 +6510,7 @@ public: void cleanup() { clear(); - Item_basic_constant::cleanup(); + Item::cleanup(); } /** Check if saved item has a non-NULL value. @@ -6076,7 +6562,11 @@ public: { return convert_to_basic_const_item(thd); } Item *derived_field_transformer_for_where(THD *thd, uchar *arg) { return convert_to_basic_const_item(thd); } - Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg) + Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) + { return convert_to_basic_const_item(thd); } + Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg) + { return convert_to_basic_const_item(thd); } + Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg) { return convert_to_basic_const_item(thd); } }; @@ -6095,8 +6585,8 @@ public: longlong val_int(); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_int(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_int(thd, ltime, fuzzydate); } bool cache_value(); int save_in_field(Field *field, bool no_conversions); Item *convert_to_basic_const_item(THD *thd); @@ -6108,9 +6598,12 @@ public: class Item_cache_year: public Item_cache_int { public: - Item_cache_year(THD *thd): Item_cache_int(thd, &type_handler_year) { } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_year(ltime, fuzzydate); } + Item_cache_year(THD *thd, const Type_handler *handler) + :Item_cache_int(thd, handler) { } + bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) + { + return type_handler_year.Item_get_date_with_warn(thd, this, to, mode); + } }; @@ -6119,14 +6612,8 @@ class Item_cache_temporal: public Item_cache_int protected: Item_cache_temporal(THD *thd, const Type_handler *handler); public: - String* val_str(String *str); - my_decimal *val_decimal(my_decimal *); - longlong val_int(); - longlong val_datetime_packed(); - longlong val_time_packed(); - double val_real(); bool cache_value(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); int save_in_field(Field *field, bool no_conversions); void store_packed(longlong val_arg, Item *example); /* @@ -6149,6 +6636,31 @@ public: Item *get_copy(THD *thd) { return get_item_copy<Item_cache_time>(thd, this); } Item *make_literal(THD *); + longlong val_datetime_packed(THD *thd) + { + Datetime::Options_cmp opt(thd); + return has_value() ? Datetime(thd, this, opt).to_packed() : 0; + } + longlong val_time_packed(THD *thd) + { + return has_value() ? value : 0; + } + longlong val_int() + { + return has_value() ? Time(this).to_longlong() : 0; + } + double val_real() + { + return has_value() ? Time(this).to_double() : 0; + } + String *val_str(String *to) + { + return has_value() ? Time(this).to_string(to, decimals) : NULL; + } + my_decimal *val_decimal(my_decimal *to) + { + return has_value() ? Time(this).to_decimal(to) : NULL; + } }; @@ -6160,6 +6672,30 @@ public: Item *get_copy(THD *thd) { return get_item_copy<Item_cache_datetime>(thd, this); } Item *make_literal(THD *); + longlong val_datetime_packed(THD *thd) + { + return has_value() ? value : 0; + } + longlong val_time_packed(THD *thd) + { + return Time(thd, this, Time::Options_cmp(thd)).to_packed(); + } + longlong val_int() + { + return has_value() ? Datetime(this).to_longlong() : 0; + } + double val_real() + { + return has_value() ? Datetime(this).to_double() : 0; + } + String *val_str(String *to) + { + return has_value() ? Datetime(this).to_string(to, decimals) : NULL; + } + my_decimal *val_decimal(my_decimal *to) + { + return has_value() ? Datetime(this).to_decimal(to) : NULL; + } }; @@ -6171,6 +6707,66 @@ public: Item *get_copy(THD *thd) { return get_item_copy<Item_cache_date>(thd, this); } Item *make_literal(THD *); + longlong val_datetime_packed(THD *thd) + { + return has_value() ? value : 0; + } + longlong val_time_packed(THD *thd) + { + return Time(thd, this, Time::Options_cmp(thd)).to_packed(); + } + longlong val_int() { return has_value() ? Date(this).to_longlong() : 0; } + double val_real() { return has_value() ? Date(this).to_double() : 0; } + String *val_str(String *to) + { + return has_value() ? Date(this).to_string(to) : NULL; + } + my_decimal *val_decimal(my_decimal *to) + { + return has_value() ? Date(this).to_decimal(to) : NULL; + } +}; + + +class Item_cache_timestamp: public Item_cache +{ + Timestamp_or_zero_datetime_native m_native; + Datetime to_datetime(THD *thd); +public: + Item_cache_timestamp(THD *thd) + :Item_cache(thd, &type_handler_timestamp2) { } + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_timestamp>(thd, this); } + bool cache_value(); + String* val_str(String *to) + { + return to_datetime(current_thd).to_string(to, decimals); + } + my_decimal *val_decimal(my_decimal *to) + { + return to_datetime(current_thd).to_decimal(to); + } + longlong val_int() + { + return to_datetime(current_thd).to_longlong(); + } + double val_real() + { + return to_datetime(current_thd).to_double(); + } + longlong val_datetime_packed(THD *thd) + { + DBUG_ASSERT(0); + return 0; + } + longlong val_time_packed(THD *thd) + { + DBUG_ASSERT(0); + return 0; + } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + int save_in_field(Field *field, bool no_conversions); + bool val_native(THD *thd, Native *to); }; @@ -6185,8 +6781,8 @@ public: longlong val_int(); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_real(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_real(thd, ltime, fuzzydate); } bool cache_value(); Item *convert_to_basic_const_item(THD *thd); Item *get_copy(THD *thd) @@ -6205,8 +6801,11 @@ public: longlong val_int(); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_decimal(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) + { + return decimal_to_datetime_with_warn(thd, VDec(this).ptr(), to, mode, + NULL, NULL); + } bool cache_value(); Item *convert_to_basic_const_item(THD *thd); Item *get_copy(THD *thd) @@ -6233,8 +6832,8 @@ public: longlong val_int(); String* val_str(String *); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_string(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_string(thd, ltime, fuzzydate); } CHARSET_INFO *charset() const { return value->charset(); }; int save_in_field(Field *field, bool no_conversions); bool cache_value(); @@ -6315,7 +6914,7 @@ public: illegal_method_call((const char*)"val_decimal"); return 0; }; - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { illegal_method_call((const char*)"val_decimal"); return true; @@ -6364,7 +6963,7 @@ public: Type_handler_hybrid_field_type(item->real_type_handler()), enum_set_typelib(0) { - DBUG_ASSERT(item->fixed); + DBUG_ASSERT(item->is_fixed()); maybe_null= item->maybe_null; } Item_type_holder(THD *thd, @@ -6398,8 +6997,9 @@ public: longlong val_int(); my_decimal *val_decimal(my_decimal *); String *val_str(String*); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); - Field *create_tmp_field(bool group, TABLE *table) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) { return Item_type_holder::real_type_handler()-> make_and_init_table_field(&name, Record_addr(maybe_null), @@ -6539,4 +7139,39 @@ inline void Virtual_column_info::print(String* str) expr->print_for_table_def(str); } +inline bool TABLE::mark_column_with_deps(Field *field) +{ + bool res; + if (!(res= bitmap_fast_test_and_set(read_set, field->field_index))) + { + if (field->vcol_info) + mark_virtual_column_deps(field); + } + return res; +} + +inline bool TABLE::mark_virtual_column_with_deps(Field *field) +{ + bool res; + DBUG_ASSERT(field->vcol_info); + if (!(res= bitmap_fast_test_and_set(read_set, field->field_index))) + mark_virtual_column_deps(field); + return res; +} + +inline void TABLE::mark_virtual_column_deps(Field *field) +{ + DBUG_ASSERT(field->vcol_info); + DBUG_ASSERT(field->vcol_info->expr); + field->vcol_info->expr->walk(&Item::register_field_in_read_map, 1, 0); +} + +inline void TABLE::use_all_stored_columns() +{ + bitmap_set_all(read_set); + if (Field **vf= vfield) + for (; *vf; vf++) + bitmap_clear_bit(read_set, (*vf)->field_index); +} + #endif /* SQL_ITEM_INCLUDED */ diff --git a/sql/item_buff.cc b/sql/item_buff.cc index 4d03462d7c3..3467fda79c7 100644 --- a/sql/item_buff.cc +++ b/sql/item_buff.cc @@ -225,16 +225,15 @@ Cached_item_decimal::Cached_item_decimal(Item *it) bool Cached_item_decimal::cmp() { - my_decimal tmp; - my_decimal *ptmp= item->val_decimal(&tmp); - if (null_value != item->null_value || - (!item->null_value && my_decimal_cmp(&value, ptmp))) + VDec tmp(item); + if (null_value != tmp.is_null() || + (!tmp.is_null() && tmp.cmp(&value))) { - null_value= item->null_value; + null_value= tmp.is_null(); /* Save only not null values */ if (!null_value) { - my_decimal2decimal(ptmp, &value); + my_decimal2decimal(tmp.ptr(), &value); return TRUE; } return FALSE; @@ -245,17 +244,9 @@ bool Cached_item_decimal::cmp() int Cached_item_decimal::cmp_read_only() { - my_decimal tmp; - my_decimal *ptmp= item->val_decimal(&tmp); + VDec tmp(item); if (null_value) - { - if (item->null_value) - return 0; - else - return -1; - } - if (item->null_value) - return 1; - return my_decimal_cmp(&value, ptmp); + return tmp.is_null() ? 0 : -1; + return tmp.is_null() ? 1 : value.cmp(tmp.ptr()); } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b1f7e54546a..4cd63042558 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -31,32 +31,8 @@ #include <m_ctype.h> #include "sql_select.h" #include "sql_parse.h" // check_stack_overrun -#include "sql_time.h" // make_truncated_value_warning #include "sql_base.h" // dynamic_column_error_message -/** - find an temporal type (item) that others will be converted to - for the purpose of comparison. - - this is the type that will be used in warnings like - "Incorrect <<TYPE>> value". -*/ -static Item *find_date_time_item(Item **args, uint nargs, uint col) -{ - Item *date_arg= 0, **arg, **arg_end; - for (arg= args, arg_end= args + nargs; arg != arg_end ; arg++) - { - Item *item= arg[0]->element_index(col); - if (item->cmp_type() != TIME_RESULT) - continue; - if (item->field_type() == MYSQL_TYPE_DATETIME) - return item; - if (!date_arg) - date_arg= item; - } - return date_arg; -} - /* Compare row signature of two expressions @@ -591,6 +567,18 @@ bool Arg_comparator::set_cmp_func_datetime() } +bool Arg_comparator::set_cmp_func_native() +{ + THD *thd= current_thd; + m_compare_collation= &my_charset_numeric; + func= is_owner_equal_func() ? &Arg_comparator::compare_e_native : + &Arg_comparator::compare_native; + a= cache_converted_constant(thd, a, &a_cache, compare_type_handler()); + b= cache_converted_constant(thd, b, &b_cache, compare_type_handler()); + return false; +} + + bool Arg_comparator::set_cmp_func_int() { THD *thd= current_thd; @@ -707,10 +695,11 @@ Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value, int Arg_comparator::compare_time() { - longlong val1= (*a)->val_time_packed(); + THD *thd= current_thd; + longlong val1= (*a)->val_time_packed(thd); if (!(*a)->null_value) { - longlong val2= (*b)->val_time_packed(); + longlong val2= (*b)->val_time_packed(thd); if (!(*b)->null_value) return compare_not_null_values(val1, val2); } @@ -722,8 +711,9 @@ int Arg_comparator::compare_time() int Arg_comparator::compare_e_time() { - longlong val1= (*a)->val_time_packed(); - longlong val2= (*b)->val_time_packed(); + THD *thd= current_thd; + longlong val1= (*a)->val_time_packed(thd); + longlong val2= (*b)->val_time_packed(thd); if ((*a)->null_value || (*b)->null_value) return MY_TEST((*a)->null_value && (*b)->null_value); return MY_TEST(val1 == val2); @@ -733,10 +723,11 @@ int Arg_comparator::compare_e_time() int Arg_comparator::compare_datetime() { - longlong val1= (*a)->val_datetime_packed(); + THD *thd= current_thd; + longlong val1= (*a)->val_datetime_packed(thd); if (!(*a)->null_value) { - longlong val2= (*b)->val_datetime_packed(); + longlong val2= (*b)->val_datetime_packed(thd); if (!(*b)->null_value) return compare_not_null_values(val1, val2); } @@ -748,8 +739,9 @@ int Arg_comparator::compare_datetime() int Arg_comparator::compare_e_datetime() { - longlong val1= (*a)->val_datetime_packed(); - longlong val2= (*b)->val_datetime_packed(); + THD *thd= current_thd; + longlong val1= (*a)->val_datetime_packed(thd); + longlong val2= (*b)->val_datetime_packed(thd); if ((*a)->null_value || (*b)->null_value) return MY_TEST((*a)->null_value && (*b)->null_value); return MY_TEST(val1 == val2); @@ -790,6 +782,39 @@ int Arg_comparator::compare_e_string() } +int Arg_comparator::compare_native() +{ + THD *thd= current_thd; + if (!(*a)->val_native_with_conversion(thd, &m_native1, + compare_type_handler())) + { + if (!(*b)->val_native_with_conversion(thd, &m_native2, + compare_type_handler())) + { + if (set_null) + owner->null_value= 0; + return compare_type_handler()->cmp_native(m_native1, m_native2); + } + } + if (set_null) + owner->null_value= 1; + return -1; +} + + +int Arg_comparator::compare_e_native() +{ + THD *thd= current_thd; + bool res1= (*a)->val_native_with_conversion(thd, &m_native1, + compare_type_handler()); + bool res2= (*b)->val_native_with_conversion(thd, &m_native2, + compare_type_handler()); + if (res1 || res2) + return MY_TEST(res1 == res2); + return MY_TEST(compare_type_handler()->cmp_native(m_native1, m_native2) == 0); +} + + int Arg_comparator::compare_real() { /* @@ -818,17 +843,15 @@ int Arg_comparator::compare_real() int Arg_comparator::compare_decimal() { - my_decimal decimal1; - my_decimal *val1= (*a)->val_decimal(&decimal1); - if (!(*a)->null_value) + VDec val1(*a); + if (!val1.is_null()) { - my_decimal decimal2; - my_decimal *val2= (*b)->val_decimal(&decimal2); - if (!(*b)->null_value) + VDec val2(*b); + if (!val2.is_null()) { if (set_null) owner->null_value= 0; - return my_decimal_cmp(val1, val2); + return val1.cmp(val2); } } if (set_null) @@ -847,12 +870,10 @@ int Arg_comparator::compare_e_real() int Arg_comparator::compare_e_decimal() { - my_decimal decimal1, decimal2; - my_decimal *val1= (*a)->val_decimal(&decimal1); - my_decimal *val2= (*b)->val_decimal(&decimal2); - if ((*a)->null_value || (*b)->null_value) - return MY_TEST((*a)->null_value && (*b)->null_value); - return MY_TEST(my_decimal_cmp(val1, val2) == 0); + VDec val1(*a), val2(*b); + if (val1.is_null() || val2.is_null()) + return MY_TEST(val1.is_null() && val2.is_null()); + return MY_TEST(val1.cmp(val2) == 0); } @@ -1292,7 +1313,7 @@ bool Item_in_optimizer::fix_left(THD *thd) used_tables_cache= args[0]->used_tables(); } eval_not_null_tables(NULL); - with_sum_func= args[0]->with_sum_func; + copy_with_sum_func(args[0]); with_param= args[0]->with_param || args[1]->with_param; with_field= args[0]->with_field; if ((const_item_cache= args[0]->const_item())) @@ -1300,11 +1321,11 @@ bool Item_in_optimizer::fix_left(THD *thd) cache->store(args[0]); cache->cache_value(); } - if (args[1]->fixed) + if (args[1]->is_fixed()) { /* to avoid overriding is called to update left expression */ used_tables_and_const_cache_join(args[1]); - with_sum_func= with_sum_func || args[1]->with_sum_func; + join_with_sum_func(args[1]); } DBUG_RETURN(0); } @@ -1340,7 +1361,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref) if (args[1]->maybe_null) maybe_null=1; m_with_subquery= true; - with_sum_func= with_sum_func || args[1]->with_sum_func; + join_with_sum_func(args[1]); with_field= with_field || args[1]->with_field; with_param= args[0]->with_param || args[1]->with_param; used_tables_and_const_cache_join(args[1]); @@ -1892,7 +1913,7 @@ bool Item_func_interval::fix_length_and_dec() max_length= 2; used_tables_and_const_cache_join(row); not_null_tables_cache= row->not_null_tables(); - with_sum_func= with_sum_func || row->with_sum_func; + join_with_sum_func(row); with_param= with_param || row->with_param; with_field= with_field || row->with_field; return FALSE; @@ -1971,11 +1992,11 @@ longlong Item_func_interval::val_int() ((el->result_type() == DECIMAL_RESULT) || (el->result_type() == INT_RESULT))) { - my_decimal e_dec_buf, *e_dec= el->val_decimal(&e_dec_buf); + VDec e_dec(el); /* Skip NULL ranges. */ - if (el->null_value) + if (e_dec.is_null()) continue; - if (my_decimal_cmp(e_dec, dec) > 0) + if (e_dec.cmp(dec) > 0) return i - 1; } else @@ -2121,22 +2142,49 @@ bool Item_func_between::fix_length_and_dec_temporal(THD *thd) } -longlong Item_func_between::val_int_cmp_temporal() +longlong Item_func_between::val_int_cmp_datetime() { - enum_field_types f_type= m_comparator.type_handler()->field_type(); - longlong value= args[0]->val_temporal_packed(f_type), a, b; + THD *thd= current_thd; + longlong value= args[0]->val_datetime_packed(thd), a, b; if ((null_value= args[0]->null_value)) return 0; - a= args[1]->val_temporal_packed(f_type); - b= args[2]->val_temporal_packed(f_type); - if (!args[1]->null_value && !args[2]->null_value) - return (longlong) ((value >= a && value <= b) != negated); - if (args[1]->null_value && args[2]->null_value) + a= args[1]->val_datetime_packed(thd); + b= args[2]->val_datetime_packed(thd); + return val_int_cmp_int_finalize(value, a, b); +} + + +longlong Item_func_between::val_int_cmp_time() +{ + THD *thd= current_thd; + longlong value= args[0]->val_time_packed(thd), a, b; + if ((null_value= args[0]->null_value)) + return 0; + a= args[1]->val_time_packed(thd); + b= args[2]->val_time_packed(thd); + return val_int_cmp_int_finalize(value, a, b); +} + + +longlong Item_func_between::val_int_cmp_native() +{ + THD *thd= current_thd; + const Type_handler *h= m_comparator.type_handler(); + NativeBuffer<STRING_BUFFER_USUAL_SIZE> value, a, b; + if (val_native_with_conversion_from_item(thd, args[0], &value, h)) + return 0; + bool ra= args[1]->val_native_with_conversion(thd, &a, h); + bool rb= args[2]->val_native_with_conversion(thd, &b, h); + if (!ra && !rb) + return (longlong) + ((h->cmp_native(value, a) >= 0 && + h->cmp_native(value, b) <= 0) != negated); + if (ra && rb) null_value= true; - else if (args[1]->null_value) - null_value= value <= b; // not null if false range. + else if (ra) + null_value= h->cmp_native(value, b) <= 0; else - null_value= value >= a; + null_value= h->cmp_native(value, a) >= 0; return (longlong) (!null_value && negated); } @@ -2188,23 +2236,37 @@ longlong Item_func_between::val_int_cmp_int() } -longlong Item_func_between::val_int_cmp_decimal() +bool Item_func_between::val_int_cmp_int_finalize(longlong value, + longlong a, + longlong b) { - my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf), - a_buf, *a_dec, b_buf, *b_dec; - if ((null_value=args[0]->null_value)) - return 0; /* purecov: inspected */ - a_dec= args[1]->val_decimal(&a_buf); - b_dec= args[2]->val_decimal(&b_buf); if (!args[1]->null_value && !args[2]->null_value) - return (longlong) ((my_decimal_cmp(dec, a_dec) >= 0 && - my_decimal_cmp(dec, b_dec) <= 0) != negated); + return (longlong) ((value >= a && value <= b) != negated); if (args[1]->null_value && args[2]->null_value) null_value= true; else if (args[1]->null_value) - null_value= (my_decimal_cmp(dec, b_dec) <= 0); + null_value= value <= b; // not null if false range. else - null_value= (my_decimal_cmp(dec, a_dec) >= 0); + null_value= value >= a; + return (longlong) (!null_value && negated); +} + + +longlong Item_func_between::val_int_cmp_decimal() +{ + VDec dec(args[0]); + if ((null_value= dec.is_null())) + return 0; /* purecov: inspected */ + VDec a_dec(args[1]), b_dec(args[2]); + if (!a_dec.is_null() && !b_dec.is_null()) + return (longlong) ((dec.cmp(a_dec) >= 0 && + dec.cmp(b_dec) <= 0) != negated); + if (a_dec.is_null() && b_dec.is_null()) + null_value= true; + else if (a_dec.is_null()) + null_value= (dec.cmp(b_dec) <= 0); + else + null_value= (dec.cmp(a_dec) >= 0); return (longlong) (!null_value && negated); } @@ -2312,12 +2374,22 @@ Item_func_ifnull::str_op(String *str) } -bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_func_ifnull::native_op(THD *thd, Native *to) +{ + DBUG_ASSERT(fixed == 1); + if (!val_native_with_conversion_from_item(thd, args[0], to, type_handler())) + return false; + return val_native_with_conversion_from_item(thd, args[1], to, type_handler()); +} + + +bool Item_func_ifnull::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); for (uint i= 0; i < 2; i++) { - Datetime dt(current_thd, args[i], fuzzydate & ~TIME_FUZZY_DATES); + Datetime_truncation_not_needed dt(thd, args[i], + fuzzydate & ~TIME_FUZZY_DATES); if (!(dt.copy_to_mysql_time(ltime, mysql_timestamp_type()))) return (null_value= false); } @@ -2325,12 +2397,12 @@ bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) } -bool Item_func_ifnull::time_op(MYSQL_TIME *ltime) +bool Item_func_ifnull::time_op(THD *thd, MYSQL_TIME *ltime) { DBUG_ASSERT(fixed == 1); for (uint i= 0; i < 2; i++) { - if (!Time(args[i]).copy_to_mysql_time(ltime)) + if (!Time(thd, args[i]).copy_to_mysql_time(ltime)) return (null_value= false); } return (null_value= true); @@ -2812,28 +2884,38 @@ Item_func_nullif::decimal_op(my_decimal * decimal_value) bool -Item_func_nullif::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) +Item_func_nullif::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); if (!compare()) return (null_value= true); - Datetime dt(current_thd, args[2], fuzzydate); + Datetime_truncation_not_needed dt(thd, args[2], fuzzydate); return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type())); } bool -Item_func_nullif::time_op(MYSQL_TIME *ltime) +Item_func_nullif::time_op(THD *thd, MYSQL_TIME *ltime) { DBUG_ASSERT(fixed == 1); if (!compare()) return (null_value= true); - return (null_value= Time(args[2]).copy_to_mysql_time(ltime)); + return (null_value= Time(thd, args[2]).copy_to_mysql_time(ltime)); } bool +Item_func_nullif::native_op(THD *thd, Native *to) +{ + DBUG_ASSERT(fixed == 1); + if (!compare()) + return (null_value= true); + return val_native_with_conversion_from_item(thd, args[2], to, type_handler()); +} + + +bool Item_func_nullif::is_null() { return (null_value= (!compare() ? 1 : args[2]->is_null())); @@ -2910,7 +2992,7 @@ Item *Item_func_case_simple::find_item() Item *Item_func_decode_oracle::find_item() { uint idx; - if (!Predicant_to_list_comparator::cmp_nulls_equal(this, &idx)) + if (!Predicant_to_list_comparator::cmp_nulls_equal(current_thd, this, &idx)) return args[idx + when_count()]; Item **pos= Item_func_decode_oracle::else_expr_addr(); return pos ? pos[0] : 0; @@ -2986,24 +3068,34 @@ my_decimal *Item_func_case::decimal_op(my_decimal *decimal_value) } -bool Item_func_case::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_func_case::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); Item *item= find_item(); if (!item) return (null_value= true); - Datetime dt(current_thd, item, fuzzydate); + Datetime_truncation_not_needed dt(thd, item, fuzzydate); return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type())); } -bool Item_func_case::time_op(MYSQL_TIME *ltime) +bool Item_func_case::time_op(THD *thd, MYSQL_TIME *ltime) +{ + DBUG_ASSERT(fixed == 1); + Item *item= find_item(); + if (!item) + return (null_value= true); + return (null_value= Time(thd, item).copy_to_mysql_time(ltime)); +} + + +bool Item_func_case::native_op(THD *thd, Native *to) { DBUG_ASSERT(fixed == 1); Item *item= find_item(); if (!item) return (null_value= true); - return (null_value= Time(item).copy_to_mysql_time(ltime)); + return val_native_with_conversion_from_item(thd, item, to, type_handler()); } @@ -3339,12 +3431,13 @@ double Item_func_coalesce::real_op() } -bool Item_func_coalesce::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_func_coalesce::date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); for (uint i= 0; i < arg_count; i++) { - Datetime dt(current_thd, args[i], fuzzydate & ~TIME_FUZZY_DATES); + Datetime_truncation_not_needed dt(thd, args[i], + fuzzydate & ~TIME_FUZZY_DATES); if (!dt.copy_to_mysql_time(ltime, mysql_timestamp_type())) return (null_value= false); } @@ -3352,18 +3445,30 @@ bool Item_func_coalesce::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) } -bool Item_func_coalesce::time_op(MYSQL_TIME *ltime) +bool Item_func_coalesce::time_op(THD *thd, MYSQL_TIME *ltime) { DBUG_ASSERT(fixed == 1); for (uint i= 0; i < arg_count; i++) { - if (!Time(args[i]).copy_to_mysql_time(ltime)) + if (!Time(thd, args[i]).copy_to_mysql_time(ltime)) return (null_value= false); } return (null_value= true); } +bool Item_func_coalesce::native_op(THD *thd, Native *to) +{ + DBUG_ASSERT(fixed == 1); + for (uint i= 0; i < arg_count; i++) + { + if (!val_native_with_conversion_from_item(thd, args[i], to, type_handler())) + return false; + } + return (null_value= true); +} + + my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); @@ -3641,11 +3746,58 @@ Item *in_longlong::create_item(THD *thd) } +static int cmp_timestamp(void *cmp_arg, + Timestamp_or_zero_datetime *a, + Timestamp_or_zero_datetime *b) +{ + return a->cmp(*b); +} + + +in_timestamp::in_timestamp(THD *thd, uint elements) + :in_vector(thd, elements, sizeof(Value), (qsort2_cmp) cmp_timestamp, 0) +{} + + +void in_timestamp::set(uint pos, Item *item) +{ + Timestamp_or_zero_datetime *buff= &((Timestamp_or_zero_datetime *) base)[pos]; + Timestamp_or_zero_datetime_native_null native(current_thd, item, true); + if (native.is_null()) + *buff= Timestamp_or_zero_datetime(); + else + *buff= Timestamp_or_zero_datetime(native); +} + + +uchar *in_timestamp::get_value(Item *item) +{ + Timestamp_or_zero_datetime_native_null native(current_thd, item, true); + if (native.is_null()) + return 0; + tmp= Timestamp_or_zero_datetime(native); + return (uchar*) &tmp; +} + + +Item *in_timestamp::create_item(THD *thd) +{ + return new (thd->mem_root) Item_timestamp_literal(thd); +} + + +void in_timestamp::value_to_item(uint pos, Item *item) +{ + const Timestamp_or_zero_datetime &buff= (((Timestamp_or_zero_datetime*) base)[pos]); + static_cast<Item_timestamp_literal*>(item)->set_value(buff); +} + + void in_datetime::set(uint pos,Item *item) { struct packed_longlong *buff= &((packed_longlong*) base)[pos]; - buff->val= item->val_datetime_packed(); + buff->val= item->val_datetime_packed(current_thd); buff->unsigned_flag= 1L; } @@ -3653,13 +3805,22 @@ void in_time::set(uint pos,Item *item) { struct packed_longlong *buff= &((packed_longlong*) base)[pos]; - buff->val= item->val_time_packed(); + buff->val= item->val_time_packed(current_thd); buff->unsigned_flag= 1L; } -uchar *in_temporal::get_value_internal(Item *item, enum_field_types f_type) +uchar *in_datetime::get_value(Item *item) { - tmp.val= item->val_temporal_packed(f_type); + tmp.val= item->val_datetime_packed(current_thd); + if (item->null_value) + return 0; + tmp.unsigned_flag= 1L; + return (uchar*) &tmp; +} + +uchar *in_time::get_value(Item *item) +{ + tmp.val= item->val_time_packed(current_thd); if (item->null_value) return 0; tmp.unsigned_flag= 1L; @@ -3871,39 +4032,15 @@ bool cmp_item_row::alloc_comparators(THD *thd, uint cols) void cmp_item_row::store_value(Item *item) { DBUG_ENTER("cmp_item_row::store_value"); - THD *thd= current_thd; - if (!alloc_comparators(thd, item->cols())) + DBUG_ASSERT(comparators); + DBUG_ASSERT(n == item->cols()); + item->bring_value(); + item->null_value= 0; + for (uint i=0; i < n; i++) { - item->bring_value(); - item->null_value= 0; - for (uint i=0; i < n; i++) - { - if (!comparators[i]) - { - /** - Comparators for the row elements that have temporal data types - are installed at initialization time by prepare_comparators(). - Here we install comparators for the other data types. - There is a bug in the below code. See MDEV-11511. - When performing: - (predicant0,predicant1) IN ((value00,value01),(value10,value11)) - It uses only the data type and the collation of the predicant - elements only. It should be fixed to aggregate the data type and - the collation for all elements at the N-th positions of the - predicate and all values: - - predicate0, value00, value01 - - predicate1, value10, value11 - */ - Item *elem= item->element_index(i); - const Type_handler *handler= elem->type_handler(); - DBUG_ASSERT(elem->cmp_type() != TIME_RESULT); - if (!(comparators[i]= - handler->make_cmp_item(thd, elem->collation.collation))) - break; // new failed - } - comparators[i]->store_value(item->element_index(i)); - item->null_value|= item->element_index(i)->null_value; - } + DBUG_ASSERT(comparators[i]); + comparators[i]->store_value(item->element_index(i)); + item->null_value|= item->element_index(i)->null_value; } DBUG_VOID_RETURN; } @@ -3996,9 +4133,8 @@ int cmp_item_decimal::cmp_not_null(const Value *val) int cmp_item_decimal::cmp(Item *arg) { - my_decimal tmp_buf, *tmp= arg->val_decimal(&tmp_buf); - return (m_null_value || arg->null_value) ? - UNKNOWN : (my_decimal_cmp(&value, tmp) != 0); + VDec tmp(arg); + return m_null_value || tmp.is_null() ? UNKNOWN : (tmp.cmp(&value) != 0); } @@ -4015,14 +4151,6 @@ cmp_item* cmp_item_decimal::make_same() } -void cmp_item_temporal::store_value_internal(Item *item, - enum_field_types f_type) -{ - value= item->val_temporal_packed(f_type); - m_null_value= item->null_value; -} - - int cmp_item_datetime::cmp_not_null(const Value *val) { DBUG_ASSERT(!val->is_null()); @@ -4033,7 +4161,7 @@ int cmp_item_datetime::cmp_not_null(const Value *val) int cmp_item_datetime::cmp(Item *arg) { - const bool rc= value != arg->val_datetime_packed(); + const bool rc= value != arg->val_datetime_packed(current_thd); return (m_null_value || arg->null_value) ? UNKNOWN : rc; } @@ -4048,7 +4176,7 @@ int cmp_item_time::cmp_not_null(const Value *val) int cmp_item_time::cmp(Item *arg) { - const bool rc= value != arg->val_time_packed(); + const bool rc= value != arg->val_time_packed(current_thd); return (m_null_value || arg->null_value) ? UNKNOWN : rc; } @@ -4072,6 +4200,49 @@ cmp_item *cmp_item_time::make_same() } +void cmp_item_timestamp::store_value(Item *item) +{ + item->val_native_with_conversion(current_thd, &m_native, + &type_handler_timestamp2); + m_null_value= item->null_value; +} + + +int cmp_item_timestamp::cmp_not_null(const Value *val) +{ + /* + This method will be implemented when we add this syntax: + SELECT TIMESTAMP WITH LOCAL TIME ZONE '2001-01-01 10:20:30' + For now TIMESTAMP is compared to non-TIMESTAMP using DATETIME. + */ + DBUG_ASSERT(0); + return 0; +} + + +int cmp_item_timestamp::cmp(Item *arg) +{ + THD *thd= current_thd; + Timestamp_or_zero_datetime_native_null tmp(thd, arg, true); + return m_null_value || tmp.is_null() ? UNKNOWN : + type_handler_timestamp2.cmp_native(m_native, tmp) != 0; +} + + +int cmp_item_timestamp::compare(cmp_item *arg) +{ + cmp_item_timestamp *tmp= static_cast<cmp_item_timestamp*>(arg); + return type_handler_timestamp2.cmp_native(m_native, tmp->m_native); +} + + +cmp_item* cmp_item_timestamp::make_same() +{ + return new cmp_item_timestamp(); +} + + + bool Item_func_in::count_sargable_conds(void *arg) { ((SELECT_LEX*) arg)->cond_count++; @@ -4292,25 +4463,84 @@ bool Item_func_in::value_list_convert_const_to_int(THD *thd) } -/** - Historically this code installs comparators at initialization time - for temporal ROW elements only. All other comparators are installed later, - during the first store_value(). This causes the bug MDEV-11511. - See also comments in cmp_item_row::store_value(). -*/ -bool cmp_item_row::prepare_comparators(THD *thd, Item **args, uint arg_count) +bool cmp_item_row:: + aggregate_row_elements_for_comparison(THD *thd, + Type_handler_hybrid_field_type *cmp, + Item_args *tmp, + const char *funcname, + uint col, + uint level) +{ + DBUG_EXECUTE_IF("cmp_item", + { + for (uint i= 0 ; i < tmp->argument_count(); i++) + { + Item *arg= tmp->arguments()[i]; + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_UNKNOWN_ERROR, "DBUG: %s[%d,%d] handler=%s", + String_space(level).c_ptr(), col, i, + arg->type_handler()->name().ptr()); + } + } + ); + bool err= cmp->aggregate_for_comparison(funcname, tmp->arguments(), + tmp->argument_count(), true); + DBUG_EXECUTE_IF("cmp_item", + { + if (!err) + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_UNKNOWN_ERROR, "DBUG: %s=> handler=%s", + String_space(level).c_ptr(), + cmp->type_handler()->name().ptr()); + } + ); + return err; +} + + +bool cmp_item_row::prepare_comparators(THD *thd, const char *funcname, + const Item_args *args, uint level) { + DBUG_EXECUTE_IF("cmp_item", + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_UNKNOWN_ERROR, "DBUG: %sROW(%d args) level=%d", + String_space(level).c_ptr(), + args->argument_count(), level);); + DBUG_ASSERT(args->argument_count() > 0); + if (alloc_comparators(thd, args->arguments()[0]->cols())) + return true; + DBUG_ASSERT(n == args->arguments()[0]->cols()); for (uint col= 0; col < n; col++) { - Item *date_arg= find_date_time_item(args, arg_count, col); - if (date_arg) + Item_args tmp; + Type_handler_hybrid_field_type cmp; + + if (tmp.alloc_and_extract_row_elements(thd, args, col) || + aggregate_row_elements_for_comparison(thd, &cmp, &tmp, + funcname, col, level + 1)) + return true; + + /* + There is a legacy bug (MDEV-11511) in the code below, + which should be fixed eventually. + When performing: + (predicant0,predicant1) IN ((value00,value01),(value10,value11)) + It uses only the data type and the collation of the predicant + elements only. It should be fixed to take into account the data type and + the collation for all elements at the N-th positions of the + predicate and all values: + - predicate0, value00, value01 + - predicate1, value10, value11 + */ + Item *item0= args->arguments()[0]->element_index(col); + CHARSET_INFO *collation= item0->collation.collation; + if (!(comparators[col]= cmp.type_handler()->make_cmp_item(thd, collation))) + return true; + if (cmp.type_handler() == &type_handler_row) { - // TODO: do like the scalar comparators do - const Type_handler *h= date_arg->type_handler(); - comparators[col]= h->field_type() == MYSQL_TYPE_TIME ? - (cmp_item *) new (thd->mem_root) cmp_item_time() : - (cmp_item *) new (thd->mem_root) cmp_item_datetime(); - if (!comparators[col]) + // Prepare comparators for ROW elements recursively + cmp_item_row *row= static_cast<cmp_item_row*>(comparators[col]); + if (row->prepare_comparators(thd, funcname, &tmp, level + 1)) return true; } } @@ -4320,19 +4550,10 @@ bool cmp_item_row::prepare_comparators(THD *thd, Item **args, uint arg_count) bool Item_func_in::fix_for_row_comparison_using_bisection(THD *thd) { - uint cols= args[0]->cols(); if (unlikely(!(array= new (thd->mem_root) in_row(thd, arg_count-1, 0)))) return true; cmp_item_row *cmp= &((in_row*)array)->tmp; - if (cmp->alloc_comparators(thd, cols) || - cmp->prepare_comparators(thd, args, arg_count)) - return true; - /* - Only DATETIME items comparators were initialized. - Call store_value() to setup others. - */ - cmp->store_value(args[0]); - if (unlikely(thd->is_fatal_error)) // OOM + if (cmp->prepare_comparators(thd, func_name(), this, 0)) return true; fix_in_vector(); return false; @@ -4371,8 +4592,7 @@ bool Item_func_in::fix_for_row_comparison_using_cmp_items(THD *thd) DBUG_ASSERT(get_comparator_type_handler(0) == &type_handler_row); DBUG_ASSERT(get_comparator_cmp_item(0)); cmp_item_row *cmp_row= (cmp_item_row*) get_comparator_cmp_item(0); - return cmp_row->alloc_comparators(thd, args[0]->cols()) || - cmp_row->prepare_comparators(thd, args, arg_count); + return cmp_row->prepare_comparators(thd, func_name(), this, 0); } @@ -4643,7 +4863,7 @@ Item_cond::fix_fields(THD *thd, Item **ref) const_item_cache= FALSE; } - with_sum_func|= item->with_sum_func; + join_with_sum_func(item); with_param|= item->with_param; with_field|= item->with_field; m_with_subquery|= item->with_subquery(); @@ -6297,76 +6517,53 @@ void Item_equal::add_const(THD *thd, Item *c) equal_items.push_front(c, thd->mem_root); return; } - Item *const_item= get_const(); - switch (Item_equal::compare_type_handler()->cmp_type()) { - case TIME_RESULT: - { - enum_field_types f_type= context_field->field_type(); - longlong value0= c->val_temporal_packed(f_type); - longlong value1= const_item->val_temporal_packed(f_type); - cond_false= c->null_value || const_item->null_value || value0 != value1; - break; - } - case STRING_RESULT: - { - String *str1, *str2; - /* - Suppose we have an expression (with a string type field) like this: - WHERE field=const1 AND field=const2 ... - - For all pairs field=constXXX we know that: - - - Item_func_eq::fix_length_and_dec() performed collation and character - set aggregation and added character set converters when needed. - Note, the case like: - WHERE field=const1 COLLATE latin1_bin AND field=const2 - is not handled here, because the field would be replaced to - Item_func_set_collation, which cannot get into Item_equal. - So all constXXX that are handled by Item_equal - already have compatible character sets with "field". - - - Also, Field_str::test_if_equality_guarantees_uniqueness() guarantees - that the comparison collation of all equalities handled by Item_equal - match the the collation of the field. - - Therefore, at Item_equal::add_const() time all constants constXXX - should be directly comparable to each other without an additional - character set conversion. - It's safe to do val_str() for "const_item" and "c" and compare - them according to the collation of the *field*. - - So in a script like this: - CREATE TABLE t1 (a VARCHAR(10) COLLATE xxx); - INSERT INTO t1 VALUES ('a'),('A'); - SELECT * FROM t1 WHERE a='a' AND a='A'; - Item_equal::add_const() effectively rewrites the condition to: - SELECT * FROM t1 WHERE a='a' AND 'a' COLLATE xxx='A'; - and then to: - SELECT * FROM t1 WHERE a='a'; // if the two constants were equal - // e.g. in case of latin1_swedish_ci - or to: - SELECT * FROM t1 WHERE FALSE; // if the two constants were not equal - // e.g. in case of latin1_bin - - Note, both "const_item" and "c" can return NULL, e.g.: - SELECT * FROM t1 WHERE a=NULL AND a='const'; - SELECT * FROM t1 WHERE a='const' AND a=NULL; - SELECT * FROM t1 WHERE a='const' AND a=(SELECT MAX(a) FROM t2) - */ - cond_false= !(str1= const_item->val_str(&cmp_value1)) || - !(str2= c->val_str(&cmp_value2)) || - !str1->eq(str2, compare_collation()); - break; - } - default: - { - Item_func_eq *func= new (thd->mem_root) Item_func_eq(thd, c, const_item); - if (func->set_cmp_func()) - return; - func->quick_fix_field(); - cond_false= !func->val_int(); - } - } + + /* + Suppose we have an expression (with a string type field) like this: + WHERE field=const1 AND field=const2 ... + + For all pairs field=constXXX we know that: + + - Item_func_eq::fix_length_and_dec() performed collation and character + set aggregation and added character set converters when needed. + Note, the case like: + WHERE field=const1 COLLATE latin1_bin AND field=const2 + is not handled here, because the field would be replaced to + Item_func_set_collation, which cannot get into Item_equal. + So all constXXX that are handled by Item_equal + already have compatible character sets with "field". + + - Also, Field_str::test_if_equality_guarantees_uniqueness() guarantees + that the comparison collation of all equalities handled by Item_equal + match the the collation of the field. + + Therefore, at Item_equal::add_const() time all constants constXXX + should be directly comparable to each other without an additional + character set conversion. + It's safe to do val_str() for "const_item" and "c" and compare + them according to the collation of the *field*. + + So in a script like this: + CREATE TABLE t1 (a VARCHAR(10) COLLATE xxx); + INSERT INTO t1 VALUES ('a'),('A'); + SELECT * FROM t1 WHERE a='a' AND a='A'; + Item_equal::add_const() effectively rewrites the condition to: + SELECT * FROM t1 WHERE a='a' AND 'a' COLLATE xxx='A'; + and then to: + SELECT * FROM t1 WHERE a='a'; // if the two constants were equal + // e.g. in case of latin1_swedish_ci + or to: + SELECT * FROM t1 WHERE FALSE; // if the two constants were not equal + // e.g. in case of latin1_bin + + Note, both "const_item" and "c" can return NULL, e.g.: + SELECT * FROM t1 WHERE a=NULL AND a='const'; + SELECT * FROM t1 WHERE a='const' AND a=NULL; + SELECT * FROM t1 WHERE a='const' AND a=(SELECT MAX(a) FROM t2) + */ + + cond_false= !Item_equal::compare_type_handler()->Item_eq_value(thd, this, c, + get_const()); if (with_const && equal_items.elements == 1) cond_true= TRUE; if (cond_false || cond_true) @@ -6671,7 +6868,7 @@ bool Item_equal::fix_fields(THD *thd, Item **ref) used_tables_cache|= item->used_tables(); tmp_table_map= item->not_null_tables(); not_null_tables_cache|= tmp_table_map; - DBUG_ASSERT(!item->with_sum_func && !item->with_subquery()); + DBUG_ASSERT(!item->with_sum_func() && !item->with_subquery()); if (item->maybe_null) maybe_null= 1; if (!item->get_item_equal()) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 60b56090a23..882f92465b1 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -68,6 +68,7 @@ class Arg_comparator: public Sql_alloc if (val1 == val2) return 0; return 1; } + NativeBuffer<STRING_BUFFER_USUAL_SIZE> m_native1, m_native2; public: /* Allow owner function to use string buffers. */ String value1, value2; @@ -89,6 +90,7 @@ public: bool set_cmp_func_string(); bool set_cmp_func_time(); bool set_cmp_func_datetime(); + bool set_cmp_func_native(); bool set_cmp_func_int(); bool set_cmp_func_real(); bool set_cmp_func_decimal(); @@ -121,6 +123,8 @@ public: int compare_e_datetime(); int compare_time(); int compare_e_time(); + int compare_native(); + int compare_e_native(); int compare_json_str_basic(Item *j, Item *s); int compare_json_str(); int compare_str_json(); @@ -152,7 +156,8 @@ public: class SEL_ARG; struct KEY_PART; -class Item_bool_func :public Item_int_func +class Item_bool_func :public Item_int_func, + public Type_cmp_attributes { protected: /* @@ -215,9 +220,9 @@ public: Item_bool_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {} Item_bool_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { } Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {} - const Type_handler *type_handler() const { return &type_handler_long; } - bool is_bool_type() { return true; } - virtual CHARSET_INFO *compare_collation() const { return NULL; } + const Type_handler *type_handler() const { return &type_handler_bool; } + const Type_handler *fixed_type_handler() const { return &type_handler_bool; } + CHARSET_INFO *compare_collation() const { return NULL; } bool fix_length_and_dec() { decimals=0; max_length=1; return FALSE; } uint decimal_precision() const { return 1; } bool need_parentheses_in_default() { return true; } @@ -891,6 +896,7 @@ class Item_func_between :public Item_func_opt_neg protected: SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Field *field, Item *value); + bool val_int_cmp_int_finalize(longlong value, longlong a, longlong b); public: String value0,value1,value2; Item_func_between(THD *thd, Item *a, Item *b, Item *c): @@ -931,7 +937,9 @@ public: { return get_item_copy<Item_func_between>(thd, this); } longlong val_int_cmp_string(); - longlong val_int_cmp_temporal(); + longlong val_int_cmp_datetime(); + longlong val_int_cmp_time(); + longlong val_int_cmp_native(); longlong val_int_cmp_int(); longlong val_int_cmp_real(); longlong val_int_cmp_decimal(); @@ -954,7 +962,7 @@ public: { if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) return TRUE; - fix_char_length(2); + fix_char_length(2); // returns "1" or "0" or "-1" return FALSE; } Item *get_copy(THD *thd) @@ -1008,8 +1016,9 @@ public: longlong int_op(); String *str_op(String *); my_decimal *decimal_op(my_decimal *); - bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool time_op(MYSQL_TIME *ltime); + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool time_op(THD *thd, MYSQL_TIME *ltime); + bool native_op(THD *thd, Native *to); bool fix_length_and_dec() { if (aggregate_for_result(func_name(), args, arg_count, true)) @@ -1087,8 +1096,9 @@ public: longlong int_op(); String *str_op(String *str); my_decimal *decimal_op(my_decimal *); - bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool time_op(MYSQL_TIME *ltime); + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool time_op(THD *thd, MYSQL_TIME *ltime); + bool native_op(THD *thd, Native *to); bool fix_length_and_dec() { if (Item_func_case_abbreviation2::fix_length_and_dec2(args)) @@ -1122,12 +1132,12 @@ public: :Item_func_case_abbreviation2(thd, a, b, c) { } - bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - Datetime dt(current_thd, find_item(), fuzzydate); + Datetime_truncation_not_needed dt(thd, find_item(), fuzzydate); return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type())); } - bool time_op(MYSQL_TIME *ltime) + bool time_op(THD *thd, MYSQL_TIME *ltime) { return (null_value= Time(find_item()).copy_to_mysql_time(ltime)); } @@ -1147,6 +1157,11 @@ public: { return val_str_from_item(find_item(), str); } + bool native_op(THD *thd, Native *to) + { + return val_native_with_conversion_from_item(thd, find_item(), to, + type_handler()); + } }; @@ -1240,12 +1255,13 @@ public: Item_func_hybrid_field_type::cleanup(); arg_count= 2; // See the comment to the constructor } - bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool time_op(MYSQL_TIME *ltime); + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool time_op(THD *thd, MYSQL_TIME *ltime); double real_op(); longlong int_op(); String *str_op(String *str); my_decimal *decimal_op(my_decimal *); + bool native_op(THD *thd, Native *to); bool fix_length_and_dec(); bool walk(Item_processor processor, bool walk_subquery, void *arg); const char *func_name() const { return "nullif"; } @@ -1282,7 +1298,11 @@ public: { reset_first_arg_if_needed(); return this; } Item *derived_field_transformer_for_where(THD *thd, uchar *arg) { reset_first_arg_if_needed(); return this; } - Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg) + Item *grouping_field_transformer_for_where(THD *thd, uchar *arg) + { reset_first_arg_if_needed(); return this; } + Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg) + { reset_first_arg_if_needed(); return this; } + Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg) { reset_first_arg_if_needed(); return this; } }; @@ -1405,13 +1425,24 @@ public: }; +class in_timestamp :public in_vector +{ + Timestamp_or_zero_datetime tmp; +public: + in_timestamp(THD *thd, uint elements); + void set(uint pos,Item *item); + uchar *get_value(Item *item); + Item* create_item(THD *thd); + void value_to_item(uint pos, Item *item); + const Type_handler *type_handler() const { return &type_handler_timestamp2; } +}; + + /* Class to represent a vector of constant DATE/DATETIME values. */ class in_temporal :public in_longlong { -protected: - uchar *get_value_internal(Item *item, enum_field_types f_type); public: /* Cache for the left item. */ @@ -1424,8 +1455,6 @@ public: Item_datetime *dt= static_cast<Item_datetime*>(item); dt->set(val->val, type_handler()->mysql_timestamp_type()); } - uchar *get_value(Item *item) - { return get_value_internal(item, type_handler()->field_type()); } friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b); }; @@ -1437,6 +1466,7 @@ public: :in_temporal(thd, elements) {} void set(uint pos,Item *item); + uchar *get_value(Item *item); const Type_handler *type_handler() const { return &type_handler_datetime2; } }; @@ -1448,6 +1478,7 @@ public: :in_temporal(thd, elements) {} void set(uint pos,Item *item); + uchar *get_value(Item *item); const Type_handler *type_handler() const { return &type_handler_time2; } }; @@ -1622,7 +1653,6 @@ class cmp_item_temporal: public cmp_item_scalar { protected: longlong value; - void store_value_internal(Item *item, enum_field_types type); public: cmp_item_temporal() {} int compare(cmp_item *ci); @@ -1637,7 +1667,8 @@ public: { } void store_value(Item *item) { - store_value_internal(item, MYSQL_TYPE_DATETIME); + value= item->val_datetime_packed(current_thd); + m_null_value= item->null_value; } int cmp_not_null(const Value *val); int cmp(Item *arg); @@ -1653,13 +1684,28 @@ public: { } void store_value(Item *item) { - store_value_internal(item, MYSQL_TYPE_TIME); + value= item->val_time_packed(current_thd); + m_null_value= item->null_value; } int cmp_not_null(const Value *val); int cmp(Item *arg); cmp_item *make_same(); }; + +class cmp_item_timestamp: public cmp_item_scalar +{ + Timestamp_or_zero_datetime_native m_native; +public: + cmp_item_timestamp() :cmp_item_scalar() { } + void store_value(Item *item); + int cmp_not_null(const Value *val); + int cmp(Item *arg); + int compare(cmp_item *ci); + cmp_item *make_same(); +}; + + class cmp_item_real : public cmp_item_scalar { double value; @@ -1891,7 +1937,7 @@ class Predicant_to_list_comparator return UNKNOWN; return in_item->cmp(args->arguments()[m_comparators[i].m_arg_index]); } - int cmp_args_nulls_equal(Item_args *args, uint i) + int cmp_args_nulls_equal(THD *thd, Item_args *args, uint i) { Predicant_to_value_comparator *cmp= &m_comparators[m_comparators[i].m_handler_index]; @@ -1902,7 +1948,7 @@ class Predicant_to_list_comparator ValueBuffer<MAX_FIELD_WIDTH> val; if (m_comparators[i].m_handler_index == i) in_item->store_value(predicant); - m_comparators[i].m_handler->Item_save_in_value(arg, &val); + m_comparators[i].m_handler->Item_save_in_value(thd, arg, &val); if (predicant->null_value && val.is_null()) return FALSE; // Two nulls are equal if (predicant->null_value || val.is_null()) @@ -2083,12 +2129,12 @@ public: /* Same as above, but treats two NULLs as equal, e.g. as in DECODE_ORACLE(). */ - bool cmp_nulls_equal(Item_args *args, uint *idx) + bool cmp_nulls_equal(THD *thd, Item_args *args, uint *idx) { for (uint i= 0 ; i < m_comparator_count ; i++) { DBUG_ASSERT(m_comparators[i].m_handler != NULL); - if (cmp_args_nulls_equal(args, i) == FALSE) + if (cmp_args_nulls_equal(thd, args, i) == FALSE) { *idx= m_comparators[i].m_arg_index; return false; // Found a matching value @@ -2124,8 +2170,9 @@ public: longlong int_op(); String *str_op(String *); my_decimal *decimal_op(my_decimal *); - bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool time_op(MYSQL_TIME *ltime); + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool time_op(THD *thd, MYSQL_TIME *ltime); + bool native_op(THD *thd, Native *to); bool fix_fields(THD *thd, Item **ref); table_map not_null_tables() const { return 0; } const char *func_name() const { return "case"; } @@ -2421,12 +2468,19 @@ class cmp_item_row :public cmp_item { cmp_item **comparators; uint n; + bool alloc_comparators(THD *thd, uint n); + bool aggregate_row_elements_for_comparison(THD *thd, + Type_handler_hybrid_field_type *cmp, + Item_args *tmp, + const char *funcname, + uint col, + uint level); public: cmp_item_row(): comparators(0), n(0) {} ~cmp_item_row(); void store_value(Item *item); - bool alloc_comparators(THD *thd, uint n); - bool prepare_comparators(THD *, Item **args, uint arg_count); + bool prepare_comparators(THD *, const char *funcname, + const Item_args *args, uint level); int cmp(Item *arg); int cmp_not_null(const Value *val) { @@ -2507,9 +2561,8 @@ public: { Field *field=((Item_field*) args[0]->real_item())->field; - if (((field->type() == MYSQL_TYPE_DATE) || - (field->type() == MYSQL_TYPE_DATETIME)) && - (field->flags & NOT_NULL_FLAG)) + if ((field->flags & NOT_NULL_FLAG) && + field->type_handler()->cond_notnull_field_isnull_to_field_eq_zero()) return true; } return false; @@ -2630,6 +2683,9 @@ public: Item_bool_func2(thd, a, b), canDoTurboBM(FALSE), pattern(0), pattern_len(0), bmGs(0), bmBc(0), escape_item(escape_arg), escape_used_in_parsing(escape_used), use_sampling(0), negated(0) {} + + bool get_negated() const { return negated; } // Used by ColumnStore + longlong val_int(); enum Functype functype() const { return LIKE_FUNC; } void print(String *str, enum_query_type query_type); @@ -3084,7 +3140,6 @@ class Item_equal: public Item_bool_func const Type_handler *m_compare_handler; CHARSET_INFO *m_compare_collation; - String cmp_value1, cmp_value2; public: COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */ @@ -3142,6 +3197,8 @@ public: { return used_tables() & tab_map; } + bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred); + friend class Item_equal_fields_iterator; bool count_sargable_conds(void *arg); friend class Item_equal_iterator<List_iterator_fast,Item>; @@ -3293,11 +3350,8 @@ public: inline bool is_cond_and(Item *item) { - if (item->type() != Item::COND_ITEM) - return FALSE; - - Item_cond *cond_item= (Item_cond*) item; - return (cond_item->functype() == Item_func::COND_AND_FUNC); + Item_func *func_item= item->get_item_func(); + return func_item && func_item->functype() == Item_func::COND_AND_FUNC; } class Item_cond_or :public Item_cond @@ -3398,11 +3452,8 @@ public: inline bool is_cond_or(Item *item) { - if (item->type() != Item::COND_ITEM) - return FALSE; - - Item_cond *cond_item= (Item_cond*) item; - return (cond_item->functype() == Item_func::COND_OR_FUNC); + Item_func *func_item= item->get_item_func(); + return func_item && func_item->functype() == Item_func::COND_OR_FUNC; } Item *and_expressions(Item *a, Item *b, Item **org_item); diff --git a/sql/item_create.cc b/sql/item_create.cc index 84f2c91ba54..87bf69f3c96 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -3487,12 +3487,11 @@ Create_sp_func::create_with_db(THD *thd, LEX_CSTRING *db, LEX_CSTRING *name, sph->add_used_routine(lex, thd, qname); if (pkgname.m_name.length) sp_handler_package_body.add_used_routine(lex, thd, &pkgname); + Name_resolution_context *ctx= lex->current_context(); if (arg_count > 0) - func= new (thd->mem_root) Item_func_sp(thd, lex->current_context(), - qname, sph, *item_list); + func= new (thd->mem_root) Item_func_sp(thd, ctx, qname, sph, *item_list); else - func= new (thd->mem_root) Item_func_sp(thd, lex->current_context(), - qname, sph); + func= new (thd->mem_root) Item_func_sp(thd, ctx, qname, sph); lex->safe_to_cache_query= 0; return func; @@ -3637,7 +3636,7 @@ Create_func_addtime Create_func_addtime::s_singleton; Item* Create_func_addtime::create_2_arg(THD *thd, Item *arg1, Item *arg2) { - return new (thd->mem_root) Item_func_add_time(thd, arg1, arg2, 0, 0); + return new (thd->mem_root) Item_func_add_time(thd, arg1, arg2, false); } @@ -6104,7 +6103,26 @@ Create_func_name_const Create_func_name_const::s_singleton; Item* Create_func_name_const::create_2_arg(THD *thd, Item *arg1, Item *arg2) { - return new (thd->mem_root) Item_name_const(thd, arg1, arg2); + if (!arg1->basic_const_item()) + goto err; + + if (arg2->basic_const_item()) + return new (thd->mem_root) Item_name_const(thd, arg1, arg2); + + if (arg2->type() == Item::FUNC_ITEM) + { + Item_func *value_func= (Item_func *) arg2; + if (value_func->functype() != Item_func::COLLATE_FUNC && + value_func->functype() != Item_func::NEG_FUNC) + goto err; + + if (!value_func->key_item()->basic_const_item()) + goto err; + return new (thd->mem_root) Item_name_const(thd, arg1, arg2); + } +err: + my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST"); + return NULL; } @@ -6658,7 +6676,7 @@ Create_func_subtime Create_func_subtime::s_singleton; Item* Create_func_subtime::create_2_arg(THD *thd, Item *arg1, Item *arg2) { - return new (thd->mem_root) Item_func_add_time(thd, arg1, arg2, 0, 1); + return new (thd->mem_root) Item_func_add_time(thd, arg1, arg2, true); } @@ -7433,84 +7451,6 @@ find_qualified_function_builder(THD *thd) } -static bool -have_important_literal_warnings(const MYSQL_TIME_STATUS *status) -{ - return (status->warnings & ~MYSQL_TIME_NOTE_TRUNCATED) != 0; -} - - -/** - Builder for datetime literals: - TIME'00:00:00', DATE'2001-01-01', TIMESTAMP'2001-01-01 00:00:00'. - @param thd The current thread - @param str Character literal - @param length Length of str - @param type Type of literal (TIME, DATE or DATETIME) - @param send_error Whether to generate an error on failure -*/ - -Item *create_temporal_literal(THD *thd, - const char *str, size_t length, - CHARSET_INFO *cs, - enum_field_types type, - bool send_error) -{ - MYSQL_TIME_STATUS status; - MYSQL_TIME ltime; - Item *item= NULL; - sql_mode_t flags= sql_mode_for_dates(thd); - - switch(type) - { - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_NEWDATE: - if (!str_to_datetime(cs, str, length, <ime, flags, &status) && - ltime.time_type == MYSQL_TIMESTAMP_DATE && !status.warnings) - item= new (thd->mem_root) Item_date_literal(thd, <ime); - break; - case MYSQL_TYPE_DATETIME: - if (!str_to_datetime(cs, str, length, <ime, flags, &status) && - ltime.time_type == MYSQL_TIMESTAMP_DATETIME && - !have_important_literal_warnings(&status)) - item= new (thd->mem_root) Item_datetime_literal(thd, <ime, - status.precision); - break; - case MYSQL_TYPE_TIME: - if (!str_to_time(cs, str, length, <ime, 0, &status) && - ltime.time_type == MYSQL_TIMESTAMP_TIME && - !have_important_literal_warnings(&status)) - item= new (thd->mem_root) Item_time_literal(thd, <ime, - status.precision); - break; - default: - DBUG_ASSERT(0); - } - - if (likely(item)) - { - if (status.warnings) // e.g. a note on nanosecond truncation - { - ErrConvString err(str, length, cs); - make_truncated_value_warning(thd, - Sql_condition::time_warn_level(status.warnings), - &err, ltime.time_type, 0, 0); - } - return item; - } - - if (send_error) - { - const char *typestr= - (type == MYSQL_TYPE_DATE) ? "DATE" : - (type == MYSQL_TYPE_TIME) ? "TIME" : "DATETIME"; - ErrConvString err(str, length, thd->variables.character_set_client); - my_error(ER_WRONG_VALUE, MYF(0), typestr, err.ptr()); - } - return NULL; -} - - static List<Item> *create_func_dyncol_prepare(THD *thd, DYNCALL_CREATE_DEF **dfs, List<DYNCALL_CREATE_DEF> &list) diff --git a/sql/item_create.h b/sql/item_create.h index 5983a092cdc..4fb3c07c4ae 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -191,21 +191,6 @@ protected: #endif -Item *create_temporal_literal(THD *thd, - const char *str, size_t length, - CHARSET_INFO *cs, - enum_field_types type, - bool send_error); -inline -Item *create_temporal_literal(THD *thd, const String *str, - enum_field_types type, - bool send_error) -{ - return create_temporal_literal(thd, - str->ptr(), str->length(), str->charset(), - type, send_error); -} - struct Native_func_registry { LEX_CSTRING name; diff --git a/sql/item_func.cc b/sql/item_func.cc index f902191d9cf..1f949a4445b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -145,7 +145,7 @@ void Item_func::sync_with_sum_func_and_with_field(List<Item> &list) Item *item; while ((item= li++)) { - with_sum_func|= item->with_sum_func; + join_with_sum_func(item); with_window_func|= item->with_window_func; with_field|= item->with_field; with_param|= item->with_param; @@ -367,7 +367,7 @@ Item_func::fix_fields(THD *thd, Item **ref) if (item->maybe_null) maybe_null=1; - with_sum_func= with_sum_func || item->with_sum_func; + join_with_sum_func(item); with_param= with_param || item->with_param; with_window_func= with_window_func || item->with_window_func; with_field= with_field || item->with_field; @@ -391,7 +391,7 @@ Item_func::quick_fix_field() { for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) { - if (!(*arg)->fixed) + if (!(*arg)->is_fixed()) (*arg)->quick_fix_field(); } } @@ -734,7 +734,7 @@ void Item_func::signal_divide_by_null() Item *Item_func::get_tmp_table_item(THD *thd) { - if (!with_sum_func && !const_item()) + if (!Item_func::with_sum_func() && !const_item()) return new (thd->mem_root) Item_temptable_field(thd, result_field); return copy_or_same(thd); } @@ -806,51 +806,6 @@ bool Item_func_plus::fix_length_and_dec(void) } -String *Item_func_hybrid_field_type::val_str_from_decimal_op(String *str) -{ - my_decimal decimal_value, *val; - if (!(val= decimal_op_with_null_check(&decimal_value))) - return 0; // null is set - DBUG_ASSERT(!null_value); - my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, FALSE, val); - str->set_charset(collation.collation); - my_decimal2string(E_DEC_FATAL_ERROR, val, 0, 0, 0, str); - return str; -} - -double Item_func_hybrid_field_type::val_real_from_decimal_op() -{ - my_decimal decimal_value, *val; - if (!(val= decimal_op_with_null_check(&decimal_value))) - return 0.0; // null is set - double result; - my_decimal2double(E_DEC_FATAL_ERROR, val, &result); - return result; -} - -longlong Item_func_hybrid_field_type::val_int_from_decimal_op() -{ - my_decimal decimal_value, *val; - if (!(val= decimal_op_with_null_check(&decimal_value))) - return 0; // null is set - longlong result; - my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result); - return result; -} - -bool Item_func_hybrid_field_type::get_date_from_decimal_op(MYSQL_TIME *ltime, - ulonglong fuzzydate) -{ - my_decimal value, *res; - if (!(res= decimal_op_with_null_check(&value)) || - decimal_to_datetime_with_warn(res, ltime, fuzzydate, - field_table_or_null(), - field_name_or_null())) - return make_zero_mysql_time(ltime, fuzzydate); - return (null_value= 0); -} - - String *Item_func_hybrid_field_type::val_str_from_int_op(String *str) { longlong nr= int_op(); @@ -876,19 +831,6 @@ Item_func_hybrid_field_type::val_decimal_from_int_op(my_decimal *dec) return dec; } -bool Item_func_hybrid_field_type::get_date_from_int_op(MYSQL_TIME *ltime, - ulonglong fuzzydate) -{ - longlong value= int_op(); - bool neg= !unsigned_flag && value < 0; - if (null_value || int_to_datetime_with_warn(neg, neg ? -value : value, - ltime, fuzzydate, - field_table_or_null(), - field_name_or_null())) - return make_zero_mysql_time(ltime, fuzzydate); - return (null_value= 0); -} - String *Item_func_hybrid_field_type::val_str_from_real_op(String *str) { @@ -914,22 +856,11 @@ Item_func_hybrid_field_type::val_decimal_from_real_op(my_decimal *dec) return dec; } -bool Item_func_hybrid_field_type::get_date_from_real_op(MYSQL_TIME *ltime, - ulonglong fuzzydate) -{ - double value= real_op(); - if (null_value || double_to_datetime_with_warn(value, ltime, fuzzydate, - field_table_or_null(), - field_name_or_null())) - return make_zero_mysql_time(ltime, fuzzydate); - return (null_value= 0); -} - String *Item_func_hybrid_field_type::val_str_from_date_op(String *str) { MYSQL_TIME ltime; - if (date_op_with_null_check(<ime) || + if (date_op_with_null_check(current_thd, <ime) || (null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH))) return (String *) 0; str->length(my_TIME_to_str(<ime, const_cast<char*>(str->ptr()), decimals)); @@ -941,7 +872,7 @@ String *Item_func_hybrid_field_type::val_str_from_date_op(String *str) double Item_func_hybrid_field_type::val_real_from_date_op() { MYSQL_TIME ltime; - if (date_op_with_null_check(<ime)) + if (date_op_with_null_check(current_thd, <ime)) return 0; return TIME_to_double(<ime); } @@ -949,7 +880,7 @@ double Item_func_hybrid_field_type::val_real_from_date_op() longlong Item_func_hybrid_field_type::val_int_from_date_op() { MYSQL_TIME ltime; - if (date_op_with_null_check(<ime)) + if (date_op_with_null_check(current_thd, <ime)) return 0; return TIME_to_ulonglong(<ime); } @@ -958,7 +889,7 @@ my_decimal * Item_func_hybrid_field_type::val_decimal_from_date_op(my_decimal *dec) { MYSQL_TIME ltime; - if (date_op_with_null_check(<ime)) + if (date_op_with_null_check(current_thd, <ime)) { my_decimal_set_zero(dec); return 0; @@ -970,7 +901,7 @@ Item_func_hybrid_field_type::val_decimal_from_date_op(my_decimal *dec) String *Item_func_hybrid_field_type::val_str_from_time_op(String *str) { MYSQL_TIME ltime; - if (time_op_with_null_check(<ime) || + if (time_op_with_null_check(current_thd, <ime) || (null_value= my_TIME_to_str(<ime, str, decimals))) return NULL; return str; @@ -979,20 +910,22 @@ String *Item_func_hybrid_field_type::val_str_from_time_op(String *str) double Item_func_hybrid_field_type::val_real_from_time_op() { MYSQL_TIME ltime; - return time_op_with_null_check(<ime) ? 0 : TIME_to_double(<ime); + return time_op_with_null_check(current_thd, <ime) ? 0 : + TIME_to_double(<ime); } longlong Item_func_hybrid_field_type::val_int_from_time_op() { MYSQL_TIME ltime; - return time_op_with_null_check(<ime) ? 0 : TIME_to_ulonglong(<ime); + return time_op_with_null_check(current_thd, <ime) ? 0 : + TIME_to_ulonglong(<ime); } my_decimal * Item_func_hybrid_field_type::val_decimal_from_time_op(my_decimal *dec) { MYSQL_TIME ltime; - if (time_op_with_null_check(<ime)) + if (time_op_with_null_check(current_thd, <ime)) { my_decimal_set_zero(dec); return 0; @@ -1020,18 +953,6 @@ Item_func_hybrid_field_type::val_decimal_from_str_op(my_decimal *decimal_value) return res ? decimal_from_string_with_check(decimal_value, res) : 0; } -bool Item_func_hybrid_field_type::get_date_from_str_op(MYSQL_TIME *ltime, - ulonglong fuzzydate) -{ - StringBuffer<40> tmp; - String *res; - if (!(res= str_op_with_null_check(&tmp)) || - str_to_datetime_with_warn(res->charset(), res->ptr(), res->length(), - ltime, fuzzydate)) - return make_zero_mysql_time(ltime, fuzzydate); - return (null_value= 0); -} - void Item_func_signed::print(String *str, enum_query_type query_type) { @@ -1051,47 +972,15 @@ void Item_func_unsigned::print(String *str, enum_query_type query_type) } -String *Item_decimal_typecast::val_str(String *str) -{ - my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf); - if (null_value) - return NULL; - my_decimal2string(E_DEC_FATAL_ERROR, tmp, 0, 0, 0, str); - return str; -} - - -double Item_decimal_typecast::val_real() -{ - my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf); - double res; - if (null_value) - return 0.0; - my_decimal2double(E_DEC_FATAL_ERROR, tmp, &res); - return res; -} - - -longlong Item_decimal_typecast::val_int() -{ - my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf); - longlong res; - if (null_value) - return 0; - my_decimal2int(E_DEC_FATAL_ERROR, tmp, unsigned_flag, &res); - return res; -} - - my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec) { - my_decimal tmp_buf, *tmp= args[0]->val_decimal(&tmp_buf); + VDec tmp(args[0]); bool sign; uint precision; - if ((null_value= args[0]->null_value)) + if ((null_value= tmp.is_null())) return NULL; - my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec); + tmp.round_to(dec, decimals, HALF_UP); sign= dec->sign(); if (unsigned_flag) { @@ -1275,17 +1164,13 @@ err: my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value) { - my_decimal value1, *val1; - my_decimal value2, *val2; - val1= args[0]->val_decimal(&value1); - if ((null_value= args[0]->null_value)) - return 0; - val2= args[1]->val_decimal(&value2); - if (!(null_value= (args[1]->null_value || + VDec2_lazy val(args[0], args[1]); + if (!(null_value= (val.has_null() || check_decimal_overflow(my_decimal_add(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, decimal_value, - val1, val2)) > 3))) + val.m_a.ptr(), + val.m_b.ptr())) > 3))) return decimal_value; return 0; } @@ -1415,18 +1300,13 @@ err: my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value) { - my_decimal value1, *val1; - my_decimal value2, *val2= - - val1= args[0]->val_decimal(&value1); - if ((null_value= args[0]->null_value)) - return 0; - val2= args[1]->val_decimal(&value2); - if (!(null_value= (args[1]->null_value || - (check_decimal_overflow(my_decimal_sub(E_DEC_FATAL_ERROR & - ~E_DEC_OVERFLOW, - decimal_value, val1, - val2)) > 3)))) + VDec2_lazy val(args[0], args[1]); + if (!(null_value= (val.has_null() || + check_decimal_overflow(my_decimal_sub(E_DEC_FATAL_ERROR & + ~E_DEC_OVERFLOW, + decimal_value, + val.m_a.ptr(), + val.m_b.ptr())) > 3))) return decimal_value; return 0; } @@ -1525,17 +1405,13 @@ err: my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value) { - my_decimal value1, *val1; - my_decimal value2, *val2; - val1= args[0]->val_decimal(&value1); - if ((null_value= args[0]->null_value)) - return 0; - val2= args[1]->val_decimal(&value2); - if (!(null_value= (args[1]->null_value || - (check_decimal_overflow(my_decimal_mul(E_DEC_FATAL_ERROR & - ~E_DEC_OVERFLOW, - decimal_value, val1, - val2)) > 3)))) + VDec2_lazy val(args[0], args[1]); + if (!(null_value= (val.has_null() || + check_decimal_overflow(my_decimal_mul(E_DEC_FATAL_ERROR & + ~E_DEC_OVERFLOW, + decimal_value, + val.m_a.ptr(), + val.m_b.ptr())) > 3))) return decimal_value; return 0; } @@ -1586,21 +1462,15 @@ double Item_func_div::real_op() my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value) { - my_decimal value1, *val1; - my_decimal value2, *val2; int err; - - val1= args[0]->val_decimal(&value1); - if ((null_value= args[0]->null_value)) - return 0; - val2= args[1]->val_decimal(&value2); - if ((null_value= args[1]->null_value)) + VDec2_lazy val(args[0], args[1]); + if ((null_value= val.has_null())) return 0; if ((err= check_decimal_overflow(my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW & ~E_DEC_DIV_ZERO, decimal_value, - val1, val2, + val.m_a.ptr(), val.m_b.ptr(), prec_increment))) > 3) { if (err == E_DEC_DIV_ZERO) @@ -1690,20 +1560,14 @@ longlong Item_func_int_div::val_int() if (args[0]->result_type() != INT_RESULT || args[1]->result_type() != INT_RESULT) { - my_decimal tmp; - my_decimal *val0p= args[0]->val_decimal(&tmp); - if ((null_value= args[0]->null_value)) - return 0; - my_decimal val0= *val0p; - - my_decimal *val1p= args[1]->val_decimal(&tmp); - if ((null_value= args[1]->null_value)) + VDec2_lazy val(args[0], args[1]); + if ((null_value= val.has_null())) return 0; - my_decimal val1= *val1p; int err; + my_decimal tmp; if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp, - &val0, &val1, 0)) > 3) + val.m_a.ptr(), val.m_b.ptr(), 0)) > 3) { if (err == E_DEC_DIV_ZERO) signal_divide_by_null(); @@ -1711,8 +1575,7 @@ longlong Item_func_int_div::val_int() } my_decimal truncated; - const bool do_truncate= true; - if (my_decimal_round(E_DEC_FATAL_ERROR, &tmp, 0, do_truncate, &truncated)) + if (tmp.round_to(&truncated, 0, TRUNCATE)) DBUG_ASSERT(false); longlong res; @@ -1814,17 +1677,11 @@ double Item_func_mod::real_op() my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value) { - my_decimal value1, *val1; - my_decimal value2, *val2; - - val1= args[0]->val_decimal(&value1); - if ((null_value= args[0]->null_value)) - return 0; - val2= args[1]->val_decimal(&value2); - if ((null_value= args[1]->null_value)) + VDec2_lazy val(args[0], args[1]); + if ((null_value= val.has_null())) return 0; switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value, - val1, val2)) { + val.m_a.ptr(), val.m_b.ptr())) { case E_DEC_TRUNCATED: case E_DEC_OK: return decimal_value; @@ -1894,10 +1751,10 @@ longlong Item_func_neg::int_op() my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value) { - my_decimal val, *value= args[0]->val_decimal(&val); - if (!(null_value= args[0]->null_value)) + VDec value(args[0]); + if (!(null_value= value.is_null())) { - my_decimal2decimal(value, decimal_value); + my_decimal2decimal(value.ptr(), decimal_value); my_decimal_neg(decimal_value); return decimal_value; } @@ -1921,7 +1778,7 @@ void Item_func_neg::fix_length_and_dec_int() longlong val= args[0]->val_int(); if ((ulonglong) val >= (ulonglong) LONGLONG_MIN && ((ulonglong) val != (ulonglong) LONGLONG_MIN || - args[0]->type() != INT_ITEM)) + !args[0]->is_of_type(CONST_ITEM, INT_RESULT))) { /* Ensure that result is converted to DECIMAL, as longlong can't hold @@ -1992,10 +1849,10 @@ longlong Item_func_abs::int_op() my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value) { - my_decimal val, *value= args[0]->val_decimal(&val); - if (!(null_value= args[0]->null_value)) + VDec value(args[0]); + if (!(null_value= value.is_null())) { - my_decimal2decimal(value, decimal_value); + my_decimal2decimal(value.ptr(), decimal_value); if (decimal_value->sign()) my_decimal_neg(decimal_value); return decimal_value; @@ -2317,25 +2174,15 @@ bool Item_func_int_val::fix_length_and_dec() longlong Item_func_ceiling::int_op() { - longlong result; switch (args[0]->result_type()) { case INT_RESULT: - result= args[0]->val_int(); - null_value= args[0]->null_value; - break; + return val_int_from_item(args[0]); case DECIMAL_RESULT: - { - my_decimal dec_buf, *dec; - if ((dec= Item_func_ceiling::decimal_op(&dec_buf))) - my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result); - else - result= 0; + return VDec_op(this).to_longlong(unsigned_flag); + default: break; } - default: - result= (longlong)Item_func_ceiling::real_op(); - }; - return result; + return (longlong) Item_func_ceiling::real_op(); } @@ -2353,10 +2200,9 @@ double Item_func_ceiling::real_op() my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value) { - my_decimal val, *value= args[0]->val_decimal(&val); - if (!(null_value= (args[0]->null_value || - my_decimal_ceiling(E_DEC_FATAL_ERROR, value, - decimal_value) > 1))) + VDec value(args[0]); + if (!(null_value= (value.is_null() || + value.round_to(decimal_value, 0, CEILING) > 1))) return decimal_value; return 0; } @@ -2364,25 +2210,19 @@ my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value) longlong Item_func_floor::int_op() { - longlong result; switch (args[0]->result_type()) { case INT_RESULT: - result= args[0]->val_int(); - null_value= args[0]->null_value; - break; + return val_int_from_item(args[0]); case DECIMAL_RESULT: { my_decimal dec_buf, *dec; - if ((dec= Item_func_floor::decimal_op(&dec_buf))) - my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result); - else - result= 0; - break; + return (!(dec= Item_func_floor::decimal_op(&dec_buf))) ? 0 : + dec->to_longlong(unsigned_flag); } default: - result= (longlong)Item_func_floor::real_op(); - }; - return result; + break; + } + return (longlong) Item_func_floor::real_op(); } @@ -2400,10 +2240,9 @@ double Item_func_floor::real_op() my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value) { - my_decimal val, *value= args[0]->val_decimal(&val); - if (!(null_value= (args[0]->null_value || - my_decimal_floor(E_DEC_FATAL_ERROR, value, - decimal_value) > 1))) + VDec value(args[0]); + if (!(null_value= (value.is_null() || + value.round_to(decimal_value, 0, FLOOR) > 1))) return decimal_value; return 0; } @@ -2592,16 +2431,16 @@ longlong Item_func_round::int_op() my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value) { - my_decimal val, *value= args[0]->val_decimal(&val); + VDec value(args[0]); longlong dec= args[1]->val_int(); if (dec >= 0 || args[1]->unsigned_flag) dec= MY_MIN((ulonglong) dec, decimals); else if (dec < INT_MIN) dec= INT_MIN; - if (!(null_value= (args[0]->null_value || args[1]->null_value || - my_decimal_round(E_DEC_FATAL_ERROR, value, (int) dec, - truncate, decimal_value) > 1))) + if (!(null_value= (value.is_null() || args[1]->null_value || + value.round_to(decimal_value, (uint) dec, + truncate ? TRUNCATE : HALF_UP) > 1))) return decimal_value; return 0; } @@ -2739,14 +2578,15 @@ bool Item_func_min_max::fix_attributes(Item **items, uint nitems) 0 Otherwise */ -bool Item_func_min_max::get_date_native(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_func_min_max::get_date_native(THD *thd, MYSQL_TIME *ltime, + date_mode_t fuzzydate) { longlong UNINIT_VAR(min_max); DBUG_ASSERT(fixed == 1); for (uint i=0; i < arg_count ; i++) { - longlong res= args[i]->val_datetime_packed(); + longlong res= args[i]->val_datetime_packed(thd); /* Check if we need to stop (because of error or KILL) and stop the loop */ if (unlikely(args[i]->null_value)) @@ -2757,8 +2597,8 @@ bool Item_func_min_max::get_date_native(MYSQL_TIME *ltime, ulonglong fuzzy_date) } unpack_time(min_max, ltime, mysql_timestamp_type()); - if (!(fuzzy_date & TIME_TIME_ONLY) && - unlikely((null_value= check_date_with_warn(ltime, fuzzy_date, + if (!(fuzzydate & TIME_TIME_ONLY) && + unlikely((null_value= check_date_with_warn(thd, ltime, fuzzydate, MYSQL_TIMESTAMP_ERROR)))) return true; @@ -2766,17 +2606,17 @@ bool Item_func_min_max::get_date_native(MYSQL_TIME *ltime, ulonglong fuzzy_date) } -bool Item_func_min_max::get_time_native(MYSQL_TIME *ltime) +bool Item_func_min_max::get_time_native(THD *thd, MYSQL_TIME *ltime) { DBUG_ASSERT(fixed == 1); - Time value(args[0]); + Time value(thd, args[0], Time::Options(thd), decimals); if (!value.is_valid_time()) return (null_value= true); for (uint i= 1; i < arg_count ; i++) { - Time tmp(args[i]); + Time tmp(thd, args[i], Time::Options(thd), decimals); if (!tmp.is_valid_time()) return (null_value= true); @@ -2890,6 +2730,28 @@ my_decimal *Item_func_min_max::val_decimal_native(my_decimal *dec) } +bool Item_func_min_max::val_native(THD *thd, Native *native) +{ + DBUG_ASSERT(fixed == 1); + const Type_handler *handler= Item_hybrid_func::type_handler(); + NativeBuffer<STRING_BUFFER_USUAL_SIZE> cur; + for (uint i= 0; i < arg_count; i++) + { + if (val_native_with_conversion_from_item(thd, args[i], + i == 0 ? native : &cur, + handler)) + return true; + if (i > 0) + { + int cmp= handler->cmp_native(*native, cur); + if ((cmp_sign < 0 ? cmp : -cmp) < 0 && native->copy(cur)) + return null_value= true; + } + } + return null_value= false; +} + + longlong Item_func_bit_length::val_int() { DBUG_ASSERT(fixed == 1); @@ -3021,14 +2883,14 @@ longlong Item_func_field::val_int() } else if (cmp_type == DECIMAL_RESULT) { - my_decimal dec_arg_buf, *dec_arg, - dec_buf, *dec= args[0]->val_decimal(&dec_buf); - if (args[0]->null_value) + VDec dec(args[0]); + if (dec.is_null()) return 0; + my_decimal dec_arg_buf; for (uint i=1; i < arg_count; i++) { - dec_arg= args[i]->val_decimal(&dec_arg_buf); - if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec)) + my_decimal *dec_arg= args[i]->val_decimal(&dec_arg_buf); + if (!args[i]->null_value && !dec.cmp(dec_arg)) return (longlong) (i); } } @@ -3281,6 +3143,7 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func, } uint i; Item **arg,**arg_end; + With_sum_func_cache *with_sum_func_cache= func->get_with_sum_func_cache(); for (i=0, arg=arguments, arg_end=arguments+arg_count; arg != arg_end ; arg++,i++) @@ -3304,7 +3167,8 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func, func->collation.set(&my_charset_bin); if (item->maybe_null) func->maybe_null=1; - func->with_sum_func= func->with_sum_func || item->with_sum_func; + if (with_sum_func_cache) + with_sum_func_cache->join_with_sum_func(item); func->with_field= func->with_field || item->with_field; func->with_param= func->with_param || item->with_param; func->With_subquery_cache::join(item); @@ -3608,32 +3472,6 @@ String *Item_func_udf_int::val_str(String *str) } -longlong Item_func_udf_decimal::val_int() -{ - my_bool tmp_null_value; - longlong result; - my_decimal dec_buf, *dec= udf.val_decimal(&tmp_null_value, &dec_buf); - null_value= tmp_null_value; - if (null_value) - return 0; - my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result); - return result; -} - - -double Item_func_udf_decimal::val_real() -{ - my_bool tmp_null_value; - double result; - my_decimal dec_buf, *dec= udf.val_decimal(&tmp_null_value, &dec_buf); - null_value= tmp_null_value; - if (null_value) - return 0.0; - my_decimal2double(E_DEC_FATAL_ERROR, dec, &result); - return result; -} - - my_decimal *Item_func_udf_decimal::val_decimal(my_decimal *dec_buf) { my_decimal *res; @@ -3649,21 +3487,6 @@ my_decimal *Item_func_udf_decimal::val_decimal(my_decimal *dec_buf) } -String *Item_func_udf_decimal::val_str(String *str) -{ - my_bool tmp_null_value; - my_decimal dec_buf, *dec= udf.val_decimal(&tmp_null_value, &dec_buf); - null_value= tmp_null_value; - if (null_value) - return 0; - if (str->length() < DECIMAL_MAX_STR_LENGTH) - str->length(DECIMAL_MAX_STR_LENGTH); - my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, FALSE, &dec_buf); - my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, 0, 0, '0', str); - return str; -} - - /* Default max_length is max argument length */ bool Item_func_udf_str::fix_length_and_dec() @@ -3730,7 +3553,7 @@ longlong Item_master_pos_wait::val_int() connection_name.length= con->length(); if (check_master_connection_name(&connection_name)) { - my_error(ER_WRONG_ARGUMENTS, MYF(ME_JUST_WARNING), + my_error(ER_WRONG_ARGUMENTS, MYF(ME_WARNING), "MASTER_CONNECTION_NAME"); goto err; } @@ -4441,7 +4264,7 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name, if (!my_hash_inited(hash)) return 0; if (!(entry = (user_var_entry*) my_malloc(size, - MYF(MY_WME | ME_FATALERROR | + MYF(MY_WME | ME_FATAL | MY_THREAD_SPECIFIC)))) return 0; entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+ @@ -4696,7 +4519,7 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length, entry->value=0; entry->value= (char*) my_realloc(entry->value, length, MYF(MY_ALLOW_ZERO_PTR | MY_WME | - ME_FATALERROR | + ME_FATAL | MY_THREAD_SPECIFIC)); if (!entry->value) return 1; @@ -4761,11 +4584,7 @@ double user_var_entry::val_real(bool *null_value) case INT_RESULT: return (double) *(longlong*) value; case DECIMAL_RESULT: - { - double result; - my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result); - return result; - } + return ((my_decimal *)value)->to_double(); case STRING_RESULT: return my_atof(value); // This is null terminated case ROW_RESULT: @@ -4790,11 +4609,7 @@ longlong user_var_entry::val_int(bool *null_value) const case INT_RESULT: return *(longlong*) value; case DECIMAL_RESULT: - { - longlong result; - my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result); - return result; - } + return ((my_decimal *)value)->to_longlong(false); case STRING_RESULT: { int error; @@ -5531,10 +5346,9 @@ bool Item_func_get_user_var::set_value(THD *thd, bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) { - DBUG_ASSERT(fixed == 0); + DBUG_ASSERT(!is_fixed()); DBUG_ASSERT(thd->lex->exchange); - if (Item::fix_fields(thd, ref) || - !(entry= get_variable(&thd->user_vars, &org_name, 1))) + if (!(entry= get_variable(&thd->user_vars, &org_name, 1))) return TRUE; entry->type= STRING_RESULT; /* @@ -5592,7 +5406,8 @@ my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer) } -bool Item_user_var_as_out_param::get_date(MYSQL_TIME *ltime, ulonglong fuzzy) +bool Item_user_var_as_out_param::get_date(THD *thd, MYSQL_TIME *ltime, + date_mode_t fuzzydate) { DBUG_ASSERT(0); return true; @@ -5631,7 +5446,7 @@ void Item_func_get_system_var::update_null_value() THD *thd= current_thd; int save_no_errors= thd->no_errors; thd->no_errors= TRUE; - Item::update_null_value(); + type_handler()->Item_update_null_value(this); thd->no_errors= save_no_errors; } @@ -6471,7 +6286,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref) (thd->lex->sql_command == SQLCOM_CREATE_VIEW)) { Security_context *save_security_ctx= thd->security_ctx; - if (context->security_ctx) + if (context && context->security_ctx) thd->security_ctx= context->security_ctx; /* @@ -6486,7 +6301,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref) if (res) { - context->process_error(thd); + process_error(thd); DBUG_RETURN(res); } } @@ -6503,7 +6318,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref) if (!(m_sp= sp)) { my_missing_function_error(m_name->m_name, ErrConvDQName(m_name).ptr()); - context->process_error(thd); + process_error(thd); DBUG_RETURN(TRUE); } @@ -6660,6 +6475,14 @@ String *Item_func_last_value::val_str(String *str) return tmp; } + +bool Item_func_last_value::val_native(THD *thd, Native *to) +{ + evaluate_sideeffects(); + return val_native_from_item(thd, last_value, to); +} + + longlong Item_func_last_value::val_int() { longlong tmp; @@ -6688,10 +6511,10 @@ my_decimal *Item_func_last_value::val_decimal(my_decimal *decimal_value) } -bool Item_func_last_value::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_func_last_value::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { evaluate_sideeffects(); - bool tmp= last_value->get_date(ltime, fuzzydate); + bool tmp= last_value->get_date(thd, ltime, fuzzydate); null_value= last_value->null_value; return tmp; } diff --git a/sql/item_func.h b/sql/item_func.h index fd789ffdc51..1081f2919c8 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -35,12 +35,11 @@ extern "C" /* Bug in BSDI include file */ #include <cmath> -class Item_func :public Item_func_or_sum +class Item_func :public Item_func_or_sum, + protected With_sum_func_cache { void sync_with_sum_func_and_with_field(List<Item> &list); protected: - String *val_str_from_val_str_ascii(String *str, String *str2); - virtual bool check_arguments() const { return check_argument_types_scalar(0, arg_count); @@ -56,6 +55,7 @@ protected: bool check_argument_types_can_return_text(uint start, uint end) const; bool check_argument_types_can_return_date(uint start, uint end) const; bool check_argument_types_can_return_time(uint start, uint end) const; + void print_cast_temporal(String *str, enum_query_type query_type); public: table_map not_null_tables_cache; @@ -80,49 +80,56 @@ public: CASE_SEARCHED_FUNC, // Used by ColumnStore/Spider CASE_SIMPLE_FUNC // Used by ColumnStore/spider }; + static scalar_comparison_op functype_to_scalar_comparison_op(Functype type) + { + switch (type) { + case EQ_FUNC: return SCALAR_CMP_EQ; + case EQUAL_FUNC: return SCALAR_CMP_EQUAL; + case LT_FUNC: return SCALAR_CMP_LT; + case LE_FUNC: return SCALAR_CMP_LE; + case GE_FUNC: return SCALAR_CMP_GE; + case GT_FUNC: return SCALAR_CMP_GT; + default: break; + } + DBUG_ASSERT(0); + return SCALAR_CMP_EQ; + } enum Type type() const { return FUNC_ITEM; } virtual enum Functype functype() const { return UNKNOWN_FUNC; } Item_func(THD *thd): Item_func_or_sum(thd) { - with_sum_func= 0; with_field= 0; with_param= 0; } - Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a) + Item_func(THD *thd, Item *a) + :Item_func_or_sum(thd, a), With_sum_func_cache(a) { - with_sum_func= a->with_sum_func; with_param= a->with_param; with_field= a->with_field; } - Item_func(THD *thd, Item *a, Item *b): - Item_func_or_sum(thd, a, b) + Item_func(THD *thd, Item *a, Item *b) + :Item_func_or_sum(thd, a, b), With_sum_func_cache(a, b) { - with_sum_func= a->with_sum_func || b->with_sum_func; with_param= a->with_param || b->with_param; with_field= a->with_field || b->with_field; } - Item_func(THD *thd, Item *a, Item *b, Item *c): - Item_func_or_sum(thd, a, b, c) + Item_func(THD *thd, Item *a, Item *b, Item *c) + :Item_func_or_sum(thd, a, b, c), With_sum_func_cache(a, b, c) { - with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func; with_field= a->with_field || b->with_field || c->with_field; with_param= a->with_param || b->with_param || c->with_param; } - Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d): - Item_func_or_sum(thd, a, b, c, d) + Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d) + :Item_func_or_sum(thd, a, b, c, d), With_sum_func_cache(a, b, c, d) { - with_sum_func= a->with_sum_func || b->with_sum_func || - c->with_sum_func || d->with_sum_func; with_field= a->with_field || b->with_field || c->with_field || d->with_field; with_param= a->with_param || b->with_param || c->with_param || d->with_param; } - Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e): - Item_func_or_sum(thd, a, b, c, d, e) + Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e) + :Item_func_or_sum(thd, a, b, c, d, e), With_sum_func_cache(a, b, c, d, e) { - with_sum_func= a->with_sum_func || b->with_sum_func || - c->with_sum_func || d->with_sum_func || e->with_sum_func; with_field= a->with_field || b->with_field || c->with_field || d->with_field || e->with_field; with_param= a->with_param || b->with_param || @@ -134,11 +141,10 @@ public: set_arguments(thd, list); } // Constructor used for Item_cond_and/or (see Item comment) - Item_func(THD *thd, Item_func *item): - Item_func_or_sum(thd, item), + Item_func(THD *thd, Item_func *item) + :Item_func_or_sum(thd, item), With_sum_func_cache(item), not_null_tables_cache(item->not_null_tables_cache) - { - } + { } bool fix_fields(THD *, Item **ref); void cleanup() { @@ -174,16 +180,12 @@ public: virtual void print(String *str, enum_query_type query_type); void print_op(String *str, enum_query_type query_type); void print_args(String *str, uint from, enum_query_type query_type); - inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) - { - DBUG_ASSERT(!(fuzzy_date & TIME_TIME_ONLY)); - Datetime dt(current_thd, args[0], fuzzy_date); - return (null_value= dt.copy_to_mysql_time(ltime)); - } bool is_null() { update_null_value(); return null_value; } + String *val_str_from_val_str_ascii(String *str, String *str2); + void signal_divide_by_null(); friend class udf_handler; Field *create_field_for_create_select(TABLE *table) @@ -338,6 +340,11 @@ public: return Item_args::excl_dep_on_grouping_fields(sel); } + bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) + { + return Item_args::excl_dep_on_in_subq_left_part(subq_pred); + } + /* We assume the result of any function that has a TIMESTAMP argument to be timezone-dependent, since a TIMESTAMP value in both numeric and string @@ -380,6 +387,10 @@ public: - or replaced to an Item_int_with_ref */ bool setup_args_and_comparator(THD *thd, Arg_comparator *cmp); + + bool with_sum_func() const { return m_with_sum_func; } + With_sum_func_cache* get_with_sum_func_cache() { return this; } + Item_func *get_item_func() { return this; } }; @@ -400,8 +411,8 @@ public: DBUG_ASSERT(fixed == 1); return Converter_double_to_longlong(val_real(), unsigned_flag).result(); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_real(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_real(thd, ltime, fuzzydate); } const Type_handler *type_handler() const { return &type_handler_double; } bool fix_length_and_dec() { @@ -441,6 +452,193 @@ public: }; +class Item_handled_func: public Item_func +{ +public: + class Handler + { + public: + virtual ~Handler() { } + virtual String *val_str(Item_handled_func *, String *) const= 0; + virtual String *val_str_ascii(Item_handled_func *, String *) const= 0; + virtual double val_real(Item_handled_func *) const= 0; + virtual longlong val_int(Item_handled_func *) const= 0; + virtual my_decimal *val_decimal(Item_handled_func *, my_decimal *) const= 0; + virtual bool get_date(THD *thd, Item_handled_func *, MYSQL_TIME *, date_mode_t fuzzydate) const= 0; + virtual const Type_handler *return_type_handler() const= 0; + virtual bool fix_length_and_dec(Item_handled_func *) const= 0; + }; + + /** + Abstract class for functions returning TIME, DATE, DATETIME or string values, + whose data type depends on parameters and is set at fix_fields time. + */ + class Handler_temporal: public Handler + { + public: + String *val_str(Item_handled_func *item, String *to) const + { + StringBuffer<MAX_FIELD_WIDTH> ascii_buf; + return item->val_str_from_val_str_ascii(to, &ascii_buf); + } + }; + + /** + Abstract class for functions returning strings, + which are generated from get_date() results, + when get_date() can return different MYSQL_TIMESTAMP_XXX per row. + */ + class Handler_temporal_string: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_string; + } + double val_real(Item_handled_func *item) const + { + return Temporal_hybrid(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Temporal_hybrid(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Temporal_hybrid(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Temporal_hybrid(item).to_string(to, item->decimals); + } + }; + + + class Handler_date: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_newdate; + } + bool fix_length_and_dec(Item_handled_func *item) const + { + item->fix_attributes_date(); + return false; + } + double val_real(Item_handled_func *item) const + { + return Date(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Date(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Date(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Date(item).to_string(to); + } + }; + + + class Handler_time: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_time2; + } + double val_real(Item_handled_func *item) const + { + return Time(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Time(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Time(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Time(item).to_string(to, item->decimals); + } + }; + + + class Handler_datetime: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_datetime2; + } + double val_real(Item_handled_func *item) const + { + return Datetime(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Datetime(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Datetime(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Datetime(item).to_string(to, item->decimals); + } + }; + + +protected: + const Handler *m_func_handler; +public: + Item_handled_func(THD *thd, Item *a) + :Item_func(thd, a), m_func_handler(NULL) { } + Item_handled_func(THD *thd, Item *a, Item *b) + :Item_func(thd, a, b), m_func_handler(NULL) { } + void set_func_handler(const Handler *handler) + { + m_func_handler= handler; + } + const Type_handler *type_handler() const + { + return m_func_handler->return_type_handler(); + } + String *val_str(String *to) + { + return m_func_handler->val_str(this, to); + } + String *val_str_ascii(String *to) + { + return m_func_handler->val_str_ascii(this, to); + } + double val_real() + { + return m_func_handler->val_real(this); + } + longlong val_int() + { + return m_func_handler->val_int(this); + } + my_decimal *val_decimal(my_decimal *to) + { + return m_func_handler->val_decimal(this, to); + } + bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) + { + return m_func_handler->get_date(thd, this, to, fuzzydate); + } +}; + + /** Functions that at fix_fields() time determine the returned field type, trying to preserve the exact data type of the arguments. @@ -463,15 +661,15 @@ class Item_func_hybrid_field_type: public Item_hybrid_func Helper methods to make sure that the result of decimal_op(), str_op() and date_op() is properly synched with null_value. */ - bool date_op_with_null_check(MYSQL_TIME *ltime) + bool date_op_with_null_check(THD *thd, MYSQL_TIME *ltime) { - bool rc= date_op(ltime, 0); + bool rc= date_op(thd, ltime, date_mode_t(0)); DBUG_ASSERT(!rc ^ null_value); return rc; } - bool time_op_with_null_check(MYSQL_TIME *ltime) + bool time_op_with_null_check(THD *thd, MYSQL_TIME *ltime) { - bool rc= time_op(ltime); + bool rc= time_op(thd, ltime); DBUG_ASSERT(!rc ^ null_value); DBUG_ASSERT(rc || ltime->time_type == MYSQL_TIMESTAMP_TIME); return rc; @@ -482,17 +680,6 @@ class Item_func_hybrid_field_type: public Item_hybrid_func DBUG_ASSERT((res != NULL) ^ null_value); return res; } - my_decimal *decimal_op_with_null_check(my_decimal *decimal_buffer) - { - my_decimal *res= decimal_op(decimal_buffer); - DBUG_ASSERT((res != NULL) ^ null_value); - return res; - } - bool make_zero_mysql_time(MYSQL_TIME *ltime, ulonglong fuzzydate) - { - bzero(ltime, sizeof(*ltime)); - return null_value|= !(fuzzydate & TIME_FUZZY_DATES); - } public: // Value methods that involve no conversion @@ -500,10 +687,6 @@ public: { return str_op_with_null_check(&str_value); } - my_decimal *val_decimal_from_decimal_op(my_decimal *dec) - { - return decimal_op_with_null_check(dec); - } longlong val_int_from_int_op() { return int_op(); @@ -514,7 +697,6 @@ public: } // Value methods that involve conversion - String *val_str_from_decimal_op(String *str); String *val_str_from_real_op(String *str); String *val_str_from_int_op(String *str); String *val_str_from_date_op(String *str); @@ -528,21 +710,14 @@ public: longlong val_int_from_str_op(); longlong val_int_from_real_op(); - longlong val_int_from_decimal_op(); longlong val_int_from_date_op(); longlong val_int_from_time_op(); double val_real_from_str_op(); - double val_real_from_decimal_op(); double val_real_from_date_op(); double val_real_from_time_op(); double val_real_from_int_op(); - bool get_date_from_str_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_from_real_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_from_decimal_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_from_int_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - public: Item_func_hybrid_field_type(THD *thd): Item_hybrid_func(thd) @@ -586,11 +761,17 @@ public: DBUG_ASSERT(null_value == (res == NULL)); return res; } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) + bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) { DBUG_ASSERT(fixed); return Item_func_hybrid_field_type::type_handler()-> - Item_func_hybrid_field_type_get_date(this, res, fuzzy_date); + Item_func_hybrid_field_type_get_date_with_warn(thd, this, to, mode); + } + + bool val_native(THD *thd, Native *to) + { + DBUG_ASSERT(fixed); + return native_op(thd, to); } /** @@ -600,6 +781,20 @@ public: @return The result of the operation. */ virtual longlong int_op()= 0; + Longlong_null to_longlong_null_op() + { + longlong nr= int_op(); + /* + C++ does not guarantee the order of parameter evaluation, + so to make sure "null_value" is passed to the constructor + after the int_op() call, int_op() is caled on a separate line. + */ + return Longlong_null(nr, null_value); + } + Longlong_hybrid_null to_longlong_hybrid_null_op() + { + return Longlong_hybrid_null(to_longlong_null_op(), unsigned_flag); + } /** @brief Performs the operation that this functions implements when the @@ -608,6 +803,12 @@ public: @return The result of the operation. */ virtual double real_op()= 0; + Double_null to_double_null_op() + { + // val_real() must be caleed on a separate line. See to_longlong_null() + double nr= real_op(); + return Double_null(nr, null_value); + } /** @brief Performs the operation that this functions implements when the @@ -634,15 +835,16 @@ public: field type is DATETIME or DATE. @return The result of the operation. */ - virtual bool date_op(MYSQL_TIME *res, ulonglong fuzzy_date)= 0; + virtual bool date_op(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate)= 0; /** @brief Performs the operation that this functions implements when field type is TIME. @return The result of the operation. */ - virtual bool time_op(MYSQL_TIME *res)= 0; + virtual bool time_op(THD *thd, MYSQL_TIME *res)= 0; + virtual bool native_op(THD *thd, Native *native)= 0; }; @@ -700,12 +902,17 @@ public: Item_func_hybrid_field_type(thd, list) { } String *str_op(String *str) { DBUG_ASSERT(0); return 0; } - bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(0); return true; } - bool time_op(MYSQL_TIME *ltime) + bool time_op(THD *thd, MYSQL_TIME *ltime) + { + DBUG_ASSERT(0); + return true; + } + bool native_op(THD *thd, Native *to) { DBUG_ASSERT(0); return true; @@ -791,8 +998,8 @@ public: { collation.set_numeric(); } double val_real(); String *val_str(String*str); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_int(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_int(thd, ltime, fuzzydate); } const Type_handler *type_handler() const= 0; bool fix_length_and_dec() { return FALSE; } }; @@ -982,12 +1189,15 @@ public: fix_char_length(my_decimal_precision_to_length_no_truncation(len, dec, unsigned_flag)); } - String *val_str(String *str); - double val_real(); - longlong val_int(); + String *val_str(String *str) { return VDec(this).to_string(str); } + double val_real() { return VDec(this).to_double(); } + longlong val_int() { return VDec(this).to_longlong(unsigned_flag); } my_decimal *val_decimal(my_decimal*); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_decimal(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) + { + return decimal_to_datetime_with_warn(thd, VDec(this).ptr(), to, mode, + NULL, NULL); + } const Type_handler *type_handler() const { return &type_handler_newdecimal; } void fix_length_and_dec_generic() {} bool fix_length_and_dec() @@ -1541,8 +1751,8 @@ public: double val_real_native(); longlong val_int_native(); my_decimal *val_decimal_native(my_decimal *); - bool get_date_native(MYSQL_TIME *res, ulonglong fuzzydate); - bool get_time_native(MYSQL_TIME *res); + bool get_date_native(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); + bool get_time_native(THD *thd, MYSQL_TIME *res); double val_real() { @@ -1568,12 +1778,13 @@ public: return Item_func_min_max::type_handler()-> Item_func_min_max_val_decimal(this, dec); } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) { DBUG_ASSERT(fixed); return Item_func_min_max::type_handler()-> - Item_func_min_max_get_date(this, res, fuzzy_date); + Item_func_min_max_get_date(thd, this, res, fuzzydate); } + bool val_native(THD *thd, Native *to); void aggregate_attributes_real(Item **items, uint nitems) { /* @@ -1637,10 +1848,12 @@ public: double val_real() { return val_real_from_item(args[0]); } longlong val_int() { return val_int_from_item(args[0]); } String *val_str(String *str) { return val_str_from_item(args[0], str); } + bool val_native(THD *thd, Native *to) + { return val_native_from_item(thd, args[0], to); } my_decimal *val_decimal(my_decimal *dec) { return val_decimal_from_item(args[0], dec); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_item(args[0], ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_item(thd, args[0], ltime, fuzzydate); } const char *func_name() const { return "rollup_const"; } bool const_item() const { return 0; } const Type_handler *type_handler() const { return args[0]->type_handler(); } @@ -2007,6 +2220,18 @@ protected: udf_handler udf; bool is_expensive_processor(void *arg) { return TRUE; } + class VDec_udf: public Dec_ptr_and_buffer + { + public: + VDec_udf(Item_udf_func *func, udf_handler *udf) + { + my_bool tmp_null_value; + m_ptr= udf->val_decimal(&tmp_null_value, &m_buffer); + DBUG_ASSERT(is_null() == (tmp_null_value != 0)); + func->null_value= is_null(); + } + }; + public: Item_udf_func(THD *thd, udf_func *udf_arg): Item_func(thd), udf(udf_arg) {} @@ -2084,9 +2309,9 @@ public: { return mark_unsupported_function(func_name(), "()", arg, VCOL_NON_DETERMINISTIC); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } }; @@ -2147,10 +2372,19 @@ public: Item_udf_func(thd, udf_arg) {} Item_func_udf_decimal(THD *thd, udf_func *udf_arg, List<Item> &list): Item_udf_func(thd, udf_arg, list) {} - longlong val_int(); - double val_real(); + longlong val_int() + { + return VDec_udf(this, &udf).to_longlong(unsigned_flag); + } + double val_real() + { + return VDec_udf(this, &udf).to_double(); + } my_decimal *val_decimal(my_decimal *); - String *val_str(String *str); + String *val_str(String *str) + { + return VDec_udf(this, &udf).to_string_round(str, decimals); + } const Type_handler *type_handler() const { return &type_handler_newdecimal; } bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; } Item *get_copy(THD *thd) @@ -2381,13 +2615,15 @@ public: Item_func_user_var(THD *thd, Item_func_user_var *item) :Item_hybrid_func(thd, item), m_var_entry(item->m_var_entry), name(item->name) { } - Field *create_tmp_field(bool group, TABLE *table) - { return create_table_field_from_handler(table); } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param); Field *create_field_for_create_select(TABLE *table) { return create_table_field_from_handler(table); } bool check_vcol_func_processor(void *arg); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return type_handler()->Item_get_date(this, ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); + } }; @@ -2515,14 +2751,14 @@ public: in List<Item> and desire to place this code somewhere near other functions working with user variables. */ -class Item_user_var_as_out_param :public Item, +class Item_user_var_as_out_param :public Item_fixed_hybrid, public Load_data_outvar { LEX_CSTRING org_name; user_var_entry *entry; public: Item_user_var_as_out_param(THD *thd, const LEX_CSTRING *a) - :Item(thd) + :Item_fixed_hybrid(thd) { DBUG_ASSERT(a->length < UINT_MAX32); org_name= *a; @@ -2557,12 +2793,18 @@ public: { return 0; } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + DBUG_ASSERT(0); + return NULL; + } /* We should return something different from FIELD_ITEM here */ - enum Type type() const { return STRING_ITEM;} + enum Type type() const { return CONST_ITEM;} double val_real(); longlong val_int(); String *val_str(String *str); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); my_decimal *val_decimal(my_decimal *decimal_buffer); /* fix_fields() binds variable name with its entry structure */ bool fix_fields(THD *thd, Item **ref); @@ -2609,9 +2851,9 @@ public: String* val_str(String*); my_decimal *val_decimal(my_decimal *dec_buf) { return val_decimal_from_real(dec_buf); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } /* TODO: fix to support views */ const char *func_name() const { return "get_system_var"; } @@ -2870,6 +3112,8 @@ public: const Type_handler *type_handler() const; + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param); Field *create_field_for_create_select(TABLE *table) { return result_type() != STRING_RESULT ? @@ -2899,7 +3143,7 @@ public: return sp_result_field->val_decimal(dec_buf); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { if (execute()) return true; @@ -2925,6 +3169,13 @@ public: return str; } + bool val_native(THD *thd, Native *to) + { + if (execute()) + return true; + return null_value= sp_result_field->val_native(to); + } + void update_null_value() { execute(); @@ -3053,7 +3304,8 @@ public: longlong val_int(); String *val_str(String *); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool val_native(THD *thd, Native *); bool fix_length_and_dec(); const char *func_name() const { return "last_value"; } const Type_handler *type_handler() const { return last_value->type_handler(); } diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 4c2a2fa8b11..1f1b5a6ceed 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -916,7 +916,7 @@ String *Item_func_point::val_str(String *str) if ((null_value= (args[0]->null_value || args[1]->null_value || - str->realloc(4/*SRID*/ + 1 + 4 + SIZEOF_STORED_DOUBLE * 2)))) + str->alloc(4/*SRID*/ + 1 + 4 + SIZEOF_STORED_DOUBLE * 2)))) return 0; str->set_charset(&my_charset_bin); diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 0e727829ce7..e6c198fb8b2 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -512,7 +512,7 @@ public: return TRUE; for (unsigned int i= 0; i < arg_count; ++i) { - if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY) + if (args[i]->is_fixed() && args[i]->field_type() != MYSQL_TYPE_GEOMETRY) { String str; args[i]->print(&str, QT_NO_DATA_EXPANSION); diff --git a/sql/item_inetfunc.cc b/sql/item_inetfunc.cc index 8a3345ecc81..f5fcbf65309 100644 --- a/sql/item_inetfunc.cc +++ b/sql/item_inetfunc.cc @@ -21,9 +21,9 @@ /////////////////////////////////////////////////////////////////////////// -static const int IN_ADDR_SIZE= sizeof (in_addr); -static const int IN6_ADDR_SIZE= sizeof (in6_addr); -static const int IN6_ADDR_NUM_WORDS= IN6_ADDR_SIZE / 2; +static const size_t IN_ADDR_SIZE= 4; +static const size_t IN6_ADDR_SIZE= 16; +static const size_t IN6_ADDR_NUM_WORDS= IN6_ADDR_SIZE / 2; static const char HEX_DIGITS[]= "0123456789abcdef"; @@ -89,7 +89,6 @@ err: return 0; } -/////////////////////////////////////////////////////////////////////////// String* Item_func_inet_ntoa::val_str(String* str) { @@ -139,91 +138,220 @@ String* Item_func_inet_ntoa::val_str(String* str) /////////////////////////////////////////////////////////////////////////// -/** - Check the function argument, handle errors properly. - @return The function value. -*/ - -longlong Item_func_inet_bool_base::val_int() +class Inet4 { - DBUG_ASSERT(fixed); - - // String argument expected - if (unlikely(args[0]->result_type() != STRING_RESULT)) - return 0; - - String buffer; - String *arg_str= args[0]->val_str(&buffer); + char m_buffer[IN_ADDR_SIZE]; +protected: + bool str_to_ipv4(const char *str, size_t length, CHARSET_INFO *cs); + bool binary_to_ipv4(const char *str, size_t length) + { + if (length != sizeof(m_buffer)) + return true; + memcpy(m_buffer, str, length); + return false; + } + // Non-initializing constructor + Inet4() { } +public: + void to_binary(char *dst, size_t dstsize) const + { + DBUG_ASSERT(dstsize >= sizeof(m_buffer)); + memcpy(dst, m_buffer, sizeof(m_buffer)); + } + bool to_binary(String *to) const + { + return to->copy(m_buffer, sizeof(m_buffer), &my_charset_bin); + } + size_t to_string(char *dst, size_t dstsize) const; + bool to_string(String *to) const + { + to->set_charset(&my_charset_latin1); + if (to->alloc(INET_ADDRSTRLEN)) + return true; + to->length((uint32) to_string((char*) to->ptr(), INET_ADDRSTRLEN)); + return false; + } +}; - if (unlikely(!arg_str)) // Out-of memory happened. error has been reported. - return 0; // Or: the underlying field is NULL - return calc_value(arg_str) ? 1 : 0; -} - -/////////////////////////////////////////////////////////////////////////// +class Inet4_null: public Inet4, public Null_flag +{ +public: + // Initialize from a text representation + Inet4_null(const char *str, size_t length, CHARSET_INFO *cs) + :Null_flag(str_to_ipv4(str, length, cs)) + { } + Inet4_null(const String &str) + :Inet4_null(str.ptr(), str.length(), str.charset()) + { } + // Initialize from a binary representation + Inet4_null(const char *str, size_t length) + :Null_flag(binary_to_ipv4(str, length)) + { } + Inet4_null(const Binary_string &str) + :Inet4_null(str.ptr(), str.length()) + { } +public: + const Inet4& to_inet4() const + { + DBUG_ASSERT(!is_null()); + return *this; + } + void to_binary(char *dst, size_t dstsize) const + { + to_inet4().to_binary(dst, dstsize); + } + bool to_binary(String *to) const + { + return to_inet4().to_binary(to); + } + size_t to_string(char *dst, size_t dstsize) const + { + return to_inet4().to_string(dst, dstsize); + } + bool to_string(String *to) const + { + return to_inet4().to_string(to); + } +}; -/** - Check the function argument, handle errors properly. - @param [out] buffer Buffer for string operations. +class Inet6 +{ + char m_buffer[IN6_ADDR_SIZE]; +protected: + bool make_from_item(Item *item); + bool str_to_ipv6(const char *str, size_t str_length, CHARSET_INFO *cs); + bool binary_to_ipv6(const char *str, size_t length) + { + if (length != sizeof(m_buffer)) + return true; + memcpy(m_buffer, str, length); + return false; + } + // Non-initializing constructor + Inet6() { } +public: + bool to_binary(String *to) const + { + return to->copy(m_buffer, sizeof(m_buffer), &my_charset_bin); + } + size_t to_string(char *dst, size_t dstsize) const; + bool to_string(String *to) const + { + to->set_charset(&my_charset_latin1); + if (to->alloc(INET6_ADDRSTRLEN)) + return true; + to->length((uint32) to_string((char*) to->ptr(), INET6_ADDRSTRLEN)); + return false; + } + bool is_v4compat() const + { + static_assert(sizeof(in6_addr) == IN6_ADDR_SIZE, "unexpected in6_addr size"); + return IN6_IS_ADDR_V4COMPAT((struct in6_addr *) m_buffer); + } + bool is_v4mapped() const + { + static_assert(sizeof(in6_addr) == IN6_ADDR_SIZE, "unexpected in6_addr size"); + return IN6_IS_ADDR_V4MAPPED((struct in6_addr *) m_buffer); + } +}; - @return The function value. -*/ -String *Item_func_inet_str_base::val_str_ascii(String *buffer) +class Inet6_null: public Inet6, public Null_flag { - DBUG_ASSERT(fixed); - - // String argument expected - if (unlikely(args[0]->result_type() != STRING_RESULT)) +public: + // Initialize from a text representation + Inet6_null(const char *str, size_t length, CHARSET_INFO *cs) + :Null_flag(str_to_ipv6(str, length, cs)) + { } + Inet6_null(const String &str) + :Inet6_null(str.ptr(), str.length(), str.charset()) + { } + // Initialize from a binary representation + Inet6_null(const char *str, size_t length) + :Null_flag(binary_to_ipv6(str, length)) + { } + Inet6_null(const Binary_string &str) + :Inet6_null(str.ptr(), str.length()) + { } + // Initialize from an Item + Inet6_null(Item *item) + :Null_flag(make_from_item(item)) + { } +public: + const Inet6& to_inet6() const { - null_value= true; - return NULL; + DBUG_ASSERT(!is_null()); + return *this; } - - StringBuffer<STRING_BUFFER_USUAL_SIZE> tmp; - String *arg_str= args[0]->val_str(&tmp); - if (unlikely(!arg_str)) + bool to_binary(String *to) const { - // Out-of memory happened. error has been reported. - // Or: the underlying field is NULL - null_value= true; - return NULL; + DBUG_ASSERT(!is_null()); + return to_inet6().to_binary(to); } + size_t to_string(char *dst, size_t dstsize) const + { + return to_inet6().to_string(dst, dstsize); + } + bool to_string(String *to) const + { + return to_inet6().to_string(to); + } + bool is_v4compat() const + { + return to_inet6().is_v4compat(); + } + bool is_v4mapped() const + { + return to_inet6().is_v4mapped(); + } +}; - null_value= !calc_value(arg_str, buffer); - return unlikely(null_value) ? NULL : buffer; -} +bool Inet6::make_from_item(Item *item) +{ + String tmp(m_buffer, sizeof(m_buffer), &my_charset_bin); + String *str= item->val_str(&tmp); + /* + Charset could be tested in item->collation.collation before the val_str() + call, but traditionally Inet6 functions still call item->val_str() + for non-binary arguments and therefore execute side effects. + */ + if (!str || str->length() != sizeof(m_buffer) || + str->charset() != &my_charset_bin) + return true; + if (str->ptr() != m_buffer) + memcpy(m_buffer, str->ptr(), sizeof(m_buffer)); + return false; +}; -/////////////////////////////////////////////////////////////////////////// /** Tries to convert given string to binary IPv4-address representation. This is a portable alternative to inet_pton(AF_INET). @param str String to convert. - @param str_len String length. - @param[out] ipv4_address Buffer to store IPv4-address. + @param str_length String length. @return Completion status. - @retval false Given string does not represent an IPv4-address. - @retval true The string has been converted sucessfully. + @retval true - error, the given string does not represent an IPv4-address. + @retval false - ok, the string has been converted sucessfully. @note The problem with inet_pton() is that it treats leading zeros in IPv4-part differently on different platforms. */ -static bool str_to_ipv4(const char *str, size_t str_length, in_addr *ipv4_address) +bool Inet4::str_to_ipv4(const char *str, size_t str_length, CHARSET_INFO *cs) { + DBUG_ASSERT(cs->mbminlen == 1); if (str_length < 7) { DBUG_PRINT("error", ("str_to_ipv4(%.*s): " "invalid IPv4 address: too short.", (int) str_length, str)); - return false; + return true; } if (str_length > 15) @@ -231,17 +359,18 @@ static bool str_to_ipv4(const char *str, size_t str_length, in_addr *ipv4_addres DBUG_PRINT("error", ("str_to_ipv4(%.*s): " "invalid IPv4 address: too long.", (int) str_length, str)); - return false; + return true; } - unsigned char *ipv4_bytes= (unsigned char *) ipv4_address; + unsigned char *ipv4_bytes= (unsigned char *) &m_buffer; + const char *str_end= str + str_length; const char *p= str; int byte_value= 0; int chars_in_group= 0; int dot_count= 0; char c= 0; - while (((p - str) < (int)str_length) && *p) + while (p < str_end && *p) { c= *p++; @@ -254,7 +383,7 @@ static bool str_to_ipv4(const char *str, size_t str_length, in_addr *ipv4_addres DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: " "too many characters in a group.", (int) str_length, str)); - return false; + return true; } byte_value= byte_value * 10 + (c - '0'); @@ -264,7 +393,7 @@ static bool str_to_ipv4(const char *str, size_t str_length, in_addr *ipv4_addres DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: " "invalid byte value.", (int) str_length, str)); - return false; + return true; } } else if (c == '.') @@ -274,7 +403,7 @@ static bool str_to_ipv4(const char *str, size_t str_length, in_addr *ipv4_addres DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: " "too few characters in a group.", (int) str_length, str)); - return false; + return true; } ipv4_bytes[dot_count]= (unsigned char) byte_value; @@ -287,7 +416,7 @@ static bool str_to_ipv4(const char *str, size_t str_length, in_addr *ipv4_addres { DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: " "too many dots.", (int) str_length, str)); - return false; + return true; } } else @@ -295,7 +424,7 @@ static bool str_to_ipv4(const char *str, size_t str_length, in_addr *ipv4_addres DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: " "invalid character at pos %d.", (int) str_length, str, (int) (p - str))); - return false; + return true; } } @@ -303,7 +432,7 @@ static bool str_to_ipv4(const char *str, size_t str_length, in_addr *ipv4_addres { DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: " "ending at '.'.", (int) str_length, str)); - return false; + return true; } if (dot_count != 3) @@ -311,7 +440,7 @@ static bool str_to_ipv4(const char *str, size_t str_length, in_addr *ipv4_addres DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: " "too few groups.", (int) str_length, str)); - return false; + return true; } ipv4_bytes[3]= (unsigned char) byte_value; @@ -320,44 +449,44 @@ static bool str_to_ipv4(const char *str, size_t str_length, in_addr *ipv4_addres (int) str_length, str, ipv4_bytes[0], ipv4_bytes[1], ipv4_bytes[2], ipv4_bytes[3])); - return true; + return false; } -/////////////////////////////////////////////////////////////////////////// /** Tries to convert given string to binary IPv6-address representation. This is a portable alternative to inet_pton(AF_INET6). @param str String to convert. - @param str_len String length. - @param[out] ipv6_address Buffer to store IPv6-address. + @param str_length String length. @return Completion status. - @retval false Given string does not represent an IPv6-address. - @retval true The string has been converted sucessfully. + @retval true - error, the given string does not represent an IPv6-address. + @retval false - ok, the string has been converted sucessfully. @note The problem with inet_pton() is that it treats leading zeros in IPv4-part differently on different platforms. */ -static bool str_to_ipv6(const char *str, int str_length, in6_addr *ipv6_address) +bool Inet6::str_to_ipv6(const char *str, size_t str_length, CHARSET_INFO *cs) { + DBUG_ASSERT(cs->mbminlen == 1); + if (str_length < 2) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: too short.", - str_length, str)); - return false; + (int) str_length, str)); + return true; } if (str_length > 8 * 4 + 7) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: too long.", - str_length, str)); - return false; + (int) str_length, str)); + return true; } - memset(ipv6_address, 0, IN6_ADDR_SIZE); + memset(m_buffer, 0, sizeof(m_buffer)); const char *p= str; @@ -368,20 +497,20 @@ static bool str_to_ipv6(const char *str, int str_length, in6_addr *ipv6_address) if (*p != ':') { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " - "can not start with ':x'.", str_length, str)); - return false; + "can not start with ':x'.", (int) str_length, str)); + return true; } } - char *ipv6_bytes= (char *) ipv6_address; - char *ipv6_bytes_end= ipv6_bytes + IN6_ADDR_SIZE; - char *dst= ipv6_bytes; + const char *str_end= str + str_length; + char *ipv6_bytes_end= m_buffer + sizeof(m_buffer); + char *dst= m_buffer; char *gap_ptr= NULL; const char *group_start_ptr= p; int chars_in_group= 0; int group_value= 0; - while (((p - str) < str_length) && *p) + while (p < str_end && *p) { char c= *p++; @@ -394,26 +523,26 @@ static bool str_to_ipv6(const char *str, int str_length, in6_addr *ipv6_address) if (gap_ptr) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " - "too many gaps(::).", str_length, str)); - return false; + "too many gaps(::).", (int) str_length, str)); + return true; } gap_ptr= dst; continue; } - if (!*p || ((p - str) >= str_length)) + if (!*p || p >= str_end) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " - "ending at ':'.", str_length, str)); - return false; + "ending at ':'.", (int) str_length, str)); + return true; } if (dst + 2 > ipv6_bytes_end) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " - "too many groups (1).", str_length, str)); - return false; + "too many groups (1).", (int) str_length, str)); + return true; } dst[0]= (unsigned char) (group_value >> 8) & 0xff; @@ -428,19 +557,19 @@ static bool str_to_ipv6(const char *str, int str_length, in6_addr *ipv6_address) if (dst + IN_ADDR_SIZE > ipv6_bytes_end) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " - "unexpected IPv4-part.", str_length, str)); - return false; + "unexpected IPv4-part.", (int) str_length, str)); + return true; } - if (!str_to_ipv4(group_start_ptr, - str + str_length - group_start_ptr, - (in_addr *) dst)) + Inet4_null tmp(group_start_ptr, (size_t) (str_end - group_start_ptr), cs); + if (tmp.is_null()) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " - "invalid IPv4-part.", str_length, str)); - return false; + "invalid IPv4-part.", (int) str_length, str)); + return true; } + tmp.to_binary(dst, IN_ADDR_SIZE); dst += IN_ADDR_SIZE; chars_in_group= 0; @@ -454,16 +583,16 @@ static bool str_to_ipv6(const char *str, int str_length, in6_addr *ipv6_address) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " "invalid character at pos %d.", - str_length, str, (int) (p - str))); - return false; + (int) str_length, str, (int) (p - str))); + return true; } if (chars_in_group >= 4) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " "too many digits in group.", - str_length, str)); - return false; + (int) str_length, str)); + return true; } group_value <<= 4; @@ -480,8 +609,8 @@ static bool str_to_ipv6(const char *str, int str_length, in6_addr *ipv6_address) if (dst + 2 > ipv6_bytes_end) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " - "too many groups (2).", str_length, str)); - return false; + "too many groups (2).", (int) str_length, str)); + return true; } dst[0]= (unsigned char) (group_value >> 8) & 0xff; @@ -494,8 +623,8 @@ static bool str_to_ipv6(const char *str, int str_length, in6_addr *ipv6_address) if (dst == ipv6_bytes_end) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " - "no room for a gap (::).", str_length, str)); - return false; + "no room for a gap (::).", (int) str_length, str)); + return true; } int bytes_to_move= (int)(dst - gap_ptr); @@ -512,49 +641,48 @@ static bool str_to_ipv6(const char *str, int str_length, in6_addr *ipv6_address) if (dst < ipv6_bytes_end) { DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: " - "too few groups.", str_length, str)); - return false; + "too few groups.", (int) str_length, str)); + return true; } - return true; + return false; } -/////////////////////////////////////////////////////////////////////////// /** Converts IPv4-binary-address to a string. This function is a portable alternative to inet_ntop(AF_INET). @param[in] ipv4 IPv4-address data (byte array) - @param[out] str A buffer to store string representation of IPv4-address. - It must be at least of INET_ADDRSTRLEN. + @param[out] dst A buffer to store string representation of IPv4-address. + @param[in] dstsize Number of bytes avaiable in "dst" @note The problem with inet_ntop() is that it is available starting from Windows Vista, but the minimum supported version is Windows 2000. */ -static void ipv4_to_str(const in_addr *ipv4, char *str) +size_t Inet4::to_string(char *dst, size_t dstsize) const { - const unsigned char *ipv4_bytes= (const unsigned char *) ipv4; - - sprintf(str, "%d.%d.%d.%d", - ipv4_bytes[0], ipv4_bytes[1], ipv4_bytes[2], ipv4_bytes[3]); + return (size_t) my_snprintf(dst, dstsize, "%d.%d.%d.%d", + (uchar) m_buffer[0], (uchar) m_buffer[1], + (uchar) m_buffer[2], (uchar) m_buffer[3]); } -/////////////////////////////////////////////////////////////////////////// + /** Converts IPv6-binary-address to a string. This function is a portable alternative to inet_ntop(AF_INET6). @param[in] ipv6 IPv6-address data (byte array) - @param[out] str A buffer to store string representation of IPv6-address. + @param[out] dst A buffer to store string representation of IPv6-address. It must be at least of INET6_ADDRSTRLEN. + @param[in] dstsize Number of bytes available dst. @note The problem with inet_ntop() is that it is available starting from Windows Vista, but out the minimum supported version is Windows 2000. */ -static void ipv6_to_str(const in6_addr *ipv6, char *str) +size_t Inet6::to_string(char *dst, size_t dstsize) const { struct Region { @@ -562,6 +690,8 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str) int length; }; + const char *ipv6= m_buffer; + char *dstend= dst + dstsize; const unsigned char *ipv6_bytes= (const unsigned char *) ipv6; // 1. Translate IPv6-address bytes to words. @@ -570,7 +700,8 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str) uint16 ipv6_words[IN6_ADDR_NUM_WORDS]; - for (int i= 0; i < IN6_ADDR_NUM_WORDS; ++i) + DBUG_ASSERT(dstsize > 0); // Need a space at least for the trailing '\0' + for (size_t i= 0; i < IN6_ADDR_NUM_WORDS; ++i) ipv6_words[i]= (ipv6_bytes[2 * i] << 8) + ipv6_bytes[2 * i + 1]; // 2. Find "the gap" -- longest sequence of zeros in IPv6-address. @@ -580,7 +711,7 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str) { Region rg= { -1, -1 }; - for (int i = 0; i < IN6_ADDR_NUM_WORDS; ++i) + for (size_t i= 0; i < IN6_ADDR_NUM_WORDS; ++i) { if (ipv6_words[i] != 0) { @@ -601,7 +732,7 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str) } else { - rg.pos= i; + rg.pos= (int) i; rg.length= 1; } } @@ -616,10 +747,14 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str) // 3. Convert binary data to string. - char *p= str; + char *p= dst; - for (int i = 0; i < IN6_ADDR_NUM_WORDS; ++i) + for (int i= 0; i < (int) IN6_ADDR_NUM_WORDS; ++i) { + DBUG_ASSERT(dstend >= p); + size_t dstsize_available= dstend - p; + if (dstsize_available < 5) + break; if (i == gap.pos) { // We're at the gap position. We should put trailing ':' and jump to @@ -646,10 +781,11 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str) { // The data represents either IPv4-compatible or IPv4-mapped address. // The IPv6-part (zeros or zeros + ffff) has been already put into - // the string (str). Now it's time to dump IPv4-part. + // the string (dst). Now it's time to dump IPv4-part. - ipv4_to_str((const in_addr *) (ipv6_bytes + 12), p); - return; + return (size_t) (p - dst) + + Inet4_null((const char *) (ipv6_bytes + 12), 4). + to_string(p, dstsize_available); } else { @@ -660,7 +796,7 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str) p += sprintf(p, "%x", ipv6_words[i]); - if (i != IN6_ADDR_NUM_WORDS - 1) + if (i + 1 != IN6_ADDR_NUM_WORDS) { *p= ':'; ++p; @@ -669,6 +805,7 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str) } *p= 0; + return (size_t) (p - dst); } /////////////////////////////////////////////////////////////////////////// @@ -676,161 +813,122 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str) /** Converts IP-address-string to IP-address-data. - @param arg IP-address-string. - @param [out] buffer Buffer to store IP-address-data. + ipv4-string -> varbinary(4) + ipv6-string -> varbinary(16) @return Completion status. - @retval false Given string does not represent an IP-address. - @retval true The string has been converted sucessfully. + @retval NULL Given string does not represent an IP-address. + @retval !NULL The string has been converted sucessfully. */ -bool Item_func_inet6_aton::calc_value(const String *arg, String *buffer) +String *Item_func_inet6_aton::val_str(String *buffer) { - // ipv4-string -> varbinary(4) - // ipv6-string -> varbinary(16) + DBUG_ASSERT(fixed); - in_addr ipv4_address; - in6_addr ipv6_address; + Ascii_ptr_and_buffer<STRING_BUFFER_USUAL_SIZE> tmp(args[0]); + if ((null_value= tmp.is_null())) + return NULL; - if (str_to_ipv4(arg->ptr(), arg->length(), &ipv4_address)) + Inet4_null ipv4(*tmp.string()); + if (!ipv4.is_null()) { - buffer->length(0); - buffer->append((char *) &ipv4_address, sizeof (in_addr), &my_charset_bin); - - return true; + ipv4.to_binary(buffer); + return buffer; } - if (str_to_ipv6(arg->ptr(), arg->length(), &ipv6_address)) + Inet6_null ipv6(*tmp.string()); + if (!ipv6.is_null()) { - buffer->length(0); - buffer->append((char *) &ipv6_address, sizeof (in6_addr), &my_charset_bin); - - return true; + ipv6.to_binary(buffer); + return buffer; } - return false; + null_value= true; + return NULL; } -/////////////////////////////////////////////////////////////////////////// /** Converts IP-address-data to IP-address-string. - - @param arg IP-address-data. - @param [out] buffer Buffer to store IP-address-string. - - @return Completion status. - @retval false The argument does not correspond to IP-address. - @retval true The string has been converted sucessfully. */ -bool Item_func_inet6_ntoa::calc_value(const String *arg, String *buffer) +String *Item_func_inet6_ntoa::val_str_ascii(String *buffer) { - if (arg->charset() != &my_charset_bin) - return false; + DBUG_ASSERT(fixed); - if ((int) arg->length() == IN_ADDR_SIZE) + // Binary string argument expected + if (unlikely(args[0]->result_type() != STRING_RESULT || + args[0]->collation.collation != &my_charset_bin)) { - char str[INET_ADDRSTRLEN]; - - ipv4_to_str((const in_addr *) arg->ptr(), str); - - buffer->length(0); - buffer->append(str, (uint32) strlen(str), &my_charset_latin1); - - return true; + null_value= true; + return NULL; } - else if ((int) arg->length() == IN6_ADDR_SIZE) - { - char str[INET6_ADDRSTRLEN]; - ipv6_to_str((const in6_addr *) arg->ptr(), str); + String_ptr_and_buffer<STRING_BUFFER_USUAL_SIZE> tmp(args[0]); + if ((null_value= tmp.is_null())) + return NULL; - buffer->length(0); - buffer->append(str, (uint32) strlen(str), &my_charset_latin1); + Inet4_null ipv4(static_cast<const Binary_string&>(*tmp.string())); + if (!ipv4.is_null()) + { + ipv4.to_string(buffer); + return buffer; + } - return true; + Inet6_null ipv6(static_cast<const Binary_string&>(*tmp.string())); + if (!ipv6.is_null()) + { + ipv6.to_string(buffer); + return buffer; } - DBUG_PRINT("info", - ("INET6_NTOA(): varbinary(4) or varbinary(16) expected.")); - return false; + DBUG_PRINT("info", ("INET6_NTOA(): varbinary(4) or varbinary(16) expected.")); + null_value= true; + return NULL; } -/////////////////////////////////////////////////////////////////////////// /** Checks if the passed string represents an IPv4-address. - - @param arg The string to check. - - @return Check status. - @retval false The passed string does not represent an IPv4-address. - @retval true The passed string represents an IPv4-address. */ -bool Item_func_is_ipv4::calc_value(const String *arg) +longlong Item_func_is_ipv4::val_int() { - in_addr ipv4_address; - - return str_to_ipv4(arg->ptr(), arg->length(), &ipv4_address); + DBUG_ASSERT(fixed); + String_ptr_and_buffer<STRING_BUFFER_USUAL_SIZE> tmp(args[0]); + return !tmp.is_null() && !Inet4_null(*tmp.string()).is_null(); } -/////////////////////////////////////////////////////////////////////////// /** Checks if the passed string represents an IPv6-address. - - @param arg The string to check. - - @return Check status. - @retval false The passed string does not represent an IPv6-address. - @retval true The passed string represents an IPv6-address. */ -bool Item_func_is_ipv6::calc_value(const String *arg) +longlong Item_func_is_ipv6::val_int() { - in6_addr ipv6_address; - - return str_to_ipv6(arg->ptr(), arg->length(), &ipv6_address); + DBUG_ASSERT(fixed); + String_ptr_and_buffer<STRING_BUFFER_USUAL_SIZE> tmp(args[0]); + return !tmp.is_null() && !Inet6_null(*tmp.string()).is_null(); } -/////////////////////////////////////////////////////////////////////////// /** Checks if the passed IPv6-address is an IPv4-compat IPv6-address. - - @param arg The IPv6-address to check. - - @return Check status. - @retval false The passed IPv6-address is not an IPv4-compatible IPv6-address. - @retval true The passed IPv6-address is an IPv4-compatible IPv6-address. */ -bool Item_func_is_ipv4_compat::calc_value(const String *arg) +longlong Item_func_is_ipv4_compat::val_int() { - if ((int) arg->length() != IN6_ADDR_SIZE || arg->charset() != &my_charset_bin) - return false; - - return IN6_IS_ADDR_V4COMPAT((struct in6_addr *) arg->ptr()); + Inet6_null ip6(args[0]); + return !ip6.is_null() && ip6.is_v4compat(); } -/////////////////////////////////////////////////////////////////////////// /** Checks if the passed IPv6-address is an IPv4-mapped IPv6-address. - - @param arg The IPv6-address to check. - - @return Check status. - @retval false The passed IPv6-address is not an IPv4-mapped IPv6-address. - @retval true The passed IPv6-address is an IPv4-mapped IPv6-address. */ -bool Item_func_is_ipv4_mapped::calc_value(const String *arg) +longlong Item_func_is_ipv4_mapped::val_int() { - if ((int) arg->length() != IN6_ADDR_SIZE || arg->charset() != &my_charset_bin) - return false; - - return IN6_IS_ADDR_V4MAPPED((struct in6_addr *) arg->ptr()); + Inet6_null ip6(args[0]); + return !ip6.is_null() && ip6.is_v4mapped(); } diff --git a/sql/item_inetfunc.h b/sql/item_inetfunc.h index 024ff8ce4f0..feeac9fa457 100644 --- a/sql/item_inetfunc.h +++ b/sql/item_inetfunc.h @@ -81,33 +81,7 @@ public: { null_value= false; } - -public: - virtual longlong val_int(); bool need_parentheses_in_default() { return false; } - -protected: - virtual bool calc_value(const String *arg) = 0; -}; - - -/************************************************************************* - Item_func_inet_str_base implements common code for INET6/IP-related - functions returning string value. -*************************************************************************/ - -class Item_func_inet_str_base : public Item_str_ascii_func -{ -public: - inline Item_func_inet_str_base(THD *thd, Item *arg): - Item_str_ascii_func(thd, arg) - { } - -public: - virtual String *val_str_ascii(String *buffer); - -protected: - virtual bool calc_value(const String *arg, String *buffer) = 0; }; @@ -115,11 +89,11 @@ protected: Item_func_inet6_aton implements INET6_ATON() SQL-function. *************************************************************************/ -class Item_func_inet6_aton : public Item_func_inet_str_base +class Item_func_inet6_aton : public Item_str_func { public: inline Item_func_inet6_aton(THD *thd, Item *ip_addr): - Item_func_inet_str_base(thd, ip_addr) + Item_str_func(thd, ip_addr) { } public: @@ -136,8 +110,7 @@ public: Item *get_copy(THD *thd) { return get_item_copy<Item_func_inet6_aton>(thd, this); } -protected: - virtual bool calc_value(const String *arg, String *buffer); + String *val_str(String *to); }; @@ -145,11 +118,11 @@ protected: Item_func_inet6_ntoa implements INET6_NTOA() SQL-function. *************************************************************************/ -class Item_func_inet6_ntoa : public Item_func_inet_str_base +class Item_func_inet6_ntoa : public Item_str_ascii_func { public: inline Item_func_inet6_ntoa(THD *thd, Item *ip_addr): - Item_func_inet_str_base(thd, ip_addr) + Item_str_ascii_func(thd, ip_addr) { } public: @@ -168,11 +141,9 @@ public: maybe_null= 1; return FALSE; } + String *val_str_ascii(String *to); Item *get_copy(THD *thd) { return get_item_copy<Item_func_inet6_ntoa>(thd, this); } - -protected: - virtual bool calc_value(const String *arg, String *buffer); }; @@ -193,8 +164,7 @@ public: Item *get_copy(THD *thd) { return get_item_copy<Item_func_is_ipv4>(thd, this); } -protected: - virtual bool calc_value(const String *arg); + longlong val_int(); }; @@ -209,14 +179,12 @@ public: Item_func_inet_bool_base(thd, ip_addr) { } -public: virtual const char *func_name() const { return "is_ipv6"; } Item *get_copy(THD *thd) { return get_item_copy<Item_func_is_ipv6>(thd, this); } -protected: - virtual bool calc_value(const String *arg); + longlong val_int(); }; @@ -230,15 +198,11 @@ public: inline Item_func_is_ipv4_compat(THD *thd, Item *ip_addr): Item_func_inet_bool_base(thd, ip_addr) { } - -public: virtual const char *func_name() const { return "is_ipv4_compat"; } Item *get_copy(THD *thd) { return get_item_copy<Item_func_is_ipv4_compat>(thd, this); } - -protected: - virtual bool calc_value(const String *arg); + longlong val_int(); }; @@ -252,15 +216,11 @@ public: inline Item_func_is_ipv4_mapped(THD *thd, Item *ip_addr): Item_func_inet_bool_base(thd, ip_addr) { } - -public: virtual const char *func_name() const { return "is_ipv4_mapped"; } Item *get_copy(THD *thd) { return get_item_copy<Item_func_is_ipv4_mapped>(thd, this); } - -protected: - virtual bool calc_value(const String *arg); + longlong val_int(); }; #endif // ITEM_INETFUNC_INCLUDED diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 588d41479e1..54bdadc3a32 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -374,17 +374,11 @@ static int path_setup_nwc(json_path_t *p, CHARSET_INFO *i_cs, longlong Item_func_json_valid::val_int() { String *js= args[0]->val_json(&tmp_value); - json_engine_t je; if ((null_value= args[0]->null_value)) return 0; - json_scan_start(&je, js->charset(), (const uchar *) js->ptr(), - (const uchar *) js->ptr()+js->length()); - - while (json_scan_next(&je) == 0) {} - - return je.s.error == 0; + return json_valid(js->ptr(), js->length(), js->charset()); } @@ -1422,7 +1416,7 @@ null_return: static int append_json_value(String *str, Item *item, String *tmp_val) { - if (item->is_bool_type()) + if (item->type_handler()->is_bool_type()) { longlong v_int= item->val_int(); const char *t_f; diff --git a/sql/item_row.cc b/sql/item_row.cc index 8233ba00f06..665c900cb3a 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -60,7 +60,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref) } } maybe_null|= item->maybe_null; - with_sum_func= with_sum_func || item->with_sum_func; + join_with_sum_func(item); with_window_func = with_window_func || item->with_window_func; with_field= with_field || item->with_field; m_with_subquery|= item->with_subquery(); @@ -91,7 +91,7 @@ void Item_row::cleanup() { DBUG_ENTER("Item_row::cleanup"); - Item::cleanup(); + Item_fixed_hybrid::cleanup(); /* Reset to the original values */ used_tables_and_const_cache_init(); with_null= 0; diff --git a/sql/item_row.h b/sql/item_row.h index e0d54403730..4f60a33ab9f 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -33,10 +33,11 @@ Item which stores (x,y,...) and ROW(x,y,...). Note that this can be recursive: ((x,y),(z,t)) is a ROW of ROWs. */ -class Item_row: public Item, +class Item_row: public Item_fixed_hybrid, private Item_args, private Used_tables_and_const_cache, - private With_subquery_cache + private With_subquery_cache, + private With_sum_func_cache { table_map not_null_tables_cache; /** @@ -45,17 +46,25 @@ class Item_row: public Item, */ bool with_null; public: - Item_row(THD *thd, List<Item> &list): - Item(thd), Item_args(thd, list), not_null_tables_cache(0), with_null(0) + Item_row(THD *thd, List<Item> &list) + :Item_fixed_hybrid(thd), Item_args(thd, list), + not_null_tables_cache(0), with_null(0) { } - Item_row(THD *thd, Item_row *row): - Item(thd), Item_args(thd, static_cast<Item_args*>(row)), Used_tables_and_const_cache(), + Item_row(THD *thd, Item_row *row) + :Item_fixed_hybrid(thd), Item_args(thd, static_cast<Item_args*>(row)), + Used_tables_and_const_cache(), + With_sum_func_cache(*row), not_null_tables_cache(0), with_null(0) { } bool with_subquery() const { DBUG_ASSERT(fixed); return m_with_subquery; } enum Type type() const { return ROW_ITEM; }; const Type_handler *type_handler() const { return &type_handler_row; } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + return NULL; // Check with Vicentiu why it's called for Item_row + } void illegal_method_call(const char *); bool is_null() { return null_value; } void make_send_field(THD *thd, Send_field *) @@ -82,7 +91,7 @@ public: illegal_method_call((const char*)"val_decimal"); return 0; }; - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { illegal_method_call((const char*)"get_date"); return true; @@ -92,6 +101,8 @@ public: void cleanup(); void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, uint flags); + bool with_sum_func() const { return m_with_sum_func; } + With_sum_func_cache* get_with_sum_func_cache() { return this; } table_map used_tables() const { return used_tables_cache; }; bool const_item() const { return const_item_cache; }; void update_used_tables() @@ -134,6 +145,11 @@ public: return Item_args::excl_dep_on_grouping_fields(sel); } + bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) + { + return Item_args::excl_dep_on_in_subq_left_part(subq_pred); + } + bool check_vcol_func_processor(void *arg) {return FALSE; } Item *get_copy(THD *thd) { return get_item_copy<Item_row>(thd, this); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 8e4f4232959..8cc539f3d12 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -255,7 +255,7 @@ String *Item_func_sha2::val_str_ascii(String *str) Since we're subverting the usual String methods, we must make sure that the destination has space for the bytes we're about to write. */ - str->realloc((uint) digest_length*2 + 1); /* Each byte as two nybbles */ + str->alloc((uint) digest_length*2 + 1); /* Each byte as two nybbles */ /* Convert the large number to a string-hex representation. */ array_to_hex((char *) str->ptr(), digest_buf, (uint)digest_length); @@ -762,7 +762,7 @@ String *Item_func_des_encrypt::val_str(String *str) tail= 8 - (res_length % 8); // 1..8 marking extra length res_length+=tail; - if (tmp_arg.realloc(res_length)) + if (tmp_arg.alloc(res_length)) goto error; tmp_arg.length(0); tmp_arg.append(res->ptr(), res->length()); @@ -770,7 +770,6 @@ String *Item_func_des_encrypt::val_str(String *str) if (tmp_arg.append(append_str, tail) || str->alloc(res_length+1)) goto error; tmp_arg[res_length-1]=tail; // save extra length - str->realloc(res_length+1); str->length(res_length+1); str->set_charset(&my_charset_bin); (*str)[0]=(char) (128 | key_number); @@ -1017,7 +1016,7 @@ String *Item_func_concat_ws::val_str(String *str) { uint new_len = MY_MAX(tmp_value.alloced_length() * 2, concat_len); - if (tmp_value.realloc(new_len)) + if (tmp_value.alloc(new_len)) goto null; } } @@ -1072,8 +1071,7 @@ String *Item_func_reverse::val_str(String *str) /* An empty string is a special case as the string pointer may be null */ if (!res->length()) return make_empty_result(); - if (str->alloced_length() < res->length() && - str->realloc(res->length())) + if (str->alloc(res->length())) { null_value= 1; return 0; @@ -2659,12 +2657,10 @@ String *Item_func_format::val_str_ascii(String *str) if (args[0]->result_type() == DECIMAL_RESULT || args[0]->result_type() == INT_RESULT) { - my_decimal dec_val, rnd_dec, *res; - res= args[0]->val_decimal(&dec_val); - if ((null_value=args[0]->null_value)) + VDec res(args[0]); + if ((null_value= res.is_null())) return 0; /* purecov: inspected */ - my_decimal_round(E_DEC_FATAL_ERROR, res, dec, false, &rnd_dec); - my_decimal2string(E_DEC_FATAL_ERROR, &rnd_dec, 0, 0, 0, str); + res.to_string_round(str, dec); str_length= str->length(); } else @@ -4180,7 +4176,7 @@ String *Item_func_compress::val_str(String *str) // Check new_size overflow: new_size <= res->length() if (((uint32) (new_size+5) <= res->length()) || - str->realloc((uint32) new_size + 4 + 1)) + str->alloc((uint32) new_size + 4 + 1)) { null_value= 1; return 0; @@ -4252,7 +4248,7 @@ String *Item_func_uncompress::val_str(String *str) max_allowed_packet)); goto err; } - if (str->realloc((uint32)new_size)) + if (str->alloc((uint32)new_size)) goto err; if ((err= uncompress((Byte*)str->ptr(), &new_size, @@ -4281,7 +4277,7 @@ String *Item_func_uuid::val_str(String *str) DBUG_ASSERT(fixed == 1); uchar guid[MY_UUID_SIZE]; - str->realloc(MY_UUID_STRING_LENGTH+1); + str->alloc(MY_UUID_STRING_LENGTH+1); str->length(MY_UUID_STRING_LENGTH); str->set_charset(system_charset_info); my_uuid(guid); @@ -4547,11 +4543,11 @@ bool Item_func_dyncol_create::prepare_arguments(THD *thd, bool force_names_arg) break; case DYN_COL_DATETIME: case DYN_COL_DATE: - args[valpos]->get_date(&vals[i].x.time_value, - sql_mode_for_dates(thd)); + args[valpos]->get_date(thd, &vals[i].x.time_value, + Datetime::Options(thd)); break; case DYN_COL_TIME: - args[valpos]->get_time(&vals[i].x.time_value); + args[valpos]->get_time(thd, &vals[i].x.time_value); break; default: DBUG_ASSERT(0); @@ -5117,7 +5113,7 @@ null: } -bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_dyncol_get::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DYNAMIC_COLUMN_VALUE val; char buff[STRING_BUFFER_USUAL_SIZE]; @@ -5138,10 +5134,8 @@ bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) if (signed_value || val.x.ulong_value <= LONGLONG_MAX) { longlong llval = (longlong)val.x.ulong_value; - bool neg = llval < 0; - if (int_to_datetime_with_warn(neg, (ulonglong)(neg ? -llval : - llval), - ltime, fuzzy_date, 0, 0 /* TODO */)) + if (int_to_datetime_with_warn(thd, Longlong_hybrid(llval, !signed_value), + ltime, fuzzydate, 0, 0 /* TODO */)) goto null; return 0; } @@ -5149,20 +5143,20 @@ bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) val.x.double_value= static_cast<double>(ULONGLONG_MAX); /* fall through */ case DYN_COL_DOUBLE: - if (double_to_datetime_with_warn(val.x.double_value, ltime, fuzzy_date, + if (double_to_datetime_with_warn(thd, val.x.double_value, ltime, fuzzydate, 0, 0 /* TODO */)) goto null; return 0; case DYN_COL_DECIMAL: - if (decimal_to_datetime_with_warn((my_decimal*)&val.x.decimal.value, ltime, - fuzzy_date, 0, 0 /* TODO */)) + if (decimal_to_datetime_with_warn(thd, (my_decimal*)&val.x.decimal.value, + ltime, fuzzydate, 0, 0 /* TODO */)) goto null; return 0; case DYN_COL_STRING: - if (str_to_datetime_with_warn(&my_charset_numeric, + if (str_to_datetime_with_warn(thd, &my_charset_numeric, val.x.string.value.str, val.x.string.value.length, - ltime, fuzzy_date)) + ltime, fuzzydate)) goto null; return 0; case DYN_COL_DATETIME: diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 29af0b43d9d..762a3c2559e 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -62,16 +62,11 @@ public: longlong val_int(); double val_real(); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_string(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_string(thd, ltime, fuzzydate); } const Type_handler *type_handler() const { return string_type_handler(); } void left_right_max_length(); bool fix_fields(THD *thd, Item **ref); - void update_null_value() - { - StringBuffer<MAX_FIELD_WIDTH> tmp; - (void) val_str(&tmp); - } }; @@ -1470,11 +1465,11 @@ public: return NULL; return res; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { if (args[0]->result_type() == STRING_RESULT) - return Item_str_func::get_date(ltime, fuzzydate); - bool res= args[0]->get_date(ltime, fuzzydate); + return Item_str_func::get_date(thd, ltime, fuzzydate); + bool res= args[0]->get_date(thd, ltime, fuzzydate); if ((null_value= args[0]->null_value)) return 1; return res; @@ -1769,7 +1764,7 @@ public: double val_real(); my_decimal *val_decimal(my_decimal *); bool get_dyn_value(THD *thd, DYNAMIC_COLUMN_VALUE *val, String *tmp); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); void print(String *str, enum_query_type query_type); Item *get_copy(THD *thd) { return get_item_copy<Item_dyncol_get>(thd, this); } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 207aa9a25c9..9c0fd057d0f 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -85,6 +85,9 @@ void Item_subselect::init(st_select_lex *select_lex, DBUG_ENTER("Item_subselect::init"); DBUG_PRINT("enter", ("select_lex: %p this: %p", select_lex, this)); + + select_lex->parent_lex->relink_hack(select_lex); + unit= select_lex->master_unit(); if (unit->item) @@ -123,13 +126,6 @@ void Item_subselect::init(st_select_lex *select_lex, else engine= new subselect_single_select_engine(select_lex, result, this); } - { - SELECT_LEX *upper= unit->outer_select(); - if (upper->parsing_place == IN_HAVING) - upper->subquery_in_having= 1; - /* The subquery is an expression cache candidate */ - upper->expr_cache_may_be_used[upper->parsing_place]= TRUE; - } DBUG_PRINT("info", ("engine: %p", engine)); DBUG_VOID_RETURN; } @@ -220,7 +216,8 @@ Item_subselect::~Item_subselect() if (own_engine) delete engine; else - engine->cleanup(); + if (engine) // can be empty in case of EOM + engine->cleanup(); engine= NULL; DBUG_VOID_RETURN; } @@ -244,6 +241,14 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) DBUG_ASSERT(unit->thd == thd); + { + SELECT_LEX *upper= unit->outer_select(); + if (upper->parsing_place == IN_HAVING) + upper->subquery_in_having= 1; + /* The subquery is an expression cache candidate */ + upper->expr_cache_may_be_used[upper->parsing_place]= TRUE; + } + status_var_increment(thd_param->status_var.feature_subquery); DBUG_ASSERT(fixed == 0); @@ -939,7 +944,7 @@ bool Item_subselect::const_item() const Item *Item_subselect::get_tmp_table_item(THD *thd_arg) { - if (!with_sum_func && !const_item()) + if (!Item_subselect::with_sum_func() && !const_item()) return new (thd->mem_root) Item_temptable_field(thd_arg, result_field); return copy_or_same(thd_arg); } @@ -1142,7 +1147,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) if (!select_lex->master_unit()->is_unit_op() && !select_lex->table_list.elements && select_lex->item_list.elements == 1 && - !select_lex->item_list.head()->with_sum_func && + !select_lex->item_list.head()->with_sum_func() && /* We cant change name of Item_field or Item_ref, because it will prevent it's correct resolving, but we should save name of @@ -1347,6 +1352,24 @@ String *Item_singlerow_subselect::val_str(String *str) } +bool Item_singlerow_subselect::val_native(THD *thd, Native *to) +{ + DBUG_ASSERT(fixed == 1); + if (forced_const) + return value->val_native(thd, to); + if (!exec() && !value->null_value) + { + null_value= false; + return value->val_native(thd, to); + } + else + { + reset(); + return true; + } +} + + my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); @@ -1383,15 +1406,15 @@ bool Item_singlerow_subselect::val_bool() } -bool Item_singlerow_subselect::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) +bool Item_singlerow_subselect::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); if (forced_const) - return value->get_date(ltime, fuzzydate); + return value->get_date(thd, ltime, fuzzydate); if (!exec() && !value->null_value) { null_value= FALSE; - return value->get_date(ltime, fuzzydate); + return value->get_date(thd, ltime, fuzzydate); } else { @@ -1407,6 +1430,8 @@ Item_exists_subselect::Item_exists_subselect(THD *thd, emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0) { DBUG_ENTER("Item_exists_subselect::Item_exists_subselect"); + + init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this)); max_columns= UINT_MAX; null_value= FALSE; //can't be NULL @@ -1449,6 +1474,7 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp, { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); DBUG_PRINT("info", ("in_strategy: %u", (uint)in_strategy)); + left_expr_orig= left_expr= left_exp; /* prepare to possible disassembling the item in convert_subq_to_sj() */ if (left_exp->type() == Item::ROW_ITEM) @@ -2038,7 +2064,7 @@ bool Item_in_subselect::fix_having(Item *having, SELECT_LEX *select_lex) { bool fix_res= 0; DBUG_ASSERT(thd); - if (!having->fixed) + if (!having->is_fixed()) { select_lex->having_fix_field= 1; fix_res= having->fix_fields(thd, 0); @@ -2375,9 +2401,9 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, Item *item_having_part2= 0; for (uint i= 0; i < cols_num; i++) { - DBUG_ASSERT((left_expr->fixed && + DBUG_ASSERT((left_expr->is_fixed() && - select_lex->ref_pointer_array[i]->fixed) || + select_lex->ref_pointer_array[i]->is_fixed()) || (select_lex->ref_pointer_array[i]->type() == REF_ITEM && ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() == Item_ref::OUTER_REF)); @@ -2446,8 +2472,8 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, for (uint i= 0; i < cols_num; i++) { Item *item, *item_isnull; - DBUG_ASSERT((left_expr->fixed && - select_lex->ref_pointer_array[i]->fixed) || + DBUG_ASSERT((left_expr->is_fixed() && + select_lex->ref_pointer_array[i]->is_fixed()) || (select_lex->ref_pointer_array[i]->type() == REF_ITEM && ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() == Item_ref::OUTER_REF)); @@ -5787,7 +5813,7 @@ int Ordered_key::cmp_keys_by_row_data(ha_rows a, ha_rows b) { uchar *rowid_a, *rowid_b; - int __attribute__((unused)) error; + int error; int cmp_res; /* The length in bytes of the rowids (positions) of tmp_table. */ uint rowid_length= tbl->file->ref_length; @@ -5801,14 +5827,14 @@ Ordered_key::cmp_keys_by_row_data(ha_rows a, ha_rows b) if (unlikely((error= tbl->file->ha_rnd_pos(tbl->record[0], rowid_a)))) { /* purecov: begin inspected */ - tbl->file->print_error(error, MYF(ME_FATALERROR)); // Sets fatal_error + tbl->file->print_error(error, MYF(ME_FATAL)); // Sets fatal_error return 0; /* purecov: end */ } if (unlikely((error= tbl->file->ha_rnd_pos(tbl->record[1], rowid_b)))) { /* purecov: begin inspected */ - tbl->file->print_error(error, MYF(ME_FATALERROR)); // Sets fatal_error + tbl->file->print_error(error, MYF(ME_FATAL)); // Sets fatal_error return 0; /* purecov: end */ } @@ -5884,13 +5910,13 @@ int Ordered_key::cmp_key_with_search_key(rownum_t row_num) /* The length in bytes of the rowids (positions) of tmp_table. */ uint rowid_length= tbl->file->ref_length; uchar *cur_rowid= row_num_to_rowid + row_num * rowid_length; - int __attribute__((unused)) error; + int error; int cmp_res; if (unlikely((error= tbl->file->ha_rnd_pos(tbl->record[0], cur_rowid)))) { /* purecov: begin inspected */ - tbl->file->print_error(error, MYF(ME_FATALERROR)); // Sets fatal_error + tbl->file->print_error(error, MYF(ME_FATAL)); // Sets fatal_error return 0; /* purecov: end */ } diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 363dbba4ddd..0e771bae42e 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -33,6 +33,7 @@ class subselect_hash_sj_engine; class Item_bool_func2; class Comp_creator; class With_element; +class Field_pair; typedef class st_select_lex SELECT_LEX; @@ -46,7 +47,8 @@ class Cached_item; /* base class for subselects */ class Item_subselect :public Item_result_field, - protected Used_tables_and_const_cache + protected Used_tables_and_const_cache, + protected With_sum_func_cache { bool value_assigned; /* value already assigned to subselect */ bool own_engine; /* the engine was not taken from other Item_subselect */ @@ -183,6 +185,8 @@ public: } bool fix_fields(THD *thd, Item **ref); bool with_subquery() const { DBUG_ASSERT(fixed); return true; } + bool with_sum_func() const { return m_with_sum_func; } + With_sum_func_cache* get_with_sum_func_cache() { return this; } bool mark_as_dependent(THD *thd, st_select_lex *select, Item *item); void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge); void recalc_used_tables(st_select_lex *new_parent, bool after_pullout); @@ -302,9 +306,10 @@ public: double val_real(); longlong val_int (); String *val_str (String *); + bool val_native(THD *thd, Native *); my_decimal *val_decimal(my_decimal *); bool val_bool(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); const Type_handler *type_handler() const; bool fix_length_and_dec(); @@ -395,14 +400,14 @@ public: } void no_rows_in_result(); - const Type_handler *type_handler() const { return &type_handler_longlong; } + const Type_handler *type_handler() const { return &type_handler_bool; } longlong val_int(); double val_real(); String *val_str(String*); my_decimal *val_decimal(my_decimal *); bool val_bool(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_int(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_int(thd, ltime, fuzzydate); } bool fix_fields(THD *thd, Item **ref); bool fix_length_and_dec(); void print(String *str, enum_query_type query_type); @@ -570,6 +575,8 @@ public: */ bool is_registered_semijoin; + List<Field_pair> corresponding_fields; + /* Used to determine how this subselect item is represented in the item tree, in case there is a need to locate it there and replace with something else. @@ -621,7 +628,6 @@ public: double val_real(); String *val_str(String*); my_decimal *val_decimal(my_decimal *); - void update_null_value () { (void) val_bool(); } bool val_bool(); bool test_limit(st_select_lex_unit *unit); void print(String *str, enum_query_type query_type); @@ -741,6 +747,8 @@ public: return 0; }; + bool pushdown_cond_for_in_subquery(THD *thd, Item *cond); + friend class Item_ref_null_helper; friend class Item_is_not_null_test; friend class Item_in_optimizer; @@ -852,7 +860,6 @@ protected: bool set_row(List<Item> &item_list, Item_cache **row); }; - class subselect_single_select_engine: public subselect_engine { bool prepared; /* simple subselect is prepared */ @@ -886,9 +893,10 @@ public: friend class subselect_hash_sj_engine; friend class Item_in_subselect; - friend bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, - Item **join_where); - + friend bool execute_degenerate_jtbm_semi_join(THD *thd, + TABLE_LIST *tbl, + Item_in_subselect *subq_pred, + List<Item> &eq_list); }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 44e5a86c863..fe901b65aeb 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -406,7 +406,7 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref) for (sl= thd->lex->current_select; sl && sl != aggr_sel && sl->master_unit()->item; sl= sl->master_unit()->outer_select() ) - sl->master_unit()->item->with_sum_func= 1; + sl->master_unit()->item->get_with_sum_func_cache()->set_with_sum_func(); } thd->lex->current_select->mark_as_dependent(thd, aggr_sel, NULL); @@ -486,7 +486,6 @@ void Item_sum::mark_as_sum_func() cur_select->n_sum_items++; cur_select->with_sum_func= 1; const_item_cache= false; - with_sum_func= 1; with_field= 0; window_func_sum_expr_flag= false; } @@ -892,7 +891,7 @@ bool Aggregator_distinct::setup(THD *thd) item_sum->null_value= item_sum->maybe_null= 1; item_sum->quick_group= 0; - DBUG_ASSERT(item_sum->get_arg(0)->fixed); + DBUG_ASSERT(item_sum->get_arg(0)->is_fixed()); arg= item_sum->get_arg(0); if (arg->const_item()) @@ -1239,9 +1238,11 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table) if (args[0]->type() == Item::FIELD_ITEM) { Field *field= ((Item_field*) args[0])->field; - if ((field= create_tmp_field_from_field(table->in_use, field, &name, - table, NULL))) - field->flags&= ~NOT_NULL_FLAG; + if ((field= field->create_tmp_field(table->in_use->mem_root, table, true))) + { + DBUG_ASSERT((field->flags & NOT_NULL_FLAG) == 0); + field->field_name= name; + } DBUG_RETURN(field); } DBUG_RETURN(tmp_table_field_from_field_type(table)); @@ -1289,7 +1290,7 @@ Item_sum_sp::fix_fields(THD *thd, Item **ref) if (!m_sp) { my_missing_function_error(m_name->m_name, ErrConvDQName(m_name).ptr()); - context->process_error(thd); + process_error(thd); return TRUE; } @@ -1641,12 +1642,7 @@ longlong Item_sum_sum::val_int() if (aggr) aggr->endup(); if (result_type() == DECIMAL_RESULT) - { - longlong result; - my_decimal2int(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, unsigned_flag, - &result); - return result; - } + return dec_buffs[curr_dec_buff].to_longlong(unsigned_flag); return val_int_from_real(); } @@ -1657,7 +1653,7 @@ double Item_sum_sum::val_real() if (aggr) aggr->endup(); if (result_type() == DECIMAL_RESULT) - my_decimal2double(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, &sum); + sum= dec_buffs[curr_dec_buff].to_double(); return sum; } @@ -1667,7 +1663,7 @@ String *Item_sum_sum::val_str(String *str) if (aggr) aggr->endup(); if (result_type() == DECIMAL_RESULT) - return val_string_from_decimal(str); + return VDec(this).to_string_round(str, decimals); return val_string_from_real(str); } @@ -2033,7 +2029,7 @@ String *Item_sum_avg::val_str(String *str) if (aggr) aggr->endup(); if (result_type() == DECIMAL_RESULT) - return val_string_from_decimal(str); + return VDec(this).to_string_round(str, decimals); return val_string_from_real(str); } @@ -2311,12 +2307,12 @@ void Item_sum_hybrid::clear() bool -Item_sum_hybrid::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +Item_sum_hybrid::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); if (null_value) return true; - bool retval= value->get_date(ltime, fuzzydate); + bool retval= value->get_date(thd, ltime, fuzzydate); if ((null_value= value->null_value)) DBUG_ASSERT(retval == true); return retval; @@ -2385,6 +2381,15 @@ Item_sum_hybrid::val_str(String *str) } +bool Item_sum_hybrid::val_native(THD *thd, Native *to) +{ + DBUG_ASSERT(fixed == 1); + if (null_value) + return true; + return val_native_from_item(thd, value, to); +} + + void Item_sum_hybrid::cleanup() { DBUG_ENTER("Item_sum_hybrid::cleanup"); @@ -2750,11 +2755,11 @@ void Item_sum_hybrid::reset_field() } case DECIMAL_RESULT: { - my_decimal value_buff, *arg_dec= arg0->val_decimal(&value_buff); + VDec arg_dec(arg0); if (maybe_null) { - if (arg0->null_value) + if (arg_dec.is_null()) result_field->set_null(); else result_field->set_notnull(); @@ -2763,9 +2768,7 @@ void Item_sum_hybrid::reset_field() We must store zero in the field as we will use the field value in add() */ - if (!arg_dec) // Null - arg_dec= &decimal_zero; - result_field->store_decimal(arg_dec); + result_field->store_decimal(arg_dec.ptr_or(&decimal_zero)); break; } case ROW_RESULT: @@ -2788,15 +2791,10 @@ void Item_sum_sum::reset_field() DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR); if (result_type() == DECIMAL_RESULT) { - my_decimal value, *arg_val; if (unlikely(direct_added)) - arg_val= &direct_sum_decimal; + result_field->store_decimal(&direct_sum_decimal); else - { - if (!(arg_val= args[0]->val_decimal(&value))) - arg_val= &decimal_zero; // Null - } - result_field->store_decimal(arg_val); + result_field->store_decimal(VDec(args[0]).ptr_or(&decimal_zero)); } else { @@ -2849,15 +2847,9 @@ void Item_sum_avg::reset_field() if (result_type() == DECIMAL_RESULT) { longlong tmp; - my_decimal value, *arg_dec= args[0]->val_decimal(&value); - if (args[0]->null_value) - { - arg_dec= &decimal_zero; - tmp= 0; - } - else - tmp= 1; - my_decimal2binary(E_DEC_FATAL_ERROR, arg_dec, res, f_precision, f_scale); + VDec value(args[0]); + tmp= value.is_null() ? 0 : 1; + value.to_binary(res, f_precision, f_scale); res+= dec_bin_size; int8store(res, tmp); } @@ -2924,9 +2916,8 @@ void Item_sum_sum::update_field() { if (!result_field->is_null()) { - my_decimal field_value; - my_decimal *field_val= result_field->val_decimal(&field_value); - my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, arg_val, field_val); + my_decimal field_value(result_field); + my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, arg_val, &field_value); result_field->store_decimal(dec_buffs); } else @@ -2993,15 +2984,14 @@ void Item_sum_avg::update_field() if (result_type() == DECIMAL_RESULT) { - my_decimal value, *arg_val= args[0]->val_decimal(&value); - if (!args[0]->null_value) + VDec tmp(args[0]); + if (!tmp.is_null()) { binary2my_decimal(E_DEC_FATAL_ERROR, res, dec_buffs + 1, f_precision, f_scale); field_count= sint8korr(res + dec_bin_size); - my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, arg_val, dec_buffs + 1); - my_decimal2binary(E_DEC_FATAL_ERROR, dec_buffs, - res, f_precision, f_scale); + my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, tmp.ptr(), dec_buffs + 1); + dec_buffs->to_binary(res, f_precision, f_scale); res+= dec_bin_size; field_count++; int8store(res, field_count); @@ -3196,9 +3186,7 @@ my_decimal *Item_avg_field_decimal::val_decimal(my_decimal *dec_buf) if ((null_value= !count)) return 0; - my_decimal dec_count, dec_field; - binary2my_decimal(E_DEC_FATAL_ERROR, - field->ptr, &dec_field, f_precision, f_scale); + my_decimal dec_count, dec_field(field->ptr, f_precision, f_scale); int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &dec_count); my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &dec_field, &dec_count, prec_increment); @@ -3256,6 +3244,25 @@ bool Item_udf_sum::add() DBUG_RETURN(0); } + +bool Item_udf_sum::supports_removal() const +{ + DBUG_ENTER("Item_udf_sum::supports_remove"); + DBUG_PRINT("info", ("support: %d", udf.supports_removal())); + DBUG_RETURN(udf.supports_removal()); +} + + +void Item_udf_sum::remove() +{ + my_bool tmp_null_value; + DBUG_ENTER("Item_udf_sum::remove"); + udf.remove(&tmp_null_value); + null_value= tmp_null_value; + DBUG_VOID_RETURN; +} + + void Item_udf_sum::cleanup() { /* @@ -3312,24 +3319,6 @@ my_decimal *Item_sum_udf_float::val_decimal(my_decimal *dec) } -String *Item_sum_udf_decimal::val_str(String *str) -{ - return val_string_from_decimal(str); -} - - -double Item_sum_udf_decimal::val_real() -{ - return val_real_from_decimal(); -} - - -longlong Item_sum_udf_decimal::val_int() -{ - return val_int_from_decimal(); -} - - my_decimal *Item_sum_udf_decimal::val_decimal(my_decimal *dec_buf) { my_decimal *res; @@ -4010,6 +3999,7 @@ bool Item_func_group_concat::setup(THD *thd) if (!ref_pointer_array) DBUG_RETURN(TRUE); memcpy(ref_pointer_array, args, arg_count * sizeof(Item*)); + DBUG_ASSERT(context); if (setup_order(thd, Ref_ptr_array(ref_pointer_array, n_elems), context->table_list, list, all_fields, *order)) DBUG_RETURN(TRUE); diff --git a/sql/item_sum.h b/sql/item_sum.h index b400ebd5f80..50e41990b13 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -384,7 +384,9 @@ protected: Item **orig_args, *tmp_orig_args[2]; static size_t ram_limitation(THD *thd); - +public: + // Methods used by ColumnStore + Item **get_orig_args() const { return orig_args; } public: void mark_as_sum_func(); @@ -511,7 +513,12 @@ public: } virtual void make_unique() { force_copy_fields= TRUE; } Item *get_tmp_table_item(THD *thd); - Field *create_tmp_field(bool group, TABLE *table); + virtual Field *create_tmp_field(bool group, TABLE *table); + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + return create_tmp_field(param->group(), table); + } virtual bool collect_outer_ref_processor(void *param); bool init_sum_func_check(THD *thd); bool check_sum_func(THD *thd, Item **ref); @@ -578,6 +585,8 @@ public: void mark_as_window_func_sum_expr() { window_func_sum_expr_flag= true; } bool is_window_func_sum_expr() { return window_func_sum_expr_flag; } virtual void setup_caches(THD *thd) {}; + + bool with_sum_func() const { return true; } }; @@ -735,9 +744,9 @@ public: longlong val_int() { return val_int_from_real(); /* Real as default */ } String *val_str(String*str); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } void reset_field(); }; @@ -1060,9 +1069,10 @@ protected: double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); void reset_field(); String *val_str(String *); + bool val_native(THD *thd, Native *); const Type_handler *real_type_handler() const { return get_arg(0)->real_type_handler(); @@ -1356,7 +1366,7 @@ public: void update_field(){DBUG_ASSERT(0);} void clear(); void cleanup(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { return execute() || sp_result_field->get_date(ltime, fuzzydate); } @@ -1384,17 +1394,21 @@ public: decimals= item->decimals; max_length= item->max_length; unsigned_flag= item->unsigned_flag; - fixed= true; } table_map used_tables() const { return (table_map) 1L; } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + return create_tmp_field_ex_simple(table, src, param); + } void save_in_result_field(bool no_conversions) { DBUG_ASSERT(0); } bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(name.str, arg, VCOL_IMPOSSIBLE); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } }; @@ -1439,9 +1453,18 @@ public: dec_bin_size(item->dec_bin_size) { } const Type_handler *type_handler() const { return &type_handler_newdecimal; } - double val_real() { return val_real_from_decimal(); } - longlong val_int() { return val_int_from_decimal(); } - String *val_str(String *str) { return val_string_from_decimal(str); } + double val_real() + { + return VDec(this).to_double(); + } + longlong val_int() + { + return VDec(this).to_longlong(unsigned_flag); + } + String *val_str(String *str) + { + return VDec(this).to_string_round(str, decimals); + } my_decimal *val_decimal(my_decimal *); Item *get_copy(THD *thd) { return get_item_copy<Item_avg_field_decimal>(thd, this); } @@ -1541,13 +1564,15 @@ public: void clear(); bool add(); + bool supports_removal() const; + void remove(); void reset_field() {}; void update_field() {}; void cleanup(); virtual void print(String *str, enum_query_type query_type); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } }; @@ -1645,9 +1670,18 @@ public: Item_udf_sum(thd, udf_arg, list) {} Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item) :Item_udf_sum(thd, item) {} - String *val_str(String *); - double val_real(); - longlong val_int(); + String *val_str(String *str) + { + return VDec(this).to_string_round(str, decimals); + } + double val_real() + { + return VDec(this).to_double(); + } + longlong val_int() + { + return VDec(this).to_longlong(unsigned_flag); + } my_decimal *val_decimal(my_decimal *); const Type_handler *type_handler() const { return &type_handler_newdecimal; } bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; } @@ -1797,6 +1831,14 @@ class Item_func_group_concat : public Item_sum element_count count __attribute__((unused)), void* item_arg); public: + // Methods used by ColumnStore + bool get_distinct() const { return distinct; } + uint get_count_field() const { return arg_count_field; } + uint get_order_field() const { return arg_count_order; } + const String* get_separator() const { return separator; } + ORDER** get_order() const { return order; } + +public: Item_func_group_concat(THD *thd, Name_resolution_context *context_arg, bool is_distinct, List<Item> *is_select, const SQL_I_List<ORDER> &is_order, String *is_separator, @@ -1845,9 +1887,9 @@ public: { return val_decimal_from_string(decimal_value); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return get_date_from_string(ltime, fuzzydate); + return get_date_from_string(thd, ltime, fuzzydate); } String* val_str(String* str); Item *copy_or_same(THD* thd); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 25fecd0a134..cccb5a4b37f 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -59,6 +59,29 @@ /** Day number for Dec 31st, 9999. */ #define MAX_DAY_NUMBER 3652424L + +Func_handler_date_add_interval_datetime_arg0_time + func_handler_date_add_interval_datetime_arg0_time; + +Func_handler_date_add_interval_datetime func_handler_date_add_interval_datetime; +Func_handler_date_add_interval_date func_handler_date_add_interval_date; +Func_handler_date_add_interval_time func_handler_date_add_interval_time; +Func_handler_date_add_interval_string func_handler_date_add_interval_string; + +Func_handler_add_time_datetime func_handler_add_time_datetime_add(1); +Func_handler_add_time_datetime func_handler_add_time_datetime_sub(-1); +Func_handler_add_time_time func_handler_add_time_time_add(1); +Func_handler_add_time_time func_handler_add_time_time_sub(-1); +Func_handler_add_time_string func_handler_add_time_string_add(1); +Func_handler_add_time_string func_handler_add_time_string_sub(-1); + +Func_handler_str_to_date_datetime_sec func_handler_str_to_date_datetime_sec; +Func_handler_str_to_date_datetime_usec func_handler_str_to_date_datetime_usec; +Func_handler_str_to_date_date func_handler_str_to_date_date; +Func_handler_str_to_date_time_sec func_handler_str_to_date_time_sec; +Func_handler_str_to_date_time_usec func_handler_str_to_date_time_usec; + + /* Date formats corresponding to compound %r and %T conversion specifiers @@ -103,12 +126,12 @@ static DATE_TIME_FORMAT time_24hrs_format= {{0}, '\0', 0, 1 error */ -static bool extract_date_time(DATE_TIME_FORMAT *format, +static bool extract_date_time(THD *thd, DATE_TIME_FORMAT *format, const char *val, uint length, MYSQL_TIME *l_time, timestamp_type cached_timestamp_type, const char **sub_pattern_end, const char *date_time_type, - ulonglong fuzzy_date) + date_conv_mode_t fuzzydate) { int weekday= 0, yearday= 0, daypart= 0; int week_number= -1; @@ -303,17 +326,17 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, We can't just set error here, as we don't want to generate two warnings in case of errors */ - if (extract_date_time(&time_ampm_format, val, + if (extract_date_time(thd, &time_ampm_format, val, (uint)(val_end - val), l_time, - cached_timestamp_type, &val, "time", fuzzy_date)) + cached_timestamp_type, &val, "time", fuzzydate)) DBUG_RETURN(1); break; /* Time in 24-hour notation */ case 'T': - if (extract_date_time(&time_24hrs_format, val, + if (extract_date_time(thd, &time_24hrs_format, val, (uint)(val_end - val), l_time, - cached_timestamp_type, &val, "time", fuzzy_date)) + cached_timestamp_type, &val, "time", fuzzydate)) DBUG_RETURN(1); break; @@ -419,7 +442,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, goto err; int was_cut; - if (check_date(l_time, fuzzy_date | TIME_INVALID_DATES, &was_cut)) + if (check_date(l_time, fuzzydate | TIME_INVALID_DATES, &was_cut)) goto err; if (val != val_end) @@ -428,10 +451,9 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, { if (!my_isspace(&my_charset_latin1,*val)) { - make_truncated_value_warning(current_thd, - Sql_condition::WARN_LEVEL_WARN, - val_begin, length, - cached_timestamp_type, 0, NullS); + ErrConvString err(val_begin, length, &my_charset_bin); + make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN, + &err, cached_timestamp_type, 0, NullS); break; } } while (++val != val_end); @@ -440,7 +462,6 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, err: { - THD *thd= current_thd; char buff[128]; strmake(buff, val_begin, MY_MIN(length, sizeof(buff)-1)); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -787,10 +808,9 @@ longlong Item_func_period_diff::val_int() longlong Item_func_to_days::val_int() { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - if (get_arg0_date(<ime, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) - return 0; - return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day); + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.daynr(); } @@ -798,42 +818,31 @@ longlong Item_func_to_seconds::val_int_endpoint(bool left_endp, bool *incl_endp) { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - longlong seconds; - longlong days; - int dummy; /* unused */ - if (get_arg0_date(<ime, TIME_FUZZY_DATES)) + // val_int_endpoint() is called only if args[0] is a temporal Item_field + Datetime_from_temporal dt(current_thd, args[0], TIME_FUZZY_DATES); + if ((null_value= !dt.is_valid_datetime())) { /* got NULL, leave the incl_endp intact */ return LONGLONG_MIN; } - seconds= ltime.hour * 3600L + ltime.minute * 60 + ltime.second; - seconds= ltime.neg ? -seconds : seconds; - days= (longlong) calc_daynr(ltime.year, ltime.month, ltime.day); - seconds+= days * 24L * 3600L; /* Set to NULL if invalid date, but keep the value */ - null_value= check_date(<ime, - (ltime.year || ltime.month || ltime.day), - (TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE), - &dummy); + null_value= dt.check_date(TIME_NO_ZEROS); /* Even if the evaluation return NULL, seconds is useful for pruning */ - return seconds; + return dt.to_seconds(); } longlong Item_func_to_seconds::val_int() { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - longlong seconds; - longlong days; - if (get_arg0_date(<ime, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) - return 0; - seconds= ltime.hour * 3600L + ltime.minute * 60 + ltime.second; - seconds=ltime.neg ? -seconds : seconds; - days= (longlong) calc_daynr(ltime.year, ltime.month, ltime.day); - return seconds + days * 24L * 3600L; + THD *thd= current_thd; + /* + Unlike val_int_endpoint(), we cannot use Datetime_from_temporal here. + The argument can be of a non-temporal data type. + */ + Datetime dt(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + return (null_value= !dt.is_valid_datetime()) ? 0 : dt.to_seconds(); } /* @@ -877,19 +886,17 @@ enum_monotonicity_info Item_func_to_seconds::get_monotonicity_info() const longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp) { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; + // val_int_endpoint() is only called if args[0] is a temporal Item_field + Datetime_from_temporal dt(current_thd, args[0], TIME_CONV_NONE); longlong res; - int dummy; /* unused */ - if (get_arg0_date(<ime, 0)) + if ((null_value= !dt.is_valid_datetime())) { /* got NULL, leave the incl_endp intact */ return LONGLONG_MIN; } - res=(longlong) calc_daynr(ltime.year,ltime.month,ltime.day); + res= (longlong) dt.daynr(); /* Set to NULL if invalid date, but keep the value */ - null_value= check_date(<ime, - (TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE), - &dummy); + null_value= dt.check_date(TIME_NO_ZEROS); if (null_value) { /* @@ -918,8 +925,8 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp) col < '2007-09-15 12:34:56' -> TO_DAYS(col) <= TO_DAYS('2007-09-15') */ - if ((!left_endp && !(ltime.hour || ltime.minute || ltime.second || - ltime.second_part)) || + const MYSQL_TIME <ime= dt.get_mysql_time()[0]; + if ((!left_endp && dt.hhmmssff_is_zero()) || (left_endp && ltime.hour == 23 && ltime.minute == 59 && ltime.second == 59)) /* do nothing */ @@ -933,25 +940,25 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp) longlong Item_func_dayofyear::val_int() { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - if (get_arg0_date(<ime, TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE)) - return 0; - return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day) - - calc_daynr(ltime.year,1,1) + 1; + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.dayofyear(); } longlong Item_func_dayofmonth::val_int() { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - return get_arg0_date(<ime, 0) ? 0 : (longlong) ltime.day; + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.get_mysql_time()->day; } longlong Item_func_month::val_int() { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - return get_arg0_date(<ime, 0) ? 0 : (longlong) ltime.month; + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.get_mysql_time()->month; } @@ -973,12 +980,12 @@ String* Item_func_monthname::val_str(String* str) DBUG_ASSERT(fixed == 1); const char *month_name; uint err; - MYSQL_TIME ltime; - - if ((null_value= (get_arg0_date(<ime, 0) || !ltime.month))) + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + if ((null_value= (!d.is_valid_datetime() || !d.get_mysql_time()->month))) return (String *) 0; - month_name= locale->month_names->type_names[ltime.month - 1]; + month_name= locale->month_names->type_names[d.get_mysql_time()->month - 1]; str->copy(month_name, (uint) strlen(month_name), &my_charset_utf8_bin, collation.collation, &err); return str; @@ -992,23 +999,24 @@ String* Item_func_monthname::val_str(String* str) longlong Item_func_quarter::val_int() { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - if (get_arg0_date(<ime, 0)) - return 0; - return (longlong) ((ltime.month+2)/3); + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.quarter(); } longlong Item_func_hour::val_int() { DBUG_ASSERT(fixed == 1); - Time tm(args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); return (null_value= !tm.is_valid_time()) ? 0 : tm.get_mysql_time()->hour; } longlong Item_func_minute::val_int() { DBUG_ASSERT(fixed == 1); - Time tm(args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); return (null_value= !tm.is_valid_time()) ? 0 : tm.get_mysql_time()->minute; } @@ -1018,7 +1026,8 @@ longlong Item_func_minute::val_int() longlong Item_func_second::val_int() { DBUG_ASSERT(fixed == 1); - Time tm(args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); return (null_value= !tm.is_valid_time()) ? 0 : tm.get_mysql_time()->second; } @@ -1065,43 +1074,36 @@ uint week_mode(uint mode) longlong Item_func_week::val_int() { DBUG_ASSERT(fixed == 1); - uint year, week_format; - MYSQL_TIME ltime; - if (get_arg0_date(<ime, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) + uint week_format; + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + if ((null_value= !d.is_valid_datetime())) return 0; if (arg_count > 1) week_format= (uint)args[1]->val_int(); else - week_format= current_thd->variables.default_week_format; - return (longlong) calc_week(<ime, week_mode(week_format), &year); + week_format= thd->variables.default_week_format; + return d.week(week_mode(week_format)); } longlong Item_func_yearweek::val_int() { DBUG_ASSERT(fixed == 1); - uint year,week; - MYSQL_TIME ltime; - if (get_arg0_date(<ime, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) - return 0; - week= calc_week(<ime, - (week_mode((uint) args[1]->val_int()) | WEEK_YEAR), - &year); - return week+year*100; + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : + d.yearweek((week_mode((uint) args[1]->val_int()) | WEEK_YEAR)); } longlong Item_func_weekday::val_int() { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - - if (get_arg0_date(<ime, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) - return 0; - - return (longlong) calc_weekday(calc_daynr(ltime.year, ltime.month, - ltime.day), - odbc_type) + MY_TEST(odbc_type); + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_NO_ZEROS, thd)); + return ((null_value= !d.is_valid_datetime())) ? 0 : + calc_weekday(d.daynr(), odbc_type) + MY_TEST(odbc_type); } bool Item_func_dayname::fix_length_and_dec() @@ -1137,8 +1139,9 @@ String* Item_func_dayname::val_str(String* str) longlong Item_func_year::val_int() { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - return get_arg0_date(<ime, 0) ? 0 : (longlong) ltime.year; + THD *thd= current_thd; + Datetime d(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + return (null_value= !d.is_valid_datetime()) ? 0 : d.get_mysql_time()->year; } @@ -1169,8 +1172,9 @@ enum_monotonicity_info Item_func_year::get_monotonicity_info() const longlong Item_func_year::val_int_endpoint(bool left_endp, bool *incl_endp) { DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - if (get_arg0_date(<ime, 0)) + // val_int_endpoint() is cally only if args[0] is a temporal Item_field + Datetime_from_temporal dt(current_thd, args[0], TIME_CONV_NONE); + if ((null_value= !dt.is_valid_datetime())) { /* got NULL, leave the incl_endp intact */ return LONGLONG_MIN; @@ -1187,8 +1191,9 @@ longlong Item_func_year::val_int_endpoint(bool left_endp, bool *incl_endp) col < '2007-09-15 23:00:00' -> YEAR(col) <= 2007 */ + const MYSQL_TIME <ime= dt.get_mysql_time()[0]; if (!left_endp && ltime.day == 1 && ltime.month == 1 && - !(ltime.hour || ltime.minute || ltime.second || ltime.second_part)) + dt.hhmmssff_is_zero()) ; /* do nothing */ else *incl_endp= TRUE; @@ -1212,14 +1217,13 @@ bool Item_func_unix_timestamp::get_timestamp_value(my_time_t *seconds, } } - MYSQL_TIME ltime; - if (get_arg0_date(<ime, TIME_NO_ZERO_IN_DATE)) - return 1; - - uint error_code; - *seconds= TIME_to_timestamp(current_thd, <ime, &error_code); - *second_part= ltime.second_part; - return (null_value= (error_code == ER_WARN_DATA_OUT_OF_RANGE)); + Timestamp_or_zero_datetime_native_null native(current_thd, args[0], true); + if ((null_value= native.is_null() || native.is_zero_datetime())) + return true; + Timestamp_or_zero_datetime tm(native); + *seconds= tm.tv().tv_sec; + *second_part= tm.tv().tv_usec; + return false; } @@ -1276,7 +1280,8 @@ longlong Item_func_unix_timestamp::val_int_endpoint(bool left_endp, bool *incl_e longlong Item_func_time_to_sec::int_op() { DBUG_ASSERT(fixed == 1); - Time tm(args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); return ((null_value= !tm.is_valid_time())) ? 0 : tm.to_seconds(); } @@ -1284,7 +1289,8 @@ longlong Item_func_time_to_sec::int_op() my_decimal *Item_func_time_to_sec::decimal_op(my_decimal* buf) { DBUG_ASSERT(fixed == 1); - Time tm(args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); if ((null_value= !tm.is_valid_time())) return 0; const MYSQL_TIME *ltime= tm.get_mysql_time(); @@ -1299,7 +1305,8 @@ my_decimal *Item_func_time_to_sec::decimal_op(my_decimal* buf) To make code easy, allow interval objects without separators. */ -bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval) +bool get_interval_value(THD *thd, Item *args, + interval_type int_type, INTERVAL *interval) { ulonglong array[5]; longlong UNINIT_VAR(value); @@ -1312,25 +1319,19 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval) bzero((char*) interval,sizeof(*interval)); if (int_type == INTERVAL_SECOND && args->decimals) { - my_decimal decimal_value, *val; - ulonglong second; - ulong second_part; - if (!(val= args->val_decimal(&decimal_value))) + VDec val(args); + if (val.is_null()) return true; - interval->neg= my_decimal2seconds(val, &second, &second_part); - if (second == LONGLONG_MAX) + Sec6 d(val.ptr()); + interval->neg= d.neg(); + if (d.sec() >= LONGLONG_MAX) { - THD *thd= current_thd; - ErrConvDecimal err(val); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_TRUNCATED_WRONG_VALUE, - ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), "DECIMAL", - err.ptr()); + ErrConvDecimal err(val.ptr()); + thd->push_warning_truncated_wrong_value("seconds", err.ptr()); return true; } - - interval->second= second; - interval->second_part= second_part; + interval->second= d.sec(); + interval->second_part= d.usec(); return false; } else if ((int) int_type <= INTERVAL_MICROSECOND) @@ -1476,90 +1477,11 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval) } -String *Item_temporal_func::val_str(String *str) -{ - DBUG_ASSERT(fixed == 1); - return val_string_from_date(str); -} - - -bool Item_temporal_hybrid_func::fix_temporal_type(MYSQL_TIME *ltime) -{ - if (ltime->time_type < 0) /* MYSQL_TIMESTAMP_NONE, MYSQL_TIMESTAMP_ERROR */ - return false; - - if (ltime->time_type != MYSQL_TIMESTAMP_TIME) - goto date_or_datetime_value; - - /* Convert TIME to DATE or DATETIME */ - switch (field_type()) - { - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_TIMESTAMP: - { - MYSQL_TIME tmp; - if (time_to_datetime_with_warn(current_thd, ltime, &tmp, 0)) - return (null_value= true); - *ltime= tmp; - if (field_type() == MYSQL_TYPE_DATE) - datetime_to_date(ltime); - return false; - } - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_STRING: /* DATE_ADD, ADDTIME can return VARCHAR */ - return false; - default: - DBUG_ASSERT(0); - return (null_value= true); - } - -date_or_datetime_value: - /* Convert DATE or DATETIME to TIME, DATE, or DATETIME */ - switch (field_type()) - { - case MYSQL_TYPE_TIME: - datetime_to_time(ltime); - return false; - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_TIMESTAMP: - date_to_datetime(ltime); - return false; - case MYSQL_TYPE_DATE: - datetime_to_date(ltime); - return false; - case MYSQL_TYPE_STRING: /* DATE_ADD, ADDTIME can return VARCHAR */ - return false; - default: - DBUG_ASSERT(0); - return (null_value= true); - } - return false; -} - - -String *Item_temporal_hybrid_func::val_str_ascii(String *str) -{ - DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; - - if (get_date(<ime, 0) || fix_temporal_type(<ime) || - (null_value= my_TIME_to_str(<ime, str, decimals))) - return (String *) 0; - - /* Check that the returned timestamp type matches to the function type */ - DBUG_ASSERT(field_type() == MYSQL_TYPE_STRING || - ltime.time_type == MYSQL_TIMESTAMP_NONE || - ltime.time_type == mysql_timestamp_type()); - return str; -} - - -bool Item_func_from_days::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_func_from_days::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { longlong value=args[0]->val_int(); if ((null_value= (args[0]->null_value || - ((fuzzy_date & TIME_NO_ZERO_DATE) && value == 0)))) + ((fuzzydate & TIME_NO_ZERO_DATE) && value == 0)))) return true; bzero(ltime, sizeof(MYSQL_TIME)); if (get_date_from_daynr((long) value, <ime->year, <ime->month, @@ -1596,10 +1518,9 @@ void Item_func_curdate_utc::store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) } -bool Item_func_curdate::get_date(MYSQL_TIME *res, - ulonglong fuzzy_date __attribute__((unused))) +bool Item_func_curdate::get_date(THD *thd, MYSQL_TIME *res, + date_mode_t fuzzydate __attribute__((unused))) { - THD *thd= current_thd; query_id_t query_id= thd->query_id; /* Cache value for this query */ if (last_query_id != query_id) @@ -1626,10 +1547,9 @@ bool Item_func_curtime::fix_fields(THD *thd, Item **items) return Item_timefunc::fix_fields(thd, items); } -bool Item_func_curtime::get_date(MYSQL_TIME *res, - ulonglong fuzzy_date __attribute__((unused))) +bool Item_func_curtime::get_date(THD *thd, MYSQL_TIME *res, + date_mode_t fuzzydate __attribute__((unused))) { - THD *thd= current_thd; query_id_t query_id= thd->query_id; /* Cache value for this query */ if (last_query_id != query_id) @@ -1700,7 +1620,7 @@ bool Item_func_now::fix_fields(THD *thd, Item **items) func_name(), TIME_SECOND_PART_DIGITS); return 1; } - return Item_temporal_func::fix_fields(thd, items); + return Item_datetimefunc::fix_fields(thd, items); } void Item_func_now::print(String *str, enum_query_type query_type) @@ -1719,15 +1639,14 @@ int Item_func_now_local::save_in_field(Field *field, bool no_conversions) { THD *thd= field->get_thd(); my_time_t ts= thd->query_start(); - uint dec= MY_MIN(decimals, field->decimals()); - ulong sec_part= dec ? thd->query_start_sec_part() : 0; - sec_part-= my_time_fraction_remainder(sec_part, dec); + ulong sec_part= decimals ? thd->query_start_sec_part() : 0; + sec_part-= my_time_fraction_remainder(sec_part, decimals); field->set_notnull(); ((Field_timestamp*)field)->store_TIME(ts, sec_part); return 0; } else - return Item_temporal_func::save_in_field(field, no_conversions); + return Item_datetimefunc::save_in_field(field, no_conversions); } @@ -1758,10 +1677,9 @@ void Item_func_now_utc::store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) } -bool Item_func_now::get_date(MYSQL_TIME *res, - ulonglong fuzzy_date __attribute__((unused))) +bool Item_func_now::get_date(THD *thd, MYSQL_TIME *res, + date_mode_t fuzzydate __attribute__((unused))) { - THD *thd= current_thd; query_id_t query_id= thd->query_id; /* Cache value for this query */ if (last_query_id != query_id) @@ -1787,62 +1705,23 @@ void Item_func_sysdate_local::store_now_in_TIME(THD *thd, MYSQL_TIME *now_time) } -bool Item_func_sysdate_local::get_date(MYSQL_TIME *res, - ulonglong fuzzy_date __attribute__((unused))) +bool Item_func_sysdate_local::get_date(THD *thd, MYSQL_TIME *res, + date_mode_t fuzzydate __attribute__((unused))) { - store_now_in_TIME(current_thd, res); + store_now_in_TIME(thd, res); return 0; } -bool Item_func_sec_to_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_func_sec_to_time::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); - bool sign; - ulonglong sec; - ulong sec_part; - - bzero((char *)ltime, sizeof(*ltime)); - ltime->time_type= MYSQL_TIMESTAMP_TIME; - - sign= args[0]->get_seconds(&sec, &sec_part); - - if ((null_value= args[0]->null_value)) - return 1; - - ltime->neg= sign; - if (sec > TIME_MAX_VALUE_SECONDS) - goto overflow; - - DBUG_ASSERT(sec_part <= TIME_MAX_SECOND_PART); - - ltime->hour= (uint) (sec/3600); - ltime->minute= (uint) (sec % 3600) /60; - ltime->second= (uint) sec % 60; - ltime->second_part= sec_part; - - return 0; - -overflow: - /* use check_time_range() to set ltime to the max value depending on dec */ - int unused; - char buf[100]; - String tmp(buf, sizeof(buf), &my_charset_bin), *err= args[0]->val_str(&tmp); - - ltime->hour= TIME_MAX_HOUR+1; - check_time_range(ltime, decimals, &unused); - if (!err) - { - ErrConvInteger err2(sec, unsigned_flag); - make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, - &err2, MYSQL_TIMESTAMP_TIME, 0, NullS); - } - else - { - ErrConvString err2(err); - make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, - &err2, MYSQL_TIMESTAMP_TIME, 0, NullS); - } - return 0; + VSec9 sec(thd, args[0], "seconds", LONGLONG_MAX); + if ((null_value= sec.is_null())) + return true; + sec.round(decimals, thd->temporal_round_mode()); + if (sec.sec_to_time(ltime, decimals) && !sec.truncated()) + sec.make_truncated_warning(thd, "seconds"); + return false; } bool Item_func_date_format::fix_length_and_dec() @@ -1997,8 +1876,10 @@ String *Item_func_date_format::val_str(String *str) uint size; const MY_LOCALE *lc= 0; DBUG_ASSERT(fixed == 1); - - if ((null_value= args[0]->get_date(&l_time, is_time_format ? TIME_TIME_ONLY : 0))) + date_conv_mode_t mode= is_time_format ? TIME_TIME_ONLY : TIME_CONV_NONE; + THD *thd= current_thd; + if ((null_value= args[0]->get_date(thd, &l_time, + Temporal::Options(mode, thd)))) return 0; if (!(format = args[1]->val_str(str)) || !format->length()) @@ -2049,35 +1930,34 @@ bool Item_func_from_unixtime::fix_length_and_dec() } -bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime, - ulonglong fuzzy_date __attribute__((unused))) +bool Item_func_from_unixtime::get_date(THD *thd, MYSQL_TIME *ltime, + date_mode_t fuzzydate __attribute__((unused))) { - bool sign; - ulonglong sec; - ulong sec_part; - bzero((char *)ltime, sizeof(*ltime)); ltime->time_type= MYSQL_TIMESTAMP_TIME; - sign= args[0]->get_seconds(&sec, &sec_part); + VSec9 sec(thd, args[0], "unixtime", TIMESTAMP_MAX_VALUE); + DBUG_ASSERT(sec.sec() <= TIMESTAMP_MAX_VALUE); - if (args[0]->null_value || sign || sec > TIMESTAMP_MAX_VALUE) + if (sec.is_null() || sec.truncated() || sec.neg()) return (null_value= 1); - tz->gmt_sec_to_TIME(ltime, (my_time_t)sec); + sec.round(MY_MIN(decimals, TIME_SECOND_PART_DIGITS), thd->temporal_round_mode()); + if (sec.sec() > TIMESTAMP_MAX_VALUE) + return (null_value= true); // Went out of range after rounding - ltime->second_part= sec_part; + tz->gmt_sec_to_TIME(ltime, (my_time_t) sec.sec()); + ltime->second_part= sec.usec(); return (null_value= 0); } -bool Item_func_convert_tz::get_date(MYSQL_TIME *ltime, - ulonglong fuzzy_date __attribute__((unused))) +bool Item_func_convert_tz::get_date(THD *thd, MYSQL_TIME *ltime, + date_mode_t fuzzydate __attribute__((unused))) { my_time_t my_time_tmp; String str; - THD *thd= current_thd; if (!from_tz_cached) { @@ -2091,9 +1971,13 @@ bool Item_func_convert_tz::get_date(MYSQL_TIME *ltime, to_tz_cached= args[2]->const_item(); } - if (from_tz==0 || to_tz==0 || - get_arg0_date(ltime, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) - return (null_value= 1); + if ((null_value= (from_tz == 0 || to_tz == 0))) + return true; + + Datetime::Options opt(TIME_NO_ZEROS, thd); + Datetime *dt= new(ltime) Datetime(thd, args[0], opt); + if ((null_value= !dt->is_valid_datetime())) + return true; { uint not_used; @@ -2113,7 +1997,7 @@ bool Item_func_convert_tz::get_date(MYSQL_TIME *ltime, void Item_func_convert_tz::cleanup() { from_tz_cached= to_tz_cached= 0; - Item_temporal_func::cleanup(); + Item_datetimefunc::cleanup(); } @@ -2144,81 +2028,44 @@ bool Item_date_add_interval::fix_length_and_dec() MYSQL_TIME or DATETIME argument) */ arg0_field_type= args[0]->field_type(); - uint interval_dec= 0; - if (int_type == INTERVAL_MICROSECOND || - (int_type >= INTERVAL_DAY_MICROSECOND && - int_type <= INTERVAL_SECOND_MICROSECOND)) - interval_dec= TIME_SECOND_PART_DIGITS; - else if (int_type == INTERVAL_SECOND && args[1]->decimals > 0) - interval_dec= MY_MIN(args[1]->decimals, TIME_SECOND_PART_DIGITS); if (arg0_field_type == MYSQL_TYPE_DATETIME || arg0_field_type == MYSQL_TYPE_TIMESTAMP) { - uint dec= MY_MAX(args[0]->datetime_precision(), interval_dec); - set_handler(&type_handler_datetime); - fix_attributes_datetime(dec); + set_func_handler(&func_handler_date_add_interval_datetime); } else if (arg0_field_type == MYSQL_TYPE_DATE) { if (int_type <= INTERVAL_DAY || int_type == INTERVAL_YEAR_MONTH) - { - set_handler(&type_handler_newdate); - fix_attributes_date(); - } + set_func_handler(&func_handler_date_add_interval_date); else - { - set_handler(&type_handler_datetime2); - fix_attributes_datetime(interval_dec); - } + set_func_handler(&func_handler_date_add_interval_datetime); } else if (arg0_field_type == MYSQL_TYPE_TIME) { - uint dec= MY_MAX(args[0]->time_precision(), interval_dec); if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH) - { - set_handler(&type_handler_time2); - fix_attributes_time(dec); - } + set_func_handler(&func_handler_date_add_interval_time); else - { - set_handler(&type_handler_datetime2); - fix_attributes_datetime(dec); - } + set_func_handler(&func_handler_date_add_interval_datetime_arg0_time); } else { - uint dec= MY_MAX(args[0]->datetime_precision(), interval_dec); - set_handler(&type_handler_string); - collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); - fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec); + set_func_handler(&func_handler_date_add_interval_string); } maybe_null= true; - return FALSE; + return m_func_handler->fix_length_and_dec(this); } -bool Item_date_add_interval::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Func_handler_date_add_interval_datetime_arg0_time:: + get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const { - INTERVAL interval; - - if (args[0]->get_date(ltime, - field_type() == MYSQL_TYPE_TIME ? - TIME_TIME_ONLY : 0) || - get_interval_value(args[1], int_type, &interval)) - return (null_value=1); - - if (ltime->time_type != MYSQL_TIMESTAMP_TIME && - check_date_with_warn(ltime, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE, - MYSQL_TIMESTAMP_ERROR)) - return (null_value=1); - - if (date_sub_interval) - interval.neg = !interval.neg; - - if (date_add_interval(ltime, int_type, interval)) - return (null_value=1); - return (null_value= 0); + // time_expr + INTERVAL {YEAR|QUARTER|MONTH|WEEK|YEAR_MONTH} + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_DATETIME_FUNCTION_OVERFLOW, + ER_THD(thd, ER_DATETIME_FUNCTION_OVERFLOW), "time"); + return (item->null_value= true); } @@ -2268,16 +2115,18 @@ void Item_extract::print(String *str, enum_query_type query_type) bool Item_extract::fix_length_and_dec() { maybe_null=1; // If wrong date + uint32 daylen= args[0]->cmp_type() == TIME_RESULT ? 2 : + TIME_MAX_INTERVAL_DAY_CHAR_LENGTH; switch (int_type) { case INTERVAL_YEAR: set_date_length(4); break; // YYYY case INTERVAL_YEAR_MONTH: set_date_length(6); break; // YYYYMM case INTERVAL_QUARTER: set_date_length(2); break; // 1..4 case INTERVAL_MONTH: set_date_length(2); break; // MM case INTERVAL_WEEK: set_date_length(2); break; // 0..52 - case INTERVAL_DAY: set_date_length(2); break; // DD - case INTERVAL_DAY_HOUR: set_time_length(4); break; // DDhh - case INTERVAL_DAY_MINUTE: set_time_length(6); break; // DDhhmm - case INTERVAL_DAY_SECOND: set_time_length(8); break; // DDhhmmss + case INTERVAL_DAY: set_day_length(daylen); break; // DD + case INTERVAL_DAY_HOUR: set_day_length(daylen+2); break; // DDhh + case INTERVAL_DAY_MINUTE: set_day_length(daylen+4); break; // DDhhmm + case INTERVAL_DAY_SECOND: set_day_length(daylen+6); break; // DDhhmmss case INTERVAL_HOUR: set_time_length(2); break; // hh case INTERVAL_HOUR_MINUTE: set_time_length(4); break; // hhmm case INTERVAL_HOUR_SECOND: set_time_length(6); break; // hhmmss @@ -2285,7 +2134,7 @@ bool Item_extract::fix_length_and_dec() case INTERVAL_MINUTE_SECOND: set_time_length(4); break; // mmss case INTERVAL_SECOND: set_time_length(2); break; // ss case INTERVAL_MICROSECOND: set_time_length(6); break; // ffffff - case INTERVAL_DAY_MICROSECOND: set_time_length(14); break; // DDhhmmssffffff + case INTERVAL_DAY_MICROSECOND: set_time_length(daylen+12); break; // DDhhmmssffffff case INTERVAL_HOUR_MICROSECOND: set_time_length(12); break; // hhmmssffffff case INTERVAL_MINUTE_MICROSECOND: set_time_length(10); break; // mmssffffff case INTERVAL_SECOND_MICROSECOND: set_time_length(8); break; // ssffffff @@ -2295,69 +2144,46 @@ bool Item_extract::fix_length_and_dec() } -longlong Item_extract::val_int() +uint Extract_source::week(THD *thd) const { - DBUG_ASSERT(fixed == 1); - MYSQL_TIME ltime; + DBUG_ASSERT(is_valid_extract_source()); uint year; - ulong week_format; - long neg; - int is_time_flag = date_value ? 0 : TIME_TIME_ONLY; - - // Not using get_arg0_date to avoid automatic TIME to DATETIME conversion - if ((null_value= args[0]->get_date(<ime, is_time_flag))) - return 0; - - neg= ltime.neg ? -1 : 1; + ulong week_format= current_thd->variables.default_week_format; + return calc_week(this, week_mode(week_format), &year); +} - DBUG_ASSERT(ltime.time_type != MYSQL_TIMESTAMP_TIME || ltime.day == 0); - if (ltime.time_type == MYSQL_TIMESTAMP_TIME) - time_to_daytime_interval(<ime); +longlong Item_extract::val_int() +{ + DBUG_ASSERT(fixed == 1); + THD *thd= current_thd; + Extract_source dt(thd, args[0], m_date_mode); + if ((null_value= !dt.is_valid_extract_source())) + return 0; switch (int_type) { - case INTERVAL_YEAR: return ltime.year; - case INTERVAL_YEAR_MONTH: return ltime.year*100L+ltime.month; - case INTERVAL_QUARTER: return (ltime.month+2)/3; - case INTERVAL_MONTH: return ltime.month; - case INTERVAL_WEEK: - { - week_format= current_thd->variables.default_week_format; - return calc_week(<ime, week_mode(week_format), &year); - } - case INTERVAL_DAY: return ltime.day; - case INTERVAL_DAY_HOUR: return (long) (ltime.day*100L+ltime.hour)*neg; - case INTERVAL_DAY_MINUTE: return (long) (ltime.day*10000L+ - ltime.hour*100L+ - ltime.minute)*neg; - case INTERVAL_DAY_SECOND: return ((longlong) ltime.day*1000000L+ - (longlong) (ltime.hour*10000L+ - ltime.minute*100+ - ltime.second))*neg; - case INTERVAL_HOUR: return (long) ltime.hour*neg; - case INTERVAL_HOUR_MINUTE: return (long) (ltime.hour*100+ltime.minute)*neg; - case INTERVAL_HOUR_SECOND: return (long) (ltime.hour*10000+ltime.minute*100+ - ltime.second)*neg; - case INTERVAL_MINUTE: return (long) ltime.minute*neg; - case INTERVAL_MINUTE_SECOND: return (long) (ltime.minute*100+ltime.second)*neg; - case INTERVAL_SECOND: return (long) ltime.second*neg; - case INTERVAL_MICROSECOND: return (long) ltime.second_part*neg; - case INTERVAL_DAY_MICROSECOND: return (((longlong)ltime.day*1000000L + - (longlong)ltime.hour*10000L + - ltime.minute*100 + - ltime.second)*1000000L + - ltime.second_part)*neg; - case INTERVAL_HOUR_MICROSECOND: return (((longlong)ltime.hour*10000L + - ltime.minute*100 + - ltime.second)*1000000L + - ltime.second_part)*neg; - case INTERVAL_MINUTE_MICROSECOND: return (((longlong)(ltime.minute*100+ - ltime.second))*1000000L+ - ltime.second_part)*neg; - case INTERVAL_SECOND_MICROSECOND: return ((longlong)ltime.second*1000000L+ - ltime.second_part)*neg; + case INTERVAL_YEAR: return dt.year(); + case INTERVAL_YEAR_MONTH: return dt.year_month(); + case INTERVAL_QUARTER: return dt.quarter(); + case INTERVAL_MONTH: return dt.month(); + case INTERVAL_WEEK: return dt.week(thd); + case INTERVAL_DAY: return dt.day(); + case INTERVAL_DAY_HOUR: return dt.day_hour(); + case INTERVAL_DAY_MINUTE: return dt.day_minute(); + case INTERVAL_DAY_SECOND: return dt.day_second(); + case INTERVAL_HOUR: return dt.hour(); + case INTERVAL_HOUR_MINUTE: return dt.hour_minute(); + case INTERVAL_HOUR_SECOND: return dt.hour_second(); + case INTERVAL_MINUTE: return dt.minute(); + case INTERVAL_MINUTE_SECOND: return dt.minute_second(); + case INTERVAL_SECOND: return dt.second(); + case INTERVAL_MICROSECOND: return dt.microsecond(); + case INTERVAL_DAY_MICROSECOND: return dt.day_microsecond(); + case INTERVAL_HOUR_MICROSECOND: return dt.hour_microsecond(); + case INTERVAL_MINUTE_MICROSECOND: return dt.minute_microsecond(); + case INTERVAL_SECOND_MICROSECOND: return dt.second_microsecond(); case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */ } - return 0; // Impossible + return 0; // Impossible } bool Item_extract::eq(const Item *item, bool binary_cmp) const @@ -2396,13 +2222,14 @@ bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const return 1; } -void Item_temporal_typecast::print(String *str, enum_query_type query_type) +void Item_func::print_cast_temporal(String *str, enum_query_type query_type) { char buf[32]; str->append(STRING_WITH_LEN("cast(")); args[0]->print(str, query_type); str->append(STRING_WITH_LEN(" as ")); - str->append(cast_type()); + const Name name= type_handler()->name(); + str->append(name.ptr(), name.length()); if (decimals && decimals != NOT_FIXED_DEC) { str->append('('); @@ -2615,45 +2442,31 @@ void Item_char_typecast::fix_length_and_dec_internal(CHARSET_INFO *from_cs) } -bool Item_time_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_time_typecast::get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) { - Time tm(args[0], Time::Options_for_cast()); - if ((null_value= !tm.is_valid_time())) - return true; - tm.copy_to_mysql_time(ltime); - if (decimals < TIME_SECOND_PART_DIGITS) - my_time_trunc(ltime, decimals); - return (fuzzy_date & TIME_TIME_ONLY) ? 0 : - (null_value= check_date_with_warn(ltime, fuzzy_date, - MYSQL_TIMESTAMP_ERROR)); + Time *tm= new(to) Time(thd, args[0], Time::Options_for_cast(mode, thd), + MY_MIN(decimals, TIME_SECOND_PART_DIGITS)); + return (null_value= !tm->is_valid_time()); } -bool Item_date_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_date_typecast::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - fuzzy_date |= sql_mode_for_dates(current_thd); - if (get_arg0_date(ltime, fuzzy_date & ~TIME_TIME_ONLY)) - return 1; - - if (make_date_with_warn(ltime, fuzzy_date, MYSQL_TIMESTAMP_DATE)) - return (null_value= 1); - - return 0; + date_mode_t tmp= (fuzzydate | sql_mode_for_dates(thd)) & ~TIME_TIME_ONLY; + // Force truncation + Date *d= new(ltime) Date(thd, args[0], Date::Options(date_conv_mode_t(tmp))); + return (null_value= !d->is_valid_date()); } -bool Item_datetime_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_datetime_typecast::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - fuzzy_date |= sql_mode_for_dates(current_thd); - if (get_arg0_date(ltime, fuzzy_date & ~TIME_TIME_ONLY)) - return 1; - - if (decimals < TIME_SECOND_PART_DIGITS) - my_time_trunc(ltime, decimals); - - DBUG_ASSERT(ltime->time_type != MYSQL_TIMESTAMP_TIME); - ltime->time_type= MYSQL_TIMESTAMP_DATETIME; - return 0; + date_mode_t tmp= (fuzzydate | sql_mode_for_dates(thd)) & ~TIME_TIME_ONLY; + // Force rounding if the current sql_mode says so + Datetime::Options opt(date_conv_mode_t(tmp), thd); + Datetime *dt= new(ltime) Datetime(thd, args[0], opt, + MY_MIN(decimals, TIME_SECOND_PART_DIGITS)); + return (null_value= !dt->is_valid_datetime()); } @@ -2668,20 +2481,17 @@ bool Item_datetime_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) 0099-12-31 */ -bool Item_func_makedate::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_func_makedate::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); - long daynr= (long) args[1]->val_int(); - long year= (long) args[0]->val_int(); - long days; + long year, days, daynr= (long) args[1]->val_int(); - if (args[0]->null_value || args[1]->null_value || - year < 0 || year > 9999 || daynr <= 0) + VYear vyear(args[0]); + if (vyear.is_null() || args[1]->null_value || vyear.truncated() || daynr <= 0) goto err; - if (year < 100) + if ((year= (long) vyear.year()) < 100) year= year_2000_handling(year); - days= calc_daynr(year,1,1) + daynr - 1; if (get_date_from_daynr(days, <ime->year, <ime->month, <ime->day)) goto err; @@ -2720,101 +2530,24 @@ bool Item_func_add_time::fix_length_and_dec() arg0_field_type= args[0]->field_type(); if (arg0_field_type == MYSQL_TYPE_DATE || arg0_field_type == MYSQL_TYPE_DATETIME || - arg0_field_type == MYSQL_TYPE_TIMESTAMP || - is_date) + arg0_field_type == MYSQL_TYPE_TIMESTAMP) { - uint dec= MY_MAX(args[0]->datetime_precision(), args[1]->time_precision()); - set_handler(&type_handler_datetime2); - fix_attributes_datetime(dec); + set_func_handler(sign > 0 ? &func_handler_add_time_datetime_add : + &func_handler_add_time_datetime_sub); } else if (arg0_field_type == MYSQL_TYPE_TIME) { - uint dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision()); - set_handler(&type_handler_time2); - fix_attributes_time(dec); + set_func_handler(sign > 0 ? &func_handler_add_time_time_add : + &func_handler_add_time_time_sub); } else { - uint dec= MY_MAX(args[0]->decimals, args[1]->decimals); - set_handler(&type_handler_string); - collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); - fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec); + set_func_handler(sign > 0 ? &func_handler_add_time_string_add : + &func_handler_add_time_string_sub); } - maybe_null= true; - return FALSE; -} -/** - ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a - time/datetime value - - t: time_or_datetime_expression - a: time_expression - - Result: Time value or datetime value -*/ - -bool Item_func_add_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) -{ - DBUG_ASSERT(fixed == 1); - MYSQL_TIME l_time1, l_time2; - bool is_time= 0; - long days, microseconds; - longlong seconds; - int l_sign= sign; - - if (Item_func_add_time::field_type() == MYSQL_TYPE_DATETIME) - { - // TIMESTAMP function OR the first argument is DATE/DATETIME/TIMESTAMP - if (get_arg0_date(&l_time1, 0) || - args[1]->get_time(&l_time2) || - l_time1.time_type == MYSQL_TIMESTAMP_TIME || - l_time2.time_type != MYSQL_TIMESTAMP_TIME) - return (null_value= 1); - } - else - { - // ADDTIME function AND the first argument is TIME - if (args[0]->get_time(&l_time1) || - args[1]->get_time(&l_time2) || - l_time2.time_type != MYSQL_TIMESTAMP_TIME) - return (null_value= 1); - is_time= (l_time1.time_type == MYSQL_TIMESTAMP_TIME); - } - if (l_time1.neg != l_time2.neg) - l_sign= -l_sign; - - bzero(ltime, sizeof(*ltime)); - - ltime->neg= calc_time_diff(&l_time1, &l_time2, -l_sign, - &seconds, µseconds); - - /* - If first argument was negative and diff between arguments - is non-zero we need to swap sign to get proper result. - */ - if (l_time1.neg && (seconds || microseconds)) - ltime->neg= 1-ltime->neg; // Swap sign of result - - if (!is_time && ltime->neg) - return (null_value= 1); - - days= (long) (seconds / SECONDS_IN_24H); - - calc_time_from_sec(ltime, (long)(seconds % SECONDS_IN_24H), microseconds); - - ltime->time_type= is_time ? MYSQL_TIMESTAMP_TIME : MYSQL_TIMESTAMP_DATETIME; - - if (!is_time) - { - if (get_date_from_daynr(days,<ime->year,<ime->month,<ime->day) || - !ltime->day) - return (null_value= 1); - return (null_value= 0); - } - - ltime->hour+= days*24; - return (null_value= adjust_time_range_with_warn(ltime, decimals)); + maybe_null= true; + return m_func_handler->fix_length_and_dec(this); } @@ -2826,7 +2559,7 @@ bool Item_func_add_time::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) Result: Time value */ -bool Item_func_timediff::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_func_timediff::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); int l_sign= 1; @@ -2834,55 +2567,47 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) ErrConvTime str(&l_time3); /* the following may be true in, for example, date_add(timediff(...), ... */ - if (fuzzy_date & TIME_NO_ZERO_IN_DATE) + if (fuzzydate & TIME_NO_ZERO_IN_DATE) return (null_value= 1); - if (args[0]->get_time(&l_time1) || - args[1]->get_time(&l_time2) || + if (args[0]->get_time(thd, &l_time1) || + args[1]->get_time(thd, &l_time2) || l_time1.time_type != l_time2.time_type) return (null_value= 1); if (l_time1.neg != l_time2.neg) l_sign= -l_sign; - if (calc_time_diff(&l_time1, &l_time2, l_sign, &l_time3, fuzzy_date)) + if (calc_time_diff(&l_time1, &l_time2, l_sign, &l_time3, fuzzydate)) return (null_value= 1); *ltime= l_time3; - return (null_value= adjust_time_range_with_warn(ltime, decimals)); + return (null_value= adjust_time_range_with_warn(thd, ltime, decimals)); } + /** MAKETIME(h,m,s) is a time function that calculates a time value from the total number of hours, minutes, and seconds. Result: Time value */ -bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_func_maketime::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); Longlong_hybrid hour(args[0]->val_int(), args[0]->unsigned_flag); longlong minute= args[1]->val_int(); - ulonglong second; - ulong microsecond; - bool neg= args[2]->get_seconds(&second, µsecond); + VSec9 sec(thd, args[2], "seconds", 59); - if (args[0]->null_value || args[1]->null_value || args[2]->null_value || - minute < 0 || minute > 59 || neg || second > 59) + DBUG_ASSERT(sec.sec() <= 59); + if (args[0]->null_value || args[1]->null_value || sec.is_null() || + minute < 0 || minute > 59 || sec.neg() || sec.truncated()) return (null_value= 1); - bzero(ltime, sizeof(*ltime)); - ltime->time_type= MYSQL_TIMESTAMP_TIME; - ltime->neg= hour.neg(); - - if (hour.abs() <= TIME_MAX_HOUR) - { - ltime->hour= (uint) hour.abs(); - ltime->minute= (uint) minute; - ltime->second= (uint) second; - ltime->second_part= microsecond; - } - else + int warn; + new(ltime) Time(&warn, hour.neg(), hour.abs(), (uint) minute, sec, + thd->temporal_round_mode(), decimals); + if (warn) { // use check_time_range() to set ltime to the max value depending on dec int unused; @@ -2890,10 +2615,10 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) check_time_range(ltime, decimals, &unused); char buf[28]; char *ptr= longlong10_to_str(hour.value(), buf, hour.is_unsigned() ? 10 : -10); - int len = (int)(ptr - buf) + sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second); - make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, - buf, len, MYSQL_TIMESTAMP_TIME, - 0, NullS); + int len = (int)(ptr - buf) + sprintf(ptr, ":%02u:%02u", + (uint) minute, (uint) sec.sec()); + ErrConvString err(buf, len, &my_charset_bin); + thd->push_warning_truncated_wrong_value("time", err.ptr()); } return (null_value= 0); @@ -2911,7 +2636,8 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) longlong Item_func_microsecond::val_int() { DBUG_ASSERT(fixed == 1); - Time tm(args[0], Time::Options_for_cast()); + THD *thd= current_thd; + Time tm(thd, args[0], Time::Options_for_cast(thd)); return ((null_value= !tm.is_valid_time())) ? 0 : tm.get_mysql_time()->second_part; } @@ -2920,17 +2646,17 @@ longlong Item_func_microsecond::val_int() longlong Item_func_timestamp_diff::val_int() { MYSQL_TIME ltime1, ltime2; - longlong seconds; - long microseconds; + ulonglong seconds; + ulong microseconds; long months= 0; int neg= 1; THD *thd= current_thd; - ulonglong fuzzydate= TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE; + Datetime::Options opt(TIME_NO_ZEROS, thd); null_value= 0; - if (Datetime(thd, args[0], fuzzydate).copy_to_mysql_time(<ime1) || - Datetime(thd, args[1], fuzzydate).copy_to_mysql_time(<ime2)) + if (Datetime(thd, args[0], opt).copy_to_mysql_time(<ime1) || + Datetime(thd, args[1], opt).copy_to_mysql_time(<ime2)) goto null_date; if (calc_time_diff(<ime2,<ime1, 1, @@ -3000,21 +2726,21 @@ longlong Item_func_timestamp_diff::val_int() case INTERVAL_MONTH: return months*neg; case INTERVAL_WEEK: - return seconds / SECONDS_IN_24H / 7L * neg; + return ((longlong) (seconds / SECONDS_IN_24H / 7L)) * neg; case INTERVAL_DAY: - return seconds / SECONDS_IN_24H * neg; + return ((longlong) (seconds / SECONDS_IN_24H)) * neg; case INTERVAL_HOUR: - return seconds/3600L*neg; + return ((longlong) (seconds / 3600L)) * neg; case INTERVAL_MINUTE: - return seconds/60L*neg; + return ((longlong) (seconds / 60L)) * neg; case INTERVAL_SECOND: - return seconds*neg; + return ((longlong) seconds) * neg; case INTERVAL_MICROSECOND: /* In MySQL difference between any two valid datetime values in microseconds fits into longlong. */ - return (seconds*1000000L+microseconds)*neg; + return ((longlong) ((ulonglong) seconds * 1000000L + microseconds)) * neg; default: break; } @@ -3144,15 +2870,10 @@ void Item_func_get_format::print(String *str, enum_query_type query_type) specifiers supported by extract_date_time() function. @return - One of date_time_format_types values: - - DATE_TIME_MICROSECOND - - DATE_TIME - - DATE_ONLY - - TIME_MICROSECOND - - TIME_ONLY + A function handler corresponding the given format */ -static date_time_format_types +static const Item_handled_func::Handler * get_date_time_result_type(const char *format, uint length) { const char *time_part_frms= "HISThiklrs"; @@ -3179,21 +2900,21 @@ get_date_time_result_type(const char *format, uint length) frac_second_used implies time_part_used, and thus we already have all types of date-time components and can end our search. */ - return DATE_TIME_MICROSECOND; + return &func_handler_str_to_date_datetime_usec; } } } /* We don't have all three types of date-time components */ if (frac_second_used) - return TIME_MICROSECOND; + return &func_handler_str_to_date_time_usec; if (time_part_used) { if (date_part_used) - return DATE_TIME; - return TIME_ONLY; + return &func_handler_str_to_date_datetime_sec; + return &func_handler_str_to_date_time_sec; } - return DATE_ONLY; + return &func_handler_str_to_date_date; } @@ -3213,56 +2934,27 @@ bool Item_func_str_to_date::fix_length_and_dec() internal_charset= &my_charset_utf8mb4_general_ci; maybe_null= true; - set_handler(&type_handler_datetime2); - fix_attributes_datetime(TIME_SECOND_PART_DIGITS); + set_func_handler(&func_handler_str_to_date_datetime_usec); if ((const_item= args[1]->const_item())) { - char format_buff[64]; - String format_str(format_buff, sizeof(format_buff), &my_charset_bin); + StringBuffer<64> format_str; String *format= args[1]->val_str(&format_str, &format_converter, internal_charset); - decimals= 0; if (!args[1]->null_value) - { - date_time_format_types cached_format_type= - get_date_time_result_type(format->ptr(), format->length()); - switch (cached_format_type) { - case DATE_ONLY: - set_handler(&type_handler_newdate); - fix_attributes_date(); - break; - case TIME_MICROSECOND: - set_handler(&type_handler_time2); - fix_attributes_time(TIME_SECOND_PART_DIGITS); - break; - case TIME_ONLY: - set_handler(&type_handler_time2); - fix_attributes_time(0); - break; - case DATE_TIME_MICROSECOND: - set_handler(&type_handler_datetime2); - fix_attributes_datetime(TIME_SECOND_PART_DIGITS); - break; - case DATE_TIME: - set_handler(&type_handler_datetime2); - fix_attributes_datetime(0); - break; - } - } + set_func_handler(get_date_time_result_type(format->ptr(), format->length())); } - cached_timestamp_type= mysql_timestamp_type(); - return FALSE; + return m_func_handler->fix_length_and_dec(this); } -bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_func_str_to_date::get_date_common(THD *thd, MYSQL_TIME *ltime, + date_mode_t fuzzydate, + timestamp_type tstype) { DATE_TIME_FORMAT date_time_format; - char val_buff[64], format_buff[64]; - String val_string(val_buff, sizeof(val_buff), &my_charset_bin), *val; - String format_str(format_buff, sizeof(format_buff), &my_charset_bin), - *format; + StringBuffer<64> val_string, format_str; + String *val, *format; val= args[0]->val_str(&val_string, &subject_converter, internal_charset); format= args[1]->val_str(&format_str, &format_converter, internal_charset); @@ -3271,29 +2963,22 @@ bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) date_time_format.format.str= (char*) format->ptr(); date_time_format.format.length= format->length(); - if (extract_date_time(&date_time_format, val->ptr(), val->length(), - ltime, cached_timestamp_type, 0, "datetime", - fuzzy_date | sql_mode_for_dates(current_thd))) + if (extract_date_time(thd, &date_time_format, val->ptr(), val->length(), + ltime, tstype, 0, "datetime", + date_conv_mode_t(fuzzydate) | + sql_mode_for_dates(thd))) return (null_value=1); - if (cached_timestamp_type == MYSQL_TIMESTAMP_TIME && ltime->day) - { - /* - Day part for time type can be nonzero value and so - we should add hours from day part to hour part to - keep valid time value. - */ - ltime->hour+= ltime->day*24; - ltime->day= 0; - } return (null_value= 0); } -bool Item_func_last_day::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) +bool Item_func_last_day::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - if (get_arg0_date(ltime, fuzzy_date & ~TIME_TIME_ONLY) || - (ltime->month == 0)) - return (null_value=1); + Datetime::Options opt(date_conv_mode_t(fuzzydate & ~TIME_TIME_ONLY), + time_round_mode_t(fuzzydate)); + Datetime *d= new(ltime) Datetime(thd, args[0], opt); + if ((null_value= (!d->is_valid_datetime() || ltime->month == 0))) + return true; uint month_idx= ltime->month-1; ltime->day= days_in_month[month_idx]; if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 7aacdec85e0..d9ab45ed46d 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -25,13 +25,9 @@ class MY_LOCALE; -enum date_time_format_types -{ - TIME_ONLY= 0, TIME_MICROSECOND, DATE_ONLY, DATE_TIME, DATE_TIME_MICROSECOND -}; - -bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval); +bool get_interval_value(THD *thd, Item *args, + interval_type int_type, INTERVAL *interval); class Item_long_func_date_field: public Item_long_func @@ -186,9 +182,9 @@ public: str->set(nr, collation.collation); return str; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return get_date_from_int(ltime, fuzzydate); + return get_date_from_int(thd, ltime, fuzzydate); } const char *func_name() const { return "month"; } const Type_handler *type_handler() const { return &type_handler_long; } @@ -459,9 +455,9 @@ public: { return (odbc_type ? "dayofweek" : "weekday"); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } const Type_handler *type_handler() const { return &type_handler_long; } bool fix_length_and_dec() @@ -516,7 +512,7 @@ public: } double real_op() { DBUG_ASSERT(0); return 0; } String *str_op(String *str) { DBUG_ASSERT(0); return 0; } - bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(0); return true; @@ -552,7 +548,8 @@ public: } bool fix_length_and_dec() { - fix_length_and_dec_generic(arg_count ? args[0]->datetime_precision() : 0); + fix_length_and_dec_generic(arg_count ? + args[0]->datetime_precision(current_thd) : 0); return FALSE; } longlong int_op(); @@ -576,7 +573,7 @@ public: } bool fix_length_and_dec() { - fix_length_and_dec_generic(args[0]->time_precision()); + fix_length_and_dec_generic(args[0]->time_precision(current_thd)); return FALSE; } longlong int_op(); @@ -586,66 +583,17 @@ public: }; -class Item_temporal_func: public Item_func -{ -public: - Item_temporal_func(THD *thd): Item_func(thd) {} - Item_temporal_func(THD *thd, Item *a): Item_func(thd, a) {} - Item_temporal_func(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {} - Item_temporal_func(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b, c) {} - String *val_str(String *str); - longlong val_int() { return val_int_from_date(); } - double val_real() { return val_real_from_date(); } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) { DBUG_ASSERT(0); return 1; } - my_decimal *val_decimal(my_decimal *decimal_value) - { return val_decimal_from_date(decimal_value); } -}; - - -/** - Abstract class for functions returning TIME, DATE, DATETIME or string values, - whose data type depends on parameters and is set at fix_fields time. -*/ -class Item_temporal_hybrid_func: public Item_hybrid_func -{ -protected: - String ascii_buf; // Conversion buffer -public: - Item_temporal_hybrid_func(THD *thd, Item *a, Item *b): - Item_hybrid_func(thd, a, b) {} - - longlong val_int() { return val_int_from_date(); } - double val_real() { return val_real_from_date(); } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date)= 0; - my_decimal *val_decimal(my_decimal *decimal_value) - { return val_decimal_from_date(decimal_value); } - - /** - Fix the returned timestamp to match field_type(), - which is important for val_str(). - */ - bool fix_temporal_type(MYSQL_TIME *ltime); - /** - Return string value in ASCII character set. - */ - String *val_str_ascii(String *str); - /** - Return string value in @@character_set_connection. - */ - String *val_str(String *str) - { - return val_str_from_val_str_ascii(str, &ascii_buf); - } -}; - - -class Item_datefunc :public Item_temporal_func +class Item_datefunc :public Item_func { public: - Item_datefunc(THD *thd): Item_temporal_func(thd) { } - Item_datefunc(THD *thd, Item *a): Item_temporal_func(thd, a) { } - Item_datefunc(THD *thd, Item *a, Item *b): Item_temporal_func(thd, a, b) { } + Item_datefunc(THD *thd): Item_func(thd) { } + Item_datefunc(THD *thd, Item *a): Item_func(thd, a) { } + Item_datefunc(THD *thd, Item *a, Item *b): Item_func(thd, a, b) { } const Type_handler *type_handler() const { return &type_handler_newdate; } + longlong val_int() { return Date(this).to_longlong(); } + double val_real() { return Date(this).to_double(); } + String *val_str(String *to) { return Date(this).to_string(to); } + my_decimal *val_decimal(my_decimal *to) { return Date(this).to_decimal(to); } bool fix_length_and_dec() { fix_attributes_date(); @@ -655,26 +603,34 @@ public: }; -class Item_timefunc :public Item_temporal_func +class Item_timefunc :public Item_func { public: - Item_timefunc(THD *thd): Item_temporal_func(thd) {} - Item_timefunc(THD *thd, Item *a): Item_temporal_func(thd, a) {} - Item_timefunc(THD *thd, Item *a, Item *b): Item_temporal_func(thd, a, b) {} - Item_timefunc(THD *thd, Item *a, Item *b, Item *c): - Item_temporal_func(thd, a, b ,c) {} + Item_timefunc(THD *thd): Item_func(thd) {} + Item_timefunc(THD *thd, Item *a): Item_func(thd, a) {} + Item_timefunc(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {} + Item_timefunc(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b ,c) {} const Type_handler *type_handler() const { return &type_handler_time2; } + longlong val_int() { return Time(this).to_longlong(); } + double val_real() { return Time(this).to_double(); } + String *val_str(String *to) { return Time(this).to_string(to, decimals); } + my_decimal *val_decimal(my_decimal *to) { return Time(this).to_decimal(to); } }; -class Item_datetimefunc :public Item_temporal_func +class Item_datetimefunc :public Item_func { public: - Item_datetimefunc(THD *thd): Item_temporal_func(thd) {} - Item_datetimefunc(THD *thd, Item *a): Item_temporal_func(thd, a) {} + Item_datetimefunc(THD *thd): Item_func(thd) {} + Item_datetimefunc(THD *thd, Item *a): Item_func(thd, a) {} + Item_datetimefunc(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {} Item_datetimefunc(THD *thd, Item *a, Item *b, Item *c): - Item_temporal_func(thd, a, b ,c) {} + Item_func(thd, a, b ,c) {} const Type_handler *type_handler() const { return &type_handler_datetime2; } + longlong val_int() { return Datetime(this).to_longlong(); } + double val_real() { return Datetime(this).to_double(); } + String *val_str(String *to) { return Datetime(this).to_string(to, decimals); } + my_decimal *val_decimal(my_decimal *to) { return Datetime(this).to_decimal(to); } }; @@ -689,7 +645,7 @@ public: { decimals= dec; } bool fix_fields(THD *, Item **); bool fix_length_and_dec() { fix_attributes_time(decimals); return FALSE; } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); /* Abstract method that defines which time zone is used for conversion. Converts time current time in my_time_t representation to broken-down @@ -734,7 +690,7 @@ class Item_func_curdate :public Item_datefunc MYSQL_TIME ltime; public: Item_func_curdate(THD *thd): Item_datefunc(thd), last_query_id(0) {} - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0; bool check_vcol_func_processor(void *arg) { @@ -777,7 +733,7 @@ public: bool fix_fields(THD *, Item **); bool fix_length_and_dec() { fix_attributes_datetime(decimals); return FALSE;} - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0; bool check_vcol_func_processor(void *arg) { @@ -832,7 +788,7 @@ public: bool const_item() const { return 0; } const char *func_name() const { return "sysdate"; } void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time); - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); table_map used_tables() const { return RAND_TABLE_BIT; } bool check_vcol_func_processor(void *arg) { @@ -852,7 +808,7 @@ class Item_func_from_days :public Item_datefunc public: Item_func_from_days(THD *thd, Item *a): Item_datefunc(thd, a) {} const char *func_name() const { return "from_days"; } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); bool check_partition_func_processor(void *int_arg) {return FALSE;} bool check_vcol_func_processor(void *arg) { return FALSE;} bool check_valid_arguments_processor(void *int_arg) @@ -917,7 +873,7 @@ class Item_func_from_unixtime :public Item_datetimefunc Item_func_from_unixtime(THD *thd, Item *a): Item_datetimefunc(thd, a) {} const char *func_name() const { return "from_unixtime"; } bool fix_length_and_dec(); - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); Item *get_copy(THD *thd) { return get_item_copy<Item_func_from_unixtime>(thd, this); } }; @@ -958,11 +914,11 @@ class Item_func_convert_tz :public Item_datetimefunc const char *func_name() const { return "convert_tz"; } bool fix_length_and_dec() { - fix_attributes_datetime(args[0]->datetime_precision()); + fix_attributes_datetime(args[0]->datetime_precision(current_thd)); maybe_null= true; return FALSE; } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); void cleanup(); Item *get_copy(THD *thd) { return get_item_copy<Item_func_convert_tz>(thd, this); } @@ -975,7 +931,7 @@ class Item_func_sec_to_time :public Item_timefunc { return args[0]->check_type_can_return_decimal(func_name()); } public: Item_func_sec_to_time(THD *thd, Item *item): Item_timefunc(thd, item) {} - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); bool fix_length_and_dec() { fix_attributes_time(args[0]->decimals); @@ -988,18 +944,17 @@ public: }; -class Item_date_add_interval :public Item_temporal_hybrid_func +class Item_date_add_interval :public Item_handled_func { public: const interval_type int_type; // keep it public const bool date_sub_interval; // keep it public Item_date_add_interval(THD *thd, Item *a, Item *b, interval_type type_arg, bool neg_arg): - Item_temporal_hybrid_func(thd, a, b),int_type(type_arg), + Item_handled_func(thd, a, b), int_type(type_arg), date_sub_interval(neg_arg) {} const char *func_name() const { return "date_add_interval"; } bool fix_length_and_dec(); - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); bool eq(const Item *item, bool binary_cmp) const; void print(String *str, enum_query_type query_type); enum precedence precedence() const { return ADDINTERVAL_PRECEDENCE; } @@ -1009,9 +964,17 @@ public: }; -class Item_extract :public Item_int_func +class Item_extract :public Item_int_func, + public Type_handler_hybrid_field_type { - bool date_value; + date_mode_t m_date_mode; + const Type_handler_int_result *handler_by_length(uint32 length, + uint32 threashold) + { + if (length >= threashold) + return &type_handler_longlong; + return &type_handler_long; + } void set_date_length(uint32 length) { /* @@ -1020,48 +983,34 @@ class Item_extract :public Item_int_func because all around the code we assume that max_length is sign inclusive. Another options is to set unsigned_flag to "true". */ - max_length= length; //QQ: see above - date_value= true; + set_handler(handler_by_length(max_length= length, 10)); // QQ: see above + m_date_mode= date_mode_t(0); + } + void set_day_length(uint32 length) + { + /* + Units starting with DAY can be negative: + EXTRACT(DAY FROM '-24:00:00') -> -1 + */ + set_handler(handler_by_length(max_length= length + 1/*sign*/, 11)); + m_date_mode= Temporal::Options(TIME_INTERVAL_DAY, current_thd); } void set_time_length(uint32 length) { - max_length= length + 1/*sign*/; - date_value= false; + set_handler(handler_by_length(max_length= length + 1/*sign*/, 11)); + m_date_mode= Temporal::Options(TIME_INTERVAL_hhmmssff, current_thd); } public: const interval_type int_type; // keep it public Item_extract(THD *thd, interval_type type_arg, Item *a): - Item_int_func(thd, a), int_type(type_arg) {} + Item_int_func(thd, a), + Type_handler_hybrid_field_type(&type_handler_longlong), + m_date_mode(date_mode_t(0)), + int_type(type_arg) + { } const Type_handler *type_handler() const { - switch (int_type) { - case INTERVAL_YEAR: - case INTERVAL_YEAR_MONTH: - case INTERVAL_QUARTER: - case INTERVAL_MONTH: - case INTERVAL_WEEK: - case INTERVAL_DAY: - case INTERVAL_DAY_HOUR: - case INTERVAL_DAY_MINUTE: - case INTERVAL_DAY_SECOND: - case INTERVAL_HOUR: - case INTERVAL_HOUR_MINUTE: - case INTERVAL_HOUR_SECOND: - case INTERVAL_MINUTE: - case INTERVAL_MINUTE_SECOND: - case INTERVAL_SECOND: - case INTERVAL_MICROSECOND: - case INTERVAL_SECOND_MICROSECOND: - return &type_handler_long; - case INTERVAL_DAY_MICROSECOND: - case INTERVAL_HOUR_MICROSECOND: - case INTERVAL_MINUTE_MICROSECOND: - return &type_handler_longlong; - case INTERVAL_LAST: - break; - } - DBUG_ASSERT(0); - return &type_handler_longlong; + return Type_handler_hybrid_field_type::type_handler(); } longlong val_int(); enum Functype functype() const { return EXTRACT_FUNC; } @@ -1131,6 +1080,9 @@ class Item_char_typecast :public Item_str_func void check_truncation_with_warn(String *src, size_t dstlen); void fix_length_and_dec_internal(CHARSET_INFO *fromcs); public: + // Methods used by ColumnStore + uint get_cast_length() const { return cast_length; } +public: Item_char_typecast(THD *thd, Item *a, uint length_arg, CHARSET_INFO *cs_arg): Item_str_func(thd, a), cast_length(length_arg), cast_cs(cs_arg), m_suppress_warning_to_error_escalation(false) {} @@ -1157,22 +1109,34 @@ public: }; -class Item_temporal_typecast: public Item_temporal_func +class Item_interval_DDhhmmssff_typecast :public Item_char_typecast { + uint m_fsp; public: - Item_temporal_typecast(THD *thd, Item *a): Item_temporal_func(thd, a) {} - virtual const char *cast_type() const = 0; - void print(String *str, enum_query_type query_type); + Item_interval_DDhhmmssff_typecast(THD *thd, Item *a, uint fsp) + :Item_char_typecast(thd, a,Interval_DDhhmmssff::max_char_length(fsp), + &my_charset_latin1), + m_fsp(fsp) + { } + String *val_str(String *to) + { + Interval_DDhhmmssff it(current_thd, args[0], m_fsp); + null_value= !it.is_valid_interval_DDhhmmssff(); + return it.to_string(to, m_fsp); + } }; -class Item_date_typecast :public Item_temporal_typecast + +class Item_date_typecast :public Item_datefunc { public: - Item_date_typecast(THD *thd, Item *a): Item_temporal_typecast(thd, a) {} + Item_date_typecast(THD *thd, Item *a): Item_datefunc(thd, a) {} const char *func_name() const { return "cast_as_date"; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); - const char *cast_type() const { return "date"; } - const Type_handler *type_handler() const { return &type_handler_newdate; } + void print(String *str, enum_query_type query_type) + { + print_cast_temporal(str, query_type); + } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool fix_length_and_dec() { return args[0]->type_handler()->Item_date_typecast_fix_length_and_dec(this); @@ -1182,15 +1146,17 @@ public: }; -class Item_time_typecast :public Item_temporal_typecast +class Item_time_typecast :public Item_timefunc { public: Item_time_typecast(THD *thd, Item *a, uint dec_arg): - Item_temporal_typecast(thd, a) { decimals= dec_arg; } + Item_timefunc(thd, a) { decimals= dec_arg; } const char *func_name() const { return "cast_as_time"; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); - const char *cast_type() const { return "time"; } - const Type_handler *type_handler() const { return &type_handler_time2; } + void print(String *str, enum_query_type query_type) + { + print_cast_temporal(str, query_type); + } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool fix_length_and_dec() { return args[0]->type_handler()-> @@ -1201,15 +1167,17 @@ public: }; -class Item_datetime_typecast :public Item_temporal_typecast +class Item_datetime_typecast :public Item_datetimefunc { public: Item_datetime_typecast(THD *thd, Item *a, uint dec_arg): - Item_temporal_typecast(thd, a) { decimals= dec_arg; } + Item_datetimefunc(thd, a) { decimals= dec_arg; } const char *func_name() const { return "cast_as_datetime"; } - const char *cast_type() const { return "datetime"; } - const Type_handler *type_handler() const { return &type_handler_datetime2; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); + void print(String *str, enum_query_type query_type) + { + print_cast_temporal(str, query_type); + } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); bool fix_length_and_dec() { return args[0]->type_handler()-> @@ -1228,31 +1196,76 @@ public: Item_func_makedate(THD *thd, Item *a, Item *b): Item_datefunc(thd, a, b) {} const char *func_name() const { return "makedate"; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); Item *get_copy(THD *thd) { return get_item_copy<Item_func_makedate>(thd, this); } }; -class Item_func_add_time :public Item_temporal_hybrid_func +class Item_func_timestamp :public Item_datetimefunc { - const bool is_date; - int sign; - + bool check_arguments() const + { + return args[0]->check_type_can_return_date(func_name()) || + args[1]->check_type_can_return_time(func_name()); + } public: - Item_func_add_time(THD *thd, Item *a, Item *b, bool type_arg, bool neg_arg): - Item_temporal_hybrid_func(thd, a, b), is_date(type_arg) - { sign= neg_arg ? -1 : 1; } - bool fix_length_and_dec(); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); - const char *func_name() const + Item_func_timestamp(THD *thd, Item *a, Item *b) + :Item_datetimefunc(thd, a, b) + { } + const char *func_name() const { return "timestamp"; } + bool fix_length_and_dec() { - return is_date ? "timestamp" : sign > 0 ? "addtime" : "subtime"; + THD *thd= current_thd; + uint dec0= args[0]->datetime_precision(thd); + uint dec1= Interval_DDhhmmssff::fsp(thd, args[1]); + fix_attributes_datetime(MY_MAX(dec0, dec1)); + maybe_null= true; + return false; + } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { + Datetime dt(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd)); + if (!dt.is_valid_datetime()) + return null_value= true; + Interval_DDhhmmssff it(thd, args[1]); + if (!it.is_valid_interval_DDhhmmssff()) + return null_value= true; + return (null_value= Sec6_add(dt.get_mysql_time(), it.get_mysql_time(), 1). + to_datetime(ltime)); } Item *get_copy(THD *thd) + { return get_item_copy<Item_func_timestamp>(thd, this); } +}; + + +/** + ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a + time/datetime value + + t: time_or_datetime_expression + a: time_expression + + Result: Time value or datetime value +*/ + +class Item_func_add_time :public Item_handled_func +{ + int sign; +public: + // Methods used by ColumnStore + int get_sign() const { return sign; } +public: + Item_func_add_time(THD *thd, Item *a, Item *b, bool neg_arg) + :Item_handled_func(thd, a, b), sign(neg_arg ? -1 : 1) + { } + bool fix_length_and_dec(); + const char *func_name() const { return sign > 0 ? "addtime" : "subtime"; } + Item *get_copy(THD *thd) { return get_item_copy<Item_func_add_time>(thd, this); } }; + class Item_func_timediff :public Item_timefunc { bool check_arguments() const @@ -1262,12 +1275,14 @@ public: const char *func_name() const { return "timediff"; } bool fix_length_and_dec() { - uint dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision()); + THD *thd= current_thd; + uint dec= MY_MAX(args[0]->time_precision(thd), + args[1]->time_precision(thd)); fix_attributes_time(dec); maybe_null= true; return FALSE; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); Item *get_copy(THD *thd) { return get_item_copy<Item_func_timediff>(thd, this); } }; @@ -1290,7 +1305,7 @@ public: return FALSE; } const char *func_name() const { return "maketime"; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); Item *get_copy(THD *thd) { return get_item_copy<Item_func_maketime>(thd, this); } }; @@ -1326,6 +1341,9 @@ class Item_func_timestamp_diff :public Item_longlong_func { return check_argument_types_can_return_date(0, arg_count); } const interval_type int_type; public: + // Methods used by ColumnStore + interval_type get_int_type() const { return int_type; }; +public: Item_func_timestamp_diff(THD *thd, Item *a, Item *b, interval_type type_arg): Item_longlong_func(thd, a, b), int_type(type_arg) {} const char *func_name() const { return "timestampdiff"; } @@ -1369,19 +1387,19 @@ public: }; -class Item_func_str_to_date :public Item_temporal_hybrid_func +class Item_func_str_to_date :public Item_handled_func { - timestamp_type cached_timestamp_type; bool const_item; String subject_converter; String format_converter; CHARSET_INFO *internal_charset; public: Item_func_str_to_date(THD *thd, Item *a, Item *b): - Item_temporal_hybrid_func(thd, a, b), const_item(false), + Item_handled_func(thd, a, b), const_item(false), internal_charset(NULL) {} - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); + bool get_date_common(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate, + timestamp_type); const char *func_name() const { return "str_to_date"; } bool fix_length_and_dec(); Item *get_copy(THD *thd) @@ -1396,9 +1414,365 @@ class Item_func_last_day :public Item_datefunc public: Item_func_last_day(THD *thd, Item *a): Item_datefunc(thd, a) {} const char *func_name() const { return "last_day"; } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); Item *get_copy(THD *thd) { return get_item_copy<Item_func_last_day>(thd, this); } }; + +/*****************************************************************************/ + +class Func_handler_date_add_interval +{ +protected: + static uint interval_dec(const Item *item, interval_type int_type) + { + if (int_type == INTERVAL_MICROSECOND || + (int_type >= INTERVAL_DAY_MICROSECOND && + int_type <= INTERVAL_SECOND_MICROSECOND)) + return TIME_SECOND_PART_DIGITS; + if (int_type == INTERVAL_SECOND && item->decimals > 0) + return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS); + return 0; + } + interval_type int_type(const Item_handled_func *item) const + { + return static_cast<const Item_date_add_interval*>(item)->int_type; + } + bool sub(const Item_handled_func *item) const + { + return static_cast<const Item_date_add_interval*>(item)->date_sub_interval; + } + bool add(THD *thd, Item *item, interval_type type, bool sub, MYSQL_TIME *to) const + { + INTERVAL interval; + if (get_interval_value(thd, item, type, &interval)) + return true; + if (sub) + interval.neg = !interval.neg; + return date_add_interval(thd, to, type, interval); + } +}; + + +class Func_handler_date_add_interval_datetime: + public Item_handled_func::Handler_datetime, + public Func_handler_date_add_interval +{ +public: + bool fix_length_and_dec(Item_handled_func *item) const + { + uint dec= MY_MAX(item->arguments()[0]->datetime_precision(current_thd), + interval_dec(item->arguments()[1], int_type(item))); + item->fix_attributes_datetime(dec); + return false; + } + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + Datetime::Options opt(TIME_CONV_NONE, thd); + Datetime dt(thd, item->arguments()[0], opt); + if (!dt.is_valid_datetime() || + dt.check_date_with_warn(thd, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) + return (item->null_value= true); + dt.copy_to_mysql_time(to); + return (item->null_value= add(thd, item->arguments()[1], + int_type(item), sub(item), to)); + } +}; + + +class Func_handler_date_add_interval_datetime_arg0_time: + public Func_handler_date_add_interval_datetime +{ +public: + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const; +}; + + +class Func_handler_date_add_interval_date: + public Item_handled_func::Handler_date, + public Func_handler_date_add_interval +{ +public: + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + /* + The first argument is known to be of the DATE data type (not DATETIME). + We don't need rounding here. + */ + Date d(thd, item->arguments()[0], TIME_CONV_NONE); + if (!d.is_valid_date() || + d.check_date_with_warn(thd, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE)) + return (item->null_value= true); + d.copy_to_mysql_time(to); + return (item->null_value= add(thd, item->arguments()[1], + int_type(item), sub(item), to)); + } +}; + + +class Func_handler_date_add_interval_time: + public Item_handled_func::Handler_time, + public Func_handler_date_add_interval +{ +public: + bool fix_length_and_dec(Item_handled_func *item) const + { + uint dec= MY_MAX(item->arguments()[0]->time_precision(current_thd), + interval_dec(item->arguments()[1], int_type(item))); + item->fix_attributes_time(dec); + return false; + } + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + Time t(thd, item->arguments()[0]); + if (!t.is_valid_time()) + return (item->null_value= true); + t.copy_to_mysql_time(to); + return (item->null_value= add(thd, item->arguments()[1], + int_type(item), sub(item), to)); + } +}; + + +class Func_handler_date_add_interval_string: + public Item_handled_func::Handler_temporal_string, + public Func_handler_date_add_interval +{ +public: + bool fix_length_and_dec(Item_handled_func *item) const + { + uint dec= MY_MAX(item->arguments()[0]->datetime_precision(current_thd), + interval_dec(item->arguments()[1], int_type(item))); + item->collation.set(item->default_charset(), + DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); + item->fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec); + return false; + } + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + if (item->arguments()[0]-> + get_date(thd, to, Datetime::Options(TIME_CONV_NONE, thd)) || + (to->time_type != MYSQL_TIMESTAMP_TIME && + check_date_with_warn(thd, to, TIME_NO_ZEROS, MYSQL_TIMESTAMP_ERROR))) + return (item->null_value= true); + return (item->null_value= add(thd, item->arguments()[1], + int_type(item), sub(item), to)); + } +}; + + +class Func_handler_sign +{ +protected: + int m_sign; + Func_handler_sign(int sign) :m_sign(sign) { } +}; + + +class Func_handler_add_time_datetime: + public Item_handled_func::Handler_datetime, + public Func_handler_sign +{ +public: + Func_handler_add_time_datetime(int sign) + :Func_handler_sign(sign) + { } + bool fix_length_and_dec(Item_handled_func *item) const + { + THD *thd= current_thd; + uint dec0= item->arguments()[0]->datetime_precision(thd); + uint dec1= Interval_DDhhmmssff::fsp(thd, item->arguments()[1]); + item->fix_attributes_datetime(MY_MAX(dec0, dec1)); + return false; + } + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + DBUG_ASSERT(item->is_fixed()); + Datetime::Options opt(TIME_CONV_NONE, thd); + Datetime dt(thd, item->arguments()[0], opt); + if (!dt.is_valid_datetime()) + return item->null_value= true; + Interval_DDhhmmssff it(thd, item->arguments()[1]); + if (!it.is_valid_interval_DDhhmmssff()) + return item->null_value= true; + return (item->null_value= (Sec6_add(dt.get_mysql_time(), + it.get_mysql_time(), m_sign). + to_datetime(to))); + } +}; + + +class Func_handler_add_time_time: + public Item_handled_func::Handler_time, + public Func_handler_sign +{ +public: + Func_handler_add_time_time(int sign) + :Func_handler_sign(sign) + { } + bool fix_length_and_dec(Item_handled_func *item) const + { + THD *thd= current_thd; + uint dec0= item->arguments()[0]->time_precision(thd); + uint dec1= Interval_DDhhmmssff::fsp(thd, item->arguments()[1]); + item->fix_attributes_time(MY_MAX(dec0, dec1)); + return false; + } + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + DBUG_ASSERT(item->is_fixed()); + Time t(thd, item->arguments()[0]); + if (!t.is_valid_time()) + return item->null_value= true; + Interval_DDhhmmssff i(thd, item->arguments()[1]); + if (!i.is_valid_interval_DDhhmmssff()) + return item->null_value= true; + return (item->null_value= (Sec6_add(t.get_mysql_time(), + i.get_mysql_time(), m_sign). + to_time(thd, to, item->decimals))); + } +}; + + +class Func_handler_add_time_string: + public Item_handled_func::Handler_temporal_string, + public Func_handler_sign +{ +public: + Func_handler_add_time_string(int sign) + :Func_handler_sign(sign) + { } + bool fix_length_and_dec(Item_handled_func *item) const + { + uint dec0= item->arguments()[0]->decimals; + uint dec1= Interval_DDhhmmssff::fsp(current_thd, item->arguments()[1]); + uint dec= MY_MAX(dec0, dec1); + item->collation.set(item->default_charset(), + DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); + item->fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec); + return false; + } + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + DBUG_ASSERT(item->is_fixed()); + // Detect a proper timestamp type based on the argument values + Temporal_hybrid l_time1(thd, item->arguments()[0], + Temporal::Options(TIME_TIME_ONLY, thd)); + if (!l_time1.is_valid_temporal()) + return (item->null_value= true); + Interval_DDhhmmssff l_time2(thd, item->arguments()[1]); + if (!l_time2.is_valid_interval_DDhhmmssff()) + return (item->null_value= true); + Sec6_add add(l_time1.get_mysql_time(), l_time2.get_mysql_time(), m_sign); + return (item->null_value= (l_time1.get_mysql_time()->time_type == + MYSQL_TIMESTAMP_TIME ? + add.to_time(thd, to, item->decimals) : + add.to_datetime(to))); + } +}; + + +class Func_handler_str_to_date_datetime_sec: + public Item_handled_func::Handler_datetime +{ +public: + bool fix_length_and_dec(Item_handled_func *item) const + { + item->fix_attributes_datetime(0); + return false; + } + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + return static_cast<Item_func_str_to_date*>(item)-> + get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_DATETIME); + } +}; + + +class Func_handler_str_to_date_datetime_usec: + public Item_handled_func::Handler_datetime +{ +public: + bool fix_length_and_dec(Item_handled_func *item) const + { + item->fix_attributes_datetime(TIME_SECOND_PART_DIGITS); + return false; + } + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + return static_cast<Item_func_str_to_date*>(item)-> + get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_DATETIME); + } +}; + + +class Func_handler_str_to_date_date: public Item_handled_func::Handler_date +{ +public: + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + return static_cast<Item_func_str_to_date*>(item)-> + get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_DATE); + } +}; + + +class Func_handler_str_to_date_time: public Item_handled_func::Handler_time +{ +public: + bool get_date(THD *thd, Item_handled_func *item, + MYSQL_TIME *to, date_mode_t fuzzy) const + { + if (static_cast<Item_func_str_to_date*>(item)-> + get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_TIME)) + return true; + if (to->day) + { + /* + Day part for time type can be nonzero value and so + we should add hours from day part to hour part to + keep valid time value. + */ + to->hour+= to->day * 24; + to->day= 0; + } + return false; + } +}; + + +class Func_handler_str_to_date_time_sec: public Func_handler_str_to_date_time +{ +public: + bool fix_length_and_dec(Item_handled_func *item) const + { + item->fix_attributes_time(0); + return false; + } +}; + + +class Func_handler_str_to_date_time_usec: public Func_handler_str_to_date_time +{ +public: + bool fix_length_and_dec(Item_handled_func *item) const + { + item->fix_attributes_time(TIME_SECOND_PART_DIGITS); + return false; + } +}; + + #endif /* ITEM_TIMEFUNC_INCLUDED */ diff --git a/sql/item_vers.cc b/sql/item_vers.cc index d7361f687f9..c4bb734096f 100644 --- a/sql/item_vers.cc +++ b/sql/item_vers.cc @@ -37,9 +37,8 @@ Item_func_trt_ts::Item_func_trt_ts(THD *thd, Item* a, TR_table::field_id_t _trt_ bool -Item_func_trt_ts::get_date(MYSQL_TIME *res, ulonglong fuzzy_date) +Item_func_trt_ts::get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) { - THD *thd= current_thd; // can it differ from constructor's? DBUG_ASSERT(thd); DBUG_ASSERT(args[0]); if (args[0]->result_type() != INT_RESULT) @@ -67,7 +66,7 @@ Item_func_trt_ts::get_date(MYSQL_TIME *res, ulonglong fuzzy_date) return true; } - return trt[trt_field]->get_date(res, fuzzy_date); + return trt[trt_field]->get_date(res, fuzzydate); } @@ -143,7 +142,9 @@ Item_func_trt_id::val_int() else { MYSQL_TIME commit_ts; - if (args[0]->get_date(&commit_ts, 0)) + THD *thd= current_thd; + Datetime::Options opt(TIME_CONV_NONE, thd); + if (args[0]->get_date(thd, &commit_ts, opt)) { null_value= true; return 0; diff --git a/sql/item_vers.h b/sql/item_vers.h index 8b9c0e6056c..a42b5a033f2 100644 --- a/sql/item_vers.h +++ b/sql/item_vers.h @@ -35,7 +35,7 @@ public: } return "trt_commit_ts"; } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); Item *get_copy(THD *thd) { return get_item_copy<Item_func_trt_ts>(thd, this); } bool fix_length_and_dec() diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc index 2db396d3065..aa2c7756ab7 100644 --- a/sql/item_windowfunc.cc +++ b/sql/item_windowfunc.cc @@ -120,7 +120,6 @@ Item_window_func::fix_fields(THD *thd, Item **ref) const_item_cache= false; with_window_func= true; - with_sum_func= false; if (fix_length_and_dec()) return TRUE; @@ -440,12 +439,12 @@ Item_sum_hybrid_simple::val_str(String *str) return retval; } -bool Item_sum_hybrid_simple::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) +bool Item_sum_hybrid_simple::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(fixed == 1); if (null_value) return true; - bool retval= value->get_date(ltime, fuzzydate); + bool retval= value->get_date(thd, ltime, fuzzydate); if ((null_value= value->null_value)) DBUG_ASSERT(retval == true); return retval; @@ -514,11 +513,11 @@ void Item_sum_hybrid_simple::reset_field() } case DECIMAL_RESULT: { - my_decimal value_buff, *arg_dec= args[0]->val_decimal(&value_buff); + VDec arg_dec(args[0]); if (maybe_null) { - if (args[0]->null_value) + if (arg_dec.is_null()) result_field->set_null(); else result_field->set_notnull(); @@ -527,9 +526,7 @@ void Item_sum_hybrid_simple::reset_field() We must store zero in the field as we will use the field value in add() */ - if (!arg_dec) // Null - arg_dec= &decimal_zero; - result_field->store_decimal(arg_dec); + result_field->store_decimal(arg_dec.ptr_or(&decimal_zero)); break; } case ROW_RESULT: diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h index 9ba60c3956d..4c704808fe4 100644 --- a/sql/item_windowfunc.h +++ b/sql/item_windowfunc.h @@ -319,7 +319,7 @@ class Item_sum_hybrid_simple : public Item_sum, my_decimal *val_decimal(my_decimal *); void reset_field(); String *val_str(String *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); const Type_handler *type_handler() const { return Type_handler_hybrid_field_type::type_handler(); } void update_field(); @@ -1273,7 +1273,7 @@ public: return res; } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { bool res; if (force_return_blank) @@ -1290,7 +1290,7 @@ public: } else { - res= window_func()->get_date(ltime, fuzzydate); + res= window_func()->get_date(thd, ltime, fuzzydate); null_value= window_func()->null_value; } return res; diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 63734ecf9ac..146c5aa57fe 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -29,10 +29,8 @@ /* TODO: future development directions: - 1. add real constants for XPATH_NODESET_CMP and XPATH_NODESET - into enum Type in item.h. - 2. add nodeset_to_nodeset_comparator - 3. add lacking functions: + 1. add nodeset_to_nodeset_comparator + 2. add lacking functions: - name() - lang() - string() @@ -44,7 +42,7 @@ - substring-after() - normalize-space() - substring-before() - 4. add lacking axis: + 3. add lacking axis: - following-sibling - following, - preceding-sibling @@ -151,6 +149,9 @@ public: }; +static Type_handler_long_blob type_handler_xpath_nodeset; + + /* Common features of the functions returning a node set. */ @@ -181,16 +182,29 @@ public: void prepare(String *nodeset) { prepare_nodes(); - String *res= args[0]->val_nodeset(&tmp_value); + String *res= args[0]->val_raw(&tmp_value); fltbeg= (MY_XPATH_FLT*) res->ptr(); fltend= (MY_XPATH_FLT*) (res->ptr() + res->length()); nodeset->length(0); } - enum Type type() const { return XPATH_NODESET; } + const Type_handler *type_handler() const + { + return &type_handler_xpath_nodeset; + } + const Type_handler *fixed_type_handler() const + { + return &type_handler_xpath_nodeset; + } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + DBUG_ASSERT(0); + return NULL; + } String *val_str(String *str) { prepare_nodes(); - String *res= val_nodeset(&tmp2_value); + String *res= val_raw(&tmp2_value); fltbeg= (MY_XPATH_FLT*) res->ptr(); fltend= (MY_XPATH_FLT*) (res->ptr() + res->length()); String active; @@ -247,7 +261,7 @@ public: Item_nodeset_func_rootelement(THD *thd, String *pxml): Item_nodeset_func(thd, pxml) {} const char *func_name() const { return "xpath_rootelement"; } - String *val_nodeset(String *nodeset); + String *val_raw(String *nodeset); Item *get_copy(THD *thd) { return get_item_copy<Item_nodeset_func_rootelement>(thd, this); } }; @@ -260,7 +274,7 @@ public: Item_nodeset_func_union(THD *thd, Item *a, Item *b, String *pxml): Item_nodeset_func(thd, a, b, pxml) {} const char *func_name() const { return "xpath_union"; } - String *val_nodeset(String *nodeset); + String *val_raw(String *nodeset); Item *get_copy(THD *thd) { return get_item_copy<Item_nodeset_func_union>(thd, this); } }; @@ -294,7 +308,7 @@ public: String *pxml): Item_nodeset_func_axisbyname(thd, a, n_arg, l_arg, pxml) {} const char *func_name() const { return "xpath_selfbyname"; } - String *val_nodeset(String *nodeset); + String *val_raw(String *nodeset); Item *get_copy(THD *thd) { return get_item_copy<Item_nodeset_func_selfbyname>(thd, this); } }; @@ -308,7 +322,7 @@ public: String *pxml): Item_nodeset_func_axisbyname(thd, a, n_arg, l_arg, pxml) {} const char *func_name() const { return "xpath_childbyname"; } - String *val_nodeset(String *nodeset); + String *val_raw(String *nodeset); Item *get_copy(THD *thd) { return get_item_copy<Item_nodeset_func_childbyname>(thd, this); } }; @@ -324,7 +338,7 @@ public: Item_nodeset_func_axisbyname(thd, a, n_arg, l_arg, pxml), need_self(need_self_arg) {} const char *func_name() const { return "xpath_descendantbyname"; } - String *val_nodeset(String *nodeset); + String *val_raw(String *nodeset); Item *get_copy(THD *thd) { return get_item_copy<Item_nodeset_func_descendantbyname>(thd, this); } }; @@ -340,7 +354,7 @@ public: Item_nodeset_func_axisbyname(thd, a, n_arg, l_arg, pxml), need_self(need_self_arg) {} const char *func_name() const { return "xpath_ancestorbyname"; } - String *val_nodeset(String *nodeset); + String *val_raw(String *nodeset); Item *get_copy(THD *thd) { return get_item_copy<Item_nodeset_func_ancestorbyname>(thd, this); } }; @@ -354,7 +368,7 @@ public: String *pxml): Item_nodeset_func_axisbyname(thd, a, n_arg, l_arg, pxml) {} const char *func_name() const { return "xpath_parentbyname"; } - String *val_nodeset(String *nodeset); + String *val_raw(String *nodeset); Item *get_copy(THD *thd) { return get_item_copy<Item_nodeset_func_parentbyname>(thd, this); } }; @@ -368,7 +382,7 @@ public: uint l_arg, String *pxml): Item_nodeset_func_axisbyname(thd, a, n_arg, l_arg, pxml) {} const char *func_name() const { return "xpath_attributebyname"; } - String *val_nodeset(String *nodeset); + String *val_raw(String *nodeset); Item *get_copy(THD *thd) { return get_item_copy<Item_nodeset_func_attributebyname>(thd, this); } }; @@ -385,7 +399,7 @@ public: Item_nodeset_func_predicate(THD *thd, Item *a, Item *b, String *pxml): Item_nodeset_func(thd, a, b, pxml) {} const char *func_name() const { return "xpath_predicate"; } - String *val_nodeset(String *nodeset); + String *val_raw(String *nodeset); Item *get_copy(THD *thd) { return get_item_copy<Item_nodeset_func_predicate>(thd, this); } }; @@ -398,7 +412,7 @@ public: Item_nodeset_func_elementbyindex(THD *thd, Item *a, Item *b, String *pxml): Item_nodeset_func(thd, a, b, pxml) { } const char *func_name() const { return "xpath_elementbyindex"; } - String *val_nodeset(String *nodeset); + String *val_raw(String *nodeset); Item *get_copy(THD *thd) { return get_item_copy<Item_nodeset_func_elementbyindex>(thd, this); } }; @@ -420,9 +434,9 @@ public: const char *func_name() const { return "xpath_cast_bool"; } longlong val_int() { - if (args[0]->type() == XPATH_NODESET) + if (args[0]->fixed_type_handler() == &type_handler_xpath_nodeset) { - String *flt= args[0]->val_nodeset(&tmp_value); + String *flt= args[0]->val_raw(&tmp_value); return flt->length() == sizeof(MY_XPATH_FLT) ? 1 : 0; } return args[0]->val_real() ? 1 : 0; @@ -455,7 +469,7 @@ public: String *string_cache; Item_nodeset_context_cache(THD *thd, String *str_arg, String *pxml): Item_nodeset_func(thd, pxml), string_cache(str_arg) { } - String *val_nodeset(String *res) + String *val_raw(String *res) { return string_cache; } bool fix_length_and_dec() { max_length= MAX_BLOB_WIDTH;; return FALSE; } Item *get_copy(THD *thd) @@ -474,7 +488,7 @@ public: bool fix_length_and_dec() { max_length=10; return FALSE; } longlong val_int() { - String *flt= args[0]->val_nodeset(&tmp_value); + String *flt= args[0]->val_raw(&tmp_value); if (flt->length() == sizeof(MY_XPATH_FLT)) return ((MY_XPATH_FLT*)flt->ptr())->pos + 1; return 0; @@ -496,7 +510,7 @@ public: longlong val_int() { uint predicate_supplied_context_size; - String *res= args[0]->val_nodeset(&tmp_value); + String *res= args[0]->val_raw(&tmp_value); if (res->length() == sizeof(MY_XPATH_FLT) && (predicate_supplied_context_size= ((MY_XPATH_FLT*)res->ptr())->size)) return predicate_supplied_context_size; @@ -519,7 +533,7 @@ public: double val_real() { double sum= 0; - String *res= args[0]->val_nodeset(&tmp_value); + String *res= args[0]->val_raw(&tmp_value); MY_XPATH_FLT *fltbeg= (MY_XPATH_FLT*) res->ptr(); MY_XPATH_FLT *fltend= (MY_XPATH_FLT*) (res->ptr() + res->length()); uint numnodes= pxml->length() / sizeof(MY_XML_NODE); @@ -587,19 +601,23 @@ public: Item_nodeset_to_const_comparator(THD *thd, Item *nodeset, Item *cmpfunc, String *p): Item_bool_func(thd, nodeset, cmpfunc), pxml(p) {} - enum Type type() const { return XPATH_NODESET_CMP; }; const char *func_name() const { return "xpath_nodeset_to_const_comparator"; } bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(func_name(), arg, VCOL_IMPOSSIBLE); } - + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + DBUG_ASSERT(0); + return NULL; + } longlong val_int() { Item_func *comp= (Item_func*)args[1]; Item_string_xml_non_const *fake= (Item_string_xml_non_const*)(comp->arguments()[0]); - String *res= args[0]->val_nodeset(&tmp_nodeset); + String *res= args[0]->val_raw(&tmp_nodeset); MY_XPATH_FLT *fltbeg= (MY_XPATH_FLT*) res->ptr(); MY_XPATH_FLT *fltend= (MY_XPATH_FLT*) (res->ptr() + res->length()); MY_XML_NODE *nodebeg= (MY_XML_NODE*) pxml->ptr(); @@ -630,7 +648,7 @@ public: }; -String *Item_nodeset_func_rootelement::val_nodeset(String *nodeset) +String *Item_nodeset_func_rootelement::val_raw(String *nodeset) { nodeset->length(0); ((XPathFilter*)nodeset)->append_element(0, 0); @@ -638,11 +656,11 @@ String *Item_nodeset_func_rootelement::val_nodeset(String *nodeset) } -String * Item_nodeset_func_union::val_nodeset(String *nodeset) +String * Item_nodeset_func_union::val_raw(String *nodeset) { uint num_nodes= pxml->length() / sizeof(MY_XML_NODE); - String set0, *s0= args[0]->val_nodeset(&set0); - String set1, *s1= args[1]->val_nodeset(&set1); + String set0, *s0= args[0]->val_raw(&set0); + String set1, *s1= args[1]->val_raw(&set1); String both_str; both_str.alloc(num_nodes); char *both= (char*) both_str.ptr(); @@ -669,7 +687,7 @@ String * Item_nodeset_func_union::val_nodeset(String *nodeset) } -String *Item_nodeset_func_selfbyname::val_nodeset(String *nodeset) +String *Item_nodeset_func_selfbyname::val_raw(String *nodeset) { prepare(nodeset); for (MY_XPATH_FLT *flt= fltbeg; flt < fltend; flt++) @@ -683,7 +701,7 @@ String *Item_nodeset_func_selfbyname::val_nodeset(String *nodeset) } -String *Item_nodeset_func_childbyname::val_nodeset(String *nodeset) +String *Item_nodeset_func_childbyname::val_raw(String *nodeset) { prepare(nodeset); for (MY_XPATH_FLT *flt= fltbeg; flt < fltend; flt++) @@ -704,7 +722,7 @@ String *Item_nodeset_func_childbyname::val_nodeset(String *nodeset) } -String *Item_nodeset_func_descendantbyname::val_nodeset(String *nodeset) +String *Item_nodeset_func_descendantbyname::val_raw(String *nodeset) { prepare(nodeset); for (MY_XPATH_FLT *flt= fltbeg; flt < fltend; flt++) @@ -726,7 +744,7 @@ String *Item_nodeset_func_descendantbyname::val_nodeset(String *nodeset) } -String *Item_nodeset_func_ancestorbyname::val_nodeset(String *nodeset) +String *Item_nodeset_func_ancestorbyname::val_raw(String *nodeset) { char *active; String active_str; @@ -768,7 +786,7 @@ String *Item_nodeset_func_ancestorbyname::val_nodeset(String *nodeset) } -String *Item_nodeset_func_parentbyname::val_nodeset(String *nodeset) +String *Item_nodeset_func_parentbyname::val_raw(String *nodeset) { char *active; String active_str; @@ -791,7 +809,7 @@ String *Item_nodeset_func_parentbyname::val_nodeset(String *nodeset) } -String *Item_nodeset_func_attributebyname::val_nodeset(String *nodeset) +String *Item_nodeset_func_attributebyname::val_raw(String *nodeset) { prepare(nodeset); for (MY_XPATH_FLT *flt= fltbeg; flt < fltend; flt++) @@ -812,7 +830,7 @@ String *Item_nodeset_func_attributebyname::val_nodeset(String *nodeset) } -String *Item_nodeset_func_predicate::val_nodeset(String *str) +String *Item_nodeset_func_predicate::val_raw(String *str) { Item_nodeset_func *nodeset_func= (Item_nodeset_func*) args[0]; Item_func *comp_func= (Item_func*)args[1]; @@ -832,7 +850,7 @@ String *Item_nodeset_func_predicate::val_nodeset(String *str) } -String *Item_nodeset_func_elementbyindex::val_nodeset(String *nodeset) +String *Item_nodeset_func_elementbyindex::val_raw(String *nodeset) { Item_nodeset_func *nodeset_func= (Item_nodeset_func*) args[0]; prepare(nodeset); @@ -845,7 +863,9 @@ String *Item_nodeset_func_elementbyindex::val_nodeset(String *nodeset) flt->pos, size); int index= (int) (args[1]->val_int()) - 1; - if (index >= 0 && (flt->pos == (uint) index || args[1]->is_bool_type())) + if (index >= 0 && + (flt->pos == (uint) index || + (args[1]->type_handler()->is_bool_type()))) ((XPathFilter*)nodeset)->append_element(flt->num, pos++); } return nodeset; @@ -858,7 +878,7 @@ String *Item_nodeset_func_elementbyindex::val_nodeset(String *nodeset) */ static Item* nodeset2bool(MY_XPATH *xpath, Item *item) { - if (item->type() == Item::XPATH_NODESET) + if (item->fixed_type_handler() == &type_handler_xpath_nodeset) return new (xpath->thd->mem_root) Item_xpath_cast_bool(xpath->thd, item, xpath->pxml); return item; @@ -988,13 +1008,13 @@ static Item *create_comparator(MY_XPATH *xpath, int oper, MY_XPATH_LEX *context, Item *a, Item *b) { - if (a->type() != Item::XPATH_NODESET && - b->type() != Item::XPATH_NODESET) + if (a->fixed_type_handler() != &type_handler_xpath_nodeset && + b->fixed_type_handler() != &type_handler_xpath_nodeset) { return eq_func(xpath->thd, oper, a, b); // two scalar arguments } - else if (a->type() == Item::XPATH_NODESET && - b->type() == Item::XPATH_NODESET) + else if (a->fixed_type_handler() == &type_handler_xpath_nodeset && + b->fixed_type_handler() == &type_handler_xpath_nodeset) { uint len= (uint)(xpath->query.end - context->beg); set_if_smaller(len, 32); @@ -1019,7 +1039,7 @@ static Item *create_comparator(MY_XPATH *xpath, Item_string_xml_non_const(thd, "", 0, xpath->cs)); Item_nodeset_func *nodeset; Item *scalar, *comp; - if (a->type() == Item::XPATH_NODESET) + if (a->fixed_type_handler() == &type_handler_xpath_nodeset) { nodeset= (Item_nodeset_func*) a; scalar= b; @@ -1053,7 +1073,7 @@ static Item* nametestfunc(MY_XPATH *xpath, MEM_ROOT *mem_root= thd->mem_root; DBUG_ASSERT(arg != 0); - DBUG_ASSERT(arg->type() == Item::XPATH_NODESET); + DBUG_ASSERT(arg->fixed_type_handler() == &type_handler_xpath_nodeset); DBUG_ASSERT(beg != 0); DBUG_ASSERT(len > 0); @@ -1306,7 +1326,7 @@ static Item *create_func_substr(MY_XPATH *xpath, Item **args, uint nargs) static Item *create_func_count(MY_XPATH *xpath, Item **args, uint nargs) { - if (args[0]->type() != Item::XPATH_NODESET) + if (args[0]->fixed_type_handler() != &type_handler_xpath_nodeset) return 0; return new (xpath->thd->mem_root) Item_func_xpath_count(xpath->thd, args[0], xpath->pxml); } @@ -1314,7 +1334,7 @@ static Item *create_func_count(MY_XPATH *xpath, Item **args, uint nargs) static Item *create_func_sum(MY_XPATH *xpath, Item **args, uint nargs) { - if (args[0]->type() != Item::XPATH_NODESET) + if (args[0]->fixed_type_handler() != &type_handler_xpath_nodeset) return 0; return new (xpath->thd->mem_root) Item_func_xpath_sum(xpath->thd, args[0], xpath->pxml); @@ -1793,7 +1813,8 @@ my_xpath_parse_AxisSpecifier_NodeTest_opt_Predicate_list(MY_XPATH *xpath) xpath->item= nodeset2bool(xpath, xpath->item); - if (xpath->item->is_bool_type()) + const Type_handler *fh; + if ((fh= xpath->item->fixed_type_handler()) && fh->is_bool_type()) { xpath->context= new (xpath->thd->mem_root) Item_nodeset_func_predicate(xpath->thd, prev_context, @@ -2047,11 +2068,11 @@ static int my_xpath_parse_UnionExpr(MY_XPATH *xpath) while (my_xpath_parse_term(xpath, MY_XPATH_LEX_VLINE)) { Item *prev= xpath->item; - if (prev->type() != Item::XPATH_NODESET) + if (prev->fixed_type_handler() != &type_handler_xpath_nodeset) return 0; if (!my_xpath_parse_PathExpr(xpath) - || xpath->item->type() != Item::XPATH_NODESET) + || xpath->item->fixed_type_handler() != &type_handler_xpath_nodeset) { xpath->error= 1; return 0; @@ -2089,7 +2110,7 @@ my_xpath_parse_FilterExpr_opt_slashes_RelativeLocationPath(MY_XPATH *xpath) if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH)) return 1; - if (xpath->item->type() != Item::XPATH_NODESET) + if (xpath->item->fixed_type_handler() != &type_handler_xpath_nodeset) { xpath->lasttok= xpath->prevtok; xpath->error= 1; @@ -3054,7 +3075,7 @@ String *Item_func_xml_update::val_str(String *str) null_value= 0; if (!nodeset_func || get_xml(&xml) || !(rep= args[2]->val_str(&tmp_value3)) || - !(nodeset= nodeset_func->val_nodeset(&tmp_value2))) + !(nodeset= nodeset_func->val_raw(&tmp_value2))) { null_value= 1; return 0; diff --git a/sql/lex.h b/sql/lex.h index da20468d593..5ffe07fa415 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -589,6 +589,7 @@ static SYMBOL symbols[] = { { "SONAME", SYM(SONAME_SYM)}, { "SOUNDS", SYM(SOUNDS_SYM)}, { "SOURCE", SYM(SOURCE_SYM)}, + { "STAGE", SYM(STAGE_SYM)}, { "STORED", SYM(STORED_SYM)}, { "SPATIAL", SYM(SPATIAL_SYM)}, { "SPECIFIC", SYM(SPECIFIC_SYM)}, diff --git a/sql/lock.cc b/sql/lock.cc index 5420e9f42b5..1564059bb20 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -77,6 +77,7 @@ #include "sql_base.h" // close_tables_for_reopen #include "sql_parse.h" // is_log_table_write_query #include "sql_acl.h" // SUPER_ACL +#include "sql_handler.h" #include <hash.h> #include "wsrep_mysqld.h" @@ -860,10 +861,9 @@ bool lock_schema_name(THD *thd, const char *db) return TRUE; } - if (thd->global_read_lock.can_acquire_protection()) + if (thd->has_read_only_protection()) return TRUE; - global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, - MDL_STATEMENT); + global_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_DDL, MDL_STATEMENT); mdl_request.init(MDL_key::SCHEMA, db, "", MDL_EXCLUSIVE, MDL_TRANSACTION); mdl_requests.push_front(&mdl_request); @@ -919,10 +919,9 @@ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type, DBUG_ASSERT(name); DEBUG_SYNC(thd, "before_wait_locked_pname"); - if (thd->global_read_lock.can_acquire_protection()) + if (thd->has_read_only_protection()) return TRUE; - global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, - MDL_STATEMENT); + global_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_DDL, MDL_STATEMENT); schema_request.init(MDL_key::SCHEMA, db, "", MDL_INTENTION_EXCLUSIVE, MDL_TRANSACTION); mdl_request.init(mdl_type, db, name, MDL_EXCLUSIVE, MDL_TRANSACTION); @@ -953,10 +952,10 @@ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type, semi-automatic. We assume that any statement which should be blocked by global read lock will either open and acquires write-lock on tables or acquires metadata locks on objects it is going to modify. For any - such statement global IX metadata lock is automatically acquired for - its duration (in case of LOCK TABLES until end of LOCK TABLES mode). - And lock_global_read_lock() simply acquires global S metadata lock - and thus prohibits execution of statements which modify data (unless + such statement MDL_BACKUP_STMT metadata lock is automatically acquired + for its duration (in case of LOCK TABLES until end of LOCK TABLES mode). + And lock_global_read_lock() simply acquires MDL_BACKUP_FTWRL1 metadata + lock and thus prohibits execution of statements which modify data (unless they modify only temporary tables). If deadlock happens it is detected by MDL subsystem and resolved in the standard fashion (by backing-off metadata locks acquired so far and restarting open tables process @@ -997,11 +996,23 @@ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type, /** Take global read lock, wait if there is protection against lock. - If the global read lock is already taken by this thread, then nothing is done. + If the global read lock is already taken by this thread, then nothing is + done. + + Concurrent thread can acquire protection against global read lock either + before or after it got table metadata lock. This may lead to a deadlock if + there is pending global read lock request. E.g. + t1 does DML, holds SHARED table lock, waiting for t3 (GRL protection) + t2 does DDL, holds GRL protection, waiting for t1 (EXCLUSIVE) + t3 does FTWRL, has pending GRL, waiting for t2 (GRL) + + Since this is very seldom deadlock and FTWRL connection must not hold any + other locks, FTWRL connection is made deadlock victim and attempt to acquire + GRL retried. See also "Handling of global read locks" above. - @param thd Reference to thread. + @param thd Reference to thread. @retval False Success, global read lock set, commits are NOT blocked. @retval True Failure, thread was killed. @@ -1013,17 +1024,38 @@ bool Global_read_lock::lock_global_read_lock(THD *thd) if (!m_state) { + MDL_deadlock_and_lock_abort_error_handler mdl_deadlock_handler; MDL_request mdl_request; + bool result; - DBUG_ASSERT(! thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "", - MDL_SHARED)); - mdl_request.init(MDL_key::GLOBAL, "", "", MDL_SHARED, MDL_EXPLICIT); - - if (thd->mdl_context.acquire_lock(&mdl_request, - thd->variables.lock_wait_timeout)) + if (thd->current_backup_stage != BACKUP_FINISHED) + { + my_error(ER_BACKUP_LOCK_IS_ACTIVE, MYF(0)); DBUG_RETURN(1); + } + + mysql_ha_cleanup_no_free(thd); - m_mdl_global_shared_lock= mdl_request.ticket; + DBUG_ASSERT(! thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "", + MDL_BACKUP_FTWRL1)); + DBUG_ASSERT(! thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "", + MDL_BACKUP_FTWRL2)); + mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_FTWRL1, + MDL_EXPLICIT); + + do + { + mdl_deadlock_handler.init(); + thd->push_internal_handler(&mdl_deadlock_handler); + result= thd->mdl_context.acquire_lock(&mdl_request, + thd->variables.lock_wait_timeout); + thd->pop_internal_handler(); + } while (mdl_deadlock_handler.need_reopen()); + + if (result) + DBUG_RETURN(true); + + m_mdl_global_read_lock= mdl_request.ticket; m_state= GRL_ACQUIRED; } /* @@ -1052,7 +1084,7 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) { DBUG_ENTER("unlock_global_read_lock"); - DBUG_ASSERT(m_mdl_global_shared_lock && m_state); + DBUG_ASSERT(m_mdl_global_read_lock && m_state); if (thd->global_disable_checkpoint) { @@ -1063,11 +1095,11 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) } } - if (m_mdl_blocks_commits_lock) - { - thd->mdl_context.release_lock(m_mdl_blocks_commits_lock); - m_mdl_blocks_commits_lock= NULL; + thd->mdl_context.release_lock(m_mdl_global_read_lock); + #ifdef WITH_WSREP + if (m_state == GRL_ACQUIRED_AND_BLOCKS_COMMIT) + { if (WSREP(thd) || wsrep_node_is_donor()) { wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; @@ -1080,14 +1112,13 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) { WSREP_WARN("resync failed %d for FTWRL: db: %s, query: %s", ret, thd->get_db(), thd->query()); - DBUG_VOID_RETURN; } } } -#endif /* WITH_WSREP */ } - thd->mdl_context.release_lock(m_mdl_global_shared_lock); - m_mdl_global_shared_lock= NULL; +#endif /* WITH_WSREP */ + + m_mdl_global_read_lock= NULL; m_state= GRL_NONE; DBUG_VOID_RETURN; @@ -1111,7 +1142,6 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) { - MDL_request mdl_request; DBUG_ENTER("make_global_read_lock_block_commit"); /* If we didn't succeed lock_global_read_lock(), or if we already suceeded @@ -1121,22 +1151,11 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) if (m_state != GRL_ACQUIRED) DBUG_RETURN(0); -#ifdef WITH_WSREP - if (WSREP(thd) && m_mdl_blocks_commits_lock) - { - WSREP_DEBUG("GRL was in block commit mode when entering " - "make_global_read_lock_block_commit"); - DBUG_RETURN(FALSE); - } -#endif /* WITH_WSREP */ - - mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT); - - if (thd->mdl_context.acquire_lock(&mdl_request, - thd->variables.lock_wait_timeout)) + if (thd->mdl_context.upgrade_shared_lock(m_mdl_global_read_lock, + MDL_BACKUP_FTWRL2, + thd->variables.lock_wait_timeout)) DBUG_RETURN(TRUE); - m_mdl_blocks_commits_lock= mdl_request.ticket; m_state= GRL_ACQUIRED_AND_BLOCKS_COMMIT; #ifdef WITH_WSREP @@ -1187,7 +1206,11 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) { WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret)); - DBUG_ASSERT(m_mdl_blocks_commits_lock == NULL); + /* + For some reason Galera wants to crash here in debug build. + It is equivalent of original assertion. + */ + DBUG_ASSERT(0); wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; my_error(ER_LOCK_DEADLOCK, MYF(0)); DBUG_RETURN(TRUE); @@ -1206,10 +1229,8 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) void Global_read_lock::set_explicit_lock_duration(THD *thd) { - if (m_mdl_global_shared_lock) - thd->mdl_context.set_lock_duration(m_mdl_global_shared_lock, MDL_EXPLICIT); - if (m_mdl_blocks_commits_lock) - thd->mdl_context.set_lock_duration(m_mdl_blocks_commits_lock, MDL_EXPLICIT); + if (m_mdl_global_read_lock) + thd->mdl_context.set_lock_duration(m_mdl_global_read_lock, MDL_EXPLICIT); } /** diff --git a/sql/log.cc b/sql/log.cc index 0fa65a05de3..a56117a4ac1 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -866,10 +866,10 @@ bool Log_to_csv_event_handler:: Open_tables_backup open_tables_backup; CHARSET_INFO *client_cs= thd->variables.character_set_client; bool save_time_zone_used; - long query_time= (long) MY_MIN(query_utime/1000000, TIME_MAX_VALUE_SECONDS); - long lock_time= (long) MY_MIN(lock_utime/1000000, TIME_MAX_VALUE_SECONDS); - long query_time_micro= (long) (query_utime % 1000000); - long lock_time_micro= (long) (lock_utime % 1000000); + ulong query_time= (ulong) MY_MIN(query_utime/1000000, TIME_MAX_VALUE_SECONDS); + ulong lock_time= (ulong) MY_MIN(lock_utime/1000000, TIME_MAX_VALUE_SECONDS); + ulong query_time_micro= (ulong) (query_utime % 1000000); + ulong lock_time_micro= (ulong) (lock_utime % 1000000); DBUG_ENTER("Log_to_csv_event_handler::log_slow"); @@ -1162,6 +1162,10 @@ bool LOGGER::error_log_print(enum loglevel level, const char *format, { bool error= FALSE; Log_event_handler **current_handler; + THD *thd= current_thd; + + if (likely(thd)) + thd->error_printed_to_log= 1; /* currently we don't need locking here as there is no error_log table */ for (current_handler= error_log_handler_list ; *current_handler ;) @@ -2183,16 +2187,16 @@ void MYSQL_BIN_LOG::set_write_error(THD *thd, bool is_transactional) { if (is_transactional) { - my_message(ER_TRANS_CACHE_FULL, ER_THD(thd, ER_TRANS_CACHE_FULL), MYF(MY_WME)); + my_message(ER_TRANS_CACHE_FULL, ER_THD(thd, ER_TRANS_CACHE_FULL), MYF(0)); } else { - my_message(ER_STMT_CACHE_FULL, ER_THD(thd, ER_STMT_CACHE_FULL), MYF(MY_WME)); + my_message(ER_STMT_CACHE_FULL, ER_THD(thd, ER_STMT_CACHE_FULL), MYF(0)); } } else { - my_error(ER_ERROR_ON_WRITE, MYF(MY_WME), name, errno); + my_error(ER_ERROR_ON_WRITE, MYF(0), name, errno); } DBUG_VOID_RETURN; @@ -2649,7 +2653,7 @@ bool MYSQL_LOG::open( #endif if ((file= mysql_file_open(log_file_key, log_file_name, open_flags, - MYF(MY_WME | ME_WAITTANG))) < 0) + MYF(MY_WME))) < 0) goto err; if (is_fifo) @@ -2791,7 +2795,7 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name, { THD *thd= current_thd; if (unlikely(thd)) - my_error(ER_NO_UNIQUE_LOGFILE, MYF(ME_FATALERROR), log_name); + my_error(ER_NO_UNIQUE_LOGFILE, MYF(ME_FATAL), log_name); sql_print_error(ER_DEFAULT(ER_NO_UNIQUE_LOGFILE), log_name); return 1; } @@ -4627,7 +4631,7 @@ int MYSQL_BIN_LOG::open_purge_index_file(bool destroy) if (!my_b_inited(&purge_index_file)) { if ((file= my_open(purge_index_file_name, O_RDWR | O_CREAT | O_BINARY, - MYF(MY_WME | ME_WAITTANG))) < 0 || + MYF(MY_WME))) < 0 || init_io_cache(&purge_index_file, file, IO_SIZE, (destroy ? WRITE_CACHE : READ_CACHE), 0, 0, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL))) @@ -5196,7 +5200,7 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock) close_on_error= TRUE; my_printf_error(ER_ERROR_ON_WRITE, ER_THD_OR_DEFAULT(current_thd, ER_CANT_OPEN_FILE), - MYF(ME_FATALERROR), name, errno); + MYF(ME_FATAL), name, errno); goto end; } bytes_written += r.data_written; @@ -5265,7 +5269,7 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock) /* handle reopening errors */ if (unlikely(error)) { - my_error(ER_CANT_OPEN_FILE, MYF(ME_FATALERROR), file_to_open, error); + my_error(ER_CANT_OPEN_FILE, MYF(ME_FATAL), file_to_open, error); close_on_error= TRUE; } @@ -7748,10 +7752,10 @@ MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry) switch (entry->error) { case ER_ERROR_ON_WRITE: - my_error(ER_ERROR_ON_WRITE, MYF(ME_NOREFRESH), name, entry->commit_errno); + my_error(ER_ERROR_ON_WRITE, MYF(ME_ERROR_LOG), name, entry->commit_errno); break; case ER_ERROR_ON_READ: - my_error(ER_ERROR_ON_READ, MYF(ME_NOREFRESH), + my_error(ER_ERROR_ON_READ, MYF(ME_ERROR_LOG), entry->error_cache->file_name, entry->commit_errno); break; default: @@ -7762,7 +7766,7 @@ MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry) */ my_printf_error(entry->error, "Error writing transaction to binary log: %d", - MYF(ME_NOREFRESH), entry->error); + MYF(ME_ERROR_LOG), entry->error); } /* @@ -7985,7 +7989,7 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) when the transaction has been safely committed in the engine. */ leader->cache_mngr->delayed_error= true; - my_error(ER_ERROR_ON_WRITE, MYF(ME_NOREFRESH), name, errno); + my_error(ER_ERROR_ON_WRITE, MYF(ME_ERROR_LOG), name, errno); check_purge= false; } /* In case of binlog rotate, update the correct current binlog offset. */ diff --git a/sql/log_event.cc b/sql/log_event.cc index 72db2717680..3ea6be95dda 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -101,16 +101,11 @@ TYPELIB binlog_checksum_typelib= TODO: correct the constant when it has been determined (which main tree to push and when) */ -const uchar checksum_version_split_mysql[3]= {5, 6, 1}; -const ulong checksum_version_product_mysql= - (checksum_version_split_mysql[0] * 256 + - checksum_version_split_mysql[1]) * 256 + - checksum_version_split_mysql[2]; -const uchar checksum_version_split_mariadb[3]= {5, 3, 0}; -const ulong checksum_version_product_mariadb= - (checksum_version_split_mariadb[0] * 256 + - checksum_version_split_mariadb[1]) * 256 + - checksum_version_split_mariadb[2]; +const Version checksum_version_split_mysql(5, 6, 1); +const Version checksum_version_split_mariadb(5, 3, 0); + +// First MySQL version with fraction seconds +const Version fsp_version_split_mysql(5, 6, 0); #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) static int rows_event_stmt_cleanup(rpl_group_info *rgi, THD* thd); @@ -2753,9 +2748,7 @@ log_event_print_value(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info, goto return_null; uint bin_size= my_decimal_get_binary_size(precision, decimals); - my_decimal dec; - binary2my_decimal(E_DEC_FATAL_ERROR, (uchar*) ptr, &dec, - precision, decimals); + my_decimal dec((const uchar *) ptr, precision, decimals); int length= DECIMAL_MAX_STR_LENGTH; char buff[DECIMAL_MAX_STR_LENGTH + 1]; decimal2string(&dec, buff, &length, 0, 0, 0); @@ -4411,7 +4404,7 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, size_t que have to use the transactional cache to ensure we don't calculate any checksum for the CREATE part. */ - trx_cache= (lex->select_lex.item_list.elements && + trx_cache= (lex->first_select_lex()->item_list.elements && thd->is_current_stmt_binlog_format_row()) || (thd->variables.option_bits & OPTION_GTID_BEGIN); use_cache= (lex->tmp_table() && @@ -4543,6 +4536,7 @@ code_name(int code) } #endif + /** Macro to check that there is enough space to read from memory. @@ -4766,6 +4760,30 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, } } +#if !defined(MYSQL_CLIENT) + if (description_event->server_version_split.kind == + Format_description_log_event::master_version_split::KIND_MYSQL) + { + // Handle MariaDB/MySQL incompatible sql_mode bits + sql_mode_t mysql_sql_mode= sql_mode; + sql_mode&= MODE_MASK_MYSQL_COMPATIBLE; // Unset MySQL specific bits + + /* + sql_mode flags related to fraction second rounding/truncation + have opposite meaning in MySQL vs MariaDB. + MySQL: + - rounds fractional seconds by default + - truncates if TIME_TRUNCATE_FRACTIONAL is set + MariaDB: + - truncates fractional seconds by default + - rounds if TIME_ROUND_FRACTIONAL is set + */ + if (description_event->server_version_split >= fsp_version_split_mysql && + !(mysql_sql_mode & MODE_MYSQL80_TIME_TRUNCATE_FRACTIONAL)) + sql_mode|= MODE_TIME_ROUND_FRACTIONAL; + } +#endif + /** Layout for the data buffer is as follows +--------+-----------+------+------+---------+----+-------+ @@ -5583,7 +5601,7 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi, gtid= rgi->current_gtid; if (unlikely(rpl_global_gtid_slave_state->record_gtid(thd, >id, sub_id, - rgi, false, + true, false, &hton))) { int errcode= thd->get_stmt_da()->sql_errno(); @@ -6551,26 +6569,24 @@ bool Format_description_log_event::start_decryption(Start_encryption_log_event* return crypto_data.init(sele->crypto_scheme, sele->key_version); } -static inline void -do_server_version_split(char* version, - Format_description_log_event::master_version_split *split_versions) + +Version::Version(const char *version, const char **endptr) { - char *p= version, *r; + const char *p= version; ulong number; for (uint i= 0; i<=2; i++) { + char *r; number= strtoul(p, &r, 10); /* It is an invalid version if any version number greater than 255 or first number is not followed by '.'. */ if (number < 256 && (*r == '.' || i != 0)) - split_versions->ver[i]= (uchar) number; + m_ver[i]= (uchar) number; else { - split_versions->ver[0]= 0; - split_versions->ver[1]= 0; - split_versions->ver[2]= 0; + *this= Version(); break; } @@ -6578,12 +6594,19 @@ do_server_version_split(char* version, if (*r == '.') p++; // skip the dot } + endptr[0]= p; +} + + +Format_description_log_event:: + master_version_split::master_version_split(const char *version) +{ + const char *p; + static_cast<Version*>(this)[0]= Version(version, &p); if (strstr(p, "MariaDB") != 0 || strstr(p, "-maria-") != 0) - split_versions->kind= - Format_description_log_event::master_version_split::KIND_MARIADB; + kind= KIND_MARIADB; else - split_versions->kind= - Format_description_log_event::master_version_split::KIND_MYSQL; + kind= KIND_MYSQL; } @@ -6597,20 +6620,14 @@ do_server_version_split(char* version, */ void Format_description_log_event::calc_server_version_split() { - do_server_version_split(server_version, &server_version_split); + server_version_split= master_version_split(server_version); DBUG_PRINT("info",("Format_description_log_event::server_version_split:" " '%s' %d %d %d", server_version, - server_version_split.ver[0], - server_version_split.ver[1], server_version_split.ver[2])); + server_version_split[0], + server_version_split[1], server_version_split[2])); } -static inline ulong -version_product(const Format_description_log_event::master_version_split* version_split) -{ - return ((version_split->ver[0] * 256 + version_split->ver[1]) * 256 - + version_split->ver[2]); -} /** @return TRUE is the event's version is earlier than one that introduced @@ -6620,9 +6637,9 @@ bool Format_description_log_event::is_version_before_checksum(const master_version_split *version_split) { - return version_product(version_split) < + return *version_split < (version_split->kind == master_version_split::KIND_MARIADB ? - checksum_version_product_mariadb : checksum_version_product_mysql); + checksum_version_split_mariadb : checksum_version_split_mysql); } /** @@ -6638,7 +6655,6 @@ enum enum_binlog_checksum_alg get_checksum_alg(const char* buf, ulong len) { enum enum_binlog_checksum_alg ret; char version[ST_SERVER_VER_LEN]; - Format_description_log_event::master_version_split version_split; DBUG_ENTER("get_checksum_alg"); DBUG_ASSERT(buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT); @@ -6648,7 +6664,7 @@ enum enum_binlog_checksum_alg get_checksum_alg(const char* buf, ulong len) ST_SERVER_VER_LEN); version[ST_SERVER_VER_LEN - 1]= 0; - do_server_version_split(version, &version_split); + Format_description_log_event::master_version_split version_split(version); ret= Format_description_log_event::is_version_before_checksum(&version_split) ? BINLOG_CHECKSUM_ALG_UNDEF : (enum_binlog_checksum_alg)buf[len - BINLOG_CHECKSUM_LEN - BINLOG_CHECKSUM_ALG_DESC_LEN]; @@ -7399,8 +7415,9 @@ int Load_log_event::do_apply_event(NET* net, rpl_group_info *rgi, ex.skip_lines = skip_lines; List<Item> field_list; - thd->lex->select_lex.context.resolve_in_table_list_only(&tables); - set_fields(tables.db.str, field_list, &thd->lex->select_lex.context); + thd->lex->first_select_lex()->context.resolve_in_table_list_only(&tables); + set_fields(tables.db.str, + field_list, &thd->lex->first_select_lex()->context); thd->variables.pseudo_thread_id= thread_id; if (net) { @@ -8379,7 +8396,7 @@ Gtid_list_log_event::do_apply_event(rpl_group_info *rgi) { if ((ret= rpl_global_gtid_slave_state->record_gtid(thd, &list[i], sub_id_list[i], - NULL, false, &hton))) + false, false, &hton))) return ret; rpl_global_gtid_slave_state->update_state_hash(sub_id_list[i], &list[i], hton, NULL); @@ -8916,7 +8933,7 @@ int Xid_log_event::do_apply_event(rpl_group_info *rgi) rgi->gtid_pending= false; gtid= rgi->current_gtid; - err= rpl_global_gtid_slave_state->record_gtid(thd, >id, sub_id, rgi, + err= rpl_global_gtid_slave_state->record_gtid(thd, >id, sub_id, true, false, &hton); if (unlikely(err)) { @@ -9054,11 +9071,8 @@ void User_var_log_event::pack_info(Protocol* protocol) String buf(buf_mem, sizeof(buf_mem), system_charset_info); char buf2[DECIMAL_MAX_STR_LENGTH+1]; String str(buf2, sizeof(buf2), &my_charset_bin); - my_decimal dec; buf.length(0); - binary2my_decimal(E_DEC_FATAL_ERROR, (uchar*) (val+2), &dec, val[0], - val[1]); - my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, 0, &str); + my_decimal((const uchar *) (val + 2), val[0], val[1]).to_string(&str); if (user_var_append_name_part(protocol->thd, &buf, name, name_len) || buf.append(buf2)) return; diff --git a/sql/log_event.h b/sql/log_event.h index 84025554ee9..38a40c90799 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2728,6 +2728,38 @@ protected: }; +class Version +{ +protected: + uchar m_ver[3]; + int cmp(const Version &other) const + { + return memcmp(m_ver, other.m_ver, 3); + } +public: + Version() + { + m_ver[0]= m_ver[1]= m_ver[2]= '\0'; + } + Version(uchar v0, uchar v1, uchar v2) + { + m_ver[0]= v0; + m_ver[1]= v1; + m_ver[2]= v2; + } + Version(const char *version, const char **endptr); + const uchar& operator [] (size_t i) const + { + DBUG_ASSERT(i < 3); + return m_ver[i]; + } + bool operator<(const Version &other) const { return cmp(other) < 0; } + bool operator>(const Version &other) const { return cmp(other) > 0; } + bool operator<=(const Version &other) const { return cmp(other) <= 0; } + bool operator>=(const Version &other) const { return cmp(other) >= 0; } +}; + + /** @class Format_description_log_event @@ -2754,10 +2786,17 @@ public: by the checksum alg decription byte */ uint8 *post_header_len; - struct master_version_split { + class master_version_split: public Version { + public: enum {KIND_MYSQL, KIND_MARIADB}; int kind; - uchar ver[3]; + master_version_split() :kind(KIND_MARIADB) { } + master_version_split(const char *version); + bool version_is_valid() const + { + /* It is invalid only when all version numbers are 0 */ + return !(m_ver[0] == 0 && m_ver[1] == 0 && m_ver[2] == 0); + } }; master_version_split server_version_split; const uint8 *event_type_permutation; @@ -2781,17 +2820,9 @@ public: (post_header_len != NULL)); } - bool version_is_valid() const - { - /* It is invalid only when all version numbers are 0 */ - return !(server_version_split.ver[0] == 0 && - server_version_split.ver[1] == 0 && - server_version_split.ver[2] == 0); - } - bool is_valid() const { - return header_is_valid() && version_is_valid(); + return header_is_valid() && server_version_split.version_is_valid(); } int get_data_size() diff --git a/sql/mdl.cc b/sql/mdl.cc index f03fc89fcc1..c06a212ed19 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -80,7 +80,7 @@ static void init_mdl_psi_keys(void) PSI_stage_info MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END]= { - {0, "Waiting for global read lock", 0}, + {0, "Waiting for backup lock", 0}, {0, "Waiting for schema metadata lock", 0}, {0, "Waiting for table metadata lock", 0}, {0, "Waiting for stored function metadata lock", 0}, @@ -88,10 +88,44 @@ PSI_stage_info MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END]= {0, "Waiting for stored package body metadata lock", 0}, {0, "Waiting for trigger metadata lock", 0}, {0, "Waiting for event metadata lock", 0}, - {0, "Waiting for commit lock", 0}, {0, "User lock", 0} /* Be compatible with old status. */ }; + +static const LEX_STRING lock_types[]= +{ + { C_STRING_WITH_LEN("MDL_INTENTION_EXCLUSIVE") }, + { C_STRING_WITH_LEN("MDL_SHARED") }, + { C_STRING_WITH_LEN("MDL_SHARED_HIGH_PRIO") }, + { C_STRING_WITH_LEN("MDL_SHARED_READ") }, + { C_STRING_WITH_LEN("MDL_SHARED_WRITE") }, + { C_STRING_WITH_LEN("MDL_SHARED_UPGRADABLE") }, + { C_STRING_WITH_LEN("MDL_SHARED_READ_ONLY") }, + { C_STRING_WITH_LEN("MDL_SHARED_NO_WRITE") }, + { C_STRING_WITH_LEN("MDL_SHARED_NO_READ_WRITE") }, + { C_STRING_WITH_LEN("MDL_EXCLUSIVE") }, +}; + + +static const LEX_STRING backup_lock_types[]= +{ + { C_STRING_WITH_LEN("MDL_BACKUP_START") }, + { C_STRING_WITH_LEN("MDL_BACKUP_FLUSH") }, + { C_STRING_WITH_LEN("MDL_BACKUP_WAIT_FLUSH") }, + { C_STRING_WITH_LEN("MDL_BACKUP_WAIT_DDL") }, + { C_STRING_WITH_LEN("MDL_BACKUP_WAIT_COMMIT") }, + { C_STRING_WITH_LEN("MDL_BACKUP_FTWRL1") }, + { C_STRING_WITH_LEN("MDL_BACKUP_FTWRL2") }, + { C_STRING_WITH_LEN("MDL_BACKUP_DML") }, + { C_STRING_WITH_LEN("MDL_BACKUP_TRANS_DML") }, + { C_STRING_WITH_LEN("MDL_BACKUP_SYS_DML") }, + { C_STRING_WITH_LEN("MDL_BACKUP_DDL") }, + { C_STRING_WITH_LEN("MDL_BACKUP_BLOCK_DDL") }, + { C_STRING_WITH_LEN("MDL_BACKUP_ALTER_COPY") }, + { C_STRING_WITH_LEN("MDL_BACKUP_COMMIT") } +}; + + #ifdef HAVE_PSI_INTERFACE void MDL_key::init_psi_keys() { @@ -128,11 +162,9 @@ public: LF_PINS *get_pins() { return lf_hash_get_pins(&m_locks); } private: LF_HASH m_locks; /**< All acquired locks in the server. */ - /** Pre-allocated MDL_lock object for GLOBAL namespace. */ - MDL_lock *m_global_lock; - /** Pre-allocated MDL_lock object for COMMIT namespace. */ - MDL_lock *m_commit_lock; - friend int mdl_iterate(int (*)(MDL_ticket *, void *), void *); + /** Pre-allocated MDL_lock object for BACKUP namespace. */ + MDL_lock *m_backup_lock; + friend int mdl_iterate(mdl_iterator_callback, void *); }; @@ -279,8 +311,6 @@ Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim) and compatibility matrices. */ -#define MDL_BIT(A) static_cast<MDL_lock::bitmap_t>(1U << A) - /** The lock context. Created internally for an acquired lock. For a given name, there exists only one MDL_lock instance, @@ -295,7 +325,7 @@ Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim) class MDL_lock { public: - typedef unsigned short bitmap_t; + typedef mdl_bitmap_t bitmap_t; class Ticket_list { @@ -328,9 +358,10 @@ public: /** Helper struct which defines how different types of locks are handled - for a specific MDL_lock. In practice we use only two strategies: "scoped" - lock strategy for locks in GLOBAL, COMMIT and SCHEMA namespaces and - "object" lock strategy for all other namespaces. + for a specific MDL_lock. In practice we use only three strategies: + "backup" lock strategy for locks in BACKUP namespace, "scoped" lock + strategy for locks in SCHEMA namespace and "object" lock strategy for + all other namespaces. */ struct MDL_lock_strategy { @@ -394,9 +425,10 @@ public: { return m_waiting_incompatible; } virtual bool needs_notification(const MDL_ticket *ticket) const { - return ticket->get_type() == MDL_SHARED_NO_WRITE || - ticket->get_type() == MDL_SHARED_NO_READ_WRITE || - ticket->get_type() == MDL_EXCLUSIVE; + return (MDL_BIT(ticket->get_type()) & + (MDL_BIT(MDL_SHARED_NO_WRITE) | + MDL_BIT(MDL_SHARED_NO_READ_WRITE) | + MDL_BIT(MDL_EXCLUSIVE))); } /** @@ -427,6 +459,43 @@ public: static const bitmap_t m_waiting_incompatible[MDL_TYPE_END]; }; + + struct MDL_backup_lock: public MDL_lock_strategy + { + MDL_backup_lock() {} + virtual const bitmap_t *incompatible_granted_types_bitmap() const + { return m_granted_incompatible; } + virtual const bitmap_t *incompatible_waiting_types_bitmap() const + { return m_waiting_incompatible; } + virtual bool needs_notification(const MDL_ticket *ticket) const + { + return (MDL_BIT(ticket->get_type()) & MDL_BIT(MDL_BACKUP_FTWRL1)); + } + + /** + Insert delayed threads may hold DML or TRANS_DML lock. + We need to kill such threads in order to get lock for FTWRL statements. + We do this by calling code outside of MDL. + */ + virtual bool conflicting_locks(const MDL_ticket *ticket) const + { + return (MDL_BIT(ticket->get_type()) & + (MDL_BIT(MDL_BACKUP_DML) | + MDL_BIT(MDL_BACKUP_TRANS_DML))); + } + + /* + In backup namespace DML/DDL may starve because of concurrent FTWRL or + BACKUP statements. This scenario is partically useless in real world, + so we just return 0 here. + */ + virtual bitmap_t hog_lock_types_bitmap() const + { return 0; } + private: + static const bitmap_t m_granted_incompatible[MDL_BACKUP_END]; + static const bitmap_t m_waiting_incompatible[MDL_BACKUP_END]; + }; + public: /** The key of the object (data) being protected. */ MDL_key key; @@ -538,10 +607,9 @@ public: MDL_lock(const MDL_key *key_arg) : key(key_arg), m_hog_lock_count(0), - m_strategy(&m_scoped_lock_strategy) + m_strategy(&m_backup_lock_strategy) { - DBUG_ASSERT(key_arg->mdl_namespace() == MDL_key::GLOBAL || - key_arg->mdl_namespace() == MDL_key::COMMIT); + DBUG_ASSERT(key_arg->mdl_namespace() == MDL_key::BACKUP); mysql_prlock_init(key_MDL_lock_rwlock, &m_rwlock); } @@ -557,8 +625,7 @@ public: static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)), MDL_lock *lock, MDL_key *key_arg) { - DBUG_ASSERT(key_arg->mdl_namespace() != MDL_key::GLOBAL && - key_arg->mdl_namespace() != MDL_key::COMMIT); + DBUG_ASSERT(key_arg->mdl_namespace() != MDL_key::BACKUP); new (&lock->key) MDL_key(key_arg); if (key_arg->mdl_namespace() == MDL_key::SCHEMA) lock->m_strategy= &m_scoped_lock_strategy; @@ -568,11 +635,13 @@ public: const MDL_lock_strategy *m_strategy; private: + static const MDL_backup_lock m_backup_lock_strategy; static const MDL_scoped_lock m_scoped_lock_strategy; static const MDL_object_lock m_object_lock_strategy; }; +const MDL_lock::MDL_backup_lock MDL_lock::m_backup_lock_strategy; const MDL_lock::MDL_scoped_lock MDL_lock::m_scoped_lock_strategy; const MDL_lock::MDL_object_lock MDL_lock::m_object_lock_strategy; @@ -636,7 +705,7 @@ void mdl_destroy() struct mdl_iterate_arg { - int (*callback)(MDL_ticket *ticket, void *arg); + mdl_iterator_callback callback; void *argument; }; @@ -649,16 +718,19 @@ static my_bool mdl_iterate_lock(MDL_lock *lock, mdl_iterate_arg *arg) must be empty for such locks anyway. */ mysql_prlock_rdlock(&lock->m_rwlock); - MDL_lock::Ticket_iterator ticket_it(lock->m_granted); + MDL_lock::Ticket_iterator granted_it(lock->m_granted); + MDL_lock::Ticket_iterator waiting_it(lock->m_waiting); MDL_ticket *ticket; - while ((ticket= ticket_it++) && !(res= arg->callback(ticket, arg->argument))) + while ((ticket= granted_it++) && !(res= arg->callback(ticket, arg->argument, true))) + /* no-op */; + while ((ticket= waiting_it++) && !(res= arg->callback(ticket, arg->argument, false))) /* no-op */; mysql_prlock_unlock(&lock->m_rwlock); return MY_TEST(res); } -int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg) +int mdl_iterate(mdl_iterator_callback callback, void *arg) { DBUG_ENTER("mdl_iterate"); mdl_iterate_arg argument= { callback, arg }; @@ -667,8 +739,7 @@ int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg) if (pins) { - res= mdl_iterate_lock(mdl_locks.m_global_lock, &argument) || - mdl_iterate_lock(mdl_locks.m_commit_lock, &argument) || + res= mdl_iterate_lock(mdl_locks.m_backup_lock, &argument) || lf_hash_iterate(&mdl_locks.m_locks, pins, (my_hash_walk_action) mdl_iterate_lock, &argument); lf_hash_put_pins(pins); @@ -689,11 +760,9 @@ my_hash_value_type mdl_hash_function(CHARSET_INFO *cs, void MDL_map::init() { - MDL_key global_lock_key(MDL_key::GLOBAL, "", ""); - MDL_key commit_lock_key(MDL_key::COMMIT, "", ""); + MDL_key backup_lock_key(MDL_key::BACKUP, "", ""); - m_global_lock= new (std::nothrow) MDL_lock(&global_lock_key); - m_commit_lock= new (std::nothrow) MDL_lock(&commit_lock_key); + m_backup_lock= new (std::nothrow) MDL_lock(&backup_lock_key); lf_hash_init(&m_locks, sizeof(MDL_lock), LF_HASH_UNIQUE, 0, 0, mdl_locks_key, &my_charset_bin); @@ -711,8 +780,7 @@ void MDL_map::init() void MDL_map::destroy() { - delete m_global_lock; - delete m_commit_lock; + delete m_backup_lock; DBUG_ASSERT(!my_atomic_load32(&m_locks.count)); lf_hash_destroy(&m_locks); @@ -732,26 +800,18 @@ MDL_lock* MDL_map::find_or_insert(LF_PINS *pins, const MDL_key *mdl_key) { MDL_lock *lock; - if (mdl_key->mdl_namespace() == MDL_key::GLOBAL || - mdl_key->mdl_namespace() == MDL_key::COMMIT) + if (mdl_key->mdl_namespace() == MDL_key::BACKUP) { /* - Avoid locking any m_mutex when lock for GLOBAL or COMMIT namespace is - requested. Return pointer to pre-allocated MDL_lock instance instead. - Such an optimization allows to save one mutex lock/unlock for any - statement changing data. + Return pointer to pre-allocated MDL_lock instance. Such an optimization + allows to save one hash lookup for any statement changing data. - It works since these namespaces contain only one element so keys + It works since this namespace contains only one element so keys for them look like '<namespace-id>\0\0'. */ DBUG_ASSERT(mdl_key->length() == 3); - - lock= (mdl_key->mdl_namespace() == MDL_key::GLOBAL) ? m_global_lock : - m_commit_lock; - - mysql_prlock_wrlock(&lock->m_rwlock); - - return lock; + mysql_prlock_wrlock(&m_backup_lock->m_rwlock); + return m_backup_lock; } retry: @@ -780,22 +840,18 @@ retry: unsigned long MDL_map::get_lock_owner(LF_PINS *pins, const MDL_key *mdl_key) { - MDL_lock *lock; unsigned long res= 0; - if (mdl_key->mdl_namespace() == MDL_key::GLOBAL || - mdl_key->mdl_namespace() == MDL_key::COMMIT) + if (mdl_key->mdl_namespace() == MDL_key::BACKUP) { - lock= (mdl_key->mdl_namespace() == MDL_key::GLOBAL) ? m_global_lock : - m_commit_lock; - mysql_prlock_rdlock(&lock->m_rwlock); - res= lock->get_lock_owner(); - mysql_prlock_unlock(&lock->m_rwlock); + mysql_prlock_rdlock(&m_backup_lock->m_rwlock); + res= m_backup_lock->get_lock_owner(); + mysql_prlock_unlock(&m_backup_lock->m_rwlock); } else { - lock= (MDL_lock*) lf_hash_search(&m_locks, pins, mdl_key->ptr(), - mdl_key->length()); + MDL_lock *lock= (MDL_lock*) lf_hash_search(&m_locks, pins, mdl_key->ptr(), + mdl_key->length()); if (lock) { /* @@ -820,13 +876,9 @@ MDL_map::get_lock_owner(LF_PINS *pins, const MDL_key *mdl_key) void MDL_map::remove(LF_PINS *pins, MDL_lock *lock) { - if (lock->key.mdl_namespace() == MDL_key::GLOBAL || - lock->key.mdl_namespace() == MDL_key::COMMIT) + if (lock->key.mdl_namespace() == MDL_key::BACKUP) { - /* - Never destroy pre-allocated MDL_lock objects for GLOBAL and - COMMIT namespaces. - */ + /* Never destroy pre-allocated MDL_lock object in BACKUP namespace. */ mysql_prlock_unlock(&lock->m_rwlock); return; } @@ -975,9 +1027,14 @@ void MDL_ticket::destroy(MDL_ticket *ticket) uint MDL_ticket::get_deadlock_weight() const { - return (m_lock->key.mdl_namespace() == MDL_key::GLOBAL || - m_type >= MDL_SHARED_UPGRADABLE ? - DEADLOCK_WEIGHT_DDL : DEADLOCK_WEIGHT_DML); + if (m_lock->key.mdl_namespace() == MDL_key::BACKUP) + { + if (m_type == MDL_BACKUP_FTWRL1) + return DEADLOCK_WEIGHT_FTWRL1; + return DEADLOCK_WEIGHT_DDL; + } + return m_type >= MDL_SHARED_UPGRADABLE ? + DEADLOCK_WEIGHT_DDL : DEADLOCK_WEIGHT_DML; } @@ -1368,17 +1425,23 @@ void MDL_lock::reschedule_waiters() /** Compatibility (or rather "incompatibility") matrices for scoped metadata - lock. Arrays of bitmaps which elements specify which granted/waiting locks + lock. + Scoped locks are database (or schema) locks. + Arrays of bitmaps which elements specify which granted/waiting locks are incompatible with type of lock being requested. The first array specifies if particular type of request can be satisfied if there is granted scoped lock of certain type. + (*) Since intention shared scoped locks (IS) are compatible with all other + type of locks, they don't need to be implemented and there is no code + for them. + | Type of active | Request | scoped lock | type | IS(*) IX S X | ---------+------------------+ - IS | + + + + | + IS(*) | + + + + | IX | + + - - | S | + - + - | X | + - - - | @@ -1391,7 +1454,7 @@ void MDL_lock::reschedule_waiters() Request | scoped lock | type | IS(*) IX S X | ---------+-----------------+ - IS | + + + + | + IS(*) | + + + + | IX | + + - - | S | + + + - | X | + + + + | @@ -1399,9 +1462,6 @@ void MDL_lock::reschedule_waiters() Here: "+" -- means that request can be satisfied "-" -- means that request can't be satisfied and should wait - (*) Since intention shared scoped locks are compatible with all other - type of locks we don't even have any accounting for them. - Note that relation between scoped locks and objects locks requested by statement is not straightforward and is therefore fully defined by SQL-layer. @@ -1440,41 +1500,41 @@ MDL_lock::MDL_scoped_lock::m_waiting_incompatible[MDL_TYPE_END]= The first array specifies if particular type of request can be satisfied if there is granted lock of certain type. - Request | Granted requests for lock | - type | S SH SR SW SU SRO SNW SNRW X | - ----------+---------------------------------------+ - S | + + + + + + + + - | - SH | + + + + + + + + - | - SR | + + + + + + + - - | - SW | + + + + + - - - - | - SU | + + + + - + - - - | - SRO | + + + - + + + - - | - SNW | + + + - - + - - - | - SNRW | + + - - - - - - - | - X | - - - - - - - - - | - SU -> X | - - - - 0 - 0 0 0 | - SNW -> X | - - - 0 0 - 0 0 0 | - SNRW -> X | - - 0 0 0 0 0 0 0 | + Request | Granted requests for lock | + type | S SH SR SW SU SRO SNW SNRW X | + ----------+------------------------------------+ + S | + + + + + + + + - | + SH | + + + + + + + + - | + SR | + + + + + + + - - | + SW | + + + + + - - - - | + SU | + + + + - + - - - | + SRO | + + + - + + + - - | + SNW | + + + - - + - - - | + SNRW | + + - - - - - - - | + X | - - - - - - - - - | + SU -> X | - - - - 0 - 0 0 0 | + SNW -> X | - - - 0 0 - 0 0 0 | + SNRW -> X | - - 0 0 0 0 0 0 0 | The second array specifies if particular type of request can be satisfied if there is waiting request for the same lock of certain type. In other words it specifies what is the priority of different lock types. - Request | Pending requests for lock | - type | S SH SR SW SU SRO SNW SNRW X | - ----------+--------------------------------------+ - S | + + + + + + + + - | - SH | + + + + + + + + + | - SR | + + + + + + + - - | - SW | + + + + + + - - - | - SU | + + + + + + + + - | - SRO | + + + - + + + - - | - SNW | + + + + + + + + - | - SNRW | + + + + + + + + - | - X | + + + + + + + + + | - SU -> X | + + + + + + + + + | - SNW -> X | + + + + + + + + + | - SNRW -> X | + + + + + + + + + | + Request | Pending requests for lock | + type | S SH SR SW SU SRO SNW SNRW X | + ----------+-----------------------------------+ + S | + + + + + + + + - | + SH | + + + + + + + + + | + SR | + + + + + + + - - | + SW | + + + + + + - - - | + SU | + + + + + + + + - | + SRO | + + + - + + + - - | + SNW | + + + + + + + + - | + SNRW | + + + + + + + + - | + X | + + + + + + + + + | + SU -> X | + + + + + + + + + | + SNW -> X | + + + + + + + + + | + SNRW -> X | + + + + + + + + + | Here: "+" -- means that request can be satisfied "-" -- means that request can't be satisfied and should wait @@ -1535,6 +1595,117 @@ MDL_lock::MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END]= /** + Compatibility (or rather "incompatibility") matrices for backup metadata + lock. Arrays of bitmaps which elements specify which granted/waiting locks + are incompatible with type of lock being requested. + + The first array specifies if particular type of request can be satisfied + if there is granted backup lock of certain type. + + Request | Type of active backup lock | + type | S0 S1 S2 S3 S4 F1 F2 D TD SD DD BL AC C | + ----------+---------------------------------------------------------+ + S0 | - - - - - + + + + + + + + + | + S1 | - + + + + + + + + + + + + + | + S2 | - + + + + + + - + + + + + + | + S3 | - + + + + + + - + + - + + + | + S4 | - + + + + + + - + - - + + - | + FTWRL1 | + + + + + + + - - - - + - + | + FTWRL2 | + + + + + + + - - - - + - - | + D | + - - - - - - + + + + + + + | + TD | + + + + + - - + + + + + + + | + SD | + + + + - - - + + + + + + + | + DDL | + + + - - - - + + + + - + + | + BLOCK_DDL | + + + + + + + + + + - + + + | + ALTER_COP | + + + + + - - + + + + + + + | + COMMIT | + + + + - + - + + + + + + + | + + The second array specifies if particular type of request can be satisfied + if there is already waiting request for the backup lock of certain type. + I.e. it specifies what is the priority of different lock types. + + Request | Pending backup lock | + type | S0 S1 S2 S3 S4 F1 F2 D TD SD DD BL AC C | + ----------+---------------------------------------------------------+ + S0 | + - - - - + + + + + + + + + | + S1 | + + + + + + + + + + + + + + | + S2 | + + + + + + + + + + + + + + | + S3 | + + + + + + + + + + + + + + | + S4 | + + + + + + + + + + + + + + | + FTWRL1 | + + + + + + + + + + + + + + | + FTWRL2 | + + + + + + + + + + + + + + | + D | + - - - - - - + + + + + + + | + TD | + + + + + - - + + + + + + + | + SD | + + + + - - - + + + + + + + | + DDL | + + + - - - - + + + + - + + | + BLOCK_DDL | + + + + + + + + + + + + + + | + ALTER_COP | + + + + + - - + + + + + + + | + COMMIT | + + + + - + - + + + + + + + | + + Here: "+" -- means that request can be satisfied + "-" -- means that request can't be satisfied and should wait +*/ + +/* + NOTE: If you add a new MDL_BACKUP_XXX level lock, you have to also add it + to MDL_BACKUP_START in the two arrays below! +*/ + +const MDL_lock::bitmap_t +MDL_lock::MDL_backup_lock::m_granted_incompatible[MDL_BACKUP_END]= +{ + /* MDL_BACKUP_START */ + MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT), + MDL_BIT(MDL_BACKUP_START), + MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_DML), + MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_DML) | MDL_BIT(MDL_BACKUP_DDL), + MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_DML) | MDL_BIT(MDL_BACKUP_SYS_DML) | MDL_BIT(MDL_BACKUP_DDL) | MDL_BIT(MDL_BACKUP_COMMIT), + + /* MDL_BACKUP_FTWRL1 */ + MDL_BIT(MDL_BACKUP_DML) | MDL_BIT(MDL_BACKUP_TRANS_DML) | MDL_BIT(MDL_BACKUP_SYS_DML) | MDL_BIT(MDL_BACKUP_DDL) | MDL_BIT(MDL_BACKUP_ALTER_COPY), + MDL_BIT(MDL_BACKUP_DML) | MDL_BIT(MDL_BACKUP_TRANS_DML) | MDL_BIT(MDL_BACKUP_SYS_DML) | MDL_BIT(MDL_BACKUP_DDL) | MDL_BIT(MDL_BACKUP_ALTER_COPY) | MDL_BIT(MDL_BACKUP_COMMIT), + /* MDL_BACKUP_DML */ + MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2), + MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2), + MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2), + /* MDL_BACKUP_DDL */ + MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2) | MDL_BIT(MDL_BACKUP_BLOCK_DDL), + /* MDL_BACKUP_BLOCK_DDL */ + MDL_BIT(MDL_BACKUP_DDL), + MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2), + /* MDL_BACKUP_COMMIT */ + MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL2) +}; + + +const MDL_lock::bitmap_t +MDL_lock::MDL_backup_lock::m_waiting_incompatible[MDL_BACKUP_END]= +{ + /* MDL_BACKUP_START */ + MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT), + 0, + 0, + 0, + 0, + /* MDL_BACKUP_FTWRL1 */ + 0, + 0, + + /* MDL_BACKUP_DML */ + MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2), + MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2), + MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2), + /* MDL_BACKUP_DDL */ + MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2) | MDL_BIT(MDL_BACKUP_BLOCK_DDL), + /* MDL_BACKUP_BLOCK_DDL */ + 0, + MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2), + /* MDL_BACKUP_COMMIT */ + MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL2) +}; + + +/** Check if request for the metadata lock can be satisfied given its current state. @@ -1584,7 +1755,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, { #ifdef WITH_WSREP if (wsrep_thd_is_BF(requestor_ctx->get_thd(),false) && - key.mdl_namespace() == MDL_key::GLOBAL) + key.mdl_namespace() == MDL_key::BACKUP) { WSREP_DEBUG("global lock granted for BF: %lu %s", thd_get_thread_id(requestor_ctx->get_thd()), @@ -1618,7 +1789,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, else { if (wsrep_thd_is_BF(requestor_ctx->get_thd(), false) && - key.mdl_namespace() == MDL_key::GLOBAL) + key.mdl_namespace() == MDL_key::BACKUP) { WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s", thd_get_thread_id(requestor_ctx->get_thd()), @@ -1739,6 +1910,27 @@ bool MDL_ticket::is_incompatible_when_waiting(enum_mdl_type type) const } +static const LEX_STRING +*get_mdl_lock_name(MDL_key::enum_mdl_namespace mdl_namespace, + enum_mdl_type type) +{ + return mdl_namespace == MDL_key::BACKUP ? + &backup_lock_types[type] : + &lock_types[type]; +} + + +const LEX_STRING *MDL_ticket::get_type_name() const +{ + return get_mdl_lock_name(get_key()->mdl_namespace(), m_type); +} + +const LEX_STRING *MDL_ticket::get_type_name(enum_mdl_type type) const +{ + return get_mdl_lock_name(get_key()->mdl_namespace(), type); +} + + /** Check whether the context already holds a compatible lock ticket on an object. @@ -1772,8 +1964,10 @@ MDL_context::find_ticket(MDL_request *mdl_request, if (mdl_request->key.is_equal(&ticket->m_lock->key) && ticket->has_stronger_or_equal_type(mdl_request->type)) { - DBUG_PRINT("info", ("Adding mdl lock %d to %d", - mdl_request->type, ticket->m_type)); + DBUG_PRINT("info", ("Adding mdl lock %s to %s", + get_mdl_lock_name(mdl_request->key.mdl_namespace(), + mdl_request->type)->str, + ticket->get_type_name()->str)); *result_duration= duration; return ticket; } @@ -1859,11 +2053,8 @@ MDL_context::try_acquire_lock_impl(MDL_request *mdl_request, MDL_ticket *ticket; enum_mdl_duration found_duration; - DBUG_ASSERT(mdl_request->type != MDL_EXCLUSIVE || - is_lock_owner(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE)); - DBUG_ASSERT(mdl_request->ticket == NULL); - /* Don't take chances in production. */ + DBUG_ASSERT(mdl_request->ticket == NULL); mdl_request->ticket= NULL; /* @@ -2064,7 +2255,10 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) MDL_ticket *ticket; MDL_wait::enum_wait_status wait_status; DBUG_ENTER("MDL_context::acquire_lock"); - DBUG_PRINT("enter", ("lock_type: %d", mdl_request->type)); + DBUG_PRINT("enter", ("lock_type: %s timeout: %f", + get_mdl_lock_name(mdl_request->key.mdl_namespace(), + mdl_request->type)->str, + lock_wait_timeout)); if (try_acquire_lock_impl(mdl_request, &ticket)) DBUG_RETURN(TRUE); @@ -2180,6 +2374,7 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout) switch (wait_status) { case MDL_wait::VICTIM: + mdl_dbug_print_locks(); my_error(ER_LOCK_DEADLOCK, MYF(0)); break; case MDL_wait::TIMEOUT: @@ -2319,15 +2514,23 @@ MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket, MDL_savepoint mdl_svp= mdl_savepoint(); bool is_new_ticket; DBUG_ENTER("MDL_context::upgrade_shared_lock"); - DBUG_PRINT("enter",("new_type: %d lock_wait_timeout: %f", new_type, + DBUG_PRINT("enter",("old_type: %s new_type: %s lock_wait_timeout: %f", + mdl_ticket->get_type_name()->str, + mdl_ticket->get_type_name(new_type)->str, lock_wait_timeout)); DEBUG_SYNC(get_thd(), "mdl_upgrade_lock"); /* Do nothing if already upgraded. Used when we FLUSH TABLE under LOCK TABLES and a table is listed twice in LOCK TABLES list. + + In BACKUP namespace upgrade must always happen. Even though + MDL_BACKUP_START is not stronger than MDL_BACKUP_FLUSH from + has_stronger_or_equal_type(), the latter effectively blocks + new MDL_BACKUP_DML while the former doesn't. */ - if (mdl_ticket->has_stronger_or_equal_type(new_type)) + if (mdl_ticket->has_stronger_or_equal_type(new_type) && + mdl_ticket->get_key()->mdl_namespace() != MDL_key::BACKUP) DBUG_RETURN(FALSE); mdl_xlock_request.init(&mdl_ticket->m_lock->key, new_type, @@ -2728,9 +2931,13 @@ void MDL_ticket::downgrade_lock(enum_mdl_type type) if (m_type == type || !has_stronger_or_equal_type(type)) return; - /* Only allow downgrade from EXCLUSIVE and SHARED_NO_WRITE. */ - DBUG_ASSERT(m_type == MDL_EXCLUSIVE || - m_type == MDL_SHARED_NO_WRITE); + /* Only allow downgrade in some specific known cases */ + DBUG_ASSERT((get_key()->mdl_namespace() != MDL_key::BACKUP && + (m_type == MDL_EXCLUSIVE || + m_type == MDL_SHARED_NO_WRITE)) || + (get_key()->mdl_namespace() == MDL_key::BACKUP && + (m_type == MDL_BACKUP_DDL || + m_type == MDL_BACKUP_WAIT_FLUSH))); mysql_prlock_wrlock(&m_lock->m_rwlock); /* @@ -3016,30 +3223,11 @@ bool MDL_context::has_explicit_locks() #ifdef WITH_WSREP static -const char *wsrep_get_mdl_type_name(enum_mdl_type type) -{ - switch (type) - { - case MDL_INTENTION_EXCLUSIVE : return "intention exclusive"; - case MDL_SHARED : return "shared"; - case MDL_SHARED_HIGH_PRIO : return "shared high prio"; - case MDL_SHARED_READ : return "shared read"; - case MDL_SHARED_WRITE : return "shared write"; - case MDL_SHARED_UPGRADABLE : return "shared upgradable"; - case MDL_SHARED_NO_WRITE : return "shared no write"; - case MDL_SHARED_NO_READ_WRITE : return "shared no read write"; - case MDL_EXCLUSIVE : return "exclusive"; - default: break; - } - return "UNKNOWN"; -} - -static const char *wsrep_get_mdl_namespace_name(MDL_key::enum_mdl_namespace ns) { switch (ns) { - case MDL_key::GLOBAL : return "GLOBAL"; + case MDL_key::BACKUP : return "BACKUP"; case MDL_key::SCHEMA : return "SCHEMA"; case MDL_key::TABLE : return "TABLE"; case MDL_key::FUNCTION : return "FUNCTION"; @@ -3047,7 +3235,6 @@ const char *wsrep_get_mdl_namespace_name(MDL_key::enum_mdl_namespace ns) case MDL_key::PACKAGE_BODY: return "PACKAGE BODY"; case MDL_key::TRIGGER : return "TRIGGER"; case MDL_key::EVENT : return "EVENT"; - case MDL_key::COMMIT : return "COMMIT"; case MDL_key::USER_LOCK : return "USER_LOCK"; default: break; } @@ -3060,10 +3247,41 @@ void MDL_ticket::wsrep_report(bool debug) const PSI_stage_info *psi_stage= m_lock->key.get_wait_state_name(); WSREP_DEBUG("MDL ticket: type: %s space: %s db: %s name: %s (%s)", - wsrep_get_mdl_type_name(get_type()), + get_type_name()->str, wsrep_get_mdl_namespace_name(m_lock->key.mdl_namespace()), m_lock->key.db_name(), m_lock->key.name(), psi_stage->m_name); } #endif /* WITH_WSREP */ + + +#ifndef DBUG_OFF + +/* + Print a list of all locks to DBUG trace to help with debugging +*/ + +static int mdl_dbug_print_lock(MDL_ticket *mdl_ticket, void *arg, bool granted) +{ + String *tmp= (String*) arg; + char buffer[128]; + MDL_key *mdl_key= mdl_ticket->get_key(); + size_t length; + length= my_snprintf(buffer, sizeof(buffer)-1, + "\nname: %s db: %.*s key_name: %.*s (%s)", + mdl_ticket->get_type_name()->str, + (int) mdl_key->db_name_length(), mdl_key->db_name(), + (int) mdl_key->name_length(), mdl_key->name(), + granted ? "granted" : "waiting"); + tmp->append(buffer, length); + return 0; +} + +void mdl_dbug_print_locks() +{ + String tmp; + mdl_iterate(mdl_dbug_print_lock, (void*) &tmp); + DBUG_PRINT("mdl_locks", ("%s", tmp.c_ptr())); +} +#endif /* DBUG_OFF */ diff --git a/sql/mdl.h b/sql/mdl.h index 952d97d301c..63cec3b65cf 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -28,6 +28,10 @@ class MDL_lock; class MDL_ticket; bool ok_for_lower_case_names(const char *name); +typedef unsigned short mdl_bitmap_t; +#define MDL_BIT(A) static_cast<mdl_bitmap_t>(1U << A) + + /** @def ENTER_COND(C, M, S, O) Start a wait on a condition. @@ -112,19 +116,25 @@ public: @sa Comments for MDL_object_lock::can_grant_lock() and MDL_scoped_lock::can_grant_lock() for details. + + Scoped locks are database (or schema) locks. + The object locks are for tables, triggers etc. */ enum enum_mdl_type { /* - An intention exclusive metadata lock. Used only for scoped locks. + An intention exclusive metadata lock (IX). Used only for scoped locks. Owner of this type of lock can acquire upgradable exclusive locks on individual objects. Compatible with other IX locks, but is incompatible with scoped S and X locks. + IX lock is taken in SCHEMA namespace when we intend to modify + object metadata. Object may refer table, stored procedure, trigger, + view/etc. */ MDL_INTENTION_EXCLUSIVE= 0, /* - A shared metadata lock. + A shared metadata lock (S). To be used in cases when we are interested in object metadata only and there is no intention to access object data (e.g. for stored routines or during preparing prepared statements). @@ -144,6 +154,9 @@ enum enum_mdl_type { use SNRW locks for them. It also does not arise when S locks are used during PREPARE calls as table-level locks are not acquired in this case. + This lock is taken for global read lock, when caching a stored + procedure in memory for the duration of the transaction and for + tables used by prepared statements. */ MDL_SHARED, /* @@ -164,8 +177,8 @@ enum enum_mdl_type { */ MDL_SHARED_HIGH_PRIO, /* - A shared metadata lock for cases when there is an intention to read data - from table. + A shared metadata lock (SR) for cases when there is an intention to read + data from table. A connection holding this kind of lock can read table metadata and read table data (after acquiring appropriate table and row-level locks). This means that one can only acquire TL_READ, TL_READ_NO_INSERT, and @@ -175,7 +188,7 @@ enum enum_mdl_type { */ MDL_SHARED_READ, /* - A shared metadata lock for cases when there is an intention to modify + A shared metadata lock (SW) for cases when there is an intention to modify (and not just read) data in the table. A connection holding SW lock can read table metadata and modify or read table data (after acquiring appropriate table and row-level locks). @@ -185,8 +198,8 @@ enum enum_mdl_type { */ MDL_SHARED_WRITE, /* - An upgradable shared metadata lock for cases when there is an intention - to modify (and not just read) data in the table. + An upgradable shared metadata lock for cases when there is an + intention to modify (and not just read) data in the table. Can be upgraded to MDL_SHARED_NO_WRITE and MDL_EXCLUSIVE. A connection holding SU lock can read table metadata and modify or read table data (after acquiring appropriate table and row-level locks). @@ -226,7 +239,7 @@ enum enum_mdl_type { */ MDL_SHARED_NO_READ_WRITE, /* - An exclusive metadata lock. + An exclusive metadata lock (X). A connection holding this lock can modify both table's metadata and data. No other type of metadata lock can be granted while this lock is held. To be used for CREATE/DROP/RENAME TABLE statements and for execution of @@ -234,7 +247,75 @@ enum enum_mdl_type { */ MDL_EXCLUSIVE, /* This should be the last !!! */ - MDL_TYPE_END}; + MDL_TYPE_END +}; + + +/** Backup locks */ + +/** + Block concurrent backup +*/ +#define MDL_BACKUP_START enum_mdl_type(0) +/** + Block new write requests to non transactional tables +*/ +#define MDL_BACKUP_FLUSH enum_mdl_type(1) +/** + In addition to previous locks, blocks running requests to non trans tables + Used to wait until all DML usage of on trans tables are finished +*/ +#define MDL_BACKUP_WAIT_FLUSH enum_mdl_type(2) +/** + In addition to previous locks, blocks new DDL's from starting +*/ +#define MDL_BACKUP_WAIT_DDL enum_mdl_type(3) +/** + In addition to previous locks, blocks commits +*/ +#define MDL_BACKUP_WAIT_COMMIT enum_mdl_type(4) + +/** + Blocks (or is blocked by) statements that intend to modify data. Acquired + before commit lock by FLUSH TABLES WITH READ LOCK. +*/ +#define MDL_BACKUP_FTWRL1 enum_mdl_type(5) + +/** + Blocks (or is blocked by) commits. Acquired after global read lock by + FLUSH TABLES WITH READ LOCK. +*/ +#define MDL_BACKUP_FTWRL2 enum_mdl_type(6) + +#define MDL_BACKUP_DML enum_mdl_type(7) +#define MDL_BACKUP_TRANS_DML enum_mdl_type(8) +#define MDL_BACKUP_SYS_DML enum_mdl_type(9) + +/** + Must be acquired by DDL statements that intend to modify data. + Currently it's also used for LOCK TABLES. +*/ +#define MDL_BACKUP_DDL enum_mdl_type(10) + +/** + Blocks new DDL's. Used by backup code to enable DDL logging +*/ +#define MDL_BACKUP_BLOCK_DDL enum_mdl_type(11) + +/* + Statement is modifying data, but will not block MDL_BACKUP_DDL or earlier + BACKUP stages. + ALTER TABLE is started with MDL_BACKUP_DDL, but changed to + MDL_BACKUP_ALTER_COPY while alter table is copying or modifing data. +*/ + +#define MDL_BACKUP_ALTER_COPY enum_mdl_type(12) + +/** + Must be acquired during commit. +*/ +#define MDL_BACKUP_COMMIT enum_mdl_type(13) +#define MDL_BACKUP_END enum_mdl_type(14) /** Duration of metadata lock. */ @@ -282,10 +363,13 @@ public: /** Object namespaces. Sic: when adding a new member to this enum make sure to - update m_namespace_to_wait_state_name array in mdl.cc! + update m_namespace_to_wait_state_name array in mdl.cc and + metadata_lock_info_lock_name in metadata_lock_info.cc! Different types of objects exist in different namespaces + - SCHEMA is for databases (to protect against DROP DATABASE) - TABLE is for tables and views. + - BACKUP is for locking DML, DDL and COMMIT's during BACKUP STAGES - FUNCTION is for stored functions. - PROCEDURE is for stored procedures. - TRIGGER is for triggers. @@ -294,7 +378,7 @@ public: it's necessary to have a separate namespace for them since MDL_key is also used outside of the MDL subsystem. */ - enum enum_mdl_namespace { GLOBAL=0, + enum enum_mdl_namespace { BACKUP=0, SCHEMA, TABLE, FUNCTION, @@ -302,7 +386,6 @@ public: PACKAGE_BODY, TRIGGER, EVENT, - COMMIT, USER_LOCK, /* user level locks. */ /* This should be the last ! */ NAMESPACE_END }; @@ -552,7 +635,8 @@ public: enum enum_deadlock_weight { - DEADLOCK_WEIGHT_DML= 0, + DEADLOCK_WEIGHT_FTWRL1= 0, + DEADLOCK_WEIGHT_DML= 1, DEADLOCK_WEIGHT_DDL= 100 }; /* A helper used to determine which lock request should be aborted. */ @@ -610,6 +694,8 @@ public: m_type == MDL_EXCLUSIVE; } enum_mdl_type get_type() const { return m_type; } + const LEX_STRING *get_type_name() const; + const LEX_STRING *get_type_name(enum_mdl_type type) const; MDL_lock *get_lock() const { return m_lock; } MDL_key *get_key() const; void downgrade_lock(enum_mdl_type type); @@ -1001,6 +1087,13 @@ extern "C" int thd_is_connected(MYSQL_THD thd); */ extern "C" ulong max_write_lock_count; +typedef int (*mdl_iterator_callback)(MDL_ticket *ticket, void *arg, + bool granted); extern MYSQL_PLUGIN_IMPORT -int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg); -#endif +int mdl_iterate(mdl_iterator_callback callback, void *arg); +#ifndef DBUG_OFF +void mdl_dbug_print_locks(); +#else + static inline void mdl_dbug_print_locks() {} +#endif /* DBUG_OFF */ +#endif /* MDL_H */ diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 338f78d8f08..6927b181d92 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -20,6 +20,7 @@ #ifndef MYSQL_CLIENT #include "sql_class.h" // THD +#include "field.h" #endif #define DIG_BASE 1000000000 @@ -95,9 +96,8 @@ int decimal_operation_results(int result, const char *value, const char *type) @retval E_DEC_OOM */ -int my_decimal2string(uint mask, const my_decimal *d, - uint fixed_prec, uint fixed_dec, - char filler, String *str) +int my_decimal::to_string_native(String *str, uint fixed_prec, uint fixed_dec, + char filler, uint mask) const { /* Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a @@ -113,11 +113,11 @@ int my_decimal2string(uint mask, const my_decimal *d, */ int length= (fixed_prec ? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1) - : my_decimal_string_length(d)); + : my_decimal_string_length(this)); int result; if (str->alloc(length)) return check_result(mask, E_DEC_OOM); - result= decimal2string((decimal_t*) d, (char*) str->ptr(), + result= decimal2string(this, (char*) str->ptr(), &length, (int)fixed_prec, fixed_dec, filler); str->length(length); @@ -156,8 +156,8 @@ str_set_decimal(uint mask, const my_decimal *val, { if (!(cs->state & MY_CS_NONASCII)) { - /* For ASCII-compatible character sets we can use my_decimal2string */ - my_decimal2string(mask, val, fixed_prec, fixed_dec, filler, str); + // For ASCII-compatible character sets we can use to_string_native() + val->to_string_native(str, fixed_prec, fixed_dec, filler, mask); str->set_charset(cs); return FALSE; } @@ -165,14 +165,13 @@ str_set_decimal(uint mask, const my_decimal *val, { /* For ASCII-incompatible character sets (like UCS2) we - call my_decimal2string() on a temporary buffer first, + call my_string_native() on a temporary buffer first, and then convert the result to the target character with help of str->copy(). */ uint errors; - char buf[DECIMAL_MAX_STR_LENGTH]; - String tmp(buf, sizeof(buf), &my_charset_latin1); - my_decimal2string(mask, val, fixed_prec, fixed_dec, filler, &tmp); + StringBuffer<DECIMAL_MAX_STR_LENGTH> tmp; + val->to_string_native(&tmp, fixed_prec, fixed_dec, filler, mask); return str->copy(tmp.ptr(), tmp.length(), &my_charset_latin1, cs, &errors); } } @@ -182,7 +181,7 @@ str_set_decimal(uint mask, const my_decimal *val, Convert from decimal to binary representation SYNOPSIS - my_decimal2binary() + to_binary() mask error processing mask d number for conversion bin pointer to buffer where to write result @@ -199,12 +198,11 @@ str_set_decimal(uint mask, const my_decimal *val, E_DEC_OVERFLOW */ -int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec, - int scale) +int my_decimal::to_binary(uchar *bin, int prec, int scale, uint mask) const { int err1= E_DEC_OK, err2; my_decimal rounded; - my_decimal2decimal(d, &rounded); + my_decimal2decimal(this, &rounded); rounded.frac= decimal_actual_fraction(&rounded); if (scale < rounded.frac) { @@ -270,7 +268,8 @@ int str2my_decimal(uint mask, const char *from, size_t length, integer part cannot be larger that 1e18 (otherwise it's an overflow). fractional part is microseconds. */ -bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, ulong *microsec) +bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, + ulong *microsec, ulong *nanosec) { int pos; @@ -288,6 +287,7 @@ bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, ulong *microsec) } *microsec= d->frac ? static_cast<longlong>(d->buf[pos+1]) / (DIG_BASE/1000000) : 0; + *nanosec= d->frac ? static_cast<longlong>(d->buf[pos+1]) % (DIG_BASE/1000000) : 0; if (pos > 1) { @@ -368,6 +368,26 @@ int my_decimal2int(uint mask, const decimal_t *d, bool unsigned_flag, } +longlong my_decimal::to_longlong(bool unsigned_flag) const +{ + longlong result; + my_decimal2int(E_DEC_FATAL_ERROR, this, unsigned_flag, &result); + return result; +} + + +my_decimal::my_decimal(Field *field) +{ + init(); + DBUG_ASSERT(!field->is_null()); +#ifndef DBUG_OFF + my_decimal *dec= +#endif + field->val_decimal(this); + DBUG_ASSERT(dec == this); +} + + #ifndef DBUG_OFF /* routines for debugging print */ diff --git a/sql/my_decimal.h b/sql/my_decimal.h index 22800c24338..c196d43e001 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -29,6 +29,8 @@ #ifndef my_decimal_h #define my_decimal_h +#include "sql_basic_types.h" + #if defined(MYSQL_SERVER) || defined(EMBEDDED_LIBRARY) #include "sql_string.h" /* String */ #endif @@ -39,6 +41,7 @@ C_MODE_START C_MODE_END class String; +class Field; typedef struct st_mysql_time MYSQL_TIME; /** @@ -63,6 +66,25 @@ inline int my_decimal_int_part(uint precision, uint decimals) } +#ifndef MYSQL_CLIENT +int decimal_operation_results(int result, const char *value, const char *type); +#else +inline int decimal_operation_results(int result, const char *value, + const char *type) +{ + return result; +} +#endif /*MYSQL_CLIENT*/ + + +inline int check_result(uint mask, int result) +{ + if (result & mask) + decimal_operation_results(result, "", "DECIMAL"); + return result; +} + + /** my_decimal class limits 'decimal_t' type to what we need in MySQL. @@ -125,6 +147,12 @@ public: { init(); } + my_decimal(const uchar *bin, int prec, int scale) + { + init(); + check_result(E_DEC_FATAL_ERROR, bin2decimal(bin, this, prec, scale)); + } + my_decimal(Field *field); ~my_decimal() { sanity_check(); @@ -141,7 +169,57 @@ public: bool sign() const { return decimal_t::sign; } void sign(bool s) { decimal_t::sign= s; } uint precision() const { return intg + frac; } + void set_zero() + { + /* + We need the up-cast here, since my_decimal has sign() member functions, + which conflicts with decimal_t::sign + (and decimal_make_zero is a macro, rather than a funcion). + */ + decimal_make_zero(static_cast<decimal_t*>(this)); + } + int cmp(const my_decimal *other) const + { + return decimal_cmp(this, other); + } +#ifndef MYSQL_CLIENT + bool to_bool() const + { + return !decimal_is_zero(this); + } + double to_double() const + { + double res; + decimal2double(this, &res); + return res; + } + longlong to_longlong(bool unsigned_flag) const; + // Convert to string returning decimal2string() error code + int to_string_native(String *to, uint prec, uint dec, char filler, + uint mask= E_DEC_FATAL_ERROR) const; + // Convert to string returning the String pointer + String *to_string(String *to, uint prec, uint dec, char filler) const + { + return to_string_native(to, prec, dec, filler) ? NULL : to; + } + String *to_string(String *to) const + { + return to_string(to, 0, 0, 0); + } + String *to_string_round(String *to, uint scale, my_decimal *round_buff) const + { + (void) round_to(round_buff, scale, HALF_UP); // QQ: check result? + return round_buff->to_string(to); + } + int round_to(my_decimal *to, uint scale, decimal_round_mode mode, + int mask= E_DEC_FATAL_ERROR) const + { + return check_result(mask, decimal_round(this, to, (int) scale, mode)); + } + int to_binary(uchar *bin, int prec, int scale, + uint mask= E_DEC_FATAL_ERROR) const; +#endif /** Swap two my_decimal values */ void swap(my_decimal &rhs) { @@ -164,16 +242,6 @@ bool str_set_decimal(uint mask, const my_decimal *val, uint fixed_prec, extern my_decimal decimal_zero; -#ifndef MYSQL_CLIENT -int decimal_operation_results(int result, const char *value, const char *type); -#else -inline int decimal_operation_results(int result, const char *value, - const char *type) -{ - return result; -} -#endif /*MYSQL_CLIENT*/ - inline void max_my_decimal(my_decimal *to, int precision, int frac) { @@ -187,13 +255,6 @@ inline void max_internal_decimal(my_decimal *to) max_my_decimal(to, DECIMAL_MAX_PRECISION, 0); } -inline int check_result(uint mask, int result) -{ - if (result & mask) - decimal_operation_results(result, "", "DECIMAL"); - return result; -} - inline int check_result_and_overflow(uint mask, int result, my_decimal *val) { if (check_result(mask, result) & E_DEC_OVERFLOW) @@ -271,10 +332,6 @@ void my_decimal2decimal(const my_decimal *from, my_decimal *to) } -int my_decimal2binary(uint mask, const my_decimal *d, uchar *bin, int prec, - int scale); - - inline int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, int prec, int scale) @@ -286,12 +343,7 @@ int binary2my_decimal(uint mask, const uchar *bin, my_decimal *d, int prec, inline int my_decimal_set_zero(my_decimal *d) { - /* - We need the up-cast here, since my_decimal has sign() member functions, - which conflicts with decimal_t::sign - (and decimal_make_zero is a macro, rather than a funcion). - */ - decimal_make_zero(static_cast<decimal_t*>(d)); + d->set_zero(); return 0; } @@ -303,42 +355,15 @@ bool my_decimal_is_zero(const my_decimal *decimal_value) } -inline -int my_decimal_round(uint mask, const my_decimal *from, int scale, - bool truncate, my_decimal *to) -{ - return check_result(mask, decimal_round(from, to, scale, - (truncate ? TRUNCATE : HALF_UP))); -} - - -inline -int my_decimal_floor(uint mask, const my_decimal *from, my_decimal *to) -{ - return check_result(mask, decimal_round(from, to, 0, FLOOR)); -} - - -inline -int my_decimal_ceiling(uint mask, const my_decimal *from, my_decimal *to) -{ - return check_result(mask, decimal_round(from, to, 0, CEILING)); -} - - inline bool str_set_decimal(const my_decimal *val, String *str, CHARSET_INFO *cs) { return str_set_decimal(E_DEC_FATAL_ERROR, val, 0, 0, 0, str, cs); } -#ifndef MYSQL_CLIENT -class String; -int my_decimal2string(uint mask, const my_decimal *d, uint fixed_prec, - uint fixed_dec, char filler, String *str); -#endif -bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, ulong *microsec); +bool my_decimal2seconds(const my_decimal *d, ulonglong *sec, + ulong *microsec, ulong *nanosec); my_decimal *seconds2my_decimal(bool sign, ulonglong sec, ulong microsec, my_decimal *d); diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc index fc8bce08276..718e49969e0 100644 --- a/sql/mysql_install_db.cc +++ b/sql/mysql_install_db.cc @@ -198,7 +198,7 @@ int main(int argc, char **argv) die("database creation failed"); } - printf("Creation of the database was successful"); + printf("Creation of the database was successful\n"); return 0; } @@ -343,17 +343,19 @@ static int create_myini() static const char update_root_passwd_part1[]= - "UPDATE mysql.user SET Password = PASSWORD("; + "UPDATE mysql.global_priv SET priv=json_set(priv," + "'$.plugin','mysql_native_password'," + "'$.authentication_string',PASSWORD("; static const char update_root_passwd_part2[]= - ") where User='root';\n"; + ")) where User='root';\n"; static const char remove_default_user_cmd[]= "DELETE FROM mysql.user where User='';\n"; static const char allow_remote_root_access_cmd[]= - "CREATE TEMPORARY TABLE tmp_user LIKE user;\n" - "INSERT INTO tmp_user SELECT * from user where user='root' " + "CREATE TEMPORARY TABLE tmp_user LIKE global_priv;\n" + "INSERT INTO tmp_user SELECT * from global_priv where user='root' " " AND host='localhost';\n" "UPDATE tmp_user SET host='%';\n" - "INSERT INTO user SELECT * FROM tmp_user;\n" + "INSERT INTO global_priv SELECT * FROM tmp_user;\n" "DROP TABLE tmp_user;\n"; static const char end_of_script[]="-- end."; diff --git a/sql/mysql_upgrade_service.cc b/sql/mysql_upgrade_service.cc index 9ea78accf44..58383df9c56 100644 --- a/sql/mysql_upgrade_service.cc +++ b/sql/mysql_upgrade_service.cc @@ -495,7 +495,7 @@ int main(int argc, char **argv) old_mysqld_exe_exists?",this can take some time":"(skipped)"); char socket_param[FN_REFLEN]; - sprintf_s(socket_param, "--socket=mysql_upgrade_service_%d", + sprintf_s(socket_param, "--socket=mysql_upgrade_service_%u", GetCurrentProcessId()); DWORD start_duration_ms = 0; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6f0f517eade..db07555196c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -117,6 +117,10 @@ #include <poll.h> #endif +#ifdef _WIN32 +#include <handle_connections_win.h> +#endif + #include <my_service_manager.h> #define mysqld_charset &my_charset_latin1 @@ -319,23 +323,6 @@ MY_TIMER_INFO sys_timer_info; /* static variables */ #ifdef HAVE_PSI_INTERFACE -#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) -static PSI_thread_key key_thread_handle_con_namedpipes; -static PSI_cond_key key_COND_handler_count; -#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */ - -#if defined(HAVE_SMEM) && !defined(EMBEDDED_LIBRARY) -static PSI_thread_key key_thread_handle_con_sharedmem; -#endif /* HAVE_SMEM && !EMBEDDED_LIBRARY */ - -#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) -static PSI_thread_key key_thread_handle_con_sockets; -#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */ - -#ifdef __WIN__ -static PSI_thread_key key_thread_handle_shutdown; -#endif /* __WIN__ */ - #ifdef HAVE_OPENSSL10 static PSI_rwlock_key key_rwlock_openssl; #endif @@ -371,6 +358,7 @@ static char *character_set_filesystem_name; static char *lc_messages; static char *lc_time_names_name; char *my_bind_addr_str; +int server_socket_ai_family; static char *default_collation_name; char *default_storage_engine, *default_tmp_storage_engine; char *enforced_storage_engine=NULL; @@ -580,6 +568,7 @@ ulong opt_binlog_commit_wait_count= 0; ulong opt_binlog_commit_wait_usec= 0; ulong opt_slave_parallel_max_queued= 131072; my_bool opt_gtid_ignore_duplicates= FALSE; +uint opt_gtid_cleanup_batch_size= 64; const double log_10[] = { 1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009, @@ -744,7 +733,6 @@ mysql_mutex_t LOCK_thread_count; other threads. It also protects these variables: - handler_count in_bootstrap select_thread_in_use slave_init_thread_running @@ -782,6 +770,7 @@ mysql_mutex_t LOCK_prepared_stmt_count; mysql_mutex_t LOCK_des_key_file; #endif mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; +mysql_rwlock_t LOCK_ssl_refresh; mysql_prlock_t LOCK_system_variables_hash; mysql_cond_t COND_thread_count, COND_start_thread; pthread_t signal_thread; @@ -1045,7 +1034,8 @@ PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger, key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave, key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock, key_LOCK_SEQUENCE, - key_rwlock_LOCK_vers_stats, key_rwlock_LOCK_stat_serial; + key_rwlock_LOCK_vers_stats, key_rwlock_LOCK_stat_serial, + key_rwlock_LOCK_ssl_refresh; static PSI_rwlock_info all_server_rwlocks[]= { @@ -1060,7 +1050,8 @@ static PSI_rwlock_info all_server_rwlocks[]= { &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL}, { &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0}, { &key_rwlock_LOCK_vers_stats, "Vers_field_stats::lock", 0}, - { &key_rwlock_LOCK_stat_serial, "TABLE_SHARE::LOCK_stat_serial", 0} + { &key_rwlock_LOCK_stat_serial, "TABLE_SHARE::LOCK_stat_serial", 0}, + { &key_rwlock_LOCK_ssl_refresh, "LOCK_ssl_refresh", PSI_FLAG_GLOBAL } }; #ifdef HAVE_MMAP @@ -1098,9 +1089,6 @@ PSI_cond_key key_COND_ack_receiver; static PSI_cond_info all_server_conds[]= { -#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) - { &key_COND_handler_count, "COND_handler_count", PSI_FLAG_GLOBAL}, -#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */ #ifdef HAVE_MMAP { &key_PAGE_cond, "PAGE::cond", 0}, { &key_COND_active, "TC_LOG_MMAP::COND_active", 0}, @@ -1161,22 +1149,6 @@ PSI_thread_key key_thread_ack_receiver; static PSI_thread_info all_server_threads[]= { -#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) - { &key_thread_handle_con_namedpipes, "con_named_pipes", PSI_FLAG_GLOBAL}, -#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */ - -#if defined(HAVE_SMEM) && !defined(EMBEDDED_LIBRARY) - { &key_thread_handle_con_sharedmem, "con_shared_mem", PSI_FLAG_GLOBAL}, -#endif /* HAVE_SMEM && !EMBEDDED_LIBRARY */ - -#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) - { &key_thread_handle_con_sockets, "con_sockets", PSI_FLAG_GLOBAL}, -#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */ - -#ifdef __WIN__ - { &key_thread_handle_shutdown, "shutdown", PSI_FLAG_GLOBAL}, -#endif /* __WIN__ */ - { &key_thread_bootstrap, "bootstrap", PSI_FLAG_GLOBAL}, { &key_thread_delayed_insert, "delayed_insert", 0}, { &key_thread_handle_manager, "manager", PSI_FLAG_GLOBAL}, @@ -1419,10 +1391,10 @@ void Buffered_logs::print() /** Logs reported before a logger is available. */ static Buffered_logs buffered_logs; -static MYSQL_SOCKET unix_sock, base_ip_sock, extra_ip_sock; struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD() #ifndef EMBEDDED_LIBRARY +MYSQL_SOCKET unix_sock, base_ip_sock, extra_ip_sock; /** Error reporter that buffer log messages. @param level log message level @@ -1478,27 +1450,18 @@ static pthread_t select_thread; #undef getpid #include <process.h> -static mysql_cond_t COND_handler_count; -static uint handler_count; static bool start_mode=0, use_opt_args; static int opt_argc; static char **opt_argv; #if !defined(EMBEDDED_LIBRARY) -static HANDLE hEventShutdown; +HANDLE hEventShutdown; static char shutdown_event_name[40]; #include "nt_servc.h" static NTService Service; ///< Service object for WinNT #endif /* EMBEDDED_LIBRARY */ #endif /* __WIN__ */ -#ifdef _WIN32 -#include <sddl.h> /* ConvertStringSecurityDescriptorToSecurityDescriptor */ -static char pipe_name[512]; -static SECURITY_ATTRIBUTES saPipeSecurity; -static HANDLE hPipe = INVALID_HANDLE_VALUE; -#endif - #ifndef EMBEDDED_LIBRARY bool mysqld_embedded=0; #else @@ -1519,11 +1482,7 @@ int deny_severity = LOG_WARNING; ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE; Query_cache query_cache; #endif -#ifdef HAVE_SMEM -const char *shared_memory_base_name= default_shared_memory_base_name; -my_bool opt_enable_shared_memory; -HANDLE smem_event_connect_request= 0; -#endif + my_bool opt_use_ssl = 0; char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL, @@ -1575,19 +1534,13 @@ extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *); static int init_thread_environment(); static char *get_relative_path(const char *path); static int fix_paths(void); +#ifndef _WIN32 void handle_connections_sockets(); -#ifdef _WIN32 -pthread_handler_t handle_connections_sockets_thread(void *arg); #endif + pthread_handler_t kill_server_thread(void *arg); static void bootstrap(MYSQL_FILE *file); static bool read_init_file(char *file_name); -#ifdef _WIN32 -pthread_handler_t handle_connections_namedpipes(void *arg); -#endif -#ifdef HAVE_SMEM -pthread_handler_t handle_connections_shared_memory(void *arg); -#endif pthread_handler_t handle_slave(void *arg); static void clean_up(bool print_message); static int test_if_case_insensitive(const char *dir_name); @@ -1622,6 +1575,7 @@ static void close_connections(void) kill_cached_threads++; flush_thread_cache(); + /* kill connection thread */ #if !defined(__WIN__) DBUG_PRINT("quit", ("waiting for select thread: %lu", @@ -1671,30 +1625,7 @@ static void close_connections(void) extra_ip_sock= MYSQL_INVALID_SOCKET; } } -#ifdef _WIN32 - if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe) - { - HANDLE temp; - DBUG_PRINT("quit", ("Closing named pipes") ); - - /* Create connection to the handle named pipe handler to break the loop */ - if ((temp = CreateFile(pipe_name, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - 0, - NULL )) != INVALID_HANDLE_VALUE) - { - WaitNamedPipe(pipe_name, 1000); - DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT; - SetNamedPipeHandleState(temp, &dwMode, NULL, NULL); - CancelIo(temp); - DisconnectNamedPipe(temp); - CloseHandle(temp); - } - } -#endif + #ifdef HAVE_SYS_UN_H if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET) { @@ -1941,12 +1872,6 @@ void kill_mysql(THD *thd) { DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError())); } - /* - or: - HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown"); - SetEvent(hEventShutdown); - CloseHandle(hEvent); - */ } #endif #elif defined(HAVE_PTHREAD_KILL) @@ -1978,7 +1903,7 @@ void kill_mysql(THD *thd) /** Force server down. Kill all connections and threads and exit. - @param sig_ptr Signal number that caused kill_server to be called. + @param sig Signal number that caused kill_server to be called. @note A signal number of 0 mean that the function was not called @@ -1986,22 +1911,14 @@ void kill_mysql(THD *thd) or stop, we just want to kill the server. */ -#if !defined(__WIN__) -static void *kill_server(void *sig_ptr) -#define RETURN_FROM_KILL_SERVER return 0 -#else -static void __cdecl kill_server(int sig_ptr) -#define RETURN_FROM_KILL_SERVER return -#endif +static void kill_server(int sig) { DBUG_ENTER("kill_server"); #ifndef EMBEDDED_LIBRARY - int sig=(int) (long) sig_ptr; // This is passed a int // if there is a signal during the kill in progress, ignore the other if (kill_in_progress) // Safety { - DBUG_LEAVE; - RETURN_FROM_KILL_SERVER; + DBUG_VOID_RETURN; } kill_in_progress=TRUE; abort_loop=1; // This should be set @@ -2018,21 +1935,6 @@ static void __cdecl kill_server(int sig_ptr) else sql_print_error(ER_DEFAULT(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */ -#ifdef HAVE_SMEM - /* - Send event to smem_event_connect_request for aborting - */ - if (opt_enable_shared_memory) - { - if (!SetEvent(smem_event_connect_request)) - { - DBUG_PRINT("error", - ("Got error: %ld from SetEvent of smem_event_connect_request", - GetLastError())); - } - } -#endif - /* Stop wsrep threads in case they are running. */ if (wsrep_running_threads > 0) { @@ -2050,20 +1952,9 @@ static void __cdecl kill_server(int sig_ptr) else unireg_end(); - /* purecov: begin deadcode */ - DBUG_LEAVE; // Must match DBUG_ENTER() - my_thread_end(); - pthread_exit(0); - /* purecov: end */ - - RETURN_FROM_KILL_SERVER; // Avoid compiler warnings +#endif /* EMBEDDED_LIBRARY*/ -#else /* EMBEDDED_LIBRARY*/ - - DBUG_LEAVE; - RETURN_FROM_KILL_SERVER; - -#endif /* EMBEDDED_LIBRARY */ + DBUG_VOID_RETURN; } @@ -2072,11 +1963,9 @@ pthread_handler_t kill_server_thread(void *arg __attribute__((unused))) { my_thread_init(); // Initialize new thread kill_server(0); - /* purecov: begin deadcode */ my_thread_end(); pthread_exit(0); return 0; - /* purecov: end */ } #endif @@ -2122,13 +2011,7 @@ static void clean_up_error_log_mutex() void unireg_end(void) { clean_up(1); - my_thread_end(); sd_notify(0, "STATUS=MariaDB server is down"); -#if defined(SIGNALS_DONT_BREAK_READ) - exit(0); -#else - pthread_exit(0); // Exit is in main thread -#endif } @@ -2396,6 +2279,7 @@ static void clean_up_mutexes() mysql_mutex_destroy(&LOCK_rpl_status); #endif /* HAVE_REPLICATION */ mysql_mutex_destroy(&LOCK_active_mi); + mysql_rwlock_destroy(&LOCK_ssl_refresh); mysql_rwlock_destroy(&LOCK_sys_init_connect); mysql_rwlock_destroy(&LOCK_sys_init_slave); mysql_mutex_destroy(&LOCK_global_system_variables); @@ -2623,6 +2507,7 @@ static MYSQL_SOCKET activate_tcp_port(uint port) } else { + server_socket_ai_family= a->ai_family; sql_print_information("Server socket created on IP: '%s'.", (const char *) ip_addr); break; @@ -2749,53 +2634,16 @@ static void network_init(void) extra_ip_sock= activate_tcp_port(mysqld_extra_port); } -#ifdef _WIN32 - /* create named pipe */ - if (mysqld_unix_port[0] && !opt_bootstrap && - opt_enable_named_pipe) - { - - strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\", - mysqld_unix_port, NullS); - /* - Create a security descriptor for pipe. - - Use low integrity level, so that it is possible to connect - from any process. - - Give Everyone read/write access to pipe. - */ - if (!ConvertStringSecurityDescriptorToSecurityDescriptor( - "S:(ML;; NW;;; LW) D:(A;; FRFW;;; WD)", - SDDL_REVISION_1, &saPipeSecurity.lpSecurityDescriptor, NULL)) - { - sql_perror("Can't start server : Initialize security descriptor"); - unireg_abort(1); - } - saPipeSecurity.nLength = sizeof(SECURITY_ATTRIBUTES); - saPipeSecurity.bInheritHandle = FALSE; - if ((hPipe= CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, - PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, - (int) global_system_variables.net_buffer_length, - (int) global_system_variables.net_buffer_length, - NMPWAIT_USE_DEFAULT_WAIT, - &saPipeSecurity)) == INVALID_HANDLE_VALUE) - { - sql_perror("Create named pipe failed"); - unireg_abort(1); - } - } -#endif - #if defined(HAVE_SYS_UN_H) /* ** Create the UNIX socket */ if (mysqld_unix_port[0] && !opt_bootstrap) { + size_t port_len; DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port)); - if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1)) + if ((port_len= strlen(mysqld_unix_port)) > sizeof(UNIXaddr.sun_path) - 1) { sql_print_error("The socket file path is too long (> %u): %s", (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); @@ -2813,14 +2661,26 @@ static void network_init(void) bzero((char*) &UNIXaddr, sizeof(UNIXaddr)); UNIXaddr.sun_family = AF_UNIX; strmov(UNIXaddr.sun_path, mysqld_unix_port); - (void) unlink(mysqld_unix_port); +#if defined(__linux__) + /* Abstract socket */ + if (mysqld_unix_port[0] == '@') + { + UNIXaddr.sun_path[0]= '\0'; + port_len+= offsetof(struct sockaddr_un, sun_path); + } + else +#endif + { + (void) unlink(mysqld_unix_port); + port_len= sizeof(UNIXaddr); + } arg= 1; (void) mysql_socket_setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR, (char*)&arg, sizeof(arg)); umask(0); if (mysql_socket_bind(unix_sock, reinterpret_cast<struct sockaddr *>(&UNIXaddr), - sizeof(UNIXaddr)) < 0) + port_len) < 0) { sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */ sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port); @@ -3546,14 +3406,15 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) (void) pthread_sigmask(SIG_BLOCK,&set,NULL); for (;;) { - int error; // Used when debugging + int error; + int origin; if (shutdown_in_progress && !abort_loop) { sig= SIGTERM; error=0; } else - while ((error=my_sigwait(&set,&sig)) == EINTR) ; + while ((error= my_sigwait(&set, &sig, &origin)) == EINTR) /* no-op */; if (cleanup_done) { DBUG_PRINT("quit",("signal_handler: calling my_thread_end()")); @@ -3588,12 +3449,12 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) sql_print_error("Can't create thread to kill server (errno= %d)", error); #else - kill_server((void*) sig); // MIT THREAD has a alarm thread + kill_server(sig); // MIT THREAD has a alarm thread #endif } break; case SIGHUP: - if (!abort_loop) + if (!abort_loop && origin != SI_KERNEL) { int not_used; mysql_print_status(); // Print some debug info @@ -3602,21 +3463,14 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) REFRESH_GRANT | REFRESH_THREADS | REFRESH_HOSTS), (TABLE_LIST*) 0, ¬_used); // Flush logs - } - /* reenable logs after the options were reloaded */ - if (log_output_options & LOG_NONE) - { - logger.set_handlers(LOG_FILE, - global_system_variables.sql_log_slow ? - LOG_TABLE : LOG_NONE, - opt_log ? LOG_TABLE : LOG_NONE); - } - else - { - logger.set_handlers(LOG_FILE, - global_system_variables.sql_log_slow ? - log_output_options : LOG_NONE, - opt_log ? log_output_options : LOG_NONE); + + /* reenable logs after the options were reloaded */ + ulonglong fixed_log_output_options= + log_output_options & LOG_NONE ? LOG_TABLE : log_output_options; + + logger.set_handlers(LOG_FILE, global_system_variables.sql_log_slow + ? fixed_log_output_options : LOG_NONE, + opt_log ? fixed_log_output_options : LOG_NONE); } break; #ifdef USE_ONE_SIGNAL_HAND @@ -3650,7 +3504,7 @@ extern "C" void my_message_sql(uint error, const char *str, myf MyFlags); void my_message_sql(uint error, const char *str, myf MyFlags) { - THD *thd= current_thd; + THD *thd= MyFlags & ME_ERROR_LOG_ONLY ? NULL : current_thd; Sql_condition::enum_warning_level level; sql_print_message_func func; DBUG_ENTER("my_message_sql"); @@ -3659,13 +3513,15 @@ void my_message_sql(uint error, const char *str, myf MyFlags) DBUG_ASSERT(str != NULL); DBUG_ASSERT(error != 0); + DBUG_ASSERT((MyFlags & ~(ME_BELL | ME_ERROR_LOG | ME_ERROR_LOG_ONLY | + ME_NOTE | ME_WARNING | ME_FATAL)) == 0); - if (MyFlags & ME_JUST_INFO) + if (MyFlags & ME_NOTE) { level= Sql_condition::WARN_LEVEL_NOTE; func= sql_print_information; } - else if (MyFlags & ME_JUST_WARNING) + else if (MyFlags & ME_WARNING) { level= Sql_condition::WARN_LEVEL_WARN; func= sql_print_warning; @@ -3678,7 +3534,7 @@ void my_message_sql(uint error, const char *str, myf MyFlags) if (likely(thd)) { - if (unlikely(MyFlags & ME_FATALERROR)) + if (unlikely(MyFlags & ME_FATAL)) thd->is_fatal_error= 1; (void) thd->raise_condition(error, NULL, level, str); } @@ -3688,7 +3544,7 @@ void my_message_sql(uint error, const char *str, myf MyFlags) /* When simulating OOM, skip writing to error log to avoid mtr errors */ DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_VOID_RETURN;); - if (unlikely(!thd) || thd->log_all_errors || (MyFlags & ME_NOREFRESH)) + if (unlikely(!thd) || thd->log_all_errors || (MyFlags & ME_ERROR_LOG)) (*func)("%s: %s", my_progname_short, str); /* purecov: inspected */ DBUG_VOID_RETURN; } @@ -3702,23 +3558,6 @@ void *my_str_malloc_mysqld(size_t size) } -#ifdef __WIN__ - -pthread_handler_t handle_shutdown(void *arg) -{ - MSG msg; - my_thread_init(); - - /* this call should create the message queue for this thread */ - PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE); -#if !defined(EMBEDDED_LIBRARY) - if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0) -#endif /* EMBEDDED_LIBRARY */ - kill_server(MYSQL_KILL_SIGNAL); - return 0; -} -#endif - #include <mysqld_default_groups.h> #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY) @@ -3826,6 +3665,7 @@ SHOW_VAR com_status_vars[]= { {"alter_user", STMT_STATUS(SQLCOM_ALTER_USER)}, {"analyze", STMT_STATUS(SQLCOM_ANALYZE)}, {"assign_to_keycache", STMT_STATUS(SQLCOM_ASSIGN_TO_KEYCACHE)}, + {"backup", STMT_STATUS(SQLCOM_BACKUP)}, {"begin", STMT_STATUS(SQLCOM_BEGIN)}, {"binlog", STMT_STATUS(SQLCOM_BINLOG_BASE64_EVENT)}, {"call_procedure", STMT_STATUS(SQLCOM_CALL)}, @@ -4121,9 +3961,28 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) else update_global_memory_status(size); } + +int json_escape_string(const char *str,const char *str_end, + char *json, char *json_end) +{ + return json_escape(system_charset_info, + (const uchar *) str, (const uchar *) str_end, + &my_charset_utf8mb4_bin, + (uchar *) json, (uchar *) json_end); } +int json_unescape_json(const char *json_str, const char *json_end, + char *res, char *res_end) +{ + return json_unescape(&my_charset_utf8mb4_bin, + (const uchar *) json_str, (const uchar *) json_end, + system_charset_info, (uchar *) res, (uchar *) res_end); +} + +} /*extern "C"*/ + + /** Create a replication file name or base for file names. @@ -4833,6 +4692,7 @@ static int init_thread_environment() #endif /* HAVE_OPENSSL */ mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect); mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave); + mysql_rwlock_init(key_rwlock_LOCK_ssl_refresh, &LOCK_ssl_refresh); mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant); mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL); mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL); @@ -4926,6 +4786,60 @@ static void openssl_lock(int mode, openssl_lock_t *lock, const char *file, } #endif /* HAVE_OPENSSL10 */ + +struct SSL_ACCEPTOR_STATS +{ + long accept; + long accept_good; + long cache_size; + long verify_mode; + long verify_depth; + long zero; + const char *session_cache_mode; + + SSL_ACCEPTOR_STATS(): + accept(),accept_good(),cache_size(),verify_mode(),verify_depth(),zero(), + session_cache_mode("NONE") + { + } + + void init() + { + DBUG_ASSERT(ssl_acceptor_fd !=0 && ssl_acceptor_fd->ssl_context != 0); + SSL_CTX *ctx= ssl_acceptor_fd->ssl_context; + accept= 0; + accept_good= 0; + verify_mode= SSL_CTX_get_verify_mode(ctx); + verify_depth= SSL_CTX_get_verify_depth(ctx); + cache_size= SSL_CTX_sess_get_cache_size(ctx); + switch (SSL_CTX_get_session_cache_mode(ctx)) + { + case SSL_SESS_CACHE_OFF: + session_cache_mode= "OFF"; break; + case SSL_SESS_CACHE_CLIENT: + session_cache_mode= "CLIENT"; break; + case SSL_SESS_CACHE_SERVER: + session_cache_mode= "SERVER"; break; + case SSL_SESS_CACHE_BOTH: + session_cache_mode= "BOTH"; break; + case SSL_SESS_CACHE_NO_AUTO_CLEAR: + session_cache_mode= "NO_AUTO_CLEAR"; break; + case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP: + session_cache_mode= "NO_INTERNAL_LOOKUP"; break; + default: + session_cache_mode= "Unknown"; break; + } + } +}; + +static SSL_ACCEPTOR_STATS ssl_acceptor_stats; +void ssl_acceptor_stats_update(int sslaccept_ret) +{ + statistic_increment(ssl_acceptor_stats.accept, &LOCK_status); + if (!sslaccept_ret) + statistic_increment(ssl_acceptor_stats.accept_good,&LOCK_status); +} + static void init_ssl() { #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) @@ -4946,6 +4860,9 @@ static void init_ssl() opt_use_ssl = 0; have_ssl= SHOW_OPTION_DISABLED; } + else + ssl_acceptor_stats.init(); + if (global_system_variables.log_warnings > 0) { ulong err; @@ -4964,6 +4881,34 @@ static void init_ssl() #endif /* HAVE_OPENSSL && ! EMBEDDED_LIBRARY */ } +/* Reinitialize SSL (FLUSH SSL) */ +int reinit_ssl() +{ +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) + if (!opt_use_ssl) + return 0; + + enum enum_ssl_init_error error = SSL_INITERR_NOERROR; + st_VioSSLFd *new_fd = new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert, + opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher, &error, opt_ssl_crl, opt_ssl_crlpath); + + if (!new_fd) + { + my_printf_error(ER_UNKNOWN_ERROR, "Failed to refresh SSL, error: %s", MYF(0), + sslGetErrString(error)); +#ifndef HAVE_YASSL + ERR_clear_error(); +#endif + return 1; + } + mysql_rwlock_wrlock(&LOCK_ssl_refresh); + free_vio_ssl_acceptor_fd(ssl_acceptor_fd); + ssl_acceptor_fd= new_fd; + ssl_acceptor_stats.init(); + mysql_rwlock_unlock(&LOCK_ssl_refresh); + return 0; +#endif +} static void end_ssl() { @@ -5094,6 +5039,7 @@ static int init_server_components() my_rnd_init(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2); setup_fpu(); init_thr_lock(); + backup_init(); #ifndef EMBEDDED_LIBRARY if (init_thr_timer(thread_scheduler->max_threads + extra_max_connections)) @@ -5623,100 +5569,17 @@ static int init_server_components() #ifndef EMBEDDED_LIBRARY - -static void create_shutdown_thread() +#ifdef _WIN32 +static void create_shutdown_event() { -#ifdef __WIN__ hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name); - pthread_t hThread; - int error; - if (unlikely((error= mysql_thread_create(key_thread_handle_shutdown, - &hThread, &connection_attrib, - handle_shutdown, 0)))) - sql_print_warning("Can't create thread to handle shutdown requests" - " (errno= %d)", error); - // On "Stop Service" we have to do regular shutdown Service.SetShutdownEvent(hEventShutdown); -#endif /* __WIN__ */ } - -#endif /* EMBEDDED_LIBRARY */ - -#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) -static void handle_connections_methods() -{ - pthread_t hThread; - int error; - DBUG_ENTER("handle_connections_methods"); - if (hPipe == INVALID_HANDLE_VALUE && - (!have_tcpip || opt_disable_networking) && - !opt_enable_shared_memory) - { - sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS"); - unireg_abort(1); // Will not return - } - - mysql_mutex_lock(&LOCK_start_thread); - mysql_cond_init(key_COND_handler_count, &COND_handler_count, NULL); - handler_count=0; - if (hPipe != INVALID_HANDLE_VALUE) - { - handler_count++; - if ((error= mysql_thread_create(key_thread_handle_con_namedpipes, - &hThread, &connection_attrib, - handle_connections_namedpipes, 0))) - { - sql_print_warning("Can't create thread to handle named pipes" - " (errno= %d)", error); - handler_count--; - } - } - if (have_tcpip && !opt_disable_networking) - { - handler_count++; - if ((error= mysql_thread_create(key_thread_handle_con_sockets, - &hThread, &connection_attrib, - handle_connections_sockets_thread, 0))) - { - sql_print_warning("Can't create thread to handle TCP/IP", - " (errno= %d)", error); - handler_count--; - } - } -#ifdef HAVE_SMEM - if (opt_enable_shared_memory) - { - handler_count++; - if ((error= mysql_thread_create(key_thread_handle_con_sharedmem, - &hThread, &connection_attrib, - handle_connections_shared_memory, 0))) - { - sql_print_warning("Can't create thread to handle shared memory", - " (errno= %d)", error); - handler_count--; - } - } +#else /*_WIN32*/ +#define create_shutdown_event() #endif - - while (handler_count > 0) - mysql_cond_wait(&COND_handler_count, &LOCK_start_thread); - mysql_mutex_unlock(&LOCK_start_thread); - DBUG_VOID_RETURN; -} - -void decrement_handler_count() -{ - mysql_mutex_lock(&LOCK_start_thread); - if (--handler_count == 0) - mysql_cond_signal(&COND_handler_count); - mysql_mutex_unlock(&LOCK_start_thread); - my_thread_end(); -} -#else -#define decrement_handler_count() -#endif /* defined(_WIN32) || defined(HAVE_SMEM) */ - +#endif /* EMBEDDED_LIBRARY */ #ifndef EMBEDDED_LIBRARY @@ -6119,7 +5982,7 @@ int mysqld_main(int argc, char **argv) } } - create_shutdown_thread(); + create_shutdown_event(); start_handle_manager(); /* Copy default global rpl_filter to global_rpl_filter */ @@ -6188,11 +6051,12 @@ int mysqld_main(int argc, char **argv) /* Memory used when everything is setup */ start_memory_used= global_status_var.global_memory_used; -#if defined(_WIN32) || defined(HAVE_SMEM) - handle_connections_methods(); +#ifdef _WIN32 + handle_connections_win(); + kill_server(0); #else handle_connections_sockets(); -#endif /* _WIN32 || HAVE_SMEM */ +#endif /* _WIN32 */ /* (void) pthread_attr_destroy(&connection_attrib); */ @@ -6601,7 +6465,7 @@ void create_thread_to_handle_connection(CONNECT *connect) @param[in,out] thd Thread handle of future thread. */ -static void create_new_thread(CONNECT *connect) +void create_new_thread(CONNECT *connect) { DBUG_ENTER("create_new_thread"); @@ -6669,18 +6533,107 @@ inline void kill_broken_server() #ifndef EMBEDDED_LIBRARY +void handle_accepted_socket(MYSQL_SOCKET new_sock, MYSQL_SOCKET sock) +{ + CONNECT *connect; + bool is_unix_sock; + +#ifdef FD_CLOEXEC + (void) fcntl(mysql_socket_getfd(new_sock), F_SETFD, FD_CLOEXEC); +#endif + +#ifdef HAVE_LIBWRAP + { + if (mysql_socket_getfd(sock) == mysql_socket_getfd(base_ip_sock) || + mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) + { + struct request_info req; + signal(SIGCHLD, SIG_DFL); + request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, + mysql_socket_getfd(new_sock), NULL); + my_fromhost(&req); + if (!my_hosts_access(&req)) + { + /* + This may be stupid but refuse() includes an exit(0) + which we surely don't want... + clean_exit() - same stupid thing ... + */ + syslog(deny_severity, "refused connect from %s", + my_eval_client(&req)); + + /* + C++ sucks (the gibberish in front just translates the supplied + sink function pointer in the req structure from a void (*sink)(); + to a void(*sink)(int) if you omit the cast, the C++ compiler + will cry... + */ + if (req.sink) + ((void(*)(int))req.sink)(req.fd); + + (void)mysql_socket_shutdown(new_sock, SHUT_RDWR); + (void)mysql_socket_close(new_sock); + /* + The connection was refused by TCP wrappers. + There are no details (by client IP) available to update the + host_cache. + */ + statistic_increment(connection_errors_tcpwrap, &LOCK_status); + return; + } + } + } +#endif /* HAVE_LIBWRAP */ + + DBUG_PRINT("info", ("Creating CONNECT for new connection")); + + if ((connect= new CONNECT())) + { + is_unix_sock= (mysql_socket_getfd(sock) == + mysql_socket_getfd(unix_sock)); + + if (!(connect->vio= + mysql_socket_vio_new(new_sock, + is_unix_sock ? VIO_TYPE_SOCKET : + VIO_TYPE_TCPIP, + is_unix_sock ? VIO_LOCALHOST : 0))) + { + delete connect; + connect= 0; // Error handling below + } + } + + if (!connect) + { + /* Connect failure */ + (void)mysql_socket_close(new_sock); + statistic_increment(aborted_connects, &LOCK_status); + statistic_increment(connection_errors_internal, &LOCK_status); + return; + } + + if (is_unix_sock) + connect->host= my_localhost; + + if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) + { + connect->extra_port= 1; + connect->scheduler= extra_thread_scheduler; + } + create_new_thread(connect); +} + +#ifndef _WIN32 void handle_connections_sockets() { MYSQL_SOCKET sock= mysql_socket_invalid(); MYSQL_SOCKET new_sock= mysql_socket_invalid(); uint error_count=0; - CONNECT *connect; struct sockaddr_storage cAddr; int ip_flags __attribute__((unused))=0; int socket_flags __attribute__((unused))= 0; int extra_ip_flags __attribute__((unused))=0; int flags=0,retval; - bool is_unix_sock; #ifdef HAVE_POLL int socket_count= 0; struct pollfd fds[3]; // for ip_sock, unix_sock and extra_ip_sock @@ -6812,10 +6765,7 @@ void handle_connections_sockets() } #endif } -#if !defined(NO_FCNTL_NONBLOCK) - if (!(test_flags & TEST_BLOCKING)) - fcntl(mysql_socket_getfd(sock), F_SETFL, flags); -#endif + if (mysql_socket_getfd(new_sock) == INVALID_SOCKET) { /* @@ -6831,443 +6781,18 @@ void handle_connections_sockets() sleep(1); // Give other threads some time continue; } -#ifdef FD_CLOEXEC - (void) fcntl(mysql_socket_getfd(new_sock), F_SETFD, FD_CLOEXEC); +#if !defined(NO_FCNTL_NONBLOCK) + if (!(test_flags & TEST_BLOCKING)) + fcntl(mysql_socket_getfd(sock), F_SETFL, flags); #endif - -#ifdef HAVE_LIBWRAP - { - if (mysql_socket_getfd(sock) == mysql_socket_getfd(base_ip_sock) || - mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) - { - struct request_info req; - signal(SIGCHLD, SIG_DFL); - request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, - mysql_socket_getfd(new_sock), NULL); - my_fromhost(&req); - if (!my_hosts_access(&req)) - { - /* - This may be stupid but refuse() includes an exit(0) - which we surely don't want... - clean_exit() - same stupid thing ... - */ - syslog(deny_severity, "refused connect from %s", - my_eval_client(&req)); - - /* - C++ sucks (the gibberish in front just translates the supplied - sink function pointer in the req structure from a void (*sink)(); - to a void(*sink)(int) if you omit the cast, the C++ compiler - will cry... - */ - if (req.sink) - ((void (*)(int))req.sink)(req.fd); - - (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) mysql_socket_close(new_sock); - /* - The connection was refused by TCP wrappers. - There are no details (by client IP) available to update the - host_cache. - */ - statistic_increment(connection_errors_tcpwrap, &LOCK_status); - continue; - } - } - } -#endif /* HAVE_LIBWRAP */ - - DBUG_PRINT("info", ("Creating CONNECT for new connection")); - - if ((connect= new CONNECT())) - { - is_unix_sock= (mysql_socket_getfd(sock) == - mysql_socket_getfd(unix_sock)); - - if (!(connect->vio= - mysql_socket_vio_new(new_sock, - is_unix_sock ? VIO_TYPE_SOCKET : - VIO_TYPE_TCPIP, - is_unix_sock ? VIO_LOCALHOST: 0))) - { - delete connect; - connect= 0; // Error handling below - } - } - - if (!connect) - { - /* Connect failure */ - (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) mysql_socket_close(new_sock); - statistic_increment(aborted_connects,&LOCK_status); - statistic_increment(connection_errors_internal, &LOCK_status); - continue; - } - - if (is_unix_sock) - connect->host= my_localhost; - - if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) - { - connect->extra_port= 1; - connect->scheduler= extra_thread_scheduler; - } - create_new_thread(connect); + handle_accepted_socket(new_sock, sock); } sd_notify(0, "STOPPING=1\n" "STATUS=Shutdown in progress\n"); DBUG_VOID_RETURN; } - -#ifdef _WIN32 -pthread_handler_t handle_connections_sockets_thread(void *arg) -{ - my_thread_init(); - handle_connections_sockets(); - decrement_handler_count(); - return 0; -} - -pthread_handler_t handle_connections_namedpipes(void *arg) -{ - HANDLE hConnectedPipe; - OVERLAPPED connectOverlapped= {0}; - my_thread_init(); - DBUG_ENTER("handle_connections_namedpipes"); - connectOverlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL); - if (!connectOverlapped.hEvent) - { - sql_print_error("Can't create event, last error=%u", GetLastError()); - unireg_abort(1); - } - DBUG_PRINT("general",("Waiting for named pipe connections.")); - while (!abort_loop) - { - /* wait for named pipe connection */ - BOOL fConnected= ConnectNamedPipe(hPipe, &connectOverlapped); - if (!fConnected && (GetLastError() == ERROR_IO_PENDING)) - { - /* - ERROR_IO_PENDING says async IO has started but not yet finished. - GetOverlappedResult will wait for completion. - */ - DWORD bytes; - fConnected= GetOverlappedResult(hPipe, &connectOverlapped,&bytes, TRUE); - } - if (abort_loop) - break; - if (!fConnected) - fConnected = GetLastError() == ERROR_PIPE_CONNECTED; - if (!fConnected) - { - CloseHandle(hPipe); - if ((hPipe= CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX | - FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE | - PIPE_READMODE_BYTE | - PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, - (int) global_system_variables. - net_buffer_length, - (int) global_system_variables. - net_buffer_length, - NMPWAIT_USE_DEFAULT_WAIT, - &saPipeSecurity)) == - INVALID_HANDLE_VALUE) - { - sql_perror("Can't create new named pipe!"); - break; // Abort - } - } - hConnectedPipe = hPipe; - /* create new pipe for new connection */ - if ((hPipe = CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX | - FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE | - PIPE_READMODE_BYTE | - PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, - (int) global_system_variables.net_buffer_length, - (int) global_system_variables.net_buffer_length, - NMPWAIT_USE_DEFAULT_WAIT, - &saPipeSecurity)) == - INVALID_HANDLE_VALUE) - { - sql_perror("Can't create new named pipe!"); - hPipe=hConnectedPipe; - continue; // We have to try again - } - CONNECT *connect; - if (!(connect= new CONNECT) || - !(connect->vio= vio_new_win32pipe(hConnectedPipe))) - { - DisconnectNamedPipe(hConnectedPipe); - CloseHandle(hConnectedPipe); - delete connect; - statistic_increment(aborted_connects,&LOCK_status); - statistic_increment(connection_errors_internal, &LOCK_status); - continue; - } - connect->host= my_localhost; - create_new_thread(connect); - } - LocalFree(saPipeSecurity.lpSecurityDescriptor); - CloseHandle(connectOverlapped.hEvent); - DBUG_LEAVE; - decrement_handler_count(); - return 0; -} -#endif /* _WIN32 */ - - -#ifdef HAVE_SMEM - -/** - Thread of shared memory's service. - - @param arg Arguments of thread -*/ -pthread_handler_t handle_connections_shared_memory(void *arg) -{ - /* file-mapping object, use for create shared memory */ - HANDLE handle_connect_file_map= 0; - char *handle_connect_map= 0; // pointer on shared memory - HANDLE event_connect_answer= 0; - ulong smem_buffer_length= shared_memory_buffer_length + 4; - ulong connect_number= 1; - char *tmp= NULL; - char *suffix_pos; - char connect_number_char[22], *p; - const char *errmsg= 0; - SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0; - my_thread_init(); - DBUG_ENTER("handle_connections_shared_memorys"); - DBUG_PRINT("general",("Waiting for allocated shared memory.")); - - /* - get enough space base-name + '_' + longest suffix we might ever send - */ - if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, - MYF(MY_FAE)))) - goto error; - - if (my_security_attr_create(&sa_event, &errmsg, - GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE)) - goto error; - - if (my_security_attr_create(&sa_mapping, &errmsg, - GENERIC_ALL, FILE_MAP_READ | FILE_MAP_WRITE)) - goto error; - - /* - The name of event and file-mapping events create agree next rule: - shared_memory_base_name+unique_part - Where: - shared_memory_base_name is unique value for each server - unique_part is unique value for each object (events and file-mapping) - */ - suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS); - strmov(suffix_pos, "CONNECT_REQUEST"); - if ((smem_event_connect_request= CreateEvent(sa_event, - FALSE, FALSE, tmp)) == 0) - { - errmsg= "Could not create request event"; - goto error; - } - strmov(suffix_pos, "CONNECT_ANSWER"); - if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0) - { - errmsg="Could not create answer event"; - goto error; - } - strmov(suffix_pos, "CONNECT_DATA"); - if ((handle_connect_file_map= - CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping, - PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0) - { - errmsg= "Could not create file mapping"; - goto error; - } - if ((handle_connect_map= (char *)MapViewOfFile(handle_connect_file_map, - FILE_MAP_WRITE,0,0, - sizeof(DWORD))) == 0) - { - errmsg= "Could not create shared memory service"; - goto error; - } - - while (!abort_loop) - { - /* Wait a request from client */ - WaitForSingleObject(smem_event_connect_request,INFINITE); - - /* - it can be after shutdown command - */ - if (abort_loop) - goto error; - - HANDLE handle_client_file_map= 0; - char *handle_client_map= 0; - HANDLE event_client_wrote= 0; - HANDLE event_client_read= 0; // for transfer data server <-> client - HANDLE event_server_wrote= 0; - HANDLE event_server_read= 0; - HANDLE event_conn_closed= 0; - CONNECT *connect= 0; - - p= int10_to_str(connect_number, connect_number_char, 10); - /* - The name of event and file-mapping events create agree next rule: - shared_memory_base_name+unique_part+number_of_connection - Where: - shared_memory_base_name is uniquel value for each server - unique_part is unique value for each object (events and file-mapping) - number_of_connection is connection-number between server and client - */ - suffix_pos= strxmov(tmp,shared_memory_base_name,"_",connect_number_char, - "_",NullS); - strmov(suffix_pos, "DATA"); - if ((handle_client_file_map= - CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping, - PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0) - { - errmsg= "Could not create file mapping"; - goto errorconn; - } - if ((handle_client_map= (char*)MapViewOfFile(handle_client_file_map, - FILE_MAP_WRITE,0,0, - smem_buffer_length)) == 0) - { - errmsg= "Could not create memory map"; - goto errorconn; - } - strmov(suffix_pos, "CLIENT_WROTE"); - if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0) - { - errmsg= "Could not create client write event"; - goto errorconn; - } - strmov(suffix_pos, "CLIENT_READ"); - if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0) - { - errmsg= "Could not create client read event"; - goto errorconn; - } - strmov(suffix_pos, "SERVER_READ"); - if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0) - { - errmsg= "Could not create server read event"; - goto errorconn; - } - strmov(suffix_pos, "SERVER_WROTE"); - if ((event_server_wrote= CreateEvent(sa_event, - FALSE, FALSE, tmp)) == 0) - { - errmsg= "Could not create server write event"; - goto errorconn; - } - strmov(suffix_pos, "CONNECTION_CLOSED"); - if ((event_conn_closed= CreateEvent(sa_event, - TRUE, FALSE, tmp)) == 0) - { - errmsg= "Could not create closed connection event"; - goto errorconn; - } - if (abort_loop) - goto errorconn; - - if (!(connect= new CONNECT)) - { - errmsg= "Could not create CONNECT object"; - goto errorconn; - } - - /* Send number of connection to client */ - int4store(handle_connect_map, connect_number); - if (!SetEvent(event_connect_answer)) - { - errmsg= "Could not send answer event"; - goto errorconn; - } - /* Set event that client should receive data */ - if (!SetEvent(event_client_read)) - { - errmsg= "Could not set client to read mode"; - goto errorconn; - } - if (!(connect->vio= vio_new_win32shared_memory(handle_client_file_map, - handle_client_map, - event_client_wrote, - event_client_read, - event_server_wrote, - event_server_read, - event_conn_closed))) - { - errmsg= "Could not create VIO object"; - goto errorconn; - } - connect->host= my_localhost; /* Host is unknown */ - create_new_thread(connect); - connect_number++; - continue; - -errorconn: - /* Could not form connection; Free used handlers/memort and retry */ - if (errmsg) - { - char buff[180]; - strxmov(buff, "Can't create shared memory connection: ", errmsg, ".", - NullS); - sql_perror(buff); - } - if (handle_client_file_map) - CloseHandle(handle_client_file_map); - if (handle_client_map) - UnmapViewOfFile(handle_client_map); - if (event_server_wrote) - CloseHandle(event_server_wrote); - if (event_server_read) - CloseHandle(event_server_read); - if (event_client_wrote) - CloseHandle(event_client_wrote); - if (event_client_read) - CloseHandle(event_client_read); - if (event_conn_closed) - CloseHandle(event_conn_closed); - - delete connect; - statistic_increment(aborted_connects,&LOCK_status); - statistic_increment(connection_errors_internal, &LOCK_status); - } - - /* End shared memory handling */ -error: - if (tmp) - my_free(tmp); - - if (errmsg) - { - char buff[180]; - strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS); - sql_perror(buff); - } - my_security_attr_free(sa_event); - my_security_attr_free(sa_mapping); - if (handle_connect_map) UnmapViewOfFile(handle_connect_map); - if (handle_connect_file_map) CloseHandle(handle_connect_file_map); - if (event_connect_answer) CloseHandle(event_connect_answer); - if (smem_event_connect_request) CloseHandle(smem_event_connect_request); - DBUG_LEAVE; - decrement_handler_count(); - return 0; -} -#endif /* HAVE_SMEM */ +#endif /* _WIN32*/ #endif /* EMBEDDED_LIBRARY */ @@ -8006,187 +7531,6 @@ static int show_flush_commands(THD *thd, SHOW_VAR *var, char *buff, #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) -/* Functions relying on CTX */ -static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, - char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, - char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_hits(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_cache_full(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_misses(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_timeouts(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, - char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_LONG; - var->value= buff; - *((long *)buff)= (!ssl_acceptor_fd ? 0 : - SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)); - return 0; -} - -static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, - char *buff, - enum enum_var_type scope) -{ - var->type= SHOW_CHAR; - if (!ssl_acceptor_fd) - var->value= const_cast<char*>("NONE"); - else - switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context)) - { - case SSL_SESS_CACHE_OFF: - var->value= const_cast<char*>("OFF"); break; - case SSL_SESS_CACHE_CLIENT: - var->value= const_cast<char*>("CLIENT"); break; - case SSL_SESS_CACHE_SERVER: - var->value= const_cast<char*>("SERVER"); break; - case SSL_SESS_CACHE_BOTH: - var->value= const_cast<char*>("BOTH"); break; - case SSL_SESS_CACHE_NO_AUTO_CLEAR: - var->value= const_cast<char*>("NO_AUTO_CLEAR"); break; - case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP: - var->value= const_cast<char*>("NO_INTERNAL_LOOKUP"); break; - default: - var->value= const_cast<char*>("Unknown"); break; - } - return 0; -} /* Functions relying on SSL @@ -8691,28 +8035,28 @@ SHOW_VAR status_vars[]= { {"Sort_scan", (char*) offsetof(STATUS_VAR, filesort_scan_count_), SHOW_LONG_STATUS}, #ifdef HAVE_OPENSSL #ifndef EMBEDDED_LIBRARY - {"Ssl_accept_renegotiates", (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_SIMPLE_FUNC}, - {"Ssl_accepts", (char*) &show_ssl_ctx_sess_accept, SHOW_SIMPLE_FUNC}, - {"Ssl_callback_cache_hits", (char*) &show_ssl_ctx_sess_cb_hits, SHOW_SIMPLE_FUNC}, + {"Ssl_accept_renegotiates", (char*) &ssl_acceptor_stats.zero, SHOW_LONG}, + {"Ssl_accepts", (char*) &ssl_acceptor_stats.accept, SHOW_LONG}, + {"Ssl_callback_cache_hits", (char*) &ssl_acceptor_stats.zero, SHOW_LONG}, {"Ssl_cipher", (char*) &show_ssl_get_cipher, SHOW_SIMPLE_FUNC}, {"Ssl_cipher_list", (char*) &show_ssl_get_cipher_list, SHOW_SIMPLE_FUNC}, - {"Ssl_client_connects", (char*) &show_ssl_ctx_sess_connect, SHOW_SIMPLE_FUNC}, - {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_SIMPLE_FUNC}, - {"Ssl_ctx_verify_depth", (char*) &show_ssl_ctx_get_verify_depth, SHOW_SIMPLE_FUNC}, - {"Ssl_ctx_verify_mode", (char*) &show_ssl_ctx_get_verify_mode, SHOW_SIMPLE_FUNC}, + {"Ssl_client_connects", (char*) &ssl_acceptor_stats.zero, SHOW_LONG}, + {"Ssl_connect_renegotiates", (char*) &ssl_acceptor_stats.zero, SHOW_LONG}, + {"Ssl_ctx_verify_depth", (char*) &ssl_acceptor_stats.verify_depth, SHOW_LONG}, + {"Ssl_ctx_verify_mode", (char*) &ssl_acceptor_stats.verify_mode, SHOW_LONG}, {"Ssl_default_timeout", (char*) &show_ssl_get_default_timeout, SHOW_SIMPLE_FUNC}, - {"Ssl_finished_accepts", (char*) &show_ssl_ctx_sess_accept_good, SHOW_SIMPLE_FUNC}, - {"Ssl_finished_connects", (char*) &show_ssl_ctx_sess_connect_good, SHOW_SIMPLE_FUNC}, + {"Ssl_finished_accepts", (char*) &ssl_acceptor_stats.accept_good, SHOW_LONG}, + {"Ssl_finished_connects", (char*) &ssl_acceptor_stats.zero, SHOW_LONG}, {"Ssl_server_not_after", (char*) &show_ssl_get_server_not_after, SHOW_SIMPLE_FUNC}, {"Ssl_server_not_before", (char*) &show_ssl_get_server_not_before, SHOW_SIMPLE_FUNC}, - {"Ssl_session_cache_hits", (char*) &show_ssl_ctx_sess_hits, SHOW_SIMPLE_FUNC}, - {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_SIMPLE_FUNC}, - {"Ssl_session_cache_mode", (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_SIMPLE_FUNC}, - {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_SIMPLE_FUNC}, - {"Ssl_session_cache_size", (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_SIMPLE_FUNC}, - {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_SIMPLE_FUNC}, - {"Ssl_sessions_reused", (char*) &show_ssl_session_reused, SHOW_SIMPLE_FUNC}, - {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_SIMPLE_FUNC}, + {"Ssl_session_cache_hits", (char*) &ssl_acceptor_stats.zero, SHOW_LONG}, + {"Ssl_session_cache_misses", (char*) &ssl_acceptor_stats.zero, SHOW_LONG}, + {"Ssl_session_cache_mode", (char*) &ssl_acceptor_stats.session_cache_mode, SHOW_CHAR_PTR}, + {"Ssl_session_cache_overflows", (char*) &ssl_acceptor_stats.zero, SHOW_LONG}, + {"Ssl_session_cache_size", (char*) &ssl_acceptor_stats.cache_size, SHOW_LONG}, + {"Ssl_session_cache_timeouts", (char*) &ssl_acceptor_stats.zero, SHOW_LONG}, + {"Ssl_sessions_reused", (char*) &ssl_acceptor_stats.zero, SHOW_LONG}, + {"Ssl_used_session_cache_entries",(char*) &ssl_acceptor_stats.zero, SHOW_LONG}, {"Ssl_verify_depth", (char*) &show_ssl_get_verify_depth, SHOW_SIMPLE_FUNC}, {"Ssl_verify_mode", (char*) &show_ssl_get_verify_mode, SHOW_SIMPLE_FUNC}, {"Ssl_version", (char*) &show_ssl_get_version, SHOW_SIMPLE_FUNC}, @@ -8957,7 +8301,9 @@ static int mysql_init_variables(void) character_set_filesystem= &my_charset_bin; opt_specialflag= SPECIAL_ENGLISH; +#ifndef EMBEDDED_LIBRARY unix_sock= base_ip_sock= extra_ip_sock= MYSQL_INVALID_SOCKET; +#endif mysql_home_ptr= mysql_home; log_error_file_ptr= log_error_file; protocol_version= PROTOCOL_VERSION; @@ -9071,9 +8417,6 @@ static int mysql_init_variables(void) ssl_acceptor_fd= 0; #endif /* ! EMBEDDED_LIBRARY */ #endif /* HAVE_OPENSSL */ -#ifdef HAVE_SMEM - shared_memory_base_name= default_shared_memory_base_name; -#endif #if defined(__WIN__) /* Allow Win32 users to move MySQL anywhere */ @@ -9816,10 +9159,10 @@ static int get_options(int *argc_ptr, char ***argv_ptr) errors. */ if (global_system_variables.log_warnings >= 10) - my_global_flags= MY_WME | ME_JUST_INFO; + my_global_flags= MY_WME | ME_NOTE; /* Log all errors not handled by thd->handle_error() to my_message_sql() */ if (global_system_variables.log_warnings >= 11) - my_global_flags|= ME_NOREFRESH; + my_global_flags|= ME_ERROR_LOG; if (my_assert_on_error) debug_assert_if_crashed_table= 1; diff --git a/sql/mysqld.h b/sql/mysqld.h index d5cabd790b2..c84e1d08efe 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -24,6 +24,7 @@ #include "mysql_com.h" /* SERVER_VERSION_LENGTH */ #include "my_atomic.h" #include "mysql/psi/mysql_file.h" /* MYSQL_FILE */ +#include "mysql/psi/mysql_socket.h" /* MYSQL_SOCKET */ #include "sql_list.h" /* I_List */ #include "sql_cmd.h" #include <my_rnd.h> @@ -92,6 +93,11 @@ void refresh_status(THD *thd); bool is_secure_file_path(char *path); void dec_connection_count(scheduler_functions *scheduler); extern void init_net_server_extension(THD *thd); +extern void handle_accepted_socket(MYSQL_SOCKET new_sock, MYSQL_SOCKET sock); +extern void create_new_thread(CONNECT *connect); + +extern void ssl_acceptor_stats_update(int sslaccept_ret); +extern int reinit_ssl(); extern "C" MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info; extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *files_charset_info ; @@ -152,6 +158,7 @@ extern ulong opt_replicate_events_marked_for_skip; extern char *default_tz_name; extern Time_zone *default_tz; extern char *my_bind_addr_str; +extern int server_socket_ai_family; extern char *default_storage_engine, *default_tmp_storage_engine; extern char *enforced_storage_engine; extern char *gtid_pos_auto_engines; @@ -258,6 +265,7 @@ extern ulong opt_slave_parallel_mode; extern ulong opt_binlog_commit_wait_count; extern ulong opt_binlog_commit_wait_usec; extern my_bool opt_gtid_ignore_duplicates; +extern uint opt_gtid_cleanup_batch_size; extern ulong back_log; extern ulong executed_events; extern char language[FN_REFLEN]; @@ -628,6 +636,7 @@ extern mysql_mutex_t LOCK_des_key_file; extern mysql_mutex_t LOCK_server_started; extern mysql_cond_t COND_server_started; extern mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; +extern mysql_rwlock_t LOCK_ssl_refresh; extern mysql_prlock_t LOCK_system_variables_hash; extern mysql_cond_t COND_thread_count, COND_start_thread; extern mysql_cond_t COND_manager; @@ -760,7 +769,7 @@ enum enum_query_type /* query_id */ extern query_id_t global_query_id; -ATTRIBUTE_NORETURN void unireg_end(void); +void unireg_end(void); /* increment query_id and return it. */ inline __attribute__((warn_unused_result)) query_id_t next_query_id() diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 0c6c585bff6..f01191d3c7e 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1479,7 +1479,6 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler, { handler *save_file= file, *org_file; THD *thd= head->in_use; - MY_BITMAP * const save_vcol_set= head->vcol_set; MY_BITMAP * const save_read_set= head->read_set; MY_BITMAP * const save_write_set= head->write_set; DBUG_ENTER("QUICK_RANGE_SELECT::init_ror_merged_scan"); @@ -1537,14 +1536,14 @@ end: org_file= head->file; head->file= file; - head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap, &column_bitmap); + head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap); head->prepare_for_keyread(index, &column_bitmap); head->prepare_for_position(); head->file= org_file; /* Restore head->read_set (and write_set) to what they had before the call */ - head->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set); + head->column_bitmaps_set(save_read_set, save_write_set); if (reset()) { @@ -1559,7 +1558,7 @@ end: DBUG_RETURN(0); failure: - head->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set); + head->column_bitmaps_set(save_read_set, save_write_set); delete file; file= save_file; DBUG_RETURN(1); @@ -1893,6 +1892,118 @@ SEL_ARG::SEL_ARG(Field *field_,uint8 part_, left=right= &null_element; } + +/* + A number of helper classes: + SEL_ARG_LE, SEL_ARG_LT, SEL_ARG_GT, SEL_ARG_GE, + to share the code between: + Field::stored_field_make_mm_leaf() + Field::stored_field_make_mm_leaf_exact() +*/ +class SEL_ARG_LE: public SEL_ARG +{ +public: + SEL_ARG_LE(const uchar *key, Field *field) + :SEL_ARG(field, key, key) + { + if (!field->real_maybe_null()) + min_flag= NO_MIN_RANGE; // From start + else + { + min_value= is_null_string; + min_flag= NEAR_MIN; // > NULL + } + } +}; + + +class SEL_ARG_LT: public SEL_ARG_LE +{ +public: + /* + Use this constructor if value->save_in_field() went precisely, + without any data rounding or truncation. + */ + SEL_ARG_LT(const uchar *key, Field *field) + :SEL_ARG_LE(key, field) + { max_flag= NEAR_MAX; } + /* + Use this constructor if value->save_in_field() returned success, + but we don't know if rounding or truncation happened + (as some Field::store() do not report minor data changes). + */ + SEL_ARG_LT(THD *thd, const uchar *key, Field *field, Item *value) + :SEL_ARG_LE(key, field) + { + if (stored_field_cmp_to_item(thd, field, value) == 0) + max_flag= NEAR_MAX; + } +}; + + +class SEL_ARG_GT: public SEL_ARG +{ +public: + /* + Use this constructor if value->save_in_field() went precisely, + without any data rounding or truncation. + */ + SEL_ARG_GT(const uchar *key, const KEY_PART *key_part, Field *field) + :SEL_ARG(field, key, key) + { + // Don't use open ranges for partial key_segments + if (!(key_part->flag & HA_PART_KEY_SEG)) + min_flag= NEAR_MIN; + max_flag= NO_MAX_RANGE; + } + /* + Use this constructor if value->save_in_field() returned success, + but we don't know if rounding or truncation happened + (as some Field::store() do not report minor data changes). + */ + SEL_ARG_GT(THD *thd, const uchar *key, + const KEY_PART *key_part, Field *field, Item *value) + :SEL_ARG(field, key, key) + { + // Don't use open ranges for partial key_segments + if ((!(key_part->flag & HA_PART_KEY_SEG)) && + (stored_field_cmp_to_item(thd, field, value) <= 0)) + min_flag= NEAR_MIN; + max_flag= NO_MAX_RANGE; + } +}; + + +class SEL_ARG_GE: public SEL_ARG +{ +public: + /* + Use this constructor if value->save_in_field() went precisely, + without any data rounding or truncation. + */ + SEL_ARG_GE(const uchar *key, Field *field) + :SEL_ARG(field, key, key) + { + max_flag= NO_MAX_RANGE; + } + /* + Use this constructor if value->save_in_field() returned success, + but we don't know if rounding or truncation happened + (as some Field::store() do not report minor data changes). + */ + SEL_ARG_GE(THD *thd, const uchar *key, + const KEY_PART *key_part, Field *field, Item *value) + :SEL_ARG(field, key, key) + { + // Don't use open ranges for partial key_segments + if ((!(key_part->flag & HA_PART_KEY_SEG)) && + (stored_field_cmp_to_item(thd, field, value) < 0)) + min_flag= NEAR_MIN; + max_flag= NO_MAX_RANGE; + } +}; + + SEL_ARG *SEL_ARG::clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent, SEL_ARG **next_arg) { @@ -4574,7 +4685,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records) if (max_cost != DBL_MAX && (busy_blocks+index_reads_cost) >= n_blocks) return 1; */ - JOIN *join= param->thd->lex->select_lex.join; + JOIN *join= param->thd->lex->first_select_lex()->join; if (!join || join->table_count == 1) { /* No join, assume reading is done in one 'sweep' */ @@ -8045,52 +8156,112 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param, SEL_ARG * Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param, Field *field, KEY_PART *key_part, - Item_func::Functype type, Item *value) + Item_func::Functype functype, Item *value) { - uint maybe_null=(uint) field->real_maybe_null(); - SEL_ARG *tree= 0; - MEM_ROOT *alloc= param->mem_root; - uchar *str; - int err; DBUG_ENTER("Item_bool_func::get_mm_leaf"); - DBUG_ASSERT(value); // IS NULL and IS NOT NULL are handled separately - if (key_part->image_type != Field::itRAW) DBUG_RETURN(0); // e.g. SPATIAL index + DBUG_RETURN(field->get_mm_leaf(param, key_part, this, + functype_to_scalar_comparison_op(functype), + value)); +} - if (param->using_real_indexes && - !field->optimize_range(param->real_keynr[key_part->key], - key_part->part) && - type != EQ_FUNC && - type != EQUAL_FUNC) - goto end; // Can't optimize this - if (!field->can_optimize_range(this, value, - type == EQUAL_FUNC || type == EQ_FUNC)) - goto end; +bool Field::can_optimize_scalar_range(const RANGE_OPT_PARAM *param, + const KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, + const Item *value) const +{ + bool is_eq_func= op == SCALAR_CMP_EQ || op == SCALAR_CMP_EQUAL; + if ((param->using_real_indexes && + !optimize_range(param->real_keynr[key_part->key], + key_part->part) && !is_eq_func) || + !can_optimize_range(cond, value, is_eq_func)) + return false; + return true; +} + + +uchar *Field::make_key_image(MEM_ROOT *mem_root, const KEY_PART *key_part) +{ + DBUG_ENTER("Field::make_key_image"); + uint maybe_null= (uint) real_maybe_null(); + uchar *str; + if (!(str= (uchar*) alloc_root(mem_root, key_part->store_length + 1))) + DBUG_RETURN(0); + if (maybe_null) + *str= (uchar) is_real_null(); // Set to 1 if null + get_key_image(str + maybe_null, key_part->length, key_part->image_type); + DBUG_RETURN(str); +} + + +SEL_ARG *Field::stored_field_make_mm_leaf_truncated(RANGE_OPT_PARAM *param, + scalar_comparison_op op, + Item *value) +{ + DBUG_ENTER("Field::stored_field_make_mm_leaf_truncated"); + if ((op == SCALAR_CMP_EQ || op == SCALAR_CMP_EQUAL) && + value->result_type() == item_cmp_type(result_type(), + value->result_type())) + DBUG_RETURN(new (param->mem_root) SEL_ARG_IMPOSSIBLE(this)); + /* + TODO: We should return trees of the type SEL_ARG::IMPOSSIBLE + for the cases like int_field > 999999999999999999999999 as well. + */ + DBUG_RETURN(0); +} + - err= value->save_in_field_no_warnings(field, 1); +SEL_ARG *Field_num::get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value) +{ + DBUG_ENTER("Field_num::get_mm_leaf"); + if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + DBUG_RETURN(0); + int err= value->save_in_field_no_warnings(this, 1); + if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) + DBUG_RETURN(&null_element); + if (err > 0 && cmp_type() != value->result_type()) + DBUG_RETURN(stored_field_make_mm_leaf_truncated(prm, op, value)); + DBUG_RETURN(stored_field_make_mm_leaf(prm, key_part, op, value)); +} + + +SEL_ARG *Field_temporal::get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value) +{ + DBUG_ENTER("Field_temporal::get_mm_leaf"); + if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + DBUG_RETURN(0); + int err= value->save_in_field_no_warnings(this, 1); + if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) + DBUG_RETURN(&null_element); if (err > 0) - { - if (field->type_handler() == &type_handler_enum || - field->type_handler() == &type_handler_set) - { - if (type == EQ_FUNC || type == EQUAL_FUNC) - tree= new (alloc) SEL_ARG_IMPOSSIBLE(field); - goto end; - } + DBUG_RETURN(stored_field_make_mm_leaf_truncated(prm, op, value)); + DBUG_RETURN(stored_field_make_mm_leaf(prm, key_part, op, value)); +} - if (err == 2 && field->cmp_type() == STRING_RESULT) - { - if (type == EQ_FUNC || type == EQUAL_FUNC) - tree= new (alloc) SEL_ARG_IMPOSSIBLE(field); - else - tree= NULL; /* Cannot infer anything */ - goto end; - } - if (err == 3 && field->type() == FIELD_TYPE_DATE) +SEL_ARG *Field_date_common::get_mm_leaf(RANGE_OPT_PARAM *prm, + KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, + Item *value) +{ + DBUG_ENTER("Field_date_common::get_mm_leaf"); + if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + DBUG_RETURN(0); + int err= value->save_in_field_no_warnings(this, 1); + if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) + DBUG_RETURN(&null_element); + if (err > 0) + { + if (err == 3) { /* We were saving DATETIME into a DATE column, the conversion went ok @@ -8110,76 +8281,86 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param, be done together with other types at the end of this function (grep for stored_field_cmp_to_item) */ - if (type == EQ_FUNC || type == EQUAL_FUNC) - { - tree= new (alloc) SEL_ARG_IMPOSSIBLE(field); - goto end; - } - // Continue with processing non-equality ranges - } - else if (field->cmp_type() != value->result_type()) - { - if ((type == EQ_FUNC || type == EQUAL_FUNC) && - value->result_type() == item_cmp_type(field->result_type(), - value->result_type())) - { - tree= new (alloc) SEL_ARG_IMPOSSIBLE(field); - goto end; - } - else - { - /* - TODO: We should return trees of the type SEL_ARG::IMPOSSIBLE - for the cases like int_field > 999999999999999999999999 as well. - */ - tree= 0; - goto end; - } - } - - /* - guaranteed at this point: err > 0; field and const of same type - If an integer got bounded (e.g. to within 0..255 / -128..127) - for < or >, set flags as for <= or >= (no NEAR_MAX / NEAR_MIN) - */ - else if (err == 1 && field->result_type() == INT_RESULT) - { - if (type == LT_FUNC && (value->val_int() > 0)) - type= LE_FUNC; - else if (type == GT_FUNC && - (field->type() != FIELD_TYPE_BIT) && - !((Field_num*)field)->unsigned_flag && - !((Item_int*)value)->unsigned_flag && - (value->val_int() < 0)) - type= GE_FUNC; + if (op == SCALAR_CMP_EQ || op == SCALAR_CMP_EQUAL) + DBUG_RETURN(new (prm->mem_root) SEL_ARG_IMPOSSIBLE(this)); + DBUG_RETURN(stored_field_make_mm_leaf(prm, key_part, op, value)); } + DBUG_RETURN(stored_field_make_mm_leaf_truncated(prm, op, value)); } - else if (err < 0) + DBUG_RETURN(stored_field_make_mm_leaf(prm, key_part, op, value)); +} + + +SEL_ARG *Field_str::get_mm_leaf(RANGE_OPT_PARAM *prm, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value) +{ + DBUG_ENTER("Field_str::get_mm_leaf"); + if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + DBUG_RETURN(0); + int err= value->save_in_field_no_warnings(this, 1); + if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) + DBUG_RETURN(&null_element); + if (err > 0) { - /* This happens when we try to insert a NULL field in a not null column */ - tree= &null_element; // cmp with NULL is never TRUE - goto end; + if (op == SCALAR_CMP_EQ || op == SCALAR_CMP_EQUAL) + DBUG_RETURN(new (prm->mem_root) SEL_ARG_IMPOSSIBLE(this)); + DBUG_RETURN(NULL); /* Cannot infer anything */ } + DBUG_RETURN(stored_field_make_mm_leaf(prm, key_part, op, value)); +} - /* - Any sargable predicate except "<=>" involving NULL as a constant is always - FALSE - */ - if (type != EQUAL_FUNC && field->is_real_null()) + +SEL_ARG *Field::get_mm_leaf_int(RANGE_OPT_PARAM *prm, KEY_PART *key_part, + const Item_bool_func *cond, + scalar_comparison_op op, Item *value, + bool unsigned_field) +{ + DBUG_ENTER("Field::get_mm_leaf_int"); + if (!can_optimize_scalar_range(prm, key_part, cond, op, value)) + DBUG_RETURN(0); + int err= value->save_in_field_no_warnings(this, 1); + if ((op != SCALAR_CMP_EQUAL && is_real_null()) || err < 0) + DBUG_RETURN(&null_element); + if (err > 0) { - tree= &null_element; - goto end; + if (value->result_type() != INT_RESULT) + DBUG_RETURN(stored_field_make_mm_leaf_truncated(prm, op, value)); + else + DBUG_RETURN(stored_field_make_mm_leaf_bounded_int(prm, key_part, + op, value, + unsigned_field)); } - - str= (uchar*) alloc_root(alloc, key_part->store_length+1); - if (!str) - goto end; - if (maybe_null) - *str= (uchar) field->is_real_null(); // Set to 1 if null - field->get_key_image(str+maybe_null, key_part->length, - key_part->image_type); - if (!(tree= new (alloc) SEL_ARG(field, str, str))) - goto end; // out of memory + if (value->result_type() != INT_RESULT) + DBUG_RETURN(stored_field_make_mm_leaf(prm, key_part, op, value)); + DBUG_RETURN(stored_field_make_mm_leaf_exact(prm, key_part, op, value)); +} + + +/* + This method is called when: + - value->save_in_field_no_warnings() returned err > 0 + - and both field and "value" are of integer data types + If an integer got bounded (e.g. to within 0..255 / -128..127) + for < or >, set flags as for <= or >= (no NEAR_MAX / NEAR_MIN) +*/ + +SEL_ARG *Field::stored_field_make_mm_leaf_bounded_int(RANGE_OPT_PARAM *param, + KEY_PART *key_part, + scalar_comparison_op op, + Item *value, + bool unsigned_field) +{ + DBUG_ENTER("Field::stored_field_make_mm_leaf_bounded_int"); + if (op == SCALAR_CMP_EQ || op == SCALAR_CMP_EQUAL) // e.g. tinyint = 200 + DBUG_RETURN(new (param->mem_root) SEL_ARG_IMPOSSIBLE(this)); + longlong item_val= value->val_int(); + + if (op == SCALAR_CMP_LT && item_val > 0) + op= SCALAR_CMP_LE; // e.g. rewrite (tinyint < 200) to (tinyint <= 127) + else if (op == SCALAR_CMP_GT && !unsigned_field && + !value->unsigned_flag && item_val < 0) + op= SCALAR_CMP_GE; // e.g. rewrite (tinyint > -200) to (tinyint >= -128) /* Check if we are comparing an UNSIGNED integer with a negative constant. @@ -8192,66 +8373,74 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param, negative integers (which otherwise fails because at query execution time negative integers are cast to unsigned if compared with unsigned). */ - if (field->result_type() == INT_RESULT && - value->result_type() == INT_RESULT && - ((field->type() == FIELD_TYPE_BIT || - ((Field_num *) field)->unsigned_flag) && - !((Item_int*) value)->unsigned_flag)) + if (unsigned_field && !value->unsigned_flag && item_val < 0) { - longlong item_val= value->val_int(); - if (item_val < 0) - { - if (type == LT_FUNC || type == LE_FUNC) - { - tree->type= SEL_ARG::IMPOSSIBLE; - goto end; - } - if (type == GT_FUNC || type == GE_FUNC) - { - tree= 0; - goto end; - } - } + if (op == SCALAR_CMP_LT || op == SCALAR_CMP_LE) // e.g. uint < -1 + DBUG_RETURN(new (param->mem_root) SEL_ARG_IMPOSSIBLE(this)); + if (op == SCALAR_CMP_GT || op == SCALAR_CMP_GE) // e.g. uint > -1 + DBUG_RETURN(0); } + DBUG_RETURN(stored_field_make_mm_leaf_exact(param, key_part, op, value)); +} - switch (type) { - case LT_FUNC: - if (stored_field_cmp_to_item(param->thd, field, value) == 0) - tree->max_flag=NEAR_MAX; - /* fall through */ - case LE_FUNC: - if (!maybe_null) - tree->min_flag=NO_MIN_RANGE; /* From start */ - else - { // > NULL - tree->min_value=is_null_string; - tree->min_flag=NEAR_MIN; - } - break; - case GT_FUNC: - /* Don't use open ranges for partial key_segments */ - if ((!(key_part->flag & HA_PART_KEY_SEG)) && - (stored_field_cmp_to_item(param->thd, field, value) <= 0)) - tree->min_flag=NEAR_MIN; - tree->max_flag= NO_MAX_RANGE; - break; - case GE_FUNC: - /* Don't use open ranges for partial key_segments */ - if ((!(key_part->flag & HA_PART_KEY_SEG)) && - (stored_field_cmp_to_item(param->thd, field, value) < 0)) - tree->min_flag= NEAR_MIN; - tree->max_flag=NO_MAX_RANGE; - break; - case EQ_FUNC: - case EQUAL_FUNC: - break; - default: - DBUG_ASSERT(0); + +SEL_ARG *Field::stored_field_make_mm_leaf(RANGE_OPT_PARAM *param, + KEY_PART *key_part, + scalar_comparison_op op, + Item *value) +{ + DBUG_ENTER("Field::stored_field_make_mm_leaf"); + THD *thd= param->thd; + MEM_ROOT *mem_root= param->mem_root; + uchar *str; + if (!(str= make_key_image(param->mem_root, key_part))) + DBUG_RETURN(0); + + switch (op) { + case SCALAR_CMP_LE: + DBUG_RETURN(new (mem_root) SEL_ARG_LE(str, this)); + case SCALAR_CMP_LT: + DBUG_RETURN(new (mem_root) SEL_ARG_LT(thd, str, this, value)); + case SCALAR_CMP_GT: + DBUG_RETURN(new (mem_root) SEL_ARG_GT(thd, str, key_part, this, value)); + case SCALAR_CMP_GE: + DBUG_RETURN(new (mem_root) SEL_ARG_GE(thd, str, key_part, this, value)); + case SCALAR_CMP_EQ: + case SCALAR_CMP_EQUAL: + DBUG_RETURN(new (mem_root) SEL_ARG(this, str, str)); break; } + DBUG_ASSERT(0); + DBUG_RETURN(NULL); +} -end: - DBUG_RETURN(tree); + +SEL_ARG *Field::stored_field_make_mm_leaf_exact(RANGE_OPT_PARAM *param, + KEY_PART *key_part, + scalar_comparison_op op, + Item *value) +{ + DBUG_ENTER("Field::stored_field_make_mm_leaf_exact"); + uchar *str; + if (!(str= make_key_image(param->mem_root, key_part))) + DBUG_RETURN(0); + + switch (op) { + case SCALAR_CMP_LE: + DBUG_RETURN(new (param->mem_root) SEL_ARG_LE(str, this)); + case SCALAR_CMP_LT: + DBUG_RETURN(new (param->mem_root) SEL_ARG_LT(str, this)); + case SCALAR_CMP_GT: + DBUG_RETURN(new (param->mem_root) SEL_ARG_GT(str, key_part, this)); + case SCALAR_CMP_GE: + DBUG_RETURN(new (param->mem_root) SEL_ARG_GE(str, this)); + case SCALAR_CMP_EQ: + case SCALAR_CMP_EQUAL: + DBUG_RETURN(new (param->mem_root) SEL_ARG(this, str, str)); + break; + } + DBUG_ASSERT(0); + DBUG_RETURN(NULL); } @@ -11381,7 +11570,6 @@ int QUICK_RANGE_SELECT::reset() HANDLER_BUFFER empty_buf; MY_BITMAP * const save_read_set= head->read_set; MY_BITMAP * const save_write_set= head->write_set; - MY_BITMAP * const save_vcol_set= head->vcol_set; DBUG_ENTER("QUICK_RANGE_SELECT::reset"); last_range= NULL; cur_range= (QUICK_RANGE**) ranges.buffer; @@ -11395,8 +11583,7 @@ int QUICK_RANGE_SELECT::reset() } if (in_ror_merged_scan) - head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap, - &column_bitmap); + head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap); if (file->inited == handler::NONE) { @@ -11442,8 +11629,7 @@ int QUICK_RANGE_SELECT::reset() err: /* Restore bitmaps set on entry */ if (in_ror_merged_scan) - head->column_bitmaps_set_no_signal(save_read_set, save_write_set, - save_vcol_set); + head->column_bitmaps_set_no_signal(save_read_set, save_write_set); DBUG_RETURN(error); } @@ -11474,16 +11660,13 @@ int QUICK_RANGE_SELECT::get_next() MY_BITMAP * const save_read_set= head->read_set; MY_BITMAP * const save_write_set= head->write_set; - MY_BITMAP * const save_vcol_set= head->vcol_set; /* We don't need to signal the bitmap change as the bitmap is always the same for this head->file */ - head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap, - &column_bitmap); + head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap); result= file->multi_range_read_next(&dummy); - head->column_bitmaps_set_no_signal(save_read_set, save_write_set, - save_vcol_set); + head->column_bitmaps_set_no_signal(save_read_set, save_write_set); DBUG_RETURN(result); } @@ -13058,7 +13241,8 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item, if (args[0] && args[1]) // this is a binary function or BETWEEN { - DBUG_ASSERT(pred->is_bool_type()); + DBUG_ASSERT(pred->fixed_type_handler()); + DBUG_ASSERT(pred->fixed_type_handler()->is_bool_type()); Item_bool_func *bool_func= (Item_bool_func*) pred; Field *field= min_max_arg_item->field; if (!args[2]) // this is a binary function diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 13c0ce0c157..c4c30c9b50d 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -519,6 +519,7 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs, if (optimizer_flag(thd, OPTIMIZER_SWITCH_MATERIALIZATION) && // 0 !child_select->is_part_of_union() && // 1 parent_unit->first_select()->leaf_tables.elements && // 2 + child_select->outer_select() && child_select->outer_select()->leaf_tables.elements && // 2A subquery_types_allow_materialization(in_subs) && (in_subs->is_top_level_item() || //3 @@ -826,7 +827,7 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs) { DBUG_ENTER("subquery_types_allow_materialization"); - DBUG_ASSERT(in_subs->left_expr->fixed); + DBUG_ASSERT(in_subs->left_expr->is_fixed()); List_iterator<Item> it(in_subs->unit->first_select()->item_list); uint elements= in_subs->unit->first_select()->item_list.elements; @@ -902,7 +903,7 @@ bool make_in_exists_conversion(THD *thd, JOIN *join, Item_in_subselect *item) /* We're going to finalize IN->EXISTS conversion. Normally, IN->EXISTS conversion takes place inside the - Item_subselect::fix_fields() call, where item_subselect->fixed==FALSE (as + Item_subselect::fix_fields() call, where item_subselect->is_fixed()==FALSE (as fix_fields() haven't finished yet) and item_subselect->changed==FALSE (as the conversion haven't been finalized) @@ -929,7 +930,7 @@ bool make_in_exists_conversion(THD *thd, JOIN *join, Item_in_subselect *item) item->fixed= 1; Item *substitute= item->substitution; - bool do_fix_fields= !item->substitution->fixed; + bool do_fix_fields= !item->substitution->is_fixed(); /* The Item_subselect has already been wrapped with Item_in_optimizer, so we should search for item->optimizer, not 'item'. @@ -1265,7 +1266,7 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) in_subq->fixed= 1; Item *substitute= in_subq->substitution; - bool do_fix_fields= !in_subq->substitution->fixed; + bool do_fix_fields= !in_subq->substitution->is_fixed(); Item **tree= (in_subq->emb_on_expr_nest == NO_JOIN_NEST)? &join->conds : &(in_subq->emb_on_expr_nest->on_expr); Item *replace_me= in_subq->original_item(); @@ -1800,7 +1801,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) subq_lex->ref_pointer_array[i]); if (!item_eq) DBUG_RETURN(TRUE); - DBUG_ASSERT(subq_pred->left_expr->element_index(i)->fixed); + DBUG_ASSERT(subq_pred->left_expr->element_index(i)->is_fixed()); if (subq_pred->left_expr_orig->element_index(i) != subq_pred->left_expr->element_index(i)) thd->change_item_tree(item_eq->arguments(), @@ -5509,31 +5510,454 @@ int select_value_catcher::send_data(List<Item> &items) } -/* - Setup JTBM join tabs for execution +/** + @brief + Add new conditions after optimize_cond() call + + @param thd the thread handle + @param cond the condition where to attach new conditions + @param cond_eq IN/OUT the multiple equalities of cond + @param new_conds IN/OUT the list of conditions needed to add + @param cond_value the returned value of the condition + + @details + The method creates new condition through conjunction of cond and + the conditions from new_conds list. + The method is called after optimize_cond() for cond. The result + of the conjunction should be the same as if it was done before the + the optimize_cond() call. + + @retval NULL if an error occurs + @retval otherwise the created condition */ -bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, - Item **join_where) +Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond, + COND_EQUAL **cond_eq, + List<Item> &new_conds, + Item::cond_result *cond_value) +{ + COND_EQUAL new_cond_equal; + Item *item; + Item_equal *equality; + bool is_simplified_cond= false; + List_iterator<Item> li(new_conds); + List_iterator_fast<Item_equal> it(new_cond_equal.current_level); + + /* + Creates multiple equalities new_cond_equal from new_conds list + equalities. If multiple equality can't be created or the condition + from new_conds list isn't an equality the method leaves it in new_conds + list. + + The equality can't be converted into the multiple equality if it + is a knowingly false or true equality. + For example, (3 = 1) equality. + */ + while ((item=li++)) + { + if (item->type() == Item::FUNC_ITEM && + ((Item_func *) item)->functype() == Item_func::EQ_FUNC && + check_simple_equality(thd, + Item::Context(Item::ANY_SUBST, + ((Item_func_equal *)item)->compare_type_handler(), + ((Item_func_equal *)item)->compare_collation()), + ((Item_func *)item)->arguments()[0], + ((Item_func *)item)->arguments()[1], + &new_cond_equal)) + li.remove(); + } + + it.rewind(); + if (cond && cond->type() == Item::COND_ITEM && + ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) + { + /* + cond is an AND-condition. + The method conjugates the AND-condition cond, created multiple + equalities new_cond_equal and remain conditions from new_conds. + + First, the method disjoins multiple equalities of cond and + merges new_cond_equal multiple equalities with these equalities. + It checks if after the merge the multiple equalities are knowingly + true or false equalities. + It attaches to cond the conditions from new_conds list and the result + of the merge of multiple equalities. The multiple equalities are + attached only to the upper level of AND-condition cond. So they + should be pushed down to the inner levels of cond AND-condition + if needed. It is done by propagate_new_equalities(). + */ + COND_EQUAL *cond_equal= &((Item_cond_and *) cond)->m_cond_equal; + List<Item_equal> *cond_equalities= &cond_equal->current_level; + List<Item> *and_args= ((Item_cond_and *)cond)->argument_list(); + and_args->disjoin((List<Item> *) cond_equalities); + and_args->append(&new_conds); + + while ((equality= it++)) + { + equality->upper_levels= 0; + equality->merge_into_list(thd, cond_equalities, false, false); + } + List_iterator_fast<Item_equal> ei(*cond_equalities); + while ((equality= ei++)) + { + if (equality->const_item() && !equality->val_int()) + is_simplified_cond= true; + equality->fixed= 0; + if (equality->fix_fields(thd, NULL)) + return NULL; + } + + and_args->append((List<Item> *) cond_equalities); + *cond_eq= &((Item_cond_and *) cond)->m_cond_equal; + + propagate_new_equalities(thd, cond, cond_equalities, + cond_equal->upper_levels, + &is_simplified_cond); + cond= cond->propagate_equal_fields(thd, + Item::Context_boolean(), + cond_equal); + } + else + { + /* + cond isn't AND-condition or is NULL. + There can be several cases: + + 1. cond is a multiple equality. + In this case cond is merged with the multiple equalities of + new_cond_equal. + The new condition is created with the conjunction of new_conds + list conditions and the result of merge of multiple equalities. + 2. cond is NULL + The new condition is created from the conditions of new_conds + list and multiple equalities from new_cond_equal. + 3. Otherwise + In this case the new condition is created from cond, remain conditions + from new_conds list and created multiple equalities from + new_cond_equal. + */ + List<Item> new_conds_list; + /* Flag is set to true if cond is a multiple equality */ + bool is_mult_eq= (cond && cond->type() == Item::FUNC_ITEM && + ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC); + + if (cond && !is_mult_eq && + new_conds_list.push_back(cond, thd->mem_root)) + return NULL; + + if (new_conds.elements > 0) + { + li.rewind(); + while ((item=li++)) + { + if (item->fix_fields_if_needed(thd, NULL)) + return NULL; + if (item->const_item() && !item->val_int()) + is_simplified_cond= true; + } + + if (new_conds.elements > 1) + new_conds_list.append(&new_conds); + else + { + li.rewind(); + item= li++; + if (new_conds_list.push_back(item, thd->mem_root)) + return NULL; + } + } + + if (is_mult_eq) + { + Item_equal *eq_cond= (Item_equal *)cond; + eq_cond->upper_levels= 0; + eq_cond->merge_into_list(thd, &new_cond_equal.current_level, + false, false); + + while ((equality= it++)) + { + if (equality->const_item() && !equality->val_int()) + is_simplified_cond= true; + } + (*cond_eq)->copy(new_cond_equal); + } + + if (new_cond_equal.current_level.elements > 0) + { + if (new_cond_equal.current_level.elements + + new_conds_list.elements == 1) + { + it.rewind(); + equality= it++; + equality->fixed= 0; + if (equality->fix_fields(thd, NULL)) + return NULL; + } + new_conds_list.append((List<Item> *)&new_cond_equal.current_level); + } + + if (new_conds_list.elements > 1) + { + Item_cond_and *and_cond= + new (thd->mem_root) Item_cond_and(thd, new_conds_list); + + and_cond->m_cond_equal.copy(new_cond_equal); + cond= (Item *)and_cond; + *cond_eq= &((Item_cond_and *)cond)->m_cond_equal; + } + else + { + List_iterator_fast<Item> iter(new_conds_list); + cond= iter++; + } + + if (cond->fix_fields_if_needed(thd, NULL)) + return NULL; + + if (new_cond_equal.current_level.elements > 0) + cond= cond->propagate_equal_fields(thd, + Item::Context_boolean(), + &new_cond_equal); + } + + /* + If it was found that some of the created condition parts are knowingly + true or false equalities the method calls removes_eq_cond() to remove them + from cond and set the cond_value to the appropriate value. + */ + if (is_simplified_cond) + cond= cond->remove_eq_conds(thd, cond_value, true); + return cond; +} + + +/** + @brief Materialize a degenerate jtbm semi join + + @param thd thread handler + @param tbl table list for the target jtbm semi join table + @param subq_pred IN subquery predicate with the degenerate jtbm semi join + @param eq_list IN/OUT the list where to add produced equalities + + @details + The method materializes the degenerate jtbm semi join for the + subquery from the IN subquery predicate subq_pred taking table + as the target for materialization. + Any degenerate table is guaranteed to produce 0 or 1 record. + Examples of both cases: + + select * from ot where col in (select ... from it where 2>3) + select * from ot where col in (select MY_MIN(it.key) from it) + + in this case, there is no necessity to create a temp.table for + materialization. + We now just need to + 1. Check whether 1 or 0 records are produced, setup this as a + constant join tab. + 2. Create a dummy temporary table, because all of the join + optimization code relies on TABLE object being present. + + In the case when materialization produces one row the function + additionally creates equalities between the expressions from the + left part of the IN subquery predicate and the corresponding + columns of the produced row. These equalities are added to the + list eq_list. They are supposed to be conjuncted with the condition + of the WHERE clause. + + @retval TRUE if an error occurs + @retval FALSE otherwise +*/ + +bool execute_degenerate_jtbm_semi_join(THD *thd, + TABLE_LIST *tbl, + Item_in_subselect *subq_pred, + List<Item> &eq_list) +{ + DBUG_ENTER("execute_degenerate_jtbm_semi_join"); + select_value_catcher *new_sink; + + DBUG_ASSERT(subq_pred->engine->engine_type() == + subselect_engine::SINGLE_SELECT_ENGINE); + subselect_single_select_engine *engine= + (subselect_single_select_engine*)subq_pred->engine; + if (!(new_sink= new (thd->mem_root) select_value_catcher(thd, subq_pred))) + DBUG_RETURN(TRUE); + if (new_sink->setup(&engine->select_lex->join->fields_list) || + engine->select_lex->join->change_result(new_sink, NULL) || + engine->exec()) + { + DBUG_RETURN(TRUE); + } + subq_pred->is_jtbm_const_tab= TRUE; + + if (new_sink->assigned) + { + /* + Subselect produced one row, which is saved in new_sink->row. + Save "left_expr[i] == row[i]" equalities into the eq_list. + */ + subq_pred->jtbm_const_row_found= TRUE; + + Item *eq_cond; + for (uint i= 0; i < subq_pred->left_expr->cols(); i++) + { + eq_cond= + new (thd->mem_root) Item_func_eq(thd, + subq_pred->left_expr->element_index(i), + new_sink->row[i]); + if (!eq_cond || eq_cond->fix_fields(thd, NULL) || + eq_list.push_back(eq_cond, thd->mem_root)) + DBUG_RETURN(TRUE); + } + } + else + { + /* Subselect produced no rows. Just set the flag */ + subq_pred->jtbm_const_row_found= FALSE; + } + + TABLE *dummy_table; + if (!(dummy_table= create_dummy_tmp_table(thd))) + DBUG_RETURN(TRUE); + tbl->table= dummy_table; + tbl->table->pos_in_table_list= tbl; + /* + Note: the table created above may be freed by: + 1. JOIN_TAB::cleanup(), when the parent join is a regular join. + 2. cleanup_empty_jtbm_semi_joins(), when the parent join is a + degenerate join (e.g. one with "Impossible where"). + */ + setup_table_map(tbl->table, tbl, tbl->jtbm_table_no); + DBUG_RETURN(FALSE); +} + + +/** + @brief + Execute degenerate jtbm semi joins before optimize_cond() for parent + + @param join the parent join for jtbm semi joins + @param join_list the list of tables where jtbm semi joins are processed + @param eq_list IN/OUT the list where to add equalities produced after + materialization of single-row degenerate jtbm semi joins + + @details + The method traverses join_list trying to find any degenerate jtbm semi + joins for subqueries of IN predicates. For each degenerate jtbm + semi join execute_degenerate_jtbm_semi_join() is called. As a result + of this call new equalities that substitute for single-row materialized + jtbm semi join are added to eq_list. + + In the case when a table is nested in another table 'nested_join' the + method is recursively called for the join_list of the 'nested_join' trying + to find in the list any degenerate jtbm semi joins. Currently a jtbm semi + join may occur in a mergeable semi join nest. + + @retval TRUE if an error occurs + @retval FALSE otherwise +*/ + +bool setup_degenerate_jtbm_semi_joins(JOIN *join, + List<TABLE_LIST> *join_list, + List<Item> &eq_list) +{ + TABLE_LIST *table; + NESTED_JOIN *nested_join; + List_iterator<TABLE_LIST> li(*join_list); + THD *thd= join->thd; + DBUG_ENTER("setup_degenerate_jtbm_semi_joins"); + + while ((table= li++)) + { + Item_in_subselect *subq_pred; + + if ((subq_pred= table->jtbm_subselect)) + { + JOIN *subq_join= subq_pred->unit->first_select()->join; + + if (!subq_join->tables_list || !subq_join->table_count) + { + if (execute_degenerate_jtbm_semi_join(thd, + table, + subq_pred, + eq_list)) + DBUG_RETURN(TRUE); + join->is_orig_degenerated= true; + } + } + if ((nested_join= table->nested_join)) + { + if (setup_degenerate_jtbm_semi_joins(join, + &nested_join->join_list, + eq_list)) + DBUG_RETURN(TRUE); + } + } + DBUG_RETURN(FALSE); +} + + +/** + @brief + Optimize jtbm semi joins for materialization + + @param join the parent join for jtbm semi joins + @param join_list the list of TABLE_LIST objects where jtbm semi join + can occur + @param eq_list IN/OUT the list where to add produced equalities + + @details + This method is called by the optimizer after the call of + optimize_cond() for parent select. + The method traverses join_list trying to find any jtbm semi joins for + subqueries from IN predicates and optimizes them. + After the optimization some of jtbm semi joins may become degenerate. + For example the subquery 'SELECT MAX(b) FROM t2' from the query + + SELECT * FROM t1 WHERE 4 IN (SELECT MAX(b) FROM t2); + + will become degenerate if there is an index on t2.b. + If a subquery becomes degenerate it is handled by the function + execute_degenerate_jtbm_semi_join(). + + Otherwise the method creates a temporary table in which the subquery + of the jtbm semi join will be materialied. + + The function saves the equalities between all pairs of the expressions + from the left part of the IN subquery predicate and the corresponding + columns of the subquery from the predicate in eq_list appending them + to the list. The equalities of eq_list will be later conjucted with the + condition of the WHERE clause. + + In the case when a table is nested in another table 'nested_join' the + method is recursively called for the join_list of the 'nested_join' trying + to find in the list any degenerate jtbm semi joins. Currently a jtbm semi + join may occur in a mergeable semi join nest. + + @retval TRUE if an error occurs + @retval FALSE otherwise +*/ + +bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, + List<Item> &eq_list) { TABLE_LIST *table; NESTED_JOIN *nested_join; List_iterator<TABLE_LIST> li(*join_list); THD *thd= join->thd; DBUG_ENTER("setup_jtbm_semi_joins"); - + while ((table= li++)) { - Item_in_subselect *item; + Item_in_subselect *subq_pred; - if ((item= table->jtbm_subselect)) + if ((subq_pred= table->jtbm_subselect)) { - Item_in_subselect *subq_pred= item; double rows; double read_time; /* - Perform optimization of the subquery, so that we know estmated + Perform optimization of the subquery, so that we know estimated - cost of materialization process - how many records will be in the materialized temp.table */ @@ -5546,102 +5970,37 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, if (!subq_join->tables_list || !subq_join->table_count) { - /* - A special case; subquery's join is degenerate, and it either produces - 0 or 1 record. Examples of both cases: - - select * from ot where col in (select ... from it where 2>3) - select * from ot where col in (select MY_MIN(it.key) from it) - - in this case, the subquery predicate has not been setup for - materialization. In particular, there is no materialized temp.table. - We'll now need to - 1. Check whether 1 or 0 records are produced, setup this as a - constant join tab. - 2. Create a dummy temporary table, because all of the join - optimization code relies on TABLE object being present (here we - follow a bad tradition started by derived tables) - */ - DBUG_ASSERT(subq_pred->engine->engine_type() == - subselect_engine::SINGLE_SELECT_ENGINE); - subselect_single_select_engine *engine= - (subselect_single_select_engine*)subq_pred->engine; - select_value_catcher *new_sink; - if (!(new_sink= - new (thd->mem_root) select_value_catcher(thd, subq_pred))) + if (!join->is_orig_degenerated && + execute_degenerate_jtbm_semi_join(thd, table, subq_pred, + eq_list)) DBUG_RETURN(TRUE); - if (new_sink->setup(&engine->select_lex->join->fields_list) || - engine->select_lex->join->change_result(new_sink, NULL) || - engine->exec()) - { - DBUG_RETURN(TRUE); - } - subq_pred->is_jtbm_const_tab= TRUE; - - if (new_sink->assigned) - { - subq_pred->jtbm_const_row_found= TRUE; - /* - Subselect produced one row, which is saved in new_sink->row. - Inject "left_expr[i] == row[i] equalities into parent's WHERE. - */ - Item *eq_cond; - for (uint i= 0; i < subq_pred->left_expr->cols(); i++) - { - eq_cond= new (thd->mem_root) - Item_func_eq(thd, subq_pred->left_expr->element_index(i), - new_sink->row[i]); - if (!eq_cond) - DBUG_RETURN(1); - - if (!((*join_where)= and_items(thd, *join_where, eq_cond)) || - (*join_where)->fix_fields(thd, join_where)) - DBUG_RETURN(1); - } - } - else - { - /* Subselect produced no rows. Just set the flag, */ - subq_pred->jtbm_const_row_found= FALSE; - } - - /* Set up a dummy TABLE*, optimizer code needs JOIN_TABs to have TABLE */ - TABLE *dummy_table; - if (!(dummy_table= create_dummy_tmp_table(thd))) - DBUG_RETURN(1); - table->table= dummy_table; - table->table->pos_in_table_list= table; - /* - Note: the table created above may be freed by: - 1. JOIN_TAB::cleanup(), when the parent join is a regular join. - 2. cleanup_empty_jtbm_semi_joins(), when the parent join is a - degenerate join (e.g. one with "Impossible where"). - */ - setup_table_map(table->table, table, table->jtbm_table_no); } else { DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION)); subq_pred->is_jtbm_const_tab= FALSE; subselect_hash_sj_engine *hash_sj_engine= - ((subselect_hash_sj_engine*)item->engine); + ((subselect_hash_sj_engine*)subq_pred->engine); table->table= hash_sj_engine->tmp_table; table->table->pos_in_table_list= table; setup_table_map(table->table, table, table->jtbm_table_no); - Item *sj_conds= hash_sj_engine->semi_join_conds; - - (*join_where)= and_items(thd, *join_where, sj_conds); - (*join_where)->fix_fields_if_needed(thd, join_where); + List_iterator<Item> li(*hash_sj_engine->semi_join_conds->argument_list()); + Item *item; + while ((item=li++)) + { + item->update_used_tables(); + if (eq_list.push_back(item, thd->mem_root)) + DBUG_RETURN(TRUE); + } } table->table->maybe_null= MY_TEST(join->mixed_implicit_grouping); } - if ((nested_join= table->nested_join)) { - if (setup_jtbm_semi_joins(join, &nested_join->join_list, join_where)) + if (setup_jtbm_semi_joins(join, &nested_join->join_list, eq_list)) DBUG_RETURN(TRUE); } } @@ -5749,8 +6108,8 @@ bool JOIN::choose_subquery_plan(table_map join_tables) /* A strategy must be chosen earlier. */ DBUG_ASSERT(in_subs->has_strategy()); DBUG_ASSERT(in_to_exists_where || in_to_exists_having); - DBUG_ASSERT(!in_to_exists_where || in_to_exists_where->fixed); - DBUG_ASSERT(!in_to_exists_having || in_to_exists_having->fixed); + DBUG_ASSERT(!in_to_exists_where || in_to_exists_where->is_fixed()); + DBUG_ASSERT(!in_to_exists_having || in_to_exists_having->is_fixed()); /* The original QEP of the subquery. */ Join_plan_state save_qep(table_count); @@ -6037,3 +6396,418 @@ bool JOIN::choose_tableless_subquery_plan() exec_const_cond= zero_result_cause ? 0 : conds; return FALSE; } + + +/* + Check if the item exists in the fields list of the left part of + the IN subquery predicate subq_pred and returns its corresponding + item from the select of the right part of subq_pred. +*/ +Item *Item::get_corresponding_field_in_insubq(Item_in_subselect *subq_pred) +{ + DBUG_ASSERT(type() == Item::FIELD_ITEM || + (type() == Item::REF_ITEM && + ((Item_ref *) this)->ref_type() == Item_ref::VIEW_REF)); + + List_iterator<Field_pair> it(subq_pred->corresponding_fields); + Field_pair *ret; + Item_field *field_item= (Item_field *) (real_item()); + while ((ret= it++)) + { + if (field_item->field == ret->field) + return ret->corresponding_item; + } + return NULL; +} + + +bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) +{ + if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred)) + return true; + if (item_equal) + { + Item_equal_fields_iterator it(*item_equal); + Item *equal_item; + while ((equal_item= it++)) + { + if (equal_item->const_item()) + continue; + if (equal_item->get_corresponding_field_in_insubq(subq_pred)) + return true; + } + } + return false; +} + + +bool Item_direct_view_ref::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) +{ + if (item_equal) + { + DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM); + if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred)) + return true; + } + return (*ref)->excl_dep_on_in_subq_left_part(subq_pred); +} + + +bool Item_equal::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) +{ + Item *left_item = get_const(); + Item_equal_fields_iterator it(*this); + Item *item; + if (!left_item) + { + while ((item=it++)) + { + if (item->excl_dep_on_in_subq_left_part(subq_pred)) + { + left_item= item; + break; + } + } + } + if (!left_item) + return false; + while ((item=it++)) + { + if (item->excl_dep_on_in_subq_left_part(subq_pred)) + return true; + } + return false; +} + + +/** + @brief + Get corresponding item from the select of the right part of IN subquery + + @param thd the thread handle + @param item the item from the left part of subq_pred for which + corresponding item should be found + @param subq_pred the IN subquery predicate + + @details + This method looks through the fields of the select of the right part of + the IN subquery predicate subq_pred trying to find the corresponding + item 'new_item' for item. If item has equal items it looks through + the fields of the select of the right part of subq_pred for each equal + item trying to find the corresponding item. + The method assumes that the given item is either a field item or + a reference to a field item. + + @retval <item*> reference to the corresponding item + @retval NULL if item was not found +*/ + +static +Item *get_corresponding_item(THD *thd, Item *item, + Item_in_subselect *subq_pred) +{ + DBUG_ASSERT(item->type() == Item::FIELD_ITEM || + (item->type() == Item::REF_ITEM && + ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF)); + + Item *corresonding_item; + Item_equal *item_equal= item->get_item_equal(); + + if (item_equal) + { + Item_equal_fields_iterator it(*item_equal); + Item *equal_item; + while ((equal_item= it++)) + { + corresonding_item= + equal_item->get_corresponding_field_in_insubq(subq_pred); + if (corresonding_item) + return corresonding_item; + } + return NULL; + } + else + return item->get_corresponding_field_in_insubq(subq_pred); +} + + +Item *Item_field::in_subq_field_transformer_for_where(THD *thd, uchar *arg) +{ + Item_in_subselect *subq_pred= (Item_in_subselect *)arg; + Item *producing_item= get_corresponding_item(thd, this, subq_pred); + if (producing_item) + return producing_item->build_clone(thd); + return this; +} + + +Item *Item_direct_view_ref::in_subq_field_transformer_for_where(THD *thd, + uchar *arg) +{ + if (item_equal) + { + Item_in_subselect *subq_pred= (Item_in_subselect *)arg; + Item *producing_item= get_corresponding_item(thd, this, subq_pred); + DBUG_ASSERT (producing_item != NULL); + return producing_item->build_clone(thd); + } + return this; +} + + +/** + @brief + Transforms item so it can be pushed into the IN subquery HAVING clause + + @param thd the thread handle + @param in_item the item for which pushable item should be created + @param subq_pred the IN subquery predicate + + @details + This method finds for in_item that is a field from the left part of the + IN subquery predicate subq_pred its corresponding item from the right part + of subq_pred. + If corresponding item is found, a shell for this item is created. + This shell can be pushed into the HAVING part of subq_pred select. + + @retval <item*> reference to the created corresponding item shell for in_item + @retval NULL if mistake occurs +*/ + +static Item* +get_corresponding_item_for_in_subq_having(THD *thd, Item *in_item, + Item_in_subselect *subq_pred) +{ + Item *new_item= get_corresponding_item(thd, in_item, subq_pred); + + if (new_item) + { + Item_ref *ref= + new (thd->mem_root) Item_ref(thd, + &subq_pred->unit->first_select()->context, + NullS, NullS, + &new_item->name); + if (!ref) + DBUG_ASSERT(0); + return ref; + } + return new_item; +} + + +Item *Item_field::in_subq_field_transformer_for_having(THD *thd, uchar *arg) +{ + return get_corresponding_item_for_in_subq_having(thd, this, + (Item_in_subselect *)arg); +} + + +Item *Item_direct_view_ref::in_subq_field_transformer_for_having(THD *thd, + uchar *arg) +{ + if (!item_equal) + return this; + else + { + Item *new_item= get_corresponding_item_for_in_subq_having(thd, this, + (Item_in_subselect *)arg); + if (!new_item) + return this; + return new_item; + } +} + + +/** + @brief + Find fields that are used in the GROUP BY of the select + + @param thd the thread handle + @param sel the select of the IN subquery predicate + @param fields fields of the left part of the IN subquery predicate + @param grouping_list GROUP BY clause + + @details + This method traverses fields which are used in the GROUP BY of + sel and saves them with their corresponding items from fields. +*/ + +bool grouping_fields_in_the_in_subq_left_part(THD *thd, + st_select_lex *sel, + List<Field_pair> *fields, + ORDER *grouping_list) +{ + DBUG_ENTER("grouping_fields_in_the_in_subq_left_part"); + sel->grouping_tmp_fields.empty(); + List_iterator<Field_pair> it(*fields); + Field_pair *item; + while ((item= it++)) + { + for (ORDER *ord= grouping_list; ord; ord= ord->next) + { + if ((*ord->item)->eq(item->corresponding_item, 0)) + { + if (sel->grouping_tmp_fields.push_back(item, thd->mem_root)) + DBUG_RETURN(TRUE); + } + } + } + DBUG_RETURN(FALSE); +} + + +/** + @brief + Extract condition that can be pushed into select of this IN subquery + + @param thd the thread handle + @param cond current condition + + @details + This function builds the most restrictive condition depending only on + the list of fields of the left part of this IN subquery predicate + (directly or indirectly through equality) that can be extracted from the + given condition cond and pushes it into this IN subquery. + + Example of the transformation: + + SELECT * FROM t1 + WHERE a>3 AND b>10 AND + (a,b) IN (SELECT x,MAX(y) FROM t2 GROUP BY x); + + => + + SELECT * FROM t1 + WHERE a>3 AND b>10 AND + (a,b) IN (SELECT x,max(y) + FROM t2 + WHERE x>3 + GROUP BY x + HAVING MAX(y)>10); + + + In details: + 1. Check what pushable formula can be extracted from cond + 2. Build a clone PC of the formula that can be extracted + (the clone is built only if the extracted formula is a AND subformula + of cond or conjunction of such subformulas) + 3. If there is no HAVING clause prepare PC to be conjuncted with + WHERE clause of this subquery. Otherwise do 4-7. + 4. Check what formula PC_where can be extracted from PC to be pushed + into the WHERE clause of the subquery + 5. Build PC_where and if PC_where is a conjunct(s) of PC remove it from PC + getting PC_having + 6. Prepare PC_where to be conjuncted with the WHERE clause of + the IN subquery + 7. Prepare PC_having to be conjuncted with the HAVING clause of + the IN subquery + + @note + This method is similar to pushdown_cond_for_derived() + + @retval TRUE if an error occurs + @retval FALSE otherwise +*/ + +bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond) +{ + DBUG_ENTER("Item_in_subselect::pushdown_cond_for_in_subquery"); + Item *remaining_cond= NULL; + + if (!cond) + DBUG_RETURN(FALSE); + + st_select_lex *sel = unit->first_select(); + + if (is_jtbm_const_tab) + DBUG_RETURN(FALSE); + + if (!sel->cond_pushdown_is_allowed()) + DBUG_RETURN(FALSE); + + /* + Create a list of Field_pair items for this IN subquery. + It consists of the pairs of fields from the left part of this IN subquery + predicate 'left_part' and the respective fields from the select of the + right part of the IN subquery 'sel' (the field from left_part with the + corresponding field from the sel projection list). + Attach this list to the IN subquery. + */ + corresponding_fields.empty(); + List_iterator_fast<Item> it(sel->join->fields_list); + Item *item; + for (uint i= 0; i < left_expr->cols(); i++) + { + item= it++; + Item *elem= left_expr->element_index(i); + + if (elem->real_item()->type() != Item::FIELD_ITEM) + continue; + + if (corresponding_fields.push_back( + new Field_pair(((Item_field *)(elem->real_item()))->field, + item))) + DBUG_RETURN(TRUE); + } + + /* 1. Check what pushable formula can be extracted from cond */ + Item *extracted_cond; + cond->check_pushable_cond(&Item::pushable_cond_checker_for_subquery, + (uchar *)this); + /* 2. Build a clone PC of the formula that can be extracted */ + extracted_cond= + cond->build_pushable_cond(thd, + &Item::pushable_equality_checker_for_subquery, + (uchar *)this); + /* Nothing to push */ + if (!extracted_cond) + { + DBUG_RETURN(FALSE); + } + + /* Collect fields that are used in the GROUP BY of sel */ + st_select_lex *save_curr_select= thd->lex->current_select; + if (sel->have_window_funcs()) + { + if (sel->group_list.first || sel->join->implicit_grouping) + goto exit; + ORDER *common_partition_fields= + sel->find_common_window_func_partition_fields(thd); + if (!common_partition_fields) + goto exit; + + if (grouping_fields_in_the_in_subq_left_part(thd, sel, &corresponding_fields, + common_partition_fields)) + DBUG_RETURN(TRUE); + } + else if (grouping_fields_in_the_in_subq_left_part(thd, sel, + &corresponding_fields, + sel->group_list.first)) + DBUG_RETURN(TRUE); + + /* Do 4-6 */ + sel->pushdown_cond_into_where_clause(thd, extracted_cond, + &remaining_cond, + &Item::in_subq_field_transformer_for_where, + (uchar *) this); + if (!remaining_cond) + goto exit; + /* + 7. Prepare PC_having to be conjuncted with the HAVING clause of + the IN subquery + */ + remaining_cond= + remaining_cond->transform(thd, + &Item::in_subq_field_transformer_for_having, + (uchar *)this); + if (!remaining_cond) + goto exit; + + remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor, + 0, 0); + sel->cond_pushed_into_having= remaining_cond; + +exit: + thd->lex->current_select= save_curr_select; + DBUG_RETURN(FALSE); +} diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index 9cb19e0cc6c..031118288b9 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -26,8 +26,15 @@ int check_and_do_in_subquery_rewrites(JOIN *join); bool convert_join_subqueries_to_semijoins(JOIN *join); int pull_out_semijoin_tables(JOIN *join); bool optimize_semijoin_nests(JOIN *join, table_map all_table_map); -bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, - Item **join_where); +Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond, + COND_EQUAL **cond_eq, + List<Item> &new_conds, + Item::cond_result *cond_value); +bool setup_degenerate_jtbm_semi_joins(JOIN *join, + List<TABLE_LIST> *join_list, + List<Item> &eq_list); +bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, + List<Item> &eq_list); void cleanup_empty_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list); // used by Loose_scan_opt diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 82946709166..ecede5903a2 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -318,7 +318,7 @@ int opt_sum_query(THD *thd, error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); if (unlikely(error)) { - tl->table->file->print_error(error, MYF(ME_FATALERROR)); + tl->table->file->print_error(error, MYF(ME_FATAL)); DBUG_RETURN(error); } count*= tl->table->file->stats.records; diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc index ef9b07cca47..74d1e775c43 100644 --- a/sql/opt_table_elimination.cc +++ b/sql/opt_table_elimination.cc @@ -617,12 +617,12 @@ void eliminate_tables(JOIN *join) we should also take into account tables mentioned in "val". */ if (join->thd->lex->sql_command == SQLCOM_INSERT_SELECT && - join->select_lex == &thd->lex->select_lex) + join->select_lex == thd->lex->first_select_lex()) { List_iterator<Item> val_it(thd->lex->value_list); while ((item= val_it++)) { - DBUG_ASSERT(item->fixed); + DBUG_ASSERT(item->is_fixed()); used_tables |= item->used_tables(); } } @@ -640,7 +640,7 @@ void eliminate_tables(JOIN *join) used_tables |= (*(cur_list->item))->used_tables(); } - if (join->select_lex == &thd->lex->select_lex) + if (join->select_lex == thd->lex->first_select_lex()) { /* Multi-table UPDATE: don't eliminate tables referred from SET statement */ diff --git a/sql/partition_info.h b/sql/partition_info.h index 95700dac517..c7d8e16dfeb 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -395,12 +395,13 @@ public: bool field_in_partition_expr(Field *field) const; bool vers_init_info(THD *thd); - bool vers_set_interval(Item *item, interval_type int_type, my_time_t start) + bool vers_set_interval(THD *thd, Item *item, + interval_type int_type, my_time_t start) { DBUG_ASSERT(part_type == VERSIONING_PARTITION); vers_info->interval.type= int_type; vers_info->interval.start= start; - return get_interval_value(item, int_type, &vers_info->interval.step) || + return get_interval_value(thd, item, int_type, &vers_info->interval.step) || vers_info->interval.step.neg || vers_info->interval.step.second_part || !(vers_info->interval.step.year || vers_info->interval.step.month || vers_info->interval.step.day || vers_info->interval.step.hour || diff --git a/sql/procedure.h b/sql/procedure.h index 1ece31223ad..050cc3817c0 100644 --- a/sql/procedure.h +++ b/sql/procedure.h @@ -44,6 +44,16 @@ public: this->name.length= strlen(name_par); } enum Type type() const { return Item::PROC_ITEM; } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + /* + We can get to here when using a CURSOR for a query with PROCEDURE: + DECLARE c CURSOR FOR SELECT * FROM t1 PROCEDURE analyse(); + OPEN c; + */ + return create_tmp_field_ex_simple(table, src, param); + } virtual void set(double nr)=0; virtual void set(const char *str,uint length,CHARSET_INFO *cs)=0; virtual void set(longlong nr)=0; @@ -59,9 +69,9 @@ public: DBUG_ASSERT(0); // impossible return mark_unsupported_function("proc", arg, VCOL_IMPOSSIBLE); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } Item* get_copy(THD *thd) { return 0; } }; diff --git a/sql/protocol.cc b/sql/protocol.cc index c4c243ea166..7eee9283989 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -1195,9 +1195,8 @@ bool Protocol_text::store_decimal(const my_decimal *d) field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL); field_pos++; #endif - char buff[DECIMAL_MAX_STR_LENGTH]; - String str(buff, sizeof(buff), &my_charset_bin); - (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str); + StringBuffer<DECIMAL_MAX_STR_LENGTH> str; + (void) d->to_string(&str); return net_store_data((uchar*) str.ptr(), str.length()); } @@ -1446,9 +1445,8 @@ bool Protocol_binary::store_decimal(const my_decimal *d) field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL); field_pos++; #endif - char buff[DECIMAL_MAX_STR_LENGTH]; - String str(buff, sizeof(buff), &my_charset_bin); - (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str); + StringBuffer<DECIMAL_MAX_STR_LENGTH> str; + (void) d->to_string(&str); return store(str.ptr(), str.length(), str.charset()); } diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 322b84130f2..17f474c2acf 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -79,7 +79,7 @@ rpl_slave_state::record_and_update_gtid(THD *thd, rpl_group_info *rgi) rgi->gtid_pending= false; if (rgi->gtid_ignore_duplicate_state!=rpl_group_info::GTID_DUPLICATE_IGNORE) { - if (record_gtid(thd, &rgi->current_gtid, sub_id, NULL, false, &hton)) + if (record_gtid(thd, &rgi->current_gtid, sub_id, false, false, &hton)) DBUG_RETURN(1); update_state_hash(sub_id, &rgi->current_gtid, hton, rgi); } @@ -244,7 +244,7 @@ rpl_slave_state_free_element(void *arg) rpl_slave_state::rpl_slave_state() - : last_sub_id(0), gtid_pos_tables(0), loaded(false) + : pending_gtid_count(0), last_sub_id(0), gtid_pos_tables(0), loaded(false) { mysql_mutex_init(key_LOCK_slave_state, &LOCK_slave_state, MY_MUTEX_INIT_SLOW); @@ -331,14 +331,11 @@ rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id, } } rgi->gtid_ignore_duplicate_state= rpl_group_info::GTID_DUPLICATE_NULL; - -#ifdef HAVE_REPLICATION - rgi->pending_gtid_deletes_clear(); -#endif } if (!(list_elem= (list_element *)my_malloc(sizeof(*list_elem), MYF(MY_WME)))) return 1; + list_elem->domain_id= domain_id; list_elem->server_id= server_id; list_elem->sub_id= sub_id; list_elem->seq_no= seq_no; @@ -348,6 +345,15 @@ rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id, if (last_sub_id < sub_id) last_sub_id= sub_id; +#ifdef HAVE_REPLICATION + ++pending_gtid_count; + if (pending_gtid_count >= opt_gtid_cleanup_batch_size) + { + pending_gtid_count = 0; + slave_background_gtid_pending_delete_request(); + } +#endif + return 0; } @@ -382,20 +388,22 @@ rpl_slave_state::get_element(uint32 domain_id) int -rpl_slave_state::put_back_list(uint32 domain_id, list_element *list) +rpl_slave_state::put_back_list(list_element *list) { - element *e; + element *e= NULL; int err= 0; mysql_mutex_lock(&LOCK_slave_state); - if (!(e= (element *)my_hash_search(&hash, (const uchar *)&domain_id, 0))) - { - err= 1; - goto end; - } while (list) { list_element *next= list->next; + + if ((!e || e->domain_id != list->domain_id) && + !(e= (element *)my_hash_search(&hash, (const uchar *)&list->domain_id, 0))) + { + err= 1; + goto end; + } e->add(list); list= next; } @@ -572,12 +580,12 @@ rpl_slave_state::select_gtid_pos_table(THD *thd, LEX_CSTRING *out_tablename) /* Write a gtid to the replication slave state table. + Do it as part of the transaction, to get slave crash safety, or as a separate + transaction if !in_transaction (eg. MyISAM or DDL). + gtid The global transaction id for this event group. sub_id Value allocated within the sub_id when the event group was read (sub_id must be consistent with commit order in master binlog). - rgi rpl_group_info context, if we are recording the gtid transactionally - as part of replicating a transactional event. NULL if called from - outside of a replicated transaction. Note that caller must later ensure that the new gtid and sub_id is inserted into the appropriate HASH element with rpl_slave_state.add(), so that it can @@ -585,16 +593,13 @@ rpl_slave_state::select_gtid_pos_table(THD *thd, LEX_CSTRING *out_tablename) */ int rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, - rpl_group_info *rgi, bool in_statement, + bool in_transaction, bool in_statement, void **out_hton) { TABLE_LIST tlist; int err= 0, not_sql_thread; bool table_opened= false; TABLE *table; - list_element *delete_list= 0, *next, *cur, **next_ptr_ptr, **best_ptr_ptr; - uint64 best_sub_id; - element *elem; ulonglong thd_saved_option= thd->variables.option_bits; Query_tables_list lex_backup; wait_for_commit* suspended_wfc; @@ -684,7 +689,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, thd->wsrep_ignore_table= true; #endif - if (!rgi) + if (!in_transaction) { DBUG_PRINT("info", ("resetting OPTION_BEGIN")); thd->variables.option_bits&= @@ -716,168 +721,280 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, my_error(ER_OUT_OF_RESOURCES, MYF(0)); goto end; } +end: - mysql_mutex_lock(&LOCK_slave_state); - if ((elem= get_element(gtid->domain_id)) == NULL) +#ifdef WITH_WSREP + thd->wsrep_ignore_table= false; +#endif + + if (table_opened) { - mysql_mutex_unlock(&LOCK_slave_state); - my_error(ER_OUT_OF_RESOURCES, MYF(0)); - err= 1; - goto end; + if (err || (err= ha_commit_trans(thd, FALSE))) + ha_rollback_trans(thd, FALSE); + + close_thread_tables(thd); + if (in_transaction) + thd->mdl_context.release_statement_locks(); + else + thd->mdl_context.release_transactional_locks(); } + thd->lex->restore_backup_query_tables_list(&lex_backup); + thd->variables.option_bits= thd_saved_option; + thd->resume_subsequent_commits(suspended_wfc); + DBUG_EXECUTE_IF("inject_record_gtid_serverid_100_sleep", + { + if (gtid->server_id == 100) + my_sleep(500000); + }); + DBUG_RETURN(err); +} - /* Now pull out all GTIDs that were recorded in this engine. */ - delete_list = NULL; - next_ptr_ptr= &elem->list; - cur= elem->list; - best_sub_id= 0; - best_ptr_ptr= NULL; - while (cur) + +/* + Return a list of all old GTIDs in any mysql.gtid_slave_pos* table that are + no longer needed and can be deleted from the table. + + Within each domain, we need to keep around the latest GTID (the one with the + highest sub_id), but any others in that domain can be deleted. +*/ +rpl_slave_state::list_element * +rpl_slave_state::gtid_grab_pending_delete_list() +{ + uint32 i; + list_element *full_list; + + mysql_mutex_lock(&LOCK_slave_state); + full_list= NULL; + for (i= 0; i < hash.records; ++i) { - list_element *next= cur->next; - if (cur->hton == hton) - { - /* Belongs to same engine, so move it to the delete list. */ - cur->next= delete_list; - delete_list= cur; - if (cur->sub_id > best_sub_id) + element *elem= (element *)my_hash_element(&hash, i); + list_element *elist= elem->list; + list_element *last_elem, **best_ptr_ptr, *cur, *next; + uint64 best_sub_id; + + if (!elist) + continue; /* Nothing here */ + + /* Delete any old stuff, but keep around the most recent one. */ + cur= elist; + best_sub_id= cur->sub_id; + best_ptr_ptr= &elist; + last_elem= cur; + while ((next= cur->next)) { + last_elem= next; + if (next->sub_id > best_sub_id) { - best_sub_id= cur->sub_id; - best_ptr_ptr= &delete_list; - } - else if (best_ptr_ptr == &delete_list) + best_sub_id= next->sub_id; best_ptr_ptr= &cur->next; - } - else - { - /* Another engine, leave it in the list. */ - if (cur->sub_id > best_sub_id) - { - best_sub_id= cur->sub_id; - /* Current best is not on the delete list. */ - best_ptr_ptr= NULL; } - *next_ptr_ptr= cur; - next_ptr_ptr= &cur->next; + cur= next; } - cur= next; - } - *next_ptr_ptr= NULL; - /* - If the highest sub_id element is on the delete list, put it back on the - original list, to preserve the highest sub_id element in the table for - GTID position recovery. - */ - if (best_ptr_ptr) - { + /* + Append the new elements to the full list. Note the order is important; + we do it here so that we do not break the list if best_sub_id is the + last of the new elements. + */ + last_elem->next= full_list; + /* + Delete the highest sub_id element from the old list, and put it back as + the single-element new list. + */ cur= *best_ptr_ptr; *best_ptr_ptr= cur->next; - cur->next= elem->list; + cur->next= NULL; elem->list= cur; + + /* + Collect the full list so far here. Note that elist may have moved if we + deleted the first element, so order is again important. + */ + full_list= elist; } mysql_mutex_unlock(&LOCK_slave_state); - if (!delete_list) - goto end; + return full_list; +} + - /* Now delete any already committed GTIDs. */ - bitmap_set_bit(table->read_set, table->field[0]->field_index); - bitmap_set_bit(table->read_set, table->field[1]->field_index); +/* Find the mysql.gtid_slave_posXXX table associated with a given hton. */ +LEX_CSTRING * +rpl_slave_state::select_gtid_pos_table(void *hton) +{ + struct gtid_pos_table *table_entry; - if ((err= table->file->ha_index_init(0, 0))) + /* + See comments on rpl_slave_state::gtid_pos_tables for rules around proper + access to the list. + */ + table_entry= (struct gtid_pos_table *) + my_atomic_loadptr_explicit(>id_pos_tables, MY_MEMORY_ORDER_ACQUIRE); + + while (table_entry) { - table->file->print_error(err, MYF(0)); - goto end; + if (table_entry->table_hton == hton) + { + if (likely(table_entry->state == GTID_POS_AVAILABLE)) + return &table_entry->table_name; + } + table_entry= table_entry->next; } - cur = delete_list; - while (cur) - { - uchar key_buffer[4+8]; - DBUG_EXECUTE_IF("gtid_slave_pos_simulate_failed_delete", - { err= ENOENT; - table->file->print_error(err, MYF(0)); - /* `break' does not work inside DBUG_EXECUTE_IF */ - goto dbug_break; }); + table_entry= (struct gtid_pos_table *) + my_atomic_loadptr_explicit(&default_gtid_pos_table, MY_MEMORY_ORDER_ACQUIRE); + return &table_entry->table_name; +} - next= cur->next; - table->field[1]->store(cur->sub_id, true); - /* domain_id is already set in table->record[0] from write_row() above. */ - key_copy(key_buffer, table->record[0], &table->key_info[0], 0, false); - if (table->file->ha_index_read_map(table->record[1], key_buffer, - HA_WHOLE_KEY, HA_READ_KEY_EXACT)) - /* We cannot find the row, assume it is already deleted. */ - ; - else if ((err= table->file->ha_delete_row(table->record[1]))) - table->file->print_error(err, MYF(0)); - /* - In case of error, we still discard the element from the list. We do - not want to endlessly error on the same element in case of table - corruption or such. - */ - cur= next; - if (err) - break; - } -IF_DBUG(dbug_break:, ) - table->file->ha_index_end(); +void +rpl_slave_state::gtid_delete_pending(THD *thd, + rpl_slave_state::list_element **list_ptr) +{ + int err= 0; + ulonglong thd_saved_option; -end: + if (unlikely(!loaded)) + return; #ifdef WITH_WSREP - thd->wsrep_ignore_table= false; + /* + Updates in slave state table should not be appended to galera transaction + writeset. + */ + thd->wsrep_ignore_table= true; #endif - if (table_opened) + thd_saved_option= thd->variables.option_bits; + thd->variables.option_bits&= + ~(ulonglong)(OPTION_NOT_AUTOCOMMIT |OPTION_BEGIN |OPTION_BIN_LOG | + OPTION_GTID_BEGIN); + + while (*list_ptr) { - if (err || (err= ha_commit_trans(thd, FALSE))) - { - /* - If error, we need to put any remaining delete_list back into the HASH - so we can do another delete attempt later. - */ - if (delete_list) - { - put_back_list(gtid->domain_id, delete_list); - delete_list = 0; - } + LEX_CSTRING *gtid_pos_table_name, *tmp_table_name; + Query_tables_list lex_backup; + TABLE_LIST tlist; + TABLE *table; + handler::Table_flags direct_pos; + list_element *cur, **cur_ptr_ptr; + bool table_opened= false; + void *hton= (*list_ptr)->hton; - ha_rollback_trans(thd, FALSE); + thd->reset_for_next_command(); + + /* + Only the SQL thread can call select_gtid_pos_table without a mutex + Other threads needs to use a mutex and take into account that the + result may change during execution, so we have to make a copy. + */ + mysql_mutex_lock(&LOCK_slave_state); + tmp_table_name= select_gtid_pos_table(hton); + gtid_pos_table_name= thd->make_clex_string(tmp_table_name->str, + tmp_table_name->length); + mysql_mutex_unlock(&LOCK_slave_state); + if (!gtid_pos_table_name) + { + /* Out of memory - we can try again later. */ + break; } - close_thread_tables(thd); - if (rgi) + + thd->lex->reset_n_backup_query_tables_list(&lex_backup); + tlist.init_one_table(&MYSQL_SCHEMA_NAME, gtid_pos_table_name, NULL, TL_WRITE); + if ((err= open_and_lock_tables(thd, &tlist, FALSE, 0))) + goto end; + table_opened= true; + table= tlist.table; + + if ((err= gtid_check_rpl_slave_state_table(table))) + goto end; + + direct_pos= table->file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION; + bitmap_set_all(table->write_set); + table->rpl_write_set= table->write_set; + + /* Now delete any already committed GTIDs. */ + bitmap_set_bit(table->read_set, table->field[0]->field_index); + bitmap_set_bit(table->read_set, table->field[1]->field_index); + + if (!direct_pos && (err= table->file->ha_index_init(0, 0))) { - thd->mdl_context.release_statement_locks(); - /* - Save the list of old gtid entries we deleted. If this transaction - fails later for some reason and is rolled back, the deletion of those - entries will be rolled back as well, and we will need to put them back - on the to-be-deleted list so we can re-do the deletion. Otherwise - redundant rows in mysql.gtid_slave_pos may accumulate if transactions - are rolled back and retried after record_gtid(). - */ -#ifdef HAVE_REPLICATION - rgi->pending_gtid_deletes_save(gtid->domain_id, delete_list); -#endif + table->file->print_error(err, MYF(0)); + goto end; } - else + + cur = *list_ptr; + cur_ptr_ptr = list_ptr; + do { - thd->mdl_context.release_transactional_locks(); -#ifdef HAVE_REPLICATION - rpl_group_info::pending_gtid_deletes_free(delete_list); -#endif + uchar key_buffer[4+8]; + list_element *next= cur->next; + + if (cur->hton == hton) + { + int res; + + table->field[0]->store((ulonglong)cur->domain_id, true); + table->field[1]->store(cur->sub_id, true); + if (direct_pos) + { + res= table->file->ha_rnd_pos_by_record(table->record[0]); + } + else + { + key_copy(key_buffer, table->record[0], &table->key_info[0], 0, false); + res= table->file->ha_index_read_map(table->record[0], key_buffer, + HA_WHOLE_KEY, HA_READ_KEY_EXACT); + } + DBUG_EXECUTE_IF("gtid_slave_pos_simulate_failed_delete", + { res= 1; + err= ENOENT; + sql_print_error("<DEBUG> Error deleting old GTID row"); + }); + if (res) + /* We cannot find the row, assume it is already deleted. */ + ; + else if ((err= table->file->ha_delete_row(table->record[0]))) + { + sql_print_error("Error deleting old GTID row: %s", + thd->get_stmt_da()->message()); + /* + In case of error, we still discard the element from the list. We do + not want to endlessly error on the same element in case of table + corruption or such. + */ + } + *cur_ptr_ptr= next; + my_free(cur); + } + else + { + /* Leave this one in the list until we get to the table for its hton. */ + cur_ptr_ptr= &cur->next; + } + cur= next; + if (err) + break; + } while (cur); +end: + if (table_opened) + { + if (!direct_pos) + table->file->ha_index_end(); + + if (err || (err= ha_commit_trans(thd, FALSE))) + ha_rollback_trans(thd, FALSE); } + close_thread_tables(thd); + thd->mdl_context.release_transactional_locks(); + thd->lex->restore_backup_query_tables_list(&lex_backup); + + if (err) + break; } - thd->lex->restore_backup_query_tables_list(&lex_backup); thd->variables.option_bits= thd_saved_option; - thd->resume_subsequent_commits(suspended_wfc); - DBUG_EXECUTE_IF("inject_record_gtid_serverid_100_sleep", - { - if (gtid->server_id == 100) - my_sleep(500000); - }); - DBUG_RETURN(err); + +#ifdef WITH_WSREP + thd->wsrep_ignore_table= false; +#endif } @@ -1251,7 +1368,7 @@ rpl_slave_state::load(THD *thd, const char *state_from_master, size_t len, if (gtid_parser_helper(&state_from_master, end, >id) || !(sub_id= next_sub_id(gtid.domain_id)) || - record_gtid(thd, >id, sub_id, NULL, in_statement, &hton) || + record_gtid(thd, >id, sub_id, false, in_statement, &hton) || update(gtid.domain_id, gtid.server_id, sub_id, gtid.seq_no, hton, NULL)) return 1; if (state_from_master == end) diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h index 0fc92d5e33c..60d822f7b0d 100644 --- a/sql/rpl_gtid.h +++ b/sql/rpl_gtid.h @@ -118,8 +118,9 @@ struct rpl_slave_state { struct list_element *next; uint64 sub_id; - uint64 seq_no; + uint32 domain_id; uint32 server_id; + uint64 seq_no; /* hton of mysql.gtid_slave_pos* table used to record this GTID. Can be NULL if the gtid table failed to load (eg. missing @@ -191,6 +192,8 @@ struct rpl_slave_state /* Mapping from domain_id to its element. */ HASH hash; + /* GTIDs added since last purge of old mysql.gtid_slave_pos rows. */ + uint32 pending_gtid_count; /* Mutex protecting access to the state. */ mysql_mutex_t LOCK_slave_state; /* Auxiliary buffer to sort gtid list. */ @@ -233,7 +236,10 @@ struct rpl_slave_state int truncate_state_table(THD *thd); void select_gtid_pos_table(THD *thd, LEX_CSTRING *out_tablename); int record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, - rpl_group_info *rgi, bool in_statement, void **out_hton); + bool in_transaction, bool in_statement, void **out_hton); + list_element *gtid_grab_pending_delete_list(); + LEX_CSTRING *select_gtid_pos_table(void *hton); + void gtid_delete_pending(THD *thd, rpl_slave_state::list_element **list_ptr); uint64 next_sub_id(uint32 domain_id); int iterate(int (*cb)(rpl_gtid *, void *), void *data, rpl_gtid *extra_gtids, uint32 num_extra, @@ -245,7 +251,7 @@ struct rpl_slave_state bool is_empty(); element *get_element(uint32 domain_id); - int put_back_list(uint32 domain_id, list_element *list); + int put_back_list(list_element *list); void update_state_hash(uint64 sub_id, rpl_gtid *gtid, void *hton, rpl_group_info *rgi); diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 6f659aa12ad..897d4394525 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -1091,7 +1091,7 @@ bool Master_info_index::init_all_master_info() if ((index_file_nr= my_open(index_file_name, O_RDWR | O_CREAT | O_BINARY , - MYF(MY_WME | ME_NOREFRESH))) < 0 || + MYF(MY_WME | ME_ERROR_LOG))) < 0 || my_sync(index_file_nr, MYF(MY_WME)) || init_io_cache(&index_file, index_file_nr, IO_SIZE, READ_CACHE, @@ -1307,7 +1307,7 @@ Master_info *get_master_info(const LEX_CSTRING *connection_name, if (warning != Sql_condition::WARN_LEVEL_NOTE) my_error(WARN_NO_MASTER_INFO, MYF(warning == Sql_condition::WARN_LEVEL_WARN ? - ME_JUST_WARNING : 0), + ME_WARNING : 0), (int) connection_name->length, connection_name->str); mysql_mutex_unlock(&LOCK_active_mi); DBUG_RETURN(0); @@ -1377,7 +1377,7 @@ Master_info_index::get_master_info(const LEX_CSTRING *connection_name, if (!mi && warning != Sql_condition::WARN_LEVEL_NOTE) { my_error(WARN_NO_MASTER_INFO, - MYF(warning == Sql_condition::WARN_LEVEL_WARN ? ME_JUST_WARNING : + MYF(warning == Sql_condition::WARN_LEVEL_WARN ? ME_WARNING : 0), (int) connection_name->length, connection_name->str); diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index db579a63ce0..94c1f08e4e3 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -497,7 +497,9 @@ int prepare_record(TABLE *const table, const uint skip, const bool check) DBUG_RETURN(0); } /** - Fills @c table->record[0] with computed values of extra persistent column which are present on slave but not on master. + Fills @c table->record[0] with computed values of extra persistent column + which are present on slave but not on master. + @param table Table whose record[0] buffer is prepared. @param master_cols No of columns on master @returns 0 on success @@ -514,10 +516,8 @@ int fill_extra_persistent_columns(TABLE *table, int master_cols) vfield= *vfield_ptr; if (vfield->field_index >= master_cols && vfield->stored_in_db()) { - /*Set bitmap for writing*/ - bitmap_set_bit(table->vcol_set, vfield->field_index); + bitmap_set_bit(table->write_set, vfield->field_index); error= vfield->vcol_info->expr->save_in_field(vfield,0); - bitmap_clear_bit(table->vcol_set, vfield->field_index); } } return error; diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index b275ad884bd..2d91620c898 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1820,6 +1820,7 @@ rpl_load_gtid_slave_state(THD *thd) int err= 0; uint32 i; load_gtid_state_cb_data cb_data; + rpl_slave_state::list_element *old_gtids_list; DBUG_ENTER("rpl_load_gtid_slave_state"); mysql_mutex_lock(&rpl_global_gtid_slave_state->LOCK_slave_state); @@ -1905,6 +1906,13 @@ rpl_load_gtid_slave_state(THD *thd) rpl_global_gtid_slave_state->loaded= true; mysql_mutex_unlock(&rpl_global_gtid_slave_state->LOCK_slave_state); + /* Clear out no longer needed elements now. */ + old_gtids_list= + rpl_global_gtid_slave_state->gtid_grab_pending_delete_list(); + rpl_global_gtid_slave_state->gtid_delete_pending(thd, &old_gtids_list); + if (old_gtids_list) + rpl_global_gtid_slave_state->put_back_list(old_gtids_list); + end: if (array_inited) delete_dynamic(&array); @@ -2086,7 +2094,6 @@ rpl_group_info::reinit(Relay_log_info *rli) long_find_row_note_printed= false; did_mark_start_commit= false; gtid_ev_flags2= 0; - pending_gtid_delete_list= NULL; last_master_timestamp = 0; gtid_ignore_duplicate_state= GTID_DUPLICATE_NULL; speculation= SPECULATE_NO; @@ -2217,12 +2224,6 @@ void rpl_group_info::cleanup_context(THD *thd, bool error) erroneously update the GTID position. */ gtid_pending= false; - - /* - Rollback will have undone any deletions of old rows we might have made - in mysql.gtid_slave_pos. Put those rows back on the list to be deleted. - */ - pending_gtid_deletes_put_back(); } m_table_map.clear_tables(); slave_close_thread_tables(thd); @@ -2448,78 +2449,6 @@ rpl_group_info::unmark_start_commit() } -/* - When record_gtid() has deleted any old rows from the table - mysql.gtid_slave_pos as part of a replicated transaction, save the list of - rows deleted here. - - If later the transaction fails (eg. optimistic parallel replication), the - deletes will be undone when the transaction is rolled back. Then we can - put back the list of rows into the rpl_global_gtid_slave_state, so that - we can re-do the deletes and avoid accumulating old rows in the table. -*/ -void -rpl_group_info::pending_gtid_deletes_save(uint32 domain_id, - rpl_slave_state::list_element *list) -{ - /* - We should never get to a state where we try to save a new pending list of - gtid deletes while we still have an old one. But make sure we handle it - anyway just in case, so we avoid leaving stray entries in the - mysql.gtid_slave_pos table. - */ - DBUG_ASSERT(!pending_gtid_delete_list); - if (unlikely(pending_gtid_delete_list)) - pending_gtid_deletes_put_back(); - - pending_gtid_delete_list= list; - pending_gtid_delete_list_domain= domain_id; -} - - -/* - Take the list recorded by pending_gtid_deletes_save() and put it back into - rpl_global_gtid_slave_state. This is needed if deletion of the rows was - rolled back due to transaction failure. -*/ -void -rpl_group_info::pending_gtid_deletes_put_back() -{ - if (pending_gtid_delete_list) - { - rpl_global_gtid_slave_state->put_back_list(pending_gtid_delete_list_domain, - pending_gtid_delete_list); - pending_gtid_delete_list= NULL; - } -} - - -/* - Free the list recorded by pending_gtid_deletes_save(). Done when the deletes - in the list have been permanently committed. -*/ -void -rpl_group_info::pending_gtid_deletes_clear() -{ - pending_gtid_deletes_free(pending_gtid_delete_list); - pending_gtid_delete_list= NULL; -} - - -void -rpl_group_info::pending_gtid_deletes_free(rpl_slave_state::list_element *list) -{ - rpl_slave_state::list_element *next; - - while (list) - { - next= list->next; - my_free(list); - list= next; - } -} - - rpl_sql_thread_info::rpl_sql_thread_info(Rpl_filter *filter) : rpl_filter(filter) { diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index d9f0e0e5d3b..b8b153c34be 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -757,11 +757,6 @@ struct rpl_group_info /* Needs room for "Gtid D-S-N\x00". */ char gtid_info_buf[5+10+1+10+1+20+1]; - /* List of not yet committed deletions in mysql.gtid_slave_pos. */ - rpl_slave_state::list_element *pending_gtid_delete_list; - /* Domain associated with pending_gtid_delete_list. */ - uint32 pending_gtid_delete_list_domain; - /* The timestamp, from the master, of the commit event. Used to do delayed update of rli->last_master_timestamp, for getting @@ -903,12 +898,6 @@ struct rpl_group_info char *gtid_info(); void unmark_start_commit(); - static void pending_gtid_deletes_free(rpl_slave_state::list_element *list); - void pending_gtid_deletes_save(uint32 domain_id, - rpl_slave_state::list_element *list); - void pending_gtid_deletes_put_back(); - void pending_gtid_deletes_clear(); - longlong get_row_stmt_start_timestamp() { return row_stmt_start_timestamp; diff --git a/sql/set_var.cc b/sql/set_var.cc index 8ab892068b3..de9bda3d067 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -742,7 +742,7 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free) err: if (free) - free_underlaid_joins(thd, &thd->lex->select_lex); + free_underlaid_joins(thd, thd->lex->first_select_lex()); DBUG_RETURN(error); } diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 9112795b754..daf010d8e8a 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6570,7 +6570,7 @@ ER_ACCESS_DENIED_NO_PASSWORD_ERROR 28000 ukr "ДоÑтуп заборонено Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувача: '%s'@'%s'" ER_SET_PASSWORD_AUTH_PLUGIN - eng "SET PASSWORD has no significance for users authenticating via plugins" + eng "SET PASSWORD is ignored for users authenticating via %s plugin" ER_GRANT_PLUGIN_USER_EXISTS eng "GRANT with IDENTIFIED WITH is illegal because the user %-.*s already exists" @@ -7921,3 +7921,13 @@ ER_KEY_DOESNT_SUPPORT eng "%s index %`s does not support this operation" ER_ALTER_OPERATION_TABLE_OPTIONS_NEED_REBUILD eng "Changing table options requires the table to be rebuilt" +ER_BACKUP_LOCK_IS_ACTIVE + eng "Can't execute the command as you have a BACKUP STAGE active" +ER_BACKUP_NOT_RUNNING + eng "You must start backup with \"BACKUP STAGE START\"" +ER_BACKUP_WRONG_STAGE + eng "Backup stage '%s' is same or before current backup stage '%s'" +ER_BACKUP_STAGE_FAILED + eng "Backup stage '%s' failed" +ER_BACKUP_UNKNOWN_STAGE + eng "Unknown backup stage: '%s'. Stage should be one of START, FLUSH, BLOCK_DDL, BLOCK_COMMIT or END" diff --git a/sql/slave.cc b/sql/slave.cc index 16fa890d86c..03b730b2b00 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -465,6 +465,8 @@ static struct slave_background_gtid_pos_create_t { void *hton; } *slave_background_gtid_pos_create_list; +static volatile bool slave_background_gtid_pending_delete_flag; + pthread_handler_t handle_slave_background(void *arg __attribute__((unused))) @@ -499,6 +501,7 @@ handle_slave_background(void *arg __attribute__((unused))) { slave_background_kill_t *kill_list; slave_background_gtid_pos_create_t *create_list; + bool pending_deletes; thd->ENTER_COND(&COND_slave_background, &LOCK_slave_background, &stage_slave_background_wait_request, @@ -508,13 +511,15 @@ handle_slave_background(void *arg __attribute__((unused))) stop= abort_loop || thd->killed || slave_background_thread_stop; kill_list= slave_background_kill_list; create_list= slave_background_gtid_pos_create_list; - if (stop || kill_list || create_list) + pending_deletes= slave_background_gtid_pending_delete_flag; + if (stop || kill_list || create_list || pending_deletes) break; mysql_cond_wait(&COND_slave_background, &LOCK_slave_background); } slave_background_kill_list= NULL; slave_background_gtid_pos_create_list= NULL; + slave_background_gtid_pending_delete_flag= false; thd->EXIT_COND(&old_stage); while (kill_list) @@ -541,6 +546,17 @@ handle_slave_background(void *arg __attribute__((unused))) create_list= next; } + if (pending_deletes) + { + rpl_slave_state::list_element *list; + + slave_background_gtid_pending_delete_flag= false; + list= rpl_global_gtid_slave_state->gtid_grab_pending_delete_list(); + rpl_global_gtid_slave_state->gtid_delete_pending(thd, &list); + if (list) + rpl_global_gtid_slave_state->put_back_list(list); + } + mysql_mutex_lock(&LOCK_slave_background); } while (!stop); @@ -615,6 +631,23 @@ slave_background_gtid_pos_create_request( /* + Request the slave background thread to delete no longer used rows from the + mysql.gtid_slave_pos* tables. + + This is called from time-critical rpl_slave_state::update(), so we avoid + taking any locks here. This means we may race with the background thread + to occasionally lose a signal. This is not a problem; any pending rows to + be deleted will just be deleted a bit later as part of the next batch. +*/ +void +slave_background_gtid_pending_delete_request(void) +{ + slave_background_gtid_pending_delete_flag= true; + mysql_cond_signal(&COND_slave_background); +} + + +/* Start the slave background thread. This thread is currently used for two purposes: @@ -7910,8 +7943,8 @@ bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report, { struct st_version_range_for_one_bug { uint bug_id; - const uchar introduced_in[3]; // first version with bug - const uchar fixed_in[3]; // first version with fix + Version introduced_in; // first version with bug + Version fixed_in; // first version with fix }; static struct st_version_range_for_one_bug versions_for_all_bugs[]= { @@ -7921,19 +7954,17 @@ bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report, {33029, { 5, 1, 0 }, { 5, 1, 12 } }, {37426, { 5, 1, 0 }, { 5, 1, 26 } }, }; - const uchar *master_ver= - rli->relay_log.description_event_for_exec->server_version_split.ver; - - DBUG_ASSERT(sizeof(rli->relay_log.description_event_for_exec->server_version_split.ver) == 3); + const Version &master_ver= + rli->relay_log.description_event_for_exec->server_version_split; for (uint i= 0; i < sizeof(versions_for_all_bugs)/sizeof(*versions_for_all_bugs);i++) { - const uchar *introduced_in= versions_for_all_bugs[i].introduced_in, - *fixed_in= versions_for_all_bugs[i].fixed_in; + const Version &introduced_in= versions_for_all_bugs[i].introduced_in; + const Version &fixed_in= versions_for_all_bugs[i].fixed_in; if ((versions_for_all_bugs[i].bug_id == bug_id) && - (memcmp(introduced_in, master_ver, 3) <= 0) && - (memcmp(fixed_in, master_ver, 3) > 0) && + introduced_in <= master_ver && + fixed_in > master_ver && (pred == NULL || (*pred)(param))) { if (!report) diff --git a/sql/slave.h b/sql/slave.h index 649d55b45b9..12d569b0333 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -276,6 +276,7 @@ bool net_request_file(NET* net, const char* fname); void slave_background_kill_request(THD *to_kill); void slave_background_gtid_pos_create_request (rpl_slave_state::gtid_pos_table *table_entry); +void slave_background_gtid_pending_delete_request(void); extern bool volatile abort_loop; extern Master_info *active_mi; /* active_mi for multi-master */ diff --git a/sql/sp.cc b/sql/sp.cc index af86737ebb9..6b38a0ddeb5 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -200,7 +200,8 @@ TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] = "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES'," "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER'," "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH'," - "'EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT')") }, + "'EMPTY_STRING_IS_NULL','SIMULTANEOUS_ASSIGNMENT'," + "'TIME_ROUND_FRACTIONAL')") }, { NULL, 0 } }, { @@ -1468,7 +1469,7 @@ log: log_query.ptr(), log_query.length(), FALSE, FALSE, FALSE, 0)) { - my_error(ER_ERROR_ON_WRITE, MYF(MY_WME), "binary log", -1); + my_error(ER_ERROR_ON_WRITE, MYF(0), "binary log", -1); goto done; } thd->variables.sql_mode= 0; @@ -1793,8 +1794,8 @@ bool lock_db_routines(THD *thd, const char *db) close_system_tables(thd, &open_tables_state_backup); /* We should already hold a global IX lock and a schema X lock. */ - DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "", - MDL_INTENTION_EXCLUSIVE) && + DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "", + MDL_BACKUP_DDL) && thd->mdl_context.is_lock_owner(MDL_key::SCHEMA, db, "", MDL_EXCLUSIVE)); DBUG_RETURN(thd->mdl_context.acquire_locks(&mdl_requests, @@ -522,12 +522,11 @@ inline const Sp_handler *Sp_handler::handler(MDL_key::enum_mdl_namespace type) return &sp_handler_procedure; case MDL_key::PACKAGE_BODY: return &sp_handler_package_body; - case MDL_key::GLOBAL: + case MDL_key::BACKUP: case MDL_key::SCHEMA: case MDL_key::TABLE: case MDL_key::TRIGGER: case MDL_key::EVENT: - case MDL_key::COMMIT: case MDL_key::USER_LOCK: case MDL_key::NAMESPACE_END: break; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 28411509adf..56b4fc8c948 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -71,33 +71,6 @@ static void reset_start_time_for_sp(THD *thd) } -Item::Type -sp_map_item_type(const Type_handler *handler) -{ - if (handler == &type_handler_row) - return Item::ROW_ITEM; - enum_field_types type= real_type_to_type(handler->real_field_type()); - - switch (type) { - case MYSQL_TYPE_BIT: - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_LONGLONG: - case MYSQL_TYPE_INT24: - return Item::INT_ITEM; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - return Item::DECIMAL_ITEM; - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - return Item::REAL_ITEM; - default: - return Item::STRING_ITEM; - } -} - - bool Item_splocal::append_for_log(THD *thd, String *str) { if (fix_fields_if_needed(thd, NULL)) @@ -318,7 +291,7 @@ sp_get_flags_for_command(LEX *lex) - EXPLAIN DELETE ... - ANALYZE DELETE ... */ - if (lex->select_lex.item_list.is_empty() && + if (lex->first_select_lex()->item_list.is_empty() && !lex->describe && !lex->analyze_stmt) flags= 0; else @@ -1922,7 +1895,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, for (arg_no= 0; arg_no < argcount; arg_no++) { /* Arguments must be fixed in Item_func_sp::fix_fields */ - DBUG_ASSERT(argp[arg_no]->fixed); + DBUG_ASSERT(argp[arg_no]->is_fixed()); if ((err_status= (*func_ctx)->set_parameter(thd, arg_no, &(argp[arg_no])))) goto err_with_cleanup; @@ -2292,6 +2265,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) if (!err_status) { err_status= execute(thd, TRUE); + DBUG_PRINT("info", ("execute returned %d", (int) err_status)); } if (save_log_general) @@ -4578,7 +4552,7 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) thd->spcont->set_case_expr(thd, m_case_expr_id, &null_item)) { /* If this also failed, we have to abort. */ - my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL)); } } else diff --git a/sql/sp_head.h b/sql/sp_head.h index cf934603cf0..8db6ecac9e7 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -39,9 +39,6 @@ @{ */ -Item::Type -sp_map_item_type(const Type_handler *handler); - uint sp_get_flags_for_command(LEX *lex); @@ -592,7 +589,8 @@ public: if (!oldlex) DBUG_RETURN(false); // Nothing to restore LEX *sublex= thd->lex; - if (thd->restore_from_local_lex_to_old_lex(oldlex))// This restores thd->lex + // This restores thd->lex and thd->stmt_lex + if (thd->restore_from_local_lex_to_old_lex(oldlex)) DBUG_RETURN(true); if (!sublex->sp_lex_in_use) { diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 3e77d8c357b..e71a529bc07 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -228,9 +228,10 @@ bool Qualified_column_ident::resolve_type_ref(THD *thd, Column_definition *def) // Make %TYPE variables see temporary tables that shadow permanent tables thd->temporary_tables= open_tables_state_backup.temporary_tables; - if ((table_list= lex.select_lex.add_table_to_list(thd, this, NULL, 0, - TL_READ_NO_INSERT, - MDL_SHARED_READ)) && + if ((table_list= + lex.first_select_lex()->add_table_to_list(thd, this, NULL, 0, + TL_READ_NO_INSERT, + MDL_SHARED_READ)) && !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) && !open_tables_only_view_structure(thd, table_list, thd->mdl_context.has_locks())) @@ -286,9 +287,10 @@ bool Table_ident::resolve_table_rowtype_ref(THD *thd, // Make %ROWTYPE variables see temporary tables that shadow permanent tables thd->temporary_tables= open_tables_state_backup.temporary_tables; - if ((table_list= lex.select_lex.add_table_to_list(thd, this, NULL, 0, - TL_READ_NO_INSERT, - MDL_SHARED_READ)) && + if ((table_list= + lex.first_select_lex()->add_table_to_list(thd, this, NULL, 0, + TL_READ_NO_INSERT, + MDL_SHARED_READ)) && !check_table_access(thd, SELECT_ACL, table_list, TRUE, UINT_MAX, FALSE) && !open_tables_only_view_structure(thd, table_list, thd->mdl_context.has_locks())) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 59ba324df31..85b54009219 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -57,7 +57,10 @@ #include "sql_plugin_compat.h" +#define MAX_SCRAMBLE_LENGTH 1024 + bool mysql_user_table_is_in_short_password_format= false; +bool using_global_priv_table= true; static LEX_CSTRING native_password_plugin_name= { STRING_WITH_LEN("mysql_native_password") @@ -85,11 +88,19 @@ LEX_CSTRING current_role= { STRING_WITH_LEN("*current_role") }; LEX_CSTRING current_user_and_current_role= { STRING_WITH_LEN("*current_user_and_current_role") }; -#ifndef NO_EMBEDDED_ACCESS_CHECKS static plugin_ref old_password_plugin; -#endif static plugin_ref native_password_plugin; +static plugin_ref get_auth_plugin(THD *thd, const LEX_CSTRING &name, bool *locked) +{ + if (name.str == native_password_plugin_name.str) + return native_password_plugin; + else if (name.str == old_password_plugin_name.str) + return old_password_plugin; + *locked=true; + return my_plugin_lock_by_name(thd, &name, MYSQL_AUTHENTICATION_PLUGIN); +} + /* Classes */ struct acl_host_and_ip @@ -119,13 +130,10 @@ public: char *db; }; -class ACL_USER_BASE :public ACL_ACCESS +class ACL_USER_BASE :public ACL_ACCESS, public Sql_alloc { public: - static void *operator new(size_t size, MEM_ROOT *mem_root) - { return (void*) alloc_root(mem_root, size); } - static void operator delete(void *, MEM_ROOT *){} uchar flags; // field used to store various state information LEX_CSTRING user; /* list to hold references to granted roles (ACL_ROLE instances) */ @@ -138,13 +146,12 @@ public: acl_host_and_ip host; size_t hostname_length; USER_RESOURCES user_resource; - uint8 salt[SCRAMBLE_LENGTH + 1]; // scrambled password in binary form - uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 4.0, 20 - 4.1.1 enum SSL_type ssl_type; const char *ssl_cipher, *x509_issuer, *x509_subject; LEX_CSTRING plugin; LEX_CSTRING auth_string; LEX_CSTRING default_rolename; + LEX_CSTRING salt; ACL_USER *copy(MEM_ROOT *root) { @@ -152,8 +159,7 @@ public: if (!dst) return 0; *dst= *this; - dst->user.str= safe_strdup_root(root, user.str); - dst->user.length= user.length; + dst->user= safe_lexcstrdup_root(root, user); dst->ssl_cipher= safe_strdup_root(root, ssl_cipher); dst->x509_issuer= safe_strdup_root(root, x509_issuer); dst->x509_subject= safe_strdup_root(root, x509_subject); @@ -161,11 +167,11 @@ public: plugin.str == old_password_plugin_name.str) dst->plugin= plugin; else - dst->plugin.str= strmake_root(root, plugin.str, plugin.length); - dst->auth_string.str= safe_strdup_root(root, auth_string.str); + dst->plugin= safe_lexcstrdup_root(root, plugin); + dst->auth_string= safe_lexcstrdup_root(root, auth_string); + dst->salt= safe_lexcstrdup_root(root, salt); dst->host.hostname= safe_strdup_root(root, host.hostname); - dst->default_rolename.str= safe_strdup_root(root, default_rolename.str); - dst->default_rolename.length= default_rolename.length; + dst->default_rolename= safe_lexcstrdup_root(root, default_rolename); bzero(&dst->role_grants, sizeof(role_grants)); return dst; } @@ -174,7 +180,7 @@ public: { CHARSET_INFO *cs= system_charset_info; int res; - res= strcmp(safe_str(user.str), safe_str(user2)); + res= strcmp(user.str, user2); if (!res) res= my_strcasecmp(cs, host.hostname, host2); return res; @@ -182,9 +188,11 @@ public: bool eq(const char *user2, const char *host2) { return !cmp(user2, host2); } + const char *get_username(){ return user.str; } + bool wild_eq(const char *user2, const char *host2, const char *ip2) { - if (strcmp(safe_str(user.str), safe_str(user2))) + if (strcmp(user.str, user2)) return false; return compare_hostname(&host, host2, ip2 ? ip2 : host2); @@ -223,6 +231,8 @@ public: acl_host_and_ip host; const char *user,*db; ulong initial_access; /* access bits present in the table */ + + const char *get_username() { return user; } }; #ifndef DBUG_OFF @@ -275,10 +285,9 @@ public: const char *proxied_host_arg, const char *proxied_user_arg, bool with_grant_arg) { - user= (user_arg && *user_arg) ? user_arg : NULL; + user= user_arg; update_hostname (&host, (host_arg && *host_arg) ? host_arg : NULL); - proxied_user= (proxied_user_arg && *proxied_user_arg) ? - proxied_user_arg : NULL; + proxied_user= proxied_user_arg; update_hostname (&proxied_host, (proxied_host_arg && *proxied_host_arg) ? proxied_host_arg : NULL); @@ -291,11 +300,10 @@ public: bool with_grant_arg) { init ((host_arg && *host_arg) ? strdup_root (mem, host_arg) : NULL, - (user_arg && *user_arg) ? strdup_root (mem, user_arg) : NULL, + strdup_root (mem, user_arg), (proxied_host_arg && *proxied_host_arg) ? strdup_root (mem, proxied_host_arg) : NULL, - (proxied_user_arg && *proxied_user_arg) ? - strdup_root (mem, proxied_user_arg) : NULL, + strdup_root (mem, proxied_user_arg), with_grant_arg); } @@ -308,7 +316,7 @@ public: const char *get_proxied_host() { return proxied_host.hostname; } void set_user(MEM_ROOT *mem, const char *user_arg) { - user= user_arg && *user_arg ? strdup_root(mem, user_arg) : NULL; + user= *user_arg ? strdup_root(mem, user_arg) : ""; } void set_host(MEM_ROOT *mem, const char *host_arg) { @@ -323,9 +331,8 @@ public: { sql_print_warning("'proxies_priv' entry '%s@%s %s@%s' " "ignored in --skip-name-resolve mode.", - safe_str(proxied_user), - safe_str(proxied_host.hostname), - safe_str(user), + proxied_user, + safe_str(proxied_host.hostname), user, safe_str(host.hostname)); return TRUE; } @@ -345,11 +352,10 @@ public: proxied_user_arg, proxied_user)); DBUG_RETURN(compare_hostname(&host, host_arg, ip_arg) && compare_hostname(&proxied_host, host_arg, ip_arg) && - (!user || + (!*user || (user_arg && !wild_compare(user_arg, user, TRUE))) && - (!proxied_user || - (proxied_user && !wild_compare(proxied_user_arg, - proxied_user, TRUE)))); + (!*proxied_user || + !wild_compare(proxied_user_arg, proxied_user, TRUE))); } @@ -381,8 +387,7 @@ public: bool granted_on(const char *host_arg, const char *user_arg) { - return (((!user && (!user_arg || !user_arg[0])) || - (user && user_arg && !strcmp(user, user_arg))) && + return (!strcmp(user, user_arg) && ((!host.hostname && (!host_arg || !host_arg[0])) || (host.hostname && host_arg && !strcmp(host.hostname, host_arg)))); } @@ -391,17 +396,15 @@ public: void print_grant(String *str) { str->append(STRING_WITH_LEN("GRANT PROXY ON '")); - if (proxied_user) - str->append(proxied_user, strlen(proxied_user)); + str->append(proxied_user); str->append(STRING_WITH_LEN("'@'")); if (proxied_host.hostname) str->append(proxied_host.hostname, strlen(proxied_host.hostname)); str->append(STRING_WITH_LEN("' TO '")); - if (user) - str->append(user, strlen(user)); + str->append(user); str->append(STRING_WITH_LEN("'@'")); if (host.hostname) - str->append(host.hostname, strlen(host.hostname)); + str->append(host.hostname); str->append(STRING_WITH_LEN("'")); if (with_grant) str->append(STRING_WITH_LEN(" WITH GRANT OPTION")); @@ -614,7 +617,11 @@ static DYNAMIC_ARRAY acl_wild_hosts; static Hash_filo<acl_entry> *acl_cache; static uint grant_version=0; /* Version of priv tables. incremented by acl_load */ static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0); -static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b); +static int acl_compare(const ACL_ACCESS *a, const ACL_ACCESS *b); +static int acl_user_compare(const ACL_USER *a, const ACL_USER *b); +static void rebuild_acl_users(); +static int acl_db_compare(const ACL_DB *a, const ACL_DB *b); +static void rebuild_acl_dbs(); static ulong get_sort(uint count,...); static void init_check_host(void); static void rebuild_check_host(void); @@ -624,8 +631,8 @@ static ACL_USER *find_user_wild(const char *host, const char *user, const char * static ACL_ROLE *find_acl_role(const char *user); static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_CSTRING *u, const LEX_CSTRING *h, const LEX_CSTRING *r); static ACL_USER_BASE *find_acl_user_base(const char *user, const char *host); -static bool update_user_table(THD *, const User_table &, const char *, const char *, const - char *, size_t new_password_len); +static bool update_user_table_password(THD *, const User_table&, + const ACL_USER &); static bool acl_load(THD *thd, const Grant_tables& grant_tables); static inline void get_grantor(THD *thd, char* grantor); static bool add_role_user_mapping(const char *uname, const char *hname, const char *rname); @@ -670,7 +677,6 @@ HASH *Sp_handler_package_body::get_priv_hash() const */ enum enum_acl_tables { - USER_TABLE, DB_TABLE, TABLES_PRIV_TABLE, COLUMNS_PRIV_TABLE, @@ -679,7 +685,7 @@ enum enum_acl_tables PROCS_PRIV_TABLE, PROXIES_PRIV_TABLE, ROLES_MAPPING_TABLE, - TABLES_MAX // <== always the last + USER_TABLE // <== always the last }; // bits for open_grant_tables static const int Table_user= 1 << USER_TABLE; @@ -691,6 +697,31 @@ static const int Table_procs_priv= 1 << PROCS_PRIV_TABLE; static const int Table_proxies_priv= 1 << PROXIES_PRIV_TABLE; static const int Table_roles_mapping= 1 << ROLES_MAPPING_TABLE; +static LEX_CSTRING MYSQL_TABLE_NAME[USER_TABLE+1]= { + {STRING_WITH_LEN("db")}, + {STRING_WITH_LEN("tables_priv")}, + {STRING_WITH_LEN("columns_priv")}, + {STRING_WITH_LEN("host")}, + {STRING_WITH_LEN("procs_priv")}, + {STRING_WITH_LEN("proxies_priv")}, + {STRING_WITH_LEN("roles_mapping")}, + {STRING_WITH_LEN("global_priv")} +}; +static LEX_CSTRING MYSQL_TABLE_NAME_USER={STRING_WITH_LEN("user")}; + +/** + Choose from either native or old password plugins when assigning a password +*/ + +static LEX_CSTRING &guess_auth_plugin(THD *thd, size_t password_len) +{ + if (thd->variables.old_passwords == 1 || + password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323) + return old_password_plugin_name; + else + return native_password_plugin_name; +} + /** Base class representing a generic grant table from the mysql database. @@ -705,105 +736,43 @@ class Grant_table_base { public: /* Number of fields for this Grant Table. */ - uint num_fields() const { return tl.table->s->fields; } + uint num_fields() const { return m_table->s->fields; } /* Check if the table exists after an attempt to open it was made. Some tables, such as the host table in MySQL 5.6.7+ are missing. */ - bool table_exists() const { return tl.table; }; + bool table_exists() const { return m_table; }; /* Initializes the READ_RECORD structure provided as a parameter to read through the whole table, with all columns available. Cleaning up is the caller's job. */ - bool init_read_record(READ_RECORD* info, THD* thd) const + bool init_read_record(READ_RECORD* info) const { - DBUG_ASSERT(tl.table); - bool result= ::init_read_record(info, thd, tl.table, NULL, NULL, 1, - true, false); + DBUG_ASSERT(m_table); + bool result= ::init_read_record(info, m_table->in_use, m_table, + NULL, NULL, 1, true, false); if (!result) - tl.table->use_all_columns(); + m_table->use_all_columns(); return result; } - /* Return the number of privilege columns for this table. */ - uint num_privileges() const { return num_privilege_cols; } - /* Return a privilege column by index. */ - Field* priv_field(uint privilege_idx) const - { - DBUG_ASSERT(privilege_idx < num_privileges()); - return tl.table->field[start_privilege_column + privilege_idx]; - } - - /* Fetch the privileges from the table as a set of bits. The first column - is represented by the first bit in the result, the second column by the - second bit, etc. */ - ulong get_access() const - { - return get_access(start_privilege_column, - start_privilege_column + num_privileges() - 1); - } - /* Return the underlying TABLE handle. */ - TABLE* table() const - { - return tl.table; - } + TABLE* table() const { return m_table; } - /** Check if the table was opened, issue an error otherwise. */ - int no_such_table() const - { - if (table_exists()) - return 0; - - my_error(ER_NO_SUCH_TABLE, MYF(0), tl.db.str, tl.alias.str); - return 1; - } - - - protected: - friend class Grant_tables; - - Grant_table_base() : start_privilege_column(0), num_privilege_cols(0) - { - bzero(&tl, sizeof(tl)); - }; - - /* Initialization sequence common for all grant tables. This should be called - after all table-specific initialization is performed. */ - void init(enum thr_lock_type lock_type, bool is_optional) - { - tl.open_type= OT_BASE_ONLY; - if (lock_type >= TL_WRITE_ALLOW_WRITE) - tl.updating= 1; - if (is_optional) - tl.open_strategy= TABLE_LIST::OPEN_IF_EXISTS; - } - - /* - Get all access bits from table between start_field and end_field indices. - - IMPLEMENTATION - The record should be already read in table->record[0]. All privileges - are specified as an ENUM(Y,N). - - SYNOPSIS - get_access() - start_field_idx The field index at which the first privilege - specification begins. - end_field_idx The field index at which the last privilege - specification is located. - - RETURN VALUE - privilege mask - */ - ulong get_access(uint start_field_idx, uint end_field_idx) const + ulong get_access() const { ulong access_bits= 0, bit= 1; - for (uint i = start_field_idx; i <= end_field_idx; i++, bit<<=1) + for (uint i = start_priv_columns; i < end_priv_columns; i++, bit<<=1) { - if (get_YN_as_bool(tl.table->field[i])) + if (get_YN_as_bool(m_table->field[i])) access_bits|= bit; } return access_bits; } + protected: + friend class Grant_tables; + + Grant_table_base() : start_priv_columns(0), end_priv_columns(0), m_table(0) + { } + /* Compute how many privilege columns this table has. This method can only be called after the table has been opened. @@ -811,115 +780,332 @@ class Grant_table_base A privilege column is of type enum('Y', 'N'). Privilege columns are expected to be one after another. */ - void compute_num_privilege_cols() + void set_table(TABLE *table) { - if (!table_exists()) // Table does not exist or not opened. + if (!(m_table= table)) // Table does not exist or not opened. return; - num_privilege_cols= 0; - for (uint i= 0; i < num_fields(); i++) + for (end_priv_columns= 0; end_priv_columns < num_fields(); end_priv_columns++) { - Field *field= tl.table->field[i]; - if (num_privilege_cols > 0 && field->real_type() != MYSQL_TYPE_ENUM) - return; + Field *field= m_table->field[end_priv_columns]; if (field->real_type() == MYSQL_TYPE_ENUM && static_cast<Field_enum*>(field)->typelib->count == 2) { - num_privilege_cols++; - if (num_privilege_cols == 1) - start_privilege_column= i; + if (!start_priv_columns) + start_priv_columns= end_priv_columns; } + else if (start_priv_columns) + break; } } /* The index at which privilege columns start. */ - uint start_privilege_column; - /* The number of privilege columns in the table. */ - uint num_privilege_cols; + uint start_priv_columns; + /* The index after the last privilege column */ + uint end_priv_columns; - TABLE_LIST tl; + TABLE *m_table; }; class User_table: public Grant_table_base { public: - /* Field getters return NULL if the column is not present in the table. - This is consistent only if the table is in a supported version. We do - not guard against corrupt tables. (yet) */ - Field* host() const - { return get_field(0); } - Field* user() const - { return get_field(1); } - Field* password() const - { return have_password() ? NULL : tl.table->field[2]; } - /* Columns after privilege columns. */ - Field* ssl_type() const - { return get_field(start_privilege_column + num_privileges()); } - Field* ssl_cipher() const - { return get_field(start_privilege_column + num_privileges() + 1); } - Field* x509_issuer() const - { return get_field(start_privilege_column + num_privileges() + 2); } - Field* x509_subject() const - { return get_field(start_privilege_column + num_privileges() + 3); } - Field* max_questions() const - { return get_field(start_privilege_column + num_privileges() + 4); } - Field* max_updates() const - { return get_field(start_privilege_column + num_privileges() + 5); } - Field* max_connections() const - { return get_field(start_privilege_column + num_privileges() + 6); } - Field* max_user_connections() const - { return get_field(start_privilege_column + num_privileges() + 7); } - Field* plugin() const - { return get_field(start_privilege_column + num_privileges() + 8); } - Field* authentication_string() const - { return get_field(start_privilege_column + num_privileges() + 9); } - Field* password_expired() const - { return get_field(start_privilege_column + num_privileges() + 10); } - Field* is_role() const - { return get_field(start_privilege_column + num_privileges() + 11); } - Field* default_role() const - { return get_field(start_privilege_column + num_privileges() + 12); } - Field* max_statement_time() const - { return get_field(start_privilege_column + num_privileges() + 13); } + bool init_read_record(READ_RECORD* info) const + { + return Grant_table_base::init_read_record(info) || setup_sysvars(); + } + + virtual LEX_CSTRING& name() const = 0; + virtual int get_auth(THD *, MEM_ROOT *, const char **, const char **) const= 0; + virtual void set_auth(const char *, size_t, const char *, size_t) const = 0; + virtual ulong get_access() const = 0; + virtual void set_access(ulong rights, bool revoke) const = 0; + + char *get_host(MEM_ROOT *root) const + { return ::get_field(root, m_table->field[0]); } + int set_host(const char *s, size_t l) const + { return m_table->field[0]->store(s, l, system_charset_info); }; + char *get_user(MEM_ROOT *root) const + { return ::get_field(root, m_table->field[1]); } + int set_user(const char *s, size_t l) const + { return m_table->field[1]->store(s, l, system_charset_info); }; + + virtual SSL_type get_ssl_type () const = 0; + virtual int set_ssl_type (SSL_type x) const = 0; + virtual const char* get_ssl_cipher (MEM_ROOT *root) const = 0; + virtual int set_ssl_cipher (const char *s, size_t l) const = 0; + virtual const char* get_x509_issuer (MEM_ROOT *root) const = 0; + virtual int set_x509_issuer (const char *s, size_t l) const = 0; + virtual const char* get_x509_subject (MEM_ROOT *root) const = 0; + virtual int set_x509_subject (const char *s, size_t l) const = 0; + virtual longlong get_max_questions () const = 0; + virtual int set_max_questions (longlong x) const = 0; + virtual longlong get_max_updates () const = 0; + virtual int set_max_updates (longlong x) const = 0; + virtual longlong get_max_connections () const = 0; + virtual int set_max_connections (longlong x) const = 0; + virtual longlong get_max_user_connections () const = 0; + virtual int set_max_user_connections (longlong x) const = 0; + virtual double get_max_statement_time () const = 0; + virtual int set_max_statement_time (double x) const = 0; + virtual bool get_is_role () const = 0; + virtual int set_is_role (bool x) const = 0; + virtual const char* get_default_role (MEM_ROOT *root) const = 0; + virtual int set_default_role (const char *s, size_t l) const = 0; + + virtual ~User_table() {} + private: + friend class Grant_tables; + virtual int setup_sysvars() const = 0; +}; - /* - Check if a user entry in the user table is marked as being a role entry +/* MySQL-3.23 to MariaDB 10.3 `user` table */ +class User_table_tabular: public User_table +{ + public: - IMPLEMENTATION - Access the coresponding column and check the coresponding ENUM of the form - ENUM('N', 'Y') + LEX_CSTRING& name() const { return MYSQL_TABLE_NAME_USER; } - SYNOPSIS - check_is_role() - form an open table to read the entry from. - The record should be already read in table->record[0] + int get_auth(THD *thd, MEM_ROOT *root, const char **plugin, const char **authstr) const + { + if (have_password()) + { + *authstr= safe_str(::get_field(&acl_memroot, password())); + *plugin= guess_auth_plugin(thd, strlen(*authstr)).str; + } + else + { + *plugin= native_password_plugin_name.str; + *authstr= ""; + } + if (this->plugin() && this->authstr()) + { + char *tmpstr= ::get_field(&acl_memroot, this->plugin()); + if (tmpstr) + { + const char *passw= *authstr; + *plugin= tmpstr; + *authstr= safe_str(::get_field(&acl_memroot, this->authstr())); - RETURN VALUE - TRUE if the user is marked as a role - FALSE otherwise - */ - bool check_is_role() const + if (*passw) + { + if (**authstr && strcmp(*authstr, passw)) + { + sql_print_warning("'user' entry '%s@%s' has both a password and an " + "authentication plugin specified. The password will be ignored.", + safe_str(get_user(thd->mem_root)), safe_str(get_host(thd->mem_root))); + } + else + *authstr= passw; + } + } + } + return 0; + } + + void set_auth(const char *p, size_t pl, const char *as, size_t asl) const { - /* Table version does not support roles */ - if (!is_role()) - return false; + if (plugin()) + { + if (have_password()) + password()->reset(); + plugin()->store(p, pl, system_charset_info); + authstr()->store(as, asl, system_charset_info); + } + else + password()->store(as, asl, system_charset_info); + } + + ulong get_access() const + { + ulong access= Grant_table_base::get_access(); + if ((num_fields() <= 13) && (access & CREATE_ACL)) + access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL; + + if (num_fields() <= 18) + { + access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL; + if (access & FILE_ACL) + access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL; + if (access & PROCESS_ACL) + access|= SUPER_ACL | EXECUTE_ACL; + } - return get_YN_as_bool(is_role()); + if (num_fields() <= 31 && (access & CREATE_ACL)) + access|= (CREATE_VIEW_ACL | SHOW_VIEW_ACL); + + if (num_fields() <= 33) + { + if (access & CREATE_ACL) + access|= CREATE_PROC_ACL; + if (access & ALTER_ACL) + access|= ALTER_PROC_ACL; + } + + if (num_fields() <= 36 && (access & GRANT_ACL)) + access|= CREATE_USER_ACL; + + if (num_fields() <= 37 && (access & SUPER_ACL)) + access|= EVENT_ACL; + + if (num_fields() <= 38 && (access & SUPER_ACL)) + access|= TRIGGER_ACL; + + if (num_fields() <= 46 && (access & DELETE_ACL)) + access|= DELETE_HISTORY_ACL; + + return access & GLOBAL_ACLS; } + void set_access(ulong rights, bool revoke) const + { + ulong priv= SELECT_ACL; + for (uint i= start_priv_columns; i < end_priv_columns; i++, priv <<= 1) + { + if (priv & rights) + m_table->field[i]->store(1 + !revoke, 0); + } + } + SSL_type get_ssl_type () const + { + Field *f= get_field(end_priv_columns, MYSQL_TYPE_ENUM); + return (SSL_type)(f ? f->val_int()-1 : 0); + } + int set_ssl_type (SSL_type x) const + { + if (Field *f= get_field(end_priv_columns, MYSQL_TYPE_ENUM)) + return f->store(x+1, 0); + else + return 1; + } + const char* get_ssl_cipher (MEM_ROOT *root) const + { + Field *f= get_field(end_priv_columns + 1, MYSQL_TYPE_BLOB); + return f ? ::get_field(root,f) : 0; + } + int set_ssl_cipher (const char *s, size_t l) const + { + if (Field *f= get_field(end_priv_columns + 1, MYSQL_TYPE_BLOB)) + return f->store(s, l, &my_charset_latin1); + else + return 1; + } + const char* get_x509_issuer (MEM_ROOT *root) const + { + Field *f= get_field(end_priv_columns + 2, MYSQL_TYPE_BLOB); + return f ? ::get_field(root,f) : 0; + } + int set_x509_issuer (const char *s, size_t l) const + { + if (Field *f= get_field(end_priv_columns + 2, MYSQL_TYPE_BLOB)) + return f->store(s, l, &my_charset_latin1); + else + return 1; + } + const char* get_x509_subject (MEM_ROOT *root) const + { + Field *f= get_field(end_priv_columns + 3, MYSQL_TYPE_BLOB); + return f ? ::get_field(root,f) : 0; + } + int set_x509_subject (const char *s, size_t l) const + { + if (Field *f= get_field(end_priv_columns + 3, MYSQL_TYPE_BLOB)) + return f->store(s, l, &my_charset_latin1); + else + return 1; + } + longlong get_max_questions () const + { + Field *f= get_field(end_priv_columns + 4, MYSQL_TYPE_LONG); + return f ? f->val_int() : 0; + } + int set_max_questions (longlong x) const + { + if (Field *f= get_field(end_priv_columns + 4, MYSQL_TYPE_LONG)) + return f->store(x, 0); + else + return 1; + } + longlong get_max_updates () const + { + Field *f= get_field(end_priv_columns + 5, MYSQL_TYPE_LONG); + return f ? f->val_int() : 0; + } + int set_max_updates (longlong x) const + { + if (Field *f= get_field(end_priv_columns + 5, MYSQL_TYPE_LONG)) + return f->store(x, 0); + else + return 1; + } + longlong get_max_connections () const + { + Field *f= get_field(end_priv_columns + 6, MYSQL_TYPE_LONG); + return f ? f->val_int() : 0; + } + int set_max_connections (longlong x) const + { + if (Field *f= get_field(end_priv_columns + 6, MYSQL_TYPE_LONG)) + return f->store(x, 0); + else + return 1; + } + longlong get_max_user_connections () const + { + Field *f= get_field(end_priv_columns + 7, MYSQL_TYPE_LONG); + return f ? f->val_int() : 0; + } + int set_max_user_connections (longlong x) const + { + if (Field *f= get_field(end_priv_columns + 7, MYSQL_TYPE_LONG)) + return f->store(x, 0); + else + return 1; + } + double get_max_statement_time () const + { + Field *f= get_field(end_priv_columns + 13, MYSQL_TYPE_NEWDECIMAL); + return f ? f->val_real() : 0; + } + int set_max_statement_time (double x) const + { + if (Field *f= get_field(end_priv_columns + 13, MYSQL_TYPE_NEWDECIMAL)) + return f->store(x); + else + return 1; + } + bool get_is_role () const + { + Field *f= get_field(end_priv_columns + 11, MYSQL_TYPE_ENUM); + return f ? f->val_int()-1 : 0; + } + int set_is_role (bool x) const + { + if (Field *f= get_field(end_priv_columns + 11, MYSQL_TYPE_ENUM)) + return f->store(x+1, 0); + else + return 1; + } + const char* get_default_role (MEM_ROOT *root) const + { + Field *f= get_field(end_priv_columns + 12, MYSQL_TYPE_STRING); + return f ? ::get_field(root,f) : 0; + } + int set_default_role (const char *s, size_t l) const + { + if (Field *f= get_field(end_priv_columns + 12, MYSQL_TYPE_STRING)) + return f->store(s, l, system_charset_info); + else + return 1; + }; + + virtual ~User_table_tabular() {} private: friend class Grant_tables; /* Only Grant_tables can instantiate this class. */ - User_table() {}; - - void init(enum thr_lock_type lock_type) - { - /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_USER_NAME, NULL, lock_type); - Grant_table_base::init(lock_type, false); - } + User_table_tabular() {} /* The user table is a bit different compared to the other Grant tables. Usually, we only add columns to the grant tables when adding functionality. @@ -931,183 +1117,400 @@ class User_table: public Grant_table_base doesn't exist. This simplifies checking of table "version", as we don't have to make use of num_fields() any more. */ - inline Field* get_field(uint field_num) const + inline Field* get_field(uint field_num, enum enum_field_types type) const { if (field_num >= num_fields()) return NULL; + Field *f= m_table->field[field_num]; + return f->real_type() == type ? f : NULL; + } - return tl.table->field[field_num]; + int setup_sysvars() const + { + username_char_length= MY_MIN(m_table->field[1]->char_length(), + USERNAME_CHAR_LENGTH); + using_global_priv_table= false; + + if (have_password()) // Password column might be missing. (MySQL 5.7.6+) + { + int password_length= password()->field_length / + password()->charset()->mbmaxlen; + if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323) + { + sql_print_error("Fatal error: mysql.user table is damaged or in " + "unsupported 3.20 format."); + return 1; + } + + mysql_mutex_lock(&LOCK_global_system_variables); + if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH) + { + if (opt_secure_auth) + { + mysql_mutex_unlock(&LOCK_global_system_variables); + sql_print_error("Fatal error: mysql.user table is in old format, " + "but server started with --secure-auth option."); + return 1; + } + mysql_user_table_is_in_short_password_format= true; + if (global_system_variables.old_passwords) + mysql_mutex_unlock(&LOCK_global_system_variables); + else + { + extern sys_var *Sys_old_passwords_ptr; + Sys_old_passwords_ptr->value_origin= sys_var::AUTO; + global_system_variables.old_passwords= 1; + mysql_mutex_unlock(&LOCK_global_system_variables); + sql_print_warning("mysql.user table is not updated to new password format; " + "Disabling new password usage until " + "mysql_fix_privilege_tables is run"); + } + m_table->in_use->variables.old_passwords= 1; + } + else + { + mysql_user_table_is_in_short_password_format= false; + mysql_mutex_unlock(&LOCK_global_system_variables); + } + } + return 0; } /* Normally password column is the third column in the table. If privileges start on the third column instead, we are missing the password column. This means we are using a MySQL 5.7.6+ data directory. */ - bool have_password() const { return start_privilege_column == 2; } + bool have_password() const { return start_priv_columns == 3; } + + Field* password() const { return m_table->field[2]; } + Field* plugin() const { return get_field(end_priv_columns + 8, MYSQL_TYPE_STRING); } + Field* authstr() const { return get_field(end_priv_columns + 9, MYSQL_TYPE_BLOB); } +}; +/* + MariaDB 10.4 and up `global_priv` table + + TODO possible optimizations: + * update json in-place if the new value can fit + * don't repeat get_value for every key, but use a streaming parser + to convert json into in-memory object (ACL_USER?) in one json scan. + - this makes sense for acl_load(), but hardly for GRANT + * similarly, pack ACL_USER (?) into json in one go. + - doesn't make sense? GRANT rarely updates more than one field. +*/ +class User_table_json: public User_table +{ + LEX_CSTRING& name() const { return MYSQL_TABLE_NAME[USER_TABLE]; } + + int get_auth(THD *thd, MEM_ROOT *root, const char **plugin, const char **authstr) const + { + *plugin= get_str_value(root, STRING_WITH_LEN("plugin")); + if (!**plugin) + *plugin= native_password_plugin_name.str; + *authstr= get_str_value(root, STRING_WITH_LEN("authentication_string")); + return *plugin == NULL || *authstr == NULL; + } + void set_auth(const char *p, size_t pl, const char *as, size_t asl) const + { + set_str_value(STRING_WITH_LEN("plugin"), p, pl); + set_str_value(STRING_WITH_LEN("authentication_string"), as, asl); + } + ulong get_access() const + { + /* + when new privileges will be added, we'll start storing GLOBAL_ACLS + (or, for example, my_count_bits(GLOBAL_ACLS)) + in the json too, and it'll allow us to do privilege upgrades + */ + return get_int_value(STRING_WITH_LEN("access")) & GLOBAL_ACLS; + } + void set_access(ulong rights, bool revoke) const + { + ulong access= get_access(); + if (revoke) + access&= ~rights; + else + access|= rights; + set_int_value(STRING_WITH_LEN("access"), access & GLOBAL_ACLS); + } + + SSL_type get_ssl_type () const + { return (SSL_type)get_int_value(STRING_WITH_LEN("ssl_type")); } + int set_ssl_type (SSL_type x) const + { return set_int_value(STRING_WITH_LEN("ssl_type"), x); } + const char* get_ssl_cipher (MEM_ROOT *root) const + { return get_str_value(root, STRING_WITH_LEN("ssl_cipher")); } + int set_ssl_cipher (const char *s, size_t l) const + { return set_str_value(STRING_WITH_LEN("ssl_cipher"), s, l); } + const char* get_x509_issuer (MEM_ROOT *root) const + { return get_str_value(root, STRING_WITH_LEN("x509_issuer")); } + int set_x509_issuer (const char *s, size_t l) const + { return set_str_value(STRING_WITH_LEN("x509_issuer"), s, l); } + const char* get_x509_subject (MEM_ROOT *root) const + { return get_str_value(root, STRING_WITH_LEN("x509_subject")); } + int set_x509_subject (const char *s, size_t l) const + { return set_str_value(STRING_WITH_LEN("x509_subject"), s, l); } + longlong get_max_questions () const + { return get_int_value(STRING_WITH_LEN("max_questions")); } + int set_max_questions (longlong x) const + { return set_int_value(STRING_WITH_LEN("max_questions"), x); } + longlong get_max_updates () const + { return get_int_value(STRING_WITH_LEN("max_updates")); } + int set_max_updates (longlong x) const + { return set_int_value(STRING_WITH_LEN("max_updates"), x); } + longlong get_max_connections () const + { return get_int_value(STRING_WITH_LEN("max_connections")); } + int set_max_connections (longlong x) const + { return set_int_value(STRING_WITH_LEN("max_connections"), x); } + longlong get_max_user_connections () const + { return get_int_value(STRING_WITH_LEN("max_user_connections")); } + int set_max_user_connections (longlong x) const + { return set_int_value(STRING_WITH_LEN("max_user_connections"), x); } + double get_max_statement_time () const + { return get_double_value(STRING_WITH_LEN("max_statement_time")); } + int set_max_statement_time (double x) const + { return set_double_value(STRING_WITH_LEN("max_statement_time"), x); } + bool get_is_role () const + { return get_bool_value(STRING_WITH_LEN("is_role")); } + int set_is_role (bool x) const + { return set_bool_value(STRING_WITH_LEN("is_role"), x); } + const char* get_default_role (MEM_ROOT *root) const + { return get_str_value(root, STRING_WITH_LEN("default_role")); } + int set_default_role (const char *s, size_t l) const + { return set_str_value(STRING_WITH_LEN("default_role"), s, l); } + + ~User_table_json() {} + private: + friend class Grant_tables; + static const uint JSON_SIZE=1024; + int setup_sysvars() const + { + using_global_priv_table= true; + username_char_length= MY_MIN(m_table->field[1]->char_length(), + USERNAME_CHAR_LENGTH); + return 0; + } + bool get_value(const char *key, size_t klen, + enum json_value_types vt, const char **v, size_t *vl) const + { + enum json_value_types value_type; + String str, *res= m_table->field[2]->val_str(&str); + if (!res || json_get_object_by_key(res->ptr(), res->length(), key, klen, + &value_type, v, vl)) + return 1; // invalid + return value_type != vt; + } + const char *get_str_value(MEM_ROOT *root, const char *key, size_t klen) const + { + size_t value_len; + const char *value_start; + if (get_value(key, klen, JSON_VALUE_STRING, &value_start, &value_len)) + return ""; + char *ptr= (char*)alloca(value_len); + int len= json_unescape(m_table->field[2]->charset(), + (const uchar*)value_start, + (const uchar*)value_start + value_len, + system_charset_info, + (uchar*)ptr, (uchar*)ptr + value_len); + if (len < 0) + return NULL; + return strmake_root(root, ptr, len); + } + longlong get_int_value(const char *key, size_t klen) const + { + int err; + size_t value_len; + const char *value_start; + if (get_value(key, klen, JSON_VALUE_NUMBER, &value_start, &value_len)) + return 0; + const char *value_end= value_start + value_len; + return my_strtoll10(value_start, (char**)&value_end, &err); + } + double get_double_value(const char *key, size_t klen) const + { + int err; + size_t value_len; + const char *value_start; + if (get_value(key, klen, JSON_VALUE_NUMBER, &value_start, &value_len)) + return 0; + const char *value_end= value_start + value_len; + return my_strtod(value_start, (char**)&value_end, &err); + } + bool get_bool_value(const char *key, size_t klen) const + { + size_t value_len; + const char *value_start; + if (get_value(key, klen, JSON_VALUE_TRUE, &value_start, &value_len)) + return false; + return true; + } + bool set_value(const char *key, size_t klen, + const char *val, size_t vlen, bool string) const + { + size_t value_len; + const char *value_start; + enum json_value_types value_type; + String str, *res= m_table->field[2]->val_str(&str); + if (!res || !res->length()) + (res= &str)->set(STRING_WITH_LEN("{}"), m_table->field[2]->charset()); + if (json_get_object_by_key(res->ptr(), res->length(), key, klen, + &value_type, &value_start, &value_len)) + return 1; // invalid + StringBuffer<JSON_SIZE> json(res->charset()); + json.copy(res->ptr(), value_start - res->ptr(), res->charset()); + if (!value_type) + { + if (value_len) + json.append(','); + json.append('"'); + json.append(key, klen); + json.append(STRING_WITH_LEN("\":")); + if (string) + json.append('"'); + } + else + value_start+= value_len; + json.append(val, vlen); + if (!value_type && string) + json.append('"'); + json.append(value_start, res->end() - value_start); + DBUG_ASSERT(json_valid(json.ptr(), json.length(), json.charset())); + m_table->field[2]->store(json.ptr(), json.length(), json.charset()); + return 0; + } + bool set_str_value(const char *key, size_t klen, const char *val, size_t vlen) const + { + char buf[JSON_SIZE]; + int blen= json_escape(system_charset_info, + (const uchar*)val, (const uchar*)val + vlen, + m_table->field[2]->charset(), + (uchar*)buf, (uchar*)buf+sizeof(buf)); + if (blen < 0) + return 1; + return set_value(key, klen, buf, blen, true); + } + bool set_int_value(const char *key, size_t klen, longlong val) const + { + char v[MY_INT64_NUM_DECIMAL_DIGITS+1]; + size_t vlen= longlong10_to_str(val, v, -10) - v; + return set_value(key, klen, v, vlen, false); + } + bool set_double_value(const char *key, size_t klen, double val) const + { + char v[FLOATING_POINT_BUFFER+1]; + size_t vlen= my_fcvt(val, TIME_SECOND_PART_DIGITS, v, NULL); + return set_value(key, klen, v, vlen, false); + } + bool set_bool_value(const char *key, size_t klen, bool val) const + { return set_value(key, klen, val ? "true" : "false", val ? 4 : 5, false); } }; class Db_table: public Grant_table_base { public: - Field* host() const { return tl.table->field[0]; } - Field* db() const { return tl.table->field[1]; } - Field* user() const { return tl.table->field[2]; } + Field* host() const { return m_table->field[0]; } + Field* db() const { return m_table->field[1]; } + Field* user() const { return m_table->field[2]; } private: friend class Grant_tables; - Db_table() {}; - - void init(enum thr_lock_type lock_type) - { - /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_DB_NAME, NULL, lock_type); - Grant_table_base::init(lock_type, false); - } + Db_table() {} }; class Tables_priv_table: public Grant_table_base { public: - Field* host() const { return tl.table->field[0]; } - Field* db() const { return tl.table->field[1]; } - Field* user() const { return tl.table->field[2]; } - Field* table_name() const { return tl.table->field[3]; } - Field* grantor() const { return tl.table->field[4]; } - Field* timestamp() const { return tl.table->field[5]; } - Field* table_priv() const { return tl.table->field[6]; } - Field* column_priv() const { return tl.table->field[7]; } + Field* host() const { return m_table->field[0]; } + Field* db() const { return m_table->field[1]; } + Field* user() const { return m_table->field[2]; } + Field* table_name() const { return m_table->field[3]; } + Field* grantor() const { return m_table->field[4]; } + Field* timestamp() const { return m_table->field[5]; } + Field* table_priv() const { return m_table->field[6]; } + Field* column_priv() const { return m_table->field[7]; } private: friend class Grant_tables; - Tables_priv_table() {}; - - void init(enum thr_lock_type lock_type, Grant_table_base *next_table= NULL) - { - /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - LEX_CSTRING MYSQL_TABLES_PRIV_NAME={STRING_WITH_LEN("tables_priv") }; - tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLES_PRIV_NAME, NULL, lock_type); - Grant_table_base::init(lock_type, false); - } + Tables_priv_table() {} }; class Columns_priv_table: public Grant_table_base { public: - Field* host() const { return tl.table->field[0]; } - Field* db() const { return tl.table->field[1]; } - Field* user() const { return tl.table->field[2]; } - Field* table_name() const { return tl.table->field[3]; } - Field* column_name() const { return tl.table->field[4]; } - Field* timestamp() const { return tl.table->field[5]; } - Field* column_priv() const { return tl.table->field[6]; } + Field* host() const { return m_table->field[0]; } + Field* db() const { return m_table->field[1]; } + Field* user() const { return m_table->field[2]; } + Field* table_name() const { return m_table->field[3]; } + Field* column_name() const { return m_table->field[4]; } + Field* timestamp() const { return m_table->field[5]; } + Field* column_priv() const { return m_table->field[6]; } private: friend class Grant_tables; - Columns_priv_table() {}; - - void init(enum thr_lock_type lock_type) - { - /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - LEX_CSTRING MYSQL_COLUMNS_PRIV_NAME={ STRING_WITH_LEN("columns_priv") }; - tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_COLUMNS_PRIV_NAME, NULL, lock_type); - Grant_table_base::init(lock_type, false); - } + Columns_priv_table() {} }; class Host_table: public Grant_table_base { public: - Field* host() const { return tl.table->field[0]; } - Field* db() const { return tl.table->field[1]; } + Field* host() const { return m_table->field[0]; } + Field* db() const { return m_table->field[1]; } private: friend class Grant_tables; Host_table() {} - - void init(enum thr_lock_type lock_type) - { - /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - LEX_CSTRING MYSQL_HOST_NAME={STRING_WITH_LEN("host") }; - tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_HOST_NAME, NULL, lock_type); - Grant_table_base::init(lock_type, true); - } }; class Procs_priv_table: public Grant_table_base { public: - Field* host() const { return tl.table->field[0]; } - Field* db() const { return tl.table->field[1]; } - Field* user() const { return tl.table->field[2]; } - Field* routine_name() const { return tl.table->field[3]; } - Field* routine_type() const { return tl.table->field[4]; } - Field* grantor() const { return tl.table->field[5]; } - Field* proc_priv() const { return tl.table->field[6]; } - Field* timestamp() const { return tl.table->field[7]; } + Field* host() const { return m_table->field[0]; } + Field* db() const { return m_table->field[1]; } + Field* user() const { return m_table->field[2]; } + Field* routine_name() const { return m_table->field[3]; } + Field* routine_type() const { return m_table->field[4]; } + Field* grantor() const { return m_table->field[5]; } + Field* proc_priv() const { return m_table->field[6]; } + Field* timestamp() const { return m_table->field[7]; } private: friend class Grant_tables; Procs_priv_table() {} - - void init(enum thr_lock_type lock_type) - { - /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - LEX_CSTRING MYSQL_PROCS_PRIV_NAME={STRING_WITH_LEN("procs_priv") }; - tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PROCS_PRIV_NAME, NULL, lock_type); - Grant_table_base::init(lock_type, true); - } }; class Proxies_priv_table: public Grant_table_base { public: - Field* host() const { return tl.table->field[0]; } - Field* user() const { return tl.table->field[1]; } - Field* proxied_host() const { return tl.table->field[2]; } - Field* proxied_user() const { return tl.table->field[3]; } - Field* with_grant() const { return tl.table->field[4]; } - Field* grantor() const { return tl.table->field[5]; } - Field* timestamp() const { return tl.table->field[6]; } + Field* host() const { return m_table->field[0]; } + Field* user() const { return m_table->field[1]; } + Field* proxied_host() const { return m_table->field[2]; } + Field* proxied_user() const { return m_table->field[3]; } + Field* with_grant() const { return m_table->field[4]; } + Field* grantor() const { return m_table->field[5]; } + Field* timestamp() const { return m_table->field[6]; } private: friend class Grant_tables; Proxies_priv_table() {} - - void init(enum thr_lock_type lock_type) - { - /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - LEX_CSTRING MYSQL_PROXIES_PRIV_NAME={STRING_WITH_LEN("proxies_priv") }; - tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PROXIES_PRIV_NAME, NULL, lock_type); - Grant_table_base::init(lock_type, true); - } }; class Roles_mapping_table: public Grant_table_base { public: - Field* host() const { return tl.table->field[0]; } - Field* user() const { return tl.table->field[1]; } - Field* role() const { return tl.table->field[2]; } - Field* admin_option() const { return tl.table->field[3]; } + Field* host() const { return m_table->field[0]; } + Field* user() const { return m_table->field[1]; } + Field* role() const { return m_table->field[2]; } + Field* admin_option() const { return m_table->field[3]; } private: friend class Grant_tables; Roles_mapping_table() {} - - void init(enum thr_lock_type lock_type) - { - /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - LEX_CSTRING MYSQL_ROLES_MAPPING_NAME={STRING_WITH_LEN("roles_mapping") }; - tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_ROLES_MAPPING_NAME, NULL, lock_type); - Grant_table_base::init(lock_type, true); - } }; /** @@ -1116,170 +1519,130 @@ class Roles_mapping_table: public Grant_table_base class Grant_tables { public: - /* When constructing the Grant_tables object, we initialize only - the tables which are going to be opened. - @param which_tables Bitmap of which tables to open. - @param lock_type Lock type to use when opening tables. - */ - Grant_tables(int which_tables, enum thr_lock_type lock_type) - { - DBUG_ENTER("Grant_tables::Grant_tables"); - DBUG_PRINT("info", ("which_tables: %x, lock_type: %u", - which_tables, lock_type)); - DBUG_ASSERT(which_tables); /* At least one table must be opened. */ - Grant_table_base* prev= NULL; - /* We start from the last table, Table_roles_mapping, such that - the first one in the linked list is Table_user. */ - if (which_tables & Table_roles_mapping) - { - m_roles_mapping_table.init(lock_type); - prev= &m_roles_mapping_table; - } - if (which_tables & Table_proxies_priv) - { - m_proxies_priv_table.init(lock_type); - link_tables(&m_proxies_priv_table, prev); - prev= &m_proxies_priv_table; - } - if (which_tables & Table_procs_priv) - { - m_procs_priv_table.init(lock_type); - link_tables(&m_procs_priv_table, prev); - prev= &m_procs_priv_table; - } - if (which_tables & Table_host) - { - m_host_table.init(lock_type); - link_tables(&m_host_table, prev); - prev= &m_host_table; - } - if (which_tables & Table_columns_priv) - { - m_columns_priv_table.init(lock_type); - link_tables(&m_columns_priv_table, prev); - prev= &m_columns_priv_table; - } - if (which_tables & Table_tables_priv) - { - m_tables_priv_table.init(lock_type); - link_tables(&m_tables_priv_table, prev); - prev= &m_tables_priv_table; - } - if (which_tables & Table_db) - { - m_db_table.init(lock_type); - link_tables(&m_db_table, prev); - prev= &m_db_table; - } - if (which_tables & Table_user) - { - m_user_table.init(lock_type); - link_tables(&m_user_table, prev); - prev= &m_user_table; - } - - first_table_in_list= prev; - DBUG_VOID_RETURN; - } - - /* Before any operation is possible on grant tables, they must be opened. - This opens the tables according to the lock type specified during - construction. + Grant_tables() : p_user_table(&m_user_table_json) { } - @retval 1 replication filters matched. Abort the operation, - but return OK (!) - @retval 0 tables were opened successfully - @retval -1 error, tables could not be opened - */ - int open_and_lock(THD *thd) + int open_and_lock(THD *thd, int which_tables, enum thr_lock_type lock_type) { DBUG_ENTER("Grant_tables::open_and_lock"); - DBUG_ASSERT(first_table_in_list); -#ifdef HAVE_REPLICATION - if (first_table_in_list->tl.lock_type >= TL_WRITE_ALLOW_WRITE && - thd->slave_thread && !thd->spcont) - { - /* - GRANT and REVOKE are applied the slave in/exclusion rules as they are - some kind of updates to the mysql.% tables. - */ - Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter; - if (rpl_filter->is_on() && - !rpl_filter->tables_ok(0, &first_table_in_list->tl)) - DBUG_RETURN(1); - } -#endif - if (open_and_lock_tables(thd, &first_table_in_list->tl, FALSE, - MYSQL_LOCK_IGNORE_TIMEOUT)) - DBUG_RETURN(-1); + TABLE_LIST tables[USER_TABLE+1], *first= NULL; + DBUG_ASSERT(which_tables); /* At least one table must be opened. */ /* We can read privilege tables even when !initialized. This can be acl_load() - server startup or FLUSH PRIVILEGES */ - if (first_table_in_list->tl.lock_type >= TL_WRITE_ALLOW_WRITE && - !initialized) + if (lock_type >= TL_WRITE_ALLOW_WRITE && !initialized) { my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables"); DBUG_RETURN(-1); } - /* The privilge columns vary based on MariaDB version. Figure out - how many we have after we've opened the table. */ - m_user_table.compute_num_privilege_cols(); - m_db_table.compute_num_privilege_cols(); - m_tables_priv_table.compute_num_privilege_cols(); - m_columns_priv_table.compute_num_privilege_cols(); - m_host_table.compute_num_privilege_cols(); - m_procs_priv_table.compute_num_privilege_cols(); - m_proxies_priv_table.compute_num_privilege_cols(); - m_roles_mapping_table.compute_num_privilege_cols(); + for (int i=USER_TABLE; i >=0; i--) + { + TABLE_LIST *tl= tables + i; + if (which_tables & (1 << i)) + { + tl->init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLE_NAME[i], + NULL, lock_type); + tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE; + if (i >= FIRST_OPTIONAL_TABLE) + tl->open_strategy= TABLE_LIST::OPEN_IF_EXISTS; + tl->next_global= tl->next_local= first; + first= tl; + } + else + tl->table= NULL; + } + + uint counter; + int res= really_open(thd, first, &counter); + + /* if User_table_json wasn't found, let's try User_table_tabular */ + if (!res && (which_tables & Table_user) && !(tables[USER_TABLE].table)) + { + uint unused; + TABLE_LIST *tl= tables + USER_TABLE; + tl->init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLE_NAME_USER, + NULL, lock_type); + tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE; + p_user_table= &m_user_table_tabular; + counter++; + res= really_open(thd, tl, &unused); + } + if (res) + DBUG_RETURN(res); + + if (lock_tables(thd, first, counter, MYSQL_LOCK_IGNORE_TIMEOUT)) + DBUG_RETURN(-1); + + p_user_table->set_table(tables[USER_TABLE].table); + m_db_table.set_table(tables[DB_TABLE].table); + m_tables_priv_table.set_table(tables[TABLES_PRIV_TABLE].table); + m_columns_priv_table.set_table(tables[COLUMNS_PRIV_TABLE].table); + m_host_table.set_table(tables[HOST_TABLE].table); + m_procs_priv_table.set_table(tables[PROCS_PRIV_TABLE].table); + m_proxies_priv_table.set_table(tables[PROXIES_PRIV_TABLE].table); + m_roles_mapping_table.set_table(tables[ROLES_MAPPING_TABLE].table); DBUG_RETURN(0); } inline const User_table& user_table() const - { - return m_user_table; - } + { return *p_user_table; } inline const Db_table& db_table() const - { - return m_db_table; - } - + { return m_db_table; } inline const Tables_priv_table& tables_priv_table() const - { - return m_tables_priv_table; - } + { return m_tables_priv_table; } inline const Columns_priv_table& columns_priv_table() const - { - return m_columns_priv_table; - } + { return m_columns_priv_table; } inline const Host_table& host_table() const - { - return m_host_table; - } + { return m_host_table; } inline const Procs_priv_table& procs_priv_table() const - { - return m_procs_priv_table; - } + { return m_procs_priv_table; } inline const Proxies_priv_table& proxies_priv_table() const - { - return m_proxies_priv_table; - } + { return m_proxies_priv_table; } inline const Roles_mapping_table& roles_mapping_table() const + { return m_roles_mapping_table; } + + private: + + /* Before any operation is possible on grant tables, they must be opened. + + @retval 1 replication filters matched. Abort the operation, + but return OK (!) + @retval 0 tables were opened successfully + @retval -1 error, tables could not be opened + */ + int really_open(THD *thd, TABLE_LIST* tables, uint *counter) { - return m_roles_mapping_table; + DBUG_ENTER("Grant_tables::really_open:"); +#ifdef HAVE_REPLICATION + if (tables->lock_type >= TL_WRITE_ALLOW_WRITE && + thd->slave_thread && !thd->spcont) + { + /* + GRANT and REVOKE are applied the slave in/exclusion rules as they are + some kind of updates to the mysql.% tables. + */ + Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter; + if (rpl_filter->is_on() && !rpl_filter->tables_ok(0, tables)) + DBUG_RETURN(1); + } +#endif + if (open_tables(thd, &tables, counter, MYSQL_LOCK_IGNORE_TIMEOUT)) + DBUG_RETURN(-1); + DBUG_RETURN(0); } - private: - User_table m_user_table; + User_table *p_user_table; + User_table_json m_user_table_json; + User_table_tabular m_user_table_tabular; Db_table m_db_table; Tables_priv_table m_tables_priv_table; Columns_priv_table m_columns_priv_table; @@ -1287,20 +1650,6 @@ class Grant_tables Procs_priv_table m_procs_priv_table; Proxies_priv_table m_proxies_priv_table; Roles_mapping_table m_roles_mapping_table; - - /* The grant tables are set-up in a linked list. We keep the head of it. */ - Grant_table_base *first_table_in_list; - /** - Chain two grant tables' TABLE_LIST members. - */ - static void link_tables(Grant_table_base *from, Grant_table_base *to) - { - DBUG_ASSERT(from); - if (to) - from->tl.next_local= from->tl.next_global= &to->tl; - else - from->tl.next_local= from->tl.next_global= NULL; - } }; @@ -1308,14 +1657,13 @@ void ACL_PROXY_USER::init(const Proxies_priv_table& proxies_priv_table, MEM_ROOT *mem) { init(get_field(mem, proxies_priv_table.host()), - get_field(mem, proxies_priv_table.user()), + safe_str(get_field(mem, proxies_priv_table.user())), get_field(mem, proxies_priv_table.proxied_host()), - get_field(mem, proxies_priv_table.proxied_user()), + safe_str(get_field(mem, proxies_priv_table.proxied_user())), proxies_priv_table.with_grant()->val_int() != 0); } - /* Enumeration of various ACL's and Hashes used in handle_grant_struct() */ @@ -1339,8 +1687,7 @@ ACL_ROLE::ACL_ROLE(ACL_USER *user, MEM_ROOT *root) : counter(0) access= user->access; /* set initial role access the same as the table row privileges */ initial_role_access= user->access; - this->user.str= safe_strdup_root(root, user->user.str); - this->user.length= user->user.length; + this->user= user->user; bzero(&role_grants, sizeof(role_grants)); bzero(&parent_grantee, sizeof(parent_grantee)); flags= IS_ROLE; @@ -1390,7 +1737,7 @@ static bool has_validation_plugins() MariaDB_PASSWORD_VALIDATION_PLUGIN, NULL); } -struct validation_data { LEX_CSTRING *user, *password; }; +struct validation_data { const LEX_CSTRING *user, *password; }; static my_bool do_validate(THD *, plugin_ref plugin, void *arg) { @@ -1401,13 +1748,13 @@ static my_bool do_validate(THD *, plugin_ref plugin, void *arg) } -static bool validate_password(LEX_USER *user, THD *thd) +static bool validate_password(THD *thd, const LEX_CSTRING &user, + const LEX_CSTRING &pwtext, bool has_hash) { - if (user->pwtext.length || !user->pwhash.length) + if (pwtext.length || !has_hash) { - struct validation_data data= { &user->user, - user->pwtext.str ? &user->pwtext : - const_cast<LEX_CSTRING *>(&empty_clex_str) }; + struct validation_data data= { &user, + pwtext.str ? &pwtext : &empty_clex_str }; if (plugin_foreach(NULL, do_validate, MariaDB_PASSWORD_VALIDATION_PLUGIN, &data)) { @@ -1428,45 +1775,87 @@ static bool validate_password(LEX_USER *user, THD *thd) } /** - Convert scrambled password to binary form, according to scramble type, - Binary form is stored in user.salt. - - @param acl_user The object where to store the salt - @param password The password hash containing the salt - @param password_len The length of the password hash - - Despite the name of the function it is used when loading ACLs from disk - to store the password hash in the ACL_USER object. -*/ + Fills in ACL_USER::auth_string and ACL_USER::salt fields, as needed -static void -set_user_salt(ACL_USER *acl_user, const char *password, size_t password_len) + hashes the plain-text password (if provided) to auth_string, + converts auth_string to salt. + + Fails if the plain-text password fails validation, if the plugin is + not loaded, if the auth_string is invalid. + + Using NULL for a password disables validation + (needed for loading from mysql.user table). +*/ +static int set_user_auth(THD *thd, ACL_USER *acl_user, const LEX_CSTRING *pwtext) { - if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH) + const char *plugin_name= acl_user->plugin.str; + bool unlock_plugin= false; + plugin_ref plugin= get_auth_plugin(thd, acl_user->plugin, &unlock_plugin); + int res= 1; + + if (!plugin) { - get_salt_from_password(acl_user->salt, password); - acl_user->salt_len= SCRAMBLE_LENGTH; + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_PLUGIN_IS_NOT_LOADED, + ER_THD(thd, ER_PLUGIN_IS_NOT_LOADED), plugin_name); + return res; } - else if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323) + + acl_user->salt= acl_user->auth_string; + + st_mysql_auth *auth= (st_mysql_auth *) plugin_decl(plugin)->info; + if (auth->interface_version >= 0x0202) { - get_salt_from_password_323((ulong *) acl_user->salt, password); - acl_user->salt_len= SCRAMBLE_LENGTH_323; + if (pwtext) + { + if (auth->hash_password && + validate_password(thd, acl_user->user, *pwtext, + acl_user->auth_string.length)) + goto end; + if (pwtext->length) + { + if (auth->hash_password) + { + char buf[MAX_SCRAMBLE_LENGTH]; + size_t len= sizeof(buf) - 1; + if (auth->hash_password(pwtext->str, pwtext->length, buf, &len)) + goto end; // OOM? + buf[len] = 0; + acl_user->auth_string.str= (char*)memdup_root(&acl_memroot, buf, len+1); + acl_user->auth_string.length= len; + } + else + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_SET_PASSWORD_AUTH_PLUGIN, + ER_THD(thd, ER_SET_PASSWORD_AUTH_PLUGIN), + acl_user->plugin.str); + } + } + } + + if (acl_user->auth_string.length) + { + if (auth->preprocess_hash) + { + uchar buf[MAX_SCRAMBLE_LENGTH]; + size_t len= sizeof(buf); + if (auth->preprocess_hash(acl_user->auth_string.str, + acl_user->auth_string.length, buf, &len)) + goto end; // ER_PASSWD_LENGTH? + acl_user->salt.str= (char*)memdup_root(&acl_memroot, buf, len); + acl_user->salt.length= len; + } + else + acl_user->salt= acl_user->auth_string; + } } - else - acl_user->salt_len= 0; -} -static const char *fix_plugin_ptr(const char *name) -{ - if (my_strcasecmp(system_charset_info, name, - native_password_plugin_name.str) == 0) - return native_password_plugin_name.str; - else - if (my_strcasecmp(system_charset_info, name, - old_password_plugin_name.str) == 0) - return old_password_plugin_name.str; - else - return name; + res= 0; +end: + if (unlock_plugin) + plugin_unlock(thd, plugin); + return res; } /** @@ -1477,8 +1866,6 @@ static const char *fix_plugin_ptr(const char *name) authentication, we want to be able to detect built-ins by comparing pointers, not strings. - Additionally - update the salt if the plugin is built-in. - @retval 0 the pointers were fixed @retval 1 this ACL_USER uses a not built-in plugin */ @@ -1491,98 +1878,6 @@ static bool fix_user_plugin_ptr(ACL_USER *user) user->plugin= old_password_plugin_name; else return true; - - if (user->auth_string.length) - set_user_salt(user, user->auth_string.str, user->auth_string.length); - return false; -} - - -/* - Validates the password, calculates password hash, transforms - equivalent LEX_USER representations. - - Upon entering this function: - - - if user->plugin is specified, user->auth is the plugin auth data. - - if user->plugin is mysql_native_password or mysql_old_password, - user->auth is the password hash, and LEX_USER is transformed - to match the next case (that is, user->plugin is cleared). - - if user->plugin is NOT specified, built-in auth is assumed, that is - mysql_native_password or mysql_old_password. In that case, - user->pwhash is the password hash. And user->pwtext is the original - plain-text password. Either one can be set or both. - - Upon exiting this function: - - - user->pwtext is left untouched - - user->pwhash is the password hash, as the mysql.user.password column - - user->plugin is the plugin name, as the mysql.user.plugin column - - user->auth is the plugin auth data, as the mysql.user.authentication_string column -*/ -static bool fix_lex_user(THD *thd, LEX_USER *user) -{ - size_t check_length; - - DBUG_ASSERT(user->plugin.length || !user->auth.length); - DBUG_ASSERT(!(user->plugin.length && (user->pwtext.length || user->pwhash.length))); - - if (lex_string_eq(&user->plugin, &native_password_plugin_name)) - check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; - else - if (lex_string_eq(&user->plugin, &old_password_plugin_name)) - check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; - else - if (user->plugin.length) - return false; // nothing else to do - else if (thd->variables.old_passwords == 1 || - user->pwhash.length == SCRAMBLED_PASSWORD_CHAR_LENGTH_323) - check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; - else - check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; - - if (user->plugin.length) - { - user->pwhash= user->auth; - user->plugin= empty_clex_str; - user->auth= empty_clex_str; - } - - if (user->pwhash.length && user->pwhash.length != check_length) - { - my_error(ER_PASSWD_LENGTH, MYF(0), (int) check_length); - return true; - } - - if (user->pwtext.length && !user->pwhash.length) - { - size_t scramble_length; - void (*make_scramble)(char *, const char *, size_t); - - if (thd->variables.old_passwords == 1) - { - scramble_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; - make_scramble= my_make_scrambled_password_323; - } - else - { - scramble_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; - make_scramble= my_make_scrambled_password; - } - - Query_arena *arena, backup; - arena= thd->activate_stmt_arena_if_needed(&backup); - char *buff= (char *) thd->alloc(scramble_length + 1); - if (arena) - thd->restore_active_arena(arena, &backup); - - if (buff == NULL) - return true; - make_scramble(buff, user->pwtext.str, user->pwtext.length); - user->pwhash.str= buff; - user->pwhash.length= scramble_length; - } - return false; } @@ -1659,27 +1954,12 @@ bool acl_init(bool dont_read_acl_tables) DBUG_RETURN(return_val); } -/** - Choose from either native or old password plugins when assigning a password -*/ - -static bool set_user_plugin (ACL_USER *user, size_t password_len) +static void push_new_user(const ACL_USER &user) { - switch (password_len) - { - case 0: /* no password */ - case SCRAMBLED_PASSWORD_CHAR_LENGTH: - user->plugin= native_password_plugin_name; - return FALSE; - case SCRAMBLED_PASSWORD_CHAR_LENGTH_323: - user->plugin= old_password_plugin_name; - return FALSE; - default: - sql_print_warning("Found invalid password for user: '%s@%s'; " - "Ignoring user", safe_str(user->user.str), - safe_str(user->host.hostname)); - return TRUE; - } + push_dynamic(&acl_users, &user); + if (!user.host.hostname || + (user.host.hostname[0] == wild_many && !user.host.hostname[1])) + allow_all_hosts=1; // Anyone can connect } @@ -1704,7 +1984,6 @@ static bool acl_load(THD *thd, const Grant_tables& tables) READ_RECORD read_record_info; bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; char tmp_name[SAFE_NAME_LEN+1]; - int password_length; Sql_mode_save old_mode_save(thd); DBUG_ENTER("acl_load"); @@ -1716,7 +1995,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) init_sql_alloc(&acl_memroot, "ACL", ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); if (host_table.table_exists()) // "host" table may not exist (e.g. in MySQL 5.6.7+) { - if (host_table.init_read_record(&read_record_info, thd)) + if (host_table.init_read_record(&read_record_info)) DBUG_RETURN(true); while (!(read_record_info.read_record())) { @@ -1770,280 +2049,99 @@ static bool acl_load(THD *thd, const Grant_tables& tables) freeze_size(&acl_hosts); const User_table& user_table= tables.user_table(); - if (user_table.init_read_record(&read_record_info, thd)) + if (user_table.init_read_record(&read_record_info)) DBUG_RETURN(true); - username_char_length= MY_MIN(user_table.user()->char_length(), - USERNAME_CHAR_LENGTH); - if (user_table.password()) // Password column might be missing. (MySQL 5.7.6+) - { - password_length= user_table.password()->field_length / - user_table.password()->charset()->mbmaxlen; - if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323) - { - sql_print_error("Fatal error: mysql.user table is damaged or in " - "unsupported 3.20 format."); - DBUG_RETURN(TRUE); - } - - DBUG_PRINT("info",("user table fields: %d, password length: %d", - user_table.num_fields(), password_length)); - - mysql_mutex_lock(&LOCK_global_system_variables); - if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH) - { - if (opt_secure_auth) - { - mysql_mutex_unlock(&LOCK_global_system_variables); - sql_print_error("Fatal error: mysql.user table is in old format, " - "but server started with --secure-auth option."); - DBUG_RETURN(TRUE); - } - mysql_user_table_is_in_short_password_format= true; - if (global_system_variables.old_passwords) - mysql_mutex_unlock(&LOCK_global_system_variables); - else - { - extern sys_var *Sys_old_passwords_ptr; - Sys_old_passwords_ptr->value_origin= sys_var::AUTO; - global_system_variables.old_passwords= 1; - mysql_mutex_unlock(&LOCK_global_system_variables); - sql_print_warning("mysql.user table is not updated to new password format; " - "Disabling new password usage until " - "mysql_fix_privilege_tables is run"); - } - thd->variables.old_passwords= 1; - } - else - { - mysql_user_table_is_in_short_password_format= false; - mysql_mutex_unlock(&LOCK_global_system_variables); - } - } - allow_all_hosts=0; while (!(read_record_info.read_record())) { ACL_USER user; bool is_role= FALSE; bzero(&user, sizeof(user)); - update_hostname(&user.host, get_field(&acl_memroot, user_table.host())); - char *username= get_field(&acl_memroot, user_table.user()); + update_hostname(&user.host, user_table.get_host(&acl_memroot)); + char *username= safe_str(user_table.get_user(&acl_memroot)); user.user.str= username; - user.user.length= safe_strlen(username); + user.user.length= strlen(username); - /* - If the user entry is a role, skip password and hostname checks - A user can not log in with a role so some checks are not necessary - */ - is_role= user_table.check_is_role(); + is_role= user_table.get_is_role(); - if (is_role && is_invalid_role_name(username)) - { - thd->clear_error(); // the warning is still issued - continue; - } + user.access= user_table.get_access(); - if (!is_role && check_no_resolve && - hostname_requires_resolving(user.host.hostname)) - { - sql_print_warning("'user' entry '%s@%s' " - "ignored in --skip-name-resolve mode.", - safe_str(user.user.str), - safe_str(user.host.hostname)); - continue; - } - - char *password= const_cast<char*>(""); - if (user_table.password()) - password= get_field(&acl_memroot, user_table.password()); - size_t password_len= safe_strlen(password); - user.auth_string.str= safe_str(password); - user.auth_string.length= password_len; - set_user_salt(&user, password, password_len); + user.sort= get_sort(2, user.host.hostname, user.user.str); + user.hostname_length= safe_strlen(user.host.hostname); - if (!is_role && set_user_plugin(&user, password_len)) - continue; + my_init_dynamic_array(&user.role_grants, sizeof(ACL_ROLE *), 0, 8, MYF(0)); + if (is_role) { - user.access= user_table.get_access() & GLOBAL_ACLS; - /* - if it is pre 5.0.1 privilege table then map CREATE privilege on - CREATE VIEW & SHOW VIEW privileges - */ - if (user_table.num_fields() <= 31 && (user.access & CREATE_ACL)) - user.access|= (CREATE_VIEW_ACL | SHOW_VIEW_ACL); - - /* - if it is pre 5.0.2 privilege table then map CREATE/ALTER privilege on - CREATE PROCEDURE & ALTER PROCEDURE privileges - */ - if (user_table.num_fields() <= 33 && (user.access & CREATE_ACL)) - user.access|= CREATE_PROC_ACL; - if (user_table.num_fields() <= 33 && (user.access & ALTER_ACL)) - user.access|= ALTER_PROC_ACL; - - /* - pre 5.0.3 did not have CREATE_USER_ACL - */ - if (user_table.num_fields() <= 36 && (user.access & GRANT_ACL)) - user.access|= CREATE_USER_ACL; - - - /* - if it is pre 5.1.6 privilege table then map CREATE privilege on - CREATE|ALTER|DROP|EXECUTE EVENT - */ - if (user_table.num_fields() <= 37 && (user.access & SUPER_ACL)) - user.access|= EVENT_ACL; - - /* - if it is pre 5.1.6 privilege then map TRIGGER privilege on CREATE. - */ - if (user_table.num_fields() <= 38 && (user.access & SUPER_ACL)) - user.access|= TRIGGER_ACL; - - if (user_table.num_fields() <= 46 && (user.access & DELETE_ACL)) - user.access|= DELETE_HISTORY_ACL; - - user.sort= get_sort(2, user.host.hostname, user.user.str); - user.hostname_length= safe_strlen(user.host.hostname); - user.user_resource.user_conn= 0; - user.user_resource.max_statement_time= 0.0; - - /* Starting from 4.0.2 we have more fields */ - if (user_table.ssl_type()) + if (is_invalid_role_name(username)) { - char *ssl_type=get_field(thd->mem_root, user_table.ssl_type()); - if (!ssl_type) - user.ssl_type=SSL_TYPE_NONE; - else if (!strcmp(ssl_type, "ANY")) - user.ssl_type=SSL_TYPE_ANY; - else if (!strcmp(ssl_type, "X509")) - user.ssl_type=SSL_TYPE_X509; - else /* !strcmp(ssl_type, "SPECIFIED") */ - user.ssl_type=SSL_TYPE_SPECIFIED; - - user.ssl_cipher= get_field(&acl_memroot, user_table.ssl_cipher()); - user.x509_issuer= get_field(&acl_memroot, user_table.x509_issuer()); - user.x509_subject= get_field(&acl_memroot, user_table.x509_subject()); - - char *ptr = get_field(thd->mem_root, user_table.max_questions()); - user.user_resource.questions=ptr ? atoi(ptr) : 0; - ptr = get_field(thd->mem_root, user_table.max_updates()); - user.user_resource.updates=ptr ? atoi(ptr) : 0; - ptr = get_field(thd->mem_root, user_table.max_connections()); - user.user_resource.conn_per_hour= ptr ? atoi(ptr) : 0; - if (user.user_resource.questions || user.user_resource.updates || - user.user_resource.conn_per_hour) - mqh_used=1; - - if (user_table.max_user_connections()) - { - /* Starting from 5.0.3 we have max_user_connections field */ - ptr= get_field(thd->mem_root, user_table.max_user_connections()); - user.user_resource.user_conn= ptr ? atoi(ptr) : 0; - } - - if (!is_role && user_table.plugin()) - { - /* We may have plugin & auth_String fields */ - char *tmpstr= get_field(&acl_memroot, user_table.plugin()); - if (tmpstr) - { - user.plugin.str= tmpstr; - user.plugin.length= strlen(user.plugin.str); - user.auth_string.str= - safe_str(get_field(&acl_memroot, - user_table.authentication_string())); - user.auth_string.length= strlen(user.auth_string.str); - - if (user.auth_string.length && password_len && - (user.auth_string.length != password_len || - memcmp(user.auth_string.str, password, password_len))) - { - sql_print_warning("'user' entry '%s@%s' has both a password " - "and an authentication plugin specified. The " - "password will be ignored.", - safe_str(user.user.str), - safe_str(user.host.hostname)); - } - - fix_user_plugin_ptr(&user); - } - } - - if (user_table.max_statement_time()) - { - /* Starting from 10.1.1 we can have max_statement_time */ - ptr= get_field(thd->mem_root, - user_table.max_statement_time()); - user.user_resource.max_statement_time= ptr ? atof(ptr) : 0.0; - } - } - else - { - user.ssl_type=SSL_TYPE_NONE; -#ifndef TO_BE_REMOVED - if (user_table.num_fields() <= 13) - { // Without grant - if (user.access & CREATE_ACL) - user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL; - } - /* Convert old privileges */ - user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL; - if (user.access & FILE_ACL) - user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL; - if (user.access & PROCESS_ACL) - user.access|= SUPER_ACL | EXECUTE_ACL; -#endif + thd->clear_error(); // the warning is still issued + continue; } - (void) my_init_dynamic_array(&user.role_grants,sizeof(ACL_ROLE *), - 8, 8, MYF(0)); + ACL_ROLE *entry= new (&acl_memroot) ACL_ROLE(&user, &acl_memroot); + entry->role_grants = user.role_grants; + my_init_dynamic_array(&entry->parent_grantee, + sizeof(ACL_USER_BASE *), 0, 8, MYF(0)); + my_hash_insert(&acl_roles, (uchar *)entry); - /* check default role, if any */ - if (!is_role && user_table.default_role()) + continue; + } + else + { + if (check_no_resolve && hostname_requires_resolving(user.host.hostname)) { - user.default_rolename.str= - get_field(&acl_memroot, user_table.default_role()); - user.default_rolename.length= safe_strlen(user.default_rolename.str); + sql_print_warning("'user' entry '%s@%s' " + "ignored in --skip-name-resolve mode.", user.user.str, + safe_str(user.host.hostname)); + continue; } - if (is_role) - { - DBUG_PRINT("info", ("Found role %s", user.user.str)); - ACL_ROLE *entry= new (&acl_memroot) ACL_ROLE(&user, &acl_memroot); - entry->role_grants = user.role_grants; - (void) my_init_dynamic_array(&entry->parent_grantee, - sizeof(ACL_USER_BASE *), 8, 8, MYF(0)); - my_hash_insert(&acl_roles, (uchar *)entry); - + if (user_table.get_auth(thd, &acl_memroot, + &user.plugin.str, &user.auth_string.str)) continue; - } - else + user.plugin.length= strlen(user.plugin.str); + user.auth_string.length= strlen(user.auth_string.str); + fix_user_plugin_ptr(&user); + + user.ssl_type= user_table.get_ssl_type(); + user.ssl_cipher= user_table.get_ssl_cipher(&acl_memroot); + user.x509_issuer= safe_str(user_table.get_x509_issuer(&acl_memroot)); + user.x509_subject= safe_str(user_table.get_x509_subject(&acl_memroot)); + user.user_resource.questions= (uint)user_table.get_max_questions(); + user.user_resource.updates= (uint)user_table.get_max_updates(); + user.user_resource.conn_per_hour= (uint)user_table.get_max_connections(); + if (user.user_resource.questions || user.user_resource.updates || + user.user_resource.conn_per_hour) + mqh_used=1; + + user.user_resource.user_conn= (int)user_table.get_max_user_connections(); + user.user_resource.max_statement_time= user_table.get_max_statement_time(); + + user.default_rolename.str= user_table.get_default_role(&acl_memroot); + user.default_rolename.length= safe_strlen(user.default_rolename.str); + + if (set_user_auth(thd, &user, NULL)) { - DBUG_PRINT("info", ("Found user %s", user.user.str)); - (void) push_dynamic(&acl_users,(uchar*) &user); + thd->clear_error(); // the warning is still issued + continue; } - if (!user.host.hostname || - (user.host.hostname[0] == wild_many && !user.host.hostname[1])) - allow_all_hosts=1; // Anyone can connect } + push_new_user(user); } - my_qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, - sizeof(ACL_USER),(qsort_cmp) acl_compare); + rebuild_acl_users(); end_read_record(&read_record_info); freeze_size(&acl_users); const Db_table& db_table= tables.db_table(); - if (db_table.init_read_record(&read_record_info, thd)) + if (db_table.init_read_record(&read_record_info)) DBUG_RETURN(TRUE); while (!(read_record_info.read_record())) { ACL_DB db; char *db_name; - db.user=get_field(&acl_memroot, db_table.user()); + db.user=safe_str(get_field(&acl_memroot, db_table.user())); const char *hostname= get_field(&acl_memroot, db_table.host()); if (!hostname && find_acl_role(db.user)) hostname= ""; @@ -2058,7 +2156,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) { sql_print_warning("'db' entry '%s %s@%s' " "ignored in --skip-name-resolve mode.", - db.db, safe_str(db.user), safe_str(db.host.hostname)); + db.db, db.user, safe_str(db.host.hostname)); continue; } db.access= db_table.get_access(); @@ -2083,7 +2181,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) "case that has been forced to lowercase because " "lower_case_table_names is set. It will not be " "possible to remove this privilege using REVOKE.", - db.db, safe_str(db.user), safe_str(db.host.hostname)); + db.db, db.user, safe_str(db.host.hostname)); } } db.sort=get_sort(3,db.host.hostname,db.db,db.user); @@ -2097,13 +2195,13 @@ static bool acl_load(THD *thd, const Grant_tables& tables) acl_dbs.push(db); } end_read_record(&read_record_info); - acl_dbs.sort((acl_dbs_cmp)acl_compare); + rebuild_acl_dbs(); acl_dbs.freeze(); const Proxies_priv_table& proxies_priv_table= tables.proxies_priv_table(); if (proxies_priv_table.table_exists()) { - if (proxies_priv_table.init_read_record(&read_record_info, thd)) + if (proxies_priv_table.init_read_record(&read_record_info)) DBUG_RETURN(TRUE); while (!(read_record_info.read_record())) { @@ -2129,7 +2227,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) const Roles_mapping_table& roles_mapping_table= tables.roles_mapping_table(); if (roles_mapping_table.table_exists()) { - if (roles_mapping_table.init_read_record(&read_record_info, thd)) + if (roles_mapping_table.init_read_record(&read_record_info)) DBUG_RETURN(TRUE); MEM_ROOT temp_root; @@ -2222,13 +2320,14 @@ bool acl_reload(THD *thd) int result; DBUG_ENTER("acl_reload"); - Grant_tables tables(Table_host | Table_user | Table_db | Table_proxies_priv | - Table_roles_mapping, TL_READ); + Grant_tables tables; /* To avoid deadlocks we should obtain table locks before obtaining acl_cache->lock mutex. */ - if (unlikely((result= tables.open_and_lock(thd)))) + const uint tables_to_open= Table_host | Table_user | Table_db | + Table_proxies_priv | Table_roles_mapping; + if ((result= tables.open_and_lock(thd, tables_to_open, TL_READ))) { DBUG_ASSERT(result <= 0); /* @@ -2375,7 +2474,7 @@ static ulong get_sort(uint count,...) } -static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b) +static int acl_compare(const ACL_ACCESS *a, const ACL_ACCESS *b) { if (a->sort > b->sort) return -1; @@ -2384,6 +2483,154 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b) return 0; } +static int acl_user_compare(const ACL_USER *a, const ACL_USER *b) +{ + int res= strcmp(a->user.str, b->user.str); + if (res) + return res; + + res= acl_compare(a, b); + if (res) + return res; + + /* + For more deterministic results, resolve ambiguity between + "localhost" and "127.0.0.1"/"::1" by sorting "localhost" before + loopback addresses. + Test suite (on Windows) expects "root@localhost", even if + root@::1 would also match. + */ + return -strcmp(a->host.hostname, b->host.hostname); +} + +static int acl_db_compare(const ACL_DB *a, const ACL_DB *b) +{ + int res= strcmp(a->user, b->user); + if (res) + return res; + + return acl_compare(a, b); +} + +static void rebuild_acl_users() +{ + my_qsort((uchar*)dynamic_element(&acl_users, 0, ACL_USER*), acl_users.elements, + sizeof(ACL_USER), (qsort_cmp)acl_user_compare); +} + +static void rebuild_acl_dbs() +{ + acl_dbs.sort(acl_db_compare); +} + + +/* + Return index of the first entry with given user in the array, + or SIZE_T_MAX if not found. + + Assumes the array is sorted by get_username +*/ +template<typename T> size_t find_first_user(T* arr, size_t len, const char *user) +{ + size_t low= 0; + size_t high= len; + size_t mid; + + bool found= false; + if(!len) + return SIZE_T_MAX; + +#ifndef DBUG_OFF + for (uint i = 0; i < len - 1; i++) + DBUG_ASSERT(strcmp(arr[i].get_username(), arr[i + 1].get_username()) <= 0); +#endif + while (low < high) + { + mid= low + (high - low) / 2; + int cmp= strcmp(arr[mid].get_username(),user); + if (cmp == 0) + found= true; + + if (cmp >= 0 ) + high= mid; + else + low= mid + 1; + } + return (!found || low == len || strcmp(arr[low].get_username(), user)!=0 )?SIZE_T_MAX:low; +} + +static size_t acl_find_user_by_name(const char *user) +{ + return find_first_user<ACL_USER>((ACL_USER *)acl_users.buffer,acl_users.elements,user); +} + +static size_t acl_find_db_by_username(const char *user) +{ + return find_first_user<ACL_DB>(acl_dbs.front(), acl_dbs.elements(), user); +} + +static bool match_db(ACL_DB *acl_db, const char *db, my_bool db_is_pattern) +{ + return !acl_db->db || (db && !wild_compare(db, acl_db->db, db_is_pattern)); +} + + +/* + Lookup in the acl_users or acl_dbs for the best matching entry corresponding to + given user, host and ip parameters (also db, in case of ACL_DB) + + Historical note: + + In the past, both arrays were sorted just by ACL_ENTRY::sort field and were + searched linearly, until the first match of (username,host) pair was found. + + This function uses optimizations (binary search by username), yet preserves the + historical behavior, i.e the returns a match with highest ACL_ENTRY::sort. +*/ +template <typename T> T* find_by_username_or_anon(T* arr, size_t len, const char *user, + const char *host, const char *ip, + const char *db, my_bool db_is_pattern, bool (*match_db_func)(T*,const char *,my_bool)) +{ + size_t i; + T *ret = NULL; + + // Check entries matching user name. + size_t start = find_first_user(arr, len, user); + for (i= start; i < len; i++) + { + T *entry= &arr[i]; + if (i > start && strcmp(user, entry->get_username())) + break; + + if (compare_hostname(&entry->host, host, ip) && (!match_db_func || match_db_func(entry, db, db_is_pattern))) + { + ret= entry; + break; + } + } + + // Look also for anonymous user (username is empty string) + // Due to sort by name, entries for anonymous user start at the start of array. + for (i= 0; i < len; i++) + { + T *entry = &arr[i]; + if (*entry->get_username() || (ret && acl_compare(entry, ret) >= 0)) + break; + if (compare_hostname(&entry->host, host, ip) && (!match_db_func || match_db_func(entry, db, db_is_pattern))) + { + ret= entry; + break; + } + } + return ret; +} + +static ACL_DB *acl_db_find(const char *db, const char *user, const char *host, const char *ip, my_bool db_is_pattern) +{ + return find_by_username_or_anon(acl_dbs.front(), acl_dbs.elements(), + user, host, ip, db, db_is_pattern, match_db); +} + /* Gets user credentials without authentication and resource limit checks. @@ -2405,13 +2652,12 @@ bool acl_getroot(Security_context *sctx, const char *user, const char *host, const char *ip, const char *db) { int res= 1; - uint i; ACL_USER *acl_user= 0; DBUG_ENTER("acl_getroot"); DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', db: '%s'", host, ip, user, db)); - sctx->user= user; + sctx->user= *user ? user : NULL; sctx->host= host; sctx->ip= ip; sctx->host_or_ip= host ? host : (safe_str(ip)); @@ -2438,26 +2684,12 @@ bool acl_getroot(Security_context *sctx, const char *user, const char *host, if (acl_user) { res= 0; - for (i=0 ; i < acl_dbs.elements() ; i++) - { - ACL_DB *acl_db= &acl_dbs.at(i); - if (!acl_db->user || - (user && user[0] && !strcmp(user, acl_db->user))) - { - if (compare_hostname(&acl_db->host, host, ip)) - { - if (!acl_db->db || (db && !wild_compare(db, acl_db->db, 0))) - { - sctx->db_access= acl_db->access; - break; - } - } - } - } + if (ACL_DB *acl_db= acl_db_find(db, user, host, ip, FALSE)) + sctx->db_access= acl_db->access; + sctx->master_access= acl_user->access; - if (acl_user->user.str) - strmake_buf(sctx->priv_user, user); + strmake_buf(sctx->priv_user, user); if (acl_user->host.hostname) strmake_buf(sctx->priv_host, acl_user->host.hostname); @@ -2469,26 +2701,12 @@ bool acl_getroot(Security_context *sctx, const char *user, const char *host, if (acl_role) { res= 0; - for (i=0 ; i < acl_dbs.elements() ; i++) - { - ACL_DB *acl_db= &acl_dbs.at(i); - if (!acl_db->user || - (user && user[0] && !strcmp(user, acl_db->user))) - { - if (compare_hostname(&acl_db->host, "", "")) - { - if (!acl_db->db || (db && !wild_compare(db, acl_db->db, 0))) - { - sctx->db_access= acl_db->access; - break; - } - } - } - } + if (ACL_DB *acl_db= acl_db_find(db, user, "", "", FALSE)) + sctx->db_access = acl_db->access; + sctx->master_access= acl_role->access; - if (acl_role->user.str) - strmake_buf(sctx->priv_role, user); + strmake_buf(sctx->priv_role, user); } } @@ -2611,66 +2829,55 @@ static void acl_update_role(const char *rolename, ulong privileges) } -static void acl_update_user(const char *user, const char *host, - const char *password, size_t password_len, - enum SSL_type ssl_type, - const char *ssl_cipher, - const char *x509_issuer, - const char *x509_subject, - USER_RESOURCES *mqh, - ulong privileges, - const LEX_CSTRING *plugin, - const LEX_CSTRING *auth) +static int acl_user_update(THD *thd, ACL_USER *acl_user, const ACL_USER *from, + const LEX_USER &combo, enum SSL_type ssl_type, + const char *ssl_cipher, const char *x509_issuer, + const char *x509_subject, const USER_RESOURCES *mqh, + ulong privileges) { - mysql_mutex_assert_owner(&acl_cache->lock); + if (from) + *acl_user= *from; + else + { + bzero(acl_user, sizeof(*acl_user)); + acl_user->user= safe_lexcstrdup_root(&acl_memroot, combo.user); + update_hostname(&acl_user->host, safe_strdup_root(&acl_memroot, combo.host.str)); + acl_user->hostname_length= combo.host.length; + acl_user->sort= get_sort(2, acl_user->host.hostname, acl_user->user.str); + acl_user->plugin= native_password_plugin_name; + acl_user->salt= acl_user->auth_string= empty_clex_str; + my_init_dynamic_array(&acl_user->role_grants, sizeof(ACL_USER *), + 0, 8, MYF(0)); + } - for (uint i=0 ; i < acl_users.elements ; i++) + if (combo.plugin.length) { - ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*); - if (acl_user->eq(user, host)) - { - if (plugin->str[0]) - { - acl_user->plugin= *plugin; - acl_user->auth_string.str= auth->str ? - strmake_root(&acl_memroot, auth->str, auth->length) : const_cast<char*>(""); - acl_user->auth_string.length= auth->length; - if (fix_user_plugin_ptr(acl_user)) - acl_user->plugin.str= strmake_root(&acl_memroot, plugin->str, plugin->length); - } - else - if (password[0]) - { - acl_user->auth_string.str= strmake_root(&acl_memroot, password, password_len); - acl_user->auth_string.length= password_len; - set_user_salt(acl_user, password, password_len); - set_user_plugin(acl_user, password_len); - } - acl_user->access=privileges; - if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) - acl_user->user_resource.questions=mqh->questions; - if (mqh->specified_limits & USER_RESOURCES::UPDATES_PER_HOUR) - acl_user->user_resource.updates=mqh->updates; - if (mqh->specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR) - acl_user->user_resource.conn_per_hour= mqh->conn_per_hour; - if (mqh->specified_limits & USER_RESOURCES::USER_CONNECTIONS) - acl_user->user_resource.user_conn= mqh->user_conn; - if (mqh->specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) - acl_user->user_resource.max_statement_time= mqh->max_statement_time; - if (ssl_type != SSL_TYPE_NOT_SPECIFIED) - { - acl_user->ssl_type= ssl_type; - acl_user->ssl_cipher= (ssl_cipher ? strdup_root(&acl_memroot,ssl_cipher) : - 0); - acl_user->x509_issuer= (x509_issuer ? strdup_root(&acl_memroot,x509_issuer) : - 0); - acl_user->x509_subject= (x509_subject ? - strdup_root(&acl_memroot,x509_subject) : 0); - } - /* search complete: */ - break; - } + acl_user->plugin= combo.plugin; + acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, combo.auth); + if (fix_user_plugin_ptr(acl_user)) + acl_user->plugin= safe_lexcstrdup_root(&acl_memroot, combo.plugin); + if (set_user_auth(thd, acl_user, &combo.pwtext)) + return 1; } + acl_user->access= privileges; + if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) + acl_user->user_resource.questions= mqh->questions; + if (mqh->specified_limits & USER_RESOURCES::UPDATES_PER_HOUR) + acl_user->user_resource.updates= mqh->updates; + if (mqh->specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR) + acl_user->user_resource.conn_per_hour= mqh->conn_per_hour; + if (mqh->specified_limits & USER_RESOURCES::USER_CONNECTIONS) + acl_user->user_resource.user_conn= mqh->user_conn; + if (mqh->specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) + acl_user->user_resource.max_statement_time= mqh->max_statement_time; + if (ssl_type != SSL_TYPE_NOT_SPECIFIED) + { + acl_user->ssl_type= ssl_type; + acl_user->ssl_cipher= safe_strdup_root(&acl_memroot, ssl_cipher); + acl_user->x509_issuer= safe_strdup_root(&acl_memroot, safe_str(x509_issuer)); + acl_user->x509_subject= safe_strdup_root(&acl_memroot, safe_str(x509_subject)); + } + return 0; } @@ -2680,82 +2887,14 @@ static void acl_insert_role(const char *rolename, ulong privileges) mysql_mutex_assert_owner(&acl_cache->lock); entry= new (&acl_memroot) ACL_ROLE(rolename, privileges, &acl_memroot); - (void) my_init_dynamic_array(&entry->parent_grantee, - sizeof(ACL_USER_BASE *), 8, 8, MYF(0)); - (void) my_init_dynamic_array(&entry->role_grants,sizeof(ACL_ROLE *), - 8, 8, MYF(0)); + my_init_dynamic_array(&entry->parent_grantee, + sizeof(ACL_USER_BASE *), 0, 8, MYF(0)); + my_init_dynamic_array(&entry->role_grants, sizeof(ACL_ROLE *), 0, 8, MYF(0)); my_hash_insert(&acl_roles, (uchar *)entry); } -static void acl_insert_user(const char *user, const char *host, - const char *password, size_t password_len, - enum SSL_type ssl_type, - const char *ssl_cipher, - const char *x509_issuer, - const char *x509_subject, - USER_RESOURCES *mqh, - ulong privileges, - const LEX_CSTRING *plugin, - const LEX_CSTRING *auth) -{ - ACL_USER acl_user; - - mysql_mutex_assert_owner(&acl_cache->lock); - - bzero(&acl_user, sizeof(acl_user)); - acl_user.user.str=*user ? strdup_root(&acl_memroot,user) : 0; - acl_user.user.length= strlen(user); - update_hostname(&acl_user.host, safe_strdup_root(&acl_memroot, host)); - if (plugin->str[0]) - { - acl_user.plugin= *plugin; - acl_user.auth_string.str= auth->str ? - strmake_root(&acl_memroot, auth->str, auth->length) : const_cast<char*>(""); - acl_user.auth_string.length= auth->length; - if (fix_user_plugin_ptr(&acl_user)) - acl_user.plugin.str= strmake_root(&acl_memroot, plugin->str, plugin->length); - } - else - { - acl_user.auth_string.str= strmake_root(&acl_memroot, password, password_len); - acl_user.auth_string.length= password_len; - set_user_salt(&acl_user, password, password_len); - set_user_plugin(&acl_user, password_len); - } - - acl_user.flags= 0; - acl_user.access=privileges; - acl_user.user_resource = *mqh; - acl_user.sort=get_sort(2, acl_user.host.hostname, acl_user.user.str); - acl_user.hostname_length=(uint) strlen(host); - acl_user.ssl_type= (ssl_type != SSL_TYPE_NOT_SPECIFIED ? - ssl_type : SSL_TYPE_NONE); - acl_user.ssl_cipher= ssl_cipher ? strdup_root(&acl_memroot,ssl_cipher) : 0; - acl_user.x509_issuer= x509_issuer ? strdup_root(&acl_memroot,x509_issuer) : 0; - acl_user.x509_subject=x509_subject ? strdup_root(&acl_memroot,x509_subject) : 0; - (void) my_init_dynamic_array(&acl_user.role_grants, sizeof(ACL_USER *), - 8, 8, MYF(0)); - - (void) push_dynamic(&acl_users,(uchar*) &acl_user); - if (!acl_user.host.hostname || - (acl_user.host.hostname[0] == wild_many && !acl_user.host.hostname[1])) - allow_all_hosts=1; // Anyone can connect /* purecov: tested */ - my_qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, - sizeof(ACL_USER),(qsort_cmp) acl_compare); - - /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ - rebuild_check_host(); - - /* - Rebuild every user's role_grants since 'acl_users' has been sorted - and old pointers to ACL_USER elements are no longer valid - */ - rebuild_role_grants(); -} - - static bool acl_update_db(const char *user, const char *host, const char *db, ulong privileges) { @@ -2763,16 +2902,13 @@ static bool acl_update_db(const char *user, const char *host, const char *db, bool updated= false; - for (uint i=0 ; i < acl_dbs.elements() ; i++) + for (size_t i= acl_find_db_by_username(user); i < acl_dbs.elements(); i++) { ACL_DB *acl_db= &acl_dbs.at(i); - if ((!acl_db->user && !user[0]) || - (acl_db->user && - !strcmp(user,acl_db->user))) + if (!strcmp(user,acl_db->user)) { if ((!acl_db->host.hostname && !host[0]) || - (acl_db->host.hostname && - !strcmp(host, acl_db->host.hostname))) + (acl_db->host.hostname && !strcmp(host, acl_db->host.hostname))) { if ((!acl_db->db && !db[0]) || (acl_db->db && !strcmp(db,acl_db->db))) @@ -2789,6 +2925,8 @@ static bool acl_update_db(const char *user, const char *host, const char *db, } } } + else + break; } return updated; @@ -2820,7 +2958,7 @@ static void acl_insert_db(const char *user, const char *host, const char *db, acl_db.initial_access= acl_db.access= privileges; acl_db.sort=get_sort(3,acl_db.host.hostname,acl_db.db,acl_db.user); acl_dbs.push(acl_db); - acl_dbs.sort((acl_dbs_cmp)acl_compare); + rebuild_acl_dbs(); } @@ -2866,26 +3004,16 @@ ulong acl_get(const char *host, const char *ip, /* Check if there are some access rights for database and user */ - for (i=0 ; i < acl_dbs.elements() ; i++) + if (ACL_DB *acl_db= acl_db_find(db,user, host, ip, db_is_pattern)) { - ACL_DB *acl_db= &acl_dbs.at(i); - if (!acl_db->user || !strcmp(user,acl_db->user)) - { - if (compare_hostname(&acl_db->host,host,ip)) - { - if (!acl_db->db || !wild_compare(db,acl_db->db,db_is_pattern)) - { - db_access=acl_db->access; - if (acl_db->host.hostname) - goto exit; // Fully specified. Take it - /* the host table is not used for roles */ - if ((!host || !host[0]) && !acl_db->host.hostname && find_acl_role(user)) - goto exit; - break; /* purecov: tested */ - } - } - } + db_access= acl_db->access; + if (acl_db->host.hostname) + goto exit; // Fully specified. Take it + /* the host table is not used for roles */ + if ((!host || !host[0]) && !acl_db->host.hostname && find_acl_role(user)) + goto exit; } + if (!db_access) goto exit; // Can't be better @@ -3226,8 +3354,7 @@ bool check_change_password(THD *thd, LEX_USER *user) { LEX_USER *real_user= get_current_user(thd, user); - if (fix_and_copy_user(real_user, user, thd) || - validate_password(real_user, thd)) + if (fix_and_copy_user(real_user, user, thd)) return true; *user= *real_user; @@ -3248,7 +3375,7 @@ bool check_change_password(THD *thd, LEX_USER *user) */ bool change_password(THD *thd, LEX_USER *user) { - Grant_tables tables(Table_user, TL_WRITE); + Grant_tables tables; /* Buffer should be extended when password length is extended. */ char buff[512]; ulong query_length= 0; @@ -3257,8 +3384,8 @@ bool change_password(THD *thd, LEX_USER *user) const CSET_STRING query_save __attribute__((unused)) = thd->query_string; DBUG_ENTER("change_password"); DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", - user->host.str, user->user.str, user->pwhash.str)); - DBUG_ASSERT(user->host.str != 0); // Ensured by parent + user->host.str, user->user.str, user->auth.str)); + DBUG_ASSERT(user->host.str != 0); // Ensured by caller /* This statement will be replicated as a statement, even when using @@ -3269,21 +3396,10 @@ bool change_password(THD *thd, LEX_USER *user) */ save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); - if (mysql_bin_log.is_open() || - (WSREP(thd) && !IF_WSREP(thd->wsrep_applier, 0))) - { - query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'", - safe_str(user->user.str), safe_str(user->host.str), - safe_str(user->pwhash.str)); - } - if (WSREP(thd) && !IF_WSREP(thd->wsrep_applier, 0)) - { - thd->set_query(buff, query_length, system_charset_info); - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, (char*)"user", NULL); - } + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); - if ((result= tables.open_and_lock(thd))) + if ((result= tables.open_and_lock(thd, Table_user, TL_WRITE))) DBUG_RETURN(result != 1); result= 1; @@ -3298,25 +3414,21 @@ bool change_password(THD *thd, LEX_USER *user) goto end; } - /* update loaded acl entry: */ if (acl_user->plugin.str == native_password_plugin_name.str || acl_user->plugin.str == old_password_plugin_name.str) { - acl_user->auth_string.str= strmake_root(&acl_memroot, user->pwhash.str, user->pwhash.length); - acl_user->auth_string.length= user->pwhash.length; - set_user_salt(acl_user, user->pwhash.str, user->pwhash.length); + /* historical hack of auto-changing the plugin */ + acl_user->plugin= guess_auth_plugin(thd, user->auth.length); + } - set_user_plugin(acl_user, user->pwhash.length); + acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, user->auth); + if (set_user_auth(thd, acl_user, &user->pwtext)) + { + mysql_mutex_unlock(&acl_cache->lock); + goto end; } - else - push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_SET_PASSWORD_AUTH_PLUGIN, - ER_THD(thd, ER_SET_PASSWORD_AUTH_PLUGIN)); - if (update_user_table(thd, tables.user_table(), - safe_str(acl_user->host.hostname), - safe_str(acl_user->user.str), - user->pwhash.str, user->pwhash.length)) + if (update_user_table_password(thd, tables.user_table(), *acl_user)) { mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */ goto end; @@ -3327,6 +3439,8 @@ bool change_password(THD *thd, LEX_USER *user) result= 0; if (mysql_bin_log.is_open()) { + query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'", + user->user.str, safe_str(user->host.str), acl_user->auth_string.str); DBUG_ASSERT(query_length); thd->clear_error(); result= thd->binlog_query(THD::STMT_QUERY_TYPE, buff, query_length, @@ -3336,7 +3450,7 @@ end: close_mysql_tables(thd); #ifdef WITH_WSREP -WSREP_ERROR_LABEL: +wsrep_error_label: if (WSREP(thd) && !thd->wsrep_applier) { WSREP_TO_ISOLATION_END; @@ -3358,20 +3472,19 @@ int acl_check_set_default_role(THD *thd, const char *host, const char *user) int acl_set_default_role(THD *thd, const char *host, const char *user, const char *rolename) { - Grant_tables tables(Table_user, TL_WRITE); + Grant_tables tables; char user_key[MAX_KEY_LENGTH]; int result= 1; int error; ulong query_length= 0; bool clear_role= FALSE; char buff[512]; - enum_binlog_format save_binlog_format= - thd->get_current_stmt_binlog_format(); + enum_binlog_format save_binlog_format= thd->get_current_stmt_binlog_format(); const CSET_STRING query_save __attribute__((unused)) = thd->query_string; DBUG_ENTER("acl_set_default_role"); DBUG_PRINT("enter",("host: '%s' user: '%s' rolename: '%s'", - safe_str(user), safe_str(host), safe_str(rolename))); + user, safe_str(host), safe_str(rolename))); if (rolename == current_role.str) { if (!thd->security_ctx->priv_role[0]) @@ -3391,7 +3504,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, { query_length= sprintf(buff,"SET DEFAULT ROLE '%-.120s' FOR '%-.120s'@'%-.120s'", - safe_str(rolename), safe_str(user), safe_str(host)); + safe_str(rolename), user, safe_str(host)); } /* @@ -3407,7 +3520,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, { thd->set_query(buff, query_length, system_charset_info); // Attention!!! here is implicit goto error; - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, (char*)"user", NULL); + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); } /* @@ -3415,7 +3528,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, TODO(cvicentiu) Should move this block out in a new function. */ { - if ((result= tables.open_and_lock(thd))) + if ((result= tables.open_and_lock(thd, Table_user, TL_WRITE))) DBUG_RETURN(result != 1); const User_table& user_table= tables.user_table(); @@ -3448,17 +3561,8 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, /* update the mysql.user table with the new default role */ tables.user_table().table()->use_all_columns(); - if (!tables.user_table().default_role()) - { - my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), - table->alias.c_ptr(), DEFAULT_ROLE_COLUMN_IDX + 1, - tables.user_table().num_fields(), - static_cast<int>(table->s->mysql_version), MYSQL_VERSION_ID); - mysql_mutex_unlock(&acl_cache->lock); - goto end; - } - user_table.host()->store(host,(uint) strlen(host), system_charset_info); - user_table.user()->store(user,(uint) strlen(user), system_charset_info); + user_table.set_host(host, strlen(host)); + user_table.set_user(user, strlen(user)); key_copy((uchar *) user_key, table->record[0], table->key_info, table->key_info->key_length); @@ -3472,9 +3576,8 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, goto end; } store_record(table, record[1]); - user_table.default_role()->store(acl_user->default_rolename.str, - acl_user->default_rolename.length, - system_charset_info); + user_table.set_default_role(acl_user->default_rolename.str, + acl_user->default_rolename.length); if (unlikely(error= table->file->ha_update_row(table->record[1], table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) @@ -3499,7 +3602,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, } #ifdef WITH_WSREP -WSREP_ERROR_LABEL: +wsrep_error_label: if (WSREP(thd) && !thd->wsrep_applier) { WSREP_TO_ISOLATION_END; @@ -3555,34 +3658,27 @@ bool is_acl_user(const char *host, const char *user) */ static ACL_USER *find_user_or_anon(const char *host, const char *user, const char *ip) { - ACL_USER *result= NULL; - mysql_mutex_assert_owner(&acl_cache->lock); - for (uint i=0; i < acl_users.elements; i++) - { - ACL_USER *acl_user_tmp= dynamic_element(&acl_users, i, ACL_USER*); - if ((!acl_user_tmp->user.str || - !strcmp(user, acl_user_tmp->user.str)) && - compare_hostname(&acl_user_tmp->host, host, ip)) - { - result= acl_user_tmp; - break; - } - } - return result; + return find_by_username_or_anon<ACL_USER> + (reinterpret_cast<ACL_USER*>(acl_users.buffer), acl_users.elements, + user, host, ip, NULL, FALSE, NULL); } /* Find first entry that matches the specified user@host pair */ -static ACL_USER * find_user_exact(const char *host, const char *user) +static ACL_USER *find_user_exact(const char *host, const char *user) { mysql_mutex_assert_owner(&acl_cache->lock); + size_t start= acl_find_user_by_name(user); - for (uint i=0 ; i < acl_users.elements ; i++) + for (size_t i= start; i < acl_users.elements; i++) { - ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*); - if (acl_user->eq(user, host)) + ACL_USER *acl_user= dynamic_element(&acl_users, i, ACL_USER*); + if (i > start && strcmp(acl_user->user.str, user)) + return 0; + + if (!my_strcasecmp(system_charset_info, acl_user->host.hostname, host)) return acl_user; } return 0; @@ -3595,10 +3691,14 @@ static ACL_USER * find_user_wild(const char *host, const char *user, const char { mysql_mutex_assert_owner(&acl_cache->lock); - for (uint i=0 ; i < acl_users.elements ; i++) + size_t start = acl_find_user_by_name(user); + + for (size_t i= start; i < acl_users.elements; i++) { ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*); - if (acl_user->wild_eq(user, host, ip)) + if (i > start && strcmp(acl_user->user.str, user)) + break; + if (compare_hostname(&acl_user->host, host, ip ? ip : host)) return acl_user; } return 0; @@ -3616,7 +3716,7 @@ static ACL_ROLE *find_acl_role(const char *role) mysql_mutex_assert_owner(&acl_cache->lock); ACL_ROLE *r= (ACL_ROLE *)my_hash_search(&acl_roles, (uchar *)role, - safe_strlen(role)); + strlen(role)); DBUG_RETURN(r); } @@ -3768,53 +3868,23 @@ bool hostname_requires_resolving(const char *hostname) } -void set_authentication_plugin_from_password(const User_table& user_table, - const char* password, size_t password_length) -{ - if (password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH || - password_length == 0) - { - user_table.plugin()->store(native_password_plugin_name.str, - native_password_plugin_name.length, - system_charset_info); - } - else - { - DBUG_ASSERT(password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH_323); - user_table.plugin()->store(old_password_plugin_name.str, - old_password_plugin_name.length, - system_charset_info); - } - user_table.authentication_string()->store(password, - password_length, - system_charset_info); -} /** Update record for user in mysql.user privilege table with new password. - @param thd THD - @param table Pointer to TABLE object for open mysql.user table - @param host Hostname - @param user Username - @param new_password New password hash - @param new_password_len Length of new password hash - @see change_password */ -static bool update_user_table(THD *thd, const User_table& user_table, - const char *host, const char *user, - const char *new_password, size_t new_password_len) +static bool update_user_table_password(THD *thd, const User_table& user_table, + const ACL_USER &user) { char user_key[MAX_KEY_LENGTH]; int error; - DBUG_ENTER("update_user_table"); - DBUG_PRINT("enter",("user: %s host: %s",user,host)); + DBUG_ENTER("update_user_table_password"); TABLE *table= user_table.table(); table->use_all_columns(); - user_table.host()->store(host,(uint) strlen(host), system_charset_info); - user_table.user()->store(user,(uint) strlen(user), system_charset_info); + user_table.set_host(user.host.hostname, user.hostname_length); + user_table.set_user(user.user.str, user.user.length); key_copy((uchar *) user_key, table->record[0], table->key_info, table->key_info->key_length); @@ -3828,15 +3898,8 @@ static bool update_user_table(THD *thd, const User_table& user_table, } store_record(table,record[1]); - if (user_table.plugin()) - { - set_authentication_plugin_from_password(user_table, new_password, - new_password_len); - } - - if (user_table.password()) - user_table.password()->store(new_password, new_password_len, system_charset_info); - + user_table.set_auth(user.plugin.str, user.plugin.length, + user.auth_string.str, user.auth_string.length); if (unlikely(error= table->file->ha_update_row(table->record[1], table->record[0])) && @@ -3866,7 +3929,8 @@ static bool test_if_create_new_users(THD *thd) { TABLE_LIST tl; ulong db_access; - tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_USER_NAME, NULL, TL_WRITE); + tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLE_NAME[USER_TABLE], + NULL, TL_WRITE); create_new_users= 1; db_access=acl_get(sctx->host, sctx->ip, @@ -3888,7 +3952,7 @@ static bool test_if_create_new_users(THD *thd) ****************************************************************************/ static int replace_user_table(THD *thd, const User_table &user_table, - LEX_USER &combo, + LEX_USER *combo, ulong rights, bool revoke_grant, bool can_create_user, bool no_auto_create) { @@ -3896,40 +3960,17 @@ static int replace_user_table(THD *thd, const User_table &user_table, bool old_row_exists=0; char what= (revoke_grant) ? 'N' : 'Y'; uchar user_key[MAX_KEY_LENGTH]; - bool handle_as_role= combo.is_role(); + bool handle_as_role= combo->is_role(); LEX *lex= thd->lex; TABLE *table= user_table.table(); + ACL_USER new_acl_user, *old_acl_user; DBUG_ENTER("replace_user_table"); mysql_mutex_assert_owner(&acl_cache->lock); - if (combo.pwhash.str && combo.pwhash.str[0]) - { - if (combo.pwhash.length != SCRAMBLED_PASSWORD_CHAR_LENGTH && - combo.pwhash.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323) - { - DBUG_ASSERT(0); - my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH); - DBUG_RETURN(-1); - } - } - else - combo.pwhash= empty_clex_str; - - /* if the user table is not up to date, we can't handle role updates */ - if (!user_table.is_role() && handle_as_role) - { - my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), - "user", ROLE_ASSIGN_COLUMN_IDX + 1, user_table.num_fields(), - static_cast<int>(table->s->mysql_version), MYSQL_VERSION_ID); - DBUG_RETURN(-1); - } - table->use_all_columns(); - user_table.host()->store(combo.host.str,combo.host.length, - system_charset_info); - user_table.user()->store(combo.user.str,combo.user.length, - system_charset_info); + user_table.set_host(combo->host.str,combo->host.length); + user_table.set_user(combo->user.str,combo->user.length); key_copy(user_key, table->record[0], table->key_info, table->key_info->key_length); @@ -3940,7 +3981,7 @@ static int replace_user_table(THD *thd, const User_table &user_table, /* what == 'N' means revoke */ if (what == 'N') { - my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str); + my_error(ER_NONEXISTING_GRANT, MYF(0), combo->user.str, combo->host.str); goto end; } /* @@ -3956,7 +3997,8 @@ static int replace_user_table(THD *thd, const User_table &user_table, see also test_if_create_new_users() */ - else if (!combo.pwhash.length && !combo.plugin.length && no_auto_create) + else if (!combo->auth.length && !combo->plugin.length && + !combo->pwtext.length && no_auto_create) { my_error(ER_PASSWORD_NO_MATCH, MYF(0)); goto end; @@ -3966,161 +4008,115 @@ static int replace_user_table(THD *thd, const User_table &user_table, my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0)); goto end; } - else if (combo.plugin.str[0]) + else if (combo->plugin.length) { - if (!plugin_is_ready(&combo.plugin, MYSQL_AUTHENTICATION_PLUGIN)) + if (!plugin_is_ready(&combo->plugin, MYSQL_AUTHENTICATION_PLUGIN)) { - my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), combo.plugin.str); + my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), combo->plugin.str); goto end; } } + else /* combo->plugin.length == 0 */ + { + combo->plugin= guess_auth_plugin(thd, combo->auth.length); + } old_row_exists = 0; restore_record(table,s->default_values); - user_table.host()->store(combo.host.str,combo.host.length, - system_charset_info); - user_table.user()->store(combo.user.str,combo.user.length, - system_charset_info); + user_table.set_host(combo->host.str,combo->host.length); + user_table.set_user(combo->user.str,combo->user.length); } else { old_row_exists = 1; store_record(table,record[1]); // Save copy for update + if (!combo->plugin.length && (combo->auth.length || combo->pwtext.length)) + { + /* GRANT ... IDENTIFIED BY */ + combo->plugin= guess_auth_plugin(thd, combo->auth.length); + } } - if (!old_row_exists || combo.pwtext.length || combo.pwhash.length) - if (!handle_as_role && validate_password(&combo, thd)) - goto end; - /* Update table columns with new privileges */ - ulong priv; - priv = SELECT_ACL; - for (uint i= 0; i < user_table.num_privileges(); i++, priv <<= 1) + user_table.set_access(rights, revoke_grant); + rights= user_table.get_access(); + + if (handle_as_role) { - if (priv & rights) - user_table.priv_field(i)->store(&what, 1, &my_charset_latin1); + if (old_row_exists && !user_table.get_is_role()) + { + goto end; + } + if (user_table.set_is_role(true)) + { + my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), + user_table.name().str, + ROLE_ASSIGN_COLUMN_IDX + 1, user_table.num_fields(), + static_cast<int>(table->s->mysql_version), MYSQL_VERSION_ID); + goto end; + } } + else + { + old_acl_user= find_user_exact(combo->host.str, combo->user.str); + if ((old_acl_user != NULL) != old_row_exists) + { + my_error(ER_PASSWORD_NO_MATCH, MYF(0)); + goto end; + } + if (acl_user_update(thd, &new_acl_user, + old_row_exists ? old_acl_user : NULL, + *combo, lex->ssl_type, lex->ssl_cipher, + lex->x509_issuer, lex->x509_subject, &lex->mqh, + rights)) + goto end; - rights= user_table.get_access(); + user_table.set_auth(new_acl_user.plugin.str, new_acl_user.plugin.length, + new_acl_user.auth_string.str, new_acl_user.auth_string.length); - DBUG_PRINT("info",("table fields: %d", user_table.num_fields())); - /* If we don't have a password column, we'll use the authentication_string - column later. */ - if (combo.pwhash.str[0] && user_table.password()) - user_table.password()->store(combo.pwhash.str, combo.pwhash.length, - system_charset_info); - /* We either have the password column, the plugin column, or both. Otherwise - we have a corrupt user table. */ - DBUG_ASSERT(user_table.password() || user_table.plugin()); - if (user_table.ssl_type()) /* From 4.0.0 we have more fields */ - { - /* We write down SSL related ACL stuff */ switch (lex->ssl_type) { - case SSL_TYPE_ANY: - user_table.ssl_type()->store(STRING_WITH_LEN("ANY"), - &my_charset_latin1); - user_table.ssl_cipher()->store("", 0, &my_charset_latin1); - user_table.x509_issuer()->store("", 0, &my_charset_latin1); - user_table.x509_subject()->store("", 0, &my_charset_latin1); + case SSL_TYPE_NOT_SPECIFIED: break; + case SSL_TYPE_NONE: + case SSL_TYPE_ANY: case SSL_TYPE_X509: - user_table.ssl_type()->store(STRING_WITH_LEN("X509"), - &my_charset_latin1); - user_table.ssl_cipher()->store("", 0, &my_charset_latin1); - user_table.x509_issuer()->store("", 0, &my_charset_latin1); - user_table.x509_subject()->store("", 0, &my_charset_latin1); + user_table.set_ssl_type(lex->ssl_type); + user_table.set_ssl_cipher("", 0); + user_table.set_x509_issuer("", 0); + user_table.set_x509_subject("", 0); break; case SSL_TYPE_SPECIFIED: - user_table.ssl_type()->store(STRING_WITH_LEN("SPECIFIED"), - &my_charset_latin1); - user_table.ssl_cipher()->store("", 0, &my_charset_latin1); - user_table.x509_issuer()->store("", 0, &my_charset_latin1); - user_table.x509_subject()->store("", 0, &my_charset_latin1); + user_table.set_ssl_type(lex->ssl_type); if (lex->ssl_cipher) - user_table.ssl_cipher()->store(lex->ssl_cipher, - strlen(lex->ssl_cipher), - system_charset_info); + user_table.set_ssl_cipher(lex->ssl_cipher, strlen(lex->ssl_cipher)); + else + user_table.set_ssl_cipher("", 0); if (lex->x509_issuer) - user_table.x509_issuer()->store(lex->x509_issuer, - strlen(lex->x509_issuer), - system_charset_info); + user_table.set_x509_issuer(lex->x509_issuer, strlen(lex->x509_issuer)); + else + user_table.set_x509_issuer("", 0); if (lex->x509_subject) - user_table.x509_subject()->store(lex->x509_subject, - strlen(lex->x509_subject), - system_charset_info); - break; - case SSL_TYPE_NOT_SPECIFIED: - break; - case SSL_TYPE_NONE: - user_table.ssl_type()->store("", 0, &my_charset_latin1); - user_table.ssl_cipher()->store("", 0, &my_charset_latin1); - user_table.x509_issuer()->store("", 0, &my_charset_latin1); - user_table.x509_subject()->store("", 0, &my_charset_latin1); + user_table.set_x509_subject(lex->x509_subject, strlen(lex->x509_subject)); + else + user_table.set_x509_subject("", 0); break; } - USER_RESOURCES mqh= lex->mqh; - if (mqh.specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) - user_table.max_questions()->store((longlong) mqh.questions, TRUE); - if (mqh.specified_limits & USER_RESOURCES::UPDATES_PER_HOUR) - user_table.max_updates()->store((longlong) mqh.updates, TRUE); - if (mqh.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR) - user_table.max_connections()->store((longlong) mqh.conn_per_hour, TRUE); - if (user_table.max_user_connections() && - (mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS)) - user_table.max_user_connections()->store((longlong) mqh.user_conn, FALSE); - if (user_table.plugin()) - { - user_table.plugin()->set_notnull(); - user_table.authentication_string()->set_notnull(); - if (combo.plugin.str[0]) - { - DBUG_ASSERT(combo.pwhash.str[0] == 0); - if (user_table.password()) - user_table.password()->reset(); - user_table.plugin()->store(combo.plugin.str, combo.plugin.length, - system_charset_info); - user_table.authentication_string()->store(combo.auth.str, combo.auth.length, - system_charset_info); - } - if (combo.pwhash.str[0]) - { - DBUG_ASSERT(combo.plugin.str[0] == 0); - /* We have Password column. */ - if (user_table.password()) - { - user_table.plugin()->reset(); - user_table.authentication_string()->reset(); - } - else - { - /* We do not have Password column. Use PLUGIN && Authentication_string - columns instead. */ - set_authentication_plugin_from_password(user_table, - combo.pwhash.str, - combo.pwhash.length); - } - } + if (lex->mqh.specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) + user_table.set_max_questions(lex->mqh.questions); + if (lex->mqh.specified_limits & USER_RESOURCES::UPDATES_PER_HOUR) + user_table.set_max_updates(lex->mqh.updates); + if (lex->mqh.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR) + user_table.set_max_connections(lex->mqh.conn_per_hour); + if (lex->mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS) + user_table.set_max_user_connections(lex->mqh.user_conn); + if (lex->mqh.specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) + user_table.set_max_statement_time(lex->mqh.max_statement_time); - if (user_table.max_statement_time()) - { - if (mqh.specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) - user_table.max_statement_time()->store(mqh.max_statement_time); - } - } - mqh_used= (mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour || - mqh.user_conn || mqh.max_statement_time != 0.0); - - /* table format checked earlier */ - if (handle_as_role) - { - if (old_row_exists && !user_table.check_is_role()) - { - goto end; - } - user_table.is_role()->store("Y", 1, system_charset_info); - } + mqh_used= (mqh_used || lex->mqh.questions || lex->mqh.updates || + lex->mqh.conn_per_hour || lex->mqh.user_conn || + lex->mqh.max_statement_time != 0.0); } if (old_row_exists) @@ -4159,37 +4155,31 @@ end: if (likely(!error)) { acl_cache->clear(1); // Clear privilege cache - if (old_row_exists) + if (handle_as_role) { - if (handle_as_role) - acl_update_role(combo.user.str, rights); + if (old_row_exists) + acl_update_role(combo->user.str, rights); else - acl_update_user(combo.user.str, combo.host.str, - combo.pwhash.str, combo.pwhash.length, - lex->ssl_type, - lex->ssl_cipher, - lex->x509_issuer, - lex->x509_subject, - &lex->mqh, - rights, - &combo.plugin, - &combo.auth); + acl_insert_role(combo->user.str, rights); } else { - if (handle_as_role) - acl_insert_role(combo.user.str, rights); + if (old_acl_user) + *old_acl_user= new_acl_user; else - acl_insert_user(combo.user.str, combo.host.str, - combo.pwhash.str, combo.pwhash.length, - lex->ssl_type, - lex->ssl_cipher, - lex->x509_issuer, - lex->x509_subject, - &lex->mqh, - rights, - &combo.plugin, - &combo.auth); + { + push_new_user(new_acl_user); + rebuild_acl_users(); + + /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ + rebuild_check_host(); + + /* + Rebuild every user's role_grants since 'acl_users' has been sorted + and old pointers to ACL_USER elements are no longer valid + */ + rebuild_role_grants(); + } } } DBUG_RETURN(error); @@ -4497,6 +4487,13 @@ replace_proxies_priv_table(THD *thd, TABLE *table, const LEX_USER *user, DBUG_ENTER("replace_proxies_priv_table"); + if (!table) + { + my_error(ER_NO_SUCH_TABLE, MYF(0), MYSQL_SCHEMA_NAME.str, + MYSQL_TABLE_NAME[PROXIES_PRIV_TABLE].str); + DBUG_RETURN(-1); + } + /* Check if there is such a user in user table in memory? */ if (!find_user_wild(user->host.str,user->user.str)) { @@ -5294,6 +5291,13 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, HASH *hash= sph->get_priv_hash(); DBUG_ENTER("replace_routine_table"); + if (!table) + { + my_error(ER_NO_SUCH_TABLE, MYF(0), MYSQL_SCHEMA_NAME.str, + MYSQL_TABLE_NAME[PROCS_PRIV_TABLE].str); + DBUG_RETURN(-1); + } + if (revoke_grant && !grant_name->init_privs) // only inherited role privs { my_hash_delete(hash, (uchar*) grant_name); @@ -5889,22 +5893,29 @@ static bool merge_role_db_privileges(ACL_ROLE *grantee, const char *dbname, } update_flags|= update_role_db(merged, first, access, grantee->user.str); - /* - to make this code a bit simpler, we sort on deletes, to move - deleted elements to the end of the array. strictly speaking it's - unnecessary, it'd be faster to remove them in one O(N) array scan. - - on the other hand, qsort on almost sorted array is pretty fast anyway... - */ - if (update_flags & (2|4)) - { // inserted or deleted, need to sort - acl_dbs.sort((acl_dbs_cmp)acl_compare); - } if (update_flags & 4) - { // deleted, trim the end - while (acl_dbs.elements() && acl_dbs.back()->sort == 0) - acl_dbs.pop(); + { + // Remove elements marked for deletion. + uint count= 0; + for(uint i= 0; i < acl_dbs.elements(); i++) + { + ACL_DB *acl_db= &acl_dbs.at(i); + if (acl_db->sort) + { + if (i > count) + acl_dbs.set(count, *acl_db); + count++; + } + } + acl_dbs.elements(count); + } + + + if (update_flags & 2) + { // inserted, need to sort + rebuild_acl_dbs(); } + return update_flags; } @@ -6290,7 +6301,7 @@ static bool merge_one_role_privileges(ACL_ROLE *grantee) static bool has_auth(LEX_USER *user, LEX *lex) { - return user->pwtext.length || user->pwhash.length || user->plugin.length || user->auth.length || + return user->pwtext.length || user->plugin.length || user->auth.length || lex->ssl_type != SSL_TYPE_NOT_SPECIFIED || lex->ssl_cipher || lex->x509_issuer || lex->x509_subject || lex->mqh.specified_limits; @@ -6302,14 +6313,9 @@ static bool fix_and_copy_user(LEX_USER *to, LEX_USER *from, THD *thd) { /* preserve authentication information, if LEX_USER was reallocated */ to->pwtext= from->pwtext; - to->pwhash= from->pwhash; to->plugin= from->plugin; to->auth= from->auth; } - - if (fix_lex_user(thd, to)) - return true; - return false; } @@ -6428,10 +6434,10 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, Open the mysql.user and mysql.tables_priv tables. Don't open column table if we don't need it ! */ - int maybe_columns_priv= 0; + int tables_to_open= Table_user | Table_tables_priv; if (column_priv || (revoke_grant && ((rights & COL_ACLS) || columns.elements))) - maybe_columns_priv= Table_columns_priv; + tables_to_open|= Table_columns_priv; /* The lock api is depending on the thd->lex variable which needs to be @@ -6446,9 +6452,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, */ thd->lex->sql_command= backup.sql_command; - Grant_tables tables(Table_user | Table_tables_priv | maybe_columns_priv, - TL_WRITE); - if ((result= tables.open_and_lock(thd))) + Grant_tables tables; + if ((result= tables.open_and_lock(thd, tables_to_open, TL_WRITE))) { thd->lex->restore_backup_query_tables_list(&backup); DBUG_RETURN(result != 1); @@ -6473,7 +6478,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, } /* Create user if needed */ error= copy_and_check_auth(Str, tmp_Str, thd) || - replace_user_table(thd, tables.user_table(), *Str, + replace_user_table(thd, tables.user_table(), Str, 0, revoke_grant, create_new_users, MY_TEST(thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER)); @@ -6627,8 +6632,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(TRUE); } - Grant_tables tables(Table_user | Table_procs_priv, TL_WRITE); - if ((result= tables.open_and_lock(thd))) + Grant_tables tables; + if ((result= tables.open_and_lock(thd, Table_user | Table_procs_priv, TL_WRITE))) DBUG_RETURN(result != 1); DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); @@ -6652,7 +6657,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, } /* Create user if needed */ if (copy_and_check_auth(Str, tmp_Str, thd) || - replace_user_table(thd, tables.user_table(), *Str, + replace_user_table(thd, tables.user_table(), Str, 0, revoke_grant, create_new_users, MY_TEST(thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER))) @@ -6685,12 +6690,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, } } - /* TODO(cvicentiu) refactor replace_routine_table to use Tables_procs_priv - instead of TABLE directly. */ - if (tables.procs_priv_table().no_such_table() || - replace_routine_table(thd, grant_name, tables.procs_priv_table().table(), - *Str, db_name, table_name, sph, rights, - revoke_grant) != 0) + if (replace_routine_table(thd, grant_name, tables.procs_priv_table().table(), + *Str, db_name, table_name, sph, rights, revoke_grant) != 0) { result= TRUE; continue; @@ -6828,8 +6829,8 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) no_auto_create_user= MY_TEST(thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER); - Grant_tables tables(Table_user | Table_roles_mapping, TL_WRITE); - if ((result= tables.open_and_lock(thd))) + Grant_tables tables; + if ((result= tables.open_and_lock(thd, Table_user | Table_roles_mapping, TL_WRITE))) DBUG_RETURN(result != 1); mysql_rwlock_wrlock(&LOCK_grant); @@ -6928,7 +6929,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) user_combo.user = username; if (copy_and_check_auth(&user_combo, &user_combo, thd) || - replace_user_table(thd, tables.user_table(), user_combo, 0, + replace_user_table(thd, tables.user_table(), &user_combo, 0, false, create_new_user, no_auto_create_user)) { @@ -7067,9 +7068,9 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, proxied_user= str_list++; } - Grant_tables tables(Table_user | (is_proxy ? Table_proxies_priv : Table_db), - TL_WRITE); - if ((result= tables.open_and_lock(thd))) + const uint tables_to_open= Table_user | (is_proxy ? Table_proxies_priv : Table_db); + Grant_tables tables; + if ((result= tables.open_and_lock(thd, tables_to_open, TL_WRITE))) DBUG_RETURN(result != 1); DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); @@ -7098,7 +7099,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, } if (copy_and_check_auth(Str, tmp_Str, thd) || - replace_user_table(thd, tables.user_table(), *Str, + replace_user_table(thd, tables.user_table(), Str, (!db ? rights : 0), revoke_grant, create_new_users, MY_TEST(thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER))) @@ -7120,13 +7121,8 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, } else if (is_proxy) { - /* TODO(cvicentiu) refactor replace_proxies_priv_table to use - Proxies_priv_table instead of TABLE directly. */ - if (tables.proxies_priv_table().no_such_table() || - replace_proxies_priv_table (thd, tables.proxies_priv_table().table(), - Str, proxied_user, - rights & GRANT_ACL ? TRUE : FALSE, - revoke_grant)) + if (replace_proxies_priv_table(thd, tables.proxies_priv_table().table(), + Str, proxied_user, rights & GRANT_ACL ? TRUE : FALSE, revoke_grant)) result= true; } if (Str->is_role()) @@ -7262,8 +7258,7 @@ static bool grant_load(THD *thd, { sql_print_warning("'tables_priv' entry '%s %s@%s' " "ignored in --skip-name-resolve mode.", - mem_check->tname, - safe_str(mem_check->user), + mem_check->tname, mem_check->user, safe_str(mem_check->host.hostname)); continue; } @@ -7389,9 +7384,9 @@ bool grant_reload(THD *thd) obtaining LOCK_grant rwlock. */ - Grant_tables tables(Table_tables_priv | Table_columns_priv| Table_procs_priv, - TL_READ); - if ((result= tables.open_and_lock(thd))) + Grant_tables tables; + const uint tables_to_open= Table_tables_priv | Table_columns_priv| Table_procs_priv; + if ((result= tables.open_and_lock(thd, tables_to_open, TL_READ))) DBUG_RETURN(result != 1); mysql_rwlock_wrlock(&LOCK_grant); @@ -8348,7 +8343,6 @@ static void add_user_parameters(String *result, ACL_USER* acl_user, { if (acl_user->auth_string.length) { - DBUG_ASSERT(acl_user->salt_len); result->append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); result->append(&acl_user->auth_string); result->append('\''); @@ -8374,14 +8368,14 @@ static void add_user_parameters(String *result, ACL_USER* acl_user, { int ssl_options = 0; result->append(STRING_WITH_LEN(" REQUIRE ")); - if (acl_user->x509_issuer) + if (acl_user->x509_issuer[0]) { ssl_options++; result->append(STRING_WITH_LEN("ISSUER \'")); result->append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); result->append('\''); } - if (acl_user->x509_subject) + if (acl_user->x509_subject[0]) { if (ssl_options++) result->append(' '); @@ -8866,7 +8860,7 @@ static bool show_database_privileges(THD *thd, const char *username, const char *user, *host; ACL_DB *acl_db= &acl_dbs.at(i); - user= safe_str(acl_db->user); + user= acl_db->user; host=acl_db->host.hostname; /* @@ -8952,7 +8946,7 @@ static bool show_table_and_column_privileges(THD *thd, const char *username, GRANT_TABLE *grant_table= (GRANT_TABLE*) my_hash_element(&column_priv_hash, index); - user= safe_str(grant_table->user); + user= grant_table->user; host= grant_table->host.hostname; /* @@ -9094,7 +9088,7 @@ static int show_routine_grants(THD* thd, const char *user, *host; GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, index); - user= safe_str(grant_proc->user); + user= grant_proc->user; host= grant_proc->host.hostname; /* @@ -9442,7 +9436,7 @@ static int handle_grant_table(THD *thd, const Grant_table_base& grant_table, if (!unlikely(error) && !*host_str) { // verify that we got a role or a user, as needed - if (static_cast<const User_table&>(grant_table).check_is_role() != + if (static_cast<const User_table&>(grant_table).get_is_role() != user_from->is_role()) error= HA_ERR_KEY_NOT_FOUND; } @@ -9606,8 +9600,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, my_hash_delete(&acl_roles, (uchar*) acl_role); DBUG_RETURN(1); } - acl_role->user.str= strdup_root(&acl_memroot, user_to->user.str); - acl_role->user.length= user_to->user.length; + acl_role->user= safe_lexcstrdup_root(&acl_memroot, user_to->user); my_hash_update(&acl_roles, (uchar*) acl_role, (uchar*) old_key, old_key_length); @@ -9703,8 +9696,6 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, default: DBUG_ASSERT(0); } - if (! user) - user= ""; if (! host) host= ""; @@ -9798,8 +9789,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, { switch ( struct_no ) { case USER_ACL: - acl_user->user.str= strdup_root(&acl_memroot, user_to->user.str); - acl_user->user.length= user_to->user.length; + acl_user->user= safe_lexcstrdup_root(&acl_memroot, user_to->user); update_hostname(&acl_user->host, strdup_root(&acl_memroot, user_to->host.str)); acl_user->hostname_length= strlen(acl_user->host.hostname); break; @@ -10146,11 +10136,11 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) DBUG_RETURN(TRUE); /* CREATE USER may be skipped on replication client. */ - Grant_tables tables(Table_user | Table_db | - Table_tables_priv | Table_columns_priv | - Table_procs_priv | Table_proxies_priv | - Table_roles_mapping, TL_WRITE); - if ((result= tables.open_and_lock(thd))) + Grant_tables tables; + const uint tables_to_open= Table_user | Table_db | Table_tables_priv | + Table_columns_priv | Table_procs_priv | + Table_proxies_priv | Table_roles_mapping; + if ((result= tables.open_and_lock(thd, tables_to_open, TL_WRITE))) DBUG_RETURN(result != 1); mysql_rwlock_wrlock(&LOCK_grant); @@ -10182,13 +10172,6 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) if (!user_name->host.str) user_name->host= host_not_specified; - if (fix_lex_user(thd, user_name)) - { - append_user(thd, &wrong_users, user_name); - result= TRUE; - continue; - } - /* Search all in-memory structures and grant tables for a mention of the new user/role name. @@ -10231,7 +10214,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) } } - if (replace_user_table(thd, tables.user_table(), *user_name, 0, 0, 1, 0)) + if (replace_user_table(thd, tables.user_table(), user_name, 0, 0, 1, 0)) { append_user(thd, &wrong_users, user_name); result= TRUE; @@ -10312,11 +10295,11 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) DBUG_PRINT("entry", ("Handle as %s", handle_as_role ? "role" : "user")); /* DROP USER may be skipped on replication client. */ - Grant_tables tables(Table_user | Table_db | - Table_tables_priv | Table_columns_priv | - Table_procs_priv | Table_proxies_priv | - Table_roles_mapping, TL_WRITE); - if ((result= tables.open_and_lock(thd))) + Grant_tables tables; + const uint tables_to_open= Table_user | Table_db | Table_tables_priv | + Table_columns_priv | Table_procs_priv | + Table_proxies_priv | Table_roles_mapping; + if ((result= tables.open_and_lock(thd, tables_to_open, TL_WRITE))) DBUG_RETURN(result != 1); thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH; @@ -10422,11 +10405,11 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) DBUG_ENTER("mysql_rename_user"); /* RENAME USER may be skipped on replication client. */ - Grant_tables tables(Table_user | Table_db | - Table_tables_priv | Table_columns_priv | - Table_procs_priv | Table_proxies_priv | - Table_roles_mapping, TL_WRITE); - if ((result= tables.open_and_lock(thd))) + Grant_tables tables; + const uint tables_to_open= Table_user | Table_db | Table_tables_priv | + Table_columns_priv | Table_procs_priv | + Table_proxies_priv | Table_roles_mapping; + if ((result= tables.open_and_lock(thd, tables_to_open, TL_WRITE))) DBUG_RETURN(result != 1); DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); @@ -10465,8 +10448,12 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) continue; } some_users_renamed= TRUE; + rebuild_acl_users(); } + /* Rebuild 'acl_dbs' since 'acl_users' has been modified */ + rebuild_acl_dbs(); + /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ rebuild_check_host(); @@ -10507,8 +10494,8 @@ int mysql_alter_user(THD* thd, List<LEX_USER> &users_list) String wrong_users; /* The only table we're altering is the user table. */ - Grant_tables tables(Table_user, TL_WRITE); - if ((result= tables.open_and_lock(thd))) + Grant_tables tables; + if ((result= tables.open_and_lock(thd, Table_user, TL_WRITE))) DBUG_RETURN(result != 1); /* Lock ACL data structures until we finish altering all users. */ @@ -10520,10 +10507,8 @@ int mysql_alter_user(THD* thd, List<LEX_USER> &users_list) while ((tmp_lex_user= users_list_iterator++)) { LEX_USER* lex_user= get_current_user(thd, tmp_lex_user, false); - if (!lex_user || - fix_lex_user(thd, lex_user) || - replace_user_table(thd, tables.user_table(), *lex_user, 0, - false, false, true)) + if (!lex_user || replace_user_table(thd, tables.user_table(), lex_user, 0, + false, false, true)) { thd->clear_error(); append_user(thd, &wrong_users, tmp_lex_user); @@ -10559,9 +10544,7 @@ int mysql_alter_user(THD* thd, List<LEX_USER> &users_list) static bool -mysql_revoke_sp_privs(THD *thd, - Grant_tables *tables, - const Sp_handler *sph, +mysql_revoke_sp_privs(THD *thd, Grant_tables *tables, const Sp_handler *sph, const LEX_USER *lex_user) { bool rc= false; @@ -10572,7 +10555,7 @@ mysql_revoke_sp_privs(THD *thd, { const char *user,*host; GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, counter); - user= safe_str(grant_proc->user); + user= grant_proc->user; host= safe_str(grant_proc->host.hostname); if (!strcmp(lex_user->user.str, user) && @@ -10617,11 +10600,11 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) ACL_DB *acl_db; DBUG_ENTER("mysql_revoke_all"); - Grant_tables tables(Table_user | Table_db | - Table_tables_priv | Table_columns_priv | - Table_procs_priv | Table_proxies_priv | - Table_roles_mapping, TL_WRITE); - if ((result= tables.open_and_lock(thd))) + Grant_tables tables; + const uint tables_to_open= Table_user | Table_db | Table_tables_priv | + Table_columns_priv | Table_procs_priv | + Table_proxies_priv | Table_roles_mapping; + if ((result= tables.open_and_lock(thd, tables_to_open, TL_WRITE))) DBUG_RETURN(result != 1); DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); @@ -10647,7 +10630,7 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) continue; } - if (replace_user_table(thd, tables.user_table(), *lex_user, + if (replace_user_table(thd, tables.user_table(), lex_user, ~(ulong)0, 1, 0, 0)) { result= -1; @@ -10664,11 +10647,11 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) { for (counter= 0, revoked= 0 ; counter < acl_dbs.elements() ; ) { - const char *user,*host; + const char *user, *host; - acl_db=&acl_dbs.at(counter); + acl_db= &acl_dbs.at(counter); - user= safe_str(acl_db->user); + user= acl_db->user; host= safe_str(acl_db->host.hostname); if (!strcmp(lex_user->user.str, user) && @@ -10700,7 +10683,7 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) const char *user,*host; GRANT_TABLE *grant_table= (GRANT_TABLE*) my_hash_element(&column_priv_hash, counter); - user= safe_str(grant_table->user); + user= grant_table->user; host= safe_str(grant_table->host.hostname); if (!strcmp(lex_user->user.str,user) && @@ -10905,11 +10888,11 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, Silence_routine_definer_errors error_handler; DBUG_ENTER("sp_revoke_privileges"); - Grant_tables tables(Table_user | Table_db | - Table_tables_priv | Table_columns_priv | - Table_procs_priv | Table_proxies_priv | - Table_roles_mapping, TL_WRITE); - if ((result= tables.open_and_lock(thd))) + Grant_tables tables; + const uint tables_to_open= Table_user | Table_db | Table_tables_priv | + Table_columns_priv | Table_procs_priv | + Table_proxies_priv | Table_roles_mapping; + if ((result= tables.open_and_lock(thd, tables_to_open, TL_WRITE))) DBUG_RETURN(result != 1); DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); @@ -11318,7 +11301,7 @@ bool check_role_is_granted(const char *username, ACL_USER_BASE *root; mysql_mutex_lock(&acl_cache->lock); if (hostname) - root= find_user_exact(username, hostname); + root= find_user_exact(hostname, username); else root= find_acl_role(username); @@ -11492,7 +11475,7 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) { const char *user,*host, *is_grantable="YES"; acl_user=dynamic_element(&acl_users,counter,ACL_USER*); - user= safe_str(acl_user->user.str); + user= acl_user->user.str; host= safe_str(acl_user->host.hostname); if (no_global_access && @@ -11566,7 +11549,7 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) const char *user, *host, *is_grantable="YES"; acl_db=&acl_dbs.at(counter); - user= safe_str(acl_db->user); + user= acl_db->user; host= safe_str(acl_db->host.hostname); if (no_global_access && @@ -11638,7 +11621,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) const char *user, *host, *is_grantable= "YES"; GRANT_TABLE *grant_table= (GRANT_TABLE*) my_hash_element(&column_priv_hash, index); - user= safe_str(grant_table->user); + user= grant_table->user; host= safe_str(grant_table->host.hostname); if (no_global_access && @@ -11720,7 +11703,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) const char *user, *host, *is_grantable= "YES"; GRANT_TABLE *grant_table= (GRANT_TABLE*) my_hash_element(&column_priv_hash, index); - user= safe_str(grant_table->user); + user= grant_table->user; host= safe_str(grant_table->host.hostname); if (no_global_access && @@ -12304,8 +12287,9 @@ static bool send_plugin_request_packet(MPVIO_EXT *mpvio, user account, it's the plugin that the client need to use to login. */ bool switch_from_long_to_short_scramble= - native_password_plugin_name.str == mpvio->cached_client_reply.plugin && - client_auth_plugin == old_password_plugin_name.str; + client_auth_plugin == old_password_plugin_name.str && + my_strcasecmp(system_charset_info, mpvio->cached_client_reply.plugin, + native_password_plugin_name.str) == 0; if (switch_from_long_to_short_scramble) DBUG_RETURN (secure_auth(mpvio->auth_info.thd) || @@ -12318,8 +12302,9 @@ static bool send_plugin_request_packet(MPVIO_EXT *mpvio, ask an old 4.0 client to use the new 4.1 authentication protocol. */ bool switch_from_short_to_long_scramble= - old_password_plugin_name.str == mpvio->cached_client_reply.plugin && - client_auth_plugin == native_password_plugin_name.str; + client_auth_plugin == native_password_plugin_name.str && + my_strcasecmp(system_charset_info, mpvio->cached_client_reply.plugin, + old_password_plugin_name.str) == 0; if (switch_from_short_to_long_scramble) { @@ -12409,9 +12394,9 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio) mpvio->auth_info.user_name= sctx->user; mpvio->auth_info.user_name_length= (uint)strlen(sctx->user); - mpvio->auth_info.auth_string= mpvio->acl_user->auth_string.str; - mpvio->auth_info.auth_string_length= (unsigned long) mpvio->acl_user->auth_string.length; - strmake_buf(mpvio->auth_info.authenticated_as, safe_str(mpvio->acl_user->user.str)); + mpvio->auth_info.auth_string= mpvio->acl_user->salt.str; + mpvio->auth_info.auth_string_length= (unsigned long) mpvio->acl_user->salt.length; + strmake_buf(mpvio->auth_info.authenticated_as, mpvio->acl_user->user.str); DBUG_PRINT("info", ("exit: user=%s, auth_string=%s, authenticated as=%s" "plugin=%s", @@ -12562,7 +12547,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) MYF(0)); DBUG_RETURN(1); } - client_plugin= fix_plugin_ptr(next_field); + client_plugin= next_field; next_field+= strlen(next_field) + 1; } else @@ -12656,7 +12641,12 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, return packet_error; DBUG_PRINT("info", ("IO layer change in progress...")); - if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, &errptr)) + mysql_rwlock_rdlock(&LOCK_ssl_refresh); + int ssl_ret = sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, &errptr); + mysql_rwlock_unlock(&LOCK_ssl_refresh); + ssl_acceptor_stats_update(ssl_ret); + + if(ssl_ret) { DBUG_PRINT("error", ("Failed to accept new SSL connection")); return packet_error; @@ -12807,7 +12797,6 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, if ((thd->client_capabilities & CLIENT_PLUGIN_AUTH) && (client_plugin < (char *)net->read_pos + pkt_len)) { - client_plugin= fix_plugin_ptr(client_plugin); next_field+= strlen(next_field) + 1; } else @@ -13076,24 +13065,25 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user) return 1; if (acl_user->ssl_cipher) { + const char *ssl_cipher= SSL_get_cipher(ssl); DBUG_PRINT("info", ("comparing ciphers: '%s' and '%s'", - acl_user->ssl_cipher, SSL_get_cipher(ssl))); - if (strcmp(acl_user->ssl_cipher, SSL_get_cipher(ssl))) + acl_user->ssl_cipher, ssl_cipher)); + if (strcmp(acl_user->ssl_cipher, ssl_cipher)) { if (global_system_variables.log_warnings) sql_print_information("X509 ciphers mismatch: should be '%s' but is '%s'", - acl_user->ssl_cipher, SSL_get_cipher(ssl)); + acl_user->ssl_cipher, ssl_cipher); return 1; } } - if (!acl_user->x509_issuer && !acl_user->x509_subject) + if (!acl_user->x509_issuer[0] && !acl_user->x509_subject[0]) return 0; // all done /* Prepare certificate (if exists) */ if (!(cert= SSL_get_peer_certificate(ssl))) return 1; /* If X509 issuer is specified, we check it... */ - if (acl_user->x509_issuer) + if (acl_user->x509_issuer[0]) { char *ptr= X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); DBUG_PRINT("info", ("comparing issuers: '%s' and '%s'", @@ -13110,7 +13100,7 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user) free(ptr); } /* X509 subject is specified, we check it .. */ - if (acl_user->x509_subject) + if (acl_user->x509_subject[0]) { char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); DBUG_PRINT("info", ("comparing subjects: '%s' and '%s'", @@ -13146,17 +13136,7 @@ static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name, { int res= CR_OK, old_status= MPVIO_EXT::FAILURE; bool unlock_plugin= false; - plugin_ref plugin= NULL; - - if (auth_plugin_name->str == native_password_plugin_name.str) - plugin= native_password_plugin; -#ifndef EMBEDDED_LIBRARY - else if (auth_plugin_name->str == old_password_plugin_name.str) - plugin= old_password_plugin; - else if ((plugin= my_plugin_lock_by_name(thd, auth_plugin_name, - MYSQL_AUTHENTICATION_PLUGIN))) - unlock_plugin= true; -#endif + plugin_ref plugin= get_auth_plugin(thd, *auth_plugin_name, &unlock_plugin); mpvio->plugin= plugin; old_status= mpvio->status; @@ -13344,7 +13324,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) { #ifndef NO_EMBEDDED_ACCESS_CHECKS bool is_proxy_user= FALSE; - const char *auth_user = safe_str(acl_user->user.str); + const char *auth_user = acl_user->user.str; ACL_PROXY_USER *proxy_user; /* check if the user is allowed to proxy as another user */ proxy_user= acl_find_proxy_user(auth_user, sctx->host, sctx->ip, @@ -13390,10 +13370,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) #endif sctx->master_access= acl_user->access; - if (acl_user->user.str) - strmake_buf(sctx->priv_user, acl_user->user.str); - else - *sctx->priv_user= 0; + strmake_buf(sctx->priv_user, acl_user->user.str); if (acl_user->host.hostname) strmake_buf(sctx->priv_host, acl_user->host.hostname); @@ -13605,15 +13582,16 @@ static int native_password_authenticate(MYSQL_PLUGIN_VIO *vio, DBUG_EXECUTE_IF("native_password_bad_reply", { pkt_len= 12; }); if (pkt_len == 0) /* no password */ - DBUG_RETURN(mpvio->acl_user->salt_len != 0 ? CR_AUTH_USER_CREDENTIALS : CR_OK); + DBUG_RETURN(info->auth_string_length != 0 + ? CR_AUTH_USER_CREDENTIALS : CR_OK); info->password_used= PASSWORD_USED_YES; if (pkt_len == SCRAMBLE_LENGTH) { - if (!mpvio->acl_user->salt_len) + if (!info->auth_string_length) DBUG_RETURN(CR_AUTH_USER_CREDENTIALS); - if (check_scramble(pkt, thd->scramble, mpvio->acl_user->salt)) + if (check_scramble(pkt, thd->scramble, (uchar*)info->auth_string)) DBUG_RETURN(CR_AUTH_USER_CREDENTIALS); else DBUG_RETURN(CR_OK); @@ -13623,6 +13601,41 @@ static int native_password_authenticate(MYSQL_PLUGIN_VIO *vio, DBUG_RETURN(CR_AUTH_HANDSHAKE); } +static int native_password_make_scramble(const char *password, + size_t password_length, char *hash, size_t *hash_length) +{ + DBUG_ASSERT(*hash_length >= SCRAMBLED_PASSWORD_CHAR_LENGTH); + if (password_length == 0) + *hash_length= 0; + else + { + *hash_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; + my_make_scrambled_password(hash, password, password_length); + } + return 0; +} + +static int native_password_get_salt(const char *hash, size_t hash_length, + unsigned char *out, size_t *out_length) +{ + DBUG_ASSERT(*out_length >= SCRAMBLE_LENGTH); + if (hash_length == 0) + { + *out_length= 0; + return 0; + } + + if (hash_length != SCRAMBLED_PASSWORD_CHAR_LENGTH) + { + my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH); + return 1; + } + + *out_length= SCRAMBLE_LENGTH; + get_salt_from_password(out, hash); + return 0; +} + static int old_password_authenticate(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { @@ -13657,7 +13670,7 @@ static int old_password_authenticate(MYSQL_PLUGIN_VIO *vio, pkt_len= (int)strnlen((char*)pkt, pkt_len); if (pkt_len == 0) /* no password */ - return info->auth_string[0] ? CR_AUTH_USER_CREDENTIALS : CR_OK; + return info->auth_string_length ? CR_AUTH_USER_CREDENTIALS : CR_OK; if (secure_auth(thd)) return CR_AUTH_HANDSHAKE; @@ -13666,30 +13679,64 @@ static int old_password_authenticate(MYSQL_PLUGIN_VIO *vio, if (pkt_len == SCRAMBLE_LENGTH_323) { - if (!mpvio->acl_user->salt_len) + if (!info->auth_string_length) return CR_AUTH_USER_CREDENTIALS; - return check_scramble_323(pkt, thd->scramble, - (ulong *) mpvio->acl_user->salt) ? - CR_AUTH_USER_CREDENTIALS : CR_OK; + return check_scramble_323(pkt, thd->scramble, (ulong *) info->auth_string) + ? CR_AUTH_USER_CREDENTIALS : CR_OK; } my_error(ER_HANDSHAKE_ERROR, MYF(0)); return CR_AUTH_HANDSHAKE; } +static int old_password_make_scramble(const char *password, + size_t password_length, char *hash, size_t *hash_length) +{ + DBUG_ASSERT(*hash_length >= SCRAMBLED_PASSWORD_CHAR_LENGTH_323); + if (password_length == 0) + *hash_length= 0; + else + { + *hash_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; + my_make_scrambled_password_323(hash, password, password_length); + } + return 0; +} + +#define SALT_LENGTH_323 (sizeof(ulong)*2) +static int old_password_get_salt(const char *hash, size_t hash_length, + unsigned char *out, size_t *out_length) +{ + DBUG_ASSERT(*out_length >= SALT_LENGTH_323); + + if (hash_length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323) + { + my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH_323); + return 1; + } + + *out_length= SALT_LENGTH_323; + get_salt_from_password_323((ulong*)out, hash); + return 0; +} + static struct st_mysql_auth native_password_handler= { MYSQL_AUTHENTICATION_INTERFACE_VERSION, native_password_plugin_name.str, - native_password_authenticate + native_password_authenticate, + native_password_make_scramble, + native_password_get_salt }; static struct st_mysql_auth old_password_handler= { MYSQL_AUTHENTICATION_INTERFACE_VERSION, old_password_plugin_name.str, - old_password_authenticate + old_password_authenticate, + old_password_make_scramble, + old_password_get_salt }; maria_declare_plugin(mysql_password) diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index c17567e6a89..b39103e382a 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -306,7 +306,7 @@ static bool open_only_one_table(THD* thd, TABLE_LIST* table, bool is_view_operator_func) { LEX *lex= thd->lex; - SELECT_LEX *select= &lex->select_lex; + SELECT_LEX *select= lex->first_select_lex(); TABLE_LIST *save_next_global, *save_next_local; bool open_error; save_next_global= table->next_global; @@ -767,7 +767,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, } collect_eis= (table->table->s->table_category == TABLE_CATEGORY_USER && - (get_use_stat_tables_mode(thd) > NEVER || + (check_eits_collection_allowed(thd) || lex->with_persistent_for_clause)); @@ -1301,7 +1301,7 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables) bool Sql_cmd_analyze_table::execute(THD *thd) { LEX *m_lex= thd->lex; - TABLE_LIST *first_table= m_lex->select_lex.table_list.first; + TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first; bool res= TRUE; thr_lock_type lock_type = TL_READ_NO_INSERT; DBUG_ENTER("Sql_cmd_analyze_table::execute"); @@ -1321,11 +1321,13 @@ bool Sql_cmd_analyze_table::execute(THD *thd) */ res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } - m_lex->select_lex.table_list.first= first_table; + m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; error: -WSREP_ERROR_LABEL: +#ifdef WITH_WSREP +wsrep_error_label: +#endif DBUG_RETURN(res); } @@ -1333,7 +1335,7 @@ WSREP_ERROR_LABEL: bool Sql_cmd_check_table::execute(THD *thd) { LEX *m_lex= thd->lex; - TABLE_LIST *first_table= m_lex->select_lex.table_list.first; + TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first; thr_lock_type lock_type = TL_READ_NO_INSERT; bool res= TRUE; DBUG_ENTER("Sql_cmd_check_table::execute"); @@ -1346,7 +1348,7 @@ bool Sql_cmd_check_table::execute(THD *thd) lock_type, 0, 0, HA_OPEN_FOR_REPAIR, 0, &handler::ha_check, &view_check); - m_lex->select_lex.table_list.first= first_table; + m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; error: @@ -1357,7 +1359,7 @@ error: bool Sql_cmd_optimize_table::execute(THD *thd) { LEX *m_lex= thd->lex; - TABLE_LIST *first_table= m_lex->select_lex.table_list.first; + TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first; bool res= TRUE; DBUG_ENTER("Sql_cmd_optimize_table::execute"); @@ -1379,11 +1381,13 @@ bool Sql_cmd_optimize_table::execute(THD *thd) */ res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } - m_lex->select_lex.table_list.first= first_table; + m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; error: -WSREP_ERROR_LABEL: +#ifdef WITH_WSREP +wsrep_error_label: +#endif DBUG_RETURN(res); } @@ -1391,7 +1395,7 @@ WSREP_ERROR_LABEL: bool Sql_cmd_repair_table::execute(THD *thd) { LEX *m_lex= thd->lex; - TABLE_LIST *first_table= m_lex->select_lex.table_list.first; + TABLE_LIST *first_table= m_lex->first_select_lex()->table_list.first; bool res= TRUE; DBUG_ENTER("Sql_cmd_repair_table::execute"); @@ -1415,10 +1419,12 @@ bool Sql_cmd_repair_table::execute(THD *thd) */ res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } - m_lex->select_lex.table_list.first= first_table; + m_lex->first_select_lex()->table_list.first= first_table; m_lex->query_tables= first_table; error: -WSREP_ERROR_LABEL: +#ifdef WITH_WSREP +wsrep_error_label: +#endif DBUG_RETURN(res); } diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index 5fc9ff8209c..05a71d7785d 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -356,7 +356,7 @@ bool Sql_cmd_alter_table::execute(THD *thd) { LEX *lex= thd->lex; /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */ - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); /* first table of first SELECT_LEX */ TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first; /* @@ -497,16 +497,17 @@ bool Sql_cmd_alter_table::execute(THD *thd) lex->ignore); DBUG_RETURN(result); - -WSREP_ERROR_LABEL: +#ifdef WITH_WSREP +wsrep_error_label: WSREP_WARN("ALTER TABLE isolation failure"); DBUG_RETURN(TRUE); +#endif } bool Sql_cmd_discard_import_tablespace::execute(THD *thd) { /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */ - SELECT_LEX *select_lex= &thd->lex->select_lex; + SELECT_LEX *select_lex= thd->lex->first_select_lex(); /* first table of first SELECT_LEX */ TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first; diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 6626a054052..a7cfaca0d0e 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -68,6 +68,25 @@ int compare_decimal2(int* len, const char *s, const char *t) } +static bool +prepare_param(THD *thd, Item **item, const char *proc_name, uint pos) +{ + if ((*item)->fix_fields_if_needed(thd, item)) + { + DBUG_PRINT("info", ("fix_fields() for the parameter %u failed", pos)); + return true; + } + if ((*item)->type_handler()->result_type() != INT_RESULT || + !(*item)->basic_const_item() || + (*item)->val_real() < 0) + { + my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name); + return true; + } + return false; +} + + Procedure * proc_analyse_init(THD *thd, ORDER *param, select_result *result, List<Item> &field_list) @@ -88,17 +107,8 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result, else if (param->next) { // first parameter - if ((*param->item)->fix_fields_if_needed(thd, param->item)) - { - DBUG_PRINT("info", ("fix_fields() for the first parameter failed")); - goto err; - } - if ((*param->item)->type() != Item::INT_ITEM || - (*param->item)->val_real() < 0) - { - my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name); + if (prepare_param(thd, param->item, proc_name, 0)) goto err; - } pc->max_tree_elements = (uint) (*param->item)->val_int(); param = param->next; if (param->next) // no third parameter possible @@ -107,25 +117,12 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result, goto err; } // second parameter - if ((*param->item)->fix_fields_if_needed(thd, param->item)) - { - DBUG_PRINT("info", ("fix_fields() for the second parameter failed")); - goto err; - } - if ((*param->item)->type() != Item::INT_ITEM || - (*param->item)->val_real() < 0) - { - my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name); + if (prepare_param(thd, param->item, proc_name, 1)) goto err; - } pc->max_treemem = (uint) (*param->item)->val_int(); } - else if ((*param->item)->type() != Item::INT_ITEM || - (*param->item)->val_real() < 0) - { - my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name); + else if (prepare_param(thd, param->item, proc_name, 0)) goto err; - } // if only one parameter was given, it will be the value of max_tree_elements else { @@ -481,30 +478,28 @@ void field_real::add() void field_decimal::add() { /*TODO - remove rounding stuff after decimal_div returns proper frac */ - my_decimal dec_buf, *dec= item->val_decimal(&dec_buf); - my_decimal rounded; + VDec vdec(item); uint length; TREE_ELEMENT *element; - if (item->null_value) + if (vdec.is_null()) { nulls++; return; } - my_decimal_round(E_DEC_FATAL_ERROR, dec, item->decimals, FALSE,&rounded); - dec= &rounded; + my_decimal dec; + vdec.round_to(&dec, item->decimals, HALF_UP); - length= my_decimal_string_length(dec); + length= my_decimal_string_length(&dec); - if (decimal_is_zero(dec)) + if (decimal_is_zero(&dec)) empty++; if (room_in_tree) { uchar buf[DECIMAL_MAX_FIELD_SIZE]; - my_decimal2binary(E_DEC_FATAL_ERROR, dec, buf, - item->max_length, item->decimals); + dec.to_binary(buf, item->max_length, item->decimals); if (!(element = tree_insert(&tree, (void*)buf, 0, tree.custom_arg))) { room_in_tree = 0; // Remove tree, out of RAM ? @@ -524,18 +519,18 @@ void field_decimal::add() if (!found) { found = 1; - min_arg = max_arg = sum[0] = *dec; - my_decimal_mul(E_DEC_FATAL_ERROR, sum_sqr, dec, dec); + min_arg = max_arg = sum[0] = dec; + my_decimal_mul(E_DEC_FATAL_ERROR, sum_sqr, &dec, &dec); cur_sum= 0; min_length = max_length = length; } - else if (!decimal_is_zero(dec)) + else if (!decimal_is_zero(&dec)) { int next_cur_sum= cur_sum ^ 1; my_decimal sqr_buf; - my_decimal_add(E_DEC_FATAL_ERROR, sum+next_cur_sum, sum+cur_sum, dec); - my_decimal_mul(E_DEC_FATAL_ERROR, &sqr_buf, dec, dec); + my_decimal_add(E_DEC_FATAL_ERROR, sum+next_cur_sum, sum+cur_sum, &dec); + my_decimal_mul(E_DEC_FATAL_ERROR, &sqr_buf, &dec, &dec); my_decimal_add(E_DEC_FATAL_ERROR, sum_sqr+next_cur_sum, sum_sqr+cur_sum, &sqr_buf); cur_sum= next_cur_sum; @@ -543,13 +538,13 @@ void field_decimal::add() min_length = length; if (length > max_length) max_length = length; - if (my_decimal_cmp(dec, &min_arg) < 0) + if (dec.cmp(&min_arg) < 0) { - min_arg= *dec; + min_arg= dec; } - if (my_decimal_cmp(dec, &max_arg) > 0) + if (dec.cmp(&max_arg) > 0) { - max_arg= *dec; + max_arg= dec; } } } @@ -1003,7 +998,7 @@ void field_decimal::get_opt_type(String *answer, uint length; my_decimal_set_zero(&zero); - my_bool is_unsigned= (my_decimal_cmp(&zero, &min_arg) >= 0); + my_bool is_unsigned= (zero.cmp(&min_arg) >= 0); length= sprintf(buff, "DECIMAL(%d, %d)", (int) (max_length - (item->decimals ? 1 : 0)), @@ -1016,14 +1011,14 @@ void field_decimal::get_opt_type(String *answer, String *field_decimal::get_min_arg(String *str) { - my_decimal2string(E_DEC_FATAL_ERROR, &min_arg, 0, 0, '0', str); + min_arg.to_string_native(str, 0, 0, '0'); return str; } String *field_decimal::get_max_arg(String *str) { - my_decimal2string(E_DEC_FATAL_ERROR, &max_arg, 0, 0, '0', str); + max_arg.to_string_native(str, 0, 0, '0'); return str; } @@ -1041,10 +1036,10 @@ String *field_decimal::avg(String *s, ha_rows rows) int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num); my_decimal_div(E_DEC_FATAL_ERROR, &avg_val, sum+cur_sum, &num, prec_increment); /* TODO remove this after decimal_div returns proper frac */ - my_decimal_round(E_DEC_FATAL_ERROR, &avg_val, + avg_val.round_to(&rounded_avg, MY_MIN(sum[cur_sum].frac + prec_increment, DECIMAL_MAX_SCALE), - FALSE,&rounded_avg); - my_decimal2string(E_DEC_FATAL_ERROR, &rounded_avg, 0, 0, '0', s); + HALF_UP); + rounded_avg.to_string_native(s, 0, 0, '0'); return s; } @@ -1057,7 +1052,6 @@ String *field_decimal::std(String *s, ha_rows rows) return s; } my_decimal num, tmp, sum2, sum2d; - double std_sqr; int prec_increment= current_thd->variables.div_precincrement; int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num); @@ -1065,7 +1059,7 @@ String *field_decimal::std(String *s, ha_rows rows) my_decimal_div(E_DEC_FATAL_ERROR, &tmp, &sum2, &num, prec_increment); my_decimal_sub(E_DEC_FATAL_ERROR, &sum2, sum_sqr+cur_sum, &tmp); my_decimal_div(E_DEC_FATAL_ERROR, &tmp, &sum2, &num, prec_increment); - my_decimal2double(E_DEC_FATAL_ERROR, &tmp, &std_sqr); + double std_sqr= tmp.to_double(); s->set_real(((double) std_sqr <= 0.0 ? 0.0 : sqrt(std_sqr)), MY_MIN(item->decimals + prec_increment, NOT_FIXED_DEC), my_thd_charset); @@ -1117,12 +1111,9 @@ int collect_decimal(uchar *element, element_count count, info->str->append(','); else info->found = 1; - my_decimal dec; - binary2my_decimal(E_DEC_FATAL_ERROR, element, &dec, - info->item->max_length, info->item->decimals); - + my_decimal dec(element, info->item->max_length, info->item->decimals); info->str->append('\''); - my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, '0', &s); + dec.to_string_native(&s, 0, 0, '0'); info->str->append(s); info->str->append('\''); return 0; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index cf9a15dec68..1b4ffd0c61e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -306,97 +306,65 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild) } -/* - Close all tables which aren't in use by any thread - - @param thd Thread context - @param tables List of tables to remove from the cache - @param wait_for_refresh Wait for a impending flush - @param timeout Timeout for waiting for flush to be completed. - - @note THD can be NULL, but then wait_for_refresh must be FALSE - and tables must be NULL. - - @note When called as part of FLUSH TABLES WITH READ LOCK this function - ignores metadata locks held by other threads. In order to avoid - situation when FLUSH TABLES WITH READ LOCK sneaks in at the moment - when some write-locked table is being reopened (by FLUSH TABLES or - ALTER TABLE) we have to rely on additional global shared metadata - lock taken by thread trying to obtain global read lock. -*/ +/** + Close all tables that are not in use in table definition cache + @param purge_flag Argument for tc_purge. true if we should force all + shares to be deleted. false if it's enough to just + evict those that are not in use. +*/ -struct close_cached_tables_arg +void purge_tables(bool purge_flag) { - tdc_version_t refresh_version; - TDC_element *element; -}; - + /* + Force close of all open tables. -static my_bool close_cached_tables_callback(TDC_element *element, - close_cached_tables_arg *arg) -{ - mysql_mutex_lock(&element->LOCK_table_share); - if (element->share && element->flushed && - element->version < arg->refresh_version) - { - /* wait_for_old_version() will unlock mutex and free share */ - arg->element= element; - return TRUE; - } - mysql_mutex_unlock(&element->LOCK_table_share); - return FALSE; + Note that code in TABLE_SHARE::wait_for_old_version() assumes that + incrementing of refresh_version is followed by purge of unused table + shares. + */ + kill_delayed_threads(); + /* + Get rid of all unused TABLE and TABLE_SHARE instances. By doing + this we automatically close all tables which were marked as "old". + */ + tc_purge(purge_flag); + /* Free table shares which were not freed implicitly by loop above. */ + tdc_purge(true); } +/** + close_cached_tables + + This function has two separate usages: + 1) Close not used tables in the table cache to free memory + 2) Close a list of tables and wait until they are not used anymore. This + is used mainly when preparing a table for export. + + If there are locked tables, they are closed and reopened before + function returns. This is done to ensure that table files will be closed + by all threads and thus external copyable when FLUSH TABLES returns. +*/ + bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool wait_for_refresh, ulong timeout) { - bool result= FALSE; - struct timespec abstime; - tdc_version_t refresh_version; DBUG_ENTER("close_cached_tables"); DBUG_ASSERT(thd || (!wait_for_refresh && !tables)); - - refresh_version= tdc_increment_refresh_version(); + DBUG_ASSERT(wait_for_refresh || !tables); if (!tables) { - /* - Force close of all open tables. - - Note that code in TABLE_SHARE::wait_for_old_version() assumes that - incrementing of refresh_version is followed by purge of unused table - shares. - */ - kill_delayed_threads(); - /* - Get rid of all unused TABLE and TABLE_SHARE instances. By doing - this we automatically close all tables which were marked as "old". - */ - tc_purge(true); - /* Free table shares which were not freed implicitly by loop above. */ - tdc_purge(true); - } - else - { - bool found=0; - for (TABLE_LIST *table= tables; table; table= table->next_local) - { - /* tdc_remove_table() also sets TABLE_SHARE::version to 0. */ - found|= tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED, table->db.str, - table->table_name.str, TRUE); - } - if (!found) - wait_for_refresh=0; // Nothing to wait for + /* Free tables that are not used */ + purge_tables(false); + if (!wait_for_refresh) + DBUG_RETURN(false); } DBUG_PRINT("info", ("open table definitions: %d", (int) tdc_records())); - if (!wait_for_refresh) - DBUG_RETURN(result); - if (thd->locked_tables_mode) { /* @@ -407,8 +375,9 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, */ TABLE_LIST *tables_to_reopen= (tables ? tables : thd->locked_tables_list.locked_tables()); + bool result= false; - /* Close open HANDLER instances to avoid self-deadlock. */ + /* close open HANDLER for this thread to allow table to be closed */ mysql_ha_flush_tables(thd, tables_to_reopen); for (TABLE_LIST *table_list= tables_to_reopen; table_list; @@ -423,63 +392,15 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, if (! table) continue; - if (wait_while_table_is_used(thd, table, - HA_EXTRA_PREPARE_FOR_FORCED_CLOSE)) + if (thd->mdl_context.upgrade_shared_lock(table->mdl_ticket, MDL_EXCLUSIVE, + timeout)) { - result= TRUE; - goto err_with_reopen; - } - close_all_tables_for_name(thd, table->s, HA_EXTRA_NOT_USED, NULL); - } - } - - /* Wait until all threads have closed all the tables we are flushing. */ - DBUG_PRINT("info", ("Waiting for other threads to close their open tables")); - - /* - To a self-deadlock or deadlocks with other FLUSH threads - waiting on our open HANDLERs, we have to flush them. - */ - mysql_ha_flush(thd); - DEBUG_SYNC(thd, "after_flush_unlock"); - - if (!tables) - { - int r= 0; - close_cached_tables_arg argument; - argument.refresh_version= refresh_version; - set_timespec(abstime, timeout); - - while (!thd->killed && - (r= tdc_iterate(thd, - (my_hash_walk_action) close_cached_tables_callback, - &argument)) == 1 && - !argument.element->share->wait_for_old_version(thd, &abstime, - MDL_wait_for_subgraph::DEADLOCK_WEIGHT_DDL)) - /* no-op */; - - if (r) - result= TRUE; - } - else - { - for (TABLE_LIST *table= tables; table; table= table->next_local) - { - if (thd->killed) - break; - if (tdc_wait_for_old_version(thd, table->db.str, table->table_name.str, timeout, - MDL_wait_for_subgraph::DEADLOCK_WEIGHT_DDL, - refresh_version)) - { - result= TRUE; + result= true; break; } + table->file->extra(HA_EXTRA_PREPARE_FOR_FORCED_CLOSE); + close_all_tables_for_name(thd, table->s, HA_EXTRA_NOT_USED, NULL); } - } - -err_with_reopen: - if (thd->locked_tables_mode) - { /* No other thread has the locked tables open; reopen them and get the old locks. This should always succeed (unless some external process @@ -487,6 +408,7 @@ err_with_reopen: */ if (thd->locked_tables_list.reopen_tables(thd, false)) result= true; + /* Since downgrade_lock() won't do anything with shared metadata lock it is much simpler to go through all open tables rather @@ -494,7 +416,181 @@ err_with_reopen: */ for (TABLE *tab= thd->open_tables; tab; tab= tab->next) tab->mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE); + + DBUG_RETURN(result); + } + else if (tables) + { + /* + Get an explicit MDL lock for all requested tables to ensure they are + not used by any other thread + */ + MDL_request_list mdl_requests; + + DBUG_PRINT("info", ("Waiting for other threads to close their open tables")); + DEBUG_SYNC(thd, "after_flush_unlock"); + + /* close open HANDLER for this thread to allow table to be closed */ + mysql_ha_flush_tables(thd, tables); + + for (TABLE_LIST *table= tables; table; table= table->next_local) + { + MDL_request *mdl_request= new (thd->mem_root) MDL_request; + if (mdl_request == NULL) + DBUG_RETURN(true); + mdl_request->init(&table->mdl_request.key, MDL_EXCLUSIVE, MDL_STATEMENT); + mdl_requests.push_front(mdl_request); + } + + if (thd->mdl_context.acquire_locks(&mdl_requests, timeout)) + DBUG_RETURN(true); + + for (TABLE_LIST *table= tables; table; table= table->next_local) + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db.str, + table->table_name.str, false); } + DBUG_RETURN(false); +} + + +/** + Collect all shares that has open tables +*/ + +struct tc_collect_arg +{ + DYNAMIC_ARRAY shares; + flush_tables_type flush_type; +}; + +static my_bool tc_collect_used_shares(TDC_element *element, + tc_collect_arg *arg) +{ + my_bool result= FALSE; + + DYNAMIC_ARRAY *shares= &arg->shares; + mysql_mutex_lock(&element->LOCK_table_share); + if (element->ref_count > 0 && !element->share->is_view) + { + DBUG_ASSERT(element->share); + bool do_flush= 0; + switch (arg->flush_type) { + case FLUSH_ALL: + do_flush= 1; + break; + case FLUSH_NON_TRANS_TABLES: + if (!element->share->online_backup && + element->share->table_category == TABLE_CATEGORY_USER) + do_flush= 1; + break; + case FLUSH_SYS_TABLES: + if (!element->share->online_backup && + element->share->table_category != TABLE_CATEGORY_USER) + do_flush= 1; + } + if (do_flush) + { + element->ref_count++; // Protect against delete + if (push_dynamic(shares, (uchar*) &element->share)) + result= TRUE; + } + } + mysql_mutex_unlock(&element->LOCK_table_share); + return result; +} + + +/** + Flush cached table as part of global read lock + + @param thd + @param flag What type of tables should be flushed + + @return 0 ok + @return 1 error + + After we get the list of table shares, we will call flush on all + possible tables, even if some flush fails. +*/ + +bool flush_tables(THD *thd, flush_tables_type flag) +{ + bool result= TRUE; + uint open_errors= 0; + tc_collect_arg collect_arg; + TABLE *tmp_table; + DBUG_ENTER("flush_tables"); + + purge_tables(false); /* Flush unused tables and shares */ + + /* + Loop over all shares and collect shares that have open tables + TODO: + Optimize this to only collect shares that have been used for + write after last time all tables was closed. + */ + + if (!(tmp_table= (TABLE*) my_malloc(sizeof(*tmp_table), + MYF(MY_WME | MY_THREAD_SPECIFIC)))) + DBUG_RETURN(1); + + my_init_dynamic_array(&collect_arg.shares, sizeof(TABLE_SHARE*), 100, 100, + MYF(0)); + collect_arg.flush_type= flag; + if (tdc_iterate(thd, (my_hash_walk_action) tc_collect_used_shares, + &collect_arg, true)) + { + /* Release already collected shares */ + for (uint i= 0 ; i < collect_arg.shares.elements ; i++) + { + TABLE_SHARE *share= *dynamic_element(&collect_arg.shares, i, + TABLE_SHARE**); + tdc_release_share(share); + } + goto err; + } + + /* Call HA_EXTRA_FLUSH on all found shares */ + for (uint i= 0 ; i < collect_arg.shares.elements ; i++) + { + TABLE_SHARE *share= *dynamic_element(&collect_arg.shares, i, + TABLE_SHARE**); + TABLE *table= tc_acquire_table(thd, share->tdc); + if (table) + { + (void) table->file->extra(HA_EXTRA_FLUSH); + tc_release_table(table); + } + else + { + /* + HA_OPEN_FOR_ALTER is used to allow us to open the table even if + TABLE_SHARE::incompatible_version is set. + */ + if (!open_table_from_share(thd, share, &empty_clex_str, + HA_OPEN_KEYFILE, 0, + HA_OPEN_FOR_ALTER, + tmp_table, FALSE, + NULL)) + { + (void) tmp_table->file->extra(HA_EXTRA_FLUSH); + /* + We don't put the table into the TDC as the table was not fully + opened (we didn't open triggers) + */ + closefrm(tmp_table); + } + else + open_errors++; + } + tdc_release_share(share); + } + + result= open_errors ? TRUE : FALSE; + DBUG_PRINT("note", ("open_errors: %u", open_errors)); +err: + my_free(tmp_table); + delete_dynamic(&collect_arg.shares); DBUG_RETURN(result); } @@ -552,8 +648,17 @@ end: } +/** + Close cached connections + + @return false ok + @return true If there was an error from closed_cached_connection_tables or + if there was any open connections that we had to force closed +*/ + bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection) { + bool res= false; close_cached_connection_tables_arg argument; DBUG_ENTER("close_cached_connections"); DBUG_ASSERT(thd); @@ -567,9 +672,13 @@ bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection) &argument)) DBUG_RETURN(true); - DBUG_RETURN(argument.tables ? - close_cached_tables(thd, argument.tables, FALSE, LONG_TIMEOUT) : - false); + for (TABLE_LIST *table= argument.tables; table; table= table->next_local) + res|= tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED, + table->db.str, + table->table_name.str, TRUE); + + /* Return true if we found any open connections */ + DBUG_RETURN(res); } @@ -598,6 +707,7 @@ bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection) static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table) { + DBUG_ENTER("mark_used_tables_as_free_for_reuse"); for (; table ; table= table->next) { DBUG_ASSERT(table->pos_in_locked_tables == NULL || @@ -608,6 +718,7 @@ static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table) table->file->ha_reset(); } } + DBUG_VOID_RETURN; } @@ -630,7 +741,7 @@ static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table) - The table is marked as closed in the locked_table_list but kept there so one can call locked_table_list->reopen_tables() to put it back. - + In case of drop/rename the documented behavior is to implicitly remove the table from LOCK TABLES list. @@ -1738,59 +1849,6 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) if (! (flags & MYSQL_OPEN_HAS_MDL_LOCK)) { - /* - We are not under LOCK TABLES and going to acquire write-lock/ - modify the base table. We need to acquire protection against - global read lock until end of this statement in order to have - this statement blocked by active FLUSH TABLES WITH READ LOCK. - - We don't need to acquire this protection under LOCK TABLES as - such protection already acquired at LOCK TABLES time and - not released until UNLOCK TABLES. - - We don't block statements which modify only temporary tables - as these tables are not preserved by any form of - backup which uses FLUSH TABLES WITH READ LOCK. - - TODO: The fact that we sometimes acquire protection against - GRL only when we encounter table to be write-locked - slightly increases probability of deadlock. - This problem will be solved once Alik pushes his - temporary table refactoring patch and we can start - pre-acquiring metadata locks at the beggining of - open_tables() call. - */ - if (table_list->mdl_request.is_write_lock_request() && - ! (flags & (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK | - MYSQL_OPEN_FORCE_SHARED_MDL | - MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL | - MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK)) && - ! ot_ctx->has_protection_against_grl()) - { - MDL_request protection_request; - MDL_deadlock_handler mdl_deadlock_handler(ot_ctx); - - if (thd->global_read_lock.can_acquire_protection()) - DBUG_RETURN(TRUE); - - protection_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, - MDL_STATEMENT); - - /* - Install error handler which if possible will convert deadlock error - into request to back-off and restart process of opening tables. - */ - thd->push_internal_handler(&mdl_deadlock_handler); - bool result= thd->mdl_context.acquire_lock(&protection_request, - ot_ctx->get_timeout()); - thd->pop_internal_handler(); - - if (result) - DBUG_RETURN(TRUE); - - ot_ctx->set_has_protection_against_grl(); - } - if (open_table_get_mdl_lock(thd, ot_ctx, &table_list->mdl_request, flags, &mdl_ticket) || mdl_ticket == NULL) @@ -1889,7 +1947,6 @@ retry_share: if (mysql_make_view(thd, share, table_list, false)) goto err_lock; - /* TODO: Don't free this */ tdc_release_share(share); @@ -1963,7 +2020,6 @@ retry_share: else { enum open_frm_error error; - /* make a new table */ if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) goto err_lock; @@ -2002,6 +2058,78 @@ retry_share: tc_add_table(thd, table); } + if (!(flags & MYSQL_OPEN_HAS_MDL_LOCK) && + table->s->table_category < TABLE_CATEGORY_INFORMATION) + { + /* + We are not under LOCK TABLES and going to acquire write-lock/ + modify the base table. We need to acquire protection against + global read lock until end of this statement in order to have + this statement blocked by active FLUSH TABLES WITH READ LOCK. + + We don't need to acquire this protection under LOCK TABLES as + such protection already acquired at LOCK TABLES time and + not released until UNLOCK TABLES. + + We don't block statements which modify only temporary tables + as these tables are not preserved by any form of + backup which uses FLUSH TABLES WITH READ LOCK. + + TODO: The fact that we sometimes acquire protection against + GRL only when we encounter table to be write-locked + slightly increases probability of deadlock. + This problem will be solved once Alik pushes his + temporary table refactoring patch and we can start + pre-acquiring metadata locks at the beggining of + open_tables() call. + */ + enum enum_mdl_type mdl_type= MDL_BACKUP_DML; + + if (table->s->table_category != TABLE_CATEGORY_USER) + mdl_type= MDL_BACKUP_SYS_DML; + else if (table->s->online_backup) + mdl_type= MDL_BACKUP_TRANS_DML; + + if (table_list->mdl_request.is_write_lock_request() && + ! (flags & (MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK | + MYSQL_OPEN_FORCE_SHARED_MDL | + MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL | + MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK)) && + ! ot_ctx->has_protection_against_grl(mdl_type)) + { + MDL_request protection_request; + MDL_deadlock_handler mdl_deadlock_handler(ot_ctx); + + if (thd->has_read_only_protection()) + { + MYSQL_UNBIND_TABLE(table->file); + tc_release_table(table); + DBUG_RETURN(TRUE); + } + + protection_request.init(MDL_key::BACKUP, "", "", mdl_type, + MDL_STATEMENT); + + /* + Install error handler which if possible will convert deadlock error + into request to back-off and restart process of opening tables. + */ + thd->push_internal_handler(&mdl_deadlock_handler); + bool result= thd->mdl_context.acquire_lock(&protection_request, + ot_ctx->get_timeout()); + thd->pop_internal_handler(); + + if (result) + { + MYSQL_UNBIND_TABLE(table->file); + tc_release_table(table); + DBUG_RETURN(TRUE); + } + + ot_ctx->set_has_protection_against_grl(mdl_type); + } + } + table->mdl_ticket= mdl_ticket; table->next= thd->open_tables; /* Link into simple list */ @@ -2118,8 +2246,8 @@ TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db, cases don't take a global IX lock in order to be compatible with global read lock. */ - if (unlikely(!thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "", - MDL_INTENTION_EXCLUSIVE))) + if (unlikely(!thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "", + MDL_BACKUP_DDL))) { error= ER_TABLE_NOT_LOCKED_FOR_WRITE; goto err_exit; @@ -2876,7 +3004,7 @@ Open_table_context::Open_table_context(THD *thd, uint flags) m_flags(flags), m_action(OT_NO_ACTION), m_has_locks(thd->mdl_context.has_locks()), - m_has_protection_against_grl(FALSE) + m_has_protection_against_grl(0) {} @@ -3092,7 +3220,7 @@ Open_table_context::recover_from_failed_open() against GRL. It is no longer valid as the corresponding lock was released by close_tables_for_reopen(). */ - m_has_protection_against_grl= FALSE; + m_has_protection_against_grl= 0; /* Prepare for possible another back-off. */ m_action= OT_NO_ACTION; return result; @@ -3755,6 +3883,40 @@ end: } +static bool upgrade_lock_if_not_exists(THD *thd, + const DDL_options_st &create_info, + TABLE_LIST *create_table, + ulong lock_wait_timeout) +{ + DBUG_ENTER("upgrade_lock_if_not_exists"); + + if (thd->lex->sql_command == SQLCOM_CREATE_TABLE || + thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE) + { + DEBUG_SYNC(thd,"create_table_before_check_if_exists"); + if (!create_info.or_replace() && + ha_table_exists(thd, &create_table->db, &create_table->table_name)) + { + if (create_info.if_not_exists()) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_TABLE_EXISTS_ERROR, + ER_THD(thd, ER_TABLE_EXISTS_ERROR), + create_table->table_name.str); + } + else + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name.str); + DBUG_RETURN(true); + } + DBUG_RETURN(thd->mdl_context.upgrade_shared_lock( + create_table->mdl_request.ticket, + MDL_EXCLUSIVE, + lock_wait_timeout)); + } + DBUG_RETURN(false); +} + + /** Acquire upgradable (SNW, SNRW) metadata locks on tables used by LOCK TABLES or by a DDL statement. Under LOCK TABLES, we can't take @@ -3792,10 +3954,7 @@ lock_table_names(THD *thd, const DDL_options_st &options, MDL_request_list mdl_requests; TABLE_LIST *table; MDL_request global_request; - ulong org_lock_wait_timeout= lock_wait_timeout; - /* Check if we are using CREATE TABLE ... IF NOT EXISTS */ - bool create_table; - Dummy_error_handler error_handler; + MDL_savepoint mdl_savepoint; DBUG_ENTER("lock_table_names"); DBUG_ASSERT(!thd->locked_tables_mode); @@ -3803,6 +3962,8 @@ lock_table_names(THD *thd, const DDL_options_st &options, for (table= tables_start; table && table != tables_end; table= table->next_global) { + DBUG_PRINT("info", ("mdl_request.type: %d open_type: %d", + table->mdl_request.type, table->open_type)); if (table->mdl_request.type < MDL_SHARED_UPGRADABLE || table->mdl_request.type == MDL_SHARED_READ_ONLY || table->open_type == OT_TEMPORARY_ONLY || @@ -3836,73 +3997,48 @@ lock_table_names(THD *thd, const DDL_options_st &options, if (mdl_requests.is_empty()) DBUG_RETURN(FALSE); - /* Check if CREATE TABLE without REPLACE was used */ - create_table= ((thd->lex->sql_command == SQLCOM_CREATE_TABLE || - thd->lex->sql_command == SQLCOM_CREATE_SEQUENCE) && - !options.or_replace()); - - if (!(flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK)) + if (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) { - /* - Protect this statement against concurrent global read lock - by acquiring global intention exclusive lock with statement - duration. - */ - if (thd->global_read_lock.can_acquire_protection()) - DBUG_RETURN(TRUE); - global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, - MDL_STATEMENT); - mdl_requests.push_front(&global_request); - - if (create_table) -#ifdef WITH_WSREP - if (thd->lex->sql_command != SQLCOM_CREATE_TABLE && - thd->wsrep_exec_mode != REPL_RECV) -#endif - lock_wait_timeout= 0; // Don't wait for timeout + DBUG_RETURN(thd->mdl_context.acquire_locks(&mdl_requests, + lock_wait_timeout) || + upgrade_lock_if_not_exists(thd, options, tables_start, + lock_wait_timeout)); } - for (;;) - { - if (create_table) - thd->push_internal_handler(&error_handler); // Avoid warnings & errors - bool res= thd->mdl_context.acquire_locks(&mdl_requests, lock_wait_timeout); - if (create_table) - thd->pop_internal_handler(); - if (!res) - DBUG_RETURN(FALSE); // Got locks + /* Protect this statement against concurrent BACKUP STAGE or FTWRL. */ + if (thd->has_read_only_protection()) + DBUG_RETURN(true); - if (!create_table) - DBUG_RETURN(TRUE); // Return original error + global_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_DDL, MDL_STATEMENT); + mdl_savepoint= thd->mdl_context.mdl_savepoint(); - /* - We come here in the case of lock timeout when executing CREATE TABLE. - Verify that table does exist (it usually does, as we got a lock conflict) - */ - if (ha_table_exists(thd, &tables_start->db, &tables_start->table_name)) + while (!thd->mdl_context.acquire_locks(&mdl_requests, lock_wait_timeout) && + !upgrade_lock_if_not_exists(thd, options, tables_start, + lock_wait_timeout) && + !thd->mdl_context.try_acquire_lock(&global_request)) + { + if (global_request.ticket) { - if (options.if_not_exists()) - { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_TABLE_EXISTS_ERROR, - ER_THD(thd, ER_TABLE_EXISTS_ERROR), - tables_start->table_name.str); - } - else - my_error(ER_TABLE_EXISTS_ERROR, MYF(0), tables_start->table_name.str); - DBUG_RETURN(TRUE); + thd->mdl_backup_ticket= global_request.ticket; + DBUG_RETURN(false); } + /* - We got error from acquire_locks, but the table didn't exists. - This could happen if another connection runs a statement - involving this non-existent table, and this statement took the mdl, - but didn't error out with ER_NO_SUCH_TABLE yet (yes, a race condition). - We play safe and restart the original acquire_locks with the - original timeout. + There is ongoing or pending BACKUP STAGE or FTWRL. + Wait until it finishes and re-try. */ - create_table= 0; - lock_wait_timeout= org_lock_wait_timeout; + thd->mdl_context.rollback_to_savepoint(mdl_savepoint); + if (thd->mdl_context.acquire_lock(&global_request, lock_wait_timeout)) + break; + thd->mdl_context.rollback_to_savepoint(mdl_savepoint); + + /* Reset tickets for all acquired locks */ + global_request.ticket= 0; + MDL_request_list::Iterator it(mdl_requests); + while (auto mdl_request= it++) + mdl_request->ticket= 0; } + DBUG_RETURN(true); } @@ -4295,7 +4431,9 @@ restart: } error: -WSREP_ERROR_LABEL: +#ifdef WITH_WSREP +wsrep_error_label: +#endif THD_STAGE_INFO(thd, stage_after_opening_tables); thd_proc_info(thd, 0); @@ -5217,8 +5355,7 @@ err: @retval TRUE A lock wait timeout, deadlock or out of memory. */ -bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, - uint flags) +bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, uint flags) { TABLE_LIST *table; DBUG_ENTER("lock_tables"); @@ -5471,43 +5608,27 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table) DBUG_ENTER("update_field_dependencies"); if (should_mark_column(thd->column_usage)) { - MY_BITMAP *bitmap; - /* We always want to register the used keys, as the column bitmap may have been set for all fields (for example for view). */ - table->covering_keys.intersect(field->part_of_key); - if (field->vcol_info) - table->mark_virtual_col(field); - if (thd->column_usage == MARK_COLUMNS_READ) - bitmap= table->read_set; + { + if (table->mark_column_with_deps(field)) + DBUG_VOID_RETURN; // Field was already marked + } else - bitmap= table->write_set; - - /* - The test-and-set mechanism in the bitmap is not reliable during - multi-UPDATE statements under MARK_COLUMNS_READ mode - (thd->column_usage == MARK_COLUMNS_READ), as this bitmap contains - only those columns that are used in the SET clause. I.e they are being - set here. See multi_update::prepare() - */ - if (bitmap_fast_test_and_set(bitmap, field->field_index)) { - if (thd->column_usage == MARK_COLUMNS_WRITE) + if (bitmap_fast_test_and_set(table->write_set, field->field_index)) { DBUG_PRINT("warning", ("Found duplicated field")); thd->dup_field= field; + DBUG_VOID_RETURN; } - else - { - DBUG_PRINT("note", ("Field found before")); - } - DBUG_VOID_RETURN; } + table->used_fields++; } if (table->get_fields_in_item_tree) @@ -7436,7 +7557,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, Item_window_func::split_sum_func. */ if (sum_func_list && - ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) || + ((item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM) || item->with_window_func)) { item->split_sum_func(thd, ref_pointer_array, *sum_func_list, @@ -7544,7 +7665,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context, TABLE_LIST *first_select_table= (select_insert ? tables->next_local: 0); - SELECT_LEX *select_lex= select_insert ? &thd->lex->select_lex : + SELECT_LEX *select_lex= select_insert ? thd->lex->first_select_lex() : thd->lex->current_select; if (select_lex->first_cond_optimization) { @@ -7572,7 +7693,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context, { /* new counting for SELECT of INSERT ... SELECT command */ first_select_table= 0; - thd->lex->select_lex.insert_tables= tablenr; + thd->lex->first_select_lex()->insert_tables= tablenr; tablenr= 0; } if(table_list->jtbm_subselect) @@ -7939,18 +8060,9 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, if ((field= field_iterator.field())) { - /* Mark fields as used to allow storage engine to optimze access */ - bitmap_set_bit(field->table->read_set, field->field_index); - /* - Mark virtual fields for write and others that the virtual fields - depend on for read. - */ - if (field->vcol_info) - field->table->mark_virtual_col(field); + field->table->mark_column_with_deps(field); if (table) - { table->covering_keys.intersect(field->part_of_key); - } if (tables->is_natural_join) { TABLE *field_table; @@ -8128,7 +8240,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves, from subquery of VIEW, because tables of subquery belongs to VIEW (see condition before prepare_check_option() call) */ - bool it_is_update= (select_lex == &thd->lex->select_lex) && + bool it_is_update= (select_lex == thd->lex->first_select_lex()) && thd->lex->which_check_option_applicable(); bool save_is_item_list_lookup= select_lex->is_item_list_lookup; TABLE_LIST *derived= select_lex->master_unit()->derived; @@ -8144,7 +8256,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves, for (table= tables; table; table= table->next_local) { - if (select_lex == &thd->lex->select_lex && + if (select_lex == thd->lex->first_select_lex() && select_lex->first_cond_optimization && table->merged_for_insert && table->prepare_where(thd, conds, FALSE)) @@ -8751,7 +8863,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) Item_func_match *ifm; while ((ifm=li++)) - if (unlikely(!ifm->fixed)) + if (unlikely(!ifm->is_fixed())) /* it mean that clause where was FT function was removed, so we have to remove the function from the list. @@ -8805,7 +8917,6 @@ open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, { Query_tables_list query_tables_list_backup; LEX *lex= thd->lex; - DBUG_ENTER("open_system_tables_for_read"); /* @@ -8819,9 +8930,15 @@ open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, thd->reset_n_backup_open_tables_state(backup); thd->lex->sql_command= SQLCOM_SELECT; + /* + Only use MYSQL_LOCK_IGNORE_TIMEOUT for tables opened for read. + This is to ensure that lock_wait_timeout is honored when trying + to update stats tables. + */ if (open_and_lock_tables(thd, table_list, FALSE, - MYSQL_OPEN_IGNORE_FLUSH | - MYSQL_LOCK_IGNORE_TIMEOUT)) + (MYSQL_OPEN_IGNORE_FLUSH | + (table_list->lock_type < TL_WRITE_ALLOW_WRITE ? + MYSQL_LOCK_IGNORE_TIMEOUT : 0)))) { lex->restore_backup_query_tables_list(&query_tables_list_backup); thd->restore_backup_open_tables_state(backup); @@ -8853,6 +8970,13 @@ open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, void close_system_tables(THD *thd, Open_tables_backup *backup) { + /* + Inform the transaction handler that we are closing the + system tables and we don't need the read view anymore. + */ + for (TABLE *table= thd->open_tables ; table ; table= table->next) + table->file->extra(HA_EXTRA_PREPARE_FOR_FORCED_CLOSE); + close_thread_tables(thd); thd->restore_backup_open_tables_state(backup); } @@ -8986,7 +9110,7 @@ void unfix_fields(List<Item> &fields) List_iterator<Item> li(fields); Item *item; while ((item= li++)) - item->fixed= 0; + item->unfix_fields(); } diff --git a/sql/sql_base.h b/sql/sql_base.h index 22247af07a8..2b245217bce 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -57,6 +57,13 @@ enum enum_resolution_type { RESOLVED_AGAINST_ALIAS }; +/* Argument to flush_tables() of what to flush */ +enum flush_tables_type { + FLUSH_ALL, + FLUSH_NON_TRANS_TABLES, + FLUSH_SYS_TABLES +}; + enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE, IGNORE_EXCEPT_NON_UNIQUE}; @@ -288,12 +295,10 @@ TABLE *open_system_table_for_update(THD *thd, TABLE_LIST *one_table); TABLE *open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_backup *backup); void close_log_table(THD *thd, Open_tables_backup *backup); -TABLE *open_performance_schema_table(THD *thd, TABLE_LIST *one_table, - Open_tables_state *backup); -void close_performance_schema_table(THD *thd, Open_tables_state *backup); - bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool wait_for_refresh, ulong timeout); +void purge_tables(bool purge_flag); +bool flush_tables(THD *thd, flush_tables_type flag); bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connect_string); void close_all_tables_for_name(THD *thd, TABLE_SHARE *share, ha_extra_function extra, @@ -371,10 +376,12 @@ inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array, bool allow_sum_func) { bool res; - thd->lex->select_lex.no_wrap_view_item= TRUE; + SELECT_LEX *first= thd->lex->first_select_lex(); + DBUG_ASSERT(thd->lex->current_select == first); + first->no_wrap_view_item= TRUE; res= setup_fields(thd, ref_pointer_array, item, column_usage, sum_func_list, NULL, allow_sum_func); - thd->lex->select_lex.no_wrap_view_item= FALSE; + first->no_wrap_view_item= FALSE; return res; } @@ -552,14 +559,14 @@ public: Set flag indicating that we have already acquired metadata lock protecting this statement against GRL while opening tables. */ - void set_has_protection_against_grl() + void set_has_protection_against_grl(enum_mdl_type mdl_type) { - m_has_protection_against_grl= TRUE; + m_has_protection_against_grl|= MDL_BIT(mdl_type); } - bool has_protection_against_grl() const + bool has_protection_against_grl(enum_mdl_type mdl_type) const { - return m_has_protection_against_grl; + return (bool) (m_has_protection_against_grl & MDL_BIT(mdl_type)); } private: @@ -591,7 +598,7 @@ private: Indicates that in the process of opening tables we have acquired protection against global read lock. */ - bool m_has_protection_against_grl; + mdl_bitmap_t m_has_protection_against_grl; }; diff --git a/sql/sql_basic_types.h b/sql/sql_basic_types.h index 1e97262cdf0..a790b68fc0c 100644 --- a/sql/sql_basic_types.h +++ b/sql/sql_basic_types.h @@ -22,4 +22,314 @@ typedef ulonglong sql_mode_t; typedef int64 query_id_t; + + +/* + "fuzzydate" with strict data type control. + Represents a mixture of *only* data type conversion flags, without rounding. + Please keep "explicit" in constructors and conversion methods. +*/ +class date_conv_mode_t +{ +public: + enum value_t + { + CONV_NONE= 0U, + /* + FUZZY_DATES is used for the result will only be used for comparison + purposes. Conversion is as relaxed as possible. + */ + FUZZY_DATES= 1U, + TIME_ONLY= 4U, + INTERVAL_hhmmssff= 8U, + INTERVAL_DAY= 16U, + RANGE0_LAST= INTERVAL_DAY, + NO_ZERO_IN_DATE= (1UL << 23), // MODE_NO_ZERO_IN_DATE + NO_ZERO_DATE= (1UL << 24), // MODE_NO_ZERO_DATE + INVALID_DATES= (1UL << 25) // MODE_INVALID_DATES + }; + + /* + BIT-OR for all known values. Let's have a separate enum for it. + - We don't put this value "value_t", to avoid handling it in switch(). + - We don't put this value as a static const inside the class, + because "gdb" would display it every time when we do "print" + for a time_round_mode_t value. + - We can't put into into a function returning this value, because + it's not allowed to use functions in static_assert. + */ + enum known_values_t + { + KNOWN_MODES= FUZZY_DATES | + TIME_ONLY | INTERVAL_hhmmssff | INTERVAL_DAY | + NO_ZERO_IN_DATE | NO_ZERO_DATE | INVALID_DATES + }; +private: + value_t m_mode; +public: + + // Constructors + explicit date_conv_mode_t(ulonglong fuzzydate) + :m_mode((value_t) fuzzydate) + { } + + // Conversion operators + explicit operator ulonglong() const + { + return m_mode; + } + explicit operator bool() const + { + return m_mode != 0; + } + + // Unary operators + ulonglong operator~() const + { + return ~m_mode; + } + + // Dyadic bitwise operators + date_conv_mode_t operator&(const date_conv_mode_t &other) const + { + return date_conv_mode_t(m_mode & other.m_mode); + } + date_conv_mode_t operator&(const ulonglong other) const + { + return date_conv_mode_t(m_mode & other); + } + + date_conv_mode_t operator|(const date_conv_mode_t &other) const + { + return date_conv_mode_t(m_mode | other.m_mode); + } + + // Dyadic bitwise assignment operators + date_conv_mode_t &operator&=(const date_conv_mode_t &other) + { + m_mode= value_t(m_mode & other.m_mode); + return *this; + } + + date_conv_mode_t &operator|=(const date_conv_mode_t &other) + { + m_mode= value_t(m_mode | other.m_mode); + return *this; + } +}; + + +/* + Fractional rounding mode for temporal data types. +*/ +class time_round_mode_t +{ +public: + enum value_t + { + /* + Use FRAC_NONE when the value needs no rounding nor truncation, + because it is already known not to haveany fractional digits outside + of the requested precision. + */ + FRAC_NONE= 0, + FRAC_TRUNCATE= date_conv_mode_t::RANGE0_LAST << 1, // 32 + FRAC_ROUND= date_conv_mode_t::RANGE0_LAST << 2 // 64 + }; + // BIT-OR for all known values. See comments in time_conv_mode_t. + enum known_values_t + { + KNOWN_MODES= FRAC_TRUNCATE | FRAC_ROUND + }; +private: + value_t m_mode; +public: + // Constructors + explicit time_round_mode_t(ulonglong mode) + :m_mode((value_t) mode) + { + DBUG_ASSERT(mode == FRAC_NONE || + mode == FRAC_TRUNCATE || + mode == FRAC_ROUND); + } + // Conversion operators + explicit operator ulonglong() const + { + return m_mode; + } + value_t mode() const + { + return m_mode; + } + // Comparison operators + bool operator==(const time_round_mode_t &other) + { + return m_mode == other.m_mode; + } +}; + + +/* + "fuzzydate" with strict data type control. + Used as a parameter to get_date() and represents a mixture of: + - data type conversion flags + - fractional second rounding flags + Please keep "explicit" in constructors and conversion methods. +*/ +class date_mode_t +{ +public: + enum value_t + { + CONV_NONE= date_conv_mode_t::CONV_NONE, // 0 + FUZZY_DATES= date_conv_mode_t::FUZZY_DATES, // 1 + TIME_ONLY= date_conv_mode_t::TIME_ONLY, // 4 + INTERVAL_hhmmssff= date_conv_mode_t::INTERVAL_hhmmssff, // 8 + INTERVAL_DAY= date_conv_mode_t::INTERVAL_DAY, // 16 + FRAC_TRUNCATE= time_round_mode_t::FRAC_TRUNCATE, // 32 + FRAC_ROUND= time_round_mode_t::FRAC_ROUND, // 64 + NO_ZERO_IN_DATE= date_conv_mode_t::NO_ZERO_IN_DATE, // (1UL << 23) + NO_ZERO_DATE= date_conv_mode_t::NO_ZERO_DATE, // (1UL << 24) + INVALID_DATES= date_conv_mode_t::INVALID_DATES, // (1UL << 25) + }; +protected: + value_t m_mode; +public: + + // Constructors + explicit date_mode_t(ulonglong fuzzydate) + :m_mode((value_t) fuzzydate) + { } + + // Conversion operators + explicit operator ulonglong() const + { + return m_mode; + } + explicit operator bool() const + { + return m_mode != 0; + } + explicit operator date_conv_mode_t() const + { + return date_conv_mode_t(ulonglong(m_mode) & date_conv_mode_t::KNOWN_MODES); + } + explicit operator time_round_mode_t() const + { + return time_round_mode_t(ulonglong(m_mode) & time_round_mode_t::KNOWN_MODES); + } + // Unary operators + ulonglong operator~() const + { + return ~m_mode; + } + bool operator!() const + { + return !m_mode; + } + + // Dyadic bitwise operators + date_mode_t operator&(const date_mode_t &other) const + { + return date_mode_t(m_mode & other.m_mode); + } + date_mode_t operator&(ulonglong other) const + { + return date_mode_t(m_mode & other); + } + + date_mode_t operator|(const date_mode_t &other) const + { + return date_mode_t(m_mode | other.m_mode); + } + + // Dyadic bitwise assignment operators + date_mode_t &operator&=(const date_mode_t &other) + { + m_mode= value_t(m_mode & other.m_mode); + return *this; + } + + date_mode_t &operator|=(const date_mode_t &other) + { + m_mode= value_t(m_mode | other.m_mode); + return *this; + } + + date_mode_t &operator|=(const date_conv_mode_t &other) + { + m_mode= value_t(m_mode | ulonglong(other)); + return *this; + } +}; + + +// Bitwise OR out-of-class operators for data type mixtures +static inline date_mode_t operator|(const date_mode_t &a, + const date_conv_mode_t &b) +{ + return date_mode_t(ulonglong(a) | ulonglong(b)); +} + +static inline date_mode_t operator|(const date_conv_mode_t &a, + const time_round_mode_t &b) +{ + return date_mode_t(ulonglong(a) | ulonglong(b)); +} + + +static inline date_mode_t operator|(const date_conv_mode_t &a, + const date_mode_t &b) +{ + return date_mode_t(ulonglong(a) | ulonglong(b)); +} + + +// Bitwise AND out-of-class operators for data type mixtures +static inline date_conv_mode_t operator&(const date_mode_t &a, + const date_conv_mode_t &b) +{ + return date_conv_mode_t(ulonglong(a) & ulonglong(b)); +} + +static inline date_conv_mode_t operator&(const date_conv_mode_t &a, + const date_mode_t &b) +{ + return date_conv_mode_t(ulonglong(a) & ulonglong(b)); +} + +static inline date_conv_mode_t operator&(sql_mode_t &a, + const date_conv_mode_t &b) +{ + return date_conv_mode_t(a & ulonglong(b)); +} + + +static const date_conv_mode_t + TIME_CONV_NONE (date_conv_mode_t::CONV_NONE), + TIME_FUZZY_DATES (date_conv_mode_t::FUZZY_DATES), + TIME_TIME_ONLY (date_conv_mode_t::TIME_ONLY), + TIME_INTERVAL_hhmmssff (date_conv_mode_t::INTERVAL_hhmmssff), + TIME_INTERVAL_DAY (date_conv_mode_t::INTERVAL_DAY), + TIME_NO_ZERO_IN_DATE (date_conv_mode_t::NO_ZERO_IN_DATE), + TIME_NO_ZERO_DATE (date_conv_mode_t::NO_ZERO_DATE), + TIME_INVALID_DATES (date_conv_mode_t::INVALID_DATES); + +// An often used combination +static const date_conv_mode_t + TIME_NO_ZEROS (date_conv_mode_t::NO_ZERO_DATE| + date_conv_mode_t::NO_ZERO_IN_DATE); + +// Flags understood by str_to_xxx, number_to_xxx, check_date +static const date_conv_mode_t + TIME_MODE_FOR_XXX_TO_DATE (date_mode_t::NO_ZERO_IN_DATE | + date_mode_t::NO_ZERO_DATE | + date_mode_t::INVALID_DATES); + +static const time_round_mode_t + TIME_FRAC_NONE (time_round_mode_t::FRAC_NONE), + TIME_FRAC_TRUNCATE (time_round_mode_t::FRAC_TRUNCATE), + TIME_FRAC_ROUND (time_round_mode_t::FRAC_ROUND); + + #endif diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index 00270fb6f32..1fa3cca7c27 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -173,7 +173,7 @@ void mysql_client_binlog_statement(THD* thd) */ if (!(rli && buf)) { - my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), 1); /* needed 1 bytes */ + my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 1); /* needed 1 bytes */ goto end; } diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index aa4c77d0939..73bb4d7b7f7 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -276,8 +276,8 @@ functions: - Called before parsing and used to match a statement with the stored queries hash. If a match is found the cached result set is sent through repeated - calls to net_real_write. (note: calling thread doesn't have a regis- - tered result set writer: thd->net.query_cache_query=0) + calls to net_real_write. (note: calling thread does not have a + registered result set writer: thd->net.query_cache_query=0) 2. Query_cache::store_query - Called just before handle_select() and is used to register a result set writer to the statement currently being processed @@ -480,8 +480,7 @@ static void make_base_query(String *new_query, /* We do not support UCS2, UTF16, UTF32 as a client character set */ DBUG_ASSERT(current_thd->variables.character_set_client->mbminlen == 1); - new_query->length(0); // Don't copy anything from old buffer - if (new_query->realloc(query_length + additional_length)) + if (new_query->alloc(query_length + additional_length)) { /* We could not allocate the query. Use original query for @@ -4147,13 +4146,13 @@ Query_cache::is_cacheable(THD *thd, LEX *lex, if (thd->lex->safe_to_cache_query && (thd->variables.query_cache_type == 1 || - (thd->variables.query_cache_type == 2 && (lex->select_lex.options & - OPTION_TO_QUERY_CACHE))) && + (thd->variables.query_cache_type == 2 && + (lex->first_select_lex()->options & OPTION_TO_QUERY_CACHE))) && qc_is_able_to_intercept_result(thd)) { DBUG_PRINT("qcache", ("options: %lx %lx type: %u", (long) OPTION_TO_QUERY_CACHE, - (long) lex->select_lex.options, + (long) lex->first_select_lex()->options, (int) thd->variables.query_cache_type)); if (!(table_count= process_and_count_tables(thd, tables_used, @@ -4174,7 +4173,7 @@ Query_cache::is_cacheable(THD *thd, LEX *lex, ("not interesting query: %d or not cacheable, options %lx %lx type: %u net->vio present: %u", (int) lex->sql_command, (long) OPTION_TO_QUERY_CACHE, - (long) lex->select_lex.options, + (long) lex->first_select_lex()->options, (int) thd->variables.query_cache_type, (uint) MY_TEST(qc_is_able_to_intercept_result(thd)))); DBUG_RETURN(0); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3881f6f28ad..2292587bbd0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1219,6 +1219,7 @@ void THD::init(bool skip_lock) first_successful_insert_id_in_prev_stmt= 0; first_successful_insert_id_in_prev_stmt_for_binlog= 0; first_successful_insert_id_in_cur_stmt= 0; + current_backup_stage= BACKUP_FINISHED; #ifdef WITH_WSREP wsrep_exec_mode= wsrep_applier ? REPL_RECV : LOCAL_STATE; wsrep_conflict_state= NO_CONFLICT; @@ -1411,7 +1412,7 @@ bool THD::set_db(const LEX_CSTRING *new_db) const char *tmp= NULL; if (new_db->str) { - if (!(tmp= my_strndup(new_db->str, new_db->length, MYF(MY_WME | ME_FATALERROR)))) + if (!(tmp= my_strndup(new_db->str, new_db->length, MYF(MY_WME | ME_FATAL)))) result= 1; } @@ -1487,6 +1488,7 @@ void THD::cleanup(void) */ mdl_context.release_transactional_locks(); + backup_end(this); /* Release the global read lock, if acquired. */ if (global_read_lock.is_acquired()) global_read_lock.unlock_global_read_lock(this); @@ -2494,6 +2496,16 @@ void THD::update_charset() ¬_used); } +void THD::give_protection_error() +{ + if (current_backup_stage != BACKUP_FINISHED) + my_error(ER_BACKUP_LOCK_IS_ACTIVE, MYF(0)); + else + { + DBUG_ASSERT(global_read_lock.is_acquired()); + my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0)); + } +} /* routings to adding tables to list of changed in transaction tables */ @@ -2570,7 +2582,7 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, size_t key_length) key_length + 1); if (!new_table) { - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATALERROR), + my_error(EE_OUTOFMEMORY, MYF(ME_FATAL), ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1); set_killed(KILL_CONNECTION); return 0; @@ -3225,9 +3237,9 @@ int select_export::send_data(List<Item> &items) ((uint64) res->length() / res->charset()->mbminlen + 1) * write_cs->mbmaxlen + 1; set_if_smaller(estimated_bytes, UINT_MAX32); - if (cvt_str.realloc((uint32) estimated_bytes)) + if (cvt_str.alloc((uint32) estimated_bytes)) { - my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), (uint32) estimated_bytes); + my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), (uint32) estimated_bytes); goto err; } @@ -3494,7 +3506,7 @@ int select_singlerow_subselect::send_data(List<Item> &items) if (it->assigned()) { my_message(ER_SUBQUERY_NO_1_ROW, ER_THD(thd, ER_SUBQUERY_NO_1_ROW), - MYF(current_thd->lex->ignore ? ME_JUST_WARNING : 0)); + MYF(current_thd->lex->ignore ? ME_WARNING : 0)); DBUG_RETURN(1); } if (unit->offset_limit_cnt) @@ -3601,18 +3613,15 @@ bool select_max_min_finder_subselect::cmp_int() bool select_max_min_finder_subselect::cmp_decimal() { Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0); - my_decimal cval, *cvalue= cache->val_decimal(&cval); - my_decimal mval, *mvalue= maxmin->val_decimal(&mval); + VDec cvalue(cache), mvalue(maxmin); /* Ignore NULLs for ANY and keep them for ALL subqueries */ - if (cache->null_value) - return (is_all && !maxmin->null_value) || (!is_all && maxmin->null_value); - if (maxmin->null_value) + if (cvalue.is_null()) + return (is_all && !mvalue.is_null()) || (!is_all && mvalue.is_null()); + if (mvalue.is_null()) return !is_all; - if (fmax) - return (my_decimal_cmp(cvalue, mvalue) > 0) ; - return (my_decimal_cmp(cvalue,mvalue) < 0); + return fmax ? cvalue.cmp(mvalue) > 0 : cvalue.cmp(mvalue) < 0; } bool select_max_min_finder_subselect::cmp_str() @@ -7722,7 +7731,7 @@ Query_arena_stmt::~Query_arena_stmt() bool THD::timestamp_to_TIME(MYSQL_TIME *ltime, my_time_t ts, - ulong sec_part, ulonglong fuzzydate) + ulong sec_part, date_mode_t fuzzydate) { time_zone_used= 1; if (ts == 0 && sec_part == 0) diff --git a/sql/sql_class.h b/sql/sql_class.h index 1a7eb943193..b1da6e19247 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -38,15 +38,14 @@ #include "thr_timer.h" #include "thr_malloc.h" #include "log_slow.h" /* LOG_SLOW_DISABLE_... */ - #include "sql_digest_stream.h" // sql_digest_state - #include <mysql/psi/mysql_stage.h> #include <mysql/psi/mysql_statement.h> #include <mysql/psi/mysql_idle.h> #include <mysql/psi/mysql_table.h> #include <mysql_com_server.h> #include "session_tracker.h" +#include "backup.h" extern "C" void set_thd_stage_info(void *thd, @@ -156,8 +155,15 @@ enum enum_binlog_row_image { #define MODE_HIGH_NOT_PRECEDENCE (1ULL << 29) #define MODE_NO_ENGINE_SUBSTITUTION (1ULL << 30) #define MODE_PAD_CHAR_TO_FULL_LENGTH (1ULL << 31) +/* SQL mode bits defined above are common for MariaDB and MySQL */ +#define MODE_MASK_MYSQL_COMPATIBLE 0xFFFFFFFFULL +/* The following modes are specific to MariaDB */ #define MODE_EMPTY_STRING_IS_NULL (1ULL << 32) #define MODE_SIMULTANEOUS_ASSIGNMENT (1ULL << 33) +#define MODE_TIME_ROUND_FRACTIONAL (1ULL << 34) +/* The following modes are specific to MySQL */ +#define MODE_MYSQL80_TIME_TRUNCATE_FRACTIONAL (1ULL << 32) + /* Bits for different old style modes */ #define OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE (1 << 0) @@ -718,6 +724,7 @@ typedef struct system_variables ulong session_track_transaction_info; my_bool session_track_schema; my_bool session_track_state_change; + my_bool tcp_nodelay; ulong threadpool_priority; @@ -1945,42 +1952,22 @@ public: Global_read_lock() : m_state(GRL_NONE), - m_mdl_global_shared_lock(NULL), - m_mdl_blocks_commits_lock(NULL) + m_mdl_global_read_lock(NULL) {} bool lock_global_read_lock(THD *thd); void unlock_global_read_lock(THD *thd); - /** - Check if this connection can acquire protection against GRL and - emit error if otherwise. - */ - bool can_acquire_protection() const - { - if (m_state) - { - my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0)); - return TRUE; - } - return FALSE; - } bool make_global_read_lock_block_commit(THD *thd); bool is_acquired() const { return m_state != GRL_NONE; } void set_explicit_lock_duration(THD *thd); private: enum_grl_state m_state; /** - In order to acquire the global read lock, the connection must - acquire shared metadata lock in GLOBAL namespace, to prohibit - all DDL. - */ - MDL_ticket *m_mdl_global_shared_lock; - /** - Also in order to acquire the global read lock, the connection - must acquire a shared metadata lock in COMMIT namespace, to - prohibit commits. + Global read lock is acquired in two steps: + 1. acquire MDL_BACKUP_FTWRL1 in BACKUP namespace to prohibit DDL and DML + 2. upgrade to MDL_BACKUP_FTWRL2 to prohibit commits */ - MDL_ticket *m_mdl_blocks_commits_lock; + MDL_ticket *m_mdl_global_read_lock; }; @@ -2192,6 +2179,7 @@ public: rpl_io_thread_info *rpl_io_info; rpl_sql_thread_info *rpl_sql_info; } system_thread_info; + MDL_ticket *mdl_backup_ticket; void reset_for_next_command(bool do_clear_errors= 1); /* @@ -2977,6 +2965,7 @@ public: uint tmp_table, global_disable_checkpoint; uint server_status,open_options; enum enum_thread_type system_thread; + enum backup_stages current_backup_stage; /* Current or next transaction isolation level. When a connection is established, the value is taken from @@ -3123,6 +3112,9 @@ public: it returned an error on master, and this is OK on the slave. */ bool is_slave_error; + /* True if we have printed something to the error log for this statement */ + bool error_printed_to_log; + /* True when a transaction is queued up for binlog group commit. Used so that if another transaction needs to wait for a row lock held by @@ -3406,11 +3398,20 @@ public: } const Type_handler *type_handler_for_date() const; bool timestamp_to_TIME(MYSQL_TIME *ltime, my_time_t ts, - ulong sec_part, ulonglong fuzzydate); + ulong sec_part, date_mode_t fuzzydate); inline my_time_t query_start() { return start_time; } inline ulong query_start_sec_part() { query_start_sec_part_used=1; return start_time_sec_part; } MYSQL_TIME query_start_TIME(); + Timeval query_start_timeval() + { + return Timeval(query_start(), query_start_sec_part()); + } + time_round_mode_t temporal_round_mode() const + { + return variables.sql_mode & MODE_TIME_ROUND_FRACTIONAL ? + TIME_FRAC_ROUND : TIME_FRAC_TRUNCATE; + } private: struct { @@ -3602,6 +3603,15 @@ public: { return server_status & SERVER_STATUS_IN_TRANS; } + void give_protection_error(); + inline bool has_read_only_protection() + { + if (current_backup_stage == BACKUP_FINISHED && + !global_read_lock.is_acquired()) + return FALSE; + give_protection_error(); + return TRUE; + } inline bool fill_derived_tables() { return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure(); @@ -4372,6 +4382,80 @@ private: return raised; } +private: + void push_warning_truncated_priv(Sql_condition::enum_warning_level level, + uint sql_errno, + const char *type_str, const char *val) + { + DBUG_ASSERT(sql_errno == ER_TRUNCATED_WRONG_VALUE || + sql_errno == ER_WRONG_VALUE); + char buff[MYSQL_ERRMSG_SIZE]; + CHARSET_INFO *cs= &my_charset_latin1; + cs->cset->snprintf(cs, buff, sizeof(buff), + ER_THD(this, sql_errno), type_str, val); + /* + Note: the format string can vary between ER_TRUNCATED_WRONG_VALUE + and ER_WRONG_VALUE, but the code passed to push_warning() is + always ER_TRUNCATED_WRONG_VALUE. This is intentional. + */ + push_warning(this, level, ER_TRUNCATED_WRONG_VALUE, buff); + } +public: + void push_warning_truncated_wrong_value(Sql_condition::enum_warning_level level, + const char *type_str, const char *val) + { + return push_warning_truncated_priv(level, ER_TRUNCATED_WRONG_VALUE, + type_str, val); + } + void push_warning_wrong_value(Sql_condition::enum_warning_level level, + const char *type_str, const char *val) + { + return push_warning_truncated_priv(level, ER_WRONG_VALUE, type_str, val); + } + void push_warning_truncated_wrong_value(const char *type_str, const char *val) + { + return push_warning_truncated_wrong_value(Sql_condition::WARN_LEVEL_WARN, + type_str, val); + } + void push_warning_truncated_value_for_field(Sql_condition::enum_warning_level + level, const char *type_str, + const char *val, + const TABLE_SHARE *s, + const char *name) + { + DBUG_ASSERT(name); + char buff[MYSQL_ERRMSG_SIZE]; + CHARSET_INFO *cs= &my_charset_latin1; + const char *db_name= s ? s->db.str : NULL; + const char *table_name= s ? s->error_table_name() : NULL; + + if (!db_name) + db_name= ""; + if (!table_name) + table_name= ""; + cs->cset->snprintf(cs, buff, sizeof(buff), + ER_THD(this, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), + type_str, val, db_name, table_name, name, + (ulong) get_stmt_da()->current_row_for_warning()); + push_warning(this, level, ER_TRUNCATED_WRONG_VALUE, buff); + + } + void push_warning_wrong_or_truncated_value(Sql_condition::enum_warning_level level, + bool totally_useless_value, + const char *type_str, + const char *val, + const TABLE_SHARE *s, + const char *field_name) + { + if (field_name) + push_warning_truncated_value_for_field(level, type_str, val, + s, field_name); + else if (totally_useless_value) + push_warning_wrong_value(level, type_str, val); + else + push_warning_truncated_wrong_value(level, type_str, val); + } + public: /** Overloaded to guard query/query_length fields */ virtual void set_statement(Statement *stmt); @@ -4886,10 +4970,18 @@ my_eof(THD *thd) (A)->variables.sql_log_bin_off= 0;} -inline sql_mode_t sql_mode_for_dates(THD *thd) +inline date_conv_mode_t sql_mode_for_dates(THD *thd) { - return thd->variables.sql_mode & - (MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE | MODE_INVALID_DATES); + static_assert((date_conv_mode_t::KNOWN_MODES & + time_round_mode_t::KNOWN_MODES) == 0, + "date_conv_mode_t and time_round_mode_t must use different " + "bit values"); + static_assert(MODE_NO_ZERO_DATE == date_mode_t::NO_ZERO_DATE && + MODE_NO_ZERO_IN_DATE == date_mode_t::NO_ZERO_IN_DATE && + MODE_INVALID_DATES == date_mode_t::INVALID_DATES, + "sql_mode_t and date_mode_t values must be equal"); + return date_conv_mode_t(thd->variables.sql_mode & + (MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE | MODE_INVALID_DATES)); } /* @@ -6029,6 +6121,10 @@ class multi_delete :public select_result_interceptor bool error_handled; public: + // Methods used by ColumnStore + uint get_num_of_tables() const { return num_of_tables; } + TABLE_LIST* get_tables() const { return delete_tables; } +public: multi_delete(THD *thd_arg, TABLE_LIST *dt, uint num_of_tables); ~multi_delete(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); @@ -6336,7 +6432,8 @@ public: inline bool add_item_to_list(THD *thd, Item *item) { - return thd->lex->current_select->add_item_to_list(thd, item); + bool res= thd->lex->current_select->add_item_to_list(thd, item); + return res; } inline bool add_value_to_list(THD *thd, Item *value) diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h index 1c4c89eb132..345ed57ee30 100644 --- a/sql/sql_cmd.h +++ b/sql/sql_cmd.h @@ -108,6 +108,7 @@ enum enum_sql_command { SQLCOM_SHOW_STATUS_PACKAGE, SQLCOM_SHOW_STATUS_PACKAGE_BODY, SQLCOM_SHOW_PACKAGE_BODY_CODE, + SQLCOM_BACKUP, /* When a command is added here, be sure it's also added in mysqld.cc diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 24fd2c60503..c89f49aaefc 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -55,6 +55,14 @@ bool With_clause::add_with_element(With_element *elem) } +void st_select_lex_unit::set_with_clause(With_clause *with_cl) +{ + with_clause= with_cl; + if (with_clause) + with_clause->set_owner(this); +} + + /** @brief Check dependencies between tables defined in a list of with clauses @@ -682,7 +690,7 @@ void With_element::move_anchors_ahead() { st_select_lex *next_sl; st_select_lex *new_pos= spec->first_select(); - new_pos->linkage= UNION_TYPE; + new_pos->set_linkage(UNION_TYPE); for (st_select_lex *sl= new_pos; sl; sl= next_sl) { next_sl= sl->next_select(); @@ -691,9 +699,9 @@ void With_element::move_anchors_ahead() sl->move_node(new_pos); if (new_pos == spec->first_select()) { - enum sub_select_type type= new_pos->linkage; - new_pos->linkage= sl->linkage; - sl->linkage= type; + enum sub_select_type type= new_pos->get_linkage(); + new_pos->set_linkage(sl->get_linkage()); + sl->set_linkage(type); new_pos->with_all_modifier= sl->with_all_modifier; sl->with_all_modifier= false; } @@ -772,7 +780,7 @@ bool With_element::set_unparsed_spec(THD *thd, char *spec_start, char *spec_end, if (!unparsed_spec.str) { - my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), + my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), static_cast<int>(unparsed_spec.length)); return true; } @@ -855,10 +863,9 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd, lex->sp_chistics= old_lex->sp_chistics; lex->stmt_lex= old_lex; - with_select= &lex->select_lex; - with_select->select_number= ++thd->lex->stmt_lex->current_select_number; parse_status= parse_sql(thd, &parser_state, 0); ((char*) &unparsed_spec.str[unparsed_spec.length])[0]= save_end; + with_select= lex->first_select_lex(); if (parse_status) goto err; @@ -1011,7 +1018,7 @@ bool With_element::prepare_unreferenced(THD *thd) rename_columns_of_derived_unit(thd, spec) || check_duplicate_names(thd, first_sl->item_list, 1))) rc= true; - + thd->lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED; return rc; } @@ -1122,7 +1129,8 @@ bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem) if(!(derived= with_elem->clone_parsed_spec(thd, this))) return true; } - derived->first_select()->linkage= DERIVED_TABLE_TYPE; + derived->first_select()->set_linkage(DERIVED_TABLE_TYPE); + select_lex->add_statistics(derived); with_elem->inc_references(); return false; } diff --git a/sql/sql_cte.h b/sql/sql_cte.h index bda62271649..03c697bf746 100644 --- a/sql/sql_cte.h +++ b/sql/sql_cte.h @@ -292,8 +292,7 @@ private: */ With_clause *next_with_clause; /* Set to true if dependencies between with elements have been checked */ - bool dependencies_are_checked; - + bool dependencies_are_checked; /* The bitmap of all recursive with elements whose specifications are not complied with restrictions imposed by the SQL standards @@ -317,9 +316,8 @@ public: bool with_recursive; With_clause(bool recursive_fl, With_clause *emb_with_clause) - : owner(NULL), - embedding_with_clause(emb_with_clause), next_with_clause(NULL), - dependencies_are_checked(false), unrestricted(0), + : owner(NULL), embedding_with_clause(emb_with_clause), + next_with_clause(NULL), dependencies_are_checked(false), unrestricted(0), with_prepared_anchor(0), cleaned(0), stabilized(0), with_recursive(recursive_fl) { } @@ -333,8 +331,12 @@ public: last_next= &this->next_with_clause; } + st_select_lex_unit *get_owner() { return owner; } + void set_owner(st_select_lex_unit *unit) { owner= unit; } + void attach_to(st_select_lex *select_lex); + With_clause *pop() { return embedding_with_clause; } bool check_dependencies(); @@ -367,7 +369,6 @@ bool With_element::is_unrestricted() } inline - bool With_element::is_with_prepared_anchor() { return owner->with_prepared_anchor & get_elem_map(); @@ -449,11 +450,14 @@ void With_element::prepare_for_next_iteration() inline -void st_select_lex_unit::set_with_clause(With_clause *with_cl) -{ - with_clause= with_cl; - if (with_clause) - with_clause->set_owner(this); +void With_clause::attach_to(st_select_lex *select_lex) +{ + for (With_element *with_elem= with_list.first; + with_elem; + with_elem= with_elem->next) + { + select_lex->register_unit(with_elem->spec, NULL); + } } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 6cf89ed09fc..148c2371a6b 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -290,7 +290,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, bool has_triggers; ORDER *order= (ORDER *) ((order_list && order_list->elements) ? order_list->first : NULL); - SELECT_LEX *select_lex= &thd->lex->select_lex; + SELECT_LEX *select_lex= thd->lex->first_select_lex(); killed_state killed_status= NOT_KILLED; THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE; bool binlog_is_row; @@ -352,7 +352,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_RETURN(TRUE); } table->map=1; - query_plan.select_lex= &thd->lex->select_lex; + query_plan.select_lex= thd->lex->first_select_lex(); query_plan.table= table; query_plan.updating_a_view= MY_TEST(table_list->view); @@ -384,7 +384,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, setup_order(thd, select_lex->ref_pointer_array, &tables, fields, all_fields, order)) { - free_underlaid_joins(thd, &thd->lex->select_lex); + free_underlaid_joins(thd, thd->lex->first_select_lex()); DBUG_RETURN(TRUE); } } @@ -770,7 +770,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, else { table->file->print_error(error, - MYF(thd->lex->ignore ? ME_JUST_WARNING : 0)); + MYF(thd->lex->ignore ? ME_WARNING : 0)); if (thd->is_error()) { error= 1; @@ -931,14 +931,16 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, bool *delete_while_scanning) { Item *fake_conds= 0; - SELECT_LEX *select_lex= &thd->lex->select_lex; + SELECT_LEX *select_lex= thd->lex->first_select_lex(); DBUG_ENTER("mysql_prepare_delete"); List<Item> all_fields; *delete_while_scanning= true; thd->lex->allow_sum_func.clear_all(); - if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, - &thd->lex->select_lex.top_join_list, + if (setup_tables_and_check_access(thd, + &thd->lex->first_select_lex()->context, + &thd->lex->first_select_lex()-> + top_join_list, table_list, select_lex->leaf_tables, FALSE, DELETE_ACL, SELECT_ACL, TRUE)) @@ -1021,21 +1023,23 @@ int mysql_multi_delete_prepare(THD *thd) lex->query_tables also point on local list of DELETE SELECT_LEX */ - if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, - &thd->lex->select_lex.top_join_list, + if (setup_tables_and_check_access(thd, + &thd->lex->first_select_lex()->context, + &thd->lex->first_select_lex()-> + top_join_list, lex->query_tables, - lex->select_lex.leaf_tables, FALSE, - DELETE_ACL, SELECT_ACL, FALSE)) + lex->first_select_lex()->leaf_tables, + FALSE, DELETE_ACL, SELECT_ACL, FALSE)) DBUG_RETURN(TRUE); - if (lex->select_lex.handle_derived(thd->lex, DT_MERGE)) + if (lex->first_select_lex()->handle_derived(thd->lex, DT_MERGE)) DBUG_RETURN(TRUE); /* Multi-delete can't be constructed over-union => we always have single SELECT on top and have to check underlying SELECTs of it */ - lex->select_lex.exclude_from_table_unique_test= TRUE; + lex->first_select_lex()->exclude_from_table_unique_test= TRUE; /* Fix tables-to-be-deleted-from list to point at opened tables */ for (target_tbl= (TABLE_LIST*) aux_tables; target_tbl; @@ -1077,8 +1081,8 @@ int mysql_multi_delete_prepare(THD *thd) Reset the exclude flag to false so it doesn't interfare with further calls to unique_table */ - lex->select_lex.exclude_from_table_unique_test= FALSE; - + lex->first_select_lex()->exclude_from_table_unique_test= FALSE; + if (lex->save_prep_leaf_tables()) DBUG_RETURN(TRUE); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 589d0214292..878aa715b84 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -99,7 +99,8 @@ mysql_handle_derived(LEX *lex, uint phases) processed normally. */ if (phases == DT_MERGE_FOR_INSERT && - cursor && cursor->top_table()->select_lex != &lex->select_lex) + cursor && (cursor->top_table()->select_lex != + lex->first_select_lex())) continue; for (; cursor && !res; @@ -1242,25 +1243,61 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) /** @brief - Extract the condition depended on derived table/view and pushed it there + Extract condition that can be pushed into a derived table/view - @param thd The thread handle - @param cond The condition from which to extract the pushed condition - @param derived The reference to the derived table/view + @param thd the thread handle + @param cond current condition + @param derived the reference to the derived table/view @details - This functiom builds the most restrictive condition depending only on - the derived table/view that can be extracted from the condition cond. - The built condition is pushed into the having clauses of the - selects contained in the query specifying the derived table/view. - The function also checks for each select whether any condition depending - only on grouping fields can be extracted from the pushed condition. - If so, it pushes the condition over grouping fields into the where - clause of the select. - - @retval - true if an error is reported - false otherwise + This function builds the most restrictive condition depending only on + the derived table/view (directly or indirectly through equality) that + can be extracted from the given condition cond and pushes it into the + derived table/view. + + Example of the transformation: + + SELECT * + FROM t1, + ( + SELECT x,MAX(y) AS max_y + FROM t2 + GROUP BY x + ) AS d_tab + WHERE d_tab.x>1 AND d_tab.max_y<30; + + => + + SELECT * + FROM t1, + ( + SELECT x,z,MAX(y) AS max_y + FROM t2 + WHERE x>1 + HAVING max_y<30 + GROUP BY x + ) AS d_tab + WHERE d_tab.x>1 AND d_tab.max_y<30; + + In details: + 1. Check what pushable formula can be extracted from cond + 2. Build a clone PC of the formula that can be extracted + (the clone is built only if the extracted formula is a AND subformula + of cond or conjunction of such subformulas) + Do for every select specifying derived table/view: + 3. If there is no HAVING clause prepare PC to be conjuncted with + WHERE clause of the select. Otherwise do 4-7. + 4. Check what formula PC_where can be extracted from PC to be pushed + into the WHERE clause of the select + 5. Build PC_where and if PC_where is a conjunct(s) of PC remove it from PC + getting PC_having + 6. Prepare PC_where to be conjuncted with the WHERE clause of the select + 7. Prepare PC_having to be conjuncted with the HAVING clause of the select + @note + This method is similar to pushdown_cond_for_in_subquery() + + @retval TRUE if an error occurs + @retval FALSE otherwise */ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) @@ -1300,63 +1337,25 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) if (!some_select_allows_cond_pushdown) DBUG_RETURN(false); - /* - Build the most restrictive condition extractable from 'cond' - that can be pushed into the derived table 'derived'. - All subexpressions of this condition are cloned from the - subexpressions of 'cond'. - This condition has to be fixed yet. - */ + /* 1. Check what pushable formula can be extracted from cond */ Item *extracted_cond; - derived->check_pushable_cond_for_table(cond); - extracted_cond= derived->build_pushable_cond_for_table(thd, cond); + cond->check_pushable_cond(&Item::pushable_cond_checker_for_derived, + (uchar *)(&derived->table->map)); + /* 2. Build a clone PC of the formula that can be extracted */ + extracted_cond= + cond->build_pushable_cond(thd, + &Item::pushable_equality_checker_for_derived, + ((uchar *)&derived->table->map)); if (!extracted_cond) { /* Nothing can be pushed into the derived table */ DBUG_RETURN(false); } - /* Push extracted_cond into every select of the unit specifying 'derived' */ + st_select_lex *save_curr_select= thd->lex->current_select; for (; sl; sl= sl->next_select()) { Item *extracted_cond_copy; - if (!sl->cond_pushdown_is_allowed()) - continue; - thd->lex->current_select= sl; - if (sl->have_window_funcs()) - { - if (sl->join->group_list || sl->join->implicit_grouping) - continue; - ORDER *common_partition_fields= - sl->find_common_window_func_partition_fields(thd); - if (!common_partition_fields) - continue; - extracted_cond_copy= !sl->next_select() ? - extracted_cond : - extracted_cond->build_clone(thd); - if (!extracted_cond_copy) - continue; - - Item *cond_over_partition_fields;; - sl->collect_grouping_fields(thd, common_partition_fields); - sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy, - derived); - cond_over_partition_fields= - sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true); - if (cond_over_partition_fields) - cond_over_partition_fields= cond_over_partition_fields->transform(thd, - &Item::derived_grouping_field_transformer_for_where, - (uchar*) sl); - if (cond_over_partition_fields) - { - cond_over_partition_fields->walk( - &Item::cleanup_excluding_const_fields_processor, 0, 0); - sl->cond_pushed_into_where= cond_over_partition_fields; - } - - continue; - } - /* For each select of the unit except the last one create a clone of extracted_cond @@ -1367,71 +1366,43 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) if (!extracted_cond_copy) continue; - if (!sl->join->group_list && !sl->with_sum_func) - { - /* extracted_cond_copy is pushed into where of sl */ - extracted_cond_copy= extracted_cond_copy->transform(thd, - &Item::derived_field_transformer_for_where, - (uchar*) sl); - if (extracted_cond_copy) - { - extracted_cond_copy->walk( - &Item::cleanup_excluding_const_fields_processor, 0, 0); - sl->cond_pushed_into_where= extracted_cond_copy; - } - - continue; - } - - /* - Figure out what can be extracted from the pushed condition - that could be pushed into the where clause of sl - */ - Item *cond_over_grouping_fields; - sl->collect_grouping_fields(thd, sl->join->group_list); - sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy, - derived); - cond_over_grouping_fields= - sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true); - - /* - Transform the references to the 'derived' columns from the condition - pushed into the where clause of sl to make them usable in the new context - */ - if (cond_over_grouping_fields) - cond_over_grouping_fields= cond_over_grouping_fields->transform(thd, - &Item::derived_grouping_field_transformer_for_where, - (uchar*) sl); - - if (cond_over_grouping_fields) + /* Collect fields that are used in the GROUP BY of sl */ + if (sl->have_window_funcs()) { - /* - In extracted_cond_copy remove top conjuncts that - has been pushed into the where clause of sl - */ - extracted_cond_copy= remove_pushed_top_conjuncts(thd, extracted_cond_copy); - - cond_over_grouping_fields->walk( - &Item::cleanup_excluding_const_fields_processor, 0, 0); - sl->cond_pushed_into_where= cond_over_grouping_fields; - - if (!extracted_cond_copy) + if (sl->group_list.first || sl->join->implicit_grouping) continue; + ORDER *common_partition_fields= + sl->find_common_window_func_partition_fields(thd); + if (!common_partition_fields) + continue; + sl->collect_grouping_fields(thd, common_partition_fields); } + else + sl->collect_grouping_fields(thd, sl->group_list.first); + + Item *remaining_cond= NULL; + /* Do 4-6 */ + sl->pushdown_cond_into_where_clause(thd, extracted_cond_copy, + &remaining_cond, + &Item::derived_field_transformer_for_where, + (uchar *) sl); + if (!remaining_cond) + continue; /* - Transform the references to the 'derived' columns from the condition - pushed into the having clause of sl to make them usable in the new context + 7. Prepare PC_having to be conjuncted with the HAVING clause of + the select */ - extracted_cond_copy= extracted_cond_copy->transform(thd, - &Item::derived_field_transformer_for_having, - (uchar*) sl); - if (!extracted_cond_copy) + remaining_cond= + remaining_cond->transform(thd, + &Item::derived_field_transformer_for_having, + (uchar *) sl); + if (!remaining_cond) continue; - extracted_cond_copy->walk(&Item::cleanup_excluding_const_fields_processor, - 0, 0); - sl->cond_pushed_into_having= extracted_cond_copy; + remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor, + 0, 0); + sl->cond_pushed_into_having= remaining_cond; } thd->lex->current_select= save_curr_select; DBUG_RETURN(false); diff --git a/sql/sql_do.cc b/sql/sql_do.cc index 2a4e43ab78a..1652b313909 100644 --- a/sql/sql_do.cc +++ b/sql/sql_do.cc @@ -33,7 +33,7 @@ bool mysql_do(THD *thd, List<Item> &values) DBUG_RETURN(TRUE); while ((value = li++)) (void) value->is_null(); - free_underlaid_joins(thd, &thd->lex->select_lex); + free_underlaid_joins(thd, thd->lex->first_select_lex()); if (unlikely(thd->is_error())) { diff --git a/sql/sql_error.cc b/sql/sql_error.cc index d6f5b99eef6..8d639f9271d 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -781,7 +781,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show) List<Item> field_list; MEM_ROOT *mem_root= thd->mem_root; const Sql_condition *err; - SELECT_LEX *sel= &thd->lex->select_lex; + SELECT_LEX *sel= thd->lex->first_select_lex(); SELECT_LEX_UNIT *unit= &thd->lex->unit; ulonglong idx= 0; Protocol *protocol=thd->protocol; diff --git a/sql/sql_error.h b/sql/sql_error.h index 822503f89d3..6586c49a125 100644 --- a/sql/sql_error.h +++ b/sql/sql_error.h @@ -814,11 +814,48 @@ private: extern char *err_conv(char *buff, uint to_length, const char *from, uint from_length, CHARSET_INFO *from_cs); -class ErrConv +class ErrBuff { protected: mutable char err_buffer[MYSQL_ERRMSG_SIZE]; public: + ErrBuff() + { + err_buffer[0]= '\0'; + } + const char *ptr() const { return err_buffer; } + const char *set_longlong(const Longlong_hybrid &nr) const + { + return nr.is_unsigned() ? ullstr(nr.value(), err_buffer) : + llstr(nr.value(), err_buffer); + } + const char *set_double(double nr) const + { + my_gcvt(nr, MY_GCVT_ARG_DOUBLE, sizeof(err_buffer), err_buffer, 0); + return err_buffer; + } + const char *set_decimal(const decimal_t *d) const + { + int len= sizeof(err_buffer); + decimal2string(d, err_buffer, &len, 0, 0, ' '); + return err_buffer; + } + const char *set_str(const char *str, size_t len, CHARSET_INFO *cs) const + { + DBUG_ASSERT(len < UINT_MAX32); + return err_conv(err_buffer, (uint) sizeof(err_buffer), str, (uint) len, cs); + } + const char *set_mysql_time(const MYSQL_TIME *ltime) const + { + my_TIME_to_str(ltime, err_buffer, AUTO_SEC_PART_DIGITS); + return err_buffer; + } +}; + + +class ErrConv: public ErrBuff +{ +public: ErrConv() {} virtual ~ErrConv() {} virtual const char *ptr() const = 0; @@ -838,20 +875,18 @@ public: : ErrConv(), str(s->ptr()), len(s->length()), cs(s->charset()) {} const char *ptr() const { - DBUG_ASSERT(len < UINT_MAX32); - return err_conv(err_buffer, (uint) sizeof(err_buffer), str, (uint) len, cs); + return set_str(str, len, cs); } }; class ErrConvInteger : public ErrConv, public Longlong_hybrid { public: - ErrConvInteger(longlong num_arg, bool unsigned_flag= false) : - ErrConv(), Longlong_hybrid(num_arg, unsigned_flag) {} + ErrConvInteger(const Longlong_hybrid &nr) + : ErrConv(), Longlong_hybrid(nr) { } const char *ptr() const { - return m_unsigned ? ullstr(m_value, err_buffer) : - llstr(m_value, err_buffer); + return set_longlong(static_cast<Longlong_hybrid>(*this)); } }; @@ -862,8 +897,7 @@ public: ErrConvDouble(double num_arg) : ErrConv(), num(num_arg) {} const char *ptr() const { - my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(err_buffer), err_buffer, 0); - return err_buffer; + return set_double(num); } }; @@ -874,8 +908,7 @@ public: ErrConvTime(const MYSQL_TIME *ltime_arg) : ErrConv(), ltime(ltime_arg) {} const char *ptr() const { - my_TIME_to_str(ltime, err_buffer, AUTO_SEC_PART_DIGITS); - return err_buffer; + return set_mysql_time(ltime); } }; @@ -886,9 +919,7 @@ public: ErrConvDecimal(const decimal_t *d_arg) : ErrConv(), d(d_arg) {} const char *ptr() const { - int len= sizeof(err_buffer); - decimal2string(d, err_buffer, &len, 0, 0, ' '); - return err_buffer; + return set_decimal(d); } }; diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 817447fe917..73b6f637a98 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -433,8 +433,6 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen) /* Always read all columns */ table->read_set= &table->s->all_set; - if (table->vcol_set) - table->vcol_set= &table->s->all_set; /* Restore the state. */ thd->set_open_tables(backup_open_tables); @@ -1198,10 +1196,10 @@ void mysql_ha_flush(THD *thd) @note Broadcasts refresh if it closed a table with old version. */ -void mysql_ha_cleanup(THD *thd) +void mysql_ha_cleanup_no_free(THD *thd) { SQL_HANDLER *hash_tables; - DBUG_ENTER("mysql_ha_cleanup"); + DBUG_ENTER("mysql_ha_cleanup_no_free"); for (uint i= 0; i < thd->handler_tables_hash.records; i++) { @@ -1209,9 +1207,15 @@ void mysql_ha_cleanup(THD *thd) if (hash_tables->table) mysql_ha_close_table(hash_tables); } + DBUG_VOID_RETURN; +} - my_hash_free(&thd->handler_tables_hash); +void mysql_ha_cleanup(THD *thd) +{ + DBUG_ENTER("mysql_ha_cleanup"); + mysql_ha_cleanup_no_free(thd); + my_hash_free(&thd->handler_tables_hash); DBUG_VOID_RETURN; } diff --git a/sql/sql_handler.h b/sql/sql_handler.h index 4c16f7e5c57..16063bb1f35 100644 --- a/sql/sql_handler.h +++ b/sql/sql_handler.h @@ -73,6 +73,7 @@ bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes, const char *, void mysql_ha_flush(THD *thd); void mysql_ha_flush_tables(THD *thd, TABLE_LIST *all_tables); void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables); +void mysql_ha_cleanup_no_free(THD *thd); void mysql_ha_cleanup(THD *thd); void mysql_ha_set_explicit_lock_duration(THD *thd); void mysql_ha_rm_temporary_tables(THD *thd); diff --git a/sql/sql_help.cc b/sql/sql_help.cc index aa9f3fedd6d..95bc6ade366 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -87,7 +87,7 @@ enum enum_used_fields static bool init_fields(THD *thd, TABLE_LIST *tables, struct st_find_field *find_fields, uint count) { - Name_resolution_context *context= &thd->lex->select_lex.context; + Name_resolution_context *context= &thd->lex->first_select_lex()->context; DBUG_ENTER("init_fields"); context->resolve_in_table_list_only(tables); for (; count-- ; find_fields++) @@ -719,10 +719,11 @@ static bool mysqld_help_internal(THD *thd, const char *mask) Init tables and fields to be usable from items tables do not contain VIEWs => we can pass 0 as conds */ - thd->lex->select_lex.context.table_list= - thd->lex->select_lex.context.first_name_resolution_table= &tables[0]; - if (setup_tables(thd, &thd->lex->select_lex.context, - &thd->lex->select_lex.top_join_list, + thd->lex->first_select_lex()->context.table_list= + thd->lex->first_select_lex()->context.first_name_resolution_table= + &tables[0]; + if (setup_tables(thd, &thd->lex->first_select_lex()->context, + &thd->lex->first_select_lex()->top_join_list, tables, leaves, FALSE, FALSE)) goto error; memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields)); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 6e2fa5767f5..f5e4185db92 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -241,7 +241,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, } else { // Part field list - SELECT_LEX *select_lex= &thd->lex->select_lex; + SELECT_LEX *select_lex= thd->lex->first_select_lex(); Name_resolution_context *context= &select_lex->context; Name_resolution_context_state ctx_state; int res; @@ -273,7 +273,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, /* Restore the current context. */ ctx_state.restore_state(context, table_list); - thd->lex->select_lex.no_wrap_view_item= FALSE; + thd->lex->first_select_lex()->no_wrap_view_item= FALSE; if (res) DBUG_RETURN(-1); @@ -547,10 +547,10 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list) If this goes ok, the tickets are cloned and added to the list of granted locks held by the handler thread. */ - if (thd->global_read_lock.can_acquire_protection()) + if (thd->has_read_only_protection()) DBUG_RETURN(TRUE); - protection_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, + protection_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_DML, MDL_STATEMENT); if (thd->mdl_context.acquire_lock(&protection_request, @@ -640,7 +640,7 @@ create_insert_stmt_from_insert_delayed(THD *thd, String *buf) if (buf->append(thd->query()) || buf->replace(thd->lex->keyword_delayed_begin_offset, thd->lex->keyword_delayed_end_offset - - thd->lex->keyword_delayed_begin_offset, 0)) + thd->lex->keyword_delayed_begin_offset, NULL, 0)) return 1; return 0; } @@ -657,7 +657,7 @@ static void save_insert_query_plan(THD* thd, TABLE_LIST *table_list) bool skip= MY_TEST(table_list->view); /* Save subquery children */ - for (SELECT_LEX_UNIT *unit= thd->lex->select_lex.first_inner_unit(); + for (SELECT_LEX_UNIT *unit= thd->lex->first_select_lex()->first_inner_unit(); unit; unit= unit->next_unit()) { @@ -777,7 +777,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, /* mysql_prepare_insert sets table_list->table if it was not set */ table= table_list->table; - context= &thd->lex->select_lex.context; + context= &thd->lex->first_select_lex()->context; /* These three asserts test the hypothesis that the resetting of the name resolution context below is not necessary at all since the list of local @@ -1070,7 +1070,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, } while (bulk_parameters_iterations(thd)); values_loop_end: - free_underlaid_joins(thd, &thd->lex->select_lex); + free_underlaid_joins(thd, thd->lex->first_select_lex()); joins_freed= TRUE; /* @@ -1259,7 +1259,7 @@ abort: table->file->ha_release_auto_increment(); if (!joins_freed) - free_underlaid_joins(thd, &thd->lex->select_lex); + free_underlaid_joins(thd, thd->lex->first_select_lex()); thd->abort_on_warning= 0; DBUG_RETURN(retval); } @@ -1289,7 +1289,7 @@ abort: static bool check_view_insertability(THD * thd, TABLE_LIST *view) { - uint num= view->view->select_lex.item_list.elements; + uint num= view->view->first_select_lex()->item_list.elements; TABLE *table= view->table; Field_translator *trans_start= view->field_translation, *trans_end= trans_start + num; @@ -1389,10 +1389,12 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, than INSERT. */ - if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, - &thd->lex->select_lex.top_join_list, + if (setup_tables_and_check_access(thd, + &thd->lex->first_select_lex()->context, + &thd->lex->first_select_lex()-> + top_join_list, table_list, - thd->lex->select_lex.leaf_tables, + thd->lex->first_select_lex()->leaf_tables, select_insert, INSERT_ACL, SELECT_ACL, TRUE)) DBUG_RETURN(TRUE); @@ -1400,7 +1402,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, if (insert_into_view && !fields.elements) { thd->lex->empty_field_list_on_rset= 1; - if (!thd->lex->select_lex.leaf_tables.head()->table || + if (!thd->lex->first_select_lex()->leaf_tables.head()->table || table_list->is_multitable()) { my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0), @@ -1474,7 +1476,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, enum_duplicates duplic, COND **where, bool select_insert) { - SELECT_LEX *select_lex= &thd->lex->select_lex; + SELECT_LEX *select_lex= thd->lex->first_select_lex(); Name_resolution_context *context= &select_lex->context; Name_resolution_context_state ctx_state; bool insert_into_view= (table_list->view != 0); @@ -1719,7 +1721,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) */ if (info->ignore) { - table->file->print_error(error, MYF(ME_JUST_WARNING)); + table->file->print_error(error, MYF(ME_WARNING)); goto ok_or_after_trg_err; /* Ignoring a not fatal error, return 0 */ } goto err; @@ -1844,7 +1846,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) { if (!(thd->variables.old_behavior & OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) - table->file->print_error(error, MYF(ME_JUST_WARNING)); + table->file->print_error(error, MYF(ME_WARNING)); goto ok_or_after_trg_err; } goto err; @@ -2025,7 +2027,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) goto err; if (!(thd->variables.old_behavior & OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) - table->file->print_error(error, MYF(ME_JUST_WARNING)); + table->file->print_error(error, MYF(ME_WARNING)); table->file->restore_auto_increment(prev_insert_id); goto ok_or_after_trg_err; } @@ -2359,7 +2361,7 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, di->thd.set_db(&table_list->db); di->thd.set_query(my_strndup(table_list->table_name.str, table_list->table_name.length, - MYF(MY_WME | ME_FATALERROR)), + MYF(MY_WME | ME_FATAL)), table_list->table_name.length, system_charset_info); if (di->thd.db.str == NULL || di->thd.query() == NULL) { @@ -2372,9 +2374,12 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, di->table_list.alias.str= di->table_list.table_name.str= di->thd.query(); di->table_list.alias.length= di->table_list.table_name.length= di->thd.query_length(); di->table_list.db= di->thd.db; - /* We need the tickets so that they can be cloned in handle_delayed_insert */ - di->grl_protection.init(MDL_key::GLOBAL, "", "", - MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT); + /* + We need the tickets so that they can be cloned in + handle_delayed_insert + */ + di->grl_protection.init(MDL_key::BACKUP, "", "", + MDL_BACKUP_DML, MDL_STATEMENT); di->grl_protection.ticket= grl_protection_request->ticket; init_mdl_requests(&di->table_list); di->table_list.mdl_request.ticket= table_list->mdl_request.ticket; @@ -2391,7 +2396,7 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, mysql_mutex_unlock(&di->mutex); di->unlock(); delete di; - my_error(ER_CANT_CREATE_THREAD, MYF(ME_FATALERROR), error); + my_error(ER_CANT_CREATE_THREAD, MYF(ME_FATAL), error); goto end_create; } @@ -2449,10 +2454,12 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, } /* Unlock the delayed insert object after its last access. */ di->unlock(); - DBUG_RETURN((table_list->table == NULL)); + DBUG_PRINT("exit", ("table_list->table: %p", table_list->table)); + DBUG_RETURN(thd->is_error()); end_create: mysql_mutex_unlock(&LOCK_delayed_create); + DBUG_PRINT("exit", ("is_error: %d", thd->is_error())); DBUG_RETURN(thd->is_error()); } @@ -2507,24 +2514,27 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) if (thd.killed) { /* - Copy the error message. Note that we don't treat fatal - errors in the delayed thread as fatal errors in the - main thread. If delayed thread was killed, we don't - want to send "Server shutdown in progress" in the - INSERT THREAD. - - The thread could be killed with an error message if - di->handle_inserts() or di->open_and_lock_table() fails. - The thread could be killed without an error message if - killed using THD::notify_shared_lock() or - kill_delayed_threads_for_table(). + Check how the insert thread was killed. If it was killed + by FLUSH TABLES which calls kill_delayed_threads_for_table(), + then is_error is not set. + In this case, return without setting an error, + which means that the insert will be converted to a normal insert. */ - if (!thd.is_error()) - my_message(ER_QUERY_INTERRUPTED, ER_THD(&thd, ER_QUERY_INTERRUPTED), - MYF(0)); - else + if (thd.is_error()) + { + /* + Copy the error message. Note that we don't treat fatal + errors in the delayed thread as fatal errors in the + main thread. If delayed thread was killed, we don't + want to send "Server shutdown in progress" in the + INSERT THREAD. + + The thread could be killed with an error message if + di->handle_inserts() or di->open_and_lock_table() fails. + */ my_message(thd.get_stmt_da()->sql_errno(), thd.get_stmt_da()->message(), MYF(0)); + } goto error; } } @@ -2605,10 +2615,6 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) share->default_fields) { bool error_reported= FALSE; - if (unlikely(!(copy->def_vcol_set= - (MY_BITMAP*) alloc_root(client_thd->mem_root, - sizeof(MY_BITMAP))))) - goto error; if (unlikely(parse_vcol_defs(client_thd, client_thd->mem_root, copy, &error_reported))) goto error; @@ -2627,15 +2633,6 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) copy->def_write_set.bitmap= ((my_bitmap_map*) (bitmap + share->column_bitmap_size)); bitmaps_used= 2; - if (share->virtual_fields) - { - my_bitmap_init(copy->def_vcol_set, - (my_bitmap_map*) (bitmap + - bitmaps_used*share->column_bitmap_size), - share->fields, FALSE); - bitmaps_used++; - copy->vcol_set= copy->def_vcol_set; - } if (share->default_fields || share->default_expressions) { my_bitmap_init(©->has_value_set, @@ -3097,11 +3094,30 @@ pthread_handler_t handle_delayed_insert(void *arg) mysql_mutex_unlock(&di->thd.mysys_var->mutex); mysql_mutex_lock(&di->mutex); } + + /* + The code depends on that the following ASSERT always hold. + I don't want to accidently introduce and bugs in the following code + in this commit, so I leave the small cleaning up of the code to + a future commit + */ + DBUG_ASSERT(thd->lock || di->stacked_inserts == 0); + DBUG_PRINT("delayed", - ("thd->killed: %d di->tables_in_use: %d thd->lock: %d", - thd->killed, di->tables_in_use, thd->lock != 0)); + ("thd->killed: %d di->status: %d di->stacked_insert: %d di->tables_in_use: %d thd->lock: %d", + thd->killed, di->status, di->stacked_inserts, di->tables_in_use, thd->lock != 0)); - if (di->tables_in_use && ! thd->lock && !thd->killed) + /* + This is used to test see what happens if killed is sent before + we have time to handle the insert requests. + */ + DBUG_EXECUTE_IF("write_delay_wakeup", + if (!thd->killed && di->stacked_inserts) + my_sleep(500000); + ); + + if (di->tables_in_use && ! thd->lock && + (!thd->killed || di->stacked_inserts)) { /* Request for new delayed insert. @@ -3261,7 +3277,7 @@ bool Delayed_insert::handle_inserts(void) or if another thread is removing the current table definition from the table cache. */ - my_error(ER_DELAYED_CANT_CHANGE_LOCK, MYF(ME_FATALERROR | ME_NOREFRESH), + my_error(ER_DELAYED_CANT_CHANGE_LOCK, MYF(ME_FATAL | ME_ERROR_LOG), table->s->table_name.str); goto err; } @@ -3434,7 +3450,7 @@ bool Delayed_insert::handle_inserts(void) { /* This is not known to happen. */ my_error(ER_DELAYED_CANT_CHANGE_LOCK, - MYF(ME_FATALERROR | ME_NOREFRESH), + MYF(ME_FATAL | ME_ERROR_LOG), table->s->table_name.str); goto err; } @@ -3530,7 +3546,7 @@ bool Delayed_insert::handle_inserts(void) bool mysql_insert_select_prepare(THD *thd) { LEX *lex= thd->lex; - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); DBUG_ENTER("mysql_insert_select_prepare"); @@ -3619,7 +3635,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) select, LEX::current_select should point to the first select while we are fixing fields from insert list. */ - lex->current_select= &lex->select_lex; + lex->current_select= lex->first_select_lex(); res= (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, NULL, 0) || @@ -3636,7 +3652,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) if (info.handle_duplicates == DUP_UPDATE && !res) { - Name_resolution_context *context= &lex->select_lex.context; + Name_resolution_context *context= &lex->first_select_lex()->context; Name_resolution_context_state ctx_state; /* Save the state of the current name resolution context. */ @@ -3646,7 +3662,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) table_list->next_local= 0; context->resolve_in_table_list_only(table_list); - lex->select_lex.no_wrap_view_item= TRUE; + lex->first_select_lex()->no_wrap_view_item= TRUE; res= res || check_update_fields(thd, context->table_list, *info.update_fields, *info.update_values, @@ -3657,22 +3673,26 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) */ true, &map); - lex->select_lex.no_wrap_view_item= FALSE; + lex->first_select_lex()->no_wrap_view_item= FALSE; /* - When we are not using GROUP BY and there are no ungrouped aggregate functions - we can refer to other tables in the ON DUPLICATE KEY part. - We use next_name_resolution_table descructively, so check it first (views?) + When we are not using GROUP BY and there are no ungrouped + aggregate functions we can refer to other tables in the ON + DUPLICATE KEY part. We use next_name_resolution_table + descructively, so check it first (views?) */ DBUG_ASSERT (!table_list->next_name_resolution_table); - if (lex->select_lex.group_list.elements == 0 && - !lex->select_lex.with_sum_func) + if (lex->first_select_lex()->group_list.elements == 0 && + !lex->first_select_lex()->with_sum_func) + { /* - We must make a single context out of the two separate name resolution contexts : - the INSERT table and the tables in the SELECT part of INSERT ... SELECT. - To do that we must concatenate the two lists + We must make a single context out of the two separate name + resolution contexts : the INSERT table and the tables in the + SELECT part of INSERT ... SELECT. To do that we must + concatenate the two lists */ table_list->next_name_resolution_table= ctx_state.get_first_name_resolution_table(); + } res= res || setup_fields(thd, Ref_ptr_array(), *info.update_values, MARK_COLUMNS_READ, 0, NULL, 0); @@ -3773,9 +3793,9 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) void DESCRIPTION - If the result table is the same as one of the source tables (INSERT SELECT), - the result table is not finally prepared at the join prepair phase. - Do the final preparation now. + If the result table is the same as one of the source tables + (INSERT SELECT), the result table is not finally prepared at the + join prepair phase. Do the final preparation now. RETURN 0 OK @@ -4081,9 +4101,9 @@ void select_insert::abort_result_set() { Field *Item::create_field_for_create_select(TABLE *table) { - Field *def_field, *tmp_field; - return ::create_tmp_field(table->in_use, table, this, type(), - (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0); + static Tmp_field_param param(false, false, false, false); + Tmp_field_src src; + return create_tmp_field_ex(table, &src, ¶m); } @@ -4400,8 +4420,6 @@ select_create::prepare(List<Item> &_values, SELECT_LEX_UNIT *u) thd->binlog_start_trans_and_stmt(); } - DEBUG_SYNC(thd,"create_table_select_before_check_if_exists"); - if (!(table= create_table_from_items(thd, &values, &extra_lock, hook_ptr))) /* abort() deletes table */ DBUG_RETURN(-1); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c048aeeb585..1b8f448553b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -174,7 +174,7 @@ init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex) { TABLE_LIST *table_list; Table_ident *table_ident; - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); Name_resolution_context *context= &select_lex->context; /* We will call the parser to create a part_info struct based on the @@ -635,6 +635,30 @@ void Lex_input_stream::reduce_digest_token(uint token_left, uint token_right) } } +/** + lex starting operations for builtin select collected together +*/ + +void SELECT_LEX::lex_start(LEX *plex) +{ + SELECT_LEX_UNIT *unit= &plex->unit; + /* 'parent_lex' is used in init_query() so it must be before it. */ + parent_lex= plex; + init_query(); + master= unit; + prev= &unit->slave; + link_next= slave= next= 0; + link_prev= (st_select_lex_node**)&(plex->all_selects_list); + DBUG_ASSERT(!group_list_ptrs); + select_number= 1; + in_sum_expr=0; + ftfunc_list_alloc.empty(); + ftfunc_list= &ftfunc_list_alloc; + group_list.empty(); + order_list.empty(); + gorder_list.empty(); +} + void lex_start(THD *thd) { DBUG_ENTER("lex_start"); @@ -659,18 +683,19 @@ void LEX::start(THD *thd_arg) DBUG_ASSERT(!explain); + builtin_select.lex_start(this); + lex_options= 0; context_stack.empty(); + //empty select_stack + select_stack_top= 0; unit.init_query(); - current_select_number= 1; - select_lex.linkage= UNSPECIFIED_TYPE; - /* 'parent_lex' is used in init_query() so it must be before it. */ - select_lex.parent_lex= this; - select_lex.init_query(); + current_select_number= 0; curr_with_clause= 0; with_clauses_list= 0; with_clauses_list_last_next= &with_clauses_list; clone_spec_offset= 0; create_view= NULL; + field_list.empty(); value_list.empty(); update_list.empty(); set_var_list.empty(); @@ -684,17 +709,8 @@ void LEX::start(THD *thd_arg) auxiliary_table_list.empty(); unit.next= unit.master= unit.link_next= unit.return_to= 0; unit.prev= unit.link_prev= 0; - unit.slave= current_select= all_selects_list= &select_lex; - select_lex.master= &unit; - select_lex.prev= &unit.slave; - select_lex.link_next= select_lex.slave= select_lex.next= 0; - select_lex.link_prev= (st_select_lex_node**)&(all_selects_list); - select_lex.options= 0; - select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED; - select_lex.init_order(); - select_lex.group_list.empty(); - if (select_lex.group_list_ptrs) - select_lex.group_list_ptrs->clear(); + unit.slave= current_select= all_selects_list= &builtin_select; + sql_cache= LEX::SQL_CACHE_UNSPECIFIED; describe= 0; analyze_stmt= 0; explain_json= false; @@ -704,14 +720,7 @@ void LEX::start(THD *thd_arg) safe_to_cache_query= 1; parsing_options.reset(); empty_field_list_on_rset= 0; - select_lex.select_number= 1; part_info= 0; - select_lex.in_sum_expr=0; - select_lex.ftfunc_list_alloc.empty(); - select_lex.ftfunc_list= &select_lex.ftfunc_list_alloc; - select_lex.group_list.empty(); - select_lex.order_list.empty(); - select_lex.gorder_list.empty(); m_sql_cmd= NULL; duplicates= DUP_ERROR; ignore= 0; @@ -723,6 +732,8 @@ void LEX::start(THD *thd_arg) query_tables= 0; reset_query_tables_list(FALSE); expr_allows_subselect= TRUE; + selects_allow_into= FALSE; + selects_allow_procedure= FALSE; use_only_table_context= FALSE; parse_vcol_expr= FALSE; check_exists= FALSE; @@ -732,8 +743,8 @@ void LEX::start(THD *thd_arg) name= null_clex_str; event_parse_data= NULL; profile_options= PROFILE_NONE; - nest_level=0 ; - select_lex.nest_level_base= &unit; + nest_level= 0; + builtin_select.nest_level_base= &unit; allow_sum_func.clear_all(); in_sum_func= NULL; @@ -757,6 +768,13 @@ void LEX::start(THD *thd_arg) vers_conditions.empty(); is_lex_started= TRUE; + + next_is_main= FALSE; + next_is_down= FALSE; + + wild= 0; + exchange= 0; + DBUG_VOID_RETURN; } @@ -1299,7 +1317,8 @@ int ORAlex(YYSTYPE *yylval, THD *thd) int Lex_input_stream::lex_token(YYSTYPE *yylval, THD *thd) { int token; - + const int left_paren= (int) '('; + if (lookahead_token >= 0) { /* @@ -1316,6 +1335,8 @@ int Lex_input_stream::lex_token(YYSTYPE *yylval, THD *thd) token= lex_one_token(yylval, thd); add_digest_token(token, yylval); + SELECT_LEX *curr_sel= thd->lex->current_select; + switch(token) { case WITH: /* @@ -1364,8 +1385,16 @@ int Lex_input_stream::lex_token(YYSTYPE *yylval, THD *thd) } break; case VALUES: - if (thd->lex->current_select->parsing_place == IN_UPDATE_ON_DUP_KEY || - thd->lex->current_select->parsing_place == IN_PART_FUNC) + if (curr_sel && + (curr_sel->parsing_place == BEFORE_OPT_LIST || + curr_sel->parsing_place == AFTER_LIST)) + { + curr_sel->parsing_place= NO_MATTER; + break; + } + if (curr_sel && + (curr_sel->parsing_place == IN_UPDATE_ON_DUP_KEY || + curr_sel->parsing_place == IN_PART_FUNC)) return VALUE_SYM; token= lex_one_token(yylval, thd); add_digest_token(token, yylval); @@ -1379,6 +1408,43 @@ int Lex_input_stream::lex_token(YYSTYPE *yylval, THD *thd) lookahead_token= token; return VALUES; } + case VALUE_SYM: + if (curr_sel && + (curr_sel->parsing_place == BEFORE_OPT_LIST || + curr_sel->parsing_place == AFTER_LIST)) + { + curr_sel->parsing_place= NO_MATTER; + return VALUES; + } + break; + case PARTITION_SYM: + case SELECT_SYM: + case UNION_SYM: + if (curr_sel && + (curr_sel->parsing_place == BEFORE_OPT_LIST || + curr_sel->parsing_place == AFTER_LIST)) + { + curr_sel->parsing_place= NO_MATTER; + } + break; + case left_paren: + if (!curr_sel || + curr_sel->parsing_place != BEFORE_OPT_LIST) + return token; + token= lex_one_token(yylval, thd); + add_digest_token(token, yylval); + lookahead_yylval= yylval; + yylval= NULL; + lookahead_token= token; + curr_sel->parsing_place= NO_MATTER; + if (token == LIKE) + return LEFT_PAREN_LIKE; + if (token == WITH) + return LEFT_PAREN_WITH; + if (token != left_paren && token != SELECT_SYM) + return LEFT_PAREN_ALT; + else + return left_paren; break; default: break; @@ -1721,7 +1787,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd) return(TEXT_STRING); } case MY_LEX_COMMENT: // Comment - lex->select_lex.options|= OPTION_FOUND_COMMENT; + lex->lex_options|= OPTION_LEX_FOUND_COMMENT; while ((c= yyGet()) != '\n' && c) ; yyUnget(); // Safety against eof state= MY_LEX_START; // Try again @@ -1732,7 +1798,7 @@ int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd) state= MY_LEX_CHAR; // Probable division break; } - lex->select_lex.options|= OPTION_FOUND_COMMENT; + lex->lex_options|= OPTION_LEX_FOUND_COMMENT; /* Reject '/' '*', since we might need to turn off the echo */ yyUnget(); @@ -2245,8 +2311,8 @@ void trim_whitespace(CHARSET_INFO *cs, LEX_CSTRING *str, size_t * prefix_length) void st_select_lex_node::init_query_common() { options= 0; - sql_cache= SQL_CACHE_UNSPECIFIED; - linkage= UNSPECIFIED_TYPE; + set_linkage(UNSPECIFIED_TYPE); + distinct= TRUE; no_table_names_allowed= 0; uncacheable= 0; } @@ -2254,7 +2320,7 @@ void st_select_lex_node::init_query_common() void st_select_lex_unit::init_query() { init_query_common(); - linkage= GLOBAL_OPTIONS_TYPE; + set_linkage(GLOBAL_OPTIONS_TYPE); select_limit_cnt= HA_POS_ERROR; offset_limit_cnt= 0; union_distinct= 0; @@ -2296,16 +2362,6 @@ void st_select_lex::init_query() having_fix_field_for_pushed_cond= 0; context.select_lex= this; context.init(); - /* - Add the name resolution context of the current (sub)query to the - stack of contexts for the whole query. - TODO: - push_context may return an error if there is no memory for a new - element in the stack, however this method has no return value, - thus push_context should be moved to a place where query - initialization is checked for failure. - */ - parent_lex->push_context(&context, parent_lex->thd->mem_root); cond_count= between_count= with_wild= 0; max_equal_elems= 0; ref_pointer_array.reset(); @@ -2351,16 +2407,14 @@ void st_select_lex::init_select() table_join_options= 0; in_sum_expr= with_wild= 0; options= 0; - sql_cache= SQL_CACHE_UNSPECIFIED; ftfunc_list_alloc.empty(); inner_sum_func_list= 0; ftfunc_list= &ftfunc_list_alloc; - order_list.elements= 0; - order_list.first= 0; - order_list.next= &order_list.first; + order_list.empty(); /* Set limit and offset to default values */ select_limit= 0; /* denotes the default limit = HA_POS_ERROR */ offset_limit= 0; /* denotes the default offset = 0 */ + is_set_query_expr_tail= false; with_sum_func= 0; with_all_modifier= 0; is_correlated= 0; @@ -2422,6 +2476,23 @@ void st_select_lex_node::add_slave(st_select_lex_node *slave_arg) } } +void st_select_lex_node::link_chain_down(st_select_lex_node *first) +{ + st_select_lex_node *last_node; + st_select_lex_node *node= first; + do + { + last_node= node; + node->master= this; + node= node->next; + } while (node); + if ((last_node->next= slave)) + { + slave->prev= &last_node->next; + } + first->prev= &slave; + slave= first; +} /* include on level down (but do not link) @@ -2471,7 +2542,7 @@ void st_select_lex_node::fast_exclude() // Remove slave structure for (; slave; slave= slave->next) slave->fast_exclude(); - + } @@ -2945,8 +3016,7 @@ void st_select_lex::print_order(String *str, else { /* replace numeric reference with equivalent for ORDER constant */ - if (order->item[0]->type() == Item::INT_ITEM && - order->item[0]->basic_const_item()) + if (order->item[0]->is_order_clause_position()) { /* make it expression instead of integer constant */ str->append(STRING_WITH_LEN("''")); @@ -3141,6 +3211,7 @@ LEX::LEX() gtid_domain_static_buffer, initial_gtid_domain_buffer_size, initial_gtid_domain_buffer_size, 0); + unit.slave= &builtin_select; } @@ -3167,12 +3238,12 @@ bool LEX::can_be_merged() // TODO: do not forget implement case when select_lex.table_list.elements==0 /* find non VIEW subqueries/unions */ - bool selects_allow_merge= (select_lex.next_select() == 0 && - !(select_lex.uncacheable & + bool selects_allow_merge= (first_select_lex()->next_select() == 0 && + !(first_select_lex()->uncacheable & UNCACHEABLE_RAND)); if (selects_allow_merge) { - for (SELECT_LEX_UNIT *tmp_unit= select_lex.first_inner_unit(); + for (SELECT_LEX_UNIT *tmp_unit= first_select_lex()->first_inner_unit(); tmp_unit; tmp_unit= tmp_unit->next_unit()) { @@ -3189,12 +3260,12 @@ bool LEX::can_be_merged() } return (selects_allow_merge && - select_lex.group_list.elements == 0 && - select_lex.having == 0 && - select_lex.with_sum_func == 0 && - select_lex.table_list.elements >= 1 && - !(select_lex.options & SELECT_DISTINCT) && - select_lex.select_limit == 0); + first_select_lex()->group_list.elements == 0 && + first_select_lex()->having == 0 && + first_select_lex()->with_sum_func == 0 && + first_select_lex()->table_list.elements >= 1 && + !(first_select_lex()->options & SELECT_DISTINCT) && + first_select_lex()->select_limit == 0); } @@ -3547,7 +3618,7 @@ void LEX::set_trg_event_type_for_tables() Do not iterate over sub-selects, only the tables in the outermost SELECT_LEX can be modified, if any. */ - TABLE_LIST *tables= select_lex.get_table_list(); + TABLE_LIST *tables= first_select_lex()->get_table_list(); while (tables) { @@ -3603,12 +3674,13 @@ TABLE_LIST *LEX::unlink_first_table(bool *link_to_local) /* and from local list if it is not empty */ - if ((*link_to_local= MY_TEST(select_lex.table_list.first))) + if ((*link_to_local= MY_TEST(first_select_lex()->table_list.first))) { - select_lex.context.table_list= - select_lex.context.first_name_resolution_table= first->next_local; - select_lex.table_list.first= first->next_local; - select_lex.table_list.elements--; //safety + first_select_lex()->context.table_list= + first_select_lex()->context.first_name_resolution_table= + first->next_local; + first_select_lex()->table_list.first= first->next_local; + first_select_lex()->table_list.elements--; //safety first->next_local= 0; /* Ensure that the global list has the same first table as the local @@ -3639,7 +3711,7 @@ TABLE_LIST *LEX::unlink_first_table(bool *link_to_local) void LEX::first_lists_tables_same() { - TABLE_LIST *first_table= select_lex.table_list.first; + TABLE_LIST *first_table= first_select_lex()->table_list.first; if (query_tables != first_table && first_table != 0) { TABLE_LIST *next; @@ -3664,6 +3736,23 @@ void LEX::first_lists_tables_same() } } +void LEX::fix_first_select_number() +{ + SELECT_LEX *first= first_select_lex(); + if (first && first->select_number != 1) + { + uint num= first->select_number; + for (SELECT_LEX *sel= all_selects_list; + sel; + sel= sel->next_select_in_list()) + { + if (sel->select_number < num) + sel->select_number++; + } + first->select_number= 1; + } +} + /* Link table back that was unlinked with unlink_first_table() @@ -3689,10 +3778,10 @@ void LEX::link_first_table_back(TABLE_LIST *first, if (link_to_local) { - first->next_local= select_lex.table_list.first; - select_lex.context.table_list= first; - select_lex.table_list.first= first; - select_lex.table_list.elements++; //safety + first->next_local= first_select_lex()->table_list.first; + first_select_lex()->context.table_list= first; + first_select_lex()->table_list.first= first; + first_select_lex()->table_list.elements++; //safety } } } @@ -3721,19 +3810,19 @@ void LEX::cleanup_after_one_table_open() NOTE: all units will be connected to thd->lex->select_lex, because we have not UNION on most upper level. */ - if (all_selects_list != &select_lex) + if (all_selects_list != first_select_lex()) { derived_tables= 0; - select_lex.exclude_from_table_unique_test= false; + first_select_lex()->exclude_from_table_unique_test= false; /* cleunup underlying units (units of VIEW) */ - for (SELECT_LEX_UNIT *un= select_lex.first_inner_unit(); + for (SELECT_LEX_UNIT *un= first_select_lex()->first_inner_unit(); un; un= un->next_unit()) un->cleanup(); /* reduce all selects list to default state */ - all_selects_list= &select_lex; + all_selects_list= first_select_lex(); /* remove underlying units (units of VIEW) subtree */ - select_lex.cut_subtree(); + first_select_lex()->cut_subtree(); } } @@ -4388,7 +4477,7 @@ void SELECT_LEX::update_used_tables() tab->covering_keys= tab->s->keys_for_keyread; tab->covering_keys.intersect(tab->keys_in_use_for_query); /* - View/derived was merged. Need to recalculate read_set/vcol_set + View/derived was merged. Need to recalculate read_set bitmaps here. For example: CREATE VIEW v1 AS SELECT f1,f2,f3 FROM t1; SELECT f1 FROM v1; @@ -4397,8 +4486,6 @@ void SELECT_LEX::update_used_tables() be in the read_set. */ bitmap_clear_all(tab->read_set); - if (tab->vcol_set) - bitmap_clear_all(tab->vcol_set); break; } } @@ -4599,7 +4686,7 @@ void st_select_lex::set_explain_type(bool on_the_fly) using_materialization= TRUE; } - if (&master_unit()->thd->lex->select_lex == this) + if (master_unit()->thd->lex->first_select_lex() == this) { type= is_primary ? "PRIMARY" : "SIMPLE"; } @@ -4794,8 +4881,8 @@ bool LEX::save_prep_leaf_tables() Query_arena *arena= thd->stmt_arena, backup; arena= thd->activate_stmt_arena_if_needed(&backup); //It is used for DETETE/UPDATE so top level has only one SELECT - DBUG_ASSERT(select_lex.next_select() == NULL); - bool res= select_lex.save_prep_leaf_tables(thd); + DBUG_ASSERT(first_select_lex()->next_select() == NULL); + bool res= first_select_lex()->save_prep_leaf_tables(thd); if (arena) thd->restore_active_arena(arena, &backup); @@ -5126,8 +5213,13 @@ bool LEX::is_partition_management() const SELECT_LEX *LEX::exclude_last_select() { - DBUG_ENTER("SELECT_LEX::exclude_last_select"); - SELECT_LEX *exclude= current_select; + return exclude_not_first_select(current_select); +} + +SELECT_LEX *LEX::exclude_not_first_select(SELECT_LEX *exclude) +{ + DBUG_ENTER("LEX::exclude_not_first_select"); + DBUG_PRINT("enter", ("exclude %p #%u", exclude, exclude->select_number)); SELECT_LEX_UNIT *unit= exclude->master_unit(); SELECT_LEX *sl; DBUG_ASSERT(unit->first_select() != exclude); @@ -5138,89 +5230,258 @@ SELECT_LEX *LEX::exclude_last_select() DBUG_PRINT("info", ("excl: %p unit: %p prev: %p", exclude, unit, sl)); if (!sl) DBUG_RETURN(NULL); - DBUG_ASSERT(exclude->next_select() == NULL); - exclude->exclude_from_tree(); + DBUG_ASSERT(&sl->next == exclude->prev); + + exclude->prev= NULL; + current_select= sl; DBUG_RETURN(exclude); } -/** - Put given (new) SELECT_LEX level below after currect (last) SELECT +SELECT_LEX_UNIT *LEX::alloc_unit() +{ + SELECT_LEX_UNIT *unit; + DBUG_ENTER("LEX::alloc_unit"); + if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT())) + DBUG_RETURN(NULL); + + unit->init_query(); + /* TODO: reentrant problem */ + unit->thd= thd; + unit->link_next= 0; + unit->link_prev= 0; + /* TODO: remove return_to */ + unit->return_to= NULL; + DBUG_RETURN(unit); +} - LAST SELECT -> DUMMY SELECT - | - V - NEW UNIT - | - V - NEW SELECT - SELECT (*LAST*) ... FROM (SELECT (*NEW*) ... ) +SELECT_LEX *LEX::alloc_select(bool select) +{ + SELECT_LEX *select_lex; + DBUG_ENTER("LEX::alloc_select"); + if (!(select_lex= new (thd->mem_root) SELECT_LEX())) + DBUG_RETURN(NULL); + DBUG_PRINT("info", ("Allocate select: %p #%u statement lex: %p", + select_lex, thd->lex->stmt_lex->current_select_number, + thd->lex->stmt_lex)); + /* + TODO: move following init to constructor when we get rid of builtin + select + */ + select_lex->select_number= ++thd->lex->stmt_lex->current_select_number; + select_lex->parent_lex= this; /* Used in init_query. */ + select_lex->init_query(); + if (select) + select_lex->init_select(); + select_lex->nest_level_base= &this->unit; + select_lex->include_global((st_select_lex_node**)&all_selects_list); + select_lex->context.resolve_in_select_list= TRUE; + DBUG_RETURN(select_lex); +} - @param nselect Select to put one level below +SELECT_LEX_UNIT * +LEX::create_unit(SELECT_LEX *first_sel) +{ + SELECT_LEX_UNIT *unit; + DBUG_ENTER("LEX::create_unit"); - @retval TRUE Error - @retval FALSE OK -*/ + if (first_sel->master_unit()) + DBUG_RETURN(first_sel->master_unit()); + + if (!(unit= alloc_unit())) + DBUG_RETURN(NULL); + + unit->register_select_chain(first_sel); + if (first_sel->next_select()) + { + unit->reset_distinct(); + DBUG_ASSERT(!unit->fake_select_lex); + if (unit->add_fake_select_lex(thd)) + DBUG_RETURN(NULL); + } + DBUG_RETURN(unit); +} -bool LEX::add_unit_in_brackets(SELECT_LEX *nselect) +SELECT_LEX_UNIT * +SELECT_LEX::attach_selects_chain(SELECT_LEX *first_sel, + Name_resolution_context *context) { - DBUG_ENTER("LEX::add_unit_in_brackets"); - bool distinct= nselect->master_unit()->union_distinct == nselect; - bool rc= add_select_to_union_list(distinct, nselect->linkage, 0); - if (rc) - DBUG_RETURN(TRUE); - SELECT_LEX* dummy_select= current_select; - dummy_select->automatic_brackets= TRUE; - dummy_select->linkage= nselect->linkage; + SELECT_LEX_UNIT *unit; + DBUG_ENTER("SELECT_LEX::attach_select_chain"); + + if (!(unit= parent_lex->alloc_unit())) + DBUG_RETURN(NULL); + + unit->register_select_chain(first_sel); + register_unit(unit, context); + if (first_sel->next_select()) + { + unit->reset_distinct(); + DBUG_ASSERT(!unit->fake_select_lex); + if (unit->add_fake_select_lex(parent_lex->thd)) + DBUG_RETURN(NULL); + } + + DBUG_RETURN(unit); +} + +SELECT_LEX * +LEX::wrap_unit_into_derived(SELECT_LEX_UNIT *unit) +{ + SELECT_LEX *wrapping_sel; + Table_ident *ti; + DBUG_ENTER("LEX::wrap_unit_into_derived"); + + if (!(wrapping_sel= alloc_select(TRUE))) + DBUG_RETURN(NULL); + Name_resolution_context *context= &wrapping_sel->context; + context->init(); + wrapping_sel->automatic_brackets= FALSE; + + wrapping_sel->register_unit(unit, context); /* stuff dummy SELECT * FROM (...) */ + + if (push_select(wrapping_sel)) // for Items & TABLE_LIST + DBUG_RETURN(NULL); + + /* add SELECT list*/ + { + Item *item= new (thd->mem_root) + Item_field(thd, context, NULL, NULL, &star_clex_str); + if (item == NULL) + goto err; + if (add_item_to_list(thd, item)) + goto err; + (wrapping_sel->with_wild)++; + } + + unit->first_select()->set_linkage(DERIVED_TABLE_TYPE); + + ti= new (thd->mem_root) Table_ident(unit); + if (ti == NULL) + goto err; + { + TABLE_LIST *table_list; + LEX_CSTRING alias; + if (wrapping_sel->make_unique_derived_name(thd, &alias)) + goto err; + + if (!(table_list= wrapping_sel->add_table_to_list(thd, ti, &alias, + 0, TL_READ, + MDL_SHARED_READ))) + goto err; + + context->resolve_in_table_list_only(table_list); + wrapping_sel->add_joined_table(table_list); + } + + pop_select(); + + derived_tables|= DERIVED_SUBQUERY; + + DBUG_RETURN(wrapping_sel); + +err: + pop_select(); + DBUG_RETURN(NULL); +} + +SELECT_LEX *LEX::wrap_select_chain_into_derived(SELECT_LEX *sel) +{ + SELECT_LEX *dummy_select; + SELECT_LEX_UNIT *unit; + Table_ident *ti; + DBUG_ENTER("LEX::wrap_select_chain_into_derived"); + + if (!(dummy_select= alloc_select(TRUE))) + DBUG_RETURN(NULL); Name_resolution_context *context= &dummy_select->context; - context->init(); + dummy_select->automatic_brackets= FALSE; + + if (!(unit= dummy_select->attach_selects_chain(sel, context))) + DBUG_RETURN(NULL); + + /* stuff dummy SELECT * FROM (...) */ + + if (push_select(dummy_select)) // for Items & TABLE_LIST + DBUG_RETURN(NULL); /* add SELECT list*/ - Item *item= new (thd->mem_root) - Item_field(thd, context, NULL, NULL, &star_clex_str); - if (unlikely(item == NULL)) - DBUG_RETURN(TRUE); - if (unlikely(add_item_to_list(thd, item))) - DBUG_RETURN(TRUE); - (dummy_select->with_wild)++; + { + Item *item= new (thd->mem_root) + Item_field(thd, context, NULL, NULL, &star_clex_str); + if (item == NULL) + goto err; + if (add_item_to_list(thd, item)) + goto err; + (dummy_select->with_wild)++; + } + + sel->set_linkage(DERIVED_TABLE_TYPE); - rc= mysql_new_select(this, 1, nselect); - nselect->linkage= DERIVED_TABLE_TYPE; - DBUG_ASSERT(nselect->outer_select() == dummy_select); + ti= new (thd->mem_root) Table_ident(unit); + if (ti == NULL) + goto err; + { + TABLE_LIST *table_list; + LEX_CSTRING alias; + if (dummy_select->make_unique_derived_name(thd, &alias)) + goto err; - current_select= dummy_select; - current_select->nest_level--; + if (!(table_list= dummy_select->add_table_to_list(thd, ti, &alias, + 0, TL_READ, + MDL_SHARED_READ))) + goto err; - SELECT_LEX_UNIT *unit= nselect->master_unit(); - Table_ident *ti= new (thd->mem_root) Table_ident(unit); - if (unlikely(ti == NULL)) - DBUG_RETURN(TRUE); - char buff[10]; - LEX_CSTRING alias; - alias.length= my_snprintf(buff, sizeof(buff), - "__%u", dummy_select->select_number); - alias.str= thd->strmake(buff, alias.length); - if (unlikely(!alias.str)) - DBUG_RETURN(TRUE); + context->resolve_in_table_list_only(table_list); + dummy_select->add_joined_table(table_list); + } - TABLE_LIST *table_list; - if (unlikely(!(table_list= - dummy_select->add_table_to_list(thd, ti, &alias, - 0, TL_READ, - MDL_SHARED_READ)))) - DBUG_RETURN(TRUE); - context->resolve_in_table_list_only(table_list); - dummy_select->add_joined_table(table_list); + pop_select(); derived_tables|= DERIVED_SUBQUERY; - current_select= nselect; - current_select->nest_level++; - DBUG_RETURN(rc); + DBUG_RETURN(dummy_select); + +err: + pop_select(); + DBUG_RETURN(NULL); +} + +bool LEX::push_context(Name_resolution_context *context) +{ + DBUG_ENTER("LEX::push_context"); + DBUG_PRINT("info", ("Context: %p Select: %p (%d)", + context, context->select_lex, + (context->select_lex ? + context->select_lex->select_number: + 0))); + bool res= context_stack.push_front(context, thd->mem_root); + DBUG_RETURN(res); +} + + +SELECT_LEX *LEX::create_priority_nest(SELECT_LEX *first_in_nest) +{ + DBUG_ENTER("LEX::create_priority_nest"); + DBUG_ASSERT(first_in_nest->first_nested); + enum sub_select_type wr_unit_type= first_in_nest->get_linkage(); + bool wr_distinct= first_in_nest->distinct; + SELECT_LEX *attach_to= first_in_nest->first_nested; + attach_to->cut_next(); + SELECT_LEX *wrapper= wrap_select_chain_into_derived(first_in_nest); + if (wrapper) + { + first_in_nest->first_nested= NULL; + wrapper->set_linkage_and_distinct(wr_unit_type, wr_distinct); + wrapper->first_nested= attach_to->first_nested; + wrapper->set_master_unit(attach_to->master_unit()); + attach_to->link_neighbour(wrapper); + } + DBUG_RETURN(wrapper); } @@ -5235,7 +5496,7 @@ bool LEX::add_unit_in_brackets(SELECT_LEX *nselect) void LEX::check_automatic_up(enum sub_select_type type) { if (type != INTERSECT_TYPE && - current_select->linkage == INTERSECT_TYPE && + current_select->get_linkage() == INTERSECT_TYPE && current_select->outer_select() && current_select->outer_select()->automatic_brackets) { @@ -5685,10 +5946,17 @@ bool LEX::sp_for_loop_implicit_cursor_statement(THD *thd, bounds->m_index->sp_lex_in_use= true; sphead->reset_lex(thd, bounds->m_index); DBUG_ASSERT(thd->lex != this); - if (unlikely(!(item= - new (thd->mem_root) Item_field(thd, - thd->lex->current_context(), - NullS, NullS, &name)))) + /* + We pass NULL as Name_resolution_context here. + It's OK, fix_fields() will not be called for this Item_field created. + Item_field is only needed for LEX::sp_for_loop_cursor_declarations() + and is used to transfer the loop index variable name, "rec" in this example: + FOR rec IN (SELECT * FROM t1) + DO + SELECT rec.a, rec.b; + END FOR; + */ + if (!(item= new (thd->mem_root) Item_field(thd, NULL, NullS, NullS, &name))) return true; bounds->m_index->set_item_and_free_list(item, NULL); if (thd->lex->sphead->restore_lex(thd)) @@ -5795,10 +6063,22 @@ bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop, const LEX_CSTRING *index, const Lex_for_loop_bounds_st &bounds) { - if (unlikely(!(loop->m_index= - bounds.m_index-> - sp_add_for_loop_variable(thd, index, - bounds.m_index->get_item())))) + Item *item; + if ((item= bounds.m_index->get_item())->type() == Item::FIELD_ITEM) + { + // We're here is the lower bound is unknown identifier + my_error(ER_SP_UNDECLARED_VAR, MYF(0), item->full_name()); + return true; + } + if ((item= bounds.m_target_bound->get_item())->type() == Item::FIELD_ITEM) + { + // We're here is the upper bound is unknown identifier + my_error(ER_SP_UNDECLARED_VAR, MYF(0), item->full_name()); + return true; + } + if (!(loop->m_index= + bounds.m_index->sp_add_for_loop_variable(thd, index, + bounds.m_index->get_item()))) return true; if (unlikely(!(loop->m_target_bound= bounds.m_target_bound-> @@ -6743,7 +7023,6 @@ Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name, my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); return NULL; } - Query_fragment pos(thd, sphead, start, end); Item_param *item= new (thd->mem_root) Item_param(thd, name, pos.pos(), pos.length()); @@ -6774,6 +7053,38 @@ bool LEX::add_resignal_statement(THD *thd, const sp_condition_value *v) } +/* + Make an Item when an identifier is found in the FOR loop bounds: + FOR rec IN cursor + FOR var IN var1 .. xxx + FOR var IN row1.field1 .. xxx + When we parse the first expression after the "IN" keyword, + we don't know yet if it's a cursor name, or a scalar SP variable name, + or a field of a ROW SP variable. Here we create Item_field to remember + the fully qualified name. Later sp_for_loop_cursor_declarations() + detects how to treat this name properly. +*/ +Item *LEX::create_item_for_loop_bound(THD *thd, + const LEX_CSTRING *a, + const LEX_CSTRING *b, + const LEX_CSTRING *c) +{ + /* + Pass NULL as the name resolution context. + This is OK, fix_fields() won't be called for this Item_field. + */ + return new (thd->mem_root) Item_field(thd, NULL, a->str, b->str, c); +} + + +bool LEX::check_expr_allows_fields_or_error(THD *thd, const char *name) const +{ + if (select_stack_top > 0) + return false; // OK, fields are allowed + my_error(ER_BAD_FIELD_ERROR, MYF(0), name, thd->where); + return true; // Error, fields are not allowed +} + Item *LEX::create_item_ident_nospvar(THD *thd, const Lex_ident_sys_st *a, const Lex_ident_sys_st *b) @@ -6796,12 +7107,11 @@ Item *LEX::create_item_ident_nospvar(THD *thd, my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), a->str, thd->where); return NULL; } - if ((current_select->parsing_place != IN_HAVING) || - (current_select->get_in_sum_expr() > 0)) - return new (thd->mem_root) Item_field(thd, current_context(), - NullS, a->str, b); - return new (thd->mem_root) Item_ref(thd, current_context(), - NullS, a->str, b); + + if (current_select->parsing_place == FOR_LOOP_BOUND) + return create_item_for_loop_bound(thd, &null_clex_str, a, b); + + return create_item_ident_field(thd, NullS, a->str, b); } @@ -7013,12 +7323,11 @@ Item *LEX::create_item_ident(THD *thd, my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), b->str, thd->where); return NULL; } - if (current_select->parsing_place != IN_HAVING || - current_select->get_in_sum_expr() > 0) - return new (thd->mem_root) Item_field(thd, current_context(), - schema, b->str, c); - return new (thd->mem_root) Item_ref(thd, current_context(), - schema, b->str, c); + + if (current_select->parsing_place == FOR_LOOP_BOUND) + return create_item_for_loop_bound(thd, &null_clex_str, b, c); + + return create_item_ident_field(thd, schema, b->str, c); } @@ -7051,11 +7360,9 @@ Item *LEX::create_item_limit(THD *thd, const Lex_ident_cli_st *ca) #endif safe_to_cache_query= 0; - if (unlikely(item->type() != Item::INT_ITEM)) - { - my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0)); + if (!item->is_valid_limit_clause_variable_with_error()) return NULL; - } + item->limit_clause_param= true; return item; } @@ -7085,11 +7392,8 @@ Item *LEX::create_item_limit(THD *thd, if (unlikely(!(item= create_item_spvar_row_field(thd, rh, &sa, &sb, spv, ca->pos(), cb->end())))) return NULL; - if (unlikely(item->type() != Item::INT_ITEM)) - { - my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0)); + if (!item->is_valid_limit_clause_variable_with_error()) return NULL; - } item->limit_clause_param= true; return item; } @@ -7109,15 +7413,20 @@ bool LEX::set_user_variable(THD *thd, const LEX_CSTRING *name, Item *val) } -Item *LEX::create_item_ident_nosp(THD *thd, Lex_ident_sys_st *name) +Item *LEX::create_item_ident_field(THD *thd, const char *db, + const char *table, + const Lex_ident_sys_st *name) { + if (check_expr_allows_fields_or_error(thd, name->str)) + return NULL; + if (current_select->parsing_place != IN_HAVING || current_select->get_in_sum_expr() > 0) return new (thd->mem_root) Item_field(thd, current_context(), - NullS, NullS, name); + db, table, name); return new (thd->mem_root) Item_ref(thd, current_context(), - NullS, NullS, name); + db, table, name); } @@ -7167,6 +7476,11 @@ Item *LEX::create_item_ident_sp(THD *thd, Lex_ident_sys_st *name, if (lex_string_eq(name, STRING_WITH_LEN("SQLERRM"))) return new (thd->mem_root) Item_func_sqlerrm(thd); } + + if (current_select->parsing_place == FOR_LOOP_BOUND) + return create_item_for_loop_bound(thd, &null_clex_str, &null_clex_str, + name); + return create_item_ident_nosp(thd, name); } @@ -7460,8 +7774,8 @@ void st_select_lex::collect_grouping_fields(THD *thd, { if ((*ord->item)->eq((Item*)item, 0)) { - Grouping_tmp_field *grouping_tmp_field= - new Grouping_tmp_field(master_unit()->derived->table->field[i], item); + Field_pair *grouping_tmp_field= + new Field_pair(master_unit()->derived->table->field[i], item); grouping_tmp_fields.push_back(grouping_tmp_field); } } @@ -7492,8 +7806,7 @@ void st_select_lex::collect_grouping_fields(THD *thd, */ void -st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond, - TABLE_LIST *derived) +st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond) { cond->clear_extraction_flag(); if (cond->type() == Item::COND_ITEM) @@ -7506,7 +7819,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond, Item *item; while ((item=li++)) { - check_cond_extraction_for_grouping_fields(item, derived); + check_cond_extraction_for_grouping_fields(item); if (item->get_extraction_flag() != NO_EXTRACTION_FL) { count++; @@ -7555,7 +7868,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond, to figure out whether a subformula depends only on these fields or not. @note The built condition C is always implied by the condition cond - (cond => C). The method tries to build the most restictive such + (cond => C). The method tries to build the least restictive such condition (i.e. for any other condition C' such that cond => C' we have C => C'). @note @@ -7631,6 +7944,140 @@ Item *st_select_lex::build_cond_for_grouping_fields(THD *thd, Item *cond, } +bool st_select_lex::set_nest_level(int new_nest_level) +{ + DBUG_ENTER("st_select_lex::set_nest_level"); + DBUG_PRINT("enter", ("select #%d %p nest level: %d", + select_number, this, new_nest_level)); + if (new_nest_level > (int) MAX_SELECT_NESTING) + { + my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0)); + DBUG_RETURN(TRUE); + } + nest_level= new_nest_level; + new_nest_level++; + for (SELECT_LEX_UNIT *u= first_inner_unit(); u; u= u->next_unit()) + { + if (u->set_nest_level(new_nest_level)) + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} + +bool st_select_lex_unit::set_nest_level(int new_nest_level) +{ + DBUG_ENTER("st_select_lex_unit::set_nest_level"); + for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) + { + if (sl->set_nest_level(new_nest_level)) + DBUG_RETURN(TRUE); + } + if (fake_select_lex && + fake_select_lex->set_nest_level(new_nest_level)) + DBUG_RETURN(TRUE); + DBUG_RETURN(FALSE); +} + + +bool st_select_lex::check_parameters(SELECT_LEX *main_select) +{ + DBUG_ENTER("st_select_lex::check_parameters"); + DBUG_PRINT("enter", ("select #%d %p nest level: %d", + select_number, this, nest_level)); + + + if ((options & OPTION_PROCEDURE_CLAUSE) && + (!parent_lex->selects_allow_procedure || + next_select() != NULL || + this != master_unit()->first_select() || + nest_level != 0)) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "PROCEDURE"); + DBUG_RETURN(TRUE); + } + + if ((options & SELECT_HIGH_PRIORITY) && this != main_select) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "HIGH_PRIORITY"); + DBUG_RETURN(TRUE); + } + if ((options & OPTION_BUFFER_RESULT) && this != main_select) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_BUFFER_RESULT"); + DBUG_RETURN(TRUE); + } + if ((options & OPTION_FOUND_ROWS) && this != main_select) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CALC_FOUND_ROWS"); + DBUG_RETURN(TRUE); + } + if (options & OPTION_NO_QUERY_CACHE) + { + /* + Allow this flag only on the first top-level SELECT statement, if + SQL_CACHE wasn't specified. + */ + if (this != main_select) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"); + DBUG_RETURN(TRUE); + } + if (parent_lex->sql_cache == LEX::SQL_CACHE) + { + my_error(ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"); + DBUG_RETURN(TRUE); + } + parent_lex->safe_to_cache_query=0; + parent_lex->sql_cache= LEX::SQL_NO_CACHE; + } + if (options & OPTION_TO_QUERY_CACHE) + { + /* + Allow this flag only on the first top-level SELECT statement, if + SQL_NO_CACHE wasn't specified. + */ + if (this != main_select) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"); + DBUG_RETURN(TRUE); + } + if (parent_lex->sql_cache == LEX::SQL_NO_CACHE) + { + my_error(ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"); + DBUG_RETURN(TRUE); + } + parent_lex->safe_to_cache_query=1; + parent_lex->sql_cache= LEX::SQL_CACHE; + } + + for (SELECT_LEX_UNIT *u= first_inner_unit(); u; u= u->next_unit()) + { + if (u->check_parameters(main_select)) + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} + + +bool st_select_lex_unit::check_parameters(SELECT_LEX *main_select) +{ + for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) + { + if (sl->check_parameters(main_select)) + return TRUE; + } + return fake_select_lex && fake_select_lex->check_parameters(main_select); +} + + +bool LEX::check_main_unit_semantics() +{ + if (unit.set_nest_level(0) || + unit.check_parameters(first_select_lex())) + return TRUE; + return FALSE; +} + int set_statement_var_if_exists(THD *thd, const char *var_name, size_t var_name_length, ulonglong value) { @@ -7685,10 +8132,10 @@ bool LEX::create_or_alter_view_finalize(THD *thd, Table_ident *table_ident) { sql_command= SQLCOM_CREATE_VIEW; /* first table in list is target VIEW name */ - if (unlikely(!select_lex.add_table_to_list(thd, table_ident, NULL, + if (!first_select_lex()->add_table_to_list(thd, table_ident, NULL, TL_OPTION_UPDATING, TL_IGNORE, - MDL_EXCLUSIVE))) + MDL_EXCLUSIVE)) return true; query_tables->open_strategy= TABLE_LIST::OPEN_STUB; return false; @@ -7981,6 +8428,130 @@ Item *Lex_trim_st::make_item_func_trim(THD *thd) const } +/** + @brief + Extract from given item a condition pushable into WHERE clause + + @param thd the thread handle + @param cond the item to extract a condition to be pushed + into WHERE + @param remaining_cond the condition that will remain of cond after + the pushdown of its parts into the WHERE clause + @param transformer the transformer callback function to be + applied to the condition so it can be pushed + down into the WHERE clause of this select + @param arg parameter to be passed to the transformer + + @details + This method checks if cond entirely or its parts can be + pushed into the WHERE clause of this select and prepares it for pushing. + + First it checks wherever this select doesn't have any aggregation function + in its projection and GROUP BY clause. If so cond can be entirely + pushed into the WHERE clause of this select but before its fields should + be transformed with transformer_for_where to make it pushable. + + Otherwise the method checks wherever any condition depending only on + grouping fields can be extracted from cond. If there is any it prepares it + for pushing using grouping_field_transformer_for_where and if it happens to + be a conjunct of cond it removes it from cond. It saves the result of + removal in remaining_cond. + The extracted condition is saved in cond_pushed_into_where of this select. + + @note + When looking for pushable condition the method considers only the grouping + fields from the list grouping_tmp_fields whose elements are of the type + Field_pair. This list must be prepared before the call of the + function. + + @note + This method is called for pushdown conditions into materialized + derived tables/views optimization. + Item::derived_field_transformer_for_where is passed as the actual + callback function. + Also it is called for pushdown conditions into materialized IN subqueries. + Item::in_subq_field_transformer_for_where is passed as the actual + callback function. +*/ + +void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond, + Item **remaining_cond, + Item_transformer transformer, + uchar *arg) +{ + if (!cond_pushdown_is_allowed()) + return; + thd->lex->current_select= this; + if (have_window_funcs()) + { + Item *cond_over_partition_fields; + check_cond_extraction_for_grouping_fields(cond); + cond_over_partition_fields= + build_cond_for_grouping_fields(thd, cond, true); + if (cond_over_partition_fields) + cond_over_partition_fields= cond_over_partition_fields->transform(thd, + &Item::grouping_field_transformer_for_where, + (uchar*) this); + if (cond_over_partition_fields) + { + cond_over_partition_fields->walk( + &Item::cleanup_excluding_const_fields_processor, 0, 0); + cond_pushed_into_where= cond_over_partition_fields; + } + + return; + } + + if (!join->group_list && !with_sum_func) + { + cond= + cond->transform(thd, transformer, arg); + if (cond) + { + cond->walk( + &Item::cleanup_excluding_const_fields_processor, 0, 0); + cond_pushed_into_where= cond; + } + + return; + } + + /* + Figure out what can be extracted from cond + that could be pushed into the WHERE clause of this select + */ + Item *cond_over_grouping_fields; + check_cond_extraction_for_grouping_fields(cond); + cond_over_grouping_fields= + build_cond_for_grouping_fields(thd, cond, true); + + /* + Transform the references to the columns from the cond + pushed into the WHERE clause of this select to make them usable in + the new context + */ + if (cond_over_grouping_fields) + cond_over_grouping_fields= cond_over_grouping_fields->transform(thd, + &Item::grouping_field_transformer_for_where, + (uchar*) this); + + if (cond_over_grouping_fields) + { + + /* + In cond remove top conjuncts that has been pushed into the WHERE + clause of this select + */ + cond= remove_pushed_top_conjuncts(thd, cond); + + cond_over_grouping_fields->walk( + &Item::cleanup_excluding_const_fields_processor, 0, 0); + cond_pushed_into_where= cond_over_grouping_fields; + } + + *remaining_cond= cond; +} + Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb, Lex_ident_cli_st *cname, List<Item> *args) { @@ -8247,9 +8818,772 @@ bool LEX::tvc_finalize_derived() thd->parse_error(); return true; } - if (current_select->linkage == GLOBAL_OPTIONS_TYPE || + if (current_select->get_linkage() == GLOBAL_OPTIONS_TYPE || unlikely(mysql_new_select(this, 1, NULL))) return true; - current_select->linkage= DERIVED_TABLE_TYPE; + current_select->set_linkage(DERIVED_TABLE_TYPE); return tvc_finalize(); } + + +void st_select_lex_unit::reset_distinct() +{ + union_distinct= NULL; + for(SELECT_LEX *sl= first_select()->next_select(); + sl; + sl= sl->next_select()) + { + if (sl->distinct) + { + union_distinct= sl; + } + } +} + + +void st_select_lex_unit::fix_distinct(st_select_lex_unit *new_unit) +{ + if (union_distinct) + { + if (this != union_distinct->master_unit()) + { + DBUG_ASSERT(new_unit == union_distinct->master_unit()); + new_unit->union_distinct= union_distinct; + reset_distinct(); + } + else + new_unit->reset_distinct(); + } +} + + +void st_select_lex_unit::register_select_chain(SELECT_LEX *first_sel) +{ + DBUG_ASSERT(first_sel != 0); + slave= first_sel; + first_sel->prev= &slave; + for(SELECT_LEX *sel=first_sel; sel; sel= sel->next_select()) + { + sel->master= (st_select_lex_node *)this; + uncacheable|= sel->uncacheable; + } +} + + +void st_select_lex::register_unit(SELECT_LEX_UNIT *unit, + Name_resolution_context *outer_context) +{ + if ((unit->next= slave)) + slave->prev= &unit->next; + unit->prev= &slave; + slave= unit; + unit->master= this; + uncacheable|= unit->uncacheable; + + for(SELECT_LEX *sel= unit->first_select();sel; sel= sel->next_select()) + { + sel->context.outer_context= outer_context; + } +} + + +void st_select_lex::add_statistics(SELECT_LEX_UNIT *unit) +{ + for (; + unit; + unit= unit->next_unit()) + for(SELECT_LEX *child= unit->first_select(); + child; + child= child->next_select()) + { + /* + A subselect can add fields to an outer select. + Reserve space for them. + */ + select_n_where_fields+= child->select_n_where_fields; + /* + Aggregate functions in having clause may add fields + to an outer select. Count them also. + */ + select_n_having_items+= child->select_n_having_items; + } +} + + +bool LEX::main_select_push() +{ + DBUG_ENTER("LEX::main_select_push"); + current_select_number= 1; + builtin_select.select_number= 1; + if (push_select(&builtin_select)) + DBUG_RETURN(TRUE); + DBUG_RETURN(FALSE); +} + +void Lex_select_lock::set_to(SELECT_LEX *sel) +{ + if (defined_lock) + { + if (sel->master_unit() && + sel == sel->master_unit()->fake_select_lex) + sel->master_unit()->set_lock_to_the_last_select(*this); + else + { + sel->parent_lex->safe_to_cache_query= 0; + if (update_lock) + { + sel->lock_type= TL_WRITE; + sel->set_lock_for_tables(TL_WRITE); + } + else + { + sel->lock_type= TL_READ_WITH_SHARED_LOCKS; + sel->set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS); + } + } + } +} + +bool Lex_order_limit_lock::set_to(SELECT_LEX *sel) +{ + /*TODO: lock */ + //if (lock.defined_lock && sel == sel->master_unit()->fake_select_lex) + // return TRUE; + if (lock.defined_timeout) + { + THD *thd= sel->parent_lex->thd; + if (set_statement_var_if_exists(thd, + C_STRING_WITH_LEN("lock_wait_timeout"), + lock.timeout) || + set_statement_var_if_exists(thd, + C_STRING_WITH_LEN("innodb_lock_wait_timeout"), + lock.timeout)) + return TRUE; + } + lock.set_to(sel); + sel->explicit_limit= limit.explicit_limit; + sel->select_limit= limit.select_limit; + sel->offset_limit= limit.offset_limit; + if (order_list) + { + if (sel->get_linkage() != GLOBAL_OPTIONS_TYPE && + sel->olap != UNSPECIFIED_OLAP_TYPE && + (sel->get_linkage() != UNION_TYPE || sel->braces)) + { + my_error(ER_WRONG_USAGE, MYF(0), + "CUBE/ROLLUP", "ORDER BY"); + return TRUE; + } + sel->order_list= *(order_list); + } + sel->is_set_query_expr_tail= true; + return FALSE; +} + + +static void change_item_list_context(List<Item> *list, + Name_resolution_context *context) +{ + List_iterator_fast<Item> it (*list); + Item *item; + while((item= it++)) + { + item->walk(&Item::change_context_processor, FALSE, (void *)context); + } +} + + +bool LEX::insert_select_hack(SELECT_LEX *sel) +{ + DBUG_ENTER("LEX::insert_select_hack"); + + DBUG_ASSERT(first_select_lex() == &builtin_select); + DBUG_ASSERT(sel != NULL); + + DBUG_ASSERT(builtin_select.first_inner_unit() == NULL); + + if (builtin_select.link_prev) + { + if ((*builtin_select.link_prev= builtin_select.link_next)) + ((st_select_lex *)builtin_select.link_next)->link_prev= + builtin_select.link_prev; + builtin_select.link_prev= NULL; // indicator of removal + } + + set_main_unit(sel->master_unit()); + + DBUG_ASSERT(builtin_select.table_list.elements == 1); + TABLE_LIST *insert_table= builtin_select.table_list.first; + + if (!(insert_table->next_local= sel->table_list.first)) + { + sel->table_list.next= &insert_table->next_local; + } + sel->table_list.first= insert_table; + sel->table_list.elements++; + insert_table->select_lex= sel; + + sel->context.first_name_resolution_table= insert_table; + builtin_select.context= sel->context; + change_item_list_context(&field_list, &sel->context); + + if (sel->tvc && !sel->next_select() && + (sql_command == SQLCOM_INSERT_SELECT || + sql_command == SQLCOM_REPLACE_SELECT)) + { + DBUG_PRINT("info", ("'Usual' INSERT detected")); + many_values= sel->tvc->lists_of_values; + sel->options= sel->tvc->select_options; + sel->tvc= NULL; + if (sql_command == SQLCOM_INSERT_SELECT) + sql_command= SQLCOM_INSERT; + else + sql_command= SQLCOM_REPLACE; + } + + + for (SELECT_LEX *sel= all_selects_list; + sel; + sel= sel->next_select_in_list()) + { + if (sel->select_number != 1) + sel->select_number--; + }; + + DBUG_RETURN(FALSE); +} + + +/* + Create an Item_singlerow_subselect for a query expression. +*/ +Item *LEX::create_item_query_expression(THD *thd, + const char *tok_start, + st_select_lex_unit *unit) +{ + if (!expr_allows_subselect || sql_command == SQLCOM_PURGE) + { + thd->parse_error(ER_SYNTAX_ERROR, tok_start); + return NULL; + } + + // Add the subtree of subquery to the current SELECT_LEX + SELECT_LEX *curr_sel= select_stack_head(); + DBUG_ASSERT(current_select == curr_sel); + if (!curr_sel) + curr_sel= &builtin_select; + curr_sel->register_unit(unit, &curr_sel->context); + curr_sel->add_statistics(unit); + + return new (thd->mem_root) + Item_singlerow_subselect(thd, unit->first_select()); +} + + +/** + Process unit parsed in brackets +*/ + +bool LEX::parsed_unit_in_brackets(SELECT_LEX_UNIT *unit) +{ + SELECT_LEX *first_in_nest= unit->pre_last_parse->next_select()->first_nested; + if (first_in_nest->first_nested != first_in_nest) + { + /* There is a priority jump starting from first_in_nest */ + if (create_priority_nest(first_in_nest) == NULL) + return true; + } + push_select(unit->fake_select_lex); + return false; +} + + +/** + Process tail of unit parsed in brackets +*/ +SELECT_LEX *LEX::parsed_unit_in_brackets_tail(SELECT_LEX_UNIT *unit, + Lex_order_limit_lock * l) +{ + pop_select(); + if (l) + { + (l)->set_to(unit->fake_select_lex); + } + return unit->first_select(); +} + + +/** + Process select parsed in brackets +*/ + +SELECT_LEX *LEX::parsed_select(SELECT_LEX *sel, Lex_order_limit_lock * l) +{ + pop_select(); + if (l) + { + if (sel->next_select()) + { + SELECT_LEX_UNIT *unit= sel->master_unit(); + if (!unit) + unit= create_unit(sel); + if (!unit) + return NULL; + if (!unit->fake_select_lex->is_set_query_expr_tail) + l->set_to(unit->fake_select_lex); + else + { + sel= wrap_unit_into_derived(unit); + if (!sel) + return NULL; + l->set_to(sel); + } + } + else if (!sel->is_set_query_expr_tail) + { + l->set_to(sel); + } + else + { + SELECT_LEX_UNIT *unit= create_unit(sel); + if (!unit) + return NULL; + sel= wrap_unit_into_derived(unit); + if (!sel) + return NULL; + l->set_to(sel); + } + } + return sel; +} + + +/** + Process select parsed in brackets +*/ + +SELECT_LEX *LEX::parsed_select_in_brackets(SELECT_LEX *sel, + Lex_order_limit_lock * l) +{ + sel->braces= TRUE; + return parsed_select(sel, l); +} + + +SELECT_LEX_UNIT *LEX::parsed_select_expr_start(SELECT_LEX *s1, SELECT_LEX *s2, + enum sub_select_type unit_type, + bool distinct) +{ + SELECT_LEX_UNIT *res; + SELECT_LEX *sel1; + SELECT_LEX *sel2; + if (!s1->next_select()) + sel1= s1; + else + { + sel1= wrap_unit_into_derived(s1->master_unit()); + if (!sel1) + return NULL; + } + if (!s2->next_select()) + sel2= s2; + else + { + sel2= wrap_unit_into_derived(s2->master_unit()); + if (!sel2) + return NULL; + } + sel1->link_neighbour(sel2); + sel2->set_linkage_and_distinct(unit_type, distinct); + sel2->first_nested= sel1->first_nested= sel1; + res= create_unit(sel1); + if (res == NULL) + return NULL; + res->pre_last_parse= sel1; + return res; +} + + +SELECT_LEX_UNIT *LEX::parsed_select_expr_cont(SELECT_LEX_UNIT *unit, + SELECT_LEX *s2, + enum sub_select_type unit_type, + bool distinct, bool oracle) +{ + SELECT_LEX *sel1; + if (!s2->next_select()) + sel1= s2; + else + { + sel1= wrap_unit_into_derived(s2->master_unit()); + if (!sel1) + return NULL; + } + SELECT_LEX *last= unit->pre_last_parse->next_select(); + + int cmp= oracle? 0 : cmp_unit_op(unit_type, last->get_linkage()); + if (cmp == 0) + { + sel1->first_nested= last->first_nested; + } + else if (cmp > 0) + { + last->first_nested= unit->pre_last_parse; + sel1->first_nested= last; + } + else /* cmp < 0 */ + { + SELECT_LEX *first_in_nest= last->first_nested; + if (first_in_nest->first_nested != first_in_nest) + { + /* There is a priority jump starting from first_in_nest */ + if ((last= create_priority_nest(first_in_nest)) == NULL) + return NULL; + } + sel1->first_nested= last->first_nested; + } + last->link_neighbour(sel1); + sel1->set_master_unit(unit); + sel1->set_linkage_and_distinct(unit_type, distinct); + unit->pre_last_parse= last; + return unit; +} + +/** + Process parsed select in body +*/ + +SELECT_LEX_UNIT *LEX::parsed_body_select(SELECT_LEX *sel, + Lex_order_limit_lock * l) +{ + if (!(sel= parsed_select(sel, l))) + return NULL; + + SELECT_LEX_UNIT *res= create_unit(sel); + return res; +} + +/** + Process parsed unit in body +*/ + +bool LEX::parsed_body_unit(SELECT_LEX_UNIT *unit) +{ + SELECT_LEX *first_in_nest= + unit->pre_last_parse->next_select()->first_nested; + if (first_in_nest->first_nested != first_in_nest) + { + /* There is a priority jump starting from first_in_nest */ + if (create_priority_nest(first_in_nest) == NULL) + return true; + } + push_select(unit->fake_select_lex); + return false; +} + +/** + Process parsed tail of unit in body + + TODO: make processing for double tail case +*/ + +SELECT_LEX_UNIT *LEX::parsed_body_unit_tail(SELECT_LEX_UNIT *unit, + Lex_order_limit_lock * l) +{ + pop_select(); + if (l) + { + (l)->set_to(unit->fake_select_lex); + } + return unit; +} + +/** + Process subselect parsing +*/ + +SELECT_LEX *LEX::parsed_subselect(SELECT_LEX_UNIT *unit, char *place) +{ + if (!expr_allows_subselect || + sql_command == (int)SQLCOM_PURGE) + { + thd->parse_error(ER_SYNTAX_ERROR, place); + return NULL; + } + + // Add the subtree of subquery to the current SELECT_LEX + SELECT_LEX *curr_sel= select_stack_head(); + DBUG_ASSERT(current_select == curr_sel); + if (curr_sel) + { + curr_sel->register_unit(unit, &curr_sel->context); + curr_sel->add_statistics(unit); + } + + return unit->first_select(); +} + + +/** + Process INSERT-like select +*/ + +bool LEX::parsed_insert_select(SELECT_LEX *first_select) +{ + if (sql_command == SQLCOM_INSERT || + sql_command == SQLCOM_REPLACE) + { + if (sql_command == SQLCOM_INSERT) + sql_command= SQLCOM_INSERT_SELECT; + else + sql_command= SQLCOM_REPLACE_SELECT; + } + insert_select_hack(first_select); + if (check_main_unit_semantics()) + return true; + + // fix "main" select + SELECT_LEX *blt= pop_select(); + DBUG_ASSERT(blt == &builtin_select); + push_select(first_select); + return false; +} + + +bool LEX::parsed_TVC_start() +{ + SELECT_LEX *sel; + many_values.empty(); + insert_list= 0; + if (!(sel= alloc_select(TRUE)) || + push_select(sel)) + return true; + sel->init_select(); + sel->braces= FALSE; // just initialisation + return false; +} + + +SELECT_LEX *LEX::parsed_TVC_end() +{ + + SELECT_LEX *res= pop_select(); // above TVC select + if (!(res->tvc= + new (thd->mem_root) table_value_constr(many_values, + res, + res->options))) + return NULL; + many_values.empty(); + return res; +} + + +TABLE_LIST *LEX::parsed_derived_select(SELECT_LEX *sel, int for_system_time, + LEX_CSTRING *alias) +{ + TABLE_LIST *res; + derived_tables|= DERIVED_SUBQUERY; + sel->set_linkage(DERIVED_TABLE_TYPE); + sel->braces= FALSE; + // Add the subtree of subquery to the current SELECT_LEX + SELECT_LEX *curr_sel= select_stack_head(); + DBUG_ASSERT(current_select == curr_sel); + SELECT_LEX_UNIT *unit= sel->master_unit(); + if (!unit) + { + unit= create_unit(sel); + if (!unit) + return NULL; + } + curr_sel->register_unit(unit, &curr_sel->context); + curr_sel->add_statistics(unit); + + Table_ident *ti= new (thd->mem_root) Table_ident(unit); + if (ti == NULL) + return NULL; + if (!(res= curr_sel->add_table_to_list(thd, ti, alias, 0, + TL_READ, MDL_SHARED_READ))) + return NULL; + if (for_system_time) + { + res->vers_conditions= vers_conditions; + } + return res; +} + +TABLE_LIST *LEX::parsed_derived_unit(SELECT_LEX_UNIT *unit, + int for_system_time, + LEX_CSTRING *alias) +{ + TABLE_LIST *res; + derived_tables|= DERIVED_SUBQUERY; + unit->first_select()->set_linkage(DERIVED_TABLE_TYPE); + + // Add the subtree of subquery to the current SELECT_LEX + SELECT_LEX *curr_sel= select_stack_head(); + DBUG_ASSERT(current_select == curr_sel); + curr_sel->register_unit(unit, &curr_sel->context); + curr_sel->add_statistics(unit); + + Table_ident *ti= new (thd->mem_root) Table_ident(unit); + if (ti == NULL) + return NULL; + if (!(res= curr_sel->add_table_to_list(thd, ti, alias, 0, + TL_READ, MDL_SHARED_READ))) + return NULL; + if (for_system_time) + { + res->vers_conditions= vers_conditions; + } + return res; +} + +bool LEX::parsed_create_view(SELECT_LEX_UNIT *unit, int check) +{ + SQL_I_List<TABLE_LIST> *save= &first_select_lex()->table_list; + set_main_unit(unit); + if (check_main_unit_semantics()) + return true; + first_select_lex()->table_list.push_front(save); + current_select= first_select_lex(); + size_t len= thd->m_parser_state->m_lip.get_cpp_ptr() - + create_view->select.str; + void *create_view_select= thd->memdup(create_view->select.str, len); + create_view->select.length= len; + create_view->select.str= (char *) create_view_select; + size_t not_used; + trim_whitespace(thd->charset(), + &create_view->select, ¬_used); + create_view->check= check; + parsing_options.allows_variable= TRUE; + return false; +} + +bool LEX::select_finalize(st_select_lex_unit *expr) +{ + sql_command= SQLCOM_SELECT; + selects_allow_into= TRUE; + selects_allow_procedure= TRUE; + set_main_unit(expr); + return check_main_unit_semantics(); +} + + +/* + "IN" and "EXISTS" subselect can appear in two statement types: + + 1. Statements that can have table columns, such as SELECT, DELETE, UPDATE + 2. Statements that cannot have table columns, e.g: + RETURN ((1) IN (SELECT * FROM t1)) + IF ((1) IN (SELECT * FROM t1)) + + Statements of the first type call master_select_push() in the beginning. + In such case everything is properly linked. + + Statements of the second type do not call mastr_select_push(). + Here we catch the second case and relink thd->lex->builtin_select and + select_lex to properly point to each other. + + QQ: Shouldn't subselects of other type also call relink_hack()? + QQ: Can we do it at constructor time instead? +*/ + +void LEX::relink_hack(st_select_lex *select_lex) +{ + if (!select_stack_top) // Statements of the second type + { + if (!select_lex->get_master()->get_master()) + ((st_select_lex *) select_lex->get_master())-> + set_master(&builtin_select); + if (!builtin_select.get_slave()) + builtin_select.set_slave(select_lex->get_master()); + } +} + + + +bool SELECT_LEX_UNIT::set_lock_to_the_last_select(Lex_select_lock l) +{ + if (l.defined_lock) + { + SELECT_LEX *sel= first_select(); + while (sel->next_select()) + sel= sel->next_select(); + if (sel->braces) + { + my_error(ER_WRONG_USAGE, MYF(0), "lock options", + "End SELECT expression"); + return TRUE; + } + l.set_to(sel); + } + return FALSE; +} + +/** + Generate unique name for generated derived table for this SELECT +*/ + +bool SELECT_LEX::make_unique_derived_name(THD *thd, LEX_CSTRING *alias) +{ + // uint32 digits + two underscores + trailing '\0' + char buff[MAX_INT_WIDTH + 2 + 1]; + alias->length= my_snprintf(buff, sizeof(buff), "__%u", select_number); + alias->str= thd->strmake(buff, alias->length); + return !alias->str; +} + + +/* + Make a new sp_instr_stmt and set its m_query to a concatenation + of two strings. +*/ +bool LEX::new_sp_instr_stmt(THD *thd, + const LEX_CSTRING &prefix, + const LEX_CSTRING &suffix) +{ + LEX_STRING qbuff; + sp_instr_stmt *i; + + if (!(i= new (thd->mem_root) sp_instr_stmt(sphead->instructions(), + spcont, this))) + return true; + + qbuff.length= prefix.length + suffix.length; + if (!(qbuff.str= (char*) alloc_root(thd->mem_root, qbuff.length + 1))) + return true; + memcpy(qbuff.str, prefix.str, prefix.length); + strmake(qbuff.str + prefix.length, suffix.str, suffix.length); + i->m_query= qbuff; + return sphead->add_instr(i); +} + + +bool LEX::sp_proc_stmt_statement_finalize_buf(THD *thd, const LEX_CSTRING &qbuf) +{ + sphead->m_flags|= sp_get_flags_for_command(this); + /* "USE db" doesn't work in a procedure */ + if (unlikely(sql_command == SQLCOM_CHANGE_DB)) + { + my_error(ER_SP_BADSTATEMENT, MYF(0), "USE"); + return true; + } + /* + Don't add an instruction for SET statements, since all + instructions for them were already added during processing + of "set" rule. + */ + DBUG_ASSERT(sql_command != SQLCOM_SET_OPTION || var_list.is_empty()); + if (sql_command != SQLCOM_SET_OPTION) + return new_sp_instr_stmt(thd, empty_clex_str, qbuf); + return false; +} + + +bool LEX::sp_proc_stmt_statement_finalize(THD *thd, bool no_lookahead) +{ + // Extract the query statement from the tokenizer + Lex_input_stream *lip= &thd->m_parser_state->m_lip; + Lex_cstring qbuf(sphead->m_tmp_query, no_lookahead ? lip->get_ptr() : + lip->get_tok_start()); + return LEX::sp_proc_stmt_statement_finalize_buf(thd, qbuf); +} diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 13e1a5c0cf8..40ba3b6e7b7 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -166,6 +166,23 @@ public: }; +/** + ORDER BY ... LIMIT parameters; +*/ +class Lex_order_limit_lock: public Sql_alloc +{ +public: + SQL_I_List<st_order> *order_list; /* ORDER clause */ + Lex_select_lock lock; + Lex_select_limit limit; + + Lex_order_limit_lock() :order_list(NULL) + {} + + bool set_to(st_select_lex *sel); +}; + + enum sub_select_type { UNSPECIFIED_TYPE, @@ -173,6 +190,14 @@ enum sub_select_type UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE, GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE, OLAP_TYPE }; + +inline int cmp_unit_op(enum sub_select_type op1, enum sub_select_type op2) +{ + DBUG_ASSERT(op1 >= UNION_TYPE && op1 <= EXCEPT_TYPE); + DBUG_ASSERT(op2 >= UNION_TYPE && op2 <= EXCEPT_TYPE); + return (op1 == INTERSECT_TYPE ? 1 : 0) - (op2 == INTERSECT_TYPE ? 1 : 0); +} + enum unit_common_op {OP_MIX, OP_UNION, OP_INTERSECT, OP_EXCEPT}; enum enum_view_suid @@ -301,7 +326,8 @@ struct LEX_TYPE This is not within #ifdef because we want "EXPLAIN PARTITIONS ..." to produce additional "partitions" column even if partitioning is not compiled in. */ -#define DESCRIBE_PARTITIONS 4 +#define DESCRIBE_PARTITIONS 4 +#define DESCRIBE_EXTENDED2 8 #ifdef MYSQL_SERVER @@ -540,7 +566,7 @@ public: unit is container of either - One SELECT - UNION of selects - select_lex and unit are both inherited form select_lex_node + select_lex and unit are both inherited form st_select_lex_node neighbors are two select_lex or units on the same level All select describing structures linked with following pointers: @@ -665,13 +691,6 @@ public: ulonglong options; /* - In sql_cache we store SQL_CACHE flag as specified by user to be - able to restore SELECT statement from internal structures. - */ - enum e_sql_cache { SQL_CACHE_UNSPECIFIED, SQL_NO_CACHE, SQL_CACHE }; - e_sql_cache sql_cache; - - /* result of this query can't be cached, bit field, can be : UNCACHEABLE_DEPENDENT_GENERATED UNCACHEABLE_DEPENDENT_INJECTED @@ -681,11 +700,15 @@ public: UNCACHEABLE_PREPARE */ uint8 uncacheable; +private: enum sub_select_type linkage; +public: bool is_linkage_set() const { return linkage == UNION_TYPE || linkage == INTERSECT_TYPE || linkage == EXCEPT_TYPE; } + enum sub_select_type get_linkage() { return linkage; } + bool distinct; bool no_table_names_allowed; /* used for global order by */ static void *operator new(size_t size, MEM_ROOT *mem_root) throw () @@ -703,13 +726,33 @@ public: } inline st_select_lex_node* get_master() { return master; } + inline st_select_lex_node* get_slave() { return slave; } void include_down(st_select_lex_node *upper); void add_slave(st_select_lex_node *slave_arg); void include_neighbour(st_select_lex_node *before); + void link_chain_down(st_select_lex_node *first); + void link_neighbour(st_select_lex_node *neighbour) + { + DBUG_ASSERT(next == NULL); + DBUG_ASSERT(neighbour != NULL); + next= neighbour; + neighbour->prev= &next; + } + void cut_next() { next= NULL; } void include_standalone(st_select_lex_node *sel, st_select_lex_node **ref); void include_global(st_select_lex_node **plink); void exclude(); void exclude_from_tree(); + void exclude_from_global() + { + if (!link_prev) + return; + if (((*link_prev)= link_next)) + link_next->link_prev= link_prev; + link_next= NULL; + link_prev= NULL; + } + void set_slave(st_select_lex_node *slave_arg) { slave= slave_arg; } void move_node(st_select_lex_node *where_to_move) @@ -725,6 +768,22 @@ public: st_select_lex_node *insert_chain_before(st_select_lex_node **ptr_pos_to_insert, st_select_lex_node *end_chain_node); void move_as_slave(st_select_lex_node *new_master); + void set_linkage(enum sub_select_type l) + { + DBUG_ENTER("st_select_lex_node::set_linkage"); + DBUG_PRINT("info", ("node: %p linkage: %d->%d", this, linkage, l)); + linkage= l; + DBUG_VOID_RETURN; + } + /* + This method created for reiniting LEX in mysql_admin_table() and can be + used only if you are going remove all SELECT_LEX & units except belonger + to LEX (LEX::unit & LEX::select, for other purposes there are + SELECT_LEX_UNIT::exclude_level & SELECT_LEX_UNIT::exclude_tree. + + It is also used in parsing to detach builtin select. + */ + void cut_subtree() { slave= 0; } friend class st_select_lex_unit; friend bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel); friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, @@ -734,6 +793,8 @@ public: friend bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *orig_table_list); friend bool TABLE_LIST::init_derived(THD *thd, bool init_view); + + friend class st_select_lex; private: void fast_exclude(); }; @@ -779,9 +840,9 @@ public: { } - TABLE *table; /* temporary table using for appending UNION results */ select_result *result; + st_select_lex *pre_last_parse; bool prepared, // prepare phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit) optimized_2, @@ -868,7 +929,7 @@ public: { return reinterpret_cast<st_select_lex*>(slave); } - inline void set_with_clause(With_clause *with_cl); + void set_with_clause(With_clause *with_cl); st_select_lex_unit* next_unit() { return reinterpret_cast<st_select_lex_unit*>(next); @@ -911,6 +972,18 @@ public: int save_union_explain(Explain_query *output); int save_union_explain_part2(Explain_query *output); unit_common_op common_op(); + + void reset_distinct(); + void fix_distinct(st_select_lex_unit *new_unit); + + void register_select_chain(SELECT_LEX *first_sel); + + bool set_nest_level(int new_nest_level); + bool check_parameters(SELECT_LEX *main_select); + + bool set_lock_to_the_last_select(Lex_select_lock l); + + friend class st_select_lex; }; typedef class st_select_lex_unit SELECT_LEX_UNIT; @@ -918,25 +991,42 @@ typedef Bounds_checked_array<Item*> Ref_ptr_array; /* - Structure which consists of the field and the item which - produces this field. + Structure which consists of the field and the item that + corresponds to this field. */ - -class Grouping_tmp_field :public Sql_alloc +class Field_pair :public Sql_alloc { public: - Field *tmp_field; - Item *producing_item; - Grouping_tmp_field(Field *fld, Item *item) - :tmp_field(fld), producing_item(item) {} + Field *field; + Item *corresponding_item; + Field_pair(Field *fld, Item *item) + :field(fld), corresponding_item(item) {} }; + /* SELECT_LEX - store information of parsed SELECT statment */ class st_select_lex: public st_select_lex_node { public: + /* + Currently the field first_nested is used only by parser. + It containa either a reference to the first select + of the nest of selects to which 'this' belongs to, or + in the case of priority jump it contains a reference to + the select to which the priority nest has to be attached to. + If there is no priority jump then the first select of the + nest contains the reference to itself in first_nested. + Example: + select1 union select2 intersect select + Here we have a priority jump at select2. + So select2->first_nested points to select1, + while select3->first_nested points to select2 and + select1->first_nested points to select1. + */ + st_select_lex *first_nested; + Name_resolution_context context; LEX_CSTRING db; Item *where, *having; /* WHERE & HAVING clauses */ @@ -1032,6 +1122,7 @@ public: SQL_I_List<ORDER> order_list; /* ORDER clause */ SQL_I_List<ORDER> gorder_list; Item *select_limit, *offset_limit; /* LIMIT clause parameters */ + bool is_set_query_expr_tail; /// Array of pointers to top elements of all_fields list Ref_ptr_array ref_pointer_array; @@ -1154,7 +1245,8 @@ public: nesting_map name_visibility_map; table_map with_dep; - List<Grouping_tmp_field> grouping_tmp_fields; + /* the structure to store fields that are used in the GROUP BY of this select */ + List<Field_pair> grouping_tmp_fields; /* it is for correct printing SELECT options */ thr_lock_type lock_type; @@ -1172,6 +1264,14 @@ public: void init_query(); void init_select(); st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; } + inline void set_master_unit(st_select_lex_unit *master_unit) + { + master= (st_select_lex_node *)master_unit; + } + void set_master(st_select_lex *master_arg) + { + master= master_arg; + } st_select_lex_unit* first_inner_unit() { return (st_select_lex_unit*) slave; @@ -1223,12 +1323,6 @@ public: List<Item>* get_item_list(); ulong get_table_join_options(); void set_lock_for_tables(thr_lock_type lock_type); - inline void init_order() - { - order_list.elements= 0; - order_list.first= 0; - order_list.next= &order_list.first; - } /* This method created for reiniting LEX in mysql_admin_table() and can be used only if you are going remove all SELECT_LEX & units except belonger @@ -1359,9 +1453,8 @@ public: With_element *find_table_def_in_with_clauses(TABLE_LIST *table); bool check_unrestricted_recursive(bool only_standard_compliant); bool check_subqueries_with_recursive_references(); - void collect_grouping_fields(THD *thd, ORDER *grouping_list); - void check_cond_extraction_for_grouping_fields(Item *cond, - TABLE_LIST *derived); + void collect_grouping_fields(THD *thd, ORDER *grouping_list); + void check_cond_extraction_for_grouping_fields(Item *cond); Item *build_cond_for_grouping_fields(THD *thd, Item *cond, bool no_to_clones); @@ -1387,6 +1480,11 @@ public: bool cond_pushdown_is_allowed() const { return !olap && !explicit_limit && !tvc; } + void pushdown_cond_into_where_clause(THD *thd, Item *extracted_cond, + Item **remaining_cond, + Item_transformer transformer, + uchar *arg); + private: bool m_non_agg_field_used; bool m_agg_func_used; @@ -1404,6 +1502,35 @@ public: DBUG_ASSERT(this != sel); select_n_where_fields+= sel->select_n_where_fields; } + inline void set_linkage_and_distinct(enum sub_select_type l, bool d) + { + DBUG_ENTER("SELECT_LEX::set_linkage_and_distinct"); + DBUG_PRINT("info", ("select: %p distinct %d", this, d)); + set_linkage(l); + DBUG_ASSERT(l == UNION_TYPE || + l == INTERSECT_TYPE || + l == EXCEPT_TYPE); + if (d && master_unit() && master_unit()->union_distinct != this) + master_unit()->union_distinct= this; + distinct= d; + with_all_modifier= !distinct; + DBUG_VOID_RETURN; + } + bool set_nest_level(int new_nest_level); + bool check_parameters(SELECT_LEX *main_select); + void mark_select() + { + DBUG_ENTER("st_select_lex::mark_select()"); + DBUG_PRINT("info", ("Select #%d", select_number)); + DBUG_VOID_RETURN; + } + void register_unit(SELECT_LEX_UNIT *unit, + Name_resolution_context *outer_context); + SELECT_LEX_UNIT *attach_selects_chain(SELECT_LEX *sel, + Name_resolution_context *context); + void add_statistics(SELECT_LEX_UNIT *unit); + bool make_unique_derived_name(THD *thd, LEX_CSTRING *alias); + void lex_start(LEX *plex); }; typedef class st_select_lex SELECT_LEX; @@ -2803,8 +2930,13 @@ class Query_arena_memroot; struct LEX: public Query_tables_list { SELECT_LEX_UNIT unit; /* most upper unit */ - SELECT_LEX select_lex; /* first SELECT_LEX */ + inline SELECT_LEX *first_select_lex() {return unit.first_select();} + +private: + SELECT_LEX builtin_select; /* current SELECT_LEX in parsing */ + +public: SELECT_LEX *current_select; /* list of all SELECT_LEX */ SELECT_LEX *all_selects_list; @@ -2906,6 +3038,12 @@ private: bool sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop); bool sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop); + /* + Check if Item_field and Item_ref are allowed in the current statement. + @retval false OK (fields are allowed) + @retval true ERROR (fields are not allowed). Error is raised. + */ + bool check_expr_allows_fields_or_error(THD *thd, const char *name) const; public: void parse_error(uint err_number= ER_SYNTAX_ERROR); inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;} @@ -2933,6 +3071,8 @@ public: required a local context, the parser pops the top-most context. */ List<Name_resolution_context> context_stack; + SELECT_LEX *select_stack[MAX_SELECT_NESTING + 1]; + uint select_stack_top; SQL_I_List<ORDER> proc_list; SQL_I_List<TABLE_LIST> auxiliary_table_list, save_list; @@ -2972,6 +3112,8 @@ public: syntax error back. */ bool expr_allows_subselect; + bool selects_allow_into; + bool selects_allow_procedure; /* A special command "PARSE_VCOL_EXPR" is defined for the parser to translate a defining expression of a virtual column into an @@ -2997,6 +3139,7 @@ public: uint profile_query_id; uint profile_options; uint grant, grant_tot_col, which_columns; + enum backup_stages backup_stage; enum Foreign_key::fk_match_opt fk_match_option; enum_fk_option fk_update_opt; enum_fk_option fk_delete_opt; @@ -3026,7 +3169,17 @@ public: enum enum_yes_no_unknown tx_chain, tx_release; bool safe_to_cache_query; bool subqueries, ignore; + bool next_is_main; // use "main" SELECT_LEX for nrxt allocation; + bool next_is_down; // use "main" SELECT_LEX for nrxt allocation; st_parsing_options parsing_options; + uint8 lex_options; // see OPTION_LEX_* + /* + In sql_cache we store SQL_CACHE flag as specified by user to be + able to restore SELECT statement from internal structures. + */ + enum e_sql_cache { SQL_CACHE_UNSPECIFIED, SQL_NO_CACHE, SQL_CACHE }; + e_sql_cache sql_cache; + Alter_info alter_info; /* For CREATE TABLE statement last element of table list which is not @@ -3225,20 +3378,24 @@ public: SELECT_LEX *sl; SELECT_LEX_UNIT *un; for (sl= current_select, un= sl->master_unit(); - un != &unit; - sl= sl->outer_select(), un= sl->master_unit()) + un && un != &unit; + sl= sl->outer_select(), un= (sl ? sl->master_unit() : NULL)) { - sl->uncacheable|= cause; - un->uncacheable|= cause; + sl->uncacheable|= cause; + un->uncacheable|= cause; } - select_lex.uncacheable|= cause; + if (sl) + sl->uncacheable|= cause; } + if (first_select_lex()) + first_select_lex()->uncacheable|= cause; } void set_trg_event_type_for_tables(); TABLE_LIST *unlink_first_table(bool *link_to_local); void link_first_table_back(TABLE_LIST *first, bool link_to_local); void first_lists_tables_same(); + void fix_first_select_number(); bool can_be_merged(); bool can_use_merged(); @@ -3276,14 +3433,83 @@ public: void cleanup_after_one_table_open(); - bool push_context(Name_resolution_context *context, MEM_ROOT *mem_root) + bool push_context(Name_resolution_context *context); + + void pop_context() { - return context_stack.push_front(context, mem_root); + DBUG_ENTER("LEX::pop_context"); + Name_resolution_context *context= context_stack.pop(); + DBUG_PRINT("info", ("Pop context %p Select: %p (%d)", + context, context->select_lex, + (context->select_lex ? + context->select_lex->select_number: + 0))); + DBUG_VOID_RETURN; } - void pop_context() + SELECT_LEX *select_stack_head() { - context_stack.pop(); + if (likely(select_stack_top)) + return select_stack[select_stack_top - 1]; + return NULL; + } + + bool push_select(SELECT_LEX *select_lex) + { + DBUG_ENTER("LEX::push_select"); + DBUG_PRINT("info", ("Top Select was %p (%d) depth: %u pushed: %p (%d)", + select_stack_head(), + select_stack_top, + (select_stack_top ? + select_stack_head()->select_number : + 0), + select_lex, select_lex->select_number)); + if (unlikely(select_stack_top > MAX_SELECT_NESTING)) + { + my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0)); + DBUG_RETURN(TRUE); + } + if (push_context(&select_lex->context)) + DBUG_RETURN(TRUE); + select_stack[select_stack_top++]= select_lex; + current_select= select_lex; + DBUG_RETURN(FALSE); + } + + SELECT_LEX *pop_select() + { + DBUG_ENTER("LEX::pop_select"); + SELECT_LEX *select_lex; + if (likely(select_stack_top)) + select_lex= select_stack[--select_stack_top]; + else + select_lex= 0; + DBUG_PRINT("info", ("Top Select is %p (%d) depth: %u poped: %p (%d)", + select_stack_head(), + select_stack_top, + (select_stack_top ? + select_stack_head()->select_number : + 0), + select_lex, + (select_lex ? select_lex->select_number : 0))); + DBUG_ASSERT(select_lex); + + pop_context(); + + if (unlikely(!select_stack_top)) + { + current_select= NULL; + DBUG_PRINT("info", ("Top Select is empty")); + } + else + current_select= select_stack[select_stack_top - 1]; + + DBUG_RETURN(select_lex); + } + + SELECT_LEX *current_select_or_default() + { + return current_select ? current_select : &builtin_select; } bool copy_db_to(LEX_CSTRING *to); @@ -3292,6 +3518,7 @@ public: { return context_stack.head(); } + /* Restore the LEX and THD in case of a parse error. */ @@ -3320,9 +3547,8 @@ public: on its top. So select_lex (as the first added) will be at the tail of the list. */ - if (&select_lex == all_selects_list && !sroutines.records) + if (first_select_lex() == all_selects_list && !sroutines.records) { - DBUG_ASSERT(!all_selects_list->next_select_in_list()); return TRUE; } return FALSE; @@ -3343,6 +3569,11 @@ public: bool last_field_generated_always_as_row_end(); bool set_bincmp(CHARSET_INFO *cs, bool bin); + bool new_sp_instr_stmt(THD *, const LEX_CSTRING &prefix, + const LEX_CSTRING &suffix); + bool sp_proc_stmt_statement_finalize_buf(THD *, const LEX_CSTRING &qbuf); + bool sp_proc_stmt_statement_finalize(THD *, bool no_lookahead); + bool get_dynamic_sql_string(LEX_CSTRING *dst, String *buffer); bool prepared_stmt_params_fix_fields(THD *thd) { @@ -3361,9 +3592,6 @@ public: int case_stmt_action_expr(Item* expr); int case_stmt_action_when(Item *when, bool simple); int case_stmt_action_then(); - bool add_select_to_union_list(bool is_union_distinct, - enum sub_select_type type, - bool is_top_level); bool setup_select_in_parentheses(); bool set_trigger_new_row(const LEX_CSTRING *name, Item *val); bool set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2, @@ -3488,7 +3716,12 @@ public: return create_item_qualified_asterisk(thd, &a, &b); } - Item *create_item_ident_nosp(THD *thd, Lex_ident_sys_st *name); + Item *create_item_ident_field(THD *thd, const char *db, const char *table, + const Lex_ident_sys_st *name); + Item *create_item_ident_nosp(THD *thd, Lex_ident_sys_st *name) + { + return create_item_ident_field(thd, NullS, NullS, name); + } Item *create_item_ident_sp(THD *thd, Lex_ident_sys_st *name, const char *start, const char *end); Item *create_item_ident(THD *thd, Lex_ident_cli_st *cname) @@ -3626,6 +3859,10 @@ public: const Lex_ident_cli_st *var_name, const Lex_ident_cli_st *field_name); + Item *create_item_query_expression(THD *thd, + const char *tok_start, + st_select_lex_unit *unit); + Item *make_item_func_replace(THD *thd, Item *org, Item *find, Item *replace); Item *make_item_func_substr(THD *thd, Item *a, Item *b, Item *c); Item *make_item_func_substr(THD *thd, Item *a, Item *b); @@ -3824,6 +4061,17 @@ public: sp_for_loop_intrange_finalize(thd, loop); } bool sp_for_loop_outer_block_finalize(THD *thd, const Lex_for_loop_st &loop); + + /* + Make an Item when an identifier is found in the FOR loop bounds: + FOR rec IN cursor + FOR rec IN var1 .. var2 + FOR rec IN row1.field1 .. xxx + */ + Item *create_item_for_loop_bound(THD *thd, + const LEX_CSTRING *a, + const LEX_CSTRING *b, + const LEX_CSTRING *c); /* End of FOR LOOP methods */ bool add_signal_statement(THD *thd, const class sp_condition_value *value); @@ -3946,7 +4194,7 @@ public: bool if_exists() const { return create_info.if_exists(); } SELECT_LEX *exclude_last_select(); - bool add_unit_in_brackets(SELECT_LEX *nselect); + SELECT_LEX *exclude_not_first_select(SELECT_LEX *exclude); void check_automatic_up(enum sub_select_type type); bool create_or_alter_view_finalize(THD *thd, Table_ident *table_ident); bool add_alter_view(THD *thd, uint16 algorithm, enum_view_suid suid, @@ -3954,7 +4202,6 @@ public: bool add_create_view(THD *thd, DDL_options_st ddl, uint16 algorithm, enum_view_suid suid, Table_ident *table_ident); - bool add_grant_command(THD *thd, enum_sql_command sql_command_arg, stored_procedure_type type_arg); @@ -3973,7 +4220,7 @@ public: */ bool check_simple_select(const LEX_CSTRING *option) { - if (current_select != &select_lex) + if (current_select != &builtin_select) { char command[80]; strmake(command, option->str, MY_MIN(option->length, sizeof(command)-1)); @@ -3991,6 +4238,63 @@ public: } bool tvc_finalize(); bool tvc_finalize_derived(); + + bool make_select_in_brackets(SELECT_LEX* dummy_select, + SELECT_LEX *nselect, bool automatic); + + SELECT_LEX_UNIT *alloc_unit(); + SELECT_LEX *alloc_select(bool is_select); + SELECT_LEX_UNIT *create_unit(SELECT_LEX*); + SELECT_LEX *wrap_unit_into_derived(SELECT_LEX_UNIT *unit); + SELECT_LEX *wrap_select_chain_into_derived(SELECT_LEX *sel); + bool main_select_push(); + bool insert_select_hack(SELECT_LEX *sel); + SELECT_LEX *create_priority_nest(SELECT_LEX *first_in_nest); + + void set_main_unit(st_select_lex_unit *u) + { + unit.options= u->options; + unit.uncacheable= u->uncacheable; + unit.register_select_chain(u->first_select()); + unit.first_select()->options|= builtin_select.options; + unit.fake_select_lex= u->fake_select_lex; + unit.union_distinct= u->union_distinct; + unit.set_with_clause(u->with_clause); + builtin_select.exclude_from_global(); + } + bool check_main_unit_semantics(); + + // reaction on different parsed parts (bodies are in sql_yacc.yy) + bool parsed_unit_in_brackets(SELECT_LEX_UNIT *unit); + SELECT_LEX *parsed_select(SELECT_LEX *sel, Lex_order_limit_lock * l); + SELECT_LEX *parsed_unit_in_brackets_tail(SELECT_LEX_UNIT *unit, + Lex_order_limit_lock * l); + SELECT_LEX *parsed_select_in_brackets(SELECT_LEX *sel, + Lex_order_limit_lock * l); + SELECT_LEX_UNIT *parsed_select_expr_start(SELECT_LEX *s1, SELECT_LEX *s2, + enum sub_select_type unit_type, + bool distinct); + SELECT_LEX_UNIT *parsed_select_expr_cont(SELECT_LEX_UNIT *unit, + SELECT_LEX *s2, + enum sub_select_type unit_type, + bool distinct, bool oracle); + SELECT_LEX_UNIT *parsed_body_select(SELECT_LEX *sel, + Lex_order_limit_lock * l); + bool parsed_body_unit(SELECT_LEX_UNIT *unit); + SELECT_LEX_UNIT *parsed_body_unit_tail(SELECT_LEX_UNIT *unit, + Lex_order_limit_lock * l); + SELECT_LEX *parsed_subselect(SELECT_LEX_UNIT *unit, char *place); + bool parsed_insert_select(SELECT_LEX *firs_select); + bool parsed_TVC_start(); + SELECT_LEX *parsed_TVC_end(); + TABLE_LIST *parsed_derived_select(SELECT_LEX *sel, int for_system_time, + LEX_CSTRING *alias); + TABLE_LIST *parsed_derived_unit(SELECT_LEX_UNIT *unit, + int for_system_time, + LEX_CSTRING *alias); + bool parsed_create_view(SELECT_LEX_UNIT *unit, int check); + bool select_finalize(st_select_lex_unit *expr); + void relink_hack(st_select_lex *select_lex); }; diff --git a/sql/sql_list.h b/sql/sql_list.h index 39a1c3375e0..27827b42be5 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -611,7 +611,7 @@ struct ilink struct ilink **prev,*next; static void *operator new(size_t size) throw () { - return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE | ME_FATALERROR)); + return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE | ME_FATAL)); } static void operator delete(void* ptr_arg, size_t) { diff --git a/sql/sql_load.cc b/sql/sql_load.cc index ddb5029c78a..dd6e723c953 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -390,10 +390,13 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, if (mysql_handle_single_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) || mysql_handle_single_derived(thd->lex, table_list, DT_PREPARE)) DBUG_RETURN(TRUE); - if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, - &thd->lex->select_lex.top_join_list, + if (setup_tables_and_check_access(thd, + &thd->lex->first_select_lex()->context, + &thd->lex->first_select_lex()-> + top_join_list, table_list, - thd->lex->select_lex.leaf_tables, FALSE, + thd->lex->first_select_lex()->leaf_tables, + FALSE, INSERT_ACL | UPDATE_ACL, INSERT_ACL | UPDATE_ACL, FALSE)) DBUG_RETURN(-1); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 233e0313121..312608e1395 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -109,6 +109,7 @@ #include "../storage/maria/ha_maria.h" #endif +#include "wsrep.h" #include "wsrep_mysqld.h" #include "wsrep_thd.h" @@ -770,6 +771,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CREATE_SERVER]= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_ALTER_SERVER]= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_DROP_SERVER]= CF_AUTO_COMMIT_TRANS; + sql_command_flags[SQLCOM_BACKUP]= CF_AUTO_COMMIT_TRANS; /* The following statements can deal with temporary tables, @@ -1180,10 +1182,8 @@ static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables) { for (const TABLE_LIST *table= tables; table; table= table->next_global) { - TABLE_CATEGORY c; LEX_CSTRING db= table->db, tn= table->table_name; - c= get_table_category(&db, &tn); - if (c != TABLE_CATEGORY_INFORMATION && c != TABLE_CATEGORY_PERFORMANCE) + if (get_table_category(&db, &tn) < TABLE_CATEGORY_INFORMATION) return false; } return true; @@ -2009,10 +2009,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, Init TABLE_LIST members necessary when the undelrying table is view. */ - table_list.select_lex= &(thd->lex->select_lex); + table_list.select_lex= thd->lex->first_select_lex(); thd->lex-> - select_lex.table_list.link_in_list(&table_list, - &table_list.next_local); + first_select_lex()->table_list.link_in_list(&table_list, + &table_list.next_local); thd->lex->add_to_query_tables(&table_list); if (is_infoschema_db(&table_list.db)) @@ -2131,6 +2131,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, DBUG_EXECUTE_IF("simulate_detached_thread_refresh", debug_simulate= TRUE;); if (debug_simulate) { + /* This code doesn't work under FTWRL */ + DBUG_ASSERT(! (options & REFRESH_READ_LOCK)); /* Simulate a reload without a attached thread session. Provides a environment similar to that of when the @@ -2577,23 +2579,24 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, DBUG_RETURN(1); #else { - if (lex->select_lex.db.str == NULL && - lex->copy_db_to(&lex->select_lex.db)) + if (lex->first_select_lex()->db.str == NULL && + lex->copy_db_to(&lex->first_select_lex()->db)) { DBUG_RETURN(1); } schema_select_lex= new (thd->mem_root) SELECT_LEX(); schema_select_lex->table_list.first= NULL; if (lower_case_table_names == 1) - lex->select_lex.db.str= thd->strdup(lex->select_lex.db.str); - schema_select_lex->db= lex->select_lex.db; + lex->first_select_lex()->db.str= + thd->strdup(lex->first_select_lex()->db.str); + schema_select_lex->db= lex->first_select_lex()->db; /* check_db_name() may change db.str if lower_case_table_names == 1, but that's ok as the db is allocted above in this case. */ - if (check_db_name((LEX_STRING*) &lex->select_lex.db)) + if (check_db_name((LEX_STRING*) &lex->first_select_lex()->db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), lex->select_lex.db.str); + my_error(ER_WRONG_DB_NAME, MYF(0), lex->first_select_lex()->db.str); DBUG_RETURN(1); } break; @@ -2632,7 +2635,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, default: break; } - + if (schema_select_lex) + schema_select_lex->set_master_unit(&lex->unit); SELECT_LEX *select_lex= lex->current_select; if (make_schema_select(thd, select_lex, get_schema_table(schema_table_idx))) DBUG_RETURN(1); @@ -3010,7 +3014,7 @@ static int mysql_create_routine(THD *thd, LEX *lex) if (sp_process_definer(thd)) return true; - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); if (!lex->sphead->m_handler->sp_create_routine(thd, lex->sphead)) { #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -3079,7 +3083,9 @@ static int mysql_create_routine(THD *thd, LEX *lex) #endif return false; } -WSREP_ERROR_LABEL: +#ifdef WITH_WSREP +wsrep_error_label: +#endif return true; } @@ -3227,7 +3233,7 @@ mysql_execute_command(THD *thd) int up_result= 0; LEX *lex= thd->lex; /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */ - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); /* first table of first SELECT_LEX */ TABLE_LIST *first_table= select_lex->table_list.first; /* list of all tables in query */ @@ -3266,6 +3272,7 @@ mysql_execute_command(THD *thd) DBUG_ASSERT(first_table == all_tables && first_table != 0); */ lex->first_lists_tables_same(); + lex->fix_first_select_number(); /* should be assigned after making first tables same */ all_tables= lex->query_tables; /* set context for commands which do not use setup_tables */ @@ -4181,11 +4188,7 @@ mysql_execute_command(THD *thd) goto end_with_restore_list; } - /* Copy temporarily the statement flags to thd for lock_table_names() */ - uint save_thd_create_info_options= thd->lex->create_info.options; - thd->lex->create_info.options|= create_info.options; res= open_and_lock_tables(thd, create_info, lex->query_tables, TRUE, 0); - thd->lex->create_info.options= save_thd_create_info_options; if (unlikely(res)) { /* Got error or warning. Set res to 1 if error */ @@ -5169,7 +5172,8 @@ end_with_restore_list: thd->mdl_context.release_transactional_locks(); thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); } - if (thd->global_read_lock.is_acquired()) + if (thd->global_read_lock.is_acquired() && + thd->current_backup_stage == BACKUP_FINISHED) thd->global_read_lock.unlock_global_read_lock(thd); if (res) goto error; @@ -5184,6 +5188,13 @@ end_with_restore_list: if (res) goto error; + /* We can't have any kind of table locks while backup is active */ + if (thd->current_backup_stage != BACKUP_FINISHED) + { + my_error(ER_BACKUP_LOCK_IS_ACTIVE, MYF(0)); + goto error; + } + /* Here we have to pre-open temporary tables for LOCK TABLES. @@ -5216,6 +5227,12 @@ end_with_restore_list: my_ok(thd); } break; + case SQLCOM_BACKUP: + if (check_global_access(thd, RELOAD_ACL)) + goto error; + if (!(res= run_backup_stage(thd, lex->backup_stage))) + my_ok(thd); + break; case SQLCOM_CREATE_DB: { if (prepare_db_action(thd, lex->create_info.or_replace() ? @@ -6298,8 +6315,10 @@ end_with_restore_list: goto finish; error: -WSREP_ERROR_LABEL: - res= TRUE; +#ifdef WITH_WSREP +wsrep_error_label: +#endif + res= true; finish: @@ -7522,7 +7541,7 @@ bool check_stack_overrun(THD *thd, long margin, if (ebuff) { my_snprintf(ebuff, MYSQL_ERRMSG_SIZE, ER_THD(thd, ER_STACK_OVERRUN_NEED_MORE), stack_used, my_thread_stack_size, margin); - my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATALERROR)); + my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATAL)); delete [] ebuff; } return 1; @@ -7592,16 +7611,21 @@ void THD::reset_for_next_command(bool do_clear_error) DBUG_ASSERT(!in_sub_stmt); if (likely(do_clear_error)) + { clear_error(1); - + /* + The following variable can't be reset in clear_error() as + clear_error() is called during auto_repair of table + */ + error_printed_to_log= 0; + } free_list= 0; /* We also assign stmt_lex in lex_start(), but during bootstrap this code is executed first. */ DBUG_ASSERT(lex == &main_lex); - main_lex.stmt_lex= &main_lex; main_lex.current_select_number= 1; - DBUG_PRINT("info", ("Lex and stmt_lex: %p", &main_lex)); + main_lex.stmt_lex= &main_lex; main_lex.current_select_number= 0; /* Those two lines below are theoretically unneeded as THD::cleanup_after_query() should take care of this already. @@ -7687,11 +7711,7 @@ mysql_init_select(LEX *lex) SELECT_LEX *select_lex= lex->current_select; select_lex->init_select(); lex->wild= 0; - if (select_lex == &lex->select_lex) - { - DBUG_ASSERT(lex->result == 0); - lex->exchange= 0; - } + lex->exchange= 0; } @@ -7712,6 +7732,7 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex) { THD *thd= lex->thd; bool new_select= select_lex == NULL; + int old_nest_level= lex->current_select->nest_level; DBUG_ENTER("mysql_new_select"); if (new_select) @@ -7723,27 +7744,19 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex) select_lex->init_query(); select_lex->init_select(); } - lex->nest_level++; - if (lex->nest_level > (int) MAX_SELECT_NESTING) - { - my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0)); - DBUG_RETURN(1); - } - select_lex->nest_level= lex->nest_level; select_lex->nest_level_base= &thd->lex->unit; if (move_down) { + lex->nest_level++; + if (select_lex->set_nest_level(old_nest_level + 1)) + DBUG_RETURN(1); SELECT_LEX_UNIT *unit; lex->subqueries= TRUE; /* first select_lex of subselect or derived table */ - if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT())) + if (!(unit= lex->alloc_unit())) DBUG_RETURN(1); - unit->init_query(); - unit->thd= thd; unit->include_down(lex->current_select); - unit->link_next= 0; - unit->link_prev= 0; unit->return_to= lex->current_select; select_lex->include_down(unit); /* @@ -7777,15 +7790,13 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex) "SELECT ... PROCEDURE ANALYSE()"); DBUG_RETURN(TRUE); } - // SELECT 1 FROM t1 ORDER BY 1 UNION SELECT 1 FROM t1 -- not possible - DBUG_ASSERT(!lex->current_select->order_list.first || - lex->current_select->braces); - // SELECT 1 FROM t1 LIMIT 1 UNION SELECT 1 FROM t1; -- not possible - DBUG_ASSERT(!lex->current_select->explicit_limit || - lex->current_select->braces); + SELECT_LEX_NODE *save_slave= select_lex->slave; select_lex->include_neighbour(lex->current_select); - SELECT_LEX_UNIT *unit= select_lex->master_unit(); + select_lex->slave= save_slave; + SELECT_LEX_UNIT *unit= select_lex->master_unit(); + if (select_lex->set_nest_level(old_nest_level)) + DBUG_RETURN(1); if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd)) DBUG_RETURN(1); select_lex->context.outer_context= @@ -7841,9 +7852,10 @@ void mysql_init_multi_delete(LEX *lex) { lex->sql_command= SQLCOM_DELETE_MULTI; mysql_init_select(lex); - lex->select_lex.select_limit= 0; + lex->first_select_lex()->select_limit= 0; lex->unit.select_limit_cnt= HA_POS_ERROR; - lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list); + lex->first_select_lex()->table_list. + save_and_clear(&lex->auxiliary_table_list); lex->query_tables= 0; lex->query_tables_last= &lex->query_tables; } @@ -8159,7 +8171,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *rawbuf, uint length) thd->reset_for_next_command(); if (!parse_sql(thd, & parser_state, NULL, true) && - all_tables_not_ok(thd, lex->select_lex.table_list.first)) + all_tables_not_ok(thd, lex->first_select_lex()->table_list.first)) error= 1; /* Ignore question */ thd->end_statement(); } @@ -8241,6 +8253,10 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, LEX_CSTRING alias_str; LEX *lex= thd->lex; DBUG_ENTER("add_table_to_list"); + DBUG_PRINT("enter", ("Table '%s' (%p) Select %p (%u)", + (alias ? alias->str : table->table.str), + table, + this, select_number)); if (unlikely(!table)) DBUG_RETURN(0); // End of memory @@ -8334,7 +8350,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->schema_table_name= ptr->table_name; ptr->schema_table= schema_table; } - ptr->select_lex= lex->current_select; + ptr->select_lex= this; /* We can't cache internal temporary tables between prepares as the table may be deleted before next exection. @@ -8441,8 +8457,6 @@ bool st_select_lex::init_nested_join(THD *thd) nested_join= ptr->nested_join= ((NESTED_JOIN*) ((uchar*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST)))); - if (unlikely(join_list->push_front(ptr, thd->mem_root))) - DBUG_RETURN(1); ptr->embedding= embedding; ptr->join_list= join_list; ptr->alias.str="(nested_join)"; @@ -8550,7 +8564,6 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd) ptr->join_using_fields= prev_join_using; } } - join_list->push_front(ptr, thd->mem_root); nested_join->used_tables= nested_join->not_null_tables= (table_map) 0; DBUG_RETURN(ptr); } @@ -8742,7 +8755,7 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg) { SELECT_LEX *first_sl= first_select(); - DBUG_ENTER("add_fake_select_lex"); + DBUG_ENTER("st_select_lex_unit::add_fake_select_lex"); DBUG_ASSERT(!fake_select_lex); if (!(fake_select_lex= new (thd_arg->mem_root) SELECT_LEX())) @@ -8752,16 +8765,19 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg) fake_select_lex->select_number= INT_MAX; fake_select_lex->parent_lex= thd_arg->lex; /* Used in init_query. */ fake_select_lex->make_empty_select(); - fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE; + fake_select_lex->set_linkage(GLOBAL_OPTIONS_TYPE); fake_select_lex->select_limit= 0; + fake_select_lex->no_table_names_allowed= 1; + fake_select_lex->context.outer_context=first_sl->context.outer_context; /* allow item list resolving in fake select for ORDER BY */ fake_select_lex->context.resolve_in_select_list= TRUE; fake_select_lex->context.select_lex= fake_select_lex; fake_select_lex->nest_level_base= first_select()->nest_level_base; - fake_select_lex->nest_level=first_select()->nest_level; + if (fake_select_lex->set_nest_level(first_select()->nest_level)) + DBUG_RETURN(1); if (!is_unit_op()) { @@ -8774,7 +8790,7 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg) fake_select_lex->no_table_names_allowed= 1; thd_arg->lex->current_select= fake_select_lex; } - thd_arg->lex->pop_context(); + //thd_arg->lex->pop_context("add fake"); DBUG_RETURN(0); } @@ -8810,7 +8826,7 @@ push_new_name_resolution_context(THD *thd, left_op->first_leaf_for_name_resolution(); on_context->last_name_resolution_table= right_op->last_leaf_for_name_resolution(); - return thd->lex->push_context(on_context, thd->mem_root); + return thd->lex->push_context(on_context); } @@ -9239,7 +9255,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) { TABLE_LIST *table; LEX *lex= thd->lex; - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); DBUG_ENTER("multi_update_precheck"); if (select_lex->item_list.elements != lex->value_list.elements) @@ -9275,7 +9291,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) /* Is there tables of subqueries? */ - if (&lex->select_lex != lex->all_selects_list) + if (lex->first_select_lex() != lex->all_selects_list) { DBUG_PRINT("info",("Checking sub query list")); for (table= tables; table; table= table->next_global) @@ -9309,7 +9325,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) { - SELECT_LEX *select_lex= &thd->lex->select_lex; + SELECT_LEX *select_lex= thd->lex->first_select_lex(); TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first; TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; DBUG_ENTER("multi_delete_precheck"); @@ -9426,7 +9442,7 @@ static TABLE_LIST *multi_delete_table_match(LEX *lex, TABLE_LIST *tbl, bool multi_delete_set_locks_and_link_aux_tables(LEX *lex) { - TABLE_LIST *tables= lex->select_lex.table_list.first; + TABLE_LIST *tables= lex->first_select_lex()->table_list.first; TABLE_LIST *target_tbl; DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables"); @@ -9468,7 +9484,8 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex) bool update_precheck(THD *thd, TABLE_LIST *tables) { DBUG_ENTER("update_precheck"); - if (thd->lex->select_lex.item_list.elements != thd->lex->value_list.elements) + if (thd->lex->first_select_lex()->item_list.elements != + thd->lex->value_list.elements) { my_message(ER_WRONG_VALUE_COUNT, ER_THD(thd, ER_WRONG_VALUE_COUNT), MYF(0)); DBUG_RETURN(TRUE); @@ -9559,7 +9576,7 @@ void create_table_set_open_action_and_adjust_tables(LEX *lex) else create_table->open_type= OT_BASE_ONLY; - if (!lex->select_lex.item_list.elements) + if (!lex->first_select_lex()->item_list.elements) { /* Avoid opening and locking target table for ordinary CREATE TABLE @@ -9590,7 +9607,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *create_table) { LEX *lex= thd->lex; - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); ulong want_priv; bool error= TRUE; // Error message is given DBUG_ENTER("create_table_precheck"); @@ -9732,8 +9749,9 @@ Item *negate_expression(THD *thd, Item *expr) { /* it is NOT(NOT( ... )) */ Item *arg= ((Item_func *) expr)->arguments()[0]; + const Type_handler *fh= arg->fixed_type_handler(); enum_parsing_place place= thd->lex->current_select->parsing_place; - if (arg->is_bool_type() || place == IN_WHERE || place == IN_HAVING) + if ((fh && fh->is_bool_type()) || place == IN_WHERE || place == IN_HAVING) return arg; /* if it is not boolean function then we have to emulate value of @@ -10101,6 +10119,9 @@ bool parse_sql(THD *thd, Parser_state *parser_state, ((thd->variables.sql_mode & MODE_ORACLE) ? ORAparse(thd) : MYSQLparse(thd)) != 0; + DBUG_ASSERT(opt_bootstrap || mysql_parse_status || + thd->lex->select_stack_top == 0); + thd->lex->current_select= thd->lex->first_select_lex(); /* Check that if MYSQLparse() failed either thd->is_error() is set, or an diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 9e6c333d3c9..6b530a95efb 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -525,15 +525,10 @@ static bool create_full_part_field_array(THD *thd, TABLE *table, full_part_field_array may be NULL if storage engine supports native partitioning. */ - table->vcol_set= table->read_set= &part_info->full_part_field_set; + table->read_set= &part_info->full_part_field_set; if ((ptr= part_info->full_part_field_array)) for (; *ptr; ptr++) - { - if ((*ptr)->vcol_info) - table->mark_virtual_col(*ptr); - else - bitmap_fast_test_and_set(table->read_set, (*ptr)->field_index); - } + table->mark_column_with_deps(*ptr); table->default_column_bitmaps(); end: @@ -835,7 +830,8 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, goto end; table->get_fields_in_item_tree= true; - func_expr->walk(&Item::change_context_processor, 0, &lex.select_lex.context); + func_expr->walk(&Item::change_context_processor, 0, + &lex.first_select_lex()->context); thd->where= "partition function"; /* In execution we must avoid the use of thd->change_item_tree since @@ -1563,7 +1559,7 @@ static bool check_vers_constants(THD *thd, partition_info *part_info) my_tz_OFFSET0->gmt_sec_to_TIME(<ime, vers_info->interval.start); while ((el= it++)->id < hist_parts) { - if (date_add_interval(<ime, vers_info->interval.type, + if (date_add_interval(thd, <ime, vers_info->interval.type, vers_info->interval.step)) goto err; uint error= 0; @@ -2656,7 +2652,7 @@ char *generate_partition_syntax(THD *thd, partition_info *part_info, default: DBUG_ASSERT(0); /* We really shouldn't get here, no use in continuing from here */ - my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL)); DBUG_RETURN(NULL); } if (part_info->part_type == VERSIONING_PARTITION) @@ -6003,7 +5999,7 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt) lpt->pack_frm_data, lpt->pack_frm_len)))) { - file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR)); + file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATAL)); } if (mysql_trans_commit_alter_copy_data(thd)) @@ -8221,7 +8217,8 @@ static int get_part_iter_for_interval_via_mapping(partition_info *part_info, field->type() == MYSQL_TYPE_DATETIME)) { /* Monotonic, but return NULL for dates with zeros in month/day. */ - zero_in_start_date= field->get_date(&start_date, 0); + DBUG_ASSERT(field->cmp_type() == TIME_RESULT); // No rounding/truncation + zero_in_start_date= field->get_date(&start_date, date_mode_t(0)); DBUG_PRINT("info", ("zero start %u %04d-%02d-%02d", zero_in_start_date, start_date.year, start_date.month, start_date.day)); @@ -8245,7 +8242,8 @@ static int get_part_iter_for_interval_via_mapping(partition_info *part_info, !part_info->part_expr->null_value) { MYSQL_TIME end_date; - bool zero_in_end_date= field->get_date(&end_date, 0); + DBUG_ASSERT(field->cmp_type() == TIME_RESULT); // No rounding/truncation + bool zero_in_end_date= field->get_date(&end_date, date_mode_t(0)); /* This is an optimization for TO_DAYS()/TO_SECONDS() to avoid scanning the NULL partition for ranges that cannot include a date with 0 as diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index 2d3c640b758..71ab7477391 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -51,7 +51,7 @@ bool Sql_cmd_alter_table_exchange_partition::execute(THD *thd) /* Moved from mysql_execute_command */ LEX *lex= thd->lex; /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */ - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); /* first table of first SELECT_LEX */ TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first; /* @@ -743,7 +743,7 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd) int error; ha_partition *partition; ulong timeout= thd->variables.lock_wait_timeout; - TABLE_LIST *first_table= thd->lex->select_lex.table_list.first; + TABLE_LIST *first_table= thd->lex->first_select_lex()->table_list.first; Alter_info *alter_info= &thd->lex->alter_info; uint table_counter, i; List<String> partition_names_list; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index b2ceb1627a1..d448b7b9e02 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -280,6 +280,7 @@ struct st_mysql_sys_var MYSQL_PLUGIN_VAR_HEADER; }; +enum install_status { INSTALL_GOOD, INSTALL_FAIL_WARN_OK, INSTALL_FAIL_NOT_OK }; /* sys_var class for access to all plugin variables visible to the user */ @@ -1077,7 +1078,7 @@ static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin) NOTE Requires that a write-lock is held on LOCK_system_variables_hash */ -static bool plugin_add(MEM_ROOT *tmp_root, +static enum install_status plugin_add(MEM_ROOT *tmp_root, bool if_not_exists, const LEX_CSTRING *name, LEX_CSTRING *dl, myf MyFlags) { struct st_plugin_int tmp, *maybe_dupe; @@ -1088,14 +1089,16 @@ static bool plugin_add(MEM_ROOT *tmp_root, if (name->str && plugin_find_internal(name, MYSQL_ANY_PLUGIN)) { + if (if_not_exists) + MyFlags|= ME_NOTE; my_error(ER_PLUGIN_INSTALLED, MyFlags, name->str); - DBUG_RETURN(TRUE); + DBUG_RETURN(if_not_exists ? INSTALL_FAIL_WARN_OK : INSTALL_FAIL_NOT_OK); } /* Clear the whole struct to catch future extensions. */ bzero((char*) &tmp, sizeof(tmp)); fix_dl_name(tmp_root, dl); if (! (tmp.plugin_dl= plugin_dl_add(dl, MyFlags))) - DBUG_RETURN(TRUE); + DBUG_RETURN(INSTALL_FAIL_NOT_OK); /* Find plugin by name */ for (plugin= tmp.plugin_dl->plugins; plugin->info; plugin++) { @@ -1121,7 +1124,7 @@ static bool plugin_add(MEM_ROOT *tmp_root, if (plugin->name != maybe_dupe->plugin->name) { my_error(ER_UDF_EXISTS, MyFlags, plugin->name); - DBUG_RETURN(TRUE); + DBUG_RETURN(INSTALL_FAIL_NOT_OK); } dupes++; continue; // already installed @@ -1173,7 +1176,7 @@ static bool plugin_add(MEM_ROOT *tmp_root, init_alloc_root(&tmp_plugin_ptr->mem_root, "plugin", 4096, 4096, MYF(0)); if (name->str) - DBUG_RETURN(FALSE); // all done + DBUG_RETURN(INSTALL_GOOD); // all done oks++; tmp.plugin_dl->ref_count++; @@ -1191,7 +1194,9 @@ err: my_error(ER_CANT_FIND_DL_ENTRY, MyFlags, name->str); plugin_dl_del(tmp.plugin_dl); - DBUG_RETURN(errs > 0 || oks + dupes == 0); + if (errs > 0 || oks + dupes == 0) + DBUG_RETURN(INSTALL_FAIL_NOT_OK); + DBUG_RETURN(INSTALL_GOOD); } static void plugin_variables_deinit(struct st_plugin_int *plugin) @@ -1847,7 +1852,7 @@ static void plugin_load(MEM_ROOT *tmp_root) the mutex here to satisfy the assert */ mysql_mutex_lock(&LOCK_plugin); - plugin_add(tmp_root, &name, &dl, MYF(ME_ERROR_LOG)); + plugin_add(tmp_root, false, &name, &dl, MYF(ME_ERROR_LOG)); free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); mysql_mutex_unlock(&LOCK_plugin); } @@ -1870,7 +1875,7 @@ end: static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) { char buffer[FN_REFLEN]; - LEX_STRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name; + LEX_CSTRING name= {buffer, 0}, dl= {NULL, 0}, *str= &name; char *p= buffer; DBUG_ENTER("plugin_load_list"); while (list) @@ -1889,7 +1894,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) #ifndef __WIN__ case ':': /* can't use this as delimiter as it may be drive letter */ #endif - str->str[str->length]= '\0'; + p[-1]= 0; if (str == &name) // load all plugins in named module { if (!name.length) @@ -1902,16 +1907,16 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) mysql_mutex_lock(&LOCK_plugin); free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); name.str= 0; // load everything - if (plugin_add(tmp_root, (LEX_CSTRING*) &name, (LEX_CSTRING*) &dl, - MYF(ME_ERROR_LOG))) + if (plugin_add(tmp_root, false, &name, &dl, + MYF(ME_ERROR_LOG)) != INSTALL_GOOD) goto error; } else { free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); mysql_mutex_lock(&LOCK_plugin); - if (plugin_add(tmp_root, (LEX_CSTRING*) &name, (LEX_CSTRING*) &dl, - MYF(ME_ERROR_LOG))) + if (plugin_add(tmp_root, false, &name, &dl, + MYF(ME_ERROR_LOG)) != INSTALL_GOOD) goto error; } mysql_mutex_unlock(&LOCK_plugin); @@ -1923,7 +1928,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) case '#': if (str == &name) { - name.str[name.length]= '\0'; + p[-1]= 0; str= &dl; str->str= p; continue; @@ -2146,7 +2151,7 @@ bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name, TABLE_LIST tables; TABLE *table; LEX_CSTRING dl= *dl_arg; - bool error; + enum install_status error; int argc=orig_argc; char **argv=orig_argv; unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] = @@ -2194,12 +2199,14 @@ bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name, mysql_audit_acquire_plugins(thd, event_class_mask); mysql_mutex_lock(&LOCK_plugin); - error= plugin_add(thd->mem_root, name, &dl, MYF(0)); - if (unlikely(error)) + error= plugin_add(thd->mem_root, thd->lex->create_info.if_not_exists(), + name, &dl, MYF(0)); + if (unlikely(error != INSTALL_GOOD)) goto err; if (name->str) - error= finalize_install(thd, table, name, &argc, argv); + error= finalize_install(thd, table, name, &argc, argv) + ? INSTALL_FAIL_NOT_OK : INSTALL_GOOD; else { st_plugin_dl *plugin_dl= plugin_dl_find(&dl); @@ -2207,11 +2214,12 @@ bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name, for (plugin= plugin_dl->plugins; plugin->info; plugin++) { LEX_CSTRING str= { plugin->name, strlen(plugin->name) }; - error|= finalize_install(thd, table, &str, &argc, argv); + if (finalize_install(thd, table, &str, &argc, argv)) + error= INSTALL_FAIL_NOT_OK; } } - if (unlikely(error)) + if (unlikely(error != INSTALL_GOOD)) { reap_needed= true; reap_plugins(); @@ -2220,10 +2228,11 @@ err: mysql_mutex_unlock(&LOCK_plugin); if (argv) free_defaults(argv); - DBUG_RETURN(error); - -WSREP_ERROR_LABEL: - DBUG_RETURN(TRUE); + DBUG_RETURN(error == INSTALL_FAIL_NOT_OK); +#ifdef WITH_WSREP +wsrep_error_label: + DBUG_RETURN(true); +#endif } @@ -2235,8 +2244,9 @@ static bool do_uninstall(THD *thd, TABLE *table, const LEX_CSTRING *name) if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)) || plugin->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_DYING)) { - my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str); - return 1; + myf MyFlags= thd->lex->if_exists() ? ME_NOTE : 0; + my_error(ER_SP_DOES_NOT_EXIST, MyFlags, "PLUGIN", name->str); + return !MyFlags; } if (!plugin->plugin_dl) { @@ -2299,7 +2309,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name, if (!opt_noacl && check_table_access(thd, DELETE_ACL, &tables, FALSE, 1, FALSE)) DBUG_RETURN(TRUE); - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); /* need to open before acquiring LOCK_plugin or it will deadlock */ if (! (table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT))) @@ -2358,17 +2368,19 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name, } else { - my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SONAME", dl.str); - error= true; + myf MyFlags= thd->lex->if_exists() ? ME_NOTE : 0; + my_error(ER_SP_DOES_NOT_EXIST, MyFlags, "SONAME", dl.str); + error|= !MyFlags; } } reap_plugins(); mysql_mutex_unlock(&LOCK_plugin); DBUG_RETURN(error); - -WSREP_ERROR_LABEL: - DBUG_RETURN(TRUE); +#ifdef WITH_WSREP +wsrep_error_label: + DBUG_RETURN(true); +#endif } diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic index 8de53aa2161..c730490a499 100644 --- a/sql/sql_plugin_services.ic +++ b/sql/sql_plugin_services.ic @@ -217,6 +217,16 @@ static struct my_print_error_service_st my_print_error_handler= my_printv_error }; +struct json_service_st json_handler= +{ + json_type, + json_get_array_item, + json_get_object_key, + json_get_object_nkey, + json_escape_string, + json_unescape_json +}; + static struct st_service_ref list_of_services[]= { { "base64_service", VERSION_base64, &base64_handler }, @@ -239,6 +249,7 @@ static struct st_service_ref list_of_services[]= { "thd_specifics_service", VERSION_thd_specifics, &thd_specifics_handler }, { "thd_timezone_service", VERSION_thd_timezone, &thd_timezone_handler }, { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, - { "wsrep_service", VERSION_wsrep, &wsrep_handler } + { "wsrep_service", VERSION_wsrep, &wsrep_handler }, + { "json_service", VERSION_json, &json_handler } }; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 2bbbd5054c8..cb822fc2e98 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1354,7 +1354,7 @@ static int mysql_test_update(Prepared_statement *stmt, THD *thd= stmt->thd; uint table_count= 0; TABLE_LIST *update_source_table; - SELECT_LEX *select= &stmt->lex->select_lex; + SELECT_LEX *select= stmt->lex->first_select_lex(); #ifndef NO_EMBEDDED_ACCESS_CHECKS uint want_privilege; #endif @@ -1410,10 +1410,10 @@ static int mysql_test_update(Prepared_statement *stmt, table_list->table->grant.want_privilege= want_privilege; table_list->register_want_access(want_privilege); #endif - thd->lex->select_lex.no_wrap_view_item= TRUE; + thd->lex->first_select_lex()->no_wrap_view_item= TRUE; res= setup_fields(thd, Ref_ptr_array(), select->item_list, MARK_COLUMNS_READ, 0, NULL, 0); - thd->lex->select_lex.no_wrap_view_item= FALSE; + thd->lex->first_select_lex()->no_wrap_view_item= FALSE; if (res) goto error; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -1478,10 +1478,10 @@ static bool mysql_test_delete(Prepared_statement *stmt, goto error; } - DBUG_RETURN(mysql_prepare_delete(thd, table_list, - lex->select_lex.with_wild, - lex->select_lex.item_list, - &lex->select_lex.where, + DBUG_RETURN(mysql_prepare_delete(thd, table_list, + lex->first_select_lex()->with_wild, + lex->first_select_lex()->item_list, + &lex->first_select_lex()->where, &delete_while_scanning)); error: DBUG_RETURN(TRUE); @@ -1513,7 +1513,7 @@ static int mysql_test_select(Prepared_statement *stmt, SELECT_LEX_UNIT *unit= &lex->unit; DBUG_ENTER("mysql_test_select"); - lex->select_lex.context.resolve_in_select_list= TRUE; + lex->first_select_lex()->context.resolve_in_select_list= TRUE; ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL; if (tables) @@ -1526,7 +1526,7 @@ static int mysql_test_select(Prepared_statement *stmt, if (!lex->result && !(lex->result= new (stmt->mem_root) select_send(thd))) { - my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), + my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), static_cast<int>(sizeof(select_send))); goto error; } @@ -1547,7 +1547,7 @@ static int mysql_test_select(Prepared_statement *stmt, if (!lex->describe && !thd->lex->analyze_stmt && !stmt->is_sql_prepare()) { /* Make copy of item list, as change_columns may change it */ - List<Item> fields(lex->select_lex.item_list); + List<Item> fields(lex->first_select_lex()->item_list); /* Change columns if a procedure like analyse() */ if (unit->last_procedure && unit->last_procedure->change_columns(thd, fields)) @@ -1705,7 +1705,7 @@ static bool select_like_stmt_test(Prepared_statement *stmt, THD *thd= stmt->thd; LEX *lex= stmt->lex; - lex->select_lex.context.resolve_in_select_list= TRUE; + lex->first_select_lex()->context.resolve_in_select_list= TRUE; if (specific_prepare && (*specific_prepare)(thd)) DBUG_RETURN(TRUE); @@ -1773,7 +1773,7 @@ static bool mysql_test_create_table(Prepared_statement *stmt) DBUG_ENTER("mysql_test_create_table"); THD *thd= stmt->thd; LEX *lex= stmt->lex; - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); bool res= FALSE; bool link_to_local; TABLE_LIST *create_table= lex->query_tables; @@ -2093,11 +2093,11 @@ static bool mysql_test_multidelete(Prepared_statement *stmt, { THD *thd= stmt->thd; - thd->lex->current_select= &thd->lex->select_lex; + thd->lex->current_select= thd->lex->first_select_lex(); if (add_item_to_list(thd, new (thd->mem_root) Item_null(thd))) { - my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), 0); + my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 0); goto error; } @@ -2132,13 +2132,14 @@ error: static int mysql_insert_select_prepare_tester(THD *thd) { - SELECT_LEX *first_select= &thd->lex->select_lex; + SELECT_LEX *first_select= thd->lex->first_select_lex(); TABLE_LIST *second_table= first_select->table_list.first->next_local; /* Skip first table, which is the table we are inserting in */ first_select->table_list.first= second_table; - thd->lex->select_lex.context.table_list= - thd->lex->select_lex.context.first_name_resolution_table= second_table; + thd->lex->first_select_lex()->context.table_list= + thd->lex->first_select_lex()->context.first_name_resolution_table= + second_table; return mysql_insert_select_prepare(thd); } @@ -2173,7 +2174,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt, return 1; /* store it, because mysql_insert_select_prepare_tester change it */ - first_local_table= lex->select_lex.table_list.first; + first_local_table= lex->first_select_lex()->table_list.first; DBUG_ASSERT(first_local_table != 0); res= @@ -2181,7 +2182,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt, &mysql_insert_select_prepare_tester, OPTION_SETUP_TABLES_DONE); /* revert changes made by mysql_insert_select_prepare_tester */ - lex->select_lex.table_list.first= first_local_table; + lex->first_select_lex()->table_list.first= first_local_table; return res; } @@ -2207,7 +2208,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt, SQL_HANDLER *ha_table; DBUG_ENTER("mysql_test_handler_read"); - lex->select_lex.context.resolve_in_select_list= TRUE; + lex->first_select_lex()->context.resolve_in_select_list= TRUE; /* We don't have to test for permissions as this is already done during @@ -2217,7 +2218,7 @@ static int mysql_test_handler_read(Prepared_statement *stmt, lex->ident.str, lex->insert_list, lex->ha_rkey_mode, - lex->select_lex.where))) + lex->first_select_lex()->where))) DBUG_RETURN(1); if (!stmt->is_sql_prepare()) @@ -2256,7 +2257,7 @@ static bool check_prepared_statement(Prepared_statement *stmt) { THD *thd= stmt->thd; LEX *lex= stmt->lex; - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); TABLE_LIST *tables; enum enum_sql_command sql_command= lex->sql_command; int res= 0; @@ -2265,10 +2266,11 @@ static bool check_prepared_statement(Prepared_statement *stmt) sql_command, stmt->param_count)); lex->first_lists_tables_same(); + lex->fix_first_select_number(); tables= lex->query_tables; /* set context for commands which do not use setup_tables */ - lex->select_lex.context.resolve_in_table_list_only(select_lex-> + lex->first_select_lex()->context.resolve_in_table_list_only(select_lex-> get_table_list()); /* Reset warning count for each query that uses tables */ @@ -3045,7 +3047,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) { tables->reinit_before_use(thd); } - lex->current_select= &lex->select_lex; + lex->current_select= lex->first_select_lex(); if (lex->result) @@ -4583,8 +4585,8 @@ bool Prepared_statement::validate_metadata(Prepared_statement *copy) if (is_sql_prepare() || lex->describe) return FALSE; - if (lex->select_lex.item_list.elements != - copy->lex->select_lex.item_list.elements) + if (lex->first_select_lex()->item_list.elements != + copy->lex->first_select_lex()->item_list.elements) { /** Column counts mismatch, update the client */ thd->server_status|= SERVER_STATUS_METADATA_CHANGED; @@ -4741,7 +4743,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) alloc_query(thd, (char*) expanded_query->ptr(), expanded_query->length())) { - my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), expanded_query->length()); + my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), expanded_query->length()); goto error; } /* @@ -5321,16 +5323,8 @@ bool Protocol_local::store_longlong(longlong value, bool unsigned_flag) bool Protocol_local::store_decimal(const my_decimal *value) { - char buf[DECIMAL_MAX_STR_LENGTH]; - String str(buf, sizeof (buf), &my_charset_bin); - int rc; - - rc= my_decimal2string(E_DEC_FATAL_ERROR, value, 0, 0, 0, &str); - - if (rc) - return TRUE; - - return store_column(str.ptr(), str.length()); + StringBuffer<DECIMAL_MAX_STR_LENGTH> str; + return value->to_string(&str) ? store_column(str.ptr(), str.length()) : true; } diff --git a/sql/sql_priv.h b/sql/sql_priv.h index e48b6195bb7..fa12b645041 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -183,7 +183,11 @@ #define OPTION_ALLOW_BATCH (1ULL << 36) // THD, intern (slave) #define OPTION_SKIP_REPLICATION (1ULL << 37) // THD, user #define OPTION_RPL_SKIP_PARALLEL (1ULL << 38) -#define OPTION_FOUND_COMMENT (1ULL << 39) // SELECT, intern, parser +#define OPTION_NO_QUERY_CACHE (1ULL << 39) // SELECT, user +#define OPTION_PROCEDURE_CLAUSE (1ULL << 40) // Internal usage + + +#define OPTION_LEX_FOUND_COMMENT (1ULL << 0) // intern, parser /* The rest of the file is included in the server only */ #ifndef MYSQL_CLIENT @@ -228,6 +232,7 @@ #define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29) #define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30) #define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31) +#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32) #define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \ OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \ @@ -254,7 +259,8 @@ OPTIMIZER_SWITCH_EXISTS_TO_IN | \ OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \ OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \ - OPTIMIZER_SWITCH_SPLIT_MATERIALIZED) + OPTIMIZER_SWITCH_SPLIT_MATERIALIZED | \ + OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY) /* Replication uses 8 bytes to store SQL_MODE in the binary log. The day you @@ -356,6 +362,9 @@ enum enum_parsing_place IN_ORDER_BY, IN_UPDATE_ON_DUP_KEY, IN_PART_FUNC, + BEFORE_OPT_LIST, + AFTER_LIST, + FOR_LOOP_BOUND, PARSING_PLACE_SIZE /* always should be the last */ }; diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 13f03fed5f3..6ca21aebb37 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -110,7 +110,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table) }; ST_FIELD_INFO *field_info; - Name_resolution_context *context= &thd->lex->select_lex.context; + Name_resolution_context *context= &thd->lex->first_select_lex()->context; int i; for (i= 0; schema_table->fields_info[i].field_name != NULL; i++) @@ -402,7 +402,7 @@ bool PROFILING::show_profiles() QUERY_PROFILE *prof; List<Item> field_list; MEM_ROOT *mem_root= thd->mem_root; - SELECT_LEX *sel= &thd->lex->select_lex; + SELECT_LEX *sel= thd->lex->first_select_lex(); SELECT_LEX_UNIT *unit= &thd->lex->unit; ha_rows idx= 0; Protocol *protocol= thd->protocol; diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index abdf9d76d15..7a5cabc8880 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -221,7 +221,9 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, !thd->mdl_context.has_locks() || thd->handler_tables_hash.records || thd->ull_hash.records || - thd->global_read_lock.is_acquired()); + thd->global_read_lock.is_acquired() || + thd->current_backup_stage != BACKUP_FINISHED + ); /* Note that if REFRESH_READ_LOCK bit is set then REFRESH_TABLES is set too @@ -231,6 +233,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, { if ((options & REFRESH_READ_LOCK) && thd) { + DBUG_ASSERT(!(options & REFRESH_FAST) && !tables); /* On the first hand we need write lock on the tables to be flushed, on the other hand we must not try to aspire a global read lock @@ -242,6 +245,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); return 1; } + /* Writing to the binlog could cause deadlocks, as we don't log UNLOCK TABLES @@ -249,9 +253,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, tmp_write_to_binlog= 0; if (thd->global_read_lock.lock_global_read_lock(thd)) return 1; // Killed - if (close_cached_tables(thd, tables, - ((options & REFRESH_FAST) ? FALSE : TRUE), - thd->variables.lock_wait_timeout)) + if (flush_tables(thd, FLUSH_ALL)) { /* NOTE: my_error() has been already called by reopen_tables() within @@ -274,11 +276,9 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, make_global_read_lock_block_commit(thd) above since they could have modified the tables too. */ - if (WSREP(thd) && - close_cached_tables(thd, tables, (options & REFRESH_FAST) ? - FALSE : TRUE, TRUE)) - result= 1; - } + if (WSREP(thd) && flush_tables(thd, FLUSH_ALL)) + result= 1; + } else { if (thd && thd->locked_tables_mode) @@ -311,8 +311,8 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, with global read lock. */ if (thd->open_tables && - !thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "", - MDL_INTENTION_EXCLUSIVE)) + !thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "", + MDL_BACKUP_DDL)) { my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), thd->open_tables->s->table_name.str); @@ -332,25 +332,21 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, } #ifdef WITH_WSREP - if (thd && thd->wsrep_applier) - { - /* - In case of applier thread, do not wait for table share(s) to be - removed from table definition cache. - */ - options|= REFRESH_FAST; - } -#endif - if (close_cached_tables(thd, tables, - ((options & REFRESH_FAST) ? FALSE : TRUE), - (thd ? thd->variables.lock_wait_timeout : - LONG_TIMEOUT))) + /* In case of applier thread, do not call flush tables */ + if (!thd || !thd->wsrep_applier) +#endif /* WITH_WSREP */ { - /* - NOTE: my_error() has been already called by reopen_tables() within - close_cached_tables(). - */ - result= 1; + if (close_cached_tables(thd, tables, + ((options & REFRESH_FAST) ? FALSE : TRUE), + (thd ? thd->variables.lock_wait_timeout : + LONG_TIMEOUT))) + { + /* + NOTE: my_error() has been already called by reopen_tables() within + close_cached_tables(). + */ + result= 1; + } } } my_dbopt_cleanup(); @@ -420,6 +416,11 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, #endif if (options & REFRESH_USER_RESOURCES) reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */ + if (options & REFRESH_SSL) + { + if (reinit_ssl()) + result= 1; + } if (options & REFRESH_GENERIC) { List_iterator_fast<LEX_CSTRING> li(thd->lex->view_list); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 4c0035b9c48..2ee175293de 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -3841,8 +3841,7 @@ int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len, if (!mysql_bin_log.is_open()) { my_message(ER_FLUSH_MASTER_BINLOG_CLOSED, - ER_THD(thd, ER_FLUSH_MASTER_BINLOG_CLOSED), - MYF(ME_BELL+ME_WAITTANG)); + ER_THD(thd, ER_FLUSH_MASTER_BINLOG_CLOSED), MYF(0)); return 1; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ddc5a25bd07..04baf5737c6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -354,7 +354,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, ulong setup_tables_done_option) { bool res; - SELECT_LEX *select_lex = &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); DBUG_ENTER("handle_select"); MYSQL_SELECT_START(thd->query()); @@ -1051,7 +1051,7 @@ JOIN::prepare(TABLE_LIST *tables_init, while ((select_el= select_it++)) { - if (select_el->with_sum_func) + if (select_el->with_sum_func()) found_sum_func_elem= true; if (select_el->with_field) found_field_elem= true; @@ -1219,14 +1219,14 @@ JOIN::prepare(TABLE_LIST *tables_init, item->max_length))) real_order= TRUE; - if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) + if (item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM) item->split_sum_func(thd, ref_ptrs, all_fields, 0); } if (!real_order) order= NULL; } - if (having && having->with_sum_func) + if (having && having->with_sum_func()) having->split_sum_func2(thd, ref_ptrs, all_fields, &having, SPLIT_SUM_SKIP_REGISTERED); if (select_lex->inner_sum_func_list) @@ -1396,6 +1396,7 @@ err: bool JOIN::build_explain() { + DBUG_ENTER("JOIN::build_explain"); create_explain_query_if_not_exists(thd->lex, thd->mem_root); have_query_plan= QEP_AVAILABLE; @@ -1413,8 +1414,7 @@ bool JOIN::build_explain() thd->mem_root= old_mem_root; DBUG_ASSERT(thd->free_list == old_free_list); // no Items were created if (res) - return 1; - + DBUG_RETURN(1); uint select_nr= select_lex->select_number; JOIN_TAB *curr_tab= join_tab + exec_join_tab_cnt(); for (uint i= 0; i < aggr_tables; i++, curr_tab++) @@ -1432,7 +1432,7 @@ bool JOIN::build_explain() get_using_temporary_read_tracker(); } } - return 0; + DBUG_RETURN(0); } @@ -1597,7 +1597,7 @@ JOIN::optimize_inner() { /* Item_cond_and can't be fixed after creation, so we do not check - conds->fixed + conds->is_fixed() */ conds->fix_fields(thd, &conds); conds->change_ref_to_fields(thd, tables_list); @@ -1641,7 +1641,7 @@ JOIN::optimize_inner() if (arena) thd->restore_active_arena(arena, &backup); } - + if (optimize_constant_subqueries()) DBUG_RETURN(1); @@ -1652,9 +1652,28 @@ JOIN::optimize_inner() (void) having->walk(&Item::cleanup_is_expensive_cache_processor, 0, (void *) 0); - if (setup_jtbm_semi_joins(this, join_list, &conds)) + List<Item> eq_list; + + if (setup_degenerate_jtbm_semi_joins(this, join_list, eq_list)) DBUG_RETURN(1); + if (eq_list.elements != 0) + { + Item *new_cond; + + if (eq_list.elements == 1) + new_cond= eq_list.pop(); + else + new_cond= new (thd->mem_root) Item_cond_and(thd, eq_list); + + if (new_cond && + ((new_cond->fix_fields(thd, &new_cond) || + !(conds= and_items(thd, conds, new_cond)) || + conds->fix_fields(thd, &conds)))) + DBUG_RETURN(TRUE); + } + eq_list.empty(); + if (select_lex->cond_pushed_into_where) { conds= and_conds(thd, conds, select_lex->cond_pushed_into_where); @@ -1685,6 +1704,31 @@ JOIN::optimize_inner() DBUG_RETURN(1); } + if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY)) + { + TABLE_LIST *tbl; + List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables); + while ((tbl= li++)) + if (tbl->jtbm_subselect) + { + if (tbl->jtbm_subselect->pushdown_cond_for_in_subquery(thd, conds)) + DBUG_RETURN(1); + } + } + + if (setup_jtbm_semi_joins(this, join_list, eq_list)) + DBUG_RETURN(1); + + if (eq_list.elements != 0) + { + conds= and_new_conditions_to_optimized_cond(thd, conds, &cond_equal, + eq_list, &cond_value); + + if (!conds && + cond_value != Item::COND_FALSE && cond_value != Item::COND_TRUE) + DBUG_RETURN(TRUE); + } + if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED)) { TABLE_LIST *tbl; @@ -1991,7 +2035,7 @@ int JOIN::optimize_stage2() if (!conds && outer_join) { /* Handle the case where we have an OUTER JOIN without a WHERE */ - conds= new (thd->mem_root) Item_int(thd, (longlong) 1,1); // Always true + conds= new (thd->mem_root) Item_bool(thd, true); // Always true } if (impossible_where) @@ -2130,7 +2174,7 @@ int JOIN::optimize_stage2() if (conds && const_table_map != found_const_table_map && (select_options & SELECT_DESCRIBE)) { - conds=new (thd->mem_root) Item_int(thd, (longlong) 0, 1); // Always false + conds=new (thd->mem_root) Item_bool(thd, false); // Always false } /* Cache constant expressions in WHERE, HAVING, ON clauses. */ @@ -2413,13 +2457,13 @@ int JOIN::optimize_stage2() elements may be lost during further having condition transformation in JOIN::exec. */ - if (having && const_table_map && !having->with_sum_func) + if (having && const_table_map && !having->with_sum_func()) { having->update_used_tables(); having= having->remove_eq_conds(thd, &select_lex->having_value, true); if (select_lex->having_value == Item::COND_FALSE) { - having= new (thd->mem_root) Item_int(thd, (longlong) 0,1); + having= new (thd->mem_root) Item_bool(thd, false); zero_result_cause= "Impossible HAVING noticed after reading const tables"; error= 0; select_lex->mark_const_derived(zero_result_cause); @@ -2457,7 +2501,7 @@ int JOIN::optimize_stage2() { JOIN_TAB *tab= &join_tab[const_tables]; - if (order) + if (order && !need_tmp) { /* Force using of tmp table if sorting by a SP or UDF function due to @@ -3162,7 +3206,7 @@ bool JOIN::make_aggr_tables_info() or end_write_group()) if JOIN::group is set to false. */ // the temporary table was explicitly requested - DBUG_ASSERT(MY_TEST(select_options & OPTION_BUFFER_RESULT)); + DBUG_ASSERT(select_options & OPTION_BUFFER_RESULT); // the temporary table does not have a grouping expression DBUG_ASSERT(!curr_tab->table->group); } @@ -3765,6 +3809,15 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite, bool need_tmp_table, bool need_order, bool distinct) { + DBUG_ENTER("JOIN::save_explain_data"); + DBUG_PRINT("enter", ("Save explain Select_lex: %u (%p) parent lex: %p stmt_lex: %p present select: %u (%p)", + select_lex->select_number, select_lex, + select_lex->parent_lex, thd->lex->stmt_lex, + (output->get_select(select_lex->select_number) ? + select_lex->select_number : 0), + (output->get_select(select_lex->select_number) ? + output->get_select(select_lex->select_number) + ->select_lex : NULL))); /* If there is SELECT in this statement with the same number it must be the same SELECT @@ -3791,8 +3844,9 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite, /* It's a degenerate join */ message= zero_result_cause ? zero_result_cause : "No tables used"; } - return save_explain_data_intern(thd->lex->explain, need_tmp_table, need_order, - distinct, message); + bool rc= save_explain_data_intern(thd->lex->explain, need_tmp_table, + need_order, distinct, message); + DBUG_RETURN(rc); } /* @@ -3814,11 +3868,11 @@ bool JOIN::save_explain_data(Explain_query *output, bool can_overwrite, { if (!(join_tab[i].filesort->tracker= new Filesort_tracker(thd->lex->analyze_stmt))) - return 1; + DBUG_RETURN(1); } } } - return 0; + DBUG_RETURN(0); } @@ -4175,10 +4229,10 @@ mysql_select(THD *thd, is it single SELECT in derived table, called in derived table creation */ - if (select_lex->linkage != DERIVED_TABLE_TYPE || + if (select_lex->get_linkage() != DERIVED_TABLE_TYPE || (select_options & SELECT_DESCRIBE)) { - if (select_lex->linkage != GLOBAL_OPTIONS_TYPE) + if (select_lex->get_linkage() != GLOBAL_OPTIONS_TYPE) { /* Original join tabs might be overwritten at first @@ -4870,7 +4924,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, if (join->cond_value == Item::COND_FALSE) { join->impossible_where= true; - conds= new (join->thd->mem_root) Item_int(join->thd, (longlong) 0, 1); + conds= new (join->thd->mem_root) Item_bool(join->thd, false); } join->cond_equal= NULL; @@ -10632,7 +10686,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) below to check if we should use 'quick' instead. */ DBUG_PRINT("info", ("Item_int")); - tmp= new (thd->mem_root) Item_int(thd, (longlong) 1, 1); // Always true + tmp= new (thd->mem_root) Item_bool(thd, true); // Always true } } @@ -10760,7 +10814,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) Yet attributes of the just built condition are not needed. Thus we call sel->cond->quick_fix_field for safety. */ - if (sel->cond && !sel->cond->fixed) + if (sel->cond && !sel->cond->is_fixed()) sel->cond->quick_fix_field(); if (sel->test_quick_select(thd, tab->keys, @@ -12769,7 +12823,8 @@ void JOIN::join_free() !(select_options & SELECT_NO_UNLOCK) && !select_lex->subquery_in_having && (select_lex == (thd->lex->unit.fake_select_lex ? - thd->lex->unit.fake_select_lex : &thd->lex->select_lex))) + thd->lex->unit.fake_select_lex : + thd->lex->first_select_lex()))) { /* TODO: unlock tables even if the join isn't top level select in the @@ -13061,7 +13116,7 @@ static void update_depend_map_for_order(JOIN *join, ORDER *order) order->used= 0; // Not item_sum(), RAND() and no reference to table outside of sub select if (!(order->depend_map & (OUTER_REF_TABLE_BIT | RAND_TABLE_BIT)) - && !order->item[0]->with_sum_func && + && !order->item[0]->with_sum_func() && join->join_tab) { for (JOIN_TAB **tab=join->map2table; @@ -13136,7 +13191,23 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, tab++) tab->cached_eq_ref_table= FALSE; - *simple_order= *join->join_tab[join->const_tables].on_expr_ref ? 0 : 1; + JOIN_TAB *head= join->join_tab + join->const_tables; + *simple_order= head->on_expr_ref[0] == NULL; + if (*simple_order && head->table->file->ha_table_flags() & HA_SLOW_RND_POS) + { + uint u1, u2, u3; + /* + normally the condition is (see filesort_use_addons()) + + length + sortlength <= max_length_for_sort_data + + but for HA_SLOW_RND_POS tables we relax it a bit, as the alternative + is to use a temporary table, which is rather expensive. + + TODO proper cost estimations + */ + *simple_order= filesort_use_addons(head->table, 0, &u1, &u2, &u3); + } } else { @@ -13152,7 +13223,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, for (order=first_order; order ; order=order->next) { table_map order_tables=order->item[0]->used_tables(); - if (order->item[0]->with_sum_func || + if (order->item[0]->with_sum_func() || /* If the outer table of an outer join is const (either by itself or after applying WHERE condition), grouping on a field from such a @@ -13328,7 +13399,7 @@ ORDER *simple_remove_const(ORDER *order, COND *where) ORDER *first= NULL, *prev= NULL; for (; order; order= order->next) { - DBUG_ASSERT(!order->item[0]->with_sum_func); // should never happen + DBUG_ASSERT(!order->item[0]->with_sum_func()); // should never happen if (!const_expression_in_where(where, order->item[0])) { if (!first) @@ -13577,9 +13648,9 @@ finish: FALSE otherwise */ -static bool check_simple_equality(THD *thd, const Item::Context &ctx, - Item *left_item, Item *right_item, - COND_EQUAL *cond_equal) +bool check_simple_equality(THD *thd, const Item::Context &ctx, + Item *left_item, Item *right_item, + COND_EQUAL *cond_equal) { Item *orig_left_item= left_item; Item *orig_right_item= right_item; @@ -14032,7 +14103,7 @@ COND *Item_cond_and::build_equal_items(THD *thd, if (!cond_args->elements && !cond_equal.current_level.elements && !eq_list.elements) - return new (thd->mem_root) Item_int(thd, (longlong) 1, 1); + return new (thd->mem_root) Item_bool(thd, true); List_iterator_fast<Item_equal> it(cond_equal.current_level); while ((item_equal= it++)) @@ -14139,7 +14210,7 @@ COND *Item_func_eq::build_equal_items(THD *thd, Item_equal *item_equal; int n= cond_equal.current_level.elements + eq_list.elements; if (n == 0) - return new (thd->mem_root) Item_int(thd, (longlong) 1, 1); + return new (thd->mem_root) Item_bool(thd, true); else if (n == 1) { if ((item_equal= cond_equal.current_level.pop())) @@ -14530,7 +14601,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, List<Item> eq_list; Item_func_eq *eq_item= 0; if (((Item *) item_equal)->const_item() && !item_equal->val_int()) - return new (thd->mem_root) Item_int(thd, (longlong) 0, 1); + return new (thd->mem_root) Item_bool(thd, false); Item *item_const= item_equal->get_const(); Item_equal_fields_iterator it(*item_equal); Item *head; @@ -14538,7 +14609,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, Item *current_sjm_head= NULL; DBUG_ASSERT(!cond || - cond->type() == Item::INT_ITEM || + cond->is_bool_literal() || (cond->type() == Item::FUNC_ITEM && ((Item_func *) cond)->functype() == Item_func::EQ_FUNC) || (cond->type() == Item::COND_ITEM && @@ -14659,13 +14730,13 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, cond AND eq_1 AND eq_2 AND eq_3 AND ... - 'cond' is a parameter for this function, which may be NULL, an Item_int(1), + 'cond' is a parameter for this function, which may be NULL, an Item_bool(1), or an Item_func_eq or an Item_cond_and. We want to return a well-formed condition: no nested Item_cond_and objects, or Item_cond_and with a single child: - if 'cond' is an Item_cond_and, we add eq_i as its tail - - if 'cond' is Item_int(1), we return eq_i + - if 'cond' is Item_bool(1), we return eq_i - otherwise, we create our own Item_cond_and and put 'cond' at the front of it. - if we have only one condition to return, we don't create an Item_cond_and @@ -14677,10 +14748,10 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, switch (eq_list.elements) { case 0: - res= cond ? cond : new (thd->mem_root) Item_int(thd, (longlong) 1, 1); + res= cond ? cond : new (thd->mem_root) Item_bool(thd, true); break; case 1: - if (!cond || cond->type() == Item::INT_ITEM) + if (!cond || cond->is_bool_literal()) res= eq_item; break; default: @@ -14822,7 +14893,7 @@ static COND* substitute_for_best_equal_field(THD *thd, JOIN_TAB *context_tab, eq_cond= 0; break; } - else if (eq_cond->type() == Item::INT_ITEM && !eq_cond->val_bool()) + else if (eq_cond->is_bool_literal() && !eq_cond->val_bool()) { /* This occurs when eliminate_item_equal() founds that cond is @@ -14847,7 +14918,7 @@ static COND* substitute_for_best_equal_field(THD *thd, JOIN_TAB *context_tab, else { /* Do not add an equality condition if it's always true */ - if (eq_cond->type() != Item::INT_ITEM && + if (!eq_cond->is_bool_literal() && cond_list->push_front(eq_cond, thd->mem_root)) eq_cond= 0; } @@ -15361,7 +15432,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top, conds= and_conds(join->thd, conds, table->on_expr); conds->top_level_item(); /* conds is always a new item as both cond and on_expr existed */ - DBUG_ASSERT(!conds->fixed); + DBUG_ASSERT(!conds->is_fixed()); conds->fix_fields(join->thd, &conds); } else @@ -16429,9 +16500,8 @@ Item_func_isnull::remove_eq_conds(THD *thd, Item::cond_result *cond_value, { Field *field= ((Item_field*) real_item)->field; - if (((field->type() == MYSQL_TYPE_DATE) || - (field->type() == MYSQL_TYPE_DATETIME)) && - (field->flags & NOT_NULL_FLAG)) + if ((field->flags & NOT_NULL_FLAG) && + field->type_handler()->cond_notnull_field_isnull_to_field_eq_zero()) { /* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */ /* @@ -16447,7 +16517,7 @@ Item_func_isnull::remove_eq_conds(THD *thd, Item::cond_result *cond_value, */ - Item *item0= new(thd->mem_root) Item_int(thd, (longlong) 0, 1); + Item *item0= new(thd->mem_root) Item_bool(thd, false); Item *eq_cond= new(thd->mem_root) Item_func_eq(thd, args[0], item0); if (!eq_cond) return this; @@ -16517,7 +16587,7 @@ Item_func_isnull::remove_eq_conds(THD *thd, Item::cond_result *cond_value, cond= new_cond; /* Item_func_eq can't be fixed after creation so we do not check - cond->fixed, also it do not need tables so we use 0 as second + cond->is_fixed(), also it do not need tables so we use 0 as second argument. */ cond->fix_fields(thd, &cond); @@ -16677,60 +16747,6 @@ const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field, Create internal temporary table ****************************************************************************/ -/** - Create field for temporary table from given field. - - @param thd Thread handler - @param org_field field from which new field will be created - @param name New field name - @param table Temporary table - @param item !=NULL if item->result_field should point to new field. - This is relevant for how fill_record() is going to work: - If item != NULL then fill_record() will update - the record in the original table. - If item == NULL then fill_record() will update - the temporary table - - @retval - NULL on error - @retval - new_created field -*/ - -Field *create_tmp_field_from_field(THD *thd, Field *org_field, - LEX_CSTRING *name, TABLE *table, - Item_field *item) -{ - Field *new_field; - - new_field= org_field->make_new_field(thd->mem_root, table, - table == org_field->table); - if (new_field) - { - new_field->init(table); - new_field->orig_table= org_field->orig_table; - if (item) - item->result_field= new_field; - else - new_field->field_name= *name; - new_field->flags|= org_field->flags & NO_DEFAULT_VALUE_FLAG; - if (org_field->maybe_null() || (item && item->maybe_null)) - new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join - if (org_field->type() == MYSQL_TYPE_VAR_STRING || - org_field->type() == MYSQL_TYPE_VARCHAR) - table->s->db_create_options|= HA_OPTION_PACK_RECORD; - else if (org_field->type() == FIELD_TYPE_DOUBLE) - ((Field_double *) new_field)->not_fixed= TRUE; - new_field->vcol_info= 0; - new_field->cond_selectivity= 1.0; - new_field->next_equal_field= NULL; - new_field->option_list= NULL; - new_field->option_struct= NULL; - } - return new_field; -} - - Field *Item::create_tmp_field_int(TABLE *table, uint convert_int_length) { const Type_handler *h= &type_handler_long; @@ -16740,6 +16756,22 @@ Field *Item::create_tmp_field_int(TABLE *table, uint convert_int_length) *this, table); } +Field *Item::tmp_table_field_from_field_type_maybe_null(TABLE *table, + Tmp_field_src *src, + const Tmp_field_param *param, + bool is_explicit_null) +{ + DBUG_ASSERT(!param->make_copy_field()); + DBUG_ASSERT(!is_result_field()); + Field *result; + if ((result= tmp_table_field_from_field_type(table))) + { + if (result && is_explicit_null) + result->is_created_from_null_item= true; + } + return result; +} + Field *Item_sum::create_tmp_field(bool group, TABLE *table) { @@ -16771,57 +16803,6 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table) } -static void create_tmp_field_from_item_finalize(THD *thd, - Field *new_field, - Item *item, - Item ***copy_func, - bool modify_item) -{ - if (copy_func && - (item->is_result_field() || - (item->real_item()->is_result_field()))) - *((*copy_func)++) = item; // Save for copy_funcs - if (modify_item) - item->set_result_field(new_field); - if (item->type() == Item::NULL_ITEM) - new_field->is_created_from_null_item= TRUE; -} - - -/** - Create field for temporary table using type of given item. - - @param thd Thread handler - @param item Item to create a field for - @param table Temporary table - @param copy_func If set and item is a function, store copy of - item in this array - @param modify_item 1 if item->result_field should point to new - item. This is relevent for how fill_record() - is going to work: - If modify_item is 1 then fill_record() will - update the record in the original table. - If modify_item is 0 then fill_record() will - update the temporary table - - @retval - 0 on error - @retval - new_created field -*/ - -static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, - Item ***copy_func, bool modify_item) -{ - Field *UNINIT_VAR(new_field); - DBUG_ASSERT(thd == table->in_use); - if ((new_field= item->create_tmp_field(false, table))) - create_tmp_field_from_item_finalize(thd, new_field, item, - copy_func, modify_item); - return new_field; -} - - /** Create field for information schema table. @@ -16859,19 +16840,182 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table) /** + Create a temporary field for Item_field (or its descendant), + either direct or referenced by an Item_ref. +*/ +Field * +Item_field::create_tmp_field_from_item_field(TABLE *new_table, + Item_ref *orig_item, + const Tmp_field_param *param) +{ + DBUG_ASSERT(!is_result_field()); + Field *result; + /* + If item have to be able to store NULLs but underlaid field can't do it, + create_tmp_field_from_field() can't be used for tmp field creation. + */ + if (((maybe_null && in_rollup) || + (new_table->in_use->create_tmp_table_for_derived && /* for mat. view/dt */ + orig_item && orig_item->maybe_null)) && + !field->maybe_null()) + { + /* + The item the ref points to may have maybe_null flag set while + the ref doesn't have it. This may happen for outer fields + when the outer query decided at some point after name resolution phase + that this field might be null. Take this into account here. + */ + Record_addr rec(orig_item ? orig_item->maybe_null : maybe_null); + const Type_handler *handler= type_handler()-> + type_handler_for_tmp_table(this); + result= handler->make_and_init_table_field(orig_item ? &orig_item->name : &name, + rec, *this, new_table); + } + else if (param->table_cant_handle_bit_fields() && + field->type() == MYSQL_TYPE_BIT) + { + const Type_handler *handler= type_handler_long_or_longlong(); + result= handler->make_and_init_table_field(&name, + Record_addr(maybe_null), + *this, new_table); + } + else + { + LEX_CSTRING *tmp= orig_item ? &orig_item->name : &name; + bool tmp_maybe_null= param->modify_item() ? maybe_null : + field->maybe_null(); + result= field->create_tmp_field(new_table->in_use->mem_root, new_table, + tmp_maybe_null); + if (result) + result->field_name= *tmp; + } + if (result && param->modify_item()) + result_field= result; + return result; +} + + +Field *Item_field::create_tmp_field_ex(TABLE *table, + Tmp_field_src *src, + const Tmp_field_param *param) +{ + DBUG_ASSERT(!is_result_field()); + Field *result; + src->set_field(field); + if (!(result= create_tmp_field_from_item_field(table, NULL, param))) + return NULL; + /* + Fields that are used as arguments to the DEFAULT() function already have + their data pointers set to the default value during name resolution. See + Item_default_value::fix_fields. + */ + if (type() != Item::DEFAULT_VALUE_ITEM && field->eq_def(result)) + src->set_default_field(field); + return result; +} + + +Field *Item_ref::create_tmp_field_ex(TABLE *table, + Tmp_field_src *src, + const Tmp_field_param *param) +{ + Item *item= real_item(); + DBUG_ASSERT(is_result_field()); + if (item->type() == Item::FIELD_ITEM) + { + Field *result; + Item_field *field= (Item_field*) item; + Tmp_field_param prm2(*param); + prm2.set_modify_item(false); + src->set_field(field->field); + if (!(result= field->create_tmp_field_from_item_field(table, this, &prm2))) + return NULL; + if (param->modify_item()) + result_field= result; + return result; + } + return Item_result_field::create_tmp_field_ex(table, src, param); +} + + +void Item_result_field::get_tmp_field_src(Tmp_field_src *src, + const Tmp_field_param *param) +{ + if (param->make_copy_field()) + { + DBUG_ASSERT(result_field); + src->set_field(result_field); + } + else + { + src->set_item_result_field(this); // Save for copy_funcs + } +} + + +Field *Item_result_field::create_tmp_field_ex(TABLE *table, + Tmp_field_src *src, + const Tmp_field_param *param) +{ + /* + Possible Item types: + - Item_cache_wrapper (only for CREATE..SELECT ?) + - Item_func + - Item_subselect + */ + DBUG_ASSERT(is_result_field()); + DBUG_ASSERT(type() != NULL_ITEM); + get_tmp_field_src(src, param); + Field *result; + if ((result= tmp_table_field_from_field_type(table)) && param->modify_item()) + result_field= result; + return result; +} + + +Field *Item_func_user_var::create_tmp_field_ex(TABLE *table, + Tmp_field_src *src, + const Tmp_field_param *param) +{ + DBUG_ASSERT(is_result_field()); + DBUG_ASSERT(type() != NULL_ITEM); + get_tmp_field_src(src, param); + Field *result; + if ((result= create_table_field_from_handler(table)) && param->modify_item()) + result_field= result; + return result; +} + + +Field *Item_func_sp::create_tmp_field_ex(TABLE *table, + Tmp_field_src *src, + const Tmp_field_param *param) +{ + Field *result; + get_tmp_field_src(src, param); + if ((result= sp_result_field->create_tmp_field(table->in_use->mem_root, + table))) + { + result->field_name= name; + if (param->modify_item()) + result_field= result; + } + return result; +} + +/** Create field for temporary table. - @param thd Thread handler - @param table Temporary table - @param item Item to create a field for - @param type Type of item (normally item->type) - @param copy_func If set and item is a function, store copy of item + @param table Temporary table + @param item Item to create a field for + @param type Type of item (normally item->type) + @param copy_func If set and item is a function, store copy of item in this array @param from_field if field will be created using other field as example, pointer example field will be written here - @param default_field If field has a default value field, store it here - @param group 1 if we are going to do a relative group by on result - @param modify_item 1 if item->result_field should point to new item. + @param default_field If field has a default value field, store it here + @param group 1 if we are going to do a relative group by on result + @param modify_item 1 if item->result_field should point to new item. This is relevent for how fill_record() is going to work: If modify_item is 1 then fill_record() will update @@ -16880,175 +17024,28 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table) the temporary table @retval - 0 on error + 0 on error @retval new_created field + Create a temporary field for Item_field (or its descendant), + either direct or referenced by an Item_ref. */ - -Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, +Field *create_tmp_field(TABLE *table, Item *item, Item ***copy_func, Field **from_field, Field **default_field, bool group, bool modify_item, bool table_cant_handle_bit_fields, bool make_copy_field) { - Field *result; - Item::Type orig_type= type; - Item *orig_item= 0; - - DBUG_ASSERT(thd == table->in_use); - - if (type != Item::FIELD_ITEM && - item->real_item()->type() == Item::FIELD_ITEM) - { - orig_item= item; - item= item->real_item(); - type= Item::FIELD_ITEM; - } - - switch (type) { - case Item::TYPE_HOLDER: - case Item::SUM_FUNC_ITEM: - { - result= item->create_tmp_field(group, table); - if (!result) - my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); - return result; - } - case Item::FIELD_ITEM: - case Item::DEFAULT_VALUE_ITEM: - case Item::INSERT_VALUE_ITEM: - case Item::TRIGGER_FIELD_ITEM: - { - Item_field *field= (Item_field*) item; - bool orig_modify= modify_item; - if (orig_type == Item::REF_ITEM) - modify_item= 0; - /* - If item have to be able to store NULLs but underlaid field can't do it, - create_tmp_field_from_field() can't be used for tmp field creation. - */ - if (((field->maybe_null && field->in_rollup) || - (thd->create_tmp_table_for_derived && /* for mat. view/dt */ - orig_item && orig_item->maybe_null)) && - !field->field->maybe_null()) - { - bool save_maybe_null= FALSE; - /* - The item the ref points to may have maybe_null flag set while - the ref doesn't have it. This may happen for outer fields - when the outer query decided at some point after name resolution phase - that this field might be null. Take this into account here. - */ - if (orig_item) - { - save_maybe_null= item->maybe_null; - item->maybe_null= orig_item->maybe_null; - } - result= create_tmp_field_from_item(thd, item, table, NULL, - modify_item); - *from_field= field->field; - if (result && modify_item) - field->result_field= result; - if (orig_item) - { - item->maybe_null= save_maybe_null; - result->field_name= orig_item->name; - } - } - else if (table_cant_handle_bit_fields && field->field->type() == - MYSQL_TYPE_BIT) - { - const Type_handler *handler= item->type_handler_long_or_longlong(); - *from_field= field->field; - if ((result= - handler->make_and_init_table_field(&item->name, - Record_addr(item->maybe_null), - *item, table))) - create_tmp_field_from_item_finalize(thd, result, item, - copy_func, modify_item); - if (result && modify_item) - field->result_field= result; - } - else - { - LEX_CSTRING *tmp= orig_item ? &orig_item->name : &item->name; - result= create_tmp_field_from_field(thd, (*from_field= field->field), - tmp, table, - modify_item ? field : - NULL); - } - - if (orig_type == Item::REF_ITEM && orig_modify) - ((Item_ref*)orig_item)->set_result_field(result); - /* - Fields that are used as arguments to the DEFAULT() function already have - their data pointers set to the default value during name resolution. See - Item_default_value::fix_fields. - */ - if (orig_type != Item::DEFAULT_VALUE_ITEM && field->field->eq_def(result)) - *default_field= field->field; - return result; - } - /* Fall through */ - case Item::FUNC_ITEM: - if (((Item_func *) item)->functype() == Item_func::FUNC_SP) - { - Item_func_sp *item_func_sp= (Item_func_sp *) item; - Field *sp_result_field= item_func_sp->get_sp_result_field(); - - if (make_copy_field) - { - DBUG_ASSERT(item_func_sp->result_field); - *from_field= item_func_sp->result_field; - } - else - { - *((*copy_func)++)= item; - } - Field *result_field= - create_tmp_field_from_field(thd, - sp_result_field, - &item_func_sp->name, - table, - NULL); - - if (modify_item) - item->set_result_field(result_field); - - return result_field; - } - - /* Fall through */ - case Item::COND_ITEM: - case Item::FIELD_AVG_ITEM: - case Item::FIELD_STD_ITEM: - case Item::SUBSELECT_ITEM: - /* The following can only happen with 'CREATE TABLE ... SELECT' */ - case Item::PROC_ITEM: - case Item::INT_ITEM: - case Item::REAL_ITEM: - case Item::DECIMAL_ITEM: - case Item::STRING_ITEM: - case Item::DATE_ITEM: - case Item::REF_ITEM: - case Item::NULL_ITEM: - case Item::VARBIN_ITEM: - case Item::CACHE_ITEM: - case Item::WINDOW_FUNC_ITEM: // psergey-winfunc: - case Item::EXPR_CACHE_ITEM: - case Item::PARAM_ITEM: - if (make_copy_field) - { - DBUG_ASSERT(((Item_result_field*)item)->result_field); - *from_field= ((Item_result_field*)item)->result_field; - } - return create_tmp_field_from_item(thd, item, table, - (make_copy_field ? 0 : copy_func), - modify_item); - default: // Dosen't have to be stored - return 0; - } + Tmp_field_src src; + Tmp_field_param prm(group, modify_item, table_cant_handle_bit_fields, + make_copy_field); + Field *result= item->create_tmp_field_ex(table, &src, &prm); + *from_field= src.field(); + *default_field= src.default_field(); + if (src.item_result_field()) + *((*copy_func)++)= src.item_result_field(); + return result; } /* @@ -17064,7 +17061,7 @@ setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps, uint field_count) { uint bitmap_size= bitmap_buffer_size(field_count); - DBUG_ASSERT(table->s->virtual_fields == 0 && table->def_vcol_set == 0); + DBUG_ASSERT(table->s->virtual_fields == 0); my_bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count, FALSE); @@ -17329,7 +17326,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, } if (not_all_columns) { - if (item->with_sum_func && type != Item::SUM_FUNC_ITEM) + if (item->with_sum_func() && type != Item::SUM_FUNC_ITEM) { if (item->used_tables() & OUTER_REF_TABLE_BIT) item->update_used_tables(); @@ -17359,7 +17356,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, { Item *tmp_item; Field *new_field= - create_tmp_field(thd, table, arg, arg->type(), ©_func, + create_tmp_field(table, arg, ©_func, tmp_from_field, &default_field[fieldnr], group != 0,not_all_columns, distinct, false); @@ -17409,7 +17406,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, else { /* - The last parameter to create_tmp_field() is a bit tricky: + The last parameter to create_tmp_field_ex() is a bit tricky: We need to set it to 0 in union, to get fill_record() to modify the temporary table. @@ -17423,7 +17420,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, */ Field *new_field= (param->schema_table) ? item->create_field_for_schema(thd, table) : - create_tmp_field(thd, table, item, type, ©_func, + create_tmp_field(table, item, ©_func, tmp_from_field, &default_field[fieldnr], group != 0, !force_copy_fields && @@ -17437,8 +17434,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, */ item->marker == 4 || param->bit_fields_as_long, force_copy_fields); - - if (unlikely(!new_field)) + if (!new_field) { if (unlikely(thd->is_fatal_error)) goto err; // Got OOM @@ -18019,12 +18015,10 @@ bool Virtual_tmp_table::add(List<Spvar_definition> &field_list) while ((cdef= it++)) { Field *tmp; - if (!(tmp= cdef->make_field(s, in_use->mem_root, 0, - (uchar*) (f_maybe_null(cdef->pack_flag) ? "" : 0), - f_maybe_null(cdef->pack_flag) ? 1 : 0, - &cdef->field_name))) + Record_addr addr(f_maybe_null(cdef->pack_flag)); + if (!(tmp= cdef->make_field(s, in_use->mem_root, &addr, &cdef->field_name))) DBUG_RETURN(true); - add(tmp); + add(tmp); } DBUG_RETURN(false); } @@ -18144,7 +18138,7 @@ bool Virtual_tmp_table::sp_set_all_fields_from_item_list(THD *thd, bool Virtual_tmp_table::sp_set_all_fields_from_item(THD *thd, Item *value) { - DBUG_ASSERT(value->fixed); + DBUG_ASSERT(value->is_fixed()); DBUG_ASSERT(value->cols() == s->fields); for (uint i= 0; i < value->cols(); i++) { @@ -18567,7 +18561,7 @@ create_internal_tmp_table_from_heap(THD *thd, TABLE *table, We don't want this error to be converted to a warning, e.g. in case of INSERT IGNORE ... SELECT. */ - table->file->print_error(error, MYF(ME_FATALERROR)); + table->file->print_error(error, MYF(ME_FATAL)); DBUG_RETURN(1); } new_table= *table; @@ -18590,7 +18584,7 @@ create_internal_tmp_table_from_heap(THD *thd, TABLE *table, new_table.no_rows= table->no_rows; if (create_internal_tmp_table(&new_table, table->key_info, start_recinfo, recinfo, - thd->lex->select_lex.options | + thd->lex->first_select_lex()->options | thd->variables.option_bits)) goto err2; if (open_tmp_table(&new_table)) @@ -22741,7 +22735,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field, if (unlikely(copy_blobs(first_field))) { my_message(ER_OUTOFMEMORY, ER_THD(thd,ER_OUTOFMEMORY), - MYF(ME_FATALERROR)); + MYF(ME_FATAL)); error=0; goto err; } @@ -23018,12 +23012,7 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, uint counter; enum_resolution_type resolution; - /* - Local SP variables may be int but are expressions, not positions. - (And they can't be used before fix_fields is called for them). - */ - if (order_item->type() == Item::INT_ITEM && order_item->basic_const_item() && - !from_window_spec) + if (order_item->is_order_clause_position() && !from_window_spec) { /* Order by position */ uint count; if (order->counter_used) @@ -23137,7 +23126,7 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, inspite of that fix_fields() calls find_item_in_list() one more time. - We check order_item->fixed because Item_func_group_concat can put + We check order_item->is_fixed() because Item_func_group_concat can put arguments for which fix_fields already was called. */ if (order_item->fix_fields_if_needed_for_order_by(thd, order->item) || @@ -23247,7 +23236,7 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, all_fields, true, true, from_window_spec)) return 1; (*ord->item)->marker= UNDEF_POS; /* Mark found */ - if ((*ord->item)->with_sum_func && context_analysis_place == IN_GROUP_BY) + if ((*ord->item)->with_sum_func() && context_analysis_place == IN_GROUP_BY) { my_error(ER_WRONG_GROUP_FIELD, MYF(0), (*ord->item)->full_name()); return 1; @@ -23406,7 +23395,7 @@ create_distinct_group(THD *thd, Ref_ptr_array ref_pointer_array, li.rewind(); while ((item=li++)) { - if (!item->const_item() && !item->with_sum_func && !item->marker) + if (!item->const_item() && !item->with_sum_func() && !item->marker) { /* Don't put duplicate columns from the SELECT list into the @@ -23503,9 +23492,11 @@ count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param, } else { + With_sum_func_cache *cache= field->get_with_sum_func_cache(); param->func_count++; - if (reset_with_sum_func) - field->with_sum_func=0; + // "field" can point to Item_std_field, so "cache" can be NULL here. + if (reset_with_sum_func && cache) + cache->reset_with_sum_func(); } } } @@ -23645,7 +23636,7 @@ void calc_group_buffer(TMP_TABLE_PARAM *param, ORDER *group) { /* Group strings are taken as varstrings and require an length field. - A field is not yet created by create_tmp_field() + A field is not yet created by create_tmp_field_ex() and the sizes should match up. */ key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH; @@ -23655,7 +23646,7 @@ void calc_group_buffer(TMP_TABLE_PARAM *param, ORDER *group) default: /* This case should never be choosen */ DBUG_ASSERT(0); - my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL)); } } parts++; @@ -23909,7 +23900,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, real_pos->real_type() == Item::SUBSELECT_ITEM || real_pos->type() == Item::CACHE_ITEM || real_pos->type() == Item::COND_ITEM) && - !real_pos->with_sum_func) + !real_pos->with_sum_func()) { // Save for send fields pos= real_pos; /* TODO: @@ -23918,7 +23909,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, on how the value is to be used: In some cases this may be an argument in a group function, like: IF(ISNULL(col),0,COUNT(*)) */ - if (!(pos=new (thd->mem_root) Item_copy_string(thd, pos))) + if (!(pos= pos->type_handler()->create_item_copy(thd, pos))) goto err; if (i < border) // HAVING, ORDER and GROUP BY { @@ -24116,7 +24107,7 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array, for (uint i= 0; (item= it++); i++) { Field *field; - if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) + if (item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM) item_field= item; else if (item->type() == Item::FIELD_ITEM) { @@ -24424,7 +24415,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) } if (unlikely(thd->is_fatal_error)) DBUG_RETURN(TRUE); - if (!cond->fixed) + if (!cond->is_fixed()) { Item *tmp_item= (Item*) cond; cond->fix_fields(thd, &tmp_item); @@ -24643,7 +24634,7 @@ bool JOIN::rollup_init() Marking the expression item as 'with_sum_func' will ensure this. */ if (changed) - item->with_sum_func= 1; + item->get_with_sum_func_cache()->set_with_sum_func(); } } return 0; @@ -25131,7 +25122,8 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta, */ if (real_table->merged_for_insert) { - TABLE_LIST *view_child= real_table->view->select_lex.table_list.first; + TABLE_LIST *view_child= + real_table->view->first_select_lex()->table_list.first; for (;view_child; view_child= view_child->next_local) { if (view_child->table == table) @@ -25584,8 +25576,9 @@ int JOIN::save_explain_data_intern(Explain_query *output, { JOIN *join= this; /* Legacy: this code used to be a non-member function */ DBUG_ENTER("JOIN::save_explain_data_intern"); - DBUG_PRINT("info", ("Select %p, type %s, message %s", - join->select_lex, join->select_lex->type, + DBUG_PRINT("info", ("Select %p (%u), type %s, message %s", + join->select_lex, join->select_lex->select_number, + join->select_lex->type, message ? message : "NULL")); DBUG_ASSERT(have_query_plan == QEP_AVAILABLE); /* fake_select_lex is created/printed by Explain_union */ @@ -25611,7 +25604,7 @@ int JOIN::save_explain_data_intern(Explain_query *output, explain->select_id= join->select_lex->select_number; explain->select_type= join->select_lex->type; - explain->linkage= select_lex->linkage; + explain->linkage= select_lex->get_linkage(); explain->using_temporary= need_tmp; explain->using_filesort= need_order_arg; /* Setting explain->message means that all other members are invalid */ @@ -25634,7 +25627,7 @@ int JOIN::save_explain_data_intern(Explain_query *output, explain->select_id= select_lex->select_number; explain->select_type= select_lex->type; - explain->linkage= select_lex->linkage; + explain->linkage= select_lex->get_linkage(); explain->using_temporary= need_tmp; explain->using_filesort= need_order_arg; explain->message= "Storage engine handles GROUP BY"; @@ -25657,7 +25650,7 @@ int JOIN::save_explain_data_intern(Explain_query *output, join->select_lex->set_explain_type(true); xpl_sel->select_id= join->select_lex->select_number; xpl_sel->select_type= join->select_lex->type; - xpl_sel->linkage= select_lex->linkage; + xpl_sel->linkage= select_lex->get_linkage(); if (select_lex->master_unit()->derived) xpl_sel->connection_type= Explain_node::EXPLAIN_NODE_DERIVED; @@ -25801,7 +25794,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, for such queries, we'll get here before having called subquery_expr->fix_fields(), which will cause failure to */ - if (unit->item && !unit->item->fixed) + if (unit->item && !unit->item->is_fixed()) { Item *ref= unit->item; if (unit->item->fix_fields(thd, &ref)) @@ -26241,6 +26234,18 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) { str->append("/* select#"); str->append_ulonglong(select_number); + if (thd->lex->describe & DESCRIBE_EXTENDED2) + { + str->append("/"); + str->append_ulonglong(nest_level); + + if (master_unit()->fake_select_lex && + master_unit()->first_select() == this) + { + str->append(" Filter Select: "); + master_unit()->fake_select_lex->print(thd, str, query_type); + } + } str->append(" */ "); } @@ -26272,18 +26277,21 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) str->append(STRING_WITH_LEN("sql_buffer_result ")); if (options & OPTION_FOUND_ROWS) str->append(STRING_WITH_LEN("sql_calc_found_rows ")); - switch (sql_cache) + if (this == parent_lex->first_select_lex()) { - case SQL_NO_CACHE: - str->append(STRING_WITH_LEN("sql_no_cache ")); - break; - case SQL_CACHE: - str->append(STRING_WITH_LEN("sql_cache ")); - break; - case SQL_CACHE_UNSPECIFIED: - break; - default: - DBUG_ASSERT(0); + switch (parent_lex->sql_cache) + { + case LEX::SQL_NO_CACHE: + str->append(STRING_WITH_LEN("sql_no_cache ")); + break; + case LEX::SQL_CACHE: + str->append(STRING_WITH_LEN("sql_cache ")); + break; + case LEX::SQL_CACHE_UNSPECIFIED: + break; + default: + DBUG_ASSERT(0); + } } //Item List diff --git a/sql/sql_select.h b/sql/sql_select.h index 0e486c1fbec..e2c78473b1a 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1477,6 +1477,11 @@ public: Dynamic_array<KEYUSE_EXT> *ext_keyuses_for_splitting; JOIN_TAB *sort_and_group_aggr_tab; + /* + Flag is set to true if select_lex was found to be degenerated before + the optimize_cond() call in JOIN::optimize_inner() method. + */ + bool is_orig_degenerated; JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg, select_result *result_arg) @@ -1572,6 +1577,7 @@ public: emb_sjm_nest= NULL; sjm_lookup_tables= 0; sjm_scan_tables= 0; + is_orig_degenerated= false; } /* True if the plan guarantees that it will be returned zero or one row */ @@ -1751,6 +1757,7 @@ public: bool fix_all_splittings_in_plan(); bool transform_in_predicates_into_in_subq(THD *thd); + bool add_equalities_to_where_condition(THD *thd, List<Item> &eq_list); private: /** Create a temporary table to be used for processing DISTINCT/ORDER @@ -1815,10 +1822,6 @@ bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, void copy_fields(TMP_TABLE_PARAM *param); bool copy_funcs(Item **func_ptr, const THD *thd); uint find_shortest_key(TABLE *table, const key_map *usable_keys); -Field* create_tmp_field_from_field(THD *thd, Field* org_field, - LEX_CSTRING *name, TABLE *table, - Item_field *item); - bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args); /* functions from opt_sum.cc */ @@ -2070,12 +2073,6 @@ bool mysql_select(THD *thd, void free_underlaid_joins(THD *thd, SELECT_LEX *select); bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result); -Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, - Item ***copy_func, Field **from_field, - Field **def_field, - bool group, bool modify_item, - bool table_cant_handle_bit_fields, - bool make_copy_field); /* General routine to change field->ptr of a NULL-terminated array of Field @@ -2343,7 +2340,7 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field, extern bool test_if_ref(Item *, Item_field *left_item,Item *right_item); -inline bool optimizer_flag(THD *thd, uint flag) +inline bool optimizer_flag(THD *thd, ulonglong flag) { return (thd->variables.optimizer_switch & flag); } @@ -2459,4 +2456,13 @@ int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort); JOIN_TAB *first_explain_order_tab(JOIN* join); JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab); +bool check_simple_equality(THD *thd, const Item::Context &ctx, + Item *left_item, Item *right_item, + COND_EQUAL *cond_equal); + +void propagate_new_equalities(THD *thd, Item *cond, + List<Item_equal> *new_equalities, + COND_EQUAL *inherited, + bool *is_simplifiable_cond); + #endif /* SQL_SELECT_INCLUDED */ diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index 1fb2e5e7714..1ed0bb38e64 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -220,8 +220,8 @@ bool check_sequence_fields(LEX *lex, List<Create_field> *fields) err: my_error(ER_SEQUENCE_INVALID_TABLE_STRUCTURE, MYF(0), - lex->select_lex.table_list.first->db.str, - lex->select_lex.table_list.first->table_name.str, reason); + lex->first_select_lex()->table_list.first->db.str, + lex->first_select_lex()->table_list.first->table_name.str, reason); DBUG_RETURN(TRUE); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 426f40d1729..5adee6731b5 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1034,9 +1034,9 @@ find_files(THD *thd, Dynamic_array<LEX_CSTRING*> *files, LEX_CSTRING *db, if (!(dirp = my_dir(path, MY_THREAD_SPECIFIC | (db ? 0 : MY_WANT_STAT)))) { if (my_errno == ENOENT) - my_error(ER_BAD_DB_ERROR, MYF(ME_BELL | ME_WAITTANG), db->str); + my_error(ER_BAD_DB_ERROR, MYF(0), db->str); else - my_error(ER_CANT_READ_DIR, MYF(ME_BELL | ME_WAITTANG), path, my_errno); + my_error(ER_CANT_READ_DIR, MYF(0), path, my_errno); DBUG_RETURN(FIND_FILES_DIR); } @@ -2184,6 +2184,12 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, field->sql_type(type); packet->append(type.ptr(), type.length(), system_charset_info); + DBUG_EXECUTE_IF("sql_type", + packet->append(" /* "); + packet->append(field->type_handler()->version().ptr()); + packet->append(" */ "); + ); + if (field->has_charset() && !(sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))) { if (field->charset() != share->table_charset) @@ -4143,8 +4149,9 @@ bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables, case SQLCOM_SHOW_TABLE_STATUS: case SQLCOM_SHOW_TRIGGERS: case SQLCOM_SHOW_EVENTS: - thd->make_lex_string(&lookup_field_values->db_value, - lex->select_lex.db.str, lex->select_lex.db.length); + thd->make_lex_string(&lookup_field_values->db_value, + lex->first_select_lex()->db.str, + lex->first_select_lex()->db.length); if (wild) { thd->make_lex_string(&lookup_field_values->table_value, @@ -4537,10 +4544,10 @@ fill_schema_table_by_open(THD *thd, MEM_ROOT *mem_root, temporary LEX. The latter is required to correctly open views and produce table describing their structure. */ - if (make_table_list(thd, &lex->select_lex, &db_name, &table_name)) + if (make_table_list(thd, lex->first_select_lex(), &db_name, &table_name)) goto end; - table_list= lex->select_lex.table_list.first; + table_list= lex->first_select_lex()->table_list.first; if (is_show_fields_or_keys) { @@ -6325,7 +6332,6 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, const char *wild, bool full_access, const char *sp_user) { - MYSQL_TIME time; LEX *lex= thd->lex; CHARSET_INFO *cs= system_charset_info; const Sp_handler *sph; @@ -6413,14 +6419,11 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, copy_field_as_string(table->field[22], proc_table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]); - bzero((char *)&time, sizeof(time)); - ((Field_timestamp *) proc_table->field[MYSQL_PROC_FIELD_CREATED])-> - get_time(&time); - table->field[23]->store_time(&time); - bzero((char *)&time, sizeof(time)); - ((Field_timestamp *) proc_table->field[MYSQL_PROC_FIELD_MODIFIED])-> - get_time(&time); - table->field[24]->store_time(&time); + proc_table->field[MYSQL_PROC_FIELD_CREATED]-> + save_in_field(table->field[23]); + proc_table->field[MYSQL_PROC_FIELD_MODIFIED]-> + save_in_field(table->field[24]); + copy_field_as_string(table->field[25], proc_table->field[MYSQL_PROC_FIELD_SQL_MODE]); copy_field_as_string(table->field[26], @@ -6713,7 +6716,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, & 'field_translation_end' are uninitialized is this case. */ - List<Item> *fields= &tables->view->select_lex.item_list; + List<Item> *fields= &tables->view->first_select_lex()->item_list; List_iterator<Item> it(*fields); Item *item; Item_field *field; @@ -7366,7 +7369,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, break; default: DBUG_ASSERT(0); - my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL)); DBUG_RETURN(1); } table->field[7]->set_notnull(); @@ -7492,7 +7495,8 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, } else if (part_info->vers_info->interval.is_set()) { - table->field[11]->store_timestamp((my_time_t)part_elem->range_value, 0); + Timeval tv((my_time_t) part_elem->range_value, 0); + table->field[11]->store_timestamp_dec(tv, AUTO_SEC_PART_DIGITS); table->field[11]->set_notnull(); } } @@ -7678,11 +7682,11 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) sch_table->field[ISE_ON_COMPLETION]-> store(STRING_WITH_LEN("PRESERVE"), scs); - number_to_datetime(et.created, 0, &time, 0, ¬_used); + number_to_datetime_or_date(et.created, 0, &time, 0, ¬_used); DBUG_ASSERT(not_used==0); sch_table->field[ISE_CREATED]->store_time(&time); - number_to_datetime(et.modified, 0, &time, 0, ¬_used); + number_to_datetime_or_date(et.modified, 0, &time, 0, ¬_used); DBUG_ASSERT(not_used==0); sch_table->field[ISE_LAST_ALTERED]->store_time(&time); @@ -7728,9 +7732,9 @@ int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; CHARSET_INFO *cs= system_charset_info; OPEN_TABLE_LIST *open_list; - if (unlikely(!(open_list= list_open_tables(thd, thd->lex->select_lex.db.str, - wild))) && - unlikely(thd->is_fatal_error)) + if (!(open_list= list_open_tables(thd, thd->lex->first_select_lex()->db.str, + wild)) + && thd->is_fatal_error) DBUG_RETURN(1); for (; open_list ; open_list=open_list->next) @@ -8224,7 +8228,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) tmp_table_param->table_charset= cs; tmp_table_param->field_count= field_count; tmp_table_param->schema_table= 1; - SELECT_LEX *select_lex= thd->lex->current_select; + SELECT_LEX *select_lex= table_list->select_lex; bool keep_row_order= is_show_command(thd); if (!(table= create_tmp_table(thd, tmp_table_param, field_list, (ORDER*) 0, 0, 0, @@ -8261,7 +8265,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) static int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { ST_FIELD_INFO *field_info= schema_table->fields_info; - Name_resolution_context *context= &thd->lex->select_lex.context; + Name_resolution_context *context= &thd->lex->first_select_lex()->context; for (; field_info->field_name; field_info++) { if (field_info->old_name) @@ -8321,14 +8325,14 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) char tmp[128]; String buffer(tmp,sizeof(tmp), thd->charset()); LEX *lex= thd->lex; - Name_resolution_context *context= &lex->select_lex.context; + Name_resolution_context *context= &lex->first_select_lex()->context; ST_FIELD_INFO *field_info= &schema_table->fields_info[2]; LEX_CSTRING field_name= {field_info->field_name, strlen(field_info->field_name) }; buffer.length(0); buffer.append(field_info->old_name); - buffer.append(&lex->select_lex.db); + buffer.append(&lex->first_select_lex()->db); if (lex->wild && lex->wild->ptr()) { buffer.append(STRING_WITH_LEN(" (")); @@ -8361,7 +8365,7 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) int fields_arr[]= {3, 15, 14, 6, 16, 5, 17, 18, 19, -1}; int *field_num= fields_arr; ST_FIELD_INFO *field_info; - Name_resolution_context *context= &thd->lex->select_lex.context; + Name_resolution_context *context= &thd->lex->first_select_lex()->context; for (; *field_num >= 0; field_num++) { @@ -8392,7 +8396,7 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) int fields_arr[]= {0, 2, 1, 3, -1}; int *field_num= fields_arr; ST_FIELD_INFO *field_info; - Name_resolution_context *context= &thd->lex->select_lex.context; + Name_resolution_context *context= &thd->lex->first_select_lex()->context; for (; *field_num >= 0; field_num++) { @@ -8419,7 +8423,7 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) int fields_arr[]= {2, 3, 4, 27, 24, 23, 22, 26, 28, 29, 30, -1}; int *field_num= fields_arr; ST_FIELD_INFO *field_info; - Name_resolution_context *context= &thd->lex->select_lex.context; + Name_resolution_context *context= &thd->lex->first_select_lex()->context; for (; *field_num >= 0; field_num++) { diff --git a/sql/sql_signal.cc b/sql/sql_signal.cc index a92d40f6bb3..83abaebd4fd 100644 --- a/sql/sql_signal.cc +++ b/sql/sql_signal.cc @@ -323,7 +323,7 @@ end: set= m_set_signal_information.m_item[i]; if (set) { - if (set->fixed) + if (set->is_fixed()) set->cleanup(); } } diff --git a/sql/sql_sort.h b/sql/sql_sort.h index c29bf1440c9..231bc93ce75 100644 --- a/sql/sql_sort.h +++ b/sql/sql_sort.h @@ -92,7 +92,6 @@ public: memset(this, 0, sizeof(*this)); } void init_for_filesort(uint sortlen, TABLE *table, - ulong max_length_for_sort_data, ha_rows maxrows, bool sort_positions); }; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 2384c68115b..6f4474860a9 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -3254,7 +3254,7 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables) { TABLE_LIST stat_tables[STATISTICS_TABLES]; Open_tables_backup open_tables_backup; - + bool has_error_active= thd->is_error(); DBUG_ENTER("read_statistics_for_tables_if_needed"); DEBUG_SYNC(thd, "statistics_read_start"); @@ -3264,7 +3264,8 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables) if (open_stat_tables(thd, stat_tables, &open_tables_backup, FALSE)) { - thd->clear_error(); + if (!has_error_active) + thd->clear_error(); DBUG_RETURN(1); } @@ -3318,7 +3319,7 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables) 'db' from all statistical tables: table_stats, column_stats, index_stats. @retval - 0 If all deletions are successful + 0 If all deletions are successful or we couldn't open statistics table @retval 1 Otherwise @@ -3326,7 +3327,8 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables) The function is called when executing the statement DROP TABLE 'tab'. */ -int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab) +int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, + const LEX_CSTRING *tab) { int err; enum_binlog_format save_binlog_format; @@ -3334,11 +3336,15 @@ int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRI TABLE_LIST tables[STATISTICS_TABLES]; Open_tables_backup open_tables_backup; int rc= 0; - + bool has_error_active= thd->is_error(); DBUG_ENTER("delete_statistics_for_table"); if (open_stat_tables(thd, tables, &open_tables_backup, TRUE)) - DBUG_RETURN(rc); + { + if (!has_error_active) + thd->clear_error(); + DBUG_RETURN(0); + } save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3403,7 +3409,7 @@ int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRI 'tab' from the statistical table column_stats. @retval - 0 If the deletion is successful + 0 If all deletions are successful or we couldn't open statistics table @retval 1 Otherwise @@ -3420,14 +3426,15 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col) TABLE_LIST tables; Open_tables_backup open_tables_backup; int rc= 0; - + bool has_error_active= thd->is_error(); DBUG_ENTER("delete_statistics_for_column"); if (open_single_stat_table(thd, &tables, &stat_table_name[1], &open_tables_backup, TRUE)) { - thd->clear_error(); - DBUG_RETURN(rc); + if (!has_error_active) + thd->clear_error(); + DBUG_RETURN(0); } save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3469,7 +3476,7 @@ int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col) defined on the table 'tab' from the statistical table index_stats. @retval - 0 If the deletion is successful + 0 If all deletions are successful or we couldn't open statistics table @retval 1 Otherwise @@ -3487,14 +3494,15 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info, TABLE_LIST tables; Open_tables_backup open_tables_backup; int rc= 0; - + bool has_error_active= thd->is_error(); DBUG_ENTER("delete_statistics_for_index"); if (open_single_stat_table(thd, &tables, &stat_table_name[2], &open_tables_backup, TRUE)) { - thd->clear_error(); - DBUG_RETURN(rc); + if (!has_error_active) + thd->clear_error(); + DBUG_RETURN(0); } save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3564,8 +3572,10 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info, The function is called when executing any statement that renames a table */ -int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab, - const LEX_CSTRING *new_db, const LEX_CSTRING *new_tab) +int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, + const LEX_CSTRING *tab, + const LEX_CSTRING *new_db, + const LEX_CSTRING *new_tab) { int err; enum_binlog_format save_binlog_format; @@ -3576,7 +3586,9 @@ int rename_table_in_stat_tables(THD *thd, const LEX_CSTRING *db, const LEX_CSTRI DBUG_ENTER("rename_table_in_stat_tables"); if (open_stat_tables(thd, tables, &open_tables_backup, TRUE)) + { DBUG_RETURN(0); // not an error + } save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -3668,7 +3680,7 @@ int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col, TABLE_LIST tables; Open_tables_backup open_tables_backup; int rc= 0; - + bool has_error_active= thd->is_error(); DBUG_ENTER("rename_column_in_stat_tables"); if (tab->s->tmp_table != NO_TMP_TABLE) @@ -3677,7 +3689,8 @@ int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col, if (open_single_stat_table(thd, &tables, &stat_table_name[1], &open_tables_backup, TRUE)) { - thd->clear_error(); + if (!has_error_active) + thd->clear_error(); DBUG_RETURN(rc); } @@ -3721,9 +3734,8 @@ void set_statistics_for_table(THD *thd, TABLE *table) { TABLE_STATISTICS_CB *stats_cb= &table->s->stats_cb; Table_statistics *read_stats= stats_cb->table_stats; - Use_stat_tables_mode use_stat_table_mode= get_use_stat_tables_mode(thd); table->used_stat_records= - (use_stat_table_mode <= COMPLEMENTARY || + (!check_eits_preferred(thd) || !table->stats_is_read || read_stats->cardinality_is_null) ? table->file->stats.records : read_stats->cardinality; @@ -3747,7 +3759,7 @@ void set_statistics_for_table(THD *thd, TABLE *table) key_info < key_info_end; key_info++) { key_info->is_statistics_from_stat_tables= - (use_stat_table_mode > COMPLEMENTARY && + (check_eits_preferred(thd) && table->stats_is_read && key_info->read_stats->avg_frequency_is_inited() && key_info->read_stats->get_avg_frequency(0) > 0.5); diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h index 89758f002ca..3ed4006efd3 100644 --- a/sql/sql_statistics.h +++ b/sql/sql_statistics.h @@ -16,12 +16,26 @@ #ifndef SQL_STATISTICS_H #define SQL_STATISTICS_H +/* + For COMPLEMENTARY_FOR_QUERIES and PREFERABLY_FOR_QUERIES they are + similar to the COMPLEMENTARY and PREFERABLY respectively except that + with these values we would not be collecting EITS for queries like + ANALYZE TABLE t1; + To collect EITS with these values, we have to use PERSISITENT FOR + analyze table t1 persistent for + columns (col1,col2...) index (idx1, idx2...) + or + analyze table t1 persistent for all +*/ + typedef enum enum_use_stat_tables_mode { NEVER, COMPLEMENTARY, PREFERABLY, + COMPLEMENTARY_FOR_QUERIES, + PREFERABLY_FOR_QUERIES } Use_stat_tables_mode; typedef @@ -87,6 +101,19 @@ Use_stat_tables_mode get_use_stat_tables_mode(THD *thd) { return (Use_stat_tables_mode) (thd->variables.use_stat_tables); } +inline +bool check_eits_collection_allowed(THD *thd) +{ + return (get_use_stat_tables_mode(thd) == COMPLEMENTARY || + get_use_stat_tables_mode(thd) == PREFERABLY); +} + +inline +bool check_eits_preferred(THD *thd) +{ + return (get_use_stat_tables_mode(thd) == PREFERABLY || + get_use_stat_tables_mode(thd) == PREFERABLY_FOR_QUERIES); +} int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables); int collect_statistics_for_table(THD *thd, TABLE *table); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index cc77452ecd1..b84585114b7 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -31,7 +31,7 @@ ** String functions *****************************************************************************/ -bool String::real_alloc(size_t length) +bool Binary_string::real_alloc(size_t length) { size_t arg_length= ALIGN_SIZE(length + 1); DBUG_ASSERT(arg_length > length); @@ -81,7 +81,7 @@ bool String::real_alloc(size_t length) @retval true An error occurred when attempting to allocate memory. */ -bool String::realloc_raw(size_t alloc_length) +bool Binary_string::realloc_raw(size_t alloc_length) { if (Alloced_length <= alloc_length) { @@ -103,8 +103,7 @@ bool String::realloc_raw(size_t alloc_length) (thread_specific ? MY_THREAD_SPECIFIC : 0))))) { - if (str_length > len - 1) - str_length= 0; + DBUG_ASSERT(str_length < len); if (str_length) // Avoid bugs in memcpy on AIX memcpy(new_ptr,Ptr,str_length); new_ptr[str_length]=0; @@ -127,19 +126,18 @@ bool String::set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs) if (alloc(l)) return TRUE; str_length=(uint32) (cs->cset->longlong10_to_str)(cs,Ptr,l,base,num); - str_charset=cs; + set_charset(cs); return FALSE; } // Convert a number into its HEX representation -bool String::set_hex(ulonglong num) +bool Binary_string::set_hex(ulonglong num) { char *n_end; if (alloc(65) || !(n_end= longlong2str(num, Ptr, 16))) return true; length((uint32) (n_end - Ptr)); - set_charset(&my_charset_latin1); return false; } @@ -157,7 +155,7 @@ static inline void APPEND_HEX(char *&to, uchar value) } -void String::qs_append_hex(const char *str, uint32 len) +void Static_binary_string::qs_append_hex(const char *str, uint32 len) { const char *str_end= str + len; for (char *to= Ptr + str_length ; str < str_end; str++) @@ -167,7 +165,7 @@ void String::qs_append_hex(const char *str, uint32 len) // Convert a string to its HEX representation -bool String::set_hex(const char *str, uint32 len) +bool Binary_string::set_hex(const char *str, uint32 len) { /* Safety: cut the source string if "len" is too large. @@ -181,7 +179,6 @@ bool String::set_hex(const char *str, uint32 len) return true; length(0); qs_append_hex(str, len); - set_charset(&my_charset_latin1); return false; } @@ -192,7 +189,7 @@ bool String::set_real(double num,uint decimals, CHARSET_INFO *cs) uint dummy_errors; size_t len; - str_charset=cs; + set_charset(cs); if (decimals >= FLOATING_POINT_DECIMALS) { len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL); @@ -204,7 +201,7 @@ bool String::set_real(double num,uint decimals, CHARSET_INFO *cs) } -bool String::copy() +bool Binary_string::copy() { if (!alloced) { @@ -225,18 +222,17 @@ bool String::copy() @retval false Success. @retval true Memory allocation failed. */ -bool String::copy(const String &str) +bool Binary_string::copy(const Binary_string &str) { if (alloc(str.str_length)) return TRUE; str_length=str.str_length; bmove(Ptr,str.Ptr,str_length); // May be overlapping Ptr[str_length]=0; - str_charset=str.str_charset; return FALSE; } -bool String::copy(const char *str,size_t arg_length, CHARSET_INFO *cs) +bool Binary_string::copy(const char *str, size_t arg_length) { DBUG_ASSERT(arg_length < UINT_MAX32); if (alloc(arg_length)) @@ -253,7 +249,6 @@ bool String::copy(const char *str,size_t arg_length, CHARSET_INFO *cs) else if ((str_length=uint32(arg_length))) memcpy(Ptr,str,arg_length); Ptr[arg_length]=0; - str_charset=cs; return FALSE; } @@ -263,7 +258,7 @@ bool String::copy(const char *str,size_t arg_length, CHARSET_INFO *cs) from valgrind */ -bool String::copy_or_move(const char *str,size_t arg_length, CHARSET_INFO *cs) +bool Binary_string::copy_or_move(const char *str, size_t arg_length) { DBUG_ASSERT(arg_length < UINT_MAX32); if (alloc(arg_length)) @@ -271,7 +266,6 @@ bool String::copy_or_move(const char *str,size_t arg_length, CHARSET_INFO *cs) if ((str_length=uint32(arg_length))) memmove(Ptr,str,arg_length); Ptr[arg_length]=0; - str_charset=cs; return FALSE; } @@ -397,7 +391,7 @@ bool String::copy_aligned(const char *str, size_t arg_length, size_t offset, Ptr[aligned_length]=0; /* str_length is always >= 0 as arg_length is != 0 */ str_length= (uint32)aligned_length; - str_charset= cs; + set_charset(cs); return FALSE; } @@ -450,7 +444,7 @@ bool String::copy(const char *str, size_t arg_length, return TRUE; str_length=copy_and_convert((char*) Ptr, new_length, to_cs, str, arg_length, from_cs, errors); - str_charset=to_cs; + set_charset(to_cs); return FALSE; } @@ -476,19 +470,20 @@ bool String::copy(const char *str, size_t arg_length, bool String::set_ascii(const char *str, size_t arg_length) { - if (str_charset->mbminlen == 1) + if (mbminlen() == 1) { - set(str, arg_length, str_charset); + set(str, arg_length, charset()); return 0; } uint dummy_errors; - return copy(str, (uint32)arg_length, &my_charset_latin1, str_charset, &dummy_errors); + return copy(str, (uint32) arg_length, &my_charset_latin1, + charset(), &dummy_errors); } /* This is used by mysql.cc */ -bool String::fill(uint32 max_length,char fill_char) +bool Binary_string::fill(uint32 max_length,char fill_char) { if (str_length > max_length) Ptr[str_length=max_length]=0; @@ -504,22 +499,10 @@ bool String::fill(uint32 max_length,char fill_char) void String::strip_sp() { - while (str_length && my_isspace(str_charset,Ptr[str_length-1])) + while (str_length && my_isspace(charset(), Ptr[str_length-1])) str_length--; } -bool String::append(const String &s) -{ - if (s.length()) - { - if (realloc_with_extra_if_needed(str_length+s.length())) - return TRUE; - memcpy(Ptr+str_length,s.ptr(),s.length()); - str_length+=s.length(); - } - return FALSE; -} - /* Append an ASCII string to the a string of the current character set @@ -535,13 +518,13 @@ bool String::append(const char *s,size_t size) /* For an ASCII incompatible string, e.g. UCS-2, we need to convert */ - if (str_charset->mbminlen > 1) + if (mbminlen() > 1) { - uint32 add_length=arg_length * str_charset->mbmaxlen; + uint32 add_length= arg_length * mbmaxlen(); uint dummy_errors; if (realloc_with_extra_if_needed(str_length+ add_length)) return TRUE; - str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset, + str_length+= copy_and_convert(Ptr + str_length, add_length, charset(), s, arg_length, &my_charset_latin1, &dummy_errors); return FALSE; @@ -550,24 +533,11 @@ bool String::append(const char *s,size_t size) /* For an ASCII compatinble string we can just append. */ - if (realloc_with_extra_if_needed(str_length+arg_length)) - return TRUE; - memcpy(Ptr+str_length,s,arg_length); - str_length+=arg_length; - return FALSE; + return Binary_string::append(s, arg_length); } -/* - Append a 0-terminated ASCII string -*/ - -bool String::append(const char *s) -{ - return append(s, (uint) strlen(s)); -} - -bool String::append_longlong(longlong val) +bool Binary_string::append_longlong(longlong val) { if (realloc(str_length+MAX_BIGINT_WIDTH+2)) return TRUE; @@ -577,7 +547,7 @@ bool String::append_longlong(longlong val) } -bool String::append_ulonglong(ulonglong val) +bool Binary_string::append_ulonglong(ulonglong val) { if (realloc(str_length+MAX_BIGINT_WIDTH+2)) return TRUE; @@ -595,13 +565,13 @@ bool String::append(const char *s, size_t arg_length, CHARSET_INFO *cs) { uint32 offset; - if (needs_conversion((uint32)arg_length, cs, str_charset, &offset)) + if (needs_conversion((uint32)arg_length, cs, charset(), &offset)) { size_t add_length; if ((cs == &my_charset_bin) && offset) { - DBUG_ASSERT(str_charset->mbminlen > offset); - offset= str_charset->mbminlen - offset; // How many characters to pad + DBUG_ASSERT(mbminlen() > offset); + offset= mbminlen() - offset; // How many characters to pad add_length= arg_length + offset; if (realloc(str_length + add_length)) return TRUE; @@ -611,24 +581,19 @@ bool String::append(const char *s, size_t arg_length, CHARSET_INFO *cs) return FALSE; } - add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen; + add_length= arg_length / cs->mbminlen * mbmaxlen(); uint dummy_errors; if (realloc_with_extra_if_needed(str_length + add_length)) return TRUE; - str_length+= copy_and_convert(Ptr+str_length, (uint32)add_length, str_charset, - s, (uint32)arg_length, cs, &dummy_errors); + str_length+= copy_and_convert(Ptr + str_length, (uint32)add_length, charset(), + s, (uint32)arg_length, cs, &dummy_errors); + return false; } - else - { - if (realloc_with_extra_if_needed(str_length + arg_length)) - return TRUE; - memcpy(Ptr + str_length, s, arg_length); - str_length+= (uint32)arg_length; - } - return FALSE; + return Binary_string::append(s, arg_length); } -bool String::append(IO_CACHE* file, uint32 arg_length) + +bool Binary_string::append(IO_CACHE* file, uint32 arg_length) { if (realloc_with_extra_if_needed(str_length+arg_length)) return TRUE; @@ -676,19 +641,8 @@ bool String::append_with_prefill(const char *s,uint32 arg_length, return FALSE; } -uint32 String::numchars() const -{ - return (uint32) str_charset->cset->numchars(str_charset, Ptr, Ptr+str_length); -} - -int String::charpos(longlong i,uint32 offset) -{ - if (i <= 0) - return (int)i; - return (int)str_charset->cset->charpos(str_charset,Ptr+offset,Ptr+str_length,(size_t)i); -} -int String::strstr(const String &s,uint32 offset) +int Static_binary_string::strstr(const Static_binary_string &s, uint32 offset) { if (s.length()+offset <= str_length) { @@ -719,7 +673,7 @@ skip: ** Search string from end. Offset is offset to the end of string */ -int String::strrstr(const String &s,uint32 offset) +int Static_binary_string::strrstr(const Static_binary_string &s, uint32 offset) { if (s.length() <= offset && offset <= str_length) { @@ -746,18 +700,9 @@ skip: return -1; } -/* - Replace substring with string - If wrong parameter or not enough memory, do nothing -*/ - -bool String::replace(uint32 offset,uint32 arg_length,const String &to) -{ - return replace(offset,arg_length,to.ptr(),to.length()); -} -bool String::replace(uint32 offset,uint32 arg_length, - const char *to, uint32 to_length) +bool Binary_string::replace(uint32 offset, uint32 arg_length, + const char *to, uint32 to_length) { long diff = (long) to_length-(long) arg_length; if (offset+arg_length <= str_length) @@ -788,7 +733,7 @@ bool String::replace(uint32 offset,uint32 arg_length, // added by Holyfoot for "geometry" needs -int String::reserve(size_t space_needed, size_t grow_by) +int Binary_string::reserve(size_t space_needed, size_t grow_by) { if (Alloced_length < str_length + space_needed) { @@ -798,34 +743,34 @@ int String::reserve(size_t space_needed, size_t grow_by) return FALSE; } -void String::qs_append(const char *str, size_t len) +void Static_binary_string::qs_append(const char *str, size_t len) { memcpy(Ptr + str_length, str, len + 1); str_length += (uint32)len; } -void String::qs_append(double d) +void Static_binary_string::qs_append(double d) { char *buff = Ptr + str_length; str_length+= (uint32) my_gcvt(d, MY_GCVT_ARG_DOUBLE, FLOATING_POINT_BUFFER - 1, buff, NULL); } -void String::qs_append(double *d) +void Static_binary_string::qs_append(double *d) { double ld; float8get(ld, (char*) d); qs_append(ld); } -void String::qs_append(int i) +void Static_binary_string::qs_append(int i) { char *buff= Ptr + str_length; char *end= int10_to_str(i, buff, -10); str_length+= (int) (end-buff); } -void String::qs_append(ulonglong i) +void Static_binary_string::qs_append(ulonglong i) { char *buff= Ptr + str_length; char *end= longlong10_to_str(i, buff, 10); @@ -947,12 +892,12 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) of a constant string. Not safe to reuse. */ - if (from->Alloced_length > 0) // "from" is #c or #d (not a constant) + if (from->alloced_length() > 0) // "from" is #c or #d (not a constant) { - if (from->Alloced_length >= from_length) + if (from->alloced_length() >= from_length) return from; // #c or #d (large enough to store from_length bytes) - if (from->alloced) + if (from->is_alloced()) { (void) from->realloc(from_length); return from; // #d (reallocated to fit from_length bytes) @@ -991,7 +936,7 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) Note, as we can't distinguish between #a and #b for sure, so we can't assert "not #a", but we can at least assert "not #e". */ - DBUG_ASSERT(!from->alloced || from->Alloced_length > 0); // Not #e + DBUG_ASSERT(!from->is_alloced() || from->alloced_length() > 0); // Not #e (void) from->realloc(from_length); return from; @@ -1000,7 +945,7 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) return from; // Actually an error if ((to->str_length=MY_MIN(from->str_length,from_length))) memcpy(to->Ptr,from->Ptr,to->str_length); - to->str_charset=from->str_charset; + to->set_charset(*from); return to; // "from" was of types #a, #b, #e, or small #c. } @@ -1160,26 +1105,6 @@ void String::print_with_conversion(String *print, CHARSET_INFO *cs) const } -/* - Exchange state of this object and argument. - - SYNOPSIS - String::swap() - - RETURN - Target string will contain state of this object and vice versa. -*/ - -void String::swap(String &s) -{ - swap_variables(char *, Ptr, s.Ptr); - swap_variables(uint32, str_length, s.str_length); - swap_variables(uint32, Alloced_length, s.Alloced_length); - swap_variables(bool, alloced, s.alloced); - swap_variables(CHARSET_INFO*, str_charset, s.str_charset); -} - - /** Convert string to printable ASCII string diff --git a/sql/sql_string.h b/sql/sql_string.h index 23783405b19..a4574c2ef2d 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -126,56 +126,62 @@ uint convert_to_printable(char *to, size_t to_len, const char *from, size_t from_len, CHARSET_INFO *from_cs, size_t nbytes= 0); -class String + +class Charset { - char *Ptr; - uint32 str_length,Alloced_length, extra_alloc; - bool alloced,thread_specific; - CHARSET_INFO *str_charset; + CHARSET_INFO *m_charset; public: - String() - { - Ptr=0; str_length=Alloced_length=extra_alloc=0; - alloced= thread_specific= 0; - str_charset= &my_charset_bin; + Charset() :m_charset(&my_charset_bin) { } + Charset(CHARSET_INFO *cs) :m_charset(cs) { } + + CHARSET_INFO *charset() const { return m_charset; } + uint mbminlen() const { return m_charset->mbminlen; } + uint mbmaxlen() const { return m_charset->mbmaxlen; } + + size_t numchars(const char *str, const char *end) const + { + return m_charset->cset->numchars(m_charset, str, end); } - String(size_t length_arg) - { - alloced= thread_specific= 0; - Alloced_length= extra_alloc= 0; (void) real_alloc(length_arg); - str_charset= &my_charset_bin; + size_t charpos(const char *str, const char *end, size_t pos) const + { + return m_charset->cset->charpos(m_charset, str, end, pos); } - String(const char *str, CHARSET_INFO *cs) - { - Ptr=(char*) str; str_length= (uint32) strlen(str); - Alloced_length= extra_alloc= 0; - alloced= thread_specific= 0; - str_charset=cs; + void set_charset(CHARSET_INFO *charset_arg) + { + m_charset= charset_arg; } - /* - NOTE: If one intend to use the c_ptr() method, the following two - contructors need the size of memory for STR to be at least LEN+1 (to make - room for zero termination). - */ - String(const char *str,size_t len, CHARSET_INFO *cs) - { - Ptr=(char*) str; str_length=(uint32)len; Alloced_length= extra_alloc=0; - alloced= thread_specific= 0; - str_charset=cs; + void set_charset(const Charset &other) + { + m_charset= other.m_charset; } - String(char *str,size_t len, CHARSET_INFO *cs) - { - Ptr=(char*) str; Alloced_length=str_length=(uint32)len; extra_alloc= 0; - alloced= thread_specific= 0; - str_charset=cs; + void swap(Charset &other) + { + swap_variables(CHARSET_INFO*, m_charset, other.m_charset); } - String(const String &str) - { - Ptr=str.Ptr ; str_length=str.str_length ; - Alloced_length=str.Alloced_length; extra_alloc= 0; - alloced= thread_specific= 0; - str_charset=str.str_charset; +}; + + +/* + A storage for String. + Should be eventually derived from LEX_STRING. +*/ +class Static_binary_string +{ +protected: + char *Ptr; + uint32 str_length; +public: + Static_binary_string() + :Ptr(NULL), + str_length(0) + { } + Static_binary_string(char *str, size_t length_arg) + :Ptr(str), + str_length((uint32) length_arg) + { + DBUG_ASSERT(length_arg < UINT_MAX32); } + static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return (void*) alloc_root(mem_root, size); } static void *operator new[](size_t size, MEM_ROOT *mem_root) throw () @@ -193,50 +199,13 @@ public: static void operator delete[](void *, MEM_ROOT *) { /* never called */ } - ~String() { free(); } - - /* Mark variable thread specific it it's not allocated already */ - inline void set_thread_specific() - { - if (!alloced) - thread_specific= 1; - } - inline void set_charset(CHARSET_INFO *charset_arg) - { str_charset= charset_arg; } - inline CHARSET_INFO *charset() const { return str_charset; } inline uint32 length() const { return str_length;} - inline uint32 alloced_length() const { return Alloced_length;} - inline uint32 extra_allocation() const { return extra_alloc;} inline char& operator [] (size_t i) const { return Ptr[i]; } inline void length(size_t len) { str_length=(uint32)len ; } - inline void extra_allocation(size_t len) { extra_alloc= (uint32)len; } inline bool is_empty() const { return (str_length == 0); } - inline void mark_as_const() { Alloced_length= 0;} inline const char *ptr() const { return Ptr; } inline const char *end() const { return Ptr + str_length; } - inline char *c_ptr() - { - DBUG_ASSERT(!alloced || !Ptr || !Alloced_length || - (Alloced_length >= (str_length + 1))); - if (!Ptr || Ptr[str_length]) /* Should be safe */ - (void) realloc(str_length); - return Ptr; - } - inline char *c_ptr_quick() - { - if (Ptr && str_length < Alloced_length) - Ptr[str_length]=0; - return Ptr; - } - inline char *c_ptr_safe() - { - if (Ptr && str_length < Alloced_length) - Ptr[str_length]=0; - else - (void) realloc(str_length); - return Ptr; - } LEX_STRING lex_string() const { LEX_STRING str = { (char*) ptr(), length() }; @@ -248,77 +217,32 @@ public: return skr; } - void set(String &str,size_t offset,size_t arg_length) - { - DBUG_ASSERT(&str != this); - free(); - Ptr=(char*) str.ptr()+offset; str_length=(uint32)arg_length; - if (str.Alloced_length) - Alloced_length=(uint32)(str.Alloced_length-offset); - str_charset=str.str_charset; - } - - - /** - Points the internal buffer to the supplied one. The old buffer is freed. - @param str Pointer to the new buffer. - @param arg_length Length of the new buffer in characters, excluding any - null character. - @param cs Character set to use for interpreting string data. - @note The new buffer will not be null terminated. - */ - inline void set(char *str,size_t arg_length, CHARSET_INFO *cs) - { - free(); - Ptr=(char*) str; str_length=Alloced_length=(uint32)arg_length; - str_charset=cs; - } - inline void set(const char *str,size_t arg_length, CHARSET_INFO *cs) - { - free(); - Ptr=(char*) str; str_length=(uint32)arg_length; - str_charset=cs; - } - bool set_ascii(const char *str, size_t arg_length); - inline void set_quick(char *str,size_t arg_length, CHARSET_INFO *cs) + bool has_8bit_bytes() const { - if (!alloced) + for (const char *c= ptr(), *c_end= end(); c < c_end; c++) { - Ptr=(char*) str; str_length=Alloced_length=(uint32)arg_length; + if (!my_isascii(*c)) + return true; } - str_charset=cs; + return false; } - bool set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs); - bool set(int num, CHARSET_INFO *cs) { return set_int(num, false, cs); } - bool set(uint num, CHARSET_INFO *cs) { return set_int(num, true, cs); } - bool set(long num, CHARSET_INFO *cs) { return set_int(num, false, cs); } - bool set(ulong num, CHARSET_INFO *cs) { return set_int(num, true, cs); } - bool set(longlong num, CHARSET_INFO *cs) { return set_int(num, false, cs); } - bool set(ulonglong num, CHARSET_INFO *cs) { return set_int((longlong)num, true, cs); } - bool set_real(double num,uint decimals, CHARSET_INFO *cs); - bool set_hex(ulonglong num); - bool set_hex(const char *str, uint32 len); + bool bin_eq(const Static_binary_string *other) const + { + return length() == other->length() && + !memcmp(ptr(), other->ptr(), length()); + } - /* Take over handling of buffer from some other object */ - void reset(char *ptr_arg, size_t length_arg, size_t alloced_length_arg, - CHARSET_INFO *cs) - { - free(); - Ptr= ptr_arg; - str_length= (uint32)length_arg; - Alloced_length= (uint32)alloced_length_arg; - str_charset= cs; - alloced= ptr_arg != 0; + void set(char *str, size_t len) + { + Ptr= str; + str_length= (uint32) len; } - /* Forget about the buffer, let some other object handle it */ - char *release() + void swap(Static_binary_string &s) { - char *old= Ptr; - Ptr=0; str_length= Alloced_length= extra_alloc= 0; - alloced= thread_specific= 0; - return old; + swap_variables(char *, Ptr, s.Ptr); + swap_variables(uint32, str_length, s.str_length); } /* @@ -330,8 +254,8 @@ public: statement to be run on the remote server, and have a comma after each. When the list is complete, I "chop" off the trailing comma - ex. - String stringobj; + ex. + String stringobj; stringobj.append("VALUES ('foo', 'fi', 'fo',"); stringobj.chop(); stringobj.append(")"); @@ -341,7 +265,6 @@ public: VALUES ('foo', 'fi', 'fo', VALUES ('foo', 'fi', 'fo' VALUES ('foo', 'fi', 'fo') - */ inline void chop() { @@ -350,6 +273,329 @@ public: DBUG_ASSERT(strlen(Ptr) == str_length); } + // Returns offset to substring or -1 + int strstr(const Static_binary_string &search, uint32 offset=0); + // Returns offset to substring or -1 + int strrstr(const Static_binary_string &search, uint32 offset=0); + + /* + The following append operations do NOT check alloced memory + q_*** methods writes values of parameters itself + qs_*** methods writes string representation of value + */ + void q_append(const char c) + { + Ptr[str_length++] = c; + } + void q_append2b(const uint32 n) + { + int2store(Ptr + str_length, n); + str_length += 2; + } + void q_append(const uint32 n) + { + int4store(Ptr + str_length, n); + str_length += 4; + } + void q_append(double d) + { + float8store(Ptr + str_length, d); + str_length += 8; + } + void q_append(double *d) + { + float8store(Ptr + str_length, *d); + str_length += 8; + } + void q_append(const char *data, size_t data_len) + { + memcpy(Ptr + str_length, data, data_len); + DBUG_ASSERT(str_length <= UINT_MAX32 - data_len); + str_length += (uint)data_len; + } + void q_append(const LEX_CSTRING *ls) + { + DBUG_ASSERT(ls->length < UINT_MAX32 && + ((ls->length == 0 && !ls->str) || + ls->length == strlen(ls->str))); + q_append(ls->str, (uint32) ls->length); + } + + void write_at_position(int position, uint32 value) + { + int4store(Ptr + position,value); + } + + void qs_append(const char *str) + { + qs_append(str, (uint32)strlen(str)); + } + void qs_append(const LEX_CSTRING *ls) + { + DBUG_ASSERT(ls->length < UINT_MAX32 && + ((ls->length == 0 && !ls->str) || + ls->length == strlen(ls->str))); + qs_append(ls->str, (uint32)ls->length); + } + void qs_append(const char *str, size_t len); + void qs_append_hex(const char *str, uint32 len); + void qs_append(double d); + void qs_append(double *d); + inline void qs_append(const char c) + { + Ptr[str_length]= c; + str_length++; + } + void qs_append(int i); + void qs_append(uint i) + { + qs_append((ulonglong)i); + } + void qs_append(ulong i) + { + qs_append((ulonglong)i); + } + void qs_append(ulonglong i); + void qs_append(longlong i, int radix) + { + char *buff= Ptr + str_length; + char *end= ll2str(i, buff, radix, 0); + str_length+= uint32(end-buff); + } +}; + + +class Binary_string: public Static_binary_string +{ + uint32 Alloced_length, extra_alloc; + bool alloced, thread_specific; + void init_private_data() + { + Alloced_length= extra_alloc= 0; + alloced= thread_specific= false; + } +public: + Binary_string() + { + init_private_data(); + } + explicit Binary_string(size_t length_arg) + { + init_private_data(); + (void) real_alloc(length_arg); + } + explicit Binary_string(const char *str) + :Binary_string(str, strlen(str)) + { } + /* + NOTE: If one intend to use the c_ptr() method, the following two + contructors need the size of memory for STR to be at least LEN+1 (to make + room for zero termination). + */ + Binary_string(const char *str, size_t len) + :Static_binary_string((char *) str, len) + { + init_private_data(); + } + Binary_string(char *str, size_t len) + :Static_binary_string(str, len) + { + Alloced_length= (uint32) len; + extra_alloc= 0; + alloced= thread_specific= 0; + } + explicit Binary_string(const Binary_string &str) + :Static_binary_string(str) + { + Alloced_length= str.Alloced_length; + extra_alloc= 0; + alloced= thread_specific= 0; + } + + ~Binary_string() { free(); } + + /* Mark variable thread specific it it's not allocated already */ + inline void set_thread_specific() + { + if (!alloced) + thread_specific= 1; + } + bool is_alloced() const { return alloced; } + inline uint32 alloced_length() const { return Alloced_length;} + inline uint32 extra_allocation() const { return extra_alloc;} + inline void extra_allocation(size_t len) { extra_alloc= (uint32)len; } + inline void mark_as_const() { Alloced_length= 0;} + + inline bool uses_buffer_owned_by(const Binary_string *s) const + { + return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length); + } + + /* Swap two string objects. Efficient way to exchange data without memcpy. */ + void swap(Binary_string &s) + { + Static_binary_string::swap(s); + swap_variables(uint32, Alloced_length, s.Alloced_length); + swap_variables(bool, alloced, s.alloced); + } + + /** + Points the internal buffer to the supplied one. The old buffer is freed. + @param str Pointer to the new buffer. + @param arg_length Length of the new buffer in characters, excluding any + null character. + @note The new buffer will not be null terminated. + */ + void set_alloced(char *str, size_t length_arg, size_t alloced_length_arg) + { + free(); + Static_binary_string::set(str, length_arg); + DBUG_ASSERT(alloced_length_arg < UINT_MAX32); + Alloced_length= (uint32) alloced_length_arg; + } + inline void set(char *str, size_t arg_length) + { + set_alloced(str, arg_length, arg_length); + } + inline void set(const char *str, size_t arg_length) + { + free(); + Static_binary_string::set((char *) str, arg_length); + } + + void set(Binary_string &str, size_t offset, size_t arg_length) + { + DBUG_ASSERT(&str != this); + free(); + Static_binary_string::set((char*) str.ptr() + offset, arg_length); + if (str.Alloced_length) + Alloced_length= (uint32) (str.Alloced_length - offset); + } + + /* Take over handling of buffer from some other object */ + void reset(char *ptr_arg, size_t length_arg, size_t alloced_length_arg) + { + set_alloced(ptr_arg, length_arg, alloced_length_arg); + alloced= ptr_arg != 0; + } + + /* Forget about the buffer, let some other object handle it */ + char *release() + { + char *old= Ptr; + Static_binary_string::set(NULL, 0); + init_private_data(); + return old; + } + + inline void set_quick(char *str, size_t arg_length) + { + if (!alloced) + { + Static_binary_string::set(str, arg_length); + Alloced_length= (uint32) arg_length; + } + } + + inline Binary_string& operator=(const Binary_string &s) + { + if (&s != this) + { + /* + It is forbidden to do assignments like + some_string = substring_of_that_string + */ + DBUG_ASSERT(!s.uses_buffer_owned_by(this)); + set_alloced((char *) s.Ptr, s.str_length, s.Alloced_length); + } + return *this; + } + + bool set_hex(ulonglong num); + bool set_hex(const char *str, uint32 len); + + bool copy(); // Alloc string if not alloced + bool copy(const Binary_string &s); // Allocate new string + bool copy(const char *s, size_t arg_length); // Allocate new string + bool copy_or_move(const char *s,size_t arg_length); + + bool append_ulonglong(ulonglong val); + bool append_longlong(longlong val); + + bool append(const char *s, size_t size) + { + if (!size) + return false; + if (realloc_with_extra_if_needed(str_length + size)) + return true; + q_append(s, size); + return false; + } + bool append(const Binary_string &s) + { + return append(s.ptr(), s.length()); + } + bool append(IO_CACHE* file, uint32 arg_length); + + inline bool append_char(char chr) + { + if (str_length < Alloced_length) + { + Ptr[str_length++]= chr; + } + else + { + if (unlikely(realloc_with_extra(str_length + 1))) + return true; + Ptr[str_length++]= chr; + } + return false; + } + bool append_hex(const char *src, uint32 srclen) + { + for (const char *src_end= src + srclen ; src != src_end ; src++) + { + if (unlikely(append_char(_dig_vec_lower[((uchar) *src) >> 4])) || + unlikely(append_char(_dig_vec_lower[((uchar) *src) & 0x0F]))) + return true; + } + return false; + } + + bool append_with_step(const char *s, uint32 arg_length, uint32 step_alloc) + { + uint32 new_length= arg_length + str_length; + if (new_length > Alloced_length && + unlikely(realloc(new_length + step_alloc))) + return true; + q_append(s, arg_length); + return false; + } + + inline char *c_ptr() + { + DBUG_ASSERT(!alloced || !Ptr || !Alloced_length || + (Alloced_length >= (str_length + 1))); + + if (!Ptr || Ptr[str_length]) // Should be safe + (void) realloc(str_length); + return Ptr; + } + inline char *c_ptr_quick() + { + if (Ptr && str_length < Alloced_length) + Ptr[str_length]=0; + return Ptr; + } + inline char *c_ptr_safe() + { + if (Ptr && str_length < Alloced_length) + Ptr[str_length]=0; + else + (void) realloc(str_length); + return Ptr; + } + inline void free() { if (alloced) @@ -358,8 +604,7 @@ public: my_free(Ptr); } Alloced_length= extra_alloc= 0; - Ptr=0; - str_length=0; /* Safety */ + Static_binary_string::set(NULL, 0); // Safety } inline bool alloc(size_t arg_length) { @@ -367,13 +612,13 @@ public: return 0; return real_alloc(arg_length); } - bool real_alloc(size_t arg_length); // Empties old string + bool real_alloc(size_t arg_length); // Empties old string bool realloc_raw(size_t arg_length); bool realloc(size_t arg_length) { if (realloc_raw(arg_length)) return TRUE; - Ptr[arg_length]=0; // This make other funcs shorter + Ptr[arg_length]= 0; // This make other funcs shorter return FALSE; } bool realloc_with_extra(size_t arg_length) @@ -407,37 +652,179 @@ public: arg_length,MYF((thread_specific ? MY_THREAD_SPECIFIC : 0)))))) { - Alloced_length = 0; - real_alloc(arg_length); + Alloced_length= 0; + real_alloc(arg_length); } else { - Ptr=new_ptr; - Alloced_length=(uint32)arg_length; + Ptr= new_ptr; + Alloced_length= (uint32) arg_length; } } } - bool is_alloced() const { return alloced; } + void move(Binary_string &s) + { + set_alloced(s.Ptr, s.str_length, s.Alloced_length); + extra_alloc= s.extra_alloc; + alloced= s.alloced; + thread_specific= s.thread_specific; + s.alloced= 0; + } + bool fill(uint32 max_length,char fill); + /* + Replace substring with string + If wrong parameter or not enough memory, do nothing + */ + bool replace(uint32 offset,uint32 arg_length, const char *to, uint32 length); + bool replace(uint32 offset,uint32 arg_length, const Static_binary_string &to) + { + return replace(offset,arg_length,to.ptr(),to.length()); + } + + int reserve(size_t space_needed) + { + return realloc(str_length + space_needed); + } + int reserve(size_t space_needed, size_t grow_by); + + inline char *prep_append(uint32 arg_length, uint32 step_alloc) + { + uint32 new_length= arg_length + str_length; + if (new_length > Alloced_length) + { + if (unlikely(realloc(new_length + step_alloc))) + return 0; + } + uint32 old_length= str_length; + str_length+= arg_length; + return Ptr + old_length; // Area to use + } + + + void q_net_store_length(ulonglong length) + { + DBUG_ASSERT(Alloced_length >= (str_length + net_length_size(length))); + char *pos= (char *) net_store_length((uchar *)(Ptr + str_length), length); + str_length= uint32(pos - Ptr); + } + void q_net_store_data(const uchar *from, size_t length) + { + DBUG_ASSERT(length < UINT_MAX32); + DBUG_ASSERT(Alloced_length >= (str_length + length + + net_length_size(length))); + q_net_store_length(length); + q_append((const char *)from, (uint32) length); + } +}; + + +class String: public Charset, public Binary_string +{ +public: + String() { } + String(size_t length_arg) + :Binary_string(length_arg) + { } + String(const char *str, CHARSET_INFO *cs) + :Charset(cs), + Binary_string(str) + { } + /* + NOTE: If one intend to use the c_ptr() method, the following two + contructors need the size of memory for STR to be at least LEN+1 (to make + room for zero termination). + */ + String(const char *str, size_t len, CHARSET_INFO *cs) + :Charset(cs), + Binary_string((char *) str, len) + { } + String(char *str, size_t len, CHARSET_INFO *cs) + :Charset(cs), + Binary_string(str, len) + { } + String(const String &str) + :Charset(str), + Binary_string(str) + { } + + void set(String &str,size_t offset,size_t arg_length) + { + Binary_string::set(str, offset, arg_length); + set_charset(str); + } + inline void set(char *str,size_t arg_length, CHARSET_INFO *cs) + { + Binary_string::set(str, arg_length); + set_charset(cs); + } + inline void set(const char *str,size_t arg_length, CHARSET_INFO *cs) + { + Binary_string::set(str, arg_length); + set_charset(cs); + } + bool set_ascii(const char *str, size_t arg_length); + inline void set_quick(char *str,size_t arg_length, CHARSET_INFO *cs) + { + Binary_string::set_quick(str, arg_length); + set_charset(cs); + } + bool set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs); + bool set(int num, CHARSET_INFO *cs) { return set_int(num, false, cs); } + bool set(uint num, CHARSET_INFO *cs) { return set_int(num, true, cs); } + bool set(long num, CHARSET_INFO *cs) { return set_int(num, false, cs); } + bool set(ulong num, CHARSET_INFO *cs) { return set_int(num, true, cs); } + bool set(longlong num, CHARSET_INFO *cs) { return set_int(num, false, cs); } + bool set(ulonglong num, CHARSET_INFO *cs) { return set_int((longlong)num, true, cs); } + bool set_real(double num,uint decimals, CHARSET_INFO *cs); + + bool set_hex(ulonglong num) + { + set_charset(&my_charset_latin1); + return Binary_string::set_hex(num); + } + bool set_hex(const char *str, uint32 len) + { + set_charset(&my_charset_latin1); + return Binary_string::set_hex(str, len); + } + + /* Take over handling of buffer from some other object */ + void reset(char *ptr_arg, size_t length_arg, size_t alloced_length_arg, + CHARSET_INFO *cs) + { + Binary_string::reset(ptr_arg, length_arg, alloced_length_arg); + set_charset(cs); + } + inline String& operator = (const String &s) { if (&s != this) { - /* - It is forbidden to do assignments like - some_string = substring_of_that_string - */ - DBUG_ASSERT(!s.uses_buffer_owned_by(this)); - free(); - Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length; - str_charset=s.str_charset; + set_charset(s); + Binary_string::operator=(s); } return *this; } - bool copy(); // Alloc string if not alloced - bool copy(const String &s); // Allocate new string - bool copy(const char *s,size_t arg_length, CHARSET_INFO *cs); // Allocate new string - bool copy_or_move(const char *s,size_t arg_length, CHARSET_INFO *cs); + bool copy() + { + return Binary_string::copy(); + } + bool copy(const String &s) + { + set_charset(s); + return Binary_string::copy(s); + } + bool copy(const char *s, size_t arg_length, CHARSET_INFO *cs) + { + set_charset(cs); + return Binary_string::copy(s, arg_length); + } + bool copy_or_move(const char *s, size_t arg_length, CHARSET_INFO *cs) + { + set_charset(cs); + return Binary_string::copy_or_move(s, arg_length); + } static bool needs_conversion(size_t arg_length, CHARSET_INFO *cs_from, CHARSET_INFO *cs_to, uint32 *offset); @@ -459,206 +846,84 @@ public: { if (unlikely(alloc(tocs->mbmaxlen * src_length))) return true; - str_length= copier->well_formed_copy(tocs, Ptr, Alloced_length, + str_length= copier->well_formed_copy(tocs, Ptr, alloced_length(), fromcs, src, (uint)src_length, (uint)nchars); - str_charset= tocs; + set_charset(tocs); return false; } - void move(String &s) + // Append without character set conversion + bool append(const String &s) { - free(); - Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length; - extra_alloc= s.extra_alloc; - alloced= s.alloced; - thread_specific= s.thread_specific; - s.alloced= 0; - } - bool append(const String &s); - bool append(const char *s); - bool append(const LEX_STRING *ls) - { - DBUG_ASSERT(ls->length < UINT_MAX32 && - ((ls->length == 0 && !ls->str) || - ls->length == strlen(ls->str))); - return append(ls->str, (uint32) ls->length); - } - bool append(const LEX_CSTRING *ls) - { - DBUG_ASSERT(ls->length < UINT_MAX32 && - ((ls->length == 0 && !ls->str) || - ls->length == strlen(ls->str))); - return append(ls->str, (uint32) ls->length); + return Binary_string::append(s); } - bool append(const LEX_CSTRING &ls) - { - return append(&ls); - } - bool append(const char *s, size_t size); - bool append(const char *s, size_t arg_length, CHARSET_INFO *cs); - bool append_ulonglong(ulonglong val); - bool append_longlong(longlong val); - bool append(IO_CACHE* file, uint32 arg_length); - bool append_with_prefill(const char *s, uint32 arg_length, - uint32 full_length, char fill_char); - bool append_parenthesized(long nr, int radix= 10); - int strstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 - int strrstr(const String &search,uint32 offset=0); // Returns offset to substring or -1 - bool replace(uint32 offset,uint32 arg_length,const char *to,uint32 length); - bool replace(uint32 offset,uint32 arg_length,const String &to); inline bool append(char chr) { - if (str_length < Alloced_length) - { - Ptr[str_length++]=chr; - } - else - { - if (unlikely(realloc_with_extra(str_length + 1))) - return 1; - Ptr[str_length++]=chr; - } - return 0; + return Binary_string::append_char(chr); } bool append_hex(const char *src, uint32 srclen) { - for (const char *src_end= src + srclen ; src != src_end ; src++) - { - if (unlikely(append(_dig_vec_lower[((uchar) *src) >> 4])) || - unlikely(append(_dig_vec_lower[((uchar) *src) & 0x0F]))) - return true; - } - return false; + return Binary_string::append_hex(src, srclen); } bool append_hex(const uchar *src, uint32 srclen) { - return append_hex((const char*)src, srclen); - } - bool fill(uint32 max_length,char fill); - void strip_sp(); - friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); - friend int stringcmp(const String *a,const String *b); - friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); - friend class Field; - uint32 numchars() const; - int charpos(longlong i,uint32 offset=0); - - int reserve(size_t space_needed) - { - return realloc(str_length + space_needed); + return Binary_string::append_hex((const char*)src, srclen); } - int reserve(size_t space_needed, size_t grow_by); - - /* - The following append operations do NOT check alloced memory - q_*** methods writes values of parameters itself - qs_*** methods writes string representation of value - */ - void q_append(const char c) + bool append(IO_CACHE* file, uint32 arg_length) { - Ptr[str_length++] = c; + return Binary_string::append(file, arg_length); } - void q_append2b(const uint32 n) - { - int2store(Ptr + str_length, n); - str_length += 2; - } - void q_append(const uint32 n) - { - int4store(Ptr + str_length, n); - str_length += 4; - } - void q_append(double d) - { - float8store(Ptr + str_length, d); - str_length += 8; - } - void q_append(double *d) + inline bool append(const char *s, uint32 arg_length, uint32 step_alloc) { - float8store(Ptr + str_length, *d); - str_length += 8; + return append_with_step(s, arg_length, step_alloc); } - void q_append(const char *data, size_t data_len) + + // Append with optional character set conversion from ASCII (e.g. to UCS2) + bool append(const char *s) { - memcpy(Ptr + str_length, data, data_len); - DBUG_ASSERT(str_length <= UINT_MAX32 - data_len); - str_length += (uint)data_len; + return append(s, strlen(s)); } - void q_append(const LEX_CSTRING *ls) + bool append(const LEX_STRING *ls) { DBUG_ASSERT(ls->length < UINT_MAX32 && ((ls->length == 0 && !ls->str) || ls->length == strlen(ls->str))); - q_append(ls->str, (uint32) ls->length); - } - - void write_at_position(int position, uint32 value) - { - int4store(Ptr + position,value); - } - - void qs_append(const char *str) - { - qs_append(str, (uint32)strlen(str)); + return append(ls->str, (uint32) ls->length); } - void qs_append(const LEX_CSTRING *ls) + bool append(const LEX_CSTRING *ls) { DBUG_ASSERT(ls->length < UINT_MAX32 && ((ls->length == 0 && !ls->str) || ls->length == strlen(ls->str))); - qs_append(ls->str, (uint32)ls->length); - } - void qs_append(const char *str, size_t len); - void qs_append_hex(const char *str, uint32 len); - void qs_append(double d); - void qs_append(double *d); - inline void qs_append(const char c) - { - Ptr[str_length]= c; - str_length++; - } - void qs_append(int i); - void qs_append(uint i) - { - qs_append((ulonglong)i); - } - void qs_append(ulong i) - { - qs_append((ulonglong)i); + return append(ls->str, (uint32) ls->length); } - void qs_append(ulonglong i); - void qs_append(longlong i, int radix) + bool append(const LEX_CSTRING &ls) { - char *buff= Ptr + str_length; - char *end= ll2str(i, buff, radix, 0); - str_length+= uint32(end-buff); + return append(&ls); } + bool append(const char *s, size_t size); + bool append_with_prefill(const char *s, uint32 arg_length, + uint32 full_length, char fill_char); + bool append_parenthesized(long nr, int radix= 10); - /* Inline (general) functions used by the protocol functions */ + // Append with optional character set conversion from cs to charset() + bool append(const char *s, size_t arg_length, CHARSET_INFO *cs); - inline char *prep_append(uint32 arg_length, uint32 step_alloc) + void strip_sp(); + friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); + friend int stringcmp(const String *a,const String *b); + friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); + friend class Field; + uint32 numchars() const { - uint32 new_length= arg_length + str_length; - if (new_length > Alloced_length) - { - if (unlikely(realloc(new_length + step_alloc))) - return 0; - } - uint32 old_length= str_length; - str_length+= arg_length; - return Ptr+ old_length; /* Area to use */ + return (uint32) Charset::numchars(ptr(), end()); } - - - inline bool append(const char *s, uint32 arg_length, uint32 step_alloc) + int charpos(longlong i, uint32 offset=0) { - uint32 new_length= arg_length + str_length; - if (new_length > Alloced_length && - unlikely(realloc(new_length + step_alloc))) - return TRUE; - memcpy(Ptr+str_length, s, arg_length); - str_length+= arg_length; - return FALSE; + if (i <= 0) + return (int) i; + return (int) Charset::charpos(ptr() + offset, end(), (size_t) i); } + void print(String *to) const; void print_with_conversion(String *to, CHARSET_INFO *cs) const; void print(String *to, CHARSET_INFO *cs) const @@ -681,13 +946,12 @@ public: return append_for_single_quote(st, (uint32) len); } - /* Swap two string objects. Efficient way to exchange data without memcpy. */ - void swap(String &s); - - inline bool uses_buffer_owned_by(const String *s) const + void swap(String &s) { - return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length); + Charset::swap(s); + Binary_string::swap(s); } + uint well_formed_length() const { return (uint) Well_formed_prefix(charset(), ptr(), length()).length(); @@ -698,36 +962,12 @@ public: return TRUE; if (charset()->mbminlen > 1) return FALSE; - for (const char *c= ptr(), *c_end= c + length(); c < c_end; c++) - { - if (!my_isascii(*c)) - return FALSE; - } - return TRUE; - } - bool bin_eq(const String *other) const - { - return length() == other->length() && - !memcmp(ptr(), other->ptr(), length()); + return !has_8bit_bytes(); } bool eq(const String *other, CHARSET_INFO *cs) const { return !sortcmp(this, other, cs); } - void q_net_store_length(ulonglong length) - { - DBUG_ASSERT(Alloced_length >= (str_length + net_length_size(length))); - char *pos= (char *) net_store_length((uchar *)(Ptr + str_length), length); - str_length= uint32(pos - Ptr); - } - void q_net_store_data(const uchar *from, size_t length) - { - DBUG_ASSERT(length < UINT_MAX32); - DBUG_ASSERT(Alloced_length >= (str_length + length + - net_length_size(length))); - q_net_store_length(length); - q_append((const char *)from, (uint32) length); - } }; @@ -762,8 +1002,19 @@ public: }; +class String_space: public String +{ +public: + String_space(uint n) + { + if (fill(n, ' ')) + set("", 0, &my_charset_bin); + } +}; + + static inline bool check_if_only_end_space(CHARSET_INFO *cs, - const char *str, + const char *str, const char *end) { return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1bf88de5f5e..666c6fb325a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -33,7 +33,6 @@ // partition_info // NOT_A_PARTITION_ID #include "sql_db.h" // load_db_opt_by_name -#include "sql_time.h" // make_truncated_value_warning #include "records.h" // init_read_record, end_read_record #include "filesort.h" // filesort_free_buffers #include "sql_select.h" // setup_order @@ -2041,18 +2040,6 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists, if (!drop_temporary) { - if (!in_bootstrap) - { - for (table= tables; table; table= table->next_local) - { - LEX_CSTRING db_name= table->db; - LEX_CSTRING table_name= table->table_name; - if (table->open_type == OT_BASE_ONLY || - !thd->find_temporary_table(table)) - (void) delete_statistics_for_table(thd, &db_name, &table_name); - } - } - if (!thd->locked_tables_mode) { if (drop_sequence) @@ -2116,6 +2103,18 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists, } } } + /* We remove statistics for table last, after we have the DDL lock */ + if (!in_bootstrap) + { + for (table= tables; table; table= table->next_local) + { + LEX_CSTRING db_name= table->db; + LEX_CSTRING table_name= table->table_name; + if (table->open_type == OT_BASE_ONLY || + !thd->find_temporary_table(table)) + (void) delete_statistics_for_table(thd, &db_name, &table_name); + } + } } /* mark for close and remove all cached entries */ @@ -2128,7 +2127,6 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists, DBUG_RETURN(TRUE); my_ok(thd); DBUG_RETURN(FALSE); - } @@ -4133,10 +4131,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, key_info++; } - if (!unique_key && !primary_key && - ((file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY) || - ((file->ha_table_flags() & HA_WANTS_PRIMARY_KEY) && - !create_info->sequence))) + if (!unique_key && !primary_key && !create_info->sequence && + (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY)) { my_message(ER_REQUIRES_PRIMARY_KEY, ER_THD(thd, ER_REQUIRES_PRIMARY_KEY), MYF(0)); @@ -4248,11 +4244,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } /* Give warnings for not supported table options */ -#if defined(WITH_ARIA_STORAGE_ENGINE) extern handlerton *maria_hton; - if (file->partition_ht() != maria_hton) -#endif - if (create_info->transactional) + if (file->partition_ht() != maria_hton && create_info->transactional && + !file->has_transaction_manager()) push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, ER_THD(thd, ER_ILLEGAL_HA_CREATE_OPTION), @@ -4877,7 +4871,7 @@ int create_table_impl(THD *thd, /* Restart statement transactions for the case of CREATE ... SELECT. */ - if (thd->lex->select_lex.item_list.elements && + if (thd->lex->first_select_lex()->item_list.elements && restart_trans_for_tables(thd, thd->lex->query_tables)) goto err; } @@ -5548,12 +5542,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, properly isolated from all concurrent operations which matter. */ - /* Copy temporarily the statement flags to thd for lock_table_names() */ - // QQ: is this really needed??? - uint save_thd_create_info_options= thd->lex->create_info.options; - thd->lex->create_info.options|= create_info->options; - res= open_tables(thd, &thd->lex->query_tables, ¬_used, 0); - thd->lex->create_info.options= save_thd_create_info_options; + res= open_tables(thd, *create_info, &thd->lex->query_tables, ¬_used, 0); if (res) { @@ -7403,6 +7392,9 @@ static bool mysql_inplace_alter_table(THD *thd, DBUG_ENTER("mysql_inplace_alter_table"); + /* Downgrade DDL lock while we are waiting for exclusive lock below */ + backup_set_alter_copy_lock(thd, table); + /* Upgrade to EXCLUSIVE lock if: - This is requested by the storage engine @@ -7475,9 +7467,7 @@ static bool mysql_inplace_alter_table(THD *thd, thd->mdl_context.upgrade_shared_lock(table->mdl_ticket, MDL_SHARED_NO_WRITE, thd->variables.lock_wait_timeout)) - { goto cleanup; - } // It's now safe to take the table level lock. if (lock_tables(thd, table_list, alter_ctx->tables_opened, 0)) @@ -7514,9 +7504,7 @@ static bool mysql_inplace_alter_table(THD *thd, if (table->file->ha_prepare_inplace_alter_table(altered_table, ha_alter_info)) - { goto rollback; - } /* Downgrade the lock if storage engine has told us that exclusive lock was @@ -7558,6 +7546,10 @@ static bool mysql_inplace_alter_table(THD *thd, if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME)) goto rollback; + /* Set MDL_BACKUP_DDL */ + if (backup_reset_alter_copy_lock(thd)) + goto rollback; + /* If we are killed after this point, we should ignore and continue. We have mostly completed the operation at this point, there should @@ -7617,7 +7609,7 @@ static bool mysql_inplace_alter_table(THD *thd, Rename to the new name (if needed) will be handled separately below. TODO: remove this check of thd->is_error() (now it intercept - errors in some val_*() methoids and bring some single place to + errors in some val_*() methods and bring some single place to such error interception). */ if (mysql_rename_table(db_type, &alter_ctx->new_db, &alter_ctx->tmp_name, @@ -9089,6 +9081,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, uint tables_opened; thd->open_options|= HA_OPEN_FOR_ALTER; + thd->mdl_backup_ticket= 0; bool error= open_tables(thd, &table_list, &tables_opened, 0, &alter_prelocking_strategy); thd->open_options&= ~HA_OPEN_FOR_ALTER; @@ -9196,12 +9189,12 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, } /* - Global intention exclusive lock must have been already acquired when - table to be altered was open, so there is no need to do it here. + Protection against global read lock must have been acquired when table + to be altered was being opened. */ - DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, + DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::BACKUP, "", "", - MDL_INTENTION_EXCLUSIVE)); + MDL_BACKUP_DDL)); if (thd->mdl_context.acquire_locks(&mdl_requests, thd->variables.lock_wait_timeout)) @@ -9545,8 +9538,6 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, } DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock"); - /* We can abort alter table for any table type */ - thd->abort_on_warning= !ignore && thd->is_strict_mode(); /* Create .FRM for new version of table with a temporary name. @@ -9576,7 +9567,6 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, C_ALTER_TABLE_FRM_ONLY, NULL, &key_info, &key_count, &frm); reenable_binlog(thd); - thd->abort_on_warning= false; if (unlikely(error)) { my_free(const_cast<uchar*>(frm.str)); @@ -10094,19 +10084,17 @@ err_new_table_cleanup: if (unlikely(alter_ctx.error_if_not_empty && thd->get_stmt_da()->current_row_for_warning())) { - const char *f_val= 0; - enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE; + const char *f_val= "0000-00-00"; + const char *f_type= "date"; switch (alter_ctx.datetime_field->real_field_type()) { case MYSQL_TYPE_DATE: case MYSQL_TYPE_NEWDATE: - f_val= "0000-00-00"; - t_type= MYSQL_TIMESTAMP_DATE; break; case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_DATETIME2: f_val= "0000-00-00 00:00:00"; - t_type= MYSQL_TIMESTAMP_DATETIME; + f_type= "datetime"; break; default: /* Shouldn't get here. */ @@ -10114,10 +10102,11 @@ err_new_table_cleanup: } bool save_abort_on_warning= thd->abort_on_warning; thd->abort_on_warning= true; - make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN, - f_val, strlength(f_val), t_type, - new_table->s, - alter_ctx.datetime_field->field_name.str); + thd->push_warning_truncated_value_for_field(Sql_condition::WARN_LEVEL_WARN, + f_type, f_val, + new_table->s, + alter_ctx.datetime_field-> + field_name.str); thd->abort_on_warning= save_abort_on_warning; } @@ -10254,12 +10243,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, DBUG_RETURN(-1); } + backup_set_alter_copy_lock(thd, from); + alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff); - /* Set read map for all fields in from table */ from->default_column_bitmaps(); - bitmap_set_all(from->read_set); - from->file->column_bitmaps_signal(); /* We can abort alter table for any table type */ thd->abort_on_warning= !ignore && thd->is_strict_mode(); @@ -10289,7 +10277,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, if (def->field == from->found_next_number_field) thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO; } - (copy_end++)->set(*ptr,def->field,0); + if (!(*ptr)->vcol_info) + { + bitmap_set_bit(from->read_set, def->field->field_index); + (copy_end++)->set(*ptr,def->field,0); + } } else { @@ -10332,8 +10324,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, Filesort_tracker dummy_tracker(false); Filesort fsort(order, HA_POS_ERROR, true, NULL); - if (thd->lex->select_lex.setup_ref_array(thd, order_num) || - setup_order(thd, thd->lex->select_lex.ref_pointer_array, + if (thd->lex->first_select_lex()->setup_ref_array(thd, order_num) || + setup_order(thd, thd->lex->first_select_lex()->ref_pointer_array, &tables, fields, all_fields, order)) goto err; @@ -10358,6 +10350,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, from_row_end= from->vers_end_field(); } + if (from_row_end) + bitmap_set_bit(from->read_set, from_row_end->field_index); + + from->file->column_bitmaps_signal(); + THD_STAGE_INFO(thd, stage_copy_to_tmp_table); /* Tell handler that we have values for all columns in the to table */ to->use_all_columns(); @@ -10529,6 +10526,9 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, cleanup_done= 1; to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + if (backup_reset_alter_copy_lock(thd)) + error= 1; + if (unlikely(mysql_trans_commit_alter_copy_data(thd))) error= 1; @@ -10547,7 +10547,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, if (!cleanup_done) { - /* This happens if we get an error during initialzation of data */ + /* This happens if we get an error during initialization of data */ DBUG_ASSERT(error); to->file->ha_end_bulk_insert(); ha_enable_transaction(thd, TRUE); @@ -10707,7 +10707,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, ha_checksum crc= 0; uchar null_mask=256 - (1 << t->s->last_null_bit_pos); - t->use_all_columns(); + t->use_all_stored_columns(); if (t->file->ha_rnd_init(1)) protocol->store_null(); diff --git a/sql/sql_time.cc b/sql/sql_time.cc index 739a95ce9c8..fea23020d7e 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -175,7 +175,7 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week) next week is week 1. */ -uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year) +uint calc_week(const MYSQL_TIME *l_time, uint week_behaviour, uint *year) { uint days; ulong daynr=calc_daynr(l_time->year,l_time->month,l_time->day); @@ -289,14 +289,14 @@ ulong convert_month_to_period(ulong month) bool -check_date_with_warn(const MYSQL_TIME *ltime, ulonglong fuzzy_date, - timestamp_type ts_type) +check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, + date_conv_mode_t fuzzydate, timestamp_type ts_type) { int unused; - if (check_date(ltime, fuzzy_date, &unused)) + if (check_date(ltime, fuzzydate, &unused)) { ErrConvTime str(ltime); - make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, + make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN, &str, ts_type, 0, 0); return true; } @@ -305,7 +305,7 @@ check_date_with_warn(const MYSQL_TIME *ltime, ulonglong fuzzy_date, bool -adjust_time_range_with_warn(MYSQL_TIME *ltime, uint dec) +adjust_time_range_with_warn(THD *thd, MYSQL_TIME *ltime, uint dec) { MYSQL_TIME copy= *ltime; ErrConvTime str(©); @@ -313,8 +313,7 @@ adjust_time_range_with_warn(MYSQL_TIME *ltime, uint dec) if (check_time_range(ltime, dec, &warnings)) return true; if (warnings) - make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, - &str, MYSQL_TIMESTAMP_TIME, 0, NullS); + thd->push_warning_truncated_wrong_value("time", str.ptr()); return false; } @@ -352,33 +351,70 @@ to_ascii(CHARSET_INFO *cs, } -/* Character set-aware version of str_to_time() */ -bool -str_to_time(CHARSET_INFO *cs, const char *str, size_t length, - MYSQL_TIME *l_time, ulonglong fuzzydate, MYSQL_TIME_STATUS *status) +class TemporalAsciiBuffer: public LEX_CSTRING { char cnv[32]; - if ((cs->state & MY_CS_NONASCII) != 0) +public: + TemporalAsciiBuffer(const char *str, size_t length, CHARSET_INFO *cs) { - length= to_ascii(cs, str, length, cnv, sizeof(cnv)); - str= cnv; + if ((cs->state & MY_CS_NONASCII) != 0) + { + LEX_CSTRING::str= cnv; + LEX_CSTRING::length= to_ascii(cs, str, length, cnv, sizeof(cnv)); + } + else + { + LEX_CSTRING::str= str; + LEX_CSTRING::length= length; + } } - return str_to_time(str, length, l_time, fuzzydate, status); +}; + + +/* Character set-aware version of ascii_to_datetime_or_date_or_time() */ +bool Temporal::str_to_datetime_or_date_or_time(THD *thd, MYSQL_TIME_STATUS *st, + const char *str, size_t length, + CHARSET_INFO *cs, + date_mode_t fuzzydate) +{ + TemporalAsciiBuffer tmp(str, length, cs); + return ascii_to_datetime_or_date_or_time(st, tmp.str, tmp.length, fuzzydate)|| + add_nanoseconds(thd, &st->warnings, fuzzydate, st->nanoseconds); } -/* Character set-aware version of str_to_datetime() */ -bool str_to_datetime(CHARSET_INFO *cs, const char *str, size_t length, - MYSQL_TIME *l_time, ulonglong flags, - MYSQL_TIME_STATUS *status) +/* Character set-aware version of str_to_datetime_or_date() */ +bool Temporal::str_to_datetime_or_date(THD *thd, MYSQL_TIME_STATUS *status, + const char *str, size_t length, + CHARSET_INFO *cs, + date_mode_t flags) { - char cnv[32]; - if ((cs->state & MY_CS_NONASCII) != 0) - { - length= to_ascii(cs, str, length, cnv, sizeof(cnv)); - str= cnv; - } - return str_to_datetime(str, length, l_time, flags, status); + TemporalAsciiBuffer tmp(str, length, cs); + return ascii_to_datetime_or_date(status, tmp.str, tmp.length, flags) || + add_nanoseconds(thd, &status->warnings, flags, status->nanoseconds); +} + + +/* Character set-aware version of ascii_to_temporal() */ +bool Temporal::str_to_temporal(THD *thd, MYSQL_TIME_STATUS *status, + const char *str, size_t length, CHARSET_INFO *cs, + date_mode_t flags) +{ + TemporalAsciiBuffer tmp(str, length, cs); + return ascii_to_temporal(status, tmp.str, tmp.length, flags) || + add_nanoseconds(thd, &status->warnings, flags, status->nanoseconds); +} + + +/* Character set-aware version of str_to_DDhhmmssff() */ +bool Interval_DDhhmmssff::str_to_DDhhmmssff(MYSQL_TIME_STATUS *status, + const char *str, size_t length, + CHARSET_INFO *cs, ulong max_hour) +{ + TemporalAsciiBuffer tmp(str, length, cs); + bool rc= ::str_to_DDhhmmssff(tmp.str, tmp.length, this, UINT_MAX32, status); + DBUG_ASSERT(status->warnings || !rc); + return rc; } @@ -387,125 +423,53 @@ bool str_to_datetime(CHARSET_INFO *cs, const char *str, size_t length, if string was truncated during conversion. NOTE - See description of str_to_datetime() for more information. + See description of str_to_datetime_xxx() for more information. */ bool -str_to_datetime_with_warn(CHARSET_INFO *cs, - const char *str, size_t length, MYSQL_TIME *l_time, - ulonglong flags) +str_to_datetime_with_warn(THD *thd, CHARSET_INFO *cs, + const char *str, size_t length, MYSQL_TIME *to, + date_mode_t mode) { - MYSQL_TIME_STATUS status; - THD *thd= current_thd; - bool ret_val= str_to_datetime(cs, str, length, l_time, flags, &status); - if (ret_val || status.warnings) - make_truncated_value_warning(thd, - ret_val ? Sql_condition::WARN_LEVEL_WARN : - Sql_condition::time_warn_level(status.warnings), - str, length, flags & TIME_TIME_ONLY ? - MYSQL_TIMESTAMP_TIME : l_time->time_type, 0, NullS); - DBUG_EXECUTE_IF("str_to_datetime_warn", - push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_YES, str);); - return ret_val; + Temporal::Warn_push warn(thd, NULL, NullS, to, mode); + Temporal_hybrid *t= new(to) Temporal_hybrid(thd, &warn, str, length, cs, mode); + return !t->is_valid_temporal(); } -/** - converts a pair of numbers (integer part, microseconds) to MYSQL_TIME - - @param neg sign of the time value - @param nr integer part of the number to convert - @param sec_part microsecond part of the number - @param ltime converted value will be written here - @param fuzzydate conversion flags (TIME_INVALID_DATE, etc) - @param str original number, as an ErrConv. For the warning - @param field_name field name or NULL if not a field. For the warning - - @returns 0 for success, 1 for a failure -*/ -static bool number_to_time_with_warn(bool neg, ulonglong nr, ulong sec_part, - MYSQL_TIME *ltime, ulonglong fuzzydate, - const ErrConv *str, - const TABLE_SHARE *s, const char *field_name) -{ - int was_cut; - longlong res; - enum_mysql_timestamp_type ts_type; - bool have_warnings; - - if (fuzzydate & TIME_TIME_ONLY) - { - fuzzydate= TIME_TIME_ONLY; // clear other flags - ts_type= MYSQL_TIMESTAMP_TIME; - res= number_to_time(neg, nr, sec_part, ltime, &was_cut); - have_warnings= MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut); - } - else - { - ts_type= MYSQL_TIMESTAMP_DATETIME; - if (neg) - { - res= -1; - } - else - { - res= number_to_datetime(nr, sec_part, ltime, fuzzydate, &was_cut); - have_warnings= was_cut && (fuzzydate & TIME_NO_ZERO_IN_DATE); - } - } - - if (res < 0 || have_warnings) - { - make_truncated_value_warning(current_thd, - Sql_condition::WARN_LEVEL_WARN, str, - res < 0 ? MYSQL_TIMESTAMP_ERROR : ts_type, - s, field_name); - } - return res < 0; -} - - -bool double_to_datetime_with_warn(double value, MYSQL_TIME *ltime, - ulonglong fuzzydate, +bool double_to_datetime_with_warn(THD *thd, double value, MYSQL_TIME *ltime, + date_mode_t fuzzydate, const TABLE_SHARE *s, const char *field_name) { - const ErrConvDouble str(value); - bool neg= value < 0; - - if (neg) - value= -value; - - if (value > LONGLONG_MAX) - value= static_cast<double>(LONGLONG_MAX); - - longlong nr= static_cast<ulonglong>(floor(value)); - uint sec_part= static_cast<ulong>((value - floor(value))*TIME_SECOND_PART_FACTOR); - return number_to_time_with_warn(neg, nr, sec_part, ltime, fuzzydate, &str, - s, field_name); + Temporal::Warn_push warn(thd, s, field_name, ltime, fuzzydate); + Temporal_hybrid *t= new (ltime) Temporal_hybrid(thd, &warn, value, fuzzydate); + return !t->is_valid_temporal(); } -bool decimal_to_datetime_with_warn(const my_decimal *value, MYSQL_TIME *ltime, - ulonglong fuzzydate, +bool decimal_to_datetime_with_warn(THD *thd, const my_decimal *value, + MYSQL_TIME *ltime, + date_mode_t fuzzydate, const TABLE_SHARE *s, const char *field_name) { - const ErrConvDecimal str(value); - ulonglong nr; - ulong sec_part; - bool neg= my_decimal2seconds(value, &nr, &sec_part); - return number_to_time_with_warn(neg, nr, sec_part, ltime, fuzzydate, &str, - s, field_name); + Temporal::Warn_push warn(thd, s, field_name, ltime, fuzzydate); + Temporal_hybrid *t= new (ltime) Temporal_hybrid(thd, &warn, value, fuzzydate); + return !t->is_valid_temporal(); } -bool int_to_datetime_with_warn(bool neg, ulonglong value, MYSQL_TIME *ltime, - ulonglong fuzzydate, +bool int_to_datetime_with_warn(THD *thd, const Longlong_hybrid &nr, + MYSQL_TIME *ltime, + date_mode_t fuzzydate, const TABLE_SHARE *s, const char *field_name) { - const ErrConvInteger str(neg ? - (longlong) value : (longlong) value, !neg); - return number_to_time_with_warn(neg, value, 0, ltime, - fuzzydate, &str, s, field_name); + /* + Note: conversion from an integer to TIME can overflow to '838:59:59.999999', + so the conversion result can have fractional digits. + */ + Temporal::Warn_push warn(thd, s, field_name, ltime, fuzzydate); + Temporal_hybrid *t= new (ltime) Temporal_hybrid(thd, &warn, nr, fuzzydate); + return !t->is_valid_temporal(); } @@ -552,7 +516,7 @@ void localtime_to_TIME(MYSQL_TIME *to, struct tm *from) } -void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds) +void calc_time_from_sec(MYSQL_TIME *to, ulong seconds, ulong microseconds) { long t_seconds; // to->neg is not cleared, it may already be set to a useful value @@ -935,50 +899,10 @@ void make_truncated_value_warning(THD *thd, timestamp_type time_type, const TABLE_SHARE *s, const char *field_name) { - char warn_buff[MYSQL_ERRMSG_SIZE]; - const char *type_str; - CHARSET_INFO *cs= &my_charset_latin1; - - switch (time_type) { - case MYSQL_TIMESTAMP_DATE: - type_str= "date"; - break; - case MYSQL_TIMESTAMP_TIME: - type_str= "time"; - break; - case MYSQL_TIMESTAMP_DATETIME: // FALLTHROUGH - default: - type_str= "datetime"; - break; - } - if (field_name) - { - const char *db_name= s->db.str; - const char *table_name= s->error_table_name(); - - if (!db_name) - db_name= ""; - if (!table_name) - table_name= ""; - - cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff), - ER_THD(thd, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - type_str, sval->ptr(), - db_name, table_name, field_name, - (ulong) thd->get_stmt_da()->current_row_for_warning()); - } - else - { - if (time_type > MYSQL_TIMESTAMP_ERROR) - cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff), - ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), - type_str, sval->ptr()); - else - cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff), - ER_THD(thd, ER_WRONG_VALUE), type_str, sval->ptr()); - } - push_warning(thd, level, - ER_TRUNCATED_WRONG_VALUE, warn_buff); + const char *type_str= Temporal::type_name_by_timestamp_type(time_type); + return thd->push_warning_wrong_or_truncated_value + (level, time_type <= MYSQL_TIMESTAMP_ERROR, type_str, sval->ptr(), + s, field_name); } @@ -989,7 +913,7 @@ void make_truncated_value_warning(THD *thd, (X)->second_part) #define GET_PART(X, N) X % N ## LL; X/= N ## LL -bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, +bool date_add_interval(THD *thd, MYSQL_TIME *ltime, interval_type int_type, const INTERVAL &interval) { long period, sign; @@ -1104,7 +1028,6 @@ bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, invalid_date: { - THD *thd= current_thd; push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_DATETIME_FUNCTION_OVERFLOW, ER_THD(thd, ER_DATETIME_FUNCTION_OVERFLOW), @@ -1144,7 +1067,7 @@ null_date: bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, - int l_sign, longlong *seconds_out, long *microseconds_out) + int l_sign, ulonglong *seconds_out, ulong *microseconds_out) { long days; bool neg; @@ -1171,10 +1094,10 @@ calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, } microseconds= ((longlong)days * SECONDS_IN_24H + - (longlong)(l_time1->hour*3600L + + (longlong)(l_time1->hour*3600LL + l_time1->minute*60L + l_time1->second) - - l_sign*(longlong)(l_time2->hour*3600L + + l_sign*(longlong)(l_time2->hour*3600LL + l_time2->minute*60L + l_time2->second)) * 1000000LL + (longlong)l_time1->second_part - @@ -1186,17 +1109,17 @@ calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, microseconds= -microseconds; neg= 1; } - *seconds_out= microseconds/1000000L; - *microseconds_out= (long) (microseconds%1000000L); + *seconds_out= (ulonglong) microseconds/1000000L; + *microseconds_out= (ulong) (microseconds%1000000L); return neg; } bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, - int l_sign, MYSQL_TIME *l_time3, ulonglong fuzzydate) + int l_sign, MYSQL_TIME *l_time3, date_mode_t fuzzydate) { - longlong seconds; - long microseconds; + ulonglong seconds; + ulong microseconds; bzero((char *) l_time3, sizeof(*l_time3)); l_time3->neg= calc_time_diff(l_time1, l_time2, l_sign, &seconds, µseconds); @@ -1215,7 +1138,7 @@ bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, ("invalid" means > TIME_MAX_SECOND) */ set_if_smaller(seconds, INT_MAX32); - calc_time_from_sec(l_time3, (long) seconds, microseconds); + calc_time_from_sec(l_time3, (ulong) seconds, microseconds); return ((fuzzydate & TIME_NO_ZERO_DATE) && (seconds == 0) && (microseconds == 0)); } @@ -1272,56 +1195,6 @@ bool time_to_datetime(MYSQL_TIME *ltime) } -/** - Return a valid DATE or DATETIME value from an arbitrary MYSQL_TIME. - If ltime is TIME, it's first converted to DATETIME. - If ts_type is DATE, hhmmss is set to zero. - The date part of the result is checked against fuzzy_date. - - @param ltime The value to convert. - @param fuzzy_date Flags to check date. - @param ts_type The type to convert to. - @return false on success, true of error (negative time).*/ -bool -make_date_with_warn(MYSQL_TIME *ltime, ulonglong fuzzy_date, - timestamp_type ts_type) -{ - DBUG_ASSERT(ts_type == MYSQL_TIMESTAMP_DATE || - ts_type == MYSQL_TIMESTAMP_DATETIME); - if (ltime->time_type == MYSQL_TIMESTAMP_TIME && time_to_datetime(ltime)) - { - /* e.g. negative time */ - ErrConvTime str(ltime); - make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, - &str, ts_type, 0, 0); - return true; - } - if ((ltime->time_type= ts_type) == MYSQL_TIMESTAMP_DATE) - ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0; - return check_date_with_warn(ltime, fuzzy_date, ts_type); -} - - -/* - Convert a TIME value to DAY-TIME interval, e.g. for extraction: - EXTRACT(DAY FROM x), EXTRACT(HOUR FROM x), etc. - Moves full days from ltime->hour to ltime->day. - Note, time_type is set to MYSQL_TIMESTAMP_NONE, to make sure that - the structure is not used for anything else other than extraction: - non-extraction TIME functions expect zero day value! -*/ -void time_to_daytime_interval(MYSQL_TIME *ltime) -{ - DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_TIME); - DBUG_ASSERT(ltime->year == 0); - DBUG_ASSERT(ltime->month == 0); - DBUG_ASSERT(ltime->day == 0); - ltime->day= ltime->hour / 24; - ltime->hour%= 24; - ltime->time_type= MYSQL_TIMESTAMP_NONE; -} - - /*** Conversion from TIME to DATETIME ***/ /* @@ -1349,8 +1222,8 @@ mix_date_and_time_complex(MYSQL_TIME *ldate, const MYSQL_TIME *ltime) { DBUG_ASSERT(ldate->time_type == MYSQL_TIMESTAMP_DATE || ldate->time_type == MYSQL_TIMESTAMP_DATETIME); - longlong seconds; - long days, useconds; + ulonglong seconds; + ulong days, useconds; int sign= ltime->neg ? 1 : -1; ldate->neg= calc_time_diff(ldate, ltime, sign, &seconds, &useconds); @@ -1440,7 +1313,7 @@ time_to_datetime(THD *thd, const MYSQL_TIME *from, MYSQL_TIME *to) bool time_to_datetime_with_warn(THD *thd, const MYSQL_TIME *from, MYSQL_TIME *to, - ulonglong fuzzydate) + date_conv_mode_t fuzzydate) { int warn= 0; DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_TIME); @@ -1456,34 +1329,13 @@ time_to_datetime_with_warn(THD *thd, check_date(to, fuzzydate, &warn))) { ErrConvTime str(from); - make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN, - &str, MYSQL_TIMESTAMP_DATETIME, 0, 0); + thd->push_warning_truncated_wrong_value("datetime", str.ptr()); return true; } return false; } -bool datetime_to_time_with_warn(THD *thd, const MYSQL_TIME *dt, - MYSQL_TIME *tm, uint dec) -{ - if (thd->variables.old_behavior & OLD_MODE_ZERO_DATE_TIME_CAST) - { - *tm= *dt; - datetime_to_time(tm); - return false; - } - else /* new mode */ - { - MYSQL_TIME current_date; - set_current_date(thd, ¤t_date); - calc_time_diff(dt, ¤t_date, 1, tm, 0); - } - int warnings= 0; - return check_time_range(tm, dec, &warnings); -} - - longlong pack_time(const MYSQL_TIME *my_time) { return ((((((my_time->year * 13ULL + diff --git a/sql/sql_time.h b/sql/sql_time.h index ca9f79273ec..161d08c80b8 100644 --- a/sql/sql_time.h +++ b/sql/sql_time.h @@ -17,6 +17,7 @@ #ifndef SQL_TIME_INCLUDED #define SQL_TIME_INCLUDED +#include "sql_basic_types.h" #include "my_time.h" #include "mysql_time.h" /* timestamp_type */ #include "sql_error.h" /* Sql_condition */ @@ -35,69 +36,28 @@ ulong convert_period_to_month(ulong period); ulong convert_month_to_period(ulong month); void set_current_date(THD *thd, MYSQL_TIME *to); bool time_to_datetime(MYSQL_TIME *ltime); -void time_to_daytime_interval(MYSQL_TIME *l_time); bool get_date_from_daynr(long daynr,uint *year, uint *month, uint *day); my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, uint *error_code); -bool str_to_datetime_with_warn(CHARSET_INFO *cs, const char *str, size_t length, MYSQL_TIME *l_time, - ulonglong flags); -bool double_to_datetime_with_warn(double value, MYSQL_TIME *ltime, - ulonglong fuzzydate, +bool str_to_datetime_with_warn(THD *thd, + CHARSET_INFO *cs, const char *str, size_t length, + MYSQL_TIME *l_time, + date_mode_t flags); +bool double_to_datetime_with_warn(THD *thd, double value, MYSQL_TIME *ltime, + date_mode_t fuzzydate, const TABLE_SHARE *s, const char *name); -bool decimal_to_datetime_with_warn(const my_decimal *value, MYSQL_TIME *ltime, - ulonglong fuzzydate, +bool decimal_to_datetime_with_warn(THD *thd, + const my_decimal *value, MYSQL_TIME *ltime, + date_mode_t fuzzydate, const TABLE_SHARE *s, const char *name); -bool int_to_datetime_with_warn(bool neg, ulonglong value, MYSQL_TIME *ltime, - ulonglong fuzzydate, +bool int_to_datetime_with_warn(THD *thd, const Longlong_hybrid &nr, + MYSQL_TIME *ltime, + date_mode_t fuzzydate, const TABLE_SHARE *s, const char *name); bool time_to_datetime(THD *thd, const MYSQL_TIME *tm, MYSQL_TIME *dt); bool time_to_datetime_with_warn(THD *thd, const MYSQL_TIME *tm, MYSQL_TIME *dt, - ulonglong fuzzydate); -/* - Simply truncate the YYYY-MM-DD part to 0000-00-00 - and change time_type to MYSQL_TIMESTAMP_TIME -*/ -inline void datetime_to_time(MYSQL_TIME *ltime) -{ - DBUG_ASSERT(ltime->time_type == MYSQL_TIMESTAMP_DATE || - ltime->time_type == MYSQL_TIMESTAMP_DATETIME); - DBUG_ASSERT(ltime->neg == 0); - ltime->year= ltime->month= ltime->day= 0; - ltime->time_type= MYSQL_TIMESTAMP_TIME; -} - - -/** - Convert DATE/DATETIME to TIME(dec) - using CURRENT_DATE in a non-old mode, - or using simple truncation in old mode (OLD_MODE_ZERO_DATE_TIME_CAST). - - @param thd - the thread to get the variables.old_behaviour value from - @param dt - the DATE of DATETIME value to convert - @param[out] tm - store result here - @param dec - the desired scale. The fractional part of the result - is checked according to this parameter before returning - the conversion result. "dec" is important in the corner - cases near the max/min limits. - If the result is '838:59:59.999999' and the desired scale - is less than 6, an error is returned. - Note, dec is not important in the - OLD_MODE_ZERO_DATE_TIME_CAST old mode. - - - in case of OLD_MODE_ZERO_DATE_TIME_CAST - the TIME part is simply truncated and "false" is returned. - - otherwise, the result is calculated effectively similar to: - TIMEDIFF(dt, CAST(CURRENT_DATE AS DATETIME)) - If the difference fits into the supported TIME range, "false" is returned, - otherwise a warning is issued and "true" is returned. - - @return false - on success - @return true - on error -*/ -bool datetime_to_time_with_warn(THD *, const MYSQL_TIME *dt, - MYSQL_TIME *tm, uint dec); - + date_conv_mode_t fuzzydate); inline void datetime_to_date(MYSQL_TIME *ltime) { @@ -118,16 +78,8 @@ void make_truncated_value_warning(THD *thd, Sql_condition::enum_warning_level level, const ErrConv *str_val, timestamp_type time_type, - const TABLE_SHARE *s, const char *field_name); - -static inline void make_truncated_value_warning(THD *thd, - Sql_condition::enum_warning_level level, const char *str_val, - size_t str_length, timestamp_type time_type, - const TABLE_SHARE *s, const char *field_name) -{ - const ErrConvString str(str_val, str_length, &my_charset_bin); - make_truncated_value_warning(thd, level, &str, time_type, s, field_name); -} + const TABLE_SHARE *s, + const char *field_name); extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type, const char *format_str, @@ -139,10 +91,10 @@ const char *get_date_time_format_str(KNOWN_DATE_TIME_FORMAT *format, bool my_TIME_to_str(const MYSQL_TIME *ltime, String *str, uint dec); /* MYSQL_TIME operations */ -bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, +bool date_add_interval(THD *thd, MYSQL_TIME *ltime, interval_type int_type, const INTERVAL &interval); bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, - int l_sign, longlong *seconds_out, long *microseconds_out); + int l_sign, ulonglong *seconds_out, ulong *microseconds_out); int append_interval(String *str, interval_type int_type, const INTERVAL &interval); /** @@ -168,26 +120,17 @@ int append_interval(String *str, interval_type int_type, @return false - otherwise */ bool calc_time_diff(const MYSQL_TIME *l_time1, const MYSQL_TIME *l_time2, - int lsign, MYSQL_TIME *l_time3, ulonglong fuzzydate); + int lsign, MYSQL_TIME *l_time3, date_mode_t fuzzydate); int my_time_compare(const MYSQL_TIME *a, const MYSQL_TIME *b); void localtime_to_TIME(MYSQL_TIME *to, struct tm *from); -void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds); -uint calc_week(MYSQL_TIME *l_time, uint week_behaviour, uint *year); +void calc_time_from_sec(MYSQL_TIME *to, ulong seconds, ulong microseconds); +uint calc_week(const MYSQL_TIME *l_time, uint week_behaviour, uint *year); int calc_weekday(long daynr,bool sunday_first_day_of_week); bool parse_date_time_format(timestamp_type format_type, const char *format, uint format_length, DATE_TIME_FORMAT *date_time_format); -/* Character set-aware version of str_to_time() */ -bool str_to_time(CHARSET_INFO *cs, const char *str,size_t length, - MYSQL_TIME *l_time, ulonglong fuzzydate, - MYSQL_TIME_STATUS *status); -/* Character set-aware version of str_to_datetime() */ -bool str_to_datetime(CHARSET_INFO *cs, - const char *str, size_t length, - MYSQL_TIME *l_time, ulonglong flags, - MYSQL_TIME_STATUS *status); /* convenience wrapper */ inline bool parse_date_time_format(timestamp_type format_type, @@ -224,15 +167,21 @@ non_zero_date(const MYSQL_TIME *ltime) non_zero_hhmmssuu(ltime)); } static inline bool -check_date(const MYSQL_TIME *ltime, ulonglong flags, int *was_cut) +check_date(const MYSQL_TIME *ltime, date_conv_mode_t flags, int *was_cut) { - return check_date(ltime, non_zero_date(ltime), flags, was_cut); + return check_date(ltime, non_zero_date(ltime), + ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), was_cut); } -bool check_date_with_warn(const MYSQL_TIME *ltime, ulonglong fuzzy_date, - timestamp_type ts_type); -bool make_date_with_warn(MYSQL_TIME *ltime, - ulonglong fuzzy_date, timestamp_type ts_type); -bool adjust_time_range_with_warn(MYSQL_TIME *ltime, uint dec); +bool check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, + date_conv_mode_t fuzzy_date, timestamp_type ts_type); +static inline bool +check_date_with_warn(THD *thd, const MYSQL_TIME *ltime, + date_mode_t fuzzydate, timestamp_type ts_type) +{ + return check_date_with_warn(thd, ltime, date_conv_mode_t(fuzzydate), ts_type); +} + +bool adjust_time_range_with_warn(THD *thd, MYSQL_TIME *ltime, uint dec); longlong pack_time(const MYSQL_TIME *my_time); void unpack_time(longlong packed, MYSQL_TIME *my_time, diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index dde93dc6ed6..b79c1a1adb1 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -35,16 +35,6 @@ #include "sp_cache.h" // sp_invalidate_cache #include <mysys_err.h> -LEX_CSTRING *make_lex_string(LEX_CSTRING *lex_str, - const char* str, size_t length, - MEM_ROOT *mem_root) -{ - if (!(lex_str->str= strmake_root(mem_root, str, length))) - return 0; - lex_str->length= length; - return lex_str; -} - /*************************************************************************/ /** @@ -622,9 +612,10 @@ end: my_ok(thd); DBUG_RETURN(result); - -WSREP_ERROR_LABEL: +#ifdef WITH_WSREP +wsrep_error_label: DBUG_RETURN(true); +#endif } @@ -1502,8 +1493,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db, if (likely((name= error_handler.get_trigger_name()))) { - if (unlikely(!(make_lex_string(&trigger->name, name->str, - name->length, &table->mem_root)))) + trigger->name= safe_lexcstrdup_root(&table->mem_root, *name); + if (unlikely(!trigger->name.str)) goto err_with_lex_cleanup; } trigger->definer= ((!trg_definer || !trg_definer->length) ? @@ -2314,12 +2305,10 @@ void Table_triggers_list::mark_fields_used(trg_event_type event) if (trg_field->field_idx != (uint)-1) { DBUG_PRINT("info", ("marking field: %d", trg_field->field_idx)); - bitmap_set_bit(trigger_table->read_set, trg_field->field_idx); if (trg_field->get_settable_routine_parameter()) bitmap_set_bit(trigger_table->write_set, trg_field->field_idx); - if (trigger_table->field[trg_field->field_idx]->vcol_info) - trigger_table->mark_virtual_col(trigger_table-> - field[trg_field->field_idx]); + trigger_table->mark_column_with_deps( + trigger_table->field[trg_field->field_idx]); } } } diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index bab9bb5e9ac..798e929170c 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -495,7 +495,7 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) bool Sql_cmd_truncate_table::execute(THD *thd) { bool res= TRUE; - TABLE_LIST *table= thd->lex->select_lex.table_list.first; + TABLE_LIST *table= thd->lex->first_select_lex()->table_list.first; DBUG_ENTER("Sql_cmd_truncate_table::execute"); if (check_one_table_access(thd, DROP_ACL, table)) diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index a5085fdfc58..0e4caae7a2f 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -173,7 +173,7 @@ bool get_type_attributes_for_tvc(THD *thd, Item *item; for (uint holder_pos= 0 ; (item= it++); holder_pos++) { - DBUG_ASSERT(item->fixed); + DBUG_ASSERT(item->is_fixed()); holders[holder_pos].add_argument(item); } } @@ -251,7 +251,6 @@ bool table_value_constr::prepare(THD *thd, SELECT_LEX *sl, holders[pos].type_handler(), &holders[pos]/*Type_all_attributes*/, holders[pos].get_maybe_null()); - new_holder->fix_fields(thd, 0); sl->item_list.push_back(new_holder); } @@ -296,7 +295,7 @@ int table_value_constr::save_explain_data_intern(THD *thd, explain->select_id= select_lex->select_number; explain->select_type= select_lex->type; - explain->linkage= select_lex->linkage; + explain->linkage= select_lex->get_linkage(); explain->using_temporary= false; explain->using_filesort= false; /* Setting explain->message means that all other members are invalid */ @@ -564,7 +563,7 @@ bool Item_subselect::wrap_tvc_in_derived_table(THD *thd, Item *item; SELECT_LEX *sq_select; // select for IN subquery; sq_select= lex->current_select; - sq_select->linkage= tvc_sl->linkage; + sq_select->set_linkage(tvc_sl->get_linkage()); sq_select->parsing_place= SELECT_LIST; item= new (thd->mem_root) Item_field(thd, &sq_select->context, NULL, NULL, &star_clex_str); @@ -583,7 +582,7 @@ bool Item_subselect::wrap_tvc_in_derived_table(THD *thd, goto err; tvc_select= lex->current_select; derived_unit= tvc_select->master_unit(); - tvc_select->linkage= DERIVED_TABLE_TYPE; + tvc_select->set_linkage(DERIVED_TABLE_TYPE); lex->current_select= sq_select; @@ -710,7 +709,7 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd, mysql_init_select(lex); tvc_select= lex->current_select; derived_unit= tvc_select->master_unit(); - tvc_select->linkage= DERIVED_TABLE_TYPE; + tvc_select->set_linkage(DERIVED_TABLE_TYPE); /* Create TVC used in the transformation */ if (create_value_list_for_tvc(thd, &values)) diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 22eebaf6a38..263b5198588 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -21,11 +21,13 @@ #include "sql_time.h" #include "item.h" #include "log.h" +#include "tztime.h" Type_handler_row type_handler_row; Type_handler_null type_handler_null; +Type_handler_bool type_handler_bool; Type_handler_tiny type_handler_tiny; Type_handler_short type_handler_short; Type_handler_long type_handler_long; @@ -41,6 +43,7 @@ Type_handler_olddecimal type_handler_olddecimal; Type_handler_newdecimal type_handler_newdecimal; Type_handler_year type_handler_year; +Type_handler_year type_handler_year2; Type_handler_time type_handler_time; Type_handler_date type_handler_date; Type_handler_timestamp type_handler_timestamp; @@ -56,6 +59,7 @@ Type_handler_set type_handler_set; Type_handler_string type_handler_string; Type_handler_var_string type_handler_var_string; Type_handler_varchar type_handler_varchar; +Type_handler_hex_hybrid type_handler_hex_hybrid; static Type_handler_varchar_compressed type_handler_varchar_compressed; Type_handler_tiny_blob type_handler_tiny_blob; @@ -64,6 +68,8 @@ Type_handler_long_blob type_handler_long_blob; Type_handler_blob type_handler_blob; static Type_handler_blob_compressed type_handler_blob_compressed; +Type_handler_interval_DDhhmmssff type_handler_interval_DDhhmmssff; + #ifdef HAVE_SPATIAL Type_handler_geometry type_handler_geometry; #endif @@ -91,6 +97,9 @@ bool Type_handler_data::init() &type_handler_geometry, &type_handler_geometry) || m_type_aggregator_for_result.add(&type_handler_geometry, + &type_handler_hex_hybrid, + &type_handler_long_blob) || + m_type_aggregator_for_result.add(&type_handler_geometry, &type_handler_tiny_blob, &type_handler_long_blob) || m_type_aggregator_for_result.add(&type_handler_geometry, @@ -125,18 +134,679 @@ bool Type_handler_data::init() Type_handler_data *type_handler_data= NULL; -void Time::make_from_item(Item *item, const Options opt) +String_ptr::String_ptr(Item *item, String *buffer) + :m_string_ptr(item->val_str(buffer)) +{ } + + +Ascii_ptr::Ascii_ptr(Item *item, String *buffer) + :String_ptr(item->val_str_ascii(buffer)) +{ } + + +void VDec::set(Item *item) +{ + m_ptr= item->val_decimal(&m_buffer); + DBUG_ASSERT((m_ptr == NULL) == item->null_value); +} + + +VDec::VDec(Item *item) +{ + m_ptr= item->val_decimal(&m_buffer); + DBUG_ASSERT((m_ptr == NULL) == item->null_value); +} + + +VDec_op::VDec_op(Item_func_hybrid_field_type *item) +{ + m_ptr= item->decimal_op(&m_buffer); + DBUG_ASSERT((m_ptr == NULL) == item->null_value); +} + + +date_conv_mode_t Temporal::sql_mode_for_dates(THD *thd) +{ + return ::sql_mode_for_dates(thd); +} + + +time_round_mode_t Temporal::default_round_mode(THD *thd) +{ + return thd->temporal_round_mode(); +} + + +time_round_mode_t Timestamp::default_round_mode(THD *thd) +{ + return thd->temporal_round_mode(); +} + + +my_decimal *Temporal::to_decimal(my_decimal *to) const +{ + return date2my_decimal(this, to); +} + + +my_decimal *Temporal::bad_to_decimal(my_decimal *to) const +{ + my_decimal_set_zero(to); + return NULL; +} + + +void Temporal::make_from_str(THD *thd, Warn *warn, + const char *str, size_t length, + CHARSET_INFO *cs, date_mode_t fuzzydate) +{ + DBUG_EXECUTE_IF("str_to_datetime_warn", + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_YES, ErrConvString(str, length,cs).ptr());); + + if (str_to_temporal(thd, warn, str, length, cs, fuzzydate)) + make_fuzzy_date(&warn->warnings, date_conv_mode_t(fuzzydate)); + if (warn->warnings) + warn->set_str(str, length, &my_charset_bin); +} + + +Temporal_hybrid::Temporal_hybrid(THD *thd, Item *item, date_mode_t fuzzydate) +{ + if (item->get_date(thd, this, fuzzydate)) + time_type= MYSQL_TIMESTAMP_NONE; +} + + +uint Timestamp::binary_length_to_precision(uint length) +{ + switch (length) { + case 4: return 0; + case 5: return 2; + case 6: return 4; + case 7: return 6; + } + DBUG_ASSERT(0); + return 0; +} + + +Timestamp::Timestamp(const Native &native) +{ + DBUG_ASSERT(native.length() >= 4 && native.length() <= 7); + uint dec= binary_length_to_precision(native.length()); + my_timestamp_from_binary(this, (const uchar *) native.ptr(), dec); +} + + +bool Timestamp::to_native(Native *to, uint decimals) const +{ + uint len= my_timestamp_binary_length(decimals); + if (to->reserve(len)) + return true; + my_timestamp_to_binary(this, (uchar *) to->ptr(), decimals); + to->length(len); + return false; +} + + +bool Timestamp::to_TIME(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) const +{ + return thd->timestamp_to_TIME(to, tv_sec, tv_usec, fuzzydate); +} + + +Timestamp::Timestamp(THD *thd, const MYSQL_TIME *ltime, uint *error_code) + :Timeval(TIME_to_timestamp(thd, ltime, error_code), ltime->second_part) +{ } + + +Timestamp_or_zero_datetime::Timestamp_or_zero_datetime(THD *thd, + const MYSQL_TIME *ltime, + uint *error_code) + :Timestamp(thd, ltime, error_code), + m_is_zero_datetime(*error_code == ER_WARN_DATA_OUT_OF_RANGE) +{ + if (m_is_zero_datetime) + { + if (!non_zero_date(ltime)) + *error_code= 0; // ltime was '0000-00-00 00:00:00' + } + else if (*error_code == ER_WARN_INVALID_TIMESTAMP) + *error_code= 0; // ltime fell into spring time gap, adjusted. +} + + +bool Timestamp_or_zero_datetime::to_TIME(THD *thd, MYSQL_TIME *to, + date_mode_t fuzzydate) const +{ + if (m_is_zero_datetime) + { + set_zero_time(to, MYSQL_TIMESTAMP_DATETIME); + return false; + } + return Timestamp::to_TIME(thd, to, fuzzydate); +} + + +bool Timestamp_or_zero_datetime::to_native(Native *to, uint decimals) const +{ + if (m_is_zero_datetime) + { + to->length(0); + return false; + } + return Timestamp::to_native(to, decimals); +} + + +int Timestamp_or_zero_datetime_native::save_in_field(Field *field, + uint decimals) const +{ + field->set_notnull(); + if (field->type_handler()->type_handler_for_native_format() == + &type_handler_timestamp2) + return field->store_native(*this); + if (is_zero_datetime()) + { + static Datetime zero(Datetime::zero()); + return field->store_time_dec(zero.get_mysql_time(), decimals); + } + return field->store_timestamp_dec(Timestamp(*this).tv(), decimals); +} + + +void Sec6::make_from_decimal(const my_decimal *d, ulong *nanoseconds) +{ + m_neg= my_decimal2seconds(d, &m_sec, &m_usec, nanoseconds); + m_truncated= (m_sec >= LONGLONG_MAX); +} + + +void Sec6::make_from_double(double nr, ulong *nanoseconds) +{ + if ((m_neg= nr < 0)) + nr= -nr; + if ((m_truncated= nr > (double) LONGLONG_MAX)) + { + m_sec= LONGLONG_MAX; + m_usec= 0; + } + else + { + m_sec= (ulonglong) nr; + m_usec= (ulong) ((nr - floor(nr)) * 1000000000); + *nanoseconds= m_usec % 1000; + m_usec/= 1000; + } +} + + +void Sec6::make_truncated_warning(THD *thd, const char *type_str) const +{ + char buff[1 + MAX_BIGINT_WIDTH + 1 + 6 + 1]; // '-' int '.' frac '\0' + to_string(buff, sizeof(buff)); + thd->push_warning_truncated_wrong_value(type_str, buff); +} + + +bool Sec6::convert_to_mysql_time(THD *thd, int *warn, MYSQL_TIME *ltime, + date_mode_t fuzzydate) const +{ + bool rc= fuzzydate & (TIME_INTERVAL_hhmmssff | TIME_INTERVAL_DAY) ? + to_datetime_or_to_interval_hhmmssff(ltime, warn) : + fuzzydate & TIME_TIME_ONLY ? + to_datetime_or_time(ltime, warn, date_conv_mode_t(fuzzydate)) : + to_datetime_or_date(ltime, warn, date_conv_mode_t(fuzzydate)); + DBUG_ASSERT(*warn || !rc); + if (truncated()) + *warn|= MYSQL_TIME_WARN_TRUNCATED; + return rc; +} + + +void Temporal::push_conversion_warnings(THD *thd, bool totally_useless_value, + int warn, + const char *typestr, + const TABLE_SHARE *s, + const char *field_name, + const char *value) +{ + if (MYSQL_TIME_WARN_HAVE_WARNINGS(warn)) + thd->push_warning_wrong_or_truncated_value(Sql_condition::WARN_LEVEL_WARN, + totally_useless_value, + typestr, value, s, field_name); + else if (MYSQL_TIME_WARN_HAVE_NOTES(warn)) + thd->push_warning_wrong_or_truncated_value(Sql_condition::WARN_LEVEL_NOTE, + false, typestr, value, s, + field_name); +} + + +VSec9::VSec9(THD *thd, Item *item, const char *type_str, ulonglong limit) +{ + if (item->decimals == 0) + { // optimize for an important special case + Longlong_hybrid nr(item->val_int(), item->unsigned_flag); + make_from_int(nr); + m_is_null= item->null_value; + if (!m_is_null && m_sec > limit) + { + m_sec= limit; + m_truncated= true; + ErrConvInteger err(nr); + thd->push_warning_truncated_wrong_value(type_str, err.ptr()); + } + } + else if (item->cmp_type() == REAL_RESULT) + { + double nr= item->val_real(); + make_from_double(nr, &m_nsec); + m_is_null= item->null_value; + if (!m_is_null && m_sec > limit) + { + m_sec= limit; + m_truncated= true; + } + if (m_truncated) + { + ErrConvDouble err(nr); + thd->push_warning_truncated_wrong_value(type_str, err.ptr()); + } + } + else + { + VDec tmp(item); + (m_is_null= tmp.is_null()) ? reset() : make_from_decimal(tmp.ptr(), &m_nsec); + if (!m_is_null && m_sec > limit) + { + m_sec= limit; + m_truncated= true; + } + if (m_truncated) + { + ErrConvDecimal err(tmp.ptr()); + thd->push_warning_truncated_wrong_value(type_str, err.ptr()); + } + } +} + + +Year::Year(longlong value, bool unsigned_flag, uint length) +{ + if ((m_truncated= (value < 0))) // Negative or huge unsigned + m_year= unsigned_flag ? 9999 : 0; + else if (value > 9999) + { + m_truncated= true; + m_year= 9999; + } + else if (length == 2) + { + m_year= value < 70 ? (uint) value + 2000 : + value <= 1900 ? (uint) value + 1900 : + (uint) value; + } + else + m_year= (uint) value; + DBUG_ASSERT(m_year <= 9999); +} + + +uint Year::year_precision(const Item *item) const +{ + return item->type_handler() == &type_handler_year2 ? 2 : 4; +} + + +VYear::VYear(Item *item) + :Year_null(item->to_longlong_null(), item->unsigned_flag, year_precision(item)) +{ } + + +VYear_op::VYear_op(Item_func_hybrid_field_type *item) + :Year_null(item->to_longlong_null_op(), item->unsigned_flag, + year_precision(item)) +{ } + + +const LEX_CSTRING Interval_DDhhmmssff::m_type_name= + {STRING_WITH_LEN("INTERVAL DAY TO SECOND")}; + + +Interval_DDhhmmssff::Interval_DDhhmmssff(THD *thd, Status *st, + bool push_warnings, + Item *item, ulong max_hour, + time_round_mode_t mode, uint dec) { - if (item->get_date(this, opt.get_date_flags())) + switch (item->cmp_type()) { + case ROW_RESULT: + DBUG_ASSERT(0); time_type= MYSQL_TIMESTAMP_NONE; + break; + case TIME_RESULT: + { + // Rounding mode is not important here + if (item->get_date(thd, this, Options(TIME_TIME_ONLY, TIME_FRAC_NONE))) + time_type= MYSQL_TIMESTAMP_NONE; + else if (time_type != MYSQL_TIMESTAMP_TIME) + { + st->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE; + push_warning_wrong_or_truncated_value(thd, ErrConvTime(this), + st->warnings); + time_type= MYSQL_TIMESTAMP_NONE; + } + break; + } + case INT_RESULT: + case REAL_RESULT: + case DECIMAL_RESULT: + case STRING_RESULT: + { + StringBuffer<STRING_BUFFER_USUAL_SIZE> tmp; + String *str= item->val_str(&tmp); + if (!str) + time_type= MYSQL_TIMESTAMP_NONE; + else if (str_to_DDhhmmssff(st, str->ptr(), str->length(), str->charset(), + UINT_MAX32)) + { + if (push_warnings) + thd->push_warning_wrong_value(Sql_condition::WARN_LEVEL_WARN, + m_type_name.str, + ErrConvString(str).ptr()); + time_type= MYSQL_TIMESTAMP_NONE; + } + else + { + if (mode == TIME_FRAC_ROUND) + time_round_or_set_max(dec, &st->warnings, max_hour, st->nanoseconds); + if (hour > max_hour) + { + st->warnings|= MYSQL_TIME_WARN_OUT_OF_RANGE; + time_type= MYSQL_TIMESTAMP_NONE; + } + // Warn if hour or nanosecond truncation happened + if (push_warnings) + push_warning_wrong_or_truncated_value(thd, ErrConvString(str), + st->warnings); + } + } + break; + } + DBUG_ASSERT(is_valid_value_slow()); +} + + +void +Interval_DDhhmmssff::push_warning_wrong_or_truncated_value(THD *thd, + const ErrConv &str, + int warnings) +{ + if (warnings & MYSQL_TIME_WARN_OUT_OF_RANGE) + { + thd->push_warning_wrong_value(Sql_condition::WARN_LEVEL_WARN, + m_type_name.str, str.ptr()); + } + else if (MYSQL_TIME_WARN_HAVE_WARNINGS(warnings)) + { + thd->push_warning_truncated_wrong_value(Sql_condition::WARN_LEVEL_WARN, + m_type_name.str, str.ptr()); + } + else if (MYSQL_TIME_WARN_HAVE_NOTES(warnings)) + { + thd->push_warning_truncated_wrong_value(Sql_condition::WARN_LEVEL_NOTE, + m_type_name.str, str.ptr()); + } +} + + +uint Interval_DDhhmmssff::fsp(THD *thd, Item *item) +{ + switch (item->cmp_type()) { + case INT_RESULT: + case TIME_RESULT: + return item->decimals; + case REAL_RESULT: + case DECIMAL_RESULT: + return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS); + case ROW_RESULT: + DBUG_ASSERT(0); + return 0; + case STRING_RESULT: + break; + } + if (!item->const_item() || item->is_expensive()) + return TIME_SECOND_PART_DIGITS; + Status st; + Interval_DDhhmmssff it(thd, &st, false/*no warnings*/, item, UINT_MAX32, + TIME_FRAC_TRUNCATE, TIME_SECOND_PART_DIGITS); + return it.is_valid_interval_DDhhmmssff() ? st.precision : + TIME_SECOND_PART_DIGITS; +} + + +void Time::make_from_item(THD *thd, int *warn, Item *item, const Options opt) +{ + *warn= 0; + if (item->get_date(thd, this, opt)) + time_type= MYSQL_TIMESTAMP_NONE; + else + valid_MYSQL_TIME_to_valid_value(thd, warn, opt); +} + + +static uint msec_round_add[7]= +{ + 500000000, + 50000000, + 5000000, + 500000, + 50000, + 5000, + 0 +}; + + +Sec9 & Sec9::round(uint dec) +{ + DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); + if (Sec6::add_nanoseconds(m_nsec + msec_round_add[dec])) + m_sec++; + m_nsec= 0; + Sec6::trunc(dec); + return *this; +} + + +void Timestamp::round_or_set_max(uint dec, int *warn) +{ + DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); + if (add_nanoseconds_usec(msec_round_add[dec]) && + tv_sec++ >= TIMESTAMP_MAX_VALUE) + { + tv_sec= TIMESTAMP_MAX_VALUE; + tv_usec= TIME_MAX_SECOND_PART; + *warn|= MYSQL_TIME_WARN_OUT_OF_RANGE; + } + my_timeval_trunc(this, dec); +} + + +bool Temporal::add_nanoseconds_with_round(THD *thd, int *warn, + date_conv_mode_t mode, + ulong nsec) +{ + switch (time_type) { + case MYSQL_TIMESTAMP_TIME: + { + ulong max_hour= (mode & (TIME_INTERVAL_DAY | TIME_INTERVAL_hhmmssff)) ? + TIME_MAX_INTERVAL_HOUR : TIME_MAX_HOUR; + time_round_or_set_max(6, warn, max_hour, nsec); + return false; + } + case MYSQL_TIMESTAMP_DATETIME: + return datetime_round_or_invalidate(thd, 6, warn, nsec); + case MYSQL_TIMESTAMP_DATE: + return false; + case MYSQL_TIMESTAMP_NONE: + return false; + case MYSQL_TIMESTAMP_ERROR: + break; + } + DBUG_ASSERT(0); + return false; +} + + +void Temporal::time_round_or_set_max(uint dec, int *warn, + ulong max_hour, ulong nsec) +{ + DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); + if (add_nanoseconds_mmssff(nsec) && ++hour > max_hour) + { + time_hhmmssff_set_max(max_hour); + *warn|= MYSQL_TIME_WARN_OUT_OF_RANGE; + } + my_time_trunc(this, dec); +} + + +void Time::round_or_set_max(uint dec, int *warn, ulong nsec) +{ + Temporal::time_round_or_set_max(dec, warn, TIME_MAX_HOUR, nsec); + DBUG_ASSERT(is_valid_time_slow()); +} + + +void Time::round_or_set_max(uint dec, int *warn) +{ + round_or_set_max(dec, warn, msec_round_add[dec]); +} + +/** + Create from a DATETIME by subtracting a given number of days, + implementing an optimized version of calc_time_diff(). +*/ +void Time::make_from_datetime_with_days_diff(int *warn, const MYSQL_TIME *from, + long days) +{ + *warn= 0; + DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_DATETIME || + from->time_type == MYSQL_TIMESTAMP_DATE); + long daynr= calc_daynr(from->year, from->month, from->day); + long daydiff= daynr - days; + if (!daynr) // Zero date + { + set_zero_time(this, MYSQL_TIMESTAMP_TIME); + neg= true; + hour= TIME_MAX_HOUR + 1; // to report "out of range" in "warn" + } + else if (daydiff >=0) + { + neg= false; + year= month= day= 0; + hhmmssff_copy(from); + hour+= daydiff * 24; + time_type= MYSQL_TIMESTAMP_TIME; + } + else + { + longlong timediff= ((((daydiff * 24LL + + from->hour) * 60LL + + from->minute) * 60LL + + from->second) * 1000000LL + + from->second_part); + unpack_time(timediff, this, MYSQL_TIMESTAMP_TIME); + if (year || month) + { + *warn|= MYSQL_TIME_WARN_OUT_OF_RANGE; + year= month= day= 0; + hour= TIME_MAX_HOUR + 1; + } + } + // The above code can generate TIME values outside of the valid TIME range. + adjust_time_range_or_invalidate(warn); +} + + +void Time::make_from_datetime_move_day_to_hour(int *warn, + const MYSQL_TIME *from) +{ + *warn= 0; + DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_DATE || + from->time_type == MYSQL_TIMESTAMP_DATETIME); + time_type= MYSQL_TIMESTAMP_TIME; + neg= false; + year= month= day= 0; + hhmmssff_copy(from); + datetime_to_time_YYYYMMDD_000000DD_mix_to_hours(warn, from->year, + from->month, from->day); + adjust_time_range_or_invalidate(warn); +} + + +void Time::make_from_datetime(int *warn, const MYSQL_TIME *from, long curdays) +{ + if (!curdays) + make_from_datetime_move_day_to_hour(warn, from); else - valid_MYSQL_TIME_to_valid_value(opt); + make_from_datetime_with_days_diff(warn, from, curdays); } -void Temporal_with_date::make_from_item(THD *thd, Item *item, sql_mode_t flags) +void Time::make_from_time(int *warn, const MYSQL_TIME *from) { - flags&= ~TIME_TIME_ONLY; + DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_TIME); + if (from->year || from->month) + make_from_out_of_range(warn); + else + { + *warn= 0; + DBUG_ASSERT(from->day == 0); + *(static_cast<MYSQL_TIME*>(this))= *from; + adjust_time_range_or_invalidate(warn); + } +} + + +Time::Time(int *warn, const MYSQL_TIME *from, long curdays) +{ + switch (from->time_type) { + case MYSQL_TIMESTAMP_NONE: + case MYSQL_TIMESTAMP_ERROR: + make_from_out_of_range(warn); + break; + case MYSQL_TIMESTAMP_DATE: + case MYSQL_TIMESTAMP_DATETIME: + make_from_datetime(warn, from, curdays); + break; + case MYSQL_TIMESTAMP_TIME: + make_from_time(warn, from); + break; + } + DBUG_ASSERT(is_valid_value_slow()); +} + + +Time::Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec6 &second) +{ + DBUG_ASSERT(second.sec() <= 59); + *warn= 0; + set_zero_time(this, MYSQL_TIMESTAMP_TIME); + MYSQL_TIME::neg= neg; + MYSQL_TIME::hour= hour > TIME_MAX_HOUR ? (uint) (TIME_MAX_HOUR + 1) : + (uint) hour; + MYSQL_TIME::minute= minute; + MYSQL_TIME::second= (uint) second.sec(); + MYSQL_TIME::second_part= second.usec(); + adjust_time_range_or_invalidate(warn); +} + + +void Temporal_with_date::make_from_item(THD *thd, Item *item, + date_mode_t fuzzydate) +{ + date_conv_mode_t flags= date_conv_mode_t(fuzzydate) & ~TIME_TIME_ONLY; /* Some TIME type items return error when trying to do get_date() without TIME_TIME_ONLY set (e.g. Item_field for Field_time). @@ -144,10 +814,11 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item, sql_mode_t flags) In the legacy time->datetime conversion mode we do not add TIME_TIME_ONLY and leave it to get_date() to check date. */ - ulonglong time_flag= (item->field_type() == MYSQL_TYPE_TIME && - !(thd->variables.old_behavior & OLD_MODE_ZERO_DATE_TIME_CAST)) ? - TIME_TIME_ONLY : 0; - if (item->get_date(this, flags | time_flag)) + date_conv_mode_t time_flag= (item->field_type() == MYSQL_TYPE_TIME && + !(thd->variables.old_behavior & OLD_MODE_ZERO_DATE_TIME_CAST)) ? + TIME_TIME_ONLY : TIME_CONV_NONE; + Options opt(flags | time_flag, time_round_mode_t(fuzzydate)); + if (item->get_date(thd, this, opt)) time_type= MYSQL_TIMESTAMP_NONE; else if (time_type == MYSQL_TIMESTAMP_TIME) { @@ -160,6 +831,154 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item, sql_mode_t flags) } +void Temporal_with_date::check_date_or_invalidate(int *warn, + date_conv_mode_t flags) +{ + if (::check_date(this, pack_time(this) != 0, + ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), warn)) + time_type= MYSQL_TIMESTAMP_NONE; +} + + +void Datetime::make_from_time(THD *thd, int *warn, const MYSQL_TIME *from, + date_conv_mode_t flags) +{ + DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_TIME); + if (time_to_datetime(thd, from, this)) + make_from_out_of_range(warn); + else + { + *warn= 0; + check_date_or_invalidate(warn, flags); + } +} + + +void Datetime::make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from, + date_conv_mode_t flags) +{ + DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_DATE || + from->time_type == MYSQL_TIMESTAMP_DATETIME); + if (from->neg || check_datetime_range(from)) + make_from_out_of_range(warn); + else + { + *warn= 0; + *(static_cast<MYSQL_TIME*>(this))= *from; + date_to_datetime(this); + check_date_or_invalidate(warn, flags); + } +} + + +Datetime::Datetime(THD *thd, const timeval &tv) +{ + thd->variables.time_zone->gmt_sec_to_TIME(this, tv.tv_sec); + second_part= tv.tv_usec; + thd->time_zone_used= 1; + DBUG_ASSERT(is_valid_value_slow()); +} + + +Datetime::Datetime(THD *thd, int *warn, const MYSQL_TIME *from, + date_conv_mode_t flags) +{ + DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false); + switch (from->time_type) { + case MYSQL_TIMESTAMP_ERROR: + case MYSQL_TIMESTAMP_NONE: + make_from_out_of_range(warn); + break; + case MYSQL_TIMESTAMP_TIME: + make_from_time(thd, warn, from, flags); + break; + case MYSQL_TIMESTAMP_DATETIME: + case MYSQL_TIMESTAMP_DATE: + make_from_datetime(thd, warn, from, flags); + break; + } + DBUG_ASSERT(is_valid_value_slow()); +} + + +bool Temporal::datetime_add_nanoseconds_or_invalidate(THD *thd, int *warn, ulong nsec) +{ + if (!add_nanoseconds_mmssff(nsec)) + return false; + /* + Overflow happened on minutes. Now we need to add 1 hour to the value. + Catch a special case for the maximum possible date and hour==23, to + truncate '9999-12-31 23:59:59.9999999' (with 7 fractional digits) + to '9999-12-31 23:59:59.999999' (with 6 fractional digits), + with a warning, instead of returning an error, so this statement: + INSERT INTO (datetime_column) VALUES ('9999-12-31 23:59:59.9999999'); + inserts a value truncated to 6 fractional digits, instead of zero + date '0000-00-00 00:00:00.000000'. + */ + if (year == 9999 && month == 12 && day == 31 && hour == 23) + { + minute= 59; + second= 59; + second_part= 999999; + *warn= MYSQL_TIME_WARN_OUT_OF_RANGE; + return false; + } + INTERVAL interval; + memset(&interval, 0, sizeof(interval)); + interval.hour= 1; + /* date_add_interval cannot handle bad dates */ + if (check_date(TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE, warn) || + date_add_interval(thd, this, INTERVAL_HOUR, interval)) + { + make_from_out_of_range(warn); + return true; + } + return false; +} + + +bool Temporal::datetime_round_or_invalidate(THD *thd, uint dec, int *warn, ulong nsec) +{ + DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS); + if (datetime_add_nanoseconds_or_invalidate(thd, warn, nsec)) + return true; + my_time_trunc(this, dec); + return false; + +} + + +bool Datetime::round_or_invalidate(THD *thd, uint dec, int *warn) +{ + return round_or_invalidate(thd, dec, warn, msec_round_add[dec]); +} + + +Datetime_from_temporal::Datetime_from_temporal(THD *thd, Item *temporal, + date_conv_mode_t fuzzydate) + :Datetime(thd, temporal, Options(fuzzydate, TIME_FRAC_NONE)) +{ + // Exact rounding mode does not matter + DBUG_ASSERT(temporal->cmp_type() == TIME_RESULT); +} + + +Datetime_truncation_not_needed::Datetime_truncation_not_needed(THD *thd, Item *item, + date_conv_mode_t mode) + :Datetime(thd, item, Options(mode, TIME_FRAC_NONE)) +{ + /* + The called Datetime() constructor only would truncate nanoseconds if they + existed (but we know there were no nanoseconds). Here we assert that there + are also no microsecond digits outside of the scale specified in "dec". + */ + DBUG_ASSERT(!is_valid_datetime() || + fraction_remainder(MY_MIN(item->decimals, + TIME_SECOND_PART_DIGITS)) == 0); +} + +/********************************************************************/ + uint Type_std_attributes::count_max_decimals(Item **item, uint nitems) { uint res= 0; @@ -280,6 +1099,32 @@ bool Type_std_attributes::count_string_length(const char *func_name, } +/* + Find a handler by its ODBC literal data type. + + @param type_str - data type name, not necessarily 0-terminated + @retval - a pointer to data type handler if type_str points + to a known ODBC literal data type, or NULL otherwise +*/ +const Type_handler * +Type_handler::odbc_literal_type_handler(const LEX_CSTRING *type_str) +{ + if (type_str->length == 1) + { + if (type_str->str[0] == 'd') // {d'2001-01-01'} + return &type_handler_newdate; + else if (type_str->str[0] == 't') // {t'10:20:30'} + return &type_handler_time2; + } + else if (type_str->length == 2) // {ts'2001-01-01 10:20:30'} + { + if (type_str->str[0] == 't' && type_str->str[1] == 's') + return &type_handler_datetime2; + } + return NULL; // Not a known ODBC literal type +} + + /** This method is used by: - Item_user_var_as_out_param::field_type() @@ -433,6 +1278,7 @@ const Name Type_handler_string::m_name_char(STRING_WITH_LEN("char")), Type_handler_var_string::m_name_var_string(STRING_WITH_LEN("varchar")), Type_handler_varchar::m_name_varchar(STRING_WITH_LEN("varchar")), + Type_handler_hex_hybrid::m_name_hex_hybrid(STRING_WITH_LEN("hex_hybrid")), Type_handler_tiny_blob::m_name_tinyblob(STRING_WITH_LEN("tinyblob")), Type_handler_medium_blob::m_name_mediumblob(STRING_WITH_LEN("mediumblob")), Type_handler_long_blob::m_name_longblob(STRING_WITH_LEN("longblob")), @@ -443,6 +1289,7 @@ const Name Type_handler_set::m_name_set(STRING_WITH_LEN("set")); const Name + Type_handler_bool::m_name_bool(STRING_WITH_LEN("boolean")), Type_handler_tiny::m_name_tiny(STRING_WITH_LEN("tinyint")), Type_handler_short::m_name_short(STRING_WITH_LEN("smallint")), Type_handler_long::m_name_int(STRING_WITH_LEN("int")), @@ -465,6 +1312,11 @@ const Name Type_handler_datetime_common::m_name_datetime(STRING_WITH_LEN("datetime")), Type_handler_timestamp_common::m_name_timestamp(STRING_WITH_LEN("timestamp")); +const Name + Type_handler::m_version_default(STRING_WITH_LEN("")), + Type_handler::m_version_mariadb53(STRING_WITH_LEN("mariadb-5.3")), + Type_handler::m_version_mysql56(STRING_WITH_LEN("mysql-5.6")); + const Type_limits_int Type_handler_tiny::m_limits_sint8= Type_limits_sint8(), @@ -530,7 +1382,7 @@ const Type_handler *Type_handler_datetime_common::type_handler_for_comparison() const Type_handler *Type_handler_timestamp_common::type_handler_for_comparison() const { - return &type_handler_datetime; + return &type_handler_timestamp; } @@ -541,6 +1393,15 @@ const Type_handler *Type_handler_row::type_handler_for_comparison() const /***************************************************************************/ +const Type_handler * +Type_handler_timestamp_common::type_handler_for_native_format() const +{ + return &type_handler_timestamp2; +} + + +/***************************************************************************/ + const Type_handler *Type_handler_typelib::type_handler_for_item_field() const { return &type_handler_string; @@ -715,6 +1576,16 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h) */ if (b == TIME_RESULT) m_type_handler= h; // Temporal types bit non-temporal types + /* + Compare TIMESTAMP to a non-temporal type as DATETIME. + This is needed to make queries with fuzzy dates work: + SELECT * FROM t1 + WHERE + ts BETWEEN '0000-00-00' AND '2010-00-01 00:00:00'; + */ + if (m_type_handler->type_handler_for_native_format() == + &type_handler_timestamp2) + m_type_handler= &type_handler_datetime; } else { @@ -798,7 +1669,19 @@ Type_handler_hybrid_field_type::aggregate_for_min_max(const Type_handler *h) } else if (a == TIME_RESULT || b == TIME_RESULT) { - if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1) + if ((m_type_handler->type_handler_for_native_format() == + &type_handler_timestamp2) + + (h->type_handler_for_native_format() == + &type_handler_timestamp2) == 1) + { + /* + Handle LEAST(TIMESTAMP, non-TIMESTAMP) as DATETIME, + to make sure fuzzy dates work in this context: + LEAST('2001-00-00', timestamp_field) + */ + m_type_handler= &type_handler_datetime2; + } + else if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1) { /* We're here if there's only one temporal data type: @@ -1604,6 +2487,70 @@ bool Type_handler_bit:: /*************************************************************************/ +void Type_handler_blob_common:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + DBUG_ASSERT(def->key_length == 0); +} + + +void Type_handler_typelib:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + DBUG_ASSERT(def->flags & (ENUM_FLAG | SET_FLAG)); + def->interval= field->get_typelib(); +} + + +#ifdef HAVE_SPATIAL +void Type_handler_geometry:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + def->geom_type= ((Field_geom*) field)->geom_type; + def->srid= ((Field_geom*) field)->srid; +} +#endif + + +void Type_handler_year:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + if (def->length != 4) + { + char buff[sizeof("YEAR()") + MY_INT64_NUM_DECIMAL_DIGITS + 1]; + my_snprintf(buff, sizeof(buff), "YEAR(%llu)", def->length); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_WARN_DEPRECATED_SYNTAX, + ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX), + buff, "YEAR(4)"); + } +} + + +void Type_handler_real_result:: + Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *def, + const Field *field) const +{ + /* + Floating points are stored with FLOATING_POINT_DECIMALS but internally + in MariaDB used with NOT_FIXED_DEC, which is >= FLOATING_POINT_DECIMALS. + */ + if (def->decimals >= FLOATING_POINT_DECIMALS) + def->decimals= NOT_FIXED_DEC; +} + + +/*************************************************************************/ + bool Type_handler:: Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, @@ -2007,8 +2954,8 @@ Field *Type_handler_tiny::make_table_field(const LEX_CSTRING *name, TABLE *table) const { return new (table->in_use->mem_root) - Field_tiny(addr.ptr, attr.max_char_length(), - addr.null_ptr, addr.null_bit, + Field_tiny(addr.ptr(), attr.max_char_length(), + addr.null_ptr(), addr.null_bit(), Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); } @@ -2020,8 +2967,8 @@ Field *Type_handler_short::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) - Field_short(addr.ptr, attr.max_char_length(), - addr.null_ptr, addr.null_bit, + Field_short(addr.ptr(), attr.max_char_length(), + addr.null_ptr(), addr.null_bit(), Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); } @@ -2032,8 +2979,8 @@ Field *Type_handler_int24::make_table_field(const LEX_CSTRING *name, TABLE *table) const { return new (table->in_use->mem_root) - Field_medium(addr.ptr, attr.max_char_length(), - addr.null_ptr, addr.null_bit, + Field_medium(addr.ptr(), attr.max_char_length(), + addr.null_ptr(), addr.null_bit(), Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); } @@ -2045,8 +2992,8 @@ Field *Type_handler_long::make_table_field(const LEX_CSTRING *name, TABLE *table) const { return new (table->in_use->mem_root) - Field_long(addr.ptr, attr.max_char_length(), - addr.null_ptr, addr.null_bit, + Field_long(addr.ptr(), attr.max_char_length(), + addr.null_ptr(), addr.null_bit(), Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); } @@ -2057,8 +3004,8 @@ Field *Type_handler_longlong::make_table_field(const LEX_CSTRING *name, TABLE *table) const { return new (table->in_use->mem_root) - Field_longlong(addr.ptr, attr.max_char_length(), - addr.null_ptr, addr.null_bit, + Field_longlong(addr.ptr(), attr.max_char_length(), + addr.null_ptr(), addr.null_bit(), Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); } @@ -2070,8 +3017,8 @@ Field *Type_handler_vers_trx_id::make_table_field(const LEX_CSTRING *name, TABLE *table) const { return new (table->in_use->mem_root) - Field_vers_trx_id(addr.ptr, attr.max_char_length(), - addr.null_ptr, addr.null_bit, + Field_vers_trx_id(addr.ptr(), attr.max_char_length(), + addr.null_ptr(), addr.null_bit(), Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag); } @@ -2083,8 +3030,8 @@ Field *Type_handler_float::make_table_field(const LEX_CSTRING *name, TABLE *table) const { return new (table->in_use->mem_root) - Field_float(addr.ptr, attr.max_char_length(), - addr.null_ptr, addr.null_bit, + Field_float(addr.ptr(), attr.max_char_length(), + addr.null_ptr(), addr.null_bit(), Field::NONE, name, (uint8) attr.decimals, 0/*zerofill*/, attr.unsigned_flag); } @@ -2096,8 +3043,8 @@ Field *Type_handler_double::make_table_field(const LEX_CSTRING *name, TABLE *table) const { return new (table->in_use->mem_root) - Field_double(addr.ptr, attr.max_char_length(), - addr.null_ptr, addr.null_bit, + Field_double(addr.ptr(), attr.max_char_length(), + addr.null_ptr(), addr.null_bit(), Field::NONE, name, (uint8) attr.decimals, 0/*zerofill*/, attr.unsigned_flag); } @@ -2118,7 +3065,8 @@ Type_handler_olddecimal::make_table_field(const LEX_CSTRING *name, */ DBUG_ASSERT(0); return new (table->in_use->mem_root) - Field_decimal(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field_decimal(addr.ptr(), attr.max_length, + addr.null_ptr(), addr.null_bit(), Field::NONE, name, (uint8) attr.decimals, 0/*zerofill*/,attr.unsigned_flag); } @@ -2165,7 +3113,7 @@ Type_handler_newdecimal::make_table_field(const LEX_CSTRING *name, len= required_length; } return new (table->in_use->mem_root) - Field_new_decimal(addr.ptr, len, addr.null_ptr, addr.null_bit, + Field_new_decimal(addr.ptr(), len, addr.null_ptr(), addr.null_bit(), Field::NONE, name, dec, 0/*zerofill*/, attr.unsigned_flag); } @@ -2177,7 +3125,8 @@ Field *Type_handler_year::make_table_field(const LEX_CSTRING *name, TABLE *table) const { return new (table->in_use->mem_root) - Field_year(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field_year(addr.ptr(), attr.max_length, + addr.null_ptr(), addr.null_bit(), Field::NONE, name); } @@ -2189,7 +3138,7 @@ Field *Type_handler_null::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) - Field_null(addr.ptr, attr.max_length, + Field_null(addr.ptr(), attr.max_length, Field::NONE, name, attr.collation.collation); } @@ -2201,7 +3150,7 @@ Field *Type_handler_timestamp::make_table_field(const LEX_CSTRING *name, { return new_Field_timestamp(table->in_use->mem_root, - addr.ptr, addr.null_ptr, addr.null_bit, + addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, table->s, attr.decimals); } @@ -2217,7 +3166,7 @@ Field *Type_handler_timestamp2::make_table_field(const LEX_CSTRING *name, make_table_field() for make_field() purposes in field.cc. */ return new_Field_timestamp(table->in_use->mem_root, - addr.ptr, addr.null_ptr, addr.null_bit, + addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, table->s, attr.decimals); } @@ -2229,7 +3178,7 @@ Field *Type_handler_newdate::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) - Field_newdate(addr.ptr, addr.null_ptr, addr.null_bit, + Field_newdate(addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name); } @@ -2246,7 +3195,7 @@ Field *Type_handler_date::make_table_field(const LEX_CSTRING *name, */ DBUG_ASSERT(0); return new (table->in_use->mem_root) - Field_date(addr.ptr, addr.null_ptr, addr.null_bit, + Field_date(addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name); } @@ -2258,7 +3207,7 @@ Field *Type_handler_time::make_table_field(const LEX_CSTRING *name, { return new_Field_time(table->in_use->mem_root, - addr.ptr, addr.null_ptr, addr.null_bit, + addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, attr.decimals); } @@ -2275,7 +3224,7 @@ Field *Type_handler_time2::make_table_field(const LEX_CSTRING *name, make_table_field() for make_field() purposes in field.cc. */ return new_Field_time(table->in_use->mem_root, - addr.ptr, addr.null_ptr, addr.null_bit, + addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, attr.decimals); } @@ -2287,7 +3236,7 @@ Field *Type_handler_datetime::make_table_field(const LEX_CSTRING *name, { return new_Field_datetime(table->in_use->mem_root, - addr.ptr, addr.null_ptr, addr.null_bit, + addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, attr.decimals); } @@ -2302,7 +3251,7 @@ Field *Type_handler_datetime2::make_table_field(const LEX_CSTRING *name, make_table_field() for make_field() purposes in field.cc. */ return new_Field_datetime(table->in_use->mem_root, - addr.ptr, addr.null_ptr, addr.null_bit, + addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, attr.decimals); } @@ -2314,8 +3263,8 @@ Field *Type_handler_bit::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) - Field_bit_as_char(addr.ptr, attr.max_length, - addr.null_ptr, addr.null_bit, + Field_bit_as_char(addr.ptr(), attr.max_length, + addr.null_ptr(), addr.null_bit(), Field::NONE, name); } @@ -2327,7 +3276,8 @@ Field *Type_handler_string::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) - Field_string(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field_string(addr.ptr(), attr.max_length, + addr.null_ptr(), addr.null_bit(), Field::NONE, name, attr.collation); } @@ -2339,9 +3289,9 @@ Field *Type_handler_varchar::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) - Field_varstring(addr.ptr, attr.max_length, + Field_varstring(addr.ptr(), attr.max_length, HA_VARCHAR_PACKLENGTH(attr.max_length), - addr.null_ptr, addr.null_bit, + addr.null_ptr(), addr.null_bit(), Field::NONE, name, table->s, attr.collation); } @@ -2354,7 +3304,7 @@ Field *Type_handler_tiny_blob::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) - Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, + Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, table->s, 1, attr.collation); } @@ -2367,7 +3317,7 @@ Field *Type_handler_blob::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) - Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, + Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, table->s, 2, attr.collation); } @@ -2381,7 +3331,7 @@ Type_handler_medium_blob::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) - Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, + Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, table->s, 3, attr.collation); } @@ -2394,7 +3344,7 @@ Field *Type_handler_long_blob::make_table_field(const LEX_CSTRING *name, { return new (table->in_use->mem_root) - Field_blob(addr.ptr, addr.null_ptr, addr.null_bit, + Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, table->s, 4, attr.collation); } @@ -2408,7 +3358,7 @@ Field *Type_handler_geometry::make_table_field(const LEX_CSTRING *name, TABLE *table) const { return new (table->in_use->mem_root) - Field_geom(addr.ptr, addr.null_ptr, addr.null_bit, + Field_geom(addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, name, table->s, 4, (Field::geometry_type) attr.uint_geometry_type(), 0); @@ -2424,7 +3374,8 @@ Field *Type_handler_enum::make_table_field(const LEX_CSTRING *name, TYPELIB *typelib= attr.get_typelib(); DBUG_ASSERT(typelib); return new (table->in_use->mem_root) - Field_enum(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field_enum(addr.ptr(), attr.max_length, + addr.null_ptr(), addr.null_bit(), Field::NONE, name, get_enum_pack_length(typelib->count), typelib, attr.collation); @@ -2440,7 +3391,8 @@ Field *Type_handler_set::make_table_field(const LEX_CSTRING *name, TYPELIB *typelib= attr.get_typelib(); DBUG_ASSERT(typelib); return new (table->in_use->mem_root) - Field_set(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit, + Field_set(addr.ptr(), attr.max_length, + addr.null_ptr(), addr.null_bit(), Field::NONE, name, get_enum_pack_length(typelib->count), typelib, attr.collation); @@ -2512,6 +3464,63 @@ uint32 Type_handler_general_purpose_int::max_display_length(const Item *item) /*************************************************************************/ +void Type_handler_row::Item_update_null_value(Item *item) const +{ + DBUG_ASSERT(0); + item->null_value= true; +} + + +void Type_handler_time_common::Item_update_null_value(Item *item) const +{ + MYSQL_TIME ltime; + THD *thd= current_thd; + (void) item->get_date(thd, <ime, Time::Options(TIME_TIME_ONLY, thd)); +} + + +void Type_handler_temporal_with_date::Item_update_null_value(Item *item) const +{ + MYSQL_TIME ltime; + THD *thd= current_thd; + (void) item->get_date(thd, <ime, Datetime::Options(thd)); +} + + +void Type_handler_string_result::Item_update_null_value(Item *item) const +{ + StringBuffer<MAX_FIELD_WIDTH> tmp; + (void) item->val_str(&tmp); +} + + +void Type_handler_real_result::Item_update_null_value(Item *item) const +{ + (void) item->val_real(); +} + + +void Type_handler_decimal_result::Item_update_null_value(Item *item) const +{ + my_decimal tmp; + (void) item->val_decimal(&tmp); +} + + +void Type_handler_int_result::Item_update_null_value(Item *item) const +{ + (void) item->val_int(); +} + + +void Type_handler_bool::Item_update_null_value(Item *item) const +{ + (void) item->val_bool(); +} + + +/*************************************************************************/ + int Type_handler_time_common::Item_save_in_field(Item *item, Field *field, bool no_conversions) const { @@ -2527,6 +3536,18 @@ int Type_handler_temporal_with_date::Item_save_in_field(Item *item, } +int Type_handler_timestamp_common::Item_save_in_field(Item *item, + Field *field, + bool no_conversions) + const +{ + Timestamp_or_zero_datetime_native_null tmp(field->table->in_use, item, true); + if (tmp.is_null()) + return set_field_to_null_with_conversions(field, no_conversions); + return tmp.save_in_field(field, item->decimals); +} + + int Type_handler_string_result::Item_save_in_field(Item *item, Field *field, bool no_conversions) const { @@ -2593,6 +3614,12 @@ Type_handler_temporal_with_date::set_comparator_func(Arg_comparator *cmp) const return cmp->set_cmp_func_datetime(); } +bool +Type_handler_timestamp_common::set_comparator_func(Arg_comparator *cmp) const +{ + return cmp->set_cmp_func_native(); +} + /*************************************************************************/ @@ -2704,7 +3731,7 @@ Type_handler_int_result::Item_get_cache(THD *thd, const Item *item) const Item_cache * Type_handler_year::Item_get_cache(THD *thd, const Item *item) const { - return new (thd->mem_root) Item_cache_year(thd); + return new (thd->mem_root) Item_cache_year(thd, item->type_handler()); } Item_cache * @@ -2728,7 +3755,7 @@ Type_handler_string_result::Item_get_cache(THD *thd, const Item *item) const Item_cache * Type_handler_timestamp_common::Item_get_cache(THD *thd, const Item *item) const { - return new (thd->mem_root) Item_cache_datetime(thd); + return new (thd->mem_root) Item_cache_timestamp(thd); } Item_cache * @@ -2749,6 +3776,22 @@ Type_handler_date_common::Item_get_cache(THD *thd, const Item *item) const return new (thd->mem_root) Item_cache_date(thd); } + +/*************************************************************************/ + +Item_copy * +Type_handler::create_item_copy(THD *thd, Item *item) const +{ + return new (thd->mem_root) Item_copy_string(thd, item); +} + + +Item_copy * +Type_handler_timestamp_common::create_item_copy(THD *thd, Item *item) const +{ + return new (thd->mem_root) Item_copy_timestamp(thd, item); +} + /*************************************************************************/ bool Type_handler_int_result:: @@ -2824,8 +3867,21 @@ bool Type_handler_typelib:: TYPELIB *typelib= NULL; for (uint i= 0; i < nitems; i++) { - if ((typelib= items[i]->get_typelib())) - break; + TYPELIB *typelib2; + if ((typelib2= items[i]->get_typelib())) + { + if (typelib) + { + /* + Two ENUM/SET columns found. We convert such combinations to VARCHAR. + This may change in the future to preserve ENUM/SET + if typelib definitions are equal. + */ + handler->set_handler(&type_handler_varchar); + return func->aggregate_attributes_string(func_name, items, nitems); + } + typelib= typelib2; + } } DBUG_ASSERT(typelib); // There must be at least one typelib func->set_typelib(typelib); @@ -2933,6 +3989,106 @@ bool Type_handler:: } +bool Type_handler_temporal_result:: + Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, + Item **items, uint nitems) const +{ + bool rc= Type_handler::Item_func_min_max_fix_attributes(thd, func, + items, nitems); + bool is_time= func->field_type() == MYSQL_TYPE_TIME; + func->decimals= 0; + for (uint i= 0; i < nitems; i++) + { + uint deci= is_time ? items[i]->time_precision(thd) : + items[i]->datetime_precision(thd); + set_if_bigger(func->decimals, deci); + } + + if (rc || func->maybe_null) + return rc; + /* + LEAST/GREATES(non-temporal, temporal) can return NULL. + CAST functions Item_{time|datetime|date}_typecast always set maybe_full + to true. Here we try to detect nullability more thoroughly. + Perhaps CAST functions should also reuse this idea eventually. + */ + const Type_handler *hf= func->type_handler(); + for (uint i= 0; i < nitems; i++) + { + /* + If items[i] does not need conversion to the current temporal data + type, then we trust items[i]->maybe_null, which was already ORred + to func->maybe_null in the argument loop in fix_fields(). + If items[i] requires conversion to the current temporal data type, + then conversion can fail and return NULL even for NOT NULL items. + */ + const Type_handler *ha= items[i]->type_handler(); + if (hf == ha) + continue; // No conversion. + if (ha->cmp_type() != TIME_RESULT) + { + func->maybe_null= true; // Conversion from non-temporal is not safe + break; + } + timestamp_type tf= hf->mysql_timestamp_type(); + timestamp_type ta= ha->mysql_timestamp_type(); + if (tf == ta || + (tf == MYSQL_TIMESTAMP_DATETIME && ta == MYSQL_TIMESTAMP_DATE)) + { + /* + If handlers have the same mysql_timestamp_type(), + then conversion is NULL safe. Conversion from DATE to DATETIME + is also safe. This branch includes data type pairs: + Function return type Argument type Comment + -------------------- ------------- ------------- + TIMESTAMP TIMESTAMP no conversion + TIMESTAMP DATETIME not possible + TIMESTAMP DATE not possible + DATETIME DATETIME no conversion + DATETIME TIMESTAMP safe conversion + DATETIME DATE safe conversion + DATE DATE no conversion + TIME TIME no conversion + + Note, a function cannot return TIMESTAMP if it has non-TIMESTAMP + arguments (it would return DATETIME in such case). + */ + DBUG_ASSERT(hf->field_type() != MYSQL_TYPE_TIMESTAMP || tf == ta); + continue; + } + /* + Here we have the following data type pairs that did not match + the condition above: + + Function return type Argument type Comment + -------------------- ------------- ------- + TIMESTAMP TIME Not possible + DATETIME TIME depends on OLD_MODE_ZERO_DATE_TIME_CAST + DATE TIMESTAMP Not possible + DATE DATETIME Not possible + DATE TIME Not possible + TIME TIMESTAMP Not possible + TIME DATETIME Not possible + TIME DATE Not possible + + Most pairs are not possible, because the function data type + would be DATETIME (according to LEAST/GREATEST aggregation rules). + Conversion to DATETIME from TIME is not safe when + OLD_MODE_ZERO_DATE_TIME_CAST is set: + - negative TIME values cannot be converted to not-NULL DATETIME values + - TIME values can produce DATETIME values that do not pass + NO_ZERO_DATE and NO_ZERO_IN_DATE tests. + */ + DBUG_ASSERT(hf->field_type() == MYSQL_TYPE_DATETIME); + if (!(thd->variables.old_behavior & OLD_MODE_ZERO_DATE_TIME_CAST)) + continue; + func->maybe_null= true; + break; + } + return rc; +} + + bool Type_handler_real_result:: Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, Item **items, uint nitems) const @@ -2983,6 +4139,13 @@ bool Type_handler_int_result:: } +bool Type_handler_bool:: + Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const +{ + return Item_sum_hybrid_fix_length_and_dec_numeric(func, &type_handler_bool); +} + + bool Type_handler_real_result:: Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const { @@ -3211,15 +4374,6 @@ bool Type_handler_int_result::Item_val_bool(Item *item) const return item->val_int() != 0; } -bool Type_handler_decimal_result::Item_val_bool(Item *item) const -{ - my_decimal decimal_value; - my_decimal *val= item->val_decimal(&decimal_value); - if (val) - return !my_decimal_is_zero(val); - return false; -} - bool Type_handler_temporal_result::Item_val_bool(Item *item) const { return item->val_real() != 0.0; @@ -3233,48 +4387,89 @@ bool Type_handler_string_result::Item_val_bool(Item *item) const /*************************************************************************/ -bool Type_handler_int_result::Item_get_date(Item *item, MYSQL_TIME *ltime, - ulonglong fuzzydate) const + +bool Type_handler::Item_get_date_with_warn(THD *thd, Item *item, + MYSQL_TIME *ltime, + date_mode_t fuzzydate) const +{ + Temporal::Warn_push warn(thd, item->field_table_or_null(), + item->field_name_or_null(), ltime, fuzzydate); + Item_get_date(thd, item, &warn, ltime, fuzzydate); + return ltime->time_type < 0; +} + + +bool Type_handler::Item_func_hybrid_field_type_get_date_with_warn(THD *thd, + Item_func_hybrid_field_type *item, + MYSQL_TIME *ltime, + date_mode_t mode) const { - return item->get_date_from_int(ltime, fuzzydate); + Temporal::Warn_push warn(thd, item->field_table_or_null(), + item->field_name_or_null(), ltime, mode); + Item_func_hybrid_field_type_get_date(thd, item, &warn, ltime, mode); + return ltime->time_type < 0; } -bool Type_handler_year::Item_get_date(Item *item, MYSQL_TIME *ltime, - ulonglong fuzzydate) const +/************************************************************************/ +void Type_handler_decimal_result::Item_get_date(THD *thd, Item *item, + Temporal::Warn *warn, + MYSQL_TIME *ltime, + date_mode_t fuzzydate) const { - return item->get_date_from_year(ltime, fuzzydate); + new(ltime) Temporal_hybrid(thd, warn, VDec(item).ptr(), fuzzydate); } -bool Type_handler_real_result::Item_get_date(Item *item, MYSQL_TIME *ltime, - ulonglong fuzzydate) const +void Type_handler_int_result::Item_get_date(THD *thd, Item *item, + Temporal::Warn *warn, + MYSQL_TIME *to, + date_mode_t mode) const { - return item->get_date_from_real(ltime, fuzzydate); + new(to) Temporal_hybrid(thd, warn, item->to_longlong_hybrid_null(), mode); } -bool Type_handler_decimal_result::Item_get_date(Item *item, MYSQL_TIME *ltime, - ulonglong fuzzydate) const +void Type_handler_year::Item_get_date(THD *thd, Item *item, + Temporal::Warn *warn, + MYSQL_TIME *ltime, + date_mode_t fuzzydate) const { - return item->get_date_from_decimal(ltime, fuzzydate); + VYear year(item); + DBUG_ASSERT(!year.truncated()); + Longlong_hybrid_null nr(Longlong_null(year.to_YYYYMMDD(), year.is_null()), + item->unsigned_flag); + new(ltime) Temporal_hybrid(thd, warn, nr, fuzzydate); } -bool Type_handler_string_result::Item_get_date(Item *item, MYSQL_TIME *ltime, - ulonglong fuzzydate) const +void Type_handler_real_result::Item_get_date(THD *thd, Item *item, + Temporal::Warn *warn, + MYSQL_TIME *ltime, + date_mode_t fuzzydate) const { - return item->get_date_from_string(ltime, fuzzydate); + new(ltime) Temporal_hybrid(thd, warn, item->to_double_null(), fuzzydate); } -bool Type_handler_temporal_result::Item_get_date(Item *item, MYSQL_TIME *ltime, - ulonglong fuzzydate) const +void Type_handler_string_result::Item_get_date(THD *thd, Item *item, + Temporal::Warn *warn, + MYSQL_TIME *ltime, + date_mode_t mode) const +{ + StringBuffer<40> tmp; + new(ltime) Temporal_hybrid(thd, warn, item->val_str(&tmp), mode); +} + + +void Type_handler_temporal_result::Item_get_date(THD *thd, Item *item, + Temporal::Warn *warn, + MYSQL_TIME *ltime, + date_mode_t fuzzydate) const { DBUG_ASSERT(0); // Temporal type items must implement native get_date() item->null_value= true; - set_zero_time(ltime, mysql_timestamp_type()); - return true; + set_zero_time(ltime, MYSQL_TIMESTAMP_NONE); } @@ -3324,12 +4519,6 @@ longlong Type_handler_int_result:: return item->val_int_unsigned_typecast_from_int(); } -longlong Type_handler_decimal_result:: - Item_val_int_unsigned_typecast(Item *item) const -{ - return item->val_int_unsigned_typecast_from_decimal(); -} - longlong Type_handler_temporal_result:: Item_val_int_unsigned_typecast(Item *item) const { @@ -3390,7 +4579,7 @@ Type_handler_decimal_result::Item_func_hybrid_field_type_val_str( Item_func_hybrid_field_type *item, String *str) const { - return item->val_str_from_decimal_op(str); + return VDec_op(item).to_string_round(str, item->decimals); } @@ -3399,7 +4588,7 @@ Type_handler_decimal_result::Item_func_hybrid_field_type_val_real( Item_func_hybrid_field_type *item) const { - return item->val_real_from_decimal_op(); + return VDec_op(item).to_double(); } @@ -3408,7 +4597,7 @@ Type_handler_decimal_result::Item_func_hybrid_field_type_val_int( Item_func_hybrid_field_type *item) const { - return item->val_int_from_decimal_op(); + return VDec_op(item).to_longlong(item->unsigned_flag); } @@ -3417,17 +4606,35 @@ Type_handler_decimal_result::Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *item, my_decimal *dec) const { - return item->val_decimal_from_decimal_op(dec); + return VDec_op(item).to_decimal(dec); } -bool +void Type_handler_decimal_result::Item_func_hybrid_field_type_get_date( + THD *thd, + Item_func_hybrid_field_type *item, + Temporal::Warn *warn, + MYSQL_TIME *ltime, + date_mode_t fuzzydate) const +{ + new (ltime) Temporal_hybrid(thd, warn, VDec_op(item).ptr(), fuzzydate); +} + + +void +Type_handler_year::Item_func_hybrid_field_type_get_date( + THD *thd, Item_func_hybrid_field_type *item, + Temporal::Warn *warn, MYSQL_TIME *ltime, - ulonglong fuzzydate) const + date_mode_t fuzzydate) const { - return item->get_date_from_decimal_op(ltime, fuzzydate); + VYear_op year(item); + DBUG_ASSERT(!year.truncated()); + Longlong_hybrid_null nr(Longlong_null(year.to_YYYYMMDD(), year.is_null()), + item->unsigned_flag); + new(ltime) Temporal_hybrid(thd, warn, nr, fuzzydate); } @@ -3470,17 +4677,18 @@ Type_handler_int_result::Item_func_hybrid_field_type_val_decimal( } -bool +void Type_handler_int_result::Item_func_hybrid_field_type_get_date( + THD *thd, Item_func_hybrid_field_type *item, - MYSQL_TIME *ltime, - ulonglong fuzzydate) const + Temporal::Warn *warn, + MYSQL_TIME *to, + date_mode_t mode) const { - return item->get_date_from_int_op(ltime, fuzzydate); + new(to) Temporal_hybrid(thd, warn, item->to_longlong_hybrid_null_op(), mode); } - /***************************************************************************/ String * @@ -3519,13 +4727,15 @@ Type_handler_real_result::Item_func_hybrid_field_type_val_decimal( } -bool +void Type_handler_real_result::Item_func_hybrid_field_type_get_date( + THD *thd, Item_func_hybrid_field_type *item, - MYSQL_TIME *ltime, - ulonglong fuzzydate) const + Temporal::Warn *warn, + MYSQL_TIME *to, + date_mode_t mode) const { - return item->get_date_from_real_op(ltime, fuzzydate); + new(to) Temporal_hybrid(thd, warn, item->to_double_null_op(), mode); } @@ -3567,13 +4777,16 @@ Type_handler_temporal_result::Item_func_hybrid_field_type_val_decimal( } -bool +void Type_handler_temporal_result::Item_func_hybrid_field_type_get_date( + THD *thd, Item_func_hybrid_field_type *item, + Temporal::Warn *warn, MYSQL_TIME *ltime, - ulonglong fuzzydate) const + date_mode_t fuzzydate) const { - return item->date_op(ltime, fuzzydate); + if (item->date_op(thd, ltime, fuzzydate)) + set_zero_time(ltime, MYSQL_TIMESTAMP_NONE); } @@ -3615,13 +4828,16 @@ Type_handler_time_common::Item_func_hybrid_field_type_val_decimal( } -bool +void Type_handler_time_common::Item_func_hybrid_field_type_get_date( + THD *thd, Item_func_hybrid_field_type *item, + Temporal::Warn *warn, MYSQL_TIME *ltime, - ulonglong fuzzydate) const + date_mode_t fuzzydate) const { - return item->time_op(ltime); + if (item->time_op(thd, ltime)) + set_zero_time(ltime, MYSQL_TIMESTAMP_NONE); } @@ -3663,13 +4879,18 @@ Type_handler_string_result::Item_func_hybrid_field_type_val_decimal( } -bool +void Type_handler_string_result::Item_func_hybrid_field_type_get_date( + THD *thd, Item_func_hybrid_field_type *item, + Temporal::Warn *warn, MYSQL_TIME *ltime, - ulonglong fuzzydate) const + date_mode_t mode) const { - return item->get_date_from_str_op(ltime, fuzzydate); + StringBuffer<40> tmp; + String *res= item->str_op(&tmp); + DBUG_ASSERT((res == NULL) == item->null_value); + new(ltime) Temporal_hybrid(thd, warn, res, mode); } /***************************************************************************/ @@ -3707,10 +4928,22 @@ longlong Type_handler_string_result:: return func->val_int_cmp_string(); } -longlong Type_handler_temporal_result:: +longlong Type_handler_temporal_with_date:: + Item_func_between_val_int(Item_func_between *func) const +{ + return func->val_int_cmp_datetime(); +} + +longlong Type_handler_time_common:: Item_func_between_val_int(Item_func_between *func) const { - return func->val_int_cmp_temporal(); + return func->val_int_cmp_time(); +} + +longlong Type_handler_timestamp_common:: + Item_func_between_val_int(Item_func_between *func) const +{ + return func->val_int_cmp_native(); } longlong Type_handler_int_result:: @@ -3776,6 +5009,12 @@ cmp_item *Type_handler_temporal_with_date::make_cmp_item(THD *thd, return new (thd->mem_root) cmp_item_datetime; } +cmp_item *Type_handler_timestamp_common::make_cmp_item(THD *thd, + CHARSET_INFO *cs) const +{ + return new (thd->mem_root) cmp_item_timestamp; +} + /***************************************************************************/ static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y) @@ -3836,6 +5075,15 @@ Type_handler_temporal_with_date::make_in_vector(THD *thd, } +in_vector * +Type_handler_timestamp_common::make_in_vector(THD *thd, + const Item_func_in *func, + uint nargs) const +{ + return new (thd->mem_root) in_timestamp(thd, nargs); +} + + in_vector *Type_handler_row::make_in_vector(THD *thd, const Item_func_in *func, uint nargs) const @@ -3930,10 +5178,33 @@ String *Type_handler_string_result:: } -String *Type_handler_temporal_result:: +String *Type_handler_time_common:: Item_func_min_max_val_str(Item_func_min_max *func, String *str) const { - return func->val_string_from_date(str); + return Time(func).to_string(str, func->decimals); +} + + +String *Type_handler_date_common:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + return Date(func).to_string(str); +} + + +String *Type_handler_datetime_common:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + return Datetime(func).to_string(str, func->decimals); +} + + +String *Type_handler_timestamp_common:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + THD *thd= current_thd; + return Timestamp_or_zero_datetime_native_null(thd, func). + to_datetime(thd).to_string(str, func->decimals); } @@ -3947,7 +5218,7 @@ String *Type_handler_int_result:: String *Type_handler_decimal_result:: Item_func_min_max_val_str(Item_func_min_max *func, String *str) const { - return func->val_string_from_decimal(str); + return VDec(func).to_string_round(str, func->decimals); } @@ -3965,13 +5236,33 @@ double Type_handler_string_result:: } -double Type_handler_temporal_result:: +double Type_handler_time_common:: Item_func_min_max_val_real(Item_func_min_max *func) const { - MYSQL_TIME ltime; - if (func->get_date(<ime, 0)) - return 0; - return TIME_to_double(<ime); + return Time(current_thd, func).to_double(); +} + + +double Type_handler_date_common:: + Item_func_min_max_val_real(Item_func_min_max *func) const +{ + return Date(current_thd, func).to_double(); +} + + +double Type_handler_datetime_common:: + Item_func_min_max_val_real(Item_func_min_max *func) const +{ + return Datetime(current_thd, func).to_double(); +} + + +double Type_handler_timestamp_common:: + Item_func_min_max_val_real(Item_func_min_max *func) const +{ + THD *thd= current_thd; + return Timestamp_or_zero_datetime_native_null(thd, func). + to_datetime(thd).to_double(); } @@ -3989,13 +5280,33 @@ longlong Type_handler_string_result:: } -longlong Type_handler_temporal_result:: +longlong Type_handler_time_common:: Item_func_min_max_val_int(Item_func_min_max *func) const { - MYSQL_TIME ltime; - if (func->get_date(<ime, 0)) - return 0; - return TIME_to_ulonglong(<ime); + return Time(current_thd, func).to_longlong(); +} + + +longlong Type_handler_date_common:: + Item_func_min_max_val_int(Item_func_min_max *func) const +{ + return Date(current_thd, func).to_longlong(); +} + + +longlong Type_handler_datetime_common:: + Item_func_min_max_val_int(Item_func_min_max *func) const +{ + return Datetime(current_thd, func).to_longlong(); +} + + +longlong Type_handler_timestamp_common:: + Item_func_min_max_val_int(Item_func_min_max *func) const +{ + THD *thd= current_thd; + return Timestamp_or_zero_datetime_native_null(thd, func). + to_datetime(thd).to_longlong(); } @@ -4022,20 +5333,43 @@ my_decimal *Type_handler_numeric:: } -my_decimal *Type_handler_temporal_result:: +my_decimal *Type_handler_time_common:: Item_func_min_max_val_decimal(Item_func_min_max *func, my_decimal *dec) const { - MYSQL_TIME ltime; - if (func->get_date(<ime, 0)) - return 0; - return date2my_decimal(<ime, dec); + return Time(current_thd, func).to_decimal(dec); +} + + +my_decimal *Type_handler_date_common:: + Item_func_min_max_val_decimal(Item_func_min_max *func, + my_decimal *dec) const +{ + return Date(current_thd, func).to_decimal(dec); +} + + +my_decimal *Type_handler_datetime_common:: + Item_func_min_max_val_decimal(Item_func_min_max *func, + my_decimal *dec) const +{ + return Datetime(current_thd, func).to_decimal(dec); +} + + +my_decimal *Type_handler_timestamp_common:: + Item_func_min_max_val_decimal(Item_func_min_max *func, + my_decimal *dec) const +{ + THD *thd= current_thd; + return Timestamp_or_zero_datetime_native_null(thd, func). + to_datetime(thd).to_decimal(dec); } bool Type_handler_string_result:: - Item_func_min_max_get_date(Item_func_min_max *func, - MYSQL_TIME *ltime, ulonglong fuzzydate) const + Item_func_min_max_get_date(THD *thd, Item_func_min_max *func, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const { /* just like ::val_int() method of a string item can be called, @@ -4043,30 +5377,51 @@ bool Type_handler_string_result:: ::get_date() can be called for non-temporal values, for example, SELECT MONTH(GREATEST("2011-11-21", "2010-10-09")) */ - return func->get_date_from_string(ltime, fuzzydate); + return func->get_date_from_string(thd, ltime, fuzzydate); } bool Type_handler_numeric:: - Item_func_min_max_get_date(Item_func_min_max *func, - MYSQL_TIME *ltime, ulonglong fuzzydate) const + Item_func_min_max_get_date(THD *thd, Item_func_min_max *func, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const { - return Item_get_date(func, ltime, fuzzydate); + return Item_get_date_with_warn(thd, func, ltime, fuzzydate); } bool Type_handler_temporal_result:: - Item_func_min_max_get_date(Item_func_min_max *func, - MYSQL_TIME *ltime, ulonglong fuzzydate) const + Item_func_min_max_get_date(THD *thd, Item_func_min_max *func, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const { - return func->get_date_native(ltime, fuzzydate); + /* + - If the caller specified TIME_TIME_ONLY, then it's going to convert + a DATETIME or DATE to TIME. So we pass the default flags for date. This is + exactly the same with what Item_func_min_max_val_{int|real|decimal|str} or + Item_send_datetime() do. We return the value in accordance with the + current session date flags and let the caller further convert it to TIME. + - If the caller did not specify TIME_TIME_ONLY, then return the value + according to the flags supplied by the caller. + */ + return func->get_date_native(thd, ltime, + fuzzydate & TIME_TIME_ONLY ? + Datetime::Options(thd) : + fuzzydate); } bool Type_handler_time_common:: - Item_func_min_max_get_date(Item_func_min_max *func, - MYSQL_TIME *ltime, ulonglong fuzzydate) const + Item_func_min_max_get_date(THD *thd, Item_func_min_max *func, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const +{ + return func->get_time_native(thd, ltime); +} + + +bool Type_handler_timestamp_common:: + Item_func_min_max_get_date(THD *thd, Item_func_min_max *func, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const { - return func->get_time_native(ltime); + return Timestamp_or_zero_datetime_native_null(thd, func). + to_datetime(thd).copy_to_mysql_time(ltime); } /***************************************************************************/ @@ -4531,7 +5886,7 @@ bool Type_handler:: Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const { uint dec= item->decimals == NOT_FIXED_DEC ? - item->arguments()[0]->time_precision() : + item->arguments()[0]->time_precision(current_thd) : item->decimals; item->fix_attributes_temporal(MIN_TIME_WIDTH, dec); item->maybe_null= true; @@ -4553,7 +5908,7 @@ bool Type_handler:: const { uint dec= item->decimals == NOT_FIXED_DEC ? - item->arguments()[0]->datetime_precision() : + item->arguments()[0]->datetime_precision(current_thd) : item->decimals; item->fix_attributes_temporal(MAX_DATETIME_WIDTH, dec); item->maybe_null= true; @@ -4873,32 +6228,35 @@ bool Type_handler_string_result:: /***************************************************************************/ -uint Type_handler::Item_time_precision(Item *item) const +uint Type_handler::Item_time_precision(THD *thd, Item *item) const { return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS); } -uint Type_handler::Item_datetime_precision(Item *item) const +uint Type_handler::Item_datetime_precision(THD *thd, Item *item) const { return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS); } -uint Type_handler_string_result::Item_temporal_precision(Item *item, +uint Type_handler_string_result::Item_temporal_precision(THD *thd, Item *item, bool is_time) const { - MYSQL_TIME ltime; StringBuffer<64> buf; String *tmp; MYSQL_TIME_STATUS status; - DBUG_ASSERT(item->fixed); + DBUG_ASSERT(item->is_fixed()); + // Nanosecond rounding is not needed here, for performance purposes if ((tmp= item->val_str(&buf)) && - !(is_time ? - str_to_time(tmp->charset(), tmp->ptr(), tmp->length(), - <ime, TIME_TIME_ONLY, &status) : - str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(), - <ime, TIME_FUZZY_DATES, &status))) + (is_time ? + Time(thd, &status, tmp->ptr(), tmp->length(), tmp->charset(), + Time::Options(TIME_TIME_ONLY, TIME_FRAC_TRUNCATE, + Time::DATETIME_TO_TIME_YYYYMMDD_TRUNCATE)). + is_valid_time() : + Datetime(thd, &status, tmp->ptr(), tmp->length(), tmp->charset(), + Datetime::Options(TIME_FUZZY_DATES, TIME_FRAC_TRUNCATE)). + is_valid_datetime())) return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS); return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS); } @@ -5087,7 +6445,7 @@ bool Type_handler::check_null(const Item *item, st_value *value) const bool Type_handler_null:: - Item_save_in_value(Item *item, st_value *value) const + Item_save_in_value(THD *thd, Item *item, st_value *value) const { value->m_type= DYN_COL_NULL; return true; @@ -5095,7 +6453,7 @@ bool Type_handler_null:: bool Type_handler_row:: - Item_save_in_value(Item *item, st_value *value) const + Item_save_in_value(THD *thd, Item *item, st_value *value) const { DBUG_ASSERT(0); value->m_type= DYN_COL_NULL; @@ -5104,7 +6462,7 @@ bool Type_handler_row:: bool Type_handler_int_result:: - Item_save_in_value(Item *item, st_value *value) const + Item_save_in_value(THD *thd, Item *item, st_value *value) const { value->m_type= item->unsigned_flag ? DYN_COL_UINT : DYN_COL_INT; value->value.m_longlong= item->val_int(); @@ -5113,7 +6471,7 @@ bool Type_handler_int_result:: bool Type_handler_real_result:: - Item_save_in_value(Item *item, st_value *value) const + Item_save_in_value(THD *thd, Item *item, st_value *value) const { value->m_type= DYN_COL_DOUBLE; value->value.m_double= item->val_real(); @@ -5122,7 +6480,7 @@ bool Type_handler_real_result:: bool Type_handler_decimal_result:: - Item_save_in_value(Item *item, st_value *value) const + Item_save_in_value(THD *thd, Item *item, st_value *value) const { value->m_type= DYN_COL_DECIMAL; my_decimal *dec= item->val_decimal(&value->m_decimal); @@ -5133,7 +6491,7 @@ bool Type_handler_decimal_result:: bool Type_handler_string_result:: - Item_save_in_value(Item *item, st_value *value) const + Item_save_in_value(THD *thd, Item *item, st_value *value) const { value->m_type= DYN_COL_STRING; String *str= item->val_str(&value->m_string); @@ -5144,19 +6502,20 @@ bool Type_handler_string_result:: bool Type_handler_temporal_with_date:: - Item_save_in_value(Item *item, st_value *value) const + Item_save_in_value(THD *thd, Item *item, st_value *value) const { value->m_type= DYN_COL_DATETIME; - item->get_date(&value->value.m_time, sql_mode_for_dates(current_thd)); + item->get_date(thd, &value->value.m_time, + Datetime::Options(thd, TIME_FRAC_NONE)); return check_null(item, value); } bool Type_handler_time_common:: - Item_save_in_value(Item *item, st_value *value) const + Item_save_in_value(THD *thd, Item *item, st_value *value) const { value->m_type= DYN_COL_DATETIME; - item->get_time(&value->value.m_time); + item->get_time(thd, &value->value.m_time); return check_null(item, value); } @@ -5337,10 +6696,23 @@ bool Type_handler:: } +bool Type_handler::Item_send_timestamp(Item *item, + Protocol *protocol, + st_value *buf) const +{ + Timestamp_or_zero_datetime_native_null native(protocol->thd, item); + if (native.is_null()) + return protocol->store_null(); + native.to_TIME(protocol->thd, &buf->value.m_time); + return protocol->store(&buf->value.m_time, item->decimals); +} + + bool Type_handler:: Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const { - item->get_date(&buf->value.m_time, sql_mode_for_dates(current_thd)); + item->get_date(protocol->thd, &buf->value.m_time, + Datetime::Options(protocol->thd)); if (!item->null_value) return protocol->store(&buf->value.m_time, item->decimals); return protocol->store_null(); @@ -5350,7 +6722,8 @@ bool Type_handler:: bool Type_handler:: Item_send_date(Item *item, Protocol *protocol, st_value *buf) const { - item->get_date(&buf->value.m_time, sql_mode_for_dates(current_thd)); + item->get_date(protocol->thd, &buf->value.m_time, + Date::Options(protocol->thd)); if (!item->null_value) return protocol->store_date(&buf->value.m_time); return protocol->store_null(); @@ -5360,7 +6733,7 @@ bool Type_handler:: bool Type_handler:: Item_send_time(Item *item, Protocol *protocol, st_value *buf) const { - item->get_time(&buf->value.m_time); + item->get_time(protocol->thd, &buf->value.m_time); if (!item->null_value) return protocol->store_time(&buf->value.m_time, item->decimals); return protocol->store_null(); @@ -5393,11 +6766,10 @@ Item *Type_handler_real_result:: Item *Type_handler_decimal_result:: make_const_item_for_comparison(THD *thd, Item *item, const Item *cmp) const { - my_decimal decimal_value; - my_decimal *result= item->val_decimal(&decimal_value); - if (item->null_value) + VDec result(item); + if (result.is_null()) return new (thd->mem_root) Item_null(thd, item->name.str); - return new (thd->mem_root) Item_decimal(thd, item->name.str, result, + return new (thd->mem_root) Item_decimal(thd, item->name.str, result.ptr(), item->max_length, item->decimals); } @@ -5420,7 +6792,7 @@ Item *Type_handler_time_common:: make_const_item_for_comparison(THD *thd, Item *item, const Item *cmp) const { Item_cache_temporal *cache; - longlong value= item->val_time_packed(); + longlong value= item->val_time_packed(thd); if (item->null_value) return new (thd->mem_root) Item_null(thd, item->name.str); cache= new (thd->mem_root) Item_cache_time(thd); @@ -5434,7 +6806,7 @@ Item *Type_handler_temporal_with_date:: make_const_item_for_comparison(THD *thd, Item *item, const Item *cmp) const { Item_cache_temporal *cache; - longlong value= item->val_datetime_packed(); + longlong value= item->val_datetime_packed(thd); if (item->null_value) return new (thd->mem_root) Item_null(thd, item->name.str); cache= new (thd->mem_root) Item_cache_datetime(thd); @@ -5636,6 +7008,21 @@ Item *Type_handler_long_blob:: return new (thd->mem_root) Item_char_typecast(thd, item, len, real_cs); } +Item *Type_handler_interval_DDhhmmssff:: + create_typecast_item(THD *thd, Item *item, + const Type_cast_attributes &attr) const +{ + if (attr.decimals() > MAX_DATETIME_PRECISION) + { + wrong_precision_error(ER_TOO_BIG_PRECISION, item, attr.decimals(), + MAX_DATETIME_PRECISION); + return 0; + } + return new (thd->mem_root) Item_interval_DDhhmmssff_typecast(thd, item, + (uint) + attr.decimals()); +} + /***************************************************************************/ void Type_handler_string_result::Item_param_setup_conversion(THD *thd, @@ -5787,6 +7174,490 @@ void Type_handler_geometry::Item_param_set_param_func(Item_param *param, /***************************************************************************/ +Field *Type_handler_row:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + DBUG_ASSERT(attr->length == 0); + DBUG_ASSERT(f_maybe_null(attr->pack_flag)); + return new (mem_root) Field_row(rec.ptr(), name); +} + + +Field *Type_handler_olddecimal:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_decimal(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_decimals(attr->pack_flag), + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_newdecimal:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_new_decimal(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_decimals(attr->pack_flag), + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_float:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + int decimals= f_decimals(attr->pack_flag); + if (decimals == FLOATING_POINT_DECIMALS) + decimals= NOT_FIXED_DEC; + return new (mem_root) + Field_float(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, decimals, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag)== 0); +} + + +Field *Type_handler_double:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + int decimals= f_decimals(attr->pack_flag); + if (decimals == FLOATING_POINT_DECIMALS) + decimals= NOT_FIXED_DEC; + return new (mem_root) + Field_double(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, decimals, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag)== 0); +} + + +Field *Type_handler_tiny:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_tiny(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_short:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_short(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_int24:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_medium(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_long:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_long(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_longlong:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG)) + return new (mem_root) + Field_vers_trx_id(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); + return new (mem_root) + Field_longlong(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + +Field *Type_handler_timestamp:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new_Field_timestamp(mem_root, + rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, + attr->temporal_dec(MAX_DATETIME_WIDTH)); +} + + +Field *Type_handler_timestamp2:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_timestampf(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, + name, share, attr->temporal_dec(MAX_DATETIME_WIDTH)); +} + + +Field *Type_handler_year:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_year(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name); +} + + +Field *Type_handler_date:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_date(rec.ptr(),rec.null_ptr(),rec.null_bit(), + attr->unireg_check, name); +} + + +Field *Type_handler_newdate:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_newdate(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name); +} + + +Field *Type_handler_time:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new_Field_time(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + attr->temporal_dec(MIN_TIME_WIDTH)); +} + + +Field *Type_handler_time2:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_timef(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + attr->temporal_dec(MIN_TIME_WIDTH)); +} + + +Field *Type_handler_datetime:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new_Field_datetime(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + attr->temporal_dec(MAX_DATETIME_WIDTH)); +} + + +Field *Type_handler_datetime2:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_datetimef(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + attr->temporal_dec(MAX_DATETIME_WIDTH)); +} + + +Field *Type_handler_null:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_null(rec.ptr(), (uint32) attr->length, attr->unireg_check, + name, attr->charset); +} + + +Field *Type_handler_bit:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return f_bit_as_char(attr->pack_flag) ? + new (mem_root) Field_bit_as_char(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name) : + new (mem_root) Field_bit(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + bit.ptr(), bit.offs(), attr->unireg_check, name); +} + + +#ifdef HAVE_SPATIAL +Field *Type_handler_geometry:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + status_var_increment(current_thd->status_var.feature_gis); + return new (mem_root) + Field_geom(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, + attr->pack_flag_to_pack_length(), attr->geom_type, attr->srid); +} +#endif + + +Field *Type_handler_string:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_string(rec.ptr(), (uint32) attr->length, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, attr->charset); +} + + +Field *Type_handler_varchar:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + if (attr->unireg_check == Field::TMYSQL_COMPRESSED) + return new (mem_root) + Field_varstring_compressed(rec.ptr(), (uint32) attr->length, + HA_VARCHAR_PACKLENGTH((uint32) attr->length), + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, attr->charset, + zlib_compression_method); + return new (mem_root) + Field_varstring(rec.ptr(), (uint32) attr->length, + HA_VARCHAR_PACKLENGTH((uint32) attr->length), + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, attr->charset); +} + + +Field *Type_handler_blob_common:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + if (attr->unireg_check == Field::TMYSQL_COMPRESSED) + return new (mem_root) + Field_blob_compressed(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, + attr->pack_flag_to_pack_length(), attr->charset, + zlib_compression_method); + return new (mem_root) + Field_blob(rec.ptr(), rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, share, + attr->pack_flag_to_pack_length(), attr->charset); +} + + +Field *Type_handler_enum:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_enum(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, attr->pack_flag_to_pack_length(), + attr->interval, attr->charset); +} + + +Field *Type_handler_set:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + return new (mem_root) + Field_set(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, attr->pack_flag_to_pack_length(), + attr->interval, attr->charset); +} + + +/***************************************************************************/ + +void Type_handler:: + Column_definition_attributes_frm_pack(const Column_definition_attributes *def, + uchar *buff) const +{ + def->frm_pack_basic(buff); + def->frm_pack_charset(buff); +} + + +#ifdef HAVE_SPATIAL +void Type_handler_geometry:: + Column_definition_attributes_frm_pack(const Column_definition_attributes *def, + uchar *buff) const +{ + def->frm_pack_basic(buff); + buff[11]= 0; + buff[14]= (uchar) def->geom_type; +} +#endif + + +/***************************************************************************/ + +bool Type_handler:: + Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, + TABLE_SHARE *share, + const uchar *buffer, + LEX_CUSTRING *gis_options) + const +{ + attr->frm_unpack_basic(buffer); + return attr->frm_unpack_charset(share, buffer); +} + + +#ifdef HAVE_SPATIAL +bool Type_handler_geometry:: + Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, + TABLE_SHARE *share, + const uchar *buffer, + LEX_CUSTRING *gis_options) + const +{ + uint gis_opt_read, gis_length, gis_decimals; + Field_geom::storage_type st_type; + attr->frm_unpack_basic(buffer); + // charset and geometry_type share the same byte in frm + attr->geom_type= (Field::geometry_type) buffer[14]; + gis_opt_read= gis_field_options_read(gis_options->str, + gis_options->length, + &st_type, &gis_length, + &gis_decimals, &attr->srid); + gis_options->str+= gis_opt_read; + gis_options->length-= gis_opt_read; + return false; +} +#endif + +/***************************************************************************/ + bool Type_handler::Vers_history_point_resolve_unit(THD *thd, Vers_history_point *point) const @@ -5845,3 +7716,480 @@ bool Type_handler_general_purpose_string:: } /***************************************************************************/ + +bool Type_handler_null::Item_const_eq(const Item_const *a, + const Item_const *b, + bool binary_cmp) const +{ + return true; +} + + +bool Type_handler_real_result::Item_const_eq(const Item_const *a, + const Item_const *b, + bool binary_cmp) const +{ + const double *va= a->const_ptr_double(); + const double *vb= b->const_ptr_double(); + return va[0] == vb[0]; +} + + +bool Type_handler_int_result::Item_const_eq(const Item_const *a, + const Item_const *b, + bool binary_cmp) const +{ + const longlong *va= a->const_ptr_longlong(); + const longlong *vb= b->const_ptr_longlong(); + bool res= va[0] == vb[0] && + (va[0] >= 0 || + (a->get_type_all_attributes_from_const()->unsigned_flag == + b->get_type_all_attributes_from_const()->unsigned_flag)); + return res; +} + + +bool Type_handler_string_result::Item_const_eq(const Item_const *a, + const Item_const *b, + bool binary_cmp) const +{ + const String *sa= a->const_ptr_string(); + const String *sb= b->const_ptr_string(); + return binary_cmp ? sa->bin_eq(sb) : + a->get_type_all_attributes_from_const()->collation.collation == + b->get_type_all_attributes_from_const()->collation.collation && + sa->eq(sb, a->get_type_all_attributes_from_const()->collation.collation); +} + + +bool +Type_handler_decimal_result::Item_const_eq(const Item_const *a, + const Item_const *b, + bool binary_cmp) const +{ + const my_decimal *da= a->const_ptr_my_decimal(); + const my_decimal *db= b->const_ptr_my_decimal(); + return !da->cmp(db) && + (!binary_cmp || + a->get_type_all_attributes_from_const()->decimals == + b->get_type_all_attributes_from_const()->decimals); +} + + +bool +Type_handler_temporal_result::Item_const_eq(const Item_const *a, + const Item_const *b, + bool binary_cmp) const +{ + const MYSQL_TIME *ta= a->const_ptr_mysql_time(); + const MYSQL_TIME *tb= b->const_ptr_mysql_time(); + return !my_time_compare(ta, tb) && + (!binary_cmp || + a->get_type_all_attributes_from_const()->decimals == + b->get_type_all_attributes_from_const()->decimals); +} + +/***************************************************************************/ + +const Type_handler * +Type_handler_hex_hybrid::cast_to_int_type_handler() const +{ + return &type_handler_longlong; +} + + +const Type_handler * +Type_handler_hex_hybrid::type_handler_for_system_time() const +{ + return &type_handler_longlong; +} + + +/***************************************************************************/ + +bool Type_handler_row::Item_eq_value(THD *thd, const Type_cmp_attributes *attr, + Item *a, Item *b) const +{ + DBUG_ASSERT(0); + return false; +} + + +bool Type_handler_int_result::Item_eq_value(THD *thd, + const Type_cmp_attributes *attr, + Item *a, Item *b) const +{ + longlong value0= a->val_int(); + longlong value1= b->val_int(); + return !a->null_value && !b->null_value && value0 == value1 && + (value0 >= 0 || a->unsigned_flag == b->unsigned_flag); +} + + +bool Type_handler_real_result::Item_eq_value(THD *thd, + const Type_cmp_attributes *attr, + Item *a, Item *b) const +{ + double value0= a->val_real(); + double value1= b->val_real(); + return !a->null_value && !b->null_value && value0 == value1; +} + + +bool Type_handler_time_common::Item_eq_value(THD *thd, + const Type_cmp_attributes *attr, + Item *a, Item *b) const +{ + longlong value0= a->val_time_packed(thd); + longlong value1= b->val_time_packed(thd); + return !a->null_value && !b->null_value && value0 == value1; +} + + +bool Type_handler_temporal_with_date::Item_eq_value(THD *thd, + const Type_cmp_attributes *attr, + Item *a, Item *b) const +{ + longlong value0= a->val_datetime_packed(thd); + longlong value1= b->val_datetime_packed(thd); + return !a->null_value && !b->null_value && value0 == value1; +} + + +bool Type_handler_timestamp_common::Item_eq_value(THD *thd, + const Type_cmp_attributes *attr, + Item *a, Item *b) const +{ + Timestamp_or_zero_datetime_native_null na(thd, a, true); + Timestamp_or_zero_datetime_native_null nb(thd, b, true); + return !na.is_null() && !nb.is_null() && !cmp_native(na, nb); +} + + +bool Type_handler_string_result::Item_eq_value(THD *thd, + const Type_cmp_attributes *attr, + Item *a, Item *b) const +{ + String *va, *vb; + StringBuffer<128> cmp_value1, cmp_value2; + return (va= a->val_str(&cmp_value1)) && + (vb= b->val_str(&cmp_value2)) && + va->eq(vb, attr->compare_collation()); +} + + +/***************************************************************************/ + +void Type_handler_var_string:: + Column_definition_implicit_upgrade(Column_definition *c) const +{ + // Change old VARCHAR to new VARCHAR + c->set_handler(&type_handler_varchar); +} + + +void Type_handler_time_common:: + Column_definition_implicit_upgrade(Column_definition *c) const +{ + if (opt_mysql56_temporal_format) + c->set_handler(&type_handler_time2); + else + c->set_handler(&type_handler_time); +} + + +void Type_handler_datetime_common:: + Column_definition_implicit_upgrade(Column_definition *c) const +{ + if (opt_mysql56_temporal_format) + c->set_handler(&type_handler_datetime2); + else + c->set_handler(&type_handler_datetime); +} + + +void Type_handler_timestamp_common:: + Column_definition_implicit_upgrade(Column_definition *c) const +{ + if (opt_mysql56_temporal_format) + c->set_handler(&type_handler_timestamp2); + else + c->set_handler(&type_handler_timestamp); +} + + +/***************************************************************************/ + + +int Type_handler_temporal_with_date::stored_field_cmp_to_item(THD *thd, + Field *field, + Item *item) const +{ + MYSQL_TIME field_time, item_time, item_time2, *item_time_cmp= &item_time; + field->get_date(&field_time, Datetime::Options(TIME_INVALID_DATES, thd)); + item->get_date(thd, &item_time, Datetime::Options(TIME_INVALID_DATES, thd)); + if (item_time.time_type == MYSQL_TIMESTAMP_TIME && + time_to_datetime(thd, &item_time, item_time_cmp= &item_time2)) + return 1; + return my_time_compare(&field_time, item_time_cmp); +} + + +int Type_handler_time_common::stored_field_cmp_to_item(THD *thd, + Field *field, + Item *item) const +{ + MYSQL_TIME field_time, item_time; + field->get_date(&field_time, Time::Options(thd)); + item->get_date(thd, &item_time, Time::Options(thd)); + return my_time_compare(&field_time, &item_time); +} + + +int Type_handler_string_result::stored_field_cmp_to_item(THD *thd, + Field *field, + Item *item) const +{ + StringBuffer<MAX_FIELD_WIDTH> item_tmp; + StringBuffer<MAX_FIELD_WIDTH> field_tmp; + String *item_result= item->val_str(&item_tmp); + /* + Some implementations of Item::val_str(String*) actually modify + the field Item::null_value, hence we can't check it earlier. + */ + if (item->null_value) + return 0; + String *field_result= field->val_str(&field_tmp); + return sortcmp(field_result, item_result, field->charset()); +} + + +int Type_handler_int_result::stored_field_cmp_to_item(THD *thd, + Field *field, + Item *item) const +{ + DBUG_ASSERT(0); // Not used yet + return 0; +} + + +int Type_handler_real_result::stored_field_cmp_to_item(THD *thd, + Field *field, + Item *item) const +{ + /* + The patch for Bug#13463415 started using this function for comparing + BIGINTs. That uncovered a bug in Visual Studio 32bit optimized mode. + Prefixing the auto variables with volatile fixes the problem.... + */ + volatile double result= item->val_real(); + if (item->null_value) + return 0; + volatile double field_result= field->val_real(); + if (field_result < result) + return -1; + else if (field_result > result) + return 1; + return 0; +} + + +/***************************************************************************/ + + +static bool have_important_literal_warnings(const MYSQL_TIME_STATUS *status) +{ + return (status->warnings & ~MYSQL_TIME_NOTE_TRUNCATED) != 0; +} + + +static void literal_warn(THD *thd, const Item *item, + const char *str, size_t length, CHARSET_INFO *cs, + const MYSQL_TIME_STATUS *st, + const char *typestr, bool send_error) +{ + if (likely(item)) + { + if (st->warnings) // e.g. a note on nanosecond truncation + { + ErrConvString err(str, length, cs); + thd->push_warning_wrong_or_truncated_value( + Sql_condition::time_warn_level(st->warnings), + false, typestr, err.ptr(), NULL, NullS); + } + } + else if (send_error) + { + ErrConvString err(str, length, cs); + my_error(ER_WRONG_VALUE, MYF(0), typestr, err.ptr()); + } +} + + +Item_literal * +Type_handler_date_common::create_literal_item(THD *thd, + const char *str, + size_t length, + CHARSET_INFO *cs, + bool send_error) const +{ + Temporal::Warn st; + Item_literal *item= NULL; + Temporal_hybrid tmp(thd, &st, str, length, cs, Temporal_hybrid::Options(thd)); + if (tmp.is_valid_temporal() && + tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATE && + !have_important_literal_warnings(&st)) + item= new (thd->mem_root) Item_date_literal(thd, tmp.get_mysql_time()); + literal_warn(thd, item, str, length, cs, &st, "DATE", send_error); + return item; +} + + +Item_literal * +Type_handler_temporal_with_date::create_literal_item(THD *thd, + const char *str, + size_t length, + CHARSET_INFO *cs, + bool send_error) const +{ + Temporal::Warn st; + Item_literal *item= NULL; + Temporal_hybrid tmp(thd, &st, str, length, cs, Temporal_hybrid::Options(thd)); + if (tmp.is_valid_temporal() && + tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATETIME && + !have_important_literal_warnings(&st)) + item= new (thd->mem_root) Item_datetime_literal(thd, tmp.get_mysql_time(), + st.precision); + literal_warn(thd, item, str, length, cs, &st, "DATETIME", send_error); + return item; +} + + +Item_literal * +Type_handler_time_common::create_literal_item(THD *thd, + const char *str, + size_t length, + CHARSET_INFO *cs, + bool send_error) const +{ + MYSQL_TIME_STATUS st; + Item_literal *item= NULL; + Time::Options opt(TIME_TIME_ONLY, thd, Time::DATETIME_TO_TIME_DISALLOW); + Time tmp(thd, &st, str, length, cs, opt); + if (tmp.is_valid_time() && + !have_important_literal_warnings(&st)) + item= new (thd->mem_root) Item_time_literal(thd, tmp.get_mysql_time(), + st.precision); + literal_warn(thd, item, str, length, cs, &st, "TIME", send_error); + return item; +} + + +bool Type_handler_timestamp_common::TIME_to_native(THD *thd, + const MYSQL_TIME *ltime, + Native *to, + uint decimals) const +{ + uint error_code; + Timestamp_or_zero_datetime tm(thd, ltime, &error_code); + if (error_code) + return true; + tm.trunc(decimals); + return tm.to_native(to, decimals); +} + + +bool +Type_handler_timestamp_common::Item_val_native_with_conversion(THD *thd, + Item *item, + Native *to) const +{ + MYSQL_TIME ltime; + if (item->type_handler()->type_handler_for_native_format() == + &type_handler_timestamp2) + return item->val_native(thd, to); + return + item->get_date(thd, <ime, Datetime::Options(TIME_NO_ZERO_IN_DATE, thd)) || + TIME_to_native(thd, <ime, to, item->datetime_precision(thd)); +} + + +bool +Type_handler_timestamp_common::Item_val_native_with_conversion_result(THD *thd, + Item *item, + Native *to) + const +{ + MYSQL_TIME ltime; + if (item->type_handler()->type_handler_for_native_format() == + &type_handler_timestamp2) + return item->val_native_result(thd, to); + return + item->get_date_result(thd, <ime, + Datetime::Options(TIME_NO_ZERO_IN_DATE, thd)) || + TIME_to_native(thd, <ime, to, item->datetime_precision(thd)); +} + + +int Type_handler_timestamp_common::cmp_native(const Native &a, + const Native &b) const +{ + /* + Optimize a simple case: + Either both timeatamp values have the same fractional precision, + or both values are zero datetime '0000-00-00 00:00:00.000000', + */ + if (a.length() == b.length()) + return memcmp(a.ptr(), b.ptr(), a.length()); + return Timestamp_or_zero_datetime(a).cmp(Timestamp_or_zero_datetime(b)); +} + + +Timestamp_or_zero_datetime_native_null:: + Timestamp_or_zero_datetime_native_null(THD *thd, Item *item, bool conv) + :Null_flag(false) +{ + DBUG_ASSERT(item->type_handler()->type_handler_for_native_format() == + &type_handler_timestamp2 || conv); + if (conv ? + type_handler_timestamp2.Item_val_native_with_conversion(thd, item, this) : + item->val_native(thd, this)) + Null_flag::operator=(true); + // If no conversion, then is_null() should be equal to item->null_value + DBUG_ASSERT(is_null() == item->null_value || conv); + /* + is_null() can be true together with item->null_value==false, which means + a non-NULL item was evaluated, but then the conversion to TIMESTAMP failed. + But is_null() can never be false if item->null_value==true. + */ + DBUG_ASSERT(is_null() >= item->null_value); +} + + +bool +Type_handler::Item_param_val_native(THD *thd, + Item_param *item, + Native *to) const +{ + DBUG_ASSERT(0); // TODO-TYPE: MDEV-14271 + return item->null_value= true; +} + + +bool +Type_handler_timestamp_common::Item_param_val_native(THD *thd, + Item_param *item, + Native *to) const +{ + /* + The below code may not run well in corner cases. + This will be fixed under terms of MDEV-14271. + Item_param should: + - either remember @@time_zone at bind time + - or store TIMESTAMP in my_time_t format, rather than in MYSQL_TIME format. + */ + MYSQL_TIME ltime; + return + item->get_date(thd, <ime, Datetime::Options(TIME_NO_ZERO_IN_DATE, thd)) || + TIME_to_native(thd, <ime, to, item->datetime_precision(thd)); +} diff --git a/sql/sql_type.h b/sql/sql_type.h index 1ddcef2da61..5f53c5f4aae 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -25,12 +25,17 @@ #include "sql_array.h" #include "sql_const.h" #include "sql_time.h" +#include "compat56.h" class Field; class Column_definition; +class Column_definition_attributes; class Item; +class Item_const; +class Item_literal; class Item_param; class Item_cache; +class Item_copy; class Item_func_or_sum; class Item_sum_hybrid; class Item_sum_sum; @@ -74,6 +79,1158 @@ struct TABLE; struct SORT_FIELD_ATTR; class Vers_history_point; +#define my_charset_numeric my_charset_latin1 + +enum scalar_comparison_op +{ + SCALAR_CMP_EQ, + SCALAR_CMP_EQUAL, + SCALAR_CMP_LT, + SCALAR_CMP_LE, + SCALAR_CMP_GE, + SCALAR_CMP_GT +}; + + +class Native: public Binary_string +{ +public: + Native(char *str, size_t len) + :Binary_string(str, len) + { } +}; + + +template<size_t buff_sz> +class NativeBuffer: public Native +{ + char buff[buff_sz]; +public: + NativeBuffer() : Native(buff, buff_sz) { length(0); } +}; + + +class String_ptr +{ +protected: + String *m_string_ptr; +public: + String_ptr(String *str) + :m_string_ptr(str) + { } + String_ptr(Item *item, String *buffer); + const String *string() const + { + DBUG_ASSERT(m_string_ptr); + return m_string_ptr; + } + bool is_null() const { return m_string_ptr == NULL; } +}; + + +class Ascii_ptr: public String_ptr +{ +public: + Ascii_ptr(Item *item, String *buffer); +}; + + +template<size_t buff_sz> +class String_ptr_and_buffer: public StringBuffer<buff_sz>, + public String_ptr +{ +public: + String_ptr_and_buffer(Item *item) + :String_ptr(item, this) + { } +}; + + +template<size_t buff_sz> +class Ascii_ptr_and_buffer: public StringBuffer<buff_sz>, + public Ascii_ptr +{ +public: + Ascii_ptr_and_buffer(Item *item) + :Ascii_ptr(item, this) + { } +}; + + +class Dec_ptr +{ +protected: + my_decimal *m_ptr; + Dec_ptr() { } +public: + Dec_ptr(my_decimal *ptr) :m_ptr(ptr) { } + bool is_null() const { return m_ptr == NULL; } + const my_decimal *ptr() const { return m_ptr; } + const my_decimal *ptr_or(const my_decimal *def) const + { + return m_ptr ? m_ptr : def; + } + my_decimal *to_decimal(my_decimal *to) const + { + if (!m_ptr) + return NULL; + *to= *m_ptr; + return to; + } + double to_double() const { return m_ptr ? m_ptr->to_double() : 0.0; } + longlong to_longlong(bool unsigned_flag) + { return m_ptr ? m_ptr->to_longlong(unsigned_flag) : 0; } + bool to_bool() const { return m_ptr ? m_ptr->to_bool() : false; } + String *to_string(String *to) const + { + return m_ptr ? m_ptr->to_string(to) : NULL; + } + String *to_string(String *to, uint prec, uint dec, char filler) + { + return m_ptr ? m_ptr->to_string(to, prec, dec, filler) : NULL; + } + int to_binary(uchar *bin, int prec, int scale) const + { + return (m_ptr ? m_ptr : &decimal_zero)->to_binary(bin, prec, scale); + } + int cmp(const my_decimal *dec) const + { + DBUG_ASSERT(m_ptr); + DBUG_ASSERT(dec); + return m_ptr->cmp(dec); + } + int cmp(const Dec_ptr &other) const + { + return cmp(other.m_ptr); + } +}; + + +// A helper class to handle results of val_decimal(), date_op(), etc. +class Dec_ptr_and_buffer: public Dec_ptr +{ +protected: + my_decimal m_buffer; +public: + int round_to(my_decimal *to, uint scale, decimal_round_mode mode) + { + DBUG_ASSERT(m_ptr); + return m_ptr->round_to(to, scale, mode); + } + int round_self(uint scale, decimal_round_mode mode) + { + return round_to(&m_buffer, scale, mode); + } + String *to_string_round(String *to, uint dec) + { + /* + decimal_round() allows from==to + So it's save even if m_ptr points to m_buffer before this call: + */ + return m_ptr ? m_ptr->to_string_round(to, dec, &m_buffer) : NULL; + } +}; + + +// A helper class to handle val_decimal() results. +class VDec: public Dec_ptr_and_buffer +{ +public: + VDec(): Dec_ptr_and_buffer() { } + VDec(Item *item); + void set(Item *a); +}; + + +// A helper class to handler decimal_op() results. +class VDec_op: public Dec_ptr_and_buffer +{ +public: + VDec_op(Item_func_hybrid_field_type *item); +}; + + +/* + Get and cache val_decimal() values for two items. + If the first value appears to be NULL, the second value is not evaluated. +*/ +class VDec2_lazy +{ +public: + VDec m_a; + VDec m_b; + VDec2_lazy(Item *a, Item *b) :m_a(a) + { + if (!m_a.is_null()) + m_b.set(b); + } + bool has_null() const + { + return m_a.is_null() || m_b.is_null(); + } +}; + + +/** + Class Sec6 represents a fixed point value with 6 fractional digits. + Used e.g. to convert double and my_decimal values to TIME/DATETIME. +*/ + +class Sec6 +{ +protected: + ulonglong m_sec; // The integer part, between 0 and LONGLONG_MAX + ulong m_usec; // The fractional part, between 0 and 999999 + bool m_neg; // false if positive, true of negative + bool m_truncated; // Indicates if the constructor truncated the value + void make_from_decimal(const my_decimal *d, ulong *nanoseconds); + void make_from_double(double d, ulong *nanoseconds); + void make_from_int(const Longlong_hybrid &nr) + { + m_neg= nr.neg(); + m_sec= nr.abs(); + m_usec= 0; + m_truncated= false; + } + void reset() + { + m_sec= m_usec= m_neg= m_truncated= 0; + } + Sec6() { } + bool add_nanoseconds(uint nanoseconds) + { + DBUG_ASSERT(nanoseconds <= 1000000000); + if (nanoseconds < 500) + return false; + m_usec+= (nanoseconds + 500) / 1000; + if (m_usec < 1000000) + return false; + m_usec%= 1000000; + return true; + } +public: + explicit Sec6(double nr) + { + ulong nanoseconds; + make_from_double(nr, &nanoseconds); + } + explicit Sec6(const my_decimal *d) + { + ulong nanoseconds; + make_from_decimal(d, &nanoseconds); + } + explicit Sec6(const Longlong_hybrid &nr) + { + make_from_int(nr); + } + explicit Sec6(longlong nr, bool unsigned_val) + { + make_from_int(Longlong_hybrid(nr, unsigned_val)); + } + bool neg() const { return m_neg; } + bool truncated() const { return m_truncated; } + ulonglong sec() const { return m_sec; } + long usec() const { return m_usec; } + /** + Converts Sec6 to MYSQL_TIME + @param thd current thd + @param [out] warn conversion warnings will be written here + @param [out] ltime converted value will be written here + @param fuzzydate conversion flags (TIME_INVALID_DATE, etc) + @returns false for success, true for a failure + */ + bool convert_to_mysql_time(THD *thd, + int *warn, + MYSQL_TIME *ltime, + date_mode_t fuzzydate) const; + +protected: + + bool to_interval_hhmmssff_only(MYSQL_TIME *to, int *warn) const + { + return number_to_time_only(m_neg, m_sec, m_usec, + TIME_MAX_INTERVAL_HOUR, to, warn); + } + bool to_datetime_or_to_interval_hhmmssff(MYSQL_TIME *to, int *warn) const + { + /* + Convert a number to a time interval. + The following formats are understood: + - 0 <= x <= 999999995959 - parse as hhhhmmss + - 999999995959 < x <= 99991231235959 - parse as YYYYMMDDhhmmss + (YYMMDDhhmmss) (YYYYMMDDhhmmss) + + Note, these formats are NOT understood: + - YYMMDD - overlaps with INTERVAL range + - YYYYMMDD - overlaps with INTERVAL range + - YYMMDDhhmmss - overlaps with INTERVAL range, partially + (see TIME_MAX_INTERVAL_HOUR) + + If we ever need wider intervals, this code switching between + full datetime and interval-only should be rewised. + */ + DBUG_ASSERT(TIME_MAX_INTERVAL_HOUR <= 999999995959); + /* (YYMMDDhhmmss) */ + if (m_sec > 999999995959ULL && + m_sec <= 99991231235959ULL && m_neg == 0) + return to_datetime_or_date(to, warn, TIME_INVALID_DATES); + if (m_sec / 10000 > TIME_MAX_INTERVAL_HOUR) + { + *warn= MYSQL_TIME_WARN_OUT_OF_RANGE; + return true; + } + return to_interval_hhmmssff_only(to, warn); + } +public: + // [-][DD]hhhmmss.ff, YYMMDDhhmmss.ff, YYYYMMDDhhmmss.ff + bool to_datetime_or_time(MYSQL_TIME *to, int *warn, + date_conv_mode_t mode) const + { + bool rc= m_sec > 9999999 && m_sec <= 99991231235959ULL && !m_neg ? + ::number_to_datetime_or_date(m_sec, m_usec, to, + ulonglong(mode & TIME_MODE_FOR_XXX_TO_DATE), warn) < 0 : + ::number_to_time_only(m_neg, m_sec, m_usec, TIME_MAX_HOUR, to, warn); + DBUG_ASSERT(*warn || !rc); + return rc; + } + /* + Convert a number in formats YYYYMMDDhhmmss.ff or YYMMDDhhmmss.ff to + TIMESTAMP'YYYY-MM-DD hh:mm:ss.ff' + */ + bool to_datetime_or_date(MYSQL_TIME *to, int *warn, + date_conv_mode_t flags) const + { + if (m_neg) + { + *warn= MYSQL_TIME_WARN_OUT_OF_RANGE; + return true; + } + bool rc= number_to_datetime_or_date(m_sec, m_usec, to, + ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), + warn) == -1; + DBUG_ASSERT(*warn || !rc); + return rc; + } + // Convert elapsed seconds to TIME + bool sec_to_time(MYSQL_TIME *ltime, uint dec) const + { + set_zero_time(ltime, MYSQL_TIMESTAMP_TIME); + ltime->neg= m_neg; + if (m_sec > TIME_MAX_VALUE_SECONDS) + { + // use check_time_range() to set ltime to the max value depending on dec + int unused; + ltime->hour= TIME_MAX_HOUR + 1; + check_time_range(ltime, dec, &unused); + return true; + } + DBUG_ASSERT(usec() <= TIME_MAX_SECOND_PART); + ltime->hour= (uint) (m_sec / 3600); + ltime->minute= (uint) (m_sec % 3600) / 60; + ltime->second= (uint) m_sec % 60; + ltime->second_part= m_usec; + return false; + } + Sec6 &trunc(uint dec) + { + m_usec-= my_time_fraction_remainder(m_usec, dec); + return *this; + } + size_t to_string(char *to, size_t nbytes) const + { + return m_usec ? + my_snprintf(to, nbytes, "%s%llu.%06lu", + m_neg ? "-" : "", m_sec, (uint) m_usec) : + my_snprintf(to, nbytes, "%s%llu", m_neg ? "-" : "", m_sec); + } + void make_truncated_warning(THD *thd, const char *type_str) const; +}; + + +class Sec9: public Sec6 +{ +protected: + ulong m_nsec; // Nanoseconds 0..999 + void make_from_int(const Longlong_hybrid &nr) + { + Sec6::make_from_int(nr); + m_nsec= 0; + } + Sec9() { } +public: + Sec9(const my_decimal *d) + { + Sec6::make_from_decimal(d, &m_nsec); + } + Sec9(double d) + { + Sec6::make_from_double(d, &m_nsec); + } + ulong nsec() const { return m_nsec; } + Sec9 &trunc(uint dec) + { + m_nsec= 0; + Sec6::trunc(dec); + return *this; + } + Sec9 &round(uint dec); + Sec9 &round(uint dec, time_round_mode_t mode) + { + return mode == TIME_FRAC_TRUNCATE ? trunc(dec) : round(dec); + } +}; + + +class VSec9: public Sec9 +{ + bool m_is_null; +public: + VSec9(THD *thd, Item *item, const char *type_str, ulonglong limit); + bool is_null() const { return m_is_null; } +}; + + +/* + A heler class to perform additive operations between + two MYSQL_TIME structures and return the result as a + combination of seconds, microseconds and sign. +*/ +class Sec6_add +{ + ulonglong m_sec; // number of seconds + ulong m_usec; // number of microseconds + bool m_neg; // false if positive, true if negative + bool m_error; // false if the value is OK, true otherwise + void to_hh24mmssff(MYSQL_TIME *ltime, timestamp_type tstype) const + { + bzero(ltime, sizeof(*ltime)); + ltime->neg= m_neg; + calc_time_from_sec(ltime, (ulong) (m_sec % SECONDS_IN_24H), m_usec); + ltime->time_type= tstype; + } +public: + /* + @param ltime1 - the first value to add (must be a valid DATE,TIME,DATETIME) + @param ltime2 - the second value to add (must be a valid TIME) + @param sign - the sign of the operation + (+1 for addition, -1 for subtraction) + */ + Sec6_add(const MYSQL_TIME *ltime1, const MYSQL_TIME *ltime2, int sign) + { + DBUG_ASSERT(sign == -1 || sign == 1); + DBUG_ASSERT(!ltime1->neg || ltime1->time_type == MYSQL_TIMESTAMP_TIME); + if (!(m_error= (ltime2->time_type != MYSQL_TIMESTAMP_TIME))) + { + if (ltime1->neg != ltime2->neg) + sign= -sign; + m_neg= calc_time_diff(ltime1, ltime2, -sign, &m_sec, &m_usec); + if (ltime1->neg && (m_sec || m_usec)) + m_neg= !m_neg; // Swap sign + } + } + bool to_time(THD *thd, MYSQL_TIME *ltime, uint decimals) const + { + if (m_error) + return true; + to_hh24mmssff(ltime, MYSQL_TIMESTAMP_TIME); + ltime->hour+= to_days_abs() * 24; + return adjust_time_range_with_warn(thd, ltime, decimals); + } + bool to_datetime(MYSQL_TIME *ltime) const + { + if (m_error || m_neg) + return true; + to_hh24mmssff(ltime, MYSQL_TIMESTAMP_DATETIME); + return get_date_from_daynr(to_days_abs(), + <ime->year, <ime->month, <ime->day) || + !ltime->day; + } + long to_days_abs() const { return (long) (m_sec / SECONDS_IN_24H); } +}; + + +class Year +{ +protected: + uint m_year; + bool m_truncated; + uint year_precision(const Item *item) const; +public: + Year(): m_year(0), m_truncated(false) { } + Year(longlong value, bool unsigned_flag, uint length); + uint year() const { return m_year; } + uint to_YYYYMMDD() const { return m_year * 10000; } + bool truncated() const { return m_truncated; } +}; + + +class Year_null: public Year, public Null_flag +{ +public: + Year_null(const Longlong_null &nr, bool unsigned_flag, uint length) + :Year(nr.is_null() ? 0 : nr.value(), unsigned_flag, length), + Null_flag(nr.is_null()) + { } +}; + + +class VYear: public Year_null +{ +public: + VYear(Item *item); +}; + + +class VYear_op: public Year_null +{ +public: + VYear_op(Item_func_hybrid_field_type *item); +}; + + +class Double_null: public Null_flag +{ +protected: + double m_value; +public: + Double_null(double value, bool is_null) + :Null_flag(is_null), m_value(value) + { } + double value() const { return m_value; } +}; + + +class Temporal: protected MYSQL_TIME +{ +public: + class Status: public MYSQL_TIME_STATUS + { + public: + Status() { my_time_status_init(this); } + }; + + class Warn: public ErrBuff, + public Status + { + public: + void push_conversion_warnings(THD *thd, bool totally_useless_value, + date_mode_t mode, timestamp_type tstype, + const TABLE_SHARE* s, const char *name) + { + const char *typestr= tstype >= 0 ? type_name_by_timestamp_type(tstype) : + mode & (TIME_INTERVAL_hhmmssff | TIME_INTERVAL_DAY) ? + "interval" : + mode & TIME_TIME_ONLY ? "time" : "datetime"; + Temporal::push_conversion_warnings(thd, totally_useless_value, warnings, + typestr, s, name, ptr()); + } + }; + + class Warn_push: public Warn + { + THD *m_thd; + const TABLE_SHARE *m_s; + const char *m_name; + const MYSQL_TIME *m_ltime; + date_mode_t m_mode; + public: + Warn_push(THD *thd, const TABLE_SHARE *s, const char *name, + const MYSQL_TIME *ltime, date_mode_t mode) + :m_thd(thd), m_s(s), m_name(name), m_ltime(ltime), m_mode(mode) + { } + ~Warn_push() + { + if (warnings) + push_conversion_warnings(m_thd, m_ltime->time_type < 0, + m_mode, m_ltime->time_type, m_s, m_name); + } + }; + +public: + static date_conv_mode_t sql_mode_for_dates(THD *thd); + static time_round_mode_t default_round_mode(THD *thd); + class Options: public date_mode_t + { + public: + explicit Options(date_mode_t flags) + :date_mode_t(flags) + { } + Options(date_conv_mode_t flags, time_round_mode_t round_mode) + :date_mode_t(flags | round_mode) + { + DBUG_ASSERT(ulonglong(flags) <= UINT_MAX32); + } + Options(date_conv_mode_t flags, THD *thd) + :Options(flags, default_round_mode(thd)) + { } + }; + + bool is_valid_temporal() const + { + DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR); + return time_type != MYSQL_TIMESTAMP_NONE; + } + static const char *type_name_by_timestamp_type(timestamp_type time_type) + { + switch (time_type) { + case MYSQL_TIMESTAMP_DATE: return "date"; + case MYSQL_TIMESTAMP_TIME: return "time"; + case MYSQL_TIMESTAMP_DATETIME: // FALLTHROUGH + default: + break; + } + return "datetime"; + } + static void push_conversion_warnings(THD *thd, bool totally_useless_value, int warn, + const char *type_name, + const TABLE_SHARE *s, + const char *field_name, + const char *value); + /* + This method is used if the item was not null but convertion to + TIME/DATE/DATETIME failed. We return a zero date if allowed, + otherwise - null. + */ + void make_fuzzy_date(int *warn, date_conv_mode_t fuzzydate) + { + /* + In the following scenario: + - The caller expected to get a TIME value + - Item returned a not NULL string or numeric value + - But then conversion from string or number to TIME failed + we need to change the default time_type from MYSQL_TIMESTAMP_DATE + (which was set in bzero) to MYSQL_TIMESTAMP_TIME and therefore + return TIME'00:00:00' rather than DATE'0000-00-00'. + If we don't do this, methods like Item::get_time_with_conversion() + will erroneously subtract CURRENT_DATE from '0000-00-00 00:00:00' + and return TIME'-838:59:59' instead of TIME'00:00:00' as a result. + */ + timestamp_type tstype= !(fuzzydate & TIME_FUZZY_DATES) ? + MYSQL_TIMESTAMP_NONE : + fuzzydate & TIME_TIME_ONLY ? + MYSQL_TIMESTAMP_TIME : + MYSQL_TIMESTAMP_DATETIME; + set_zero_time(this, tstype); + } + +protected: + my_decimal *bad_to_decimal(my_decimal *to) const; + my_decimal *to_decimal(my_decimal *to) const; + static double to_double(bool negate, ulonglong num, ulong frac) + { + double d= (double) num + frac / (double) TIME_SECOND_PART_FACTOR; + return negate ? -d : d; + } + longlong to_packed() const { return ::pack_time(this); } + void make_from_out_of_range(int *warn) + { + *warn= MYSQL_TIME_WARN_OUT_OF_RANGE; + time_type= MYSQL_TIMESTAMP_NONE; + } + void make_from_sec6(THD *thd, MYSQL_TIME_STATUS *st, + const Sec6 &nr, date_mode_t mode) + { + if (nr.convert_to_mysql_time(thd, &st->warnings, this, mode)) + make_fuzzy_date(&st->warnings, date_conv_mode_t(mode)); + } + void make_from_sec9(THD *thd, MYSQL_TIME_STATUS *st, + const Sec9 &nr, date_mode_t mode) + { + if (nr.convert_to_mysql_time(thd, &st->warnings, this, mode) || + add_nanoseconds(thd, &st->warnings, mode, nr.nsec())) + make_fuzzy_date(&st->warnings, date_conv_mode_t(mode)); + } + void make_from_str(THD *thd, Warn *warn, + const char *str, size_t length, CHARSET_INFO *cs, + date_mode_t fuzzydate); + void make_from_double(THD *thd, Warn *warn, double nr, date_mode_t mode) + { + make_from_sec9(thd, warn, Sec9(nr), mode); + if (warn->warnings) + warn->set_double(nr); + } + void make_from_longlong_hybrid(THD *thd, Warn *warn, + const Longlong_hybrid &nr, date_mode_t mode) + { + /* + Note: conversion from an integer to TIME can overflow to + '838:59:59.999999', so the conversion result can have fractional digits. + */ + make_from_sec6(thd, warn, Sec6(nr), mode); + if (warn->warnings) + warn->set_longlong(nr); + } + void make_from_decimal(THD *thd, Warn *warn, + const my_decimal *nr, date_mode_t mode) + { + make_from_sec9(thd, warn, Sec9(nr), mode); + if (warn->warnings) + warn->set_decimal(nr); + } + bool ascii_to_temporal(MYSQL_TIME_STATUS *st, + const char *str, size_t length, + date_mode_t mode) + { + if (mode & (TIME_INTERVAL_hhmmssff | TIME_INTERVAL_DAY)) + return ascii_to_datetime_or_date_or_interval_DDhhmmssff(st, str, length, + mode); + if (mode & TIME_TIME_ONLY) + return ascii_to_datetime_or_date_or_time(st, str, length, mode); + return ascii_to_datetime_or_date(st, str, length, mode); + } + bool ascii_to_datetime_or_date_or_interval_DDhhmmssff(MYSQL_TIME_STATUS *st, + const char *str, + size_t length, + date_mode_t mode) + { + longlong cflags= ulonglong(mode & TIME_MODE_FOR_XXX_TO_DATE); + bool rc= mode & TIME_INTERVAL_DAY ? + ::str_to_datetime_or_date_or_interval_day(str, length, this, cflags, st, + TIME_MAX_INTERVAL_HOUR, + TIME_MAX_INTERVAL_HOUR) : + ::str_to_datetime_or_date_or_interval_hhmmssff(str, length, this, + cflags, st, + TIME_MAX_INTERVAL_HOUR, + TIME_MAX_INTERVAL_HOUR); + DBUG_ASSERT(!rc || st->warnings); + return rc; + } + bool ascii_to_datetime_or_date_or_time(MYSQL_TIME_STATUS *status, + const char *str, size_t length, + date_mode_t fuzzydate) + { + ulonglong cflags= ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE); + bool rc= ::str_to_datetime_or_date_or_time(str, length, this, + cflags, status, + TIME_MAX_HOUR, UINT_MAX32); + DBUG_ASSERT(!rc || status->warnings); + return rc; + } + bool ascii_to_datetime_or_date(MYSQL_TIME_STATUS *status, + const char *str, size_t length, + date_mode_t fuzzydate) + { + DBUG_ASSERT(bool(fuzzydate & TIME_TIME_ONLY) == false); + bool rc= ::str_to_datetime_or_date(str, length, this, + ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE), + status); + DBUG_ASSERT(!rc || status->warnings); + return rc; + } + // Character set aware versions for string conversion routines + bool str_to_temporal(THD *thd, MYSQL_TIME_STATUS *st, + const char *str, size_t length, + CHARSET_INFO *cs, date_mode_t fuzzydate); + bool str_to_datetime_or_date_or_time(THD *thd, MYSQL_TIME_STATUS *st, + const char *str, size_t length, + CHARSET_INFO *cs, date_mode_t mode); + bool str_to_datetime_or_date(THD *thd, MYSQL_TIME_STATUS *st, + const char *str, size_t length, + CHARSET_INFO *cs, date_mode_t mode); + + bool has_valid_mmssff() const + { + return minute <= TIME_MAX_MINUTE && + second <= TIME_MAX_SECOND && + second_part <= TIME_MAX_SECOND_PART; + } + bool has_zero_YYYYMM() const + { + return year == 0 && month == 0; + } + bool has_zero_YYYYMMDD() const + { + return year == 0 && month == 0 && day == 0; + } + bool check_date(date_conv_mode_t flags, int *warn) const + { + return ::check_date(this, flags, warn); + } + void time_hhmmssff_set_max(ulong max_hour) + { + hour= max_hour; + minute= TIME_MAX_MINUTE; + second= TIME_MAX_SECOND; + second_part= TIME_MAX_SECOND_PART; + } + /* + Add nanoseconds to ssff + retval true if seconds overflowed (the caller should increment minutes) + false if no overflow happened + */ + bool add_nanoseconds_ssff(uint nanoseconds) + { + DBUG_ASSERT(nanoseconds <= 1000000000); + if (nanoseconds < 500) + return false; + second_part+= (nanoseconds + 500) / 1000; + if (second_part < 1000000) + return false; + second_part%= 1000000; + if (second < 59) + { + second++; + return false; + } + second= 0; + return true; + } + /* + Add nanoseconds to mmssff + retval true if hours overflowed (the caller should increment hours) + false if no overflow happened + */ + bool add_nanoseconds_mmssff(uint nanoseconds) + { + if (!add_nanoseconds_ssff(nanoseconds)) + return false; + if (minute < 59) + { + minute++; + return false; + } + minute= 0; + return true; + } + void time_round_or_set_max(uint dec, int *warn, ulong max_hour, ulong nsec); + bool datetime_add_nanoseconds_or_invalidate(THD *thd, int *warn, ulong nsec); + bool datetime_round_or_invalidate(THD *thd, uint dec, int *warn, ulong nsec); + bool add_nanoseconds_with_round(THD *thd, int *warn, + date_conv_mode_t mode, ulong nsec); + bool add_nanoseconds(THD *thd, int *warn, date_mode_t mode, ulong nsec) + { + date_conv_mode_t cmode= date_conv_mode_t(mode); + return time_round_mode_t(mode) == TIME_FRAC_ROUND ? + add_nanoseconds_with_round(thd, warn, cmode, nsec) : false; + } +public: + static void *operator new(size_t size, MYSQL_TIME *ltime) throw() + { + DBUG_ASSERT(size == sizeof(MYSQL_TIME)); + return ltime; + } + static void operator delete(void *ptr, MYSQL_TIME *ltime) { } + + long fraction_remainder(uint dec) const + { + return my_time_fraction_remainder(second_part, dec); + } +}; + + +/* + Use this class when you need to get a MYSQL_TIME from an Item + using Item's native timestamp type, without automatic timestamp + type conversion. +*/ +class Temporal_hybrid: public Temporal +{ +public: + class Options: public Temporal::Options + { + public: + Options(THD *thd) + :Temporal::Options(sql_mode_for_dates(thd), default_round_mode(thd)) + { } + Options(date_conv_mode_t flags, time_round_mode_t round_mode) + :Temporal::Options(flags, round_mode) + { } + explicit Options(const Temporal::Options &opt) + :Temporal::Options(opt) + { } + explicit Options(date_mode_t fuzzydate) + :Temporal::Options(fuzzydate) + { } + }; + +public: + // Contructors for Item + Temporal_hybrid(THD *thd, Item *item, date_mode_t fuzzydate); + Temporal_hybrid(THD *thd, Item *item) + :Temporal_hybrid(thd, item, Options(thd)) + { } + Temporal_hybrid(Item *item) + :Temporal_hybrid(current_thd, item) + { } + + // Constructors for non-NULL values + Temporal_hybrid(THD *thd, Warn *warn, + const char *str, size_t length, CHARSET_INFO *cs, + date_mode_t fuzzydate) + { + make_from_str(thd, warn, str, length, cs, fuzzydate); + } + Temporal_hybrid(THD *thd, Warn *warn, + const Longlong_hybrid &nr, date_mode_t fuzzydate) + { + make_from_longlong_hybrid(thd, warn, nr, fuzzydate); + } + Temporal_hybrid(THD *thd, Warn *warn, double nr, date_mode_t fuzzydate) + { + make_from_double(thd, warn, nr, fuzzydate); + } + + // Constructors for nullable values + Temporal_hybrid(THD *thd, Warn *warn, const String *str, date_mode_t mode) + { + if (!str) + time_type= MYSQL_TIMESTAMP_NONE; + else + make_from_str(thd, warn, str->ptr(), str->length(), str->charset(), mode); + } + Temporal_hybrid(THD *thd, Warn *warn, + const Longlong_hybrid_null &nr, date_mode_t fuzzydate) + { + if (nr.is_null()) + time_type= MYSQL_TIMESTAMP_NONE; + else + make_from_longlong_hybrid(thd, warn, nr, fuzzydate); + } + Temporal_hybrid(THD *thd, Warn *warn, const Double_null &nr, date_mode_t mode) + { + if (nr.is_null()) + time_type= MYSQL_TIMESTAMP_NONE; + else + make_from_double(thd, warn, nr.value(), mode); + } + Temporal_hybrid(THD *thd, Warn *warn, const my_decimal *nr, date_mode_t mode) + { + if (!nr) + time_type= MYSQL_TIMESTAMP_NONE; + else + make_from_decimal(thd, warn, nr, mode); + } + // End of constuctors + + longlong to_longlong() const + { + if (!is_valid_temporal()) + return 0; + ulonglong v= TIME_to_ulonglong(this); + return neg ? -(longlong) v : (longlong) v; + } + double to_double() const + { + return is_valid_temporal() ? TIME_to_double(this) : 0; + } + my_decimal *to_decimal(my_decimal *to) + { + return is_valid_temporal() ? Temporal::to_decimal(to) : bad_to_decimal(to); + } + String *to_string(String *str, uint dec) const + { + if (!is_valid_temporal()) + return NULL; + str->set_charset(&my_charset_numeric); + if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) + str->length(my_TIME_to_str(this, const_cast<char*>(str->ptr()), dec)); + return str; + } + const MYSQL_TIME *get_mysql_time() const + { + DBUG_ASSERT(is_valid_temporal()); + return this; + } +}; + + +/* + This class resembles the SQL standard <extract source>, + used in extract expressions, e.g: EXTRACT(DAY FROM dt) + <extract expression> ::= + EXTRACT <left paren> <extract field> FROM <extract source> <right paren> + <extract source> ::= <datetime value expression> | <interval value expression> +*/ +class Extract_source: public Temporal_hybrid +{ + /* + Convert a TIME value to DAY-TIME interval, e.g. for extraction: + EXTRACT(DAY FROM x), EXTRACT(HOUR FROM x), etc. + Moves full days from ltime->hour to ltime->day. + */ + void time_to_daytime_interval() + { + DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_TIME); + DBUG_ASSERT(has_zero_YYYYMMDD()); + MYSQL_TIME::day= MYSQL_TIME::hour / 24; + MYSQL_TIME::hour%= 24; + } + bool is_valid_extract_source_slow() const + { + return is_valid_temporal() && MYSQL_TIME::hour < 24 && + (has_zero_YYYYMM() || time_type != MYSQL_TIMESTAMP_TIME); + } + bool is_valid_value_slow() const + { + return time_type == MYSQL_TIMESTAMP_NONE || is_valid_extract_source_slow(); + } +public: + Extract_source(THD *thd, Item *item, date_mode_t mode) + :Temporal_hybrid(thd, item, mode) + { + if (MYSQL_TIME::time_type == MYSQL_TIMESTAMP_TIME) + time_to_daytime_interval(); + DBUG_ASSERT(is_valid_value_slow()); + } + inline const MYSQL_TIME *get_mysql_time() const + { + DBUG_ASSERT(is_valid_extract_source_slow()); + return this; + } + bool is_valid_extract_source() const { return is_valid_temporal(); } + int sign() const { return get_mysql_time()->neg ? -1 : 1; } + uint year() const { return get_mysql_time()->year; } + uint month() const { return get_mysql_time()->month; } + int day() const { return (int) get_mysql_time()->day * sign(); } + int hour() const { return (int) get_mysql_time()->hour * sign(); } + int minute() const { return (int) get_mysql_time()->minute * sign(); } + int second() const { return (int) get_mysql_time()->second * sign(); } + int microsecond() const { return (int) get_mysql_time()->second_part * sign(); } + + uint year_month() const { return year() * 100 + month(); } + uint quarter() const { return (month() + 2)/3; } + uint week(THD *thd) const; + + longlong second_microsecond() const + { + return (second() * 1000000LL + microsecond()); + } + + // DAY TO XXX + longlong day_hour() const + { + return (longlong) day() * 100LL + hour(); + } + longlong day_minute() const + { + return day_hour() * 100LL + minute(); + } + longlong day_second() const + { + return day_minute() * 100LL + second(); + } + longlong day_microsecond() const + { + return day_second() * 1000000LL + microsecond(); + } + + // HOUR TO XXX + int hour_minute() const + { + return hour() * 100 + minute(); + } + int hour_second() const + { + return hour_minute() * 100 + second(); + } + longlong hour_microsecond() const + { + return hour_second() * 1000000LL + microsecond(); + } + + // MINUTE TO XXX + int minute_second() const + { + return minute() * 100 + second(); + } + longlong minute_microsecond() const + { + return minute_second() * 1000000LL + microsecond(); + } +}; + + +/* + This class is used for the "time_interval" argument of these SQL functions: + TIMESTAMP(tm,time_interval) + ADDTIME(tm,time_interval) + Features: + - DATE and DATETIME formats are treated as errors + - Preserves hours for TIME format as is, without limiting to TIME_MAX_HOUR +*/ +class Interval_DDhhmmssff: public Temporal +{ + static const LEX_CSTRING m_type_name; + bool str_to_DDhhmmssff(MYSQL_TIME_STATUS *status, + const char *str, size_t length, CHARSET_INFO *cs, + ulong max_hour); + void push_warning_wrong_or_truncated_value(THD *thd, + const ErrConv &str, + int warnings); + bool is_valid_interval_DDhhmmssff_slow() const + { + return time_type == MYSQL_TIMESTAMP_TIME && + has_zero_YYYYMMDD() && has_valid_mmssff(); + } + bool is_valid_value_slow() const + { + return time_type == MYSQL_TIMESTAMP_NONE || + is_valid_interval_DDhhmmssff_slow(); + } +public: + // Get fractional second precision from an Item + static uint fsp(THD *thd, Item *item); + /* + Maximum useful HOUR value: + TIMESTAMP'0001-01-01 00:00:00' + '87649415:59:59' = '9999-12-31 23:59:59' + This gives maximum possible interval values: + - '87649415:59:59.999999' (in 'hh:mm:ss.ff' format) + - '3652058 23:59:59.999999' (in 'DD hh:mm:ss.ff' format) + */ + static uint max_useful_hour() + { + return TIME_MAX_INTERVAL_HOUR; + } + static uint max_int_part_char_length() + { + // e.g. '+3652058 23:59:59' + return 1/*sign*/ + TIME_MAX_INTERVAL_DAY_CHAR_LENGTH + 1 + 8/*hh:mm:ss*/; + } + static uint max_char_length(uint fsp) + { + DBUG_ASSERT(fsp <= TIME_SECOND_PART_DIGITS); + return max_int_part_char_length() + (fsp ? 1 : 0) + fsp; + } + +public: + Interval_DDhhmmssff(THD *thd, Status *st, bool push_warnings, + Item *item, ulong max_hour, + time_round_mode_t mode, uint dec); + Interval_DDhhmmssff(THD *thd, Item *item, uint dec) + { + Status st; + new(this) Interval_DDhhmmssff(thd, &st, true, item, max_useful_hour(), + default_round_mode(thd), dec); + } + Interval_DDhhmmssff(THD *thd, Item *item) + :Interval_DDhhmmssff(thd, item, TIME_SECOND_PART_DIGITS) + { } + const MYSQL_TIME *get_mysql_time() const + { + DBUG_ASSERT(is_valid_interval_DDhhmmssff_slow()); + return this; + } + bool is_valid_interval_DDhhmmssff() const + { + return time_type == MYSQL_TIMESTAMP_TIME; + } + bool is_valid_value() const + { + return time_type == MYSQL_TIMESTAMP_NONE || is_valid_interval_DDhhmmssff(); + } + String *to_string(String *str, uint dec) const + { + if (!is_valid_interval_DDhhmmssff()) + return NULL; + str->set_charset(&my_charset_numeric); + if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) + str->length(my_interval_DDhhmmssff_to_str(this, + const_cast<char*>(str->ptr()), + dec)); + return str; + } +}; + /** Class Time is designed to store valid TIME values. @@ -93,35 +1250,46 @@ class Vers_history_point; Time derives from MYSQL_TIME privately to make sure it is accessed externally only in the valid state. */ -class Time: private MYSQL_TIME +class Time: public Temporal { public: enum datetime_to_time_mode_t { + DATETIME_TO_TIME_DISALLOW, DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS, - DATETIME_TO_TIME_YYYYMMDD_TRUNCATE + DATETIME_TO_TIME_YYYYMMDD_TRUNCATE, + DATETIME_TO_TIME_YYYYMMDD_00000000_ONLY, + DATETIME_TO_TIME_MINUS_CURRENT_DATE }; - class Options + class Options: public Temporal::Options { - sql_mode_t m_get_date_flags; datetime_to_time_mode_t m_datetime_to_time_mode; public: - Options() - :m_get_date_flags(flags_for_get_date()), - m_datetime_to_time_mode(DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS) + Options(THD *thd) + :Temporal::Options(default_flags_for_get_date(), default_round_mode(thd)), + m_datetime_to_time_mode(default_datetime_to_time_mode()) { } - Options(sql_mode_t flags) - :m_get_date_flags(flags), - m_datetime_to_time_mode(DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS) + Options(date_conv_mode_t flags, THD *thd) + :Temporal::Options(flags, default_round_mode(thd)), + m_datetime_to_time_mode(default_datetime_to_time_mode()) { } - Options(sql_mode_t flags, datetime_to_time_mode_t dtmode) - :m_get_date_flags(flags), + Options(date_conv_mode_t flags, THD *thd, datetime_to_time_mode_t dtmode) + :Temporal::Options(flags, default_round_mode(thd)), m_datetime_to_time_mode(dtmode) { } - sql_mode_t get_date_flags() const - { return m_get_date_flags; } + Options(date_conv_mode_t fuzzydate, time_round_mode_t round_mode, + datetime_to_time_mode_t datetime_to_time_mode) + :Temporal::Options(fuzzydate, round_mode), + m_datetime_to_time_mode(datetime_to_time_mode) + { } + datetime_to_time_mode_t datetime_to_time_mode() const { return m_datetime_to_time_mode; } + + static datetime_to_time_mode_t default_datetime_to_time_mode() + { + return DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS; + } }; /* CAST(AS TIME) historically does not mix days to hours. @@ -131,8 +1299,26 @@ public: class Options_for_cast: public Options { public: - Options_for_cast() - :Options(flags_for_get_date(), DATETIME_TO_TIME_YYYYMMDD_TRUNCATE) + Options_for_cast(THD *thd) + :Options(default_flags_for_get_date(), default_round_mode(thd), + DATETIME_TO_TIME_YYYYMMDD_TRUNCATE) + { } + Options_for_cast(date_mode_t mode, THD *thd) + :Options(default_flags_for_get_date() | (mode & TIME_FUZZY_DATES), + default_round_mode(thd), + DATETIME_TO_TIME_YYYYMMDD_TRUNCATE) + { } + }; + + class Options_cmp: public Options + { + public: + Options_cmp(THD *thd) + :Options(comparison_flags_for_get_date(), thd) + { } + Options_cmp(THD *thd, datetime_to_time_mode_t dtmode) + :Options(comparison_flags_for_get_date(), + default_round_mode(thd), dtmode) { } }; private: @@ -143,46 +1329,79 @@ private: bool is_valid_time_slow() const { return time_type == MYSQL_TIMESTAMP_TIME && - year == 0 && month == 0 && day == 0 && - minute <= TIME_MAX_MINUTE && - second <= TIME_MAX_SECOND && - second_part <= TIME_MAX_SECOND_PART; + has_zero_YYYYMMDD() && has_valid_mmssff(); + } + void hhmmssff_copy(const MYSQL_TIME *from) + { + hour= from->hour; + minute= from->minute; + second= from->second; + second_part= from->second_part; + } + void datetime_to_time_YYYYMMDD_000000DD_mix_to_hours(int *warn, + uint from_year, + uint from_month, + uint from_day) + { + if (from_year != 0 || from_month != 0) + *warn|= MYSQL_TIME_NOTE_TRUNCATED; + else + hour+= from_day * 24; + } + /* + The result is calculated effectively similar to: + TIMEDIFF(dt, CAST(CURRENT_DATE AS DATETIME)) + If the difference does not fit to the supported TIME range, it's truncated. + */ + void datetime_to_time_minus_current_date(THD *thd) + { + MYSQL_TIME current_date, tmp; + set_current_date(thd, ¤t_date); + calc_time_diff(this, ¤t_date, 1, &tmp, date_mode_t(0)); + static_cast<MYSQL_TIME*>(this)[0]= tmp; + int warnings= 0; + (void) check_time_range(this, TIME_SECOND_PART_DIGITS, &warnings); + DBUG_ASSERT(is_valid_time()); } - /* Convert a valid DATE or DATETIME to TIME. Before this call, "this" must be a valid DATE or DATETIME value, - e.g. returned from Item::get_date(). + e.g. returned from Item::get_date(), str_to_xxx(), number_to_xxx(). After this call, "this" is a valid TIME value. */ - void valid_datetime_to_valid_time(const Options opt) + void valid_datetime_to_valid_time(THD *thd, int *warn, const Options opt) { DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATE || time_type == MYSQL_TIMESTAMP_DATETIME); /* - Make sure that day and hour are valid, so the result hour value + We're dealing with a DATE or DATETIME returned from + str_to_xxx(), number_to_xxx() or unpack_time(). + Do some asserts to make sure the result hour value after mixing days to hours does not go out of the valid TIME range. + The maximum hour value after mixing days will be 31*24+23=767, + which is within the supported TIME range. + Thus no adjust_time_range_or_invalidate() is needed here. */ DBUG_ASSERT(day < 32); DBUG_ASSERT(hour < 24); - if (year == 0 && month == 0 && - opt.datetime_to_time_mode() == - DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS) + if (opt.datetime_to_time_mode() == DATETIME_TO_TIME_MINUS_CURRENT_DATE) + { + datetime_to_time_minus_current_date(thd); + } + else { - /* - The maximum hour value after mixing days will be 31*24+23=767, - which is within the supported TIME range. - Thus no adjust_time_range_or_invalidate() is needed here. - */ - hour+= day * 24; + if (opt.datetime_to_time_mode() == + DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS) + datetime_to_time_YYYYMMDD_000000DD_mix_to_hours(warn, year, month, day); + year= month= day= 0; + time_type= MYSQL_TIMESTAMP_TIME; } - year= month= day= 0; - time_type= MYSQL_TIMESTAMP_TIME; DBUG_ASSERT(is_valid_time_slow()); } /** Convert valid DATE/DATETIME to valid TIME if needed. This method is called after Item::get_date(), + str_to_xxx(), number_to_xxx(). which can return only valid TIME/DATE/DATETIME values. Before this call, "this" is: - either a valid TIME/DATE/DATETIME value @@ -192,12 +1411,19 @@ private: - either a valid TIME (within the supported TIME range), - or MYSQL_TIMESTAMP_NONE */ - void valid_MYSQL_TIME_to_valid_value(const Options opt) + void valid_MYSQL_TIME_to_valid_value(THD *thd, int *warn, const Options opt) { switch (time_type) { case MYSQL_TIMESTAMP_DATE: case MYSQL_TIMESTAMP_DATETIME: - valid_datetime_to_valid_time(opt); + if (opt.datetime_to_time_mode() == + DATETIME_TO_TIME_YYYYMMDD_00000000_ONLY && + (year || month || day)) + make_from_out_of_range(warn); + else if (opt.datetime_to_time_mode() == DATETIME_TO_TIME_DISALLOW) + make_from_out_of_range(warn); + else + valid_datetime_to_valid_time(thd, warn, opt); break; case MYSQL_TIMESTAMP_NONE: break; @@ -209,14 +1435,147 @@ private: break; } } - void make_from_item(class Item *item, const Options opt); + + /* + This method is called after number_to_xxx() and str_to_xxx(), + which can return DATE or DATETIME values. Convert to TIME if needed. + We trust that xxx_to_time() returns a valid TIME/DATE/DATETIME value, + so here we need to do only simple validation. + */ + void xxx_to_time_result_to_valid_value(THD *thd, int *warn, const Options opt) + { + // str_to_xxx(), number_to_xxx() never return MYSQL_TIMESTAMP_ERROR + DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR); + valid_MYSQL_TIME_to_valid_value(thd, warn, opt); + } + void adjust_time_range_or_invalidate(int *warn) + { + if (check_time_range(this, TIME_SECOND_PART_DIGITS, warn)) + time_type= MYSQL_TIMESTAMP_NONE; + DBUG_ASSERT(is_valid_value_slow()); + } +public: + void round_or_set_max(uint dec, int *warn, ulong nsec); +private: + void round_or_set_max(uint dec, int *warn); + + /* + All make_from_xxx() methods initialize *warn. + The old value gets lost. + */ + void make_from_datetime_move_day_to_hour(int *warn, const MYSQL_TIME *from); + void make_from_datetime_with_days_diff(int *warn, const MYSQL_TIME *from, + long curdays); + void make_from_time(int *warn, const MYSQL_TIME *from); + void make_from_datetime(int *warn, const MYSQL_TIME *from, long curdays); + void make_from_item(THD *thd, int *warn, Item *item, const Options opt); public: + /* + All constructors that accept an "int *warn" parameter initialize *warn. + The old value gets lost. + */ + Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec6 &second); Time() { time_type= MYSQL_TIMESTAMP_NONE; } - Time(Item *item) { make_from_item(item, Options()); } - Time(Item *item, const Options opt) { make_from_item(item, opt); } - static sql_mode_t flags_for_get_date() + Time(Item *item) + :Time(current_thd, item) + { } + Time(THD *thd, Item *item, const Options opt) + { + int warn; + make_from_item(thd, &warn, item, opt); + } + Time(THD *thd, Item *item) + :Time(thd, item, Options(thd)) + { } + Time(int *warn, const MYSQL_TIME *from, long curdays); + Time(THD *thd, MYSQL_TIME_STATUS *status, + const char *str, size_t len, CHARSET_INFO *cs, + const Options opt) + { + if (str_to_datetime_or_date_or_time(thd, status, str, len, cs, opt)) + time_type= MYSQL_TIMESTAMP_NONE; + // The below call will optionally add notes to already collected warnings: + else + xxx_to_time_result_to_valid_value(thd, &status->warnings, opt); + } + +protected: + Time(THD *thd, int *warn, const Sec6 &nr, const Options opt) + { + if (nr.to_datetime_or_time(this, warn, TIME_INVALID_DATES)) + time_type= MYSQL_TIMESTAMP_NONE; + xxx_to_time_result_to_valid_value(thd, warn, opt); + } + Time(THD *thd, int *warn, const Sec9 &nr, const Options &opt) + :Time(thd, warn, static_cast<Sec6>(nr), opt) + { + if (is_valid_time() && time_round_mode_t(opt) == TIME_FRAC_ROUND) + round_or_set_max(6, warn, nr.nsec()); + } + +public: + Time(THD *thd, int *warn, const Longlong_hybrid &nr, const Options &opt) + :Time(thd, warn, Sec6(nr), opt) + { } + Time(THD *thd, int *warn, double nr, const Options &opt) + :Time(thd, warn, Sec9(nr), opt) + { } + Time(THD *thd, int *warn, const my_decimal *d, const Options &opt) + :Time(thd, warn, Sec9(d), opt) + { } + + Time(THD *thd, Item *item, const Options opt, uint dec) + :Time(thd, item, opt) + { + round(dec, time_round_mode_t(opt)); + } + Time(int *warn, const MYSQL_TIME *from, long curdays, + const Time::Options &opt, uint dec) + :Time(warn, from, curdays) + { + round(dec, time_round_mode_t(opt), warn); + } + Time(int *warn, bool neg, ulonglong hour, uint minute, const Sec9 &second, + time_round_mode_t mode, uint dec) + :Time(warn, neg, hour, minute, second) + { + DBUG_ASSERT(is_valid_time()); + if ((ulonglong) mode == (ulonglong) TIME_FRAC_ROUND) + round_or_set_max(6, warn, second.nsec()); + round(dec, mode, warn); + } + Time(THD *thd, MYSQL_TIME_STATUS *status, + const char *str, size_t len, CHARSET_INFO *cs, + const Options &opt, uint dec) + :Time(thd, status, str, len, cs, opt) + { + round(dec, time_round_mode_t(opt), &status->warnings); + } + Time(THD *thd, int *warn, const Longlong_hybrid &nr, + const Options &opt, uint dec) + :Time(thd, warn, nr, opt) + { + /* + Decimal digit truncation is needed here in case if nr was out + of the supported TIME range, so "this" was set to '838:59:59.999999'. + We always do truncation (not rounding) here, independently from "opt". + */ + trunc(dec); + } + Time(THD *thd, int *warn, double nr, const Options &opt, uint dec) + :Time(thd, warn, nr, opt) + { + round(dec, time_round_mode_t(opt), warn); + } + Time(THD *thd, int *warn, const my_decimal *d, const Options &opt, uint dec) + :Time(thd, warn, d, opt) + { + round(dec, time_round_mode_t(opt), warn); + } + + static date_conv_mode_t default_flags_for_get_date() { return TIME_TIME_ONLY | TIME_INVALID_DATES; } - static sql_mode_t comparison_flags_for_get_date() + static date_conv_mode_t comparison_flags_for_get_date() { return TIME_TIME_ONLY | TIME_INVALID_DATES | TIME_FUZZY_DATES; } bool is_valid_time() const { @@ -243,8 +1602,8 @@ public: { DBUG_ASSERT(is_valid_time_slow()); DBUG_ASSERT(other->is_valid_time_slow()); - longlong p0= pack_time(this); - longlong p1= pack_time(other); + longlong p0= to_packed(); + longlong p1= other->to_packed(); if (p0 < p1) return -1; if (p0 > p1) @@ -260,6 +1619,74 @@ public: { return neg ? -to_seconds_abs() : to_seconds_abs(); } + longlong to_longlong() const + { + if (!is_valid_time()) + return 0; + ulonglong v= TIME_to_ulonglong_time(this); + return neg ? -(longlong) v : (longlong) v; + } + double to_double() const + { + return !is_valid_time() ? 0 : + Temporal::to_double(neg, TIME_to_ulonglong_time(this), second_part); + } + String *to_string(String *str, uint dec) const + { + if (!is_valid_time()) + return NULL; + str->set_charset(&my_charset_numeric); + if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) + str->length(my_time_to_str(this, const_cast<char*>(str->ptr()), dec)); + return str; + } + my_decimal *to_decimal(my_decimal *to) + { + return is_valid_time() ? Temporal::to_decimal(to) : bad_to_decimal(to); + } + longlong to_packed() const + { + return is_valid_time() ? Temporal::to_packed() : 0; + } + long fraction_remainder(uint dec) const + { + DBUG_ASSERT(is_valid_time()); + return Temporal::fraction_remainder(dec); + } + + Time &trunc(uint dec) + { + if (is_valid_time()) + my_time_trunc(this, dec); + DBUG_ASSERT(is_valid_value_slow()); + return *this; + } + Time &round(uint dec, int *warn) + { + if (is_valid_time()) + round_or_set_max(dec, warn); + DBUG_ASSERT(is_valid_value_slow()); + return *this; + } + Time &round(uint dec, time_round_mode_t mode, int *warn) + { + switch (mode.mode()) { + case time_round_mode_t::FRAC_NONE: + DBUG_ASSERT(fraction_remainder(dec) == 0); + return trunc(dec); + case time_round_mode_t::FRAC_TRUNCATE: + return trunc(dec); + case time_round_mode_t::FRAC_ROUND: + return round(dec, warn); + } + return *this; + } + Time &round(uint dec, time_round_mode_t mode) + { + int warn= 0; + return round(dec, mode, &warn); + } + }; @@ -286,14 +1713,79 @@ public: it is accessed externally only in the valid state. */ -class Temporal_with_date: protected MYSQL_TIME +class Temporal_with_date: public Temporal { +public: + class Options: public Temporal::Options + { + public: + Options(date_conv_mode_t fuzzydate, time_round_mode_t mode): + Temporal::Options(fuzzydate, mode) + {} + explicit Options(const Temporal::Options &opt) + :Temporal::Options(opt) + { } + explicit Options(date_mode_t mode) + :Temporal::Options(mode) + { } + }; protected: - void make_from_item(THD *thd, Item *item, sql_mode_t flags); - Temporal_with_date(THD *thd, Item *item, sql_mode_t flags) + void check_date_or_invalidate(int *warn, date_conv_mode_t flags); + void make_from_item(THD *thd, Item *item, date_mode_t flags); + + ulong daynr() const + { + return (ulong) ::calc_daynr((uint) year, (uint) month, (uint) day); + } + ulong dayofyear() const + { + return (ulong) (daynr() - ::calc_daynr(year, 1, 1) + 1); + } + uint quarter() const + { + return (month + 2) / 3; + } + uint week(uint week_behaviour) const + { + uint year; + return calc_week(this, week_behaviour, &year); + } + uint yearweek(uint week_behaviour) const + { + uint year; + uint week= calc_week(this, week_behaviour, &year); + return week + year * 100; + } +public: + Temporal_with_date() + { + time_type= MYSQL_TIMESTAMP_NONE; + } + Temporal_with_date(THD *thd, Item *item, date_mode_t fuzzydate) { - make_from_item(thd, item, flags); + make_from_item(thd, item, fuzzydate); } + Temporal_with_date(int *warn, const Sec6 &nr, date_mode_t flags) + { + DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false); + if (nr.to_datetime_or_date(this, warn, date_conv_mode_t(flags))) + time_type= MYSQL_TIMESTAMP_NONE; + } + Temporal_with_date(THD *thd, MYSQL_TIME_STATUS *status, + const char *str, size_t len, CHARSET_INFO *cs, + date_mode_t flags) + { + DBUG_ASSERT(bool(flags & TIME_TIME_ONLY) == false); + if (str_to_datetime_or_date(thd, status, str, len, cs, flags)) + time_type= MYSQL_TIMESTAMP_NONE; + } +public: + bool check_date_with_warn(THD *thd, date_conv_mode_t flags) + { + return ::check_date_with_warn(thd, this, flags, MYSQL_TIMESTAMP_ERROR); + } + static date_conv_mode_t comparison_flags_for_get_date() + { return TIME_INVALID_DATES | TIME_FUZZY_DATES; } }; @@ -318,13 +1810,42 @@ class Date: public Temporal_with_date return !check_datetime_range(this); } public: - Date(THD *thd, Item *item, sql_mode_t flags) - :Temporal_with_date(thd, item, flags) + class Options: public Temporal_with_date::Options + { + public: + explicit Options(date_conv_mode_t fuzzydate) + :Temporal_with_date::Options(fuzzydate, TIME_FRAC_TRUNCATE) + { } + Options(THD *thd, time_round_mode_t mode) + :Temporal_with_date::Options(sql_mode_for_dates(thd), mode) + { } + explicit Options(THD *thd) + :Temporal_with_date::Options(sql_mode_for_dates(thd), TIME_FRAC_TRUNCATE) + { } + explicit Options(date_mode_t fuzzydate) + :Temporal_with_date::Options(fuzzydate) + { } + }; +public: + Date(Item *item, date_mode_t fuzzydate) + :Date(current_thd, item, fuzzydate) + { } + Date(THD *thd, Item *item, date_mode_t fuzzydate) + :Temporal_with_date(thd, item, fuzzydate) { if (time_type == MYSQL_TIMESTAMP_DATETIME) datetime_to_date(this); DBUG_ASSERT(is_valid_value_slow()); } + Date(THD *thd, Item *item, date_conv_mode_t fuzzydate) + :Date(thd, item, Options(fuzzydate)) + { } + Date(THD *thd, Item *item) + :Temporal_with_date(Date(thd, item, Options(thd, TIME_FRAC_TRUNCATE))) + { } + Date(Item *item) + :Temporal_with_date(Date(current_thd, item)) + { } Date(const Temporal_with_date *d) :Temporal_with_date(*d) { @@ -341,6 +1862,64 @@ public: DBUG_ASSERT(is_valid_date_slow()); return this; } + bool copy_to_mysql_time(MYSQL_TIME *ltime) const + { + if (time_type == MYSQL_TIMESTAMP_NONE) + { + ltime->time_type= MYSQL_TIMESTAMP_NONE; + return true; + } + DBUG_ASSERT(is_valid_date_slow()); + *ltime= *this; + return false; + } + ulong daynr() const + { + DBUG_ASSERT(is_valid_date_slow()); + return Temporal_with_date::daynr(); + } + ulong dayofyear() const + { + DBUG_ASSERT(is_valid_date_slow()); + return Temporal_with_date::dayofyear(); + } + uint quarter() const + { + DBUG_ASSERT(is_valid_date_slow()); + return Temporal_with_date::quarter(); + } + uint week(uint week_behaviour) const + { + DBUG_ASSERT(is_valid_date_slow()); + return Temporal_with_date::week(week_behaviour); + } + uint yearweek(uint week_behaviour) const + { + DBUG_ASSERT(is_valid_date_slow()); + return Temporal_with_date::yearweek(week_behaviour); + } + + longlong to_longlong() const + { + return is_valid_date() ? (longlong) TIME_to_ulonglong_date(this) : 0LL; + } + double to_double() const + { + return (double) to_longlong(); + } + String *to_string(String *str) const + { + if (!is_valid_date()) + return NULL; + str->set_charset(&my_charset_numeric); + if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) + str->length(my_date_to_str(this, const_cast<char*>(str->ptr()))); + return str; + } + my_decimal *to_decimal(my_decimal *to) + { + return is_valid_date() ? Temporal::to_decimal(to) : bad_to_decimal(to); + } }; @@ -365,14 +1944,148 @@ class Datetime: public Temporal_with_date DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATETIME); return !check_datetime_range(this); } -public: - Datetime(THD *thd, Item *item, sql_mode_t flags) - :Temporal_with_date(thd, item, flags) + bool add_nanoseconds_or_invalidate(THD *thd, int *warn, ulong nsec) + { + DBUG_ASSERT(is_valid_datetime_slow()); + bool rc= Temporal::datetime_add_nanoseconds_or_invalidate(thd, warn, nsec); + DBUG_ASSERT(is_valid_value_slow()); + return rc; + } + void date_to_datetime_if_needed() { if (time_type == MYSQL_TIMESTAMP_DATE) date_to_datetime(this); + } + void make_from_time(THD *thd, int *warn, const MYSQL_TIME *from, + date_conv_mode_t flags); + void make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from, + date_conv_mode_t flags); + bool round_or_invalidate(THD *thd, uint dec, int *warn); + bool round_or_invalidate(THD *thd, uint dec, int *warn, ulong nsec) + { + DBUG_ASSERT(is_valid_datetime_slow()); + bool rc= Temporal::datetime_round_or_invalidate(thd, dec, warn, nsec); + DBUG_ASSERT(is_valid_value_slow()); + return rc; + } +public: + + class Options: public Temporal_with_date::Options + { + public: + Options(date_conv_mode_t fuzzydate, time_round_mode_t nanosecond_rounding) + :Temporal_with_date::Options(fuzzydate, nanosecond_rounding) + { } + Options(THD *thd) + :Temporal_with_date::Options(sql_mode_for_dates(thd), default_round_mode(thd)) + { } + Options(THD *thd, time_round_mode_t rounding_mode) + :Temporal_with_date::Options(sql_mode_for_dates(thd), rounding_mode) + { } + Options(date_conv_mode_t fuzzydate, THD *thd) + :Temporal_with_date::Options(fuzzydate, default_round_mode(thd)) + { } + }; + + class Options_cmp: public Options + { + public: + Options_cmp(THD *thd) + :Options(comparison_flags_for_get_date(), thd) + { } + }; + + static Datetime zero() + { + int warn; + static Longlong_hybrid nr(0, false); + return Datetime(&warn, nr, date_mode_t(0)); + } +public: + Datetime() // NULL value + :Temporal_with_date() + { } + Datetime(THD *thd, Item *item, date_mode_t fuzzydate) + :Temporal_with_date(thd, item, fuzzydate) + { + date_to_datetime_if_needed(); + DBUG_ASSERT(is_valid_value_slow()); + } + Datetime(THD *thd, Item *item) + :Temporal_with_date(Datetime(thd, item, Options(thd))) + { } + Datetime(Item *item) + :Datetime(current_thd, item) + { } + + Datetime(THD *thd, int *warn, const MYSQL_TIME *from, date_conv_mode_t flags); + Datetime(THD *thd, MYSQL_TIME_STATUS *status, + const char *str, size_t len, CHARSET_INFO *cs, + const date_mode_t fuzzydate) + :Temporal_with_date(thd, status, str, len, cs, fuzzydate) + { + date_to_datetime_if_needed(); + DBUG_ASSERT(is_valid_value_slow()); + } + +protected: + Datetime(int *warn, const Sec6 &nr, date_mode_t flags) + :Temporal_with_date(warn, nr, flags) + { + date_to_datetime_if_needed(); + DBUG_ASSERT(is_valid_value_slow()); + } + Datetime(THD *thd, int *warn, const Sec9 &nr, date_mode_t fuzzydate) + :Datetime(warn, static_cast<const Sec6>(nr), fuzzydate) + { + if (is_valid_datetime() && + time_round_mode_t(fuzzydate) == TIME_FRAC_ROUND) + round_or_invalidate(thd, 6, warn, nr.nsec()); DBUG_ASSERT(is_valid_value_slow()); } + +public: + Datetime(int *warn, const Longlong_hybrid &nr, date_mode_t mode) + :Datetime(warn, Sec6(nr), mode) + { } + Datetime(THD *thd, int *warn, double nr, date_mode_t fuzzydate) + :Datetime(thd, warn, Sec9(nr), fuzzydate) + { } + Datetime(THD *thd, int *warn, const my_decimal *d, date_mode_t fuzzydate) + :Datetime(thd, warn, Sec9(d), fuzzydate) + { } + Datetime(THD *thd, const timeval &tv); + + Datetime(THD *thd, Item *item, date_mode_t fuzzydate, uint dec) + :Datetime(thd, item, fuzzydate) + { + int warn= 0; + round(thd, dec, time_round_mode_t(fuzzydate), &warn); + } + Datetime(THD *thd, MYSQL_TIME_STATUS *status, + const char *str, size_t len, CHARSET_INFO *cs, + date_mode_t fuzzydate, uint dec) + :Datetime(thd, status, str, len, cs, fuzzydate) + { + round(thd, dec, time_round_mode_t(fuzzydate), &status->warnings); + } + Datetime(THD *thd, int *warn, double nr, date_mode_t fuzzydate, uint dec) + :Datetime(thd, warn, nr, fuzzydate) + { + round(thd, dec, time_round_mode_t(fuzzydate), warn); + } + Datetime(THD *thd, int *warn, const my_decimal *d, date_mode_t fuzzydate, uint dec) + :Datetime(thd, warn, d, fuzzydate) + { + round(thd, dec, time_round_mode_t(fuzzydate), warn); + } + Datetime(THD *thd, int *warn, const MYSQL_TIME *from, + date_mode_t fuzzydate, uint dec) + :Datetime(thd, warn, from, date_conv_mode_t(fuzzydate) & ~TIME_TIME_ONLY) + { + round(thd, dec, time_round_mode_t(fuzzydate), warn); + } + bool is_valid_datetime() const { /* @@ -382,11 +2095,63 @@ public: DBUG_ASSERT(is_valid_value_slow()); return time_type == MYSQL_TIMESTAMP_DATETIME; } + bool check_date(date_conv_mode_t flags, int *warnings) const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return ::check_date(this, (year || month || day), + ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE), + warnings); + } + bool check_date(date_conv_mode_t flags) const + { + int dummy; /* unused */ + return check_date(flags, &dummy); + } bool hhmmssff_is_zero() const { DBUG_ASSERT(is_valid_datetime_slow()); return hour == 0 && minute == 0 && second == 0 && second_part == 0; } + ulong daynr() const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return Temporal_with_date::daynr(); + } + ulong dayofyear() const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return Temporal_with_date::dayofyear(); + } + uint quarter() const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return Temporal_with_date::quarter(); + } + uint week(uint week_behaviour) const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return Temporal_with_date::week(week_behaviour); + } + uint yearweek(uint week_behaviour) const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return Temporal_with_date::yearweek(week_behaviour); + } + + longlong hhmmss_to_seconds_abs() const + { + DBUG_ASSERT(is_valid_datetime_slow()); + return hour * 3600L + minute * 60 + second; + } + longlong hhmmss_to_seconds() const + { + return neg ? -hhmmss_to_seconds_abs() : hhmmss_to_seconds_abs(); + } + longlong to_seconds() const + { + return hhmmss_to_seconds() + (longlong) daynr() * 24L * 3600L; + } + const MYSQL_TIME *get_mysql_time() const { DBUG_ASSERT(is_valid_datetime_slow()); @@ -418,8 +2183,298 @@ public: ltime->time_type= type; return false; } + longlong to_longlong() const + { + return is_valid_datetime() ? + (longlong) TIME_to_ulonglong_datetime(this) : 0LL; + } + double to_double() const + { + return !is_valid_datetime() ? 0 : + Temporal::to_double(neg, TIME_to_ulonglong_datetime(this), second_part); + } + String *to_string(String *str, uint dec) const + { + if (!is_valid_datetime()) + return NULL; + str->set_charset(&my_charset_numeric); + if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) + str->length(my_datetime_to_str(this, const_cast<char*>(str->ptr()), dec)); + return str; + } + my_decimal *to_decimal(my_decimal *to) + { + return is_valid_datetime() ? Temporal::to_decimal(to) : bad_to_decimal(to); + } + longlong to_packed() const + { + return is_valid_datetime() ? Temporal::to_packed() : 0; + } + long fraction_remainder(uint dec) const + { + DBUG_ASSERT(is_valid_datetime()); + return Temporal::fraction_remainder(dec); + } + + Datetime &trunc(uint dec) + { + if (is_valid_datetime()) + my_time_trunc(this, dec); + DBUG_ASSERT(is_valid_value_slow()); + return *this; + } + Datetime &round(THD *thd, uint dec, int *warn) + { + if (is_valid_datetime()) + round_or_invalidate(thd, dec, warn); + DBUG_ASSERT(is_valid_value_slow()); + return *this; + } + Datetime &round(THD *thd, uint dec, time_round_mode_t mode, int *warn) + { + switch (mode.mode()) { + case time_round_mode_t::FRAC_NONE: + DBUG_ASSERT(fraction_remainder(dec) == 0); + return trunc(dec); + case time_round_mode_t::FRAC_TRUNCATE: + return trunc(dec); + case time_round_mode_t::FRAC_ROUND: + return round(thd, dec, warn); + } + return *this; + } + Datetime &round(THD *thd, uint dec, time_round_mode_t mode) + { + int warn= 0; + return round(thd, dec, mode, &warn); + } + +}; + + +/* + Datetime to be created from an Item who is known to be of a temporal + data type. For temporal data types we don't need nanosecond rounding + or truncation, as their precision is limited. +*/ +class Datetime_from_temporal: public Datetime +{ +public: + // The constructor DBUG_ASSERTs on a proper Item data type. + Datetime_from_temporal(THD *thd, Item *temporal, date_conv_mode_t flags); }; + +/* + Datetime to be created from an Item who is known not to have digits outside + of the specified scale. So it's not important which rounding method to use. + TRUNCATE should work. + Typically, Item is of a temporal data type, but this is not strictly required. +*/ +class Datetime_truncation_not_needed: public Datetime +{ +public: + Datetime_truncation_not_needed(THD *thd, Item *item, date_conv_mode_t mode); + Datetime_truncation_not_needed(THD *thd, Item *item, date_mode_t mode) + :Datetime_truncation_not_needed(thd, item, date_conv_mode_t(mode)) + { } +}; + + +class Timestamp: protected Timeval +{ + static uint binary_length_to_precision(uint length); +protected: + void round_or_set_max(uint dec, int *warn); + bool add_nanoseconds_usec(uint nanoseconds) + { + DBUG_ASSERT(nanoseconds <= 1000000000); + if (nanoseconds < 500) + return false; + tv_usec+= (nanoseconds + 500) / 1000; + if (tv_usec < 1000000) + return false; + tv_usec%= 1000000; + return true; + } +public: + static date_conv_mode_t sql_mode_for_timestamp(THD *thd); + static time_round_mode_t default_round_mode(THD *thd); + class DatetimeOptions: public date_mode_t + { + public: + DatetimeOptions(date_conv_mode_t fuzzydate, time_round_mode_t round_mode) + :date_mode_t(fuzzydate | round_mode) + { } + DatetimeOptions(THD *thd) + :DatetimeOptions(sql_mode_for_timestamp(thd), default_round_mode(thd)) + { } + }; +public: + Timestamp(my_time_t timestamp, ulong sec_part) + :Timeval(timestamp, sec_part) + { } + explicit Timestamp(const timeval &tv) + :Timeval(tv) + { } + explicit Timestamp(const Native &native); + Timestamp(THD *thd, const MYSQL_TIME *ltime, uint *error_code); + const struct timeval &tv() const { return *this; } + int cmp(const Timestamp &other) const + { + return tv_sec < other.tv_sec ? -1 : + tv_sec > other.tv_sec ? +1 : + tv_usec < other.tv_usec ? -1 : + tv_usec > other.tv_usec ? +1 : 0; + } + bool to_TIME(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) const; + bool to_native(Native *to, uint decimals) const; + long fraction_remainder(uint dec) const + { + return my_time_fraction_remainder(tv_usec, dec); + } + Timestamp &trunc(uint dec) + { + my_timeval_trunc(this, dec); + return *this; + } + Timestamp &round(uint dec, int *warn) + { + round_or_set_max(dec, warn); + return *this; + } + Timestamp &round(uint dec, time_round_mode_t mode, int *warn) + { + switch (mode.mode()) { + case time_round_mode_t::FRAC_NONE: + DBUG_ASSERT(fraction_remainder(dec) == 0); + return trunc(dec); + case time_round_mode_t::FRAC_TRUNCATE: + return trunc(dec); + case time_round_mode_t::FRAC_ROUND: + return round(dec, warn); + } + return *this; + } + Timestamp &round(uint dec, time_round_mode_t mode) + { + int warn= 0; + return round(dec, mode, &warn); + } +}; + + +/** + A helper class to store MariaDB TIMESTAMP values, which can be: + - real TIMESTAMP (seconds and microseconds since epoch), or + - zero datetime '0000-00-00 00:00:00.000000' +*/ +class Timestamp_or_zero_datetime: public Timestamp +{ + bool m_is_zero_datetime; +public: + Timestamp_or_zero_datetime() + :Timestamp(0,0), m_is_zero_datetime(true) + { } + Timestamp_or_zero_datetime(const Native &native) + :Timestamp(native.length() ? Timestamp(native) : Timestamp(0,0)), + m_is_zero_datetime(native.length() == 0) + { } + Timestamp_or_zero_datetime(const Timestamp &tm, bool is_zero_datetime) + :Timestamp(tm), m_is_zero_datetime(is_zero_datetime) + { } + Timestamp_or_zero_datetime(THD *thd, const MYSQL_TIME *ltime, uint *err_code); + Datetime to_datetime(THD *thd) const + { + return Datetime(thd, *this); + } + bool is_zero_datetime() const { return m_is_zero_datetime; } + const struct timeval &tv() const + { + DBUG_ASSERT(!is_zero_datetime()); + return Timestamp::tv(); + } + void trunc(uint decimals) + { + if (!is_zero_datetime()) + Timestamp::trunc(decimals); + } + int cmp(const Timestamp_or_zero_datetime &other) const + { + if (is_zero_datetime()) + return other.is_zero_datetime() ? 0 : -1; + if (other.is_zero_datetime()) + return 1; + return Timestamp::cmp(other); + } + bool to_TIME(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) const; + /* + Convert to native format: + - Real timestamps are encoded in the same way how Field_timestamp2 stores + values (big endian seconds followed by big endian microseconds) + - Zero datetime '0000-00-00 00:00:00.000000' is encoded as empty string. + Two native values are binary comparable. + */ + bool to_native(Native *to, uint decimals) const; +}; + + +/** + A helper class to store non-null MariaDB TIMESTAMP values in + the native binary encoded representation. +*/ +class Timestamp_or_zero_datetime_native: + public NativeBuffer<STRING_BUFFER_TIMESTAMP_BINARY_SIZE> +{ +public: + Timestamp_or_zero_datetime_native() { } + Timestamp_or_zero_datetime_native(const Timestamp_or_zero_datetime &ts, + uint decimals) + { + if (ts.to_native(this, decimals)) + length(0); // safety + } + int save_in_field(Field *field, uint decimals) const; + bool is_zero_datetime() const + { + return length() == 0; + } +}; + + +/** + A helper class to store nullable MariaDB TIMESTAMP values in + the native binary encoded representation. +*/ +class Timestamp_or_zero_datetime_native_null: public Timestamp_or_zero_datetime_native, + public Null_flag +{ +public: + // With optional data type conversion + Timestamp_or_zero_datetime_native_null(THD *thd, Item *item, bool conv); + // Without data type conversion: item is known to be of the TIMESTAMP type + Timestamp_or_zero_datetime_native_null(THD *thd, Item *item) + :Timestamp_or_zero_datetime_native_null(thd, item, false) + { } + Datetime to_datetime(THD *thd) const + { + return is_null() ? Datetime() : + Datetime(thd, Timestamp_or_zero_datetime(*this).tv()); + } + void to_TIME(THD *thd, MYSQL_TIME *to) + { + DBUG_ASSERT(!is_null()); + Datetime::Options opt(TIME_CONV_NONE, TIME_FRAC_NONE); + Timestamp_or_zero_datetime(*this).to_TIME(thd, to, opt); + } + bool is_zero_datetime() const + { + DBUG_ASSERT(!is_null()); + return Timestamp_or_zero_datetime_native::is_zero_datetime(); + } +}; + + /* Flags for collation aggregation modes, used in TDCollation::agg(): @@ -445,7 +2500,6 @@ public: #define MY_COLL_CMP_CONV (MY_COLL_ALLOW_CONV | MY_COLL_DISALLOW_NONE) -#define my_charset_numeric my_charset_latin1 #define MY_REPERTOIRE_NUMERIC MY_REPERTOIRE_ASCII @@ -834,6 +2888,14 @@ public: }; +class Type_cmp_attributes +{ +public: + virtual ~Type_cmp_attributes() { } + virtual CHARSET_INFO *compare_collation() const= 0; +}; + + class Type_cast_attributes { CHARSET_INFO *m_charset; @@ -886,28 +2948,67 @@ public: }; -class Record_addr +class Bit_addr { -public: - uchar *ptr; // Position to field in record /** - Byte where the @c NULL bit is stored inside a record. If this Field is a - @c NOT @c NULL field, this member is @c NULL. + Byte where the bit is stored inside a record. + If the corresponding Field is a NOT NULL field, this member is NULL. */ - uchar *null_ptr; - uchar null_bit; // Bit used to test null bit + uchar *m_ptr; + /** + Offset of the bit inside m_ptr[0], in the range 0..7. + */ + uchar m_offs; +public: + Bit_addr() + :m_ptr(NULL), + m_offs(0) + { } + Bit_addr(uchar *ptr, uchar offs) + :m_ptr(ptr), m_offs(offs) + { + DBUG_ASSERT(ptr || offs == 0); + DBUG_ASSERT(offs < 8); + } + Bit_addr(bool maybe_null) + :m_ptr(maybe_null ? (uchar *) "" : NULL), + m_offs(0) + { } + uchar *ptr() const { return m_ptr; } + uchar offs() const { return m_offs; } + uchar bit() const { return m_ptr ? ((uchar) 1) << m_offs : 0; } + void inc() + { + DBUG_ASSERT(m_ptr); + m_ptr+= (m_offs == 7); + m_offs= (m_offs + 1) & 7; + } +}; + + +class Record_addr +{ + uchar *m_ptr; // Position of the field in the record + Bit_addr m_null; // Position and offset of the null bit +public: Record_addr(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg) - :ptr(ptr_arg), - null_ptr(null_ptr_arg), - null_bit(null_bit_arg) + :m_ptr(ptr_arg), + m_null(null_ptr_arg, null_bit_arg) + { } + Record_addr(uchar *ptr, const Bit_addr &null) + :m_ptr(ptr), + m_null(null) { } Record_addr(bool maybe_null) - :ptr(NULL), - null_ptr(maybe_null ? (uchar*) "" : 0), - null_bit(0) + :m_ptr(NULL), + m_null(maybe_null) { } + uchar *ptr() const { return m_ptr; } + const Bit_addr &null() const { return m_null; } + uchar *null_ptr() const { return m_null.ptr(); } + uchar null_bit() const { return m_null.bit(); } }; @@ -982,6 +3083,9 @@ public: class Type_handler { protected: + static const Name m_version_default; + static const Name m_version_mysql56; + static const Name m_version_mariadb53; String *print_item_value_csstr(THD *thd, Item *item, String *str) const; String *print_item_value_temporal(THD *thd, Item *item, String *str, const Name &type_name, String *buf) const; @@ -1003,6 +3107,7 @@ protected: bool Item_send_double(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_time(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_date(Item *item, Protocol *protocol, st_value *buf) const; + bool Item_send_timestamp(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const; bool Column_definition_prepare_stage2_legacy(Column_definition *c, enum_field_types type) @@ -1014,6 +3119,7 @@ protected: enum_field_types type) const; public: + static const Type_handler *odbc_literal_type_handler(const LEX_CSTRING *str); static const Type_handler *blob_type_handler(uint max_octet_length); static const Type_handler *string_type_handler(uint max_octet_length); static const Type_handler *bit_and_int_mixture_handler(uint max_char_len); @@ -1047,8 +3153,31 @@ public: const Type_handler *h2); virtual const Name name() const= 0; + virtual const Name version() const { return m_version_default; } virtual enum_field_types field_type() const= 0; virtual enum_field_types real_field_type() const { return field_type(); } + /** + Type code which is used for merging of traditional data types for result + (for UNION and for hybrid functions such as COALESCE). + Mapping can be done both ways: old->new, new->old, depending + on the particular data type implementation: + - type_handler_var_string (MySQL-4.1 old VARCHAR) is converted to + new VARCHAR before merging. + field_type_merge_rules[][] returns new VARCHAR. + - type_handler_newdate is converted to old DATE before merging. + field_type_merge_rules[][] returns NEWDATE. + - Temporal type_handler_xxx2 (new MySQL-5.6 types) are converted to + corresponding old type codes before merging (e.g. TIME2->TIME). + field_type_merge_rules[][] returns old type codes (e.g. TIME). + Then old types codes are supposed to convert to new type codes somehow, + but they do not. So UNION and COALESCE create old columns. + This is a bug and should be fixed eventually. + */ + virtual enum_field_types traditional_merge_field_type() const + { + DBUG_ASSERT(is_traditional_type()); + return field_type(); + } virtual Item_result result_type() const= 0; virtual Item_result cmp_type() const= 0; virtual enum_mysql_timestamp_type mysql_timestamp_type() const @@ -1059,6 +3188,25 @@ public: { return false; } + virtual bool is_order_clause_position_type() const + { + return false; + } + virtual bool is_limit_clause_valid_type() const + { + return false; + } + /* + Returns true if this data type supports a hack that + WHERE notnull_column IS NULL + finds zero values, e.g.: + WHERE date_notnull_column IS NULL -> + WHERE date_notnull_column = '0000-00-00' + */ + virtual bool cond_notnull_field_isnull_to_field_eq_zero() const + { + return false; + } /** Check whether a field type can be partially indexed by a key. @param type field type @@ -1081,6 +3229,10 @@ public: */ virtual bool is_param_long_data_type() const { return false; } virtual const Type_handler *type_handler_for_comparison() const= 0; + virtual const Type_handler *type_handler_for_native_format() const + { + return this; + } virtual const Type_handler *type_handler_for_item_field() const { return this; @@ -1097,6 +3249,12 @@ public: { return this; } + virtual const Type_handler *type_handler_for_system_time() const + { + return this; + } + virtual int + stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const= 0; virtual CHARSET_INFO *charset_for_protocol(const Item *item) const; virtual const Type_handler* type_handler_adjusted_to_max_octet_length(uint max_octet_length, @@ -1123,9 +3281,10 @@ public: virtual bool can_return_text() const { return true; } virtual bool can_return_date() const { return true; } virtual bool can_return_time() const { return true; } + virtual bool is_bool_type() const { return false; } virtual bool is_general_purpose_string_type() const { return false; } - virtual uint Item_time_precision(Item *item) const; - virtual uint Item_datetime_precision(Item *item) const; + virtual uint Item_time_precision(THD *thd, Item *item) const; + virtual uint Item_datetime_precision(THD *thd, Item *item) const; virtual uint Item_decimal_scale(const Item *item) const; virtual uint Item_decimal_precision(const Item *item) const= 0; /* @@ -1169,7 +3328,20 @@ public: virtual Field *make_conversion_table_field(TABLE *TABLE, uint metadata, const Field *target) const= 0; + // Automatic upgrade, e.g. for ALTER TABLE t1 FORCE + virtual void Column_definition_implicit_upgrade(Column_definition *c) const + { } + // Fix attributes after the parser virtual bool Column_definition_fix_attributes(Column_definition *c) const= 0; + /* + Fix attributes from an existing field. Used for: + - ALTER TABLE (for columns that do not change) + - DECLARE var TYPE OF t1.col1; (anchored SP variables) + */ + virtual void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const + { } virtual bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, @@ -1208,6 +3380,23 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + virtual Field * + make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const= 0; + virtual void + Column_definition_attributes_frm_pack(const Column_definition_attributes *at, + uchar *buff) const; + virtual bool + Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, + TABLE_SHARE *share, + const uchar *buffer, + LEX_CUSTRING *gis_options) const; + virtual void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const= 0; @@ -1217,7 +3406,8 @@ public: virtual uint32 max_display_length(const Item *item) const= 0; virtual uint32 calc_pack_length(uint32 length) const= 0; - virtual bool Item_save_in_value(Item *item, st_value *value) const= 0; + virtual void Item_update_null_value(Item *item) const= 0; + virtual bool Item_save_in_value(THD *thd, Item *item, st_value *value) const= 0; virtual void Item_param_setup_conversion(THD *thd, Item_param *) const {} virtual void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; @@ -1225,6 +3415,9 @@ public: Item_param *param, const Type_all_attributes *attr, const st_value *value) const= 0; + virtual bool Item_param_val_native(THD *thd, + Item_param *item, + Native *to) const; virtual bool Item_send(Item *item, Protocol *p, st_value *buf) const= 0; virtual int Item_save_in_field(Item *item, Field *field, bool no_conversions) const= 0; @@ -1295,13 +3488,52 @@ public: Item *src, const Item *cmp) const= 0; virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0; + /** + A builder for literals with data type name prefix, e.g.: + TIME'00:00:00', DATE'2001-01-01', TIMESTAMP'2001-01-01 00:00:00'. + @param thd The current thread + @param str Character literal + @param length Length of str + @param cs Character set of the string + @param send_error Whether to generate an error on failure + + @retval A pointer to a new Item on success + NULL on error (wrong literal value, EOM) + */ + virtual Item_literal *create_literal_item(THD *thd, + const char *str, size_t length, + CHARSET_INFO *cs, + bool send_error) const + { + DBUG_ASSERT(0); + return NULL; + } + Item_literal *create_literal_item(THD *thd, const String *str, + bool send_error) const + { + return create_literal_item(thd, str->ptr(), str->length(), str->charset(), + send_error); + } virtual Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const { DBUG_ASSERT(0); return NULL; } + virtual Item_copy *create_item_copy(THD *thd, Item *item) const; + virtual int cmp_native(const Native &a, const Native &b) const + { + DBUG_ASSERT(0); + return 0; + } virtual bool set_comparator_func(Arg_comparator *cmp) const= 0; + virtual bool Item_const_eq(const Item_const *a, const Item_const *b, + bool binary_cmp) const + { + return false; + } + virtual bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, + Item *a, Item *b) const= 0; virtual bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -1318,9 +3550,23 @@ public: virtual bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const= 0; + virtual bool Item_val_native_with_conversion(THD *thd, Item *item, + Native *to) const + { + return true; + } + virtual bool Item_val_native_with_conversion_result(THD *thd, Item *item, + Native *to) const + { + return true; + } + virtual bool Item_val_bool(Item *item) const= 0; - virtual bool Item_get_date(Item *item, MYSQL_TIME *ltime, - ulonglong fuzzydate) const= 0; + virtual void Item_get_date(THD *thd, Item *item, + Temporal::Warn *buff, MYSQL_TIME *ltime, + date_mode_t fuzzydate) const= 0; + bool Item_get_date_with_warn(THD *thd, Item *item, MYSQL_TIME *ltime, + date_mode_t fuzzydate) const; virtual longlong Item_val_int_signed_typecast(Item *item) const= 0; virtual longlong Item_val_int_unsigned_typecast(Item *item) const= 0; @@ -1341,9 +3587,15 @@ public: Item_func_hybrid_field_type *, my_decimal *) const= 0; virtual - bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, + void Item_func_hybrid_field_type_get_date(THD *, + Item_func_hybrid_field_type *, + Temporal::Warn *, MYSQL_TIME *, - ulonglong fuzzydate) const= 0; + date_mode_t fuzzydate) const= 0; + bool Item_func_hybrid_field_type_get_date_with_warn(THD *thd, + Item_func_hybrid_field_type *, + MYSQL_TIME *, + date_mode_t) const; virtual String *Item_func_min_max_val_str(Item_func_min_max *, String *) const= 0; virtual @@ -1354,8 +3606,8 @@ public: my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const= 0; virtual - bool Item_func_min_max_get_date(Item_func_min_max*, - MYSQL_TIME *, ulonglong fuzzydate) const= 0; + bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, + MYSQL_TIME *, date_mode_t fuzzydate) const= 0; virtual bool Item_func_between_fix_length_and_dec(Item_func_between *func) const= 0; virtual longlong @@ -1447,6 +3699,11 @@ public: return ROW_RESULT; } const Type_handler *type_handler_for_comparison() const; + int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const + { + DBUG_ASSERT(0); + return 0; + } bool subquery_type_allows_materialization(const Item *inner, const Item *outer) const { @@ -1469,6 +3726,12 @@ public: { return false; } + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const + { + DBUG_ASSERT(0); + } bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, @@ -1497,6 +3760,13 @@ public: DBUG_ASSERT(0); return NULL; } + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const @@ -1518,12 +3788,14 @@ public: DBUG_ASSERT(0); return 0; } + bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, + Item *a, Item *b) const; uint Item_decimal_precision(const Item *item) const { DBUG_ASSERT(0); return DECIMAL_MAX_PRECISION; } - bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_save_in_value(THD *thd, Item *item, st_value *value) const; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, @@ -1533,6 +3805,7 @@ public: DBUG_ASSERT(0); return true; } + void Item_update_null_value(Item *item) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const { DBUG_ASSERT(0); @@ -1549,6 +3822,11 @@ public: } Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; + Item_copy *create_item_copy(THD *thd, Item *item) const + { + DBUG_ASSERT(0); + return NULL; + } bool set_comparator_func(Arg_comparator *cmp) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, @@ -1584,10 +3862,12 @@ public: DBUG_ASSERT(0); return false; } - bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const + void Item_get_date(THD *thd, Item *item, + Temporal::Warn *warn, MYSQL_TIME *ltime, + date_mode_t fuzzydate) const { DBUG_ASSERT(0); - return true; + set_zero_time(ltime, MYSQL_TIMESTAMP_NONE); } longlong Item_val_int_signed_typecast(Item *item) const { @@ -1629,12 +3909,14 @@ public: DBUG_ASSERT(0); return NULL; } - bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, - MYSQL_TIME *, - ulonglong fuzzydate) const + void Item_func_hybrid_field_type_get_date(THD *, + Item_func_hybrid_field_type *, + Temporal::Warn *, + MYSQL_TIME *ltime, + date_mode_t fuzzydate) const { DBUG_ASSERT(0); - return true; + set_zero_time(ltime, MYSQL_TIMESTAMP_NONE); } String *Item_func_min_max_val_str(Item_func_min_max *, String *) const @@ -1658,8 +3940,8 @@ public: DBUG_ASSERT(0); return NULL; } - bool Item_func_min_max_get_date(Item_func_min_max*, - MYSQL_TIME *, ulonglong fuzzydate) const + bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, + MYSQL_TIME *, date_mode_t fuzzydate) const { DBUG_ASSERT(0); return true; @@ -1743,8 +4025,8 @@ public: longlong Item_func_min_max_val_int(Item_func_min_max *) const; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const; - bool Item_func_min_max_get_date(Item_func_min_max*, - MYSQL_TIME *, ulonglong fuzzydate) const; + bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, + MYSQL_TIME *, date_mode_t fuzzydate) const; virtual ~Type_handler_numeric() { } bool can_change_cond_ref_to_const(Item_bool_func2 *target, Item *target_expr, Item *target_value, @@ -1764,6 +4046,10 @@ public: Item_result cmp_type() const { return REAL_RESULT; } virtual ~Type_handler_real_result() {} const Type_handler *type_handler_for_comparison() const; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const; + int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const; bool subquery_type_allows_materialization(const Item *inner, const Item *outer) const; void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, @@ -1771,12 +4057,17 @@ public: void sortlength(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const; + bool Item_const_eq(const Item_const *a, const Item_const *b, + bool binary_cmp) const; + bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, + Item *a, Item *b) const; uint Item_decimal_precision(const Item *item) const; - bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_save_in_value(THD *thd, Item *item, st_value *value) const; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *value) const; + void Item_update_null_value(Item *item) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; @@ -1795,7 +4086,8 @@ public: bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const; bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const; bool Item_val_bool(Item *item) const; - bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const; + void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const; longlong Item_val_int_signed_typecast(Item *item) const; longlong Item_val_int_unsigned_typecast(Item *item) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; @@ -1808,9 +4100,11 @@ public: my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const; - bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, + void Item_func_hybrid_field_type_get_date(THD *, + Item_func_hybrid_field_type *, + Temporal::Warn *, MYSQL_TIME *, - ulonglong fuzzydate) const; + date_mode_t fuzzydate) const; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; longlong Item_func_between_val_int(Item_func_between *func) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; @@ -1837,6 +4131,11 @@ public: Item_result cmp_type() const { return DECIMAL_RESULT; } virtual ~Type_handler_decimal_result() {}; const Type_handler *type_handler_for_comparison() const; + int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const + { + VDec item_val(item); + return item_val.is_null() ? 0 : my_decimal(field).cmp(item_val.ptr()); + } bool subquery_type_allows_materialization(const Item *inner, const Item *outer) const; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; @@ -1848,8 +4147,16 @@ public: uint32 max_display_length(const Item *item) const; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const; + bool Item_const_eq(const Item_const *a, const Item_const *b, + bool binary_cmp) const; + bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, + Item *a, Item *b) const + { + VDec va(a), vb(b); + return va.ptr() && vb.ptr() && !va.cmp(vb); + } uint Item_decimal_precision(const Item *item) const; - bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_save_in_value(THD *thd, Item *item, st_value *value) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; bool Item_param_set_from_value(THD *thd, @@ -1860,6 +4167,7 @@ public: { return Item_send_str(item, protocol, buf); } + void Item_update_null_value(Item *item) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; @@ -1873,10 +4181,17 @@ public: bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; - bool Item_val_bool(Item *item) const; - bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const; + bool Item_val_bool(Item *item) const + { + return VDec(item).to_bool(); + } + void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const; longlong Item_val_int_signed_typecast(Item *item) const; - longlong Item_val_int_unsigned_typecast(Item *item) const; + longlong Item_val_int_unsigned_typecast(Item *item) const + { + return VDec(item).to_longlong(true); + } String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *, String *) const; @@ -1887,9 +4202,11 @@ public: my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const; - bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, + void Item_func_hybrid_field_type_get_date(THD *, + Item_func_hybrid_field_type *, + Temporal::Warn *, MYSQL_TIME *, - ulonglong fuzzydate) const; + date_mode_t fuzzydate) const; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; longlong Item_func_between_val_int(Item_func_between *func) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; @@ -2038,8 +4355,11 @@ class Type_handler_int_result: public Type_handler_numeric public: Item_result result_type() const { return INT_RESULT; } Item_result cmp_type() const { return INT_RESULT; } + bool is_order_clause_position_type() const { return true; } + bool is_limit_clause_valid_type() const { return true; } virtual ~Type_handler_int_result() {} const Type_handler *type_handler_for_comparison() const; + int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const; bool subquery_type_allows_materialization(const Item *inner, const Item *outer) const; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; @@ -2048,12 +4368,17 @@ public: void sortlength(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const; + bool Item_const_eq(const Item_const *a, const Item_const *b, + bool binary_cmp) const; + bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, + Item *a, Item *b) const; uint Item_decimal_precision(const Item *item) const; - bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_save_in_value(THD *thd, Item *item, st_value *value) const; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, const st_value *value) const; + void Item_update_null_value(Item *item) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; @@ -2068,7 +4393,8 @@ public: bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; bool Item_val_bool(Item *item) const; - bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const; + void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const; longlong Item_val_int_signed_typecast(Item *item) const; longlong Item_val_int_unsigned_typecast(Item *item) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; @@ -2081,9 +4407,11 @@ public: my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const; - bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, + void Item_func_hybrid_field_type_get_date(THD *, + Item_func_hybrid_field_type *, + Temporal::Warn *, MYSQL_TIME *, - ulonglong fuzzydate) const; + date_mode_t fuzzydate) const; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; longlong Item_func_between_val_int(Item_func_between *func) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; @@ -2099,6 +4427,7 @@ public: bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const; bool Item_func_div_fix_length_and_dec(Item_func_div *) const; bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const; + }; @@ -2127,6 +4456,8 @@ public: void sortlength(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const; + bool Item_const_eq(const Item_const *a, const Item_const *b, + bool binary_cmp) const; bool Item_param_set_from_value(THD *thd, Item_param *param, const Type_all_attributes *attr, @@ -2138,12 +4469,15 @@ public: Item *source_expr, Item *source_const) const; bool subquery_type_allows_materialization(const Item *inner, const Item *outer) const; + bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, + Item **items, uint nitems) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; bool Item_val_bool(Item *item) const; - bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const; + void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const; longlong Item_val_int_signed_typecast(Item *item) const; longlong Item_val_int_unsigned_typecast(Item *item) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; @@ -2156,18 +4490,14 @@ public: my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const; - bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, + void Item_func_hybrid_field_type_get_date(THD *, + Item_func_hybrid_field_type *, + Temporal::Warn *, MYSQL_TIME *, - ulonglong fuzzydate) const; - String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; - double Item_func_min_max_val_real(Item_func_min_max *) const; - longlong Item_func_min_max_val_int(Item_func_min_max *) const; - my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, - my_decimal *) const; - bool Item_func_min_max_get_date(Item_func_min_max*, - MYSQL_TIME *, ulonglong fuzzydate) const; + date_mode_t fuzzydate) const; + bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, + MYSQL_TIME *, date_mode_t fuzzydate) const; bool Item_func_between_fix_length_and_dec(Item_func_between *func) const; - longlong Item_func_between_val_int(Item_func_between *func) const; bool Item_func_in_fix_comparator_compatible_types(THD *thd, Item_func_in *) const; bool Item_func_round_fix_length_and_dec(Item_func_round *) const; @@ -2185,13 +4515,14 @@ public: class Type_handler_string_result: public Type_handler { - uint Item_temporal_precision(Item *item, bool is_time) const; + uint Item_temporal_precision(THD *thd, Item *item, bool is_time) const; public: Item_result result_type() const { return STRING_RESULT; } Item_result cmp_type() const { return STRING_RESULT; } CHARSET_INFO *charset_for_protocol(const Item *item) const; virtual ~Type_handler_string_result() {} const Type_handler *type_handler_for_comparison() const; + int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const; const Type_handler * type_handler_adjusted_to_max_octet_length(uint max_octet_length, CHARSET_INFO *cs) const; @@ -2211,16 +4542,21 @@ public: const Schema_specification_st *schema) const; uint32 max_display_length(const Item *item) const; - uint Item_time_precision(Item *item) const + bool Item_const_eq(const Item_const *a, const Item_const *b, + bool binary_cmp) const; + bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, + Item *a, Item *b) const; + uint Item_time_precision(THD *thd, Item *item) const { - return Item_temporal_precision(item, true); + return Item_temporal_precision(thd, item, true); } - uint Item_datetime_precision(Item *item) const + uint Item_datetime_precision(THD *thd, Item *item) const { - return Item_temporal_precision(item, false); + return Item_temporal_precision(thd, item, false); } uint Item_decimal_precision(const Item *item) const; - bool Item_save_in_value(Item *item, st_value *value) const; + void Item_update_null_value(Item *item) const; + bool Item_save_in_value(THD *thd, Item *item, st_value *value) const; void Item_param_setup_conversion(THD *thd, Item_param *) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; @@ -2258,7 +4594,8 @@ public: bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const; bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const; bool Item_val_bool(Item *item) const; - bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const; + void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const; longlong Item_val_int_signed_typecast(Item *item) const; longlong Item_val_int_unsigned_typecast(Item *item) const; String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const; @@ -2271,16 +4608,18 @@ public: my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const; - bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, + void Item_func_hybrid_field_type_get_date(THD *, + Item_func_hybrid_field_type *, + Temporal::Warn *, MYSQL_TIME *, - ulonglong fuzzydate) const; + date_mode_t fuzzydate) const; String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; double Item_func_min_max_val_real(Item_func_min_max *) const; longlong Item_func_min_max_val_int(Item_func_min_max *) const; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, my_decimal *) const; - bool Item_func_min_max_get_date(Item_func_min_max*, - MYSQL_TIME *, ulonglong fuzzydate) const; + bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, + MYSQL_TIME *, date_mode_t fuzzydate) const; bool Item_func_between_fix_length_and_dec(Item_func_between *func) const; longlong Item_func_between_val_int(Item_func_between *func) const; bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const; @@ -2357,6 +4696,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2391,6 +4737,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2425,11 +4778,29 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; +class Type_handler_bool: public Type_handler_long +{ + static const Name m_name_bool; +public: + const Name name() const { return m_name_bool; } + bool is_bool_type() const { return true; } + void Item_update_null_value(Item *item) const; + bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const; +}; + + class Type_handler_longlong: public Type_handler_general_purpose_int { static const Name m_name_longlong; @@ -2463,6 +4834,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2508,6 +4886,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2527,6 +4912,9 @@ public: Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; bool Column_definition_fix_attributes(Column_definition *c) const; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const @@ -2535,8 +4923,21 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; - bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const; + void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn, + MYSQL_TIME *ltime, date_mode_t fuzzydate) const; + void Item_func_hybrid_field_type_get_date(THD *, + Item_func_hybrid_field_type *item, + Temporal::Warn *, + MYSQL_TIME *to, + date_mode_t fuzzydate) const; }; @@ -2577,6 +4978,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; bool Vers_history_point_resolve_unit(THD *thd, Vers_history_point *p) const; }; @@ -2607,6 +5015,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2639,6 +5054,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; }; @@ -2655,8 +5077,12 @@ public: { return MYSQL_TIMESTAMP_TIME; } + Item_literal *create_literal_item(THD *thd, const char *str, size_t length, + CHARSET_INFO *cs, bool send_error) const; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const; + bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, + Item *a, Item *b) const; uint Item_decimal_scale(const Item *item) const { return Item_decimal_scale_with_seconds(item); @@ -2667,12 +5093,15 @@ public: return Item_divisor_precision_increment_with_seconds(item); } const Type_handler *type_handler_for_comparison() const; + int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const; + void Column_definition_implicit_upgrade(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const; - bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_save_in_value(THD *thd, Item *item, st_value *value) const; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const { return Item_send_time(item, protocol, buf); } + void Item_update_null_value(Item *item) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; String *print_item_value(THD *thd, Item *item, String *str) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; @@ -2690,11 +5119,19 @@ public: my_decimal *Item_func_hybrid_field_type_val_decimal( Item_func_hybrid_field_type *, my_decimal *) const; - bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, + void Item_func_hybrid_field_type_get_date(THD *, + Item_func_hybrid_field_type *, + Temporal::Warn *, MYSQL_TIME *, - ulonglong fuzzydate) const; - bool Item_func_min_max_get_date(Item_func_min_max*, - MYSQL_TIME *, ulonglong fuzzydate) const; + date_mode_t fuzzydate) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; + double Item_func_min_max_val_real(Item_func_min_max *) const; + longlong Item_func_min_max_val_int(Item_func_min_max *) const; + my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, + my_decimal *) const; + bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, + MYSQL_TIME *, date_mode_t fuzzydate) const; + longlong Item_func_between_val_int(Item_func_between *func) const; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; @@ -2711,6 +5148,7 @@ class Type_handler_time: public Type_handler_time_common public: static uint hires_bytes(uint dec) { return m_hires_bytes[dec]; } virtual ~Type_handler_time() {} + const Name version() const { return m_version_mariadb53; } uint32 calc_pack_length(uint32 length) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; @@ -2722,6 +5160,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2729,6 +5174,7 @@ class Type_handler_time2: public Type_handler_time_common { public: virtual ~Type_handler_time2() {} + const Name version() const { return m_version_mysql56; } enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; } uint32 calc_pack_length(uint32 length) const; Field *make_conversion_table_field(TABLE *, uint metadata, @@ -2741,6 +5187,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2748,16 +5201,23 @@ class Type_handler_temporal_with_date: public Type_handler_temporal_result { public: virtual ~Type_handler_temporal_with_date() {} - bool Item_save_in_value(Item *item, st_value *value) const; + Item_literal *create_literal_item(THD *thd, const char *str, size_t length, + CHARSET_INFO *cs, bool send_error) const; + bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, + Item *a, Item *b) const; + int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) const; + bool Item_save_in_value(THD *thd, Item *item, st_value *value) const; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const { return Item_send_date(item, protocol, buf); } + void Item_update_null_value(Item *item) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const; + longlong Item_func_between_val_int(Item_func_between *func) const; }; @@ -2773,12 +5233,23 @@ public: { return MYSQL_TIMESTAMP_DATE; } + bool cond_notnull_field_isnull_to_field_eq_zero() const + { + return true; + } + Item_literal *create_literal_item(THD *thd, const char *str, size_t length, + CHARSET_INFO *cs, bool send_error) const; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const; bool Column_definition_fix_attributes(Column_definition *c) const; uint Item_decimal_precision(const Item *item) const; String *print_item_value(THD *thd, Item *item, String *str) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; + double Item_func_min_max_val_real(Item_func_min_max *) const; + longlong Item_func_min_max_val_int(Item_func_min_max *) const; + my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, + my_decimal *) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -2803,6 +5274,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2822,6 +5300,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2837,8 +5322,13 @@ public: { return MYSQL_TIMESTAMP_DATETIME; } + bool cond_notnull_field_isnull_to_field_eq_zero() const + { + return true; + } Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const; + void Column_definition_implicit_upgrade(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const; uint Item_decimal_scale(const Item *item) const { @@ -2855,6 +5345,11 @@ public: } String *print_item_value(THD *thd, Item *item, String *str) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; + double Item_func_min_max_val_real(Item_func_min_max *) const; + longlong Item_func_min_max_val_int(Item_func_min_max *) const; + my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, + my_decimal *) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -2872,6 +5367,7 @@ class Type_handler_datetime: public Type_handler_datetime_common public: static uint hires_bytes(uint dec) { return m_hires_bytes[dec]; } virtual ~Type_handler_datetime() {} + const Name version() const { return m_version_mariadb53; } uint32 calc_pack_length(uint32 length) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; @@ -2883,6 +5379,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2890,6 +5393,7 @@ class Type_handler_datetime2: public Type_handler_datetime_common { public: virtual ~Type_handler_datetime2() {} + const Name version() const { return m_version_mysql56; } enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; } uint32 calc_pack_length(uint32 length) const; Field *make_conversion_table_field(TABLE *, uint metadata, @@ -2902,16 +5406,26 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; class Type_handler_timestamp_common: public Type_handler_temporal_with_date { static const Name m_name_timestamp; +protected: + bool TIME_to_native(THD *, const MYSQL_TIME *from, Native *to, uint dec) const; public: virtual ~Type_handler_timestamp_common() {} const Name name() const { return m_name_timestamp; } const Type_handler *type_handler_for_comparison() const; + const Type_handler *type_handler_for_native_format() const; enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; } enum_mysql_timestamp_type mysql_timestamp_type() const { @@ -2921,6 +5435,21 @@ public: { return true; } + void Column_definition_implicit_upgrade(Column_definition *c) const; + bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, + Item *a, Item *b) const; + bool Item_val_native_with_conversion(THD *thd, Item *, Native *to) const; + bool Item_val_native_with_conversion_result(THD *thd, Item *, Native *to) const; + bool Item_param_val_native(THD *thd, Item_param *item, Native *to) const; + int cmp_native(const Native &a, const Native &b) const; + longlong Item_func_between_val_int(Item_func_between *func) const; + cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; + in_vector *make_in_vector(THD *thd, const Item_func_in *f, uint nargs) const; + void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, + Sort_param *param) const; + void sortlength(THD *thd, + const Type_std_attributes *item, + SORT_FIELD_ATTR *attr) const; bool Column_definition_fix_attributes(Column_definition *c) const; uint Item_decimal_scale(const Item *item) const { @@ -2933,10 +5462,18 @@ public: } bool Item_send(Item *item, Protocol *protocol, st_value *buf) const { - return Item_send_datetime(item, protocol, buf); + return Item_send_timestamp(item, protocol, buf); } + int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; String *print_item_value(THD *thd, Item *item, String *str) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; + Item_copy *create_item_copy(THD *thd, Item *item) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; + double Item_func_min_max_val_real(Item_func_min_max *) const; + longlong Item_func_min_max_val_int(Item_func_min_max *) const; + my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, + my_decimal *) const; + bool set_comparator_func(Arg_comparator *cmp) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -2944,6 +5481,8 @@ public: Item **items, uint nitems) const; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const; + bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*, + MYSQL_TIME *, date_mode_t fuzzydate) const; }; @@ -2954,6 +5493,7 @@ class Type_handler_timestamp: public Type_handler_timestamp_common public: static uint sec_part_bytes(uint dec) { return m_sec_part_bytes[dec]; } virtual ~Type_handler_timestamp() {} + const Name version() const { return m_version_mariadb53; } uint32 calc_pack_length(uint32 length) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; @@ -2965,6 +5505,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -2972,6 +5519,7 @@ class Type_handler_timestamp2: public Type_handler_timestamp_common { public: virtual ~Type_handler_timestamp2() {} + const Name version() const { return m_version_mysql56; } enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; } uint32 calc_pack_length(uint32 length) const; Field *make_conversion_table_field(TABLE *, uint metadata, @@ -2986,6 +5534,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -3010,6 +5565,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -3041,6 +5603,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -3056,7 +5625,9 @@ public: const Type_handler *type_handler_for_union(const Item *) const; uint32 max_display_length(const Item *item) const { return 0; } uint32 calc_pack_length(uint32 length) const { return 0; } - bool Item_save_in_value(Item *item, st_value *value) const; + bool Item_const_eq(const Item_const *a, const Item_const *b, + bool binary_cmp) const; + bool Item_save_in_value(THD *thd, Item *item, st_value *value) const; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; @@ -3079,6 +5650,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -3115,6 +5693,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -3127,10 +5712,15 @@ public: const Name name() const { return m_name_var_string; } enum_field_types field_type() const { return MYSQL_TYPE_VAR_STRING; } enum_field_types real_field_type() const { return MYSQL_TYPE_STRING; } + enum_field_types traditional_merge_field_type() const + { + return MYSQL_TYPE_VARCHAR; + } const Type_handler *type_handler_for_tmp_table(const Item *item) const { return varstring_type_handler(item); } + void Column_definition_implicit_upgrade(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, @@ -3173,10 +5763,28 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; bool adjust_spparam_type(Spvar_definition *def, Item *from) const; }; +class Type_handler_hex_hybrid: public Type_handler_varchar +{ + static const Name m_name_hex_hybrid; +public: + virtual ~Type_handler_hex_hybrid() {} + const Name name() const { return m_name_hex_hybrid; } + const Type_handler *cast_to_int_type_handler() const; + const Type_handler *type_handler_for_system_time() const; +}; + + class Type_handler_varchar_compressed: public Type_handler_varchar { public: @@ -3206,6 +5814,9 @@ public: } bool is_param_long_data_type() const { return true; } bool Column_definition_fix_attributes(Column_definition *c) const; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const; bool Column_definition_prepare_stage2(Column_definition *c, handler *file, ulonglong table_flags) const; @@ -3216,6 +5827,13 @@ public: Item **items, uint nitems) const; void Item_param_setup_conversion(THD *thd, Item_param *) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -3317,7 +5935,18 @@ public: const st_value *value) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; + void + Column_definition_attributes_frm_pack(const Column_definition_attributes *at, + uchar *buff) const; + bool + Column_definition_attributes_frm_unpack(Column_definition_attributes *attr, + TABLE_SHARE *share, + const uchar *buffer, + LEX_CUSTRING *gis_options) const; bool Column_definition_fix_attributes(Column_definition *c) const; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, @@ -3331,6 +5960,14 @@ public: const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; + bool can_return_int() const { return false; } bool can_return_decimal() const { return false; } bool can_return_real() const { return false; } @@ -3380,6 +6017,9 @@ public: Type_handler_hybrid_field_type *, Type_all_attributes *atrr, Item **items, uint nitems) const; + void Column_definition_reuse_fix_attributes(THD *thd, + Column_definition *c, + const Field *field) const; bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, @@ -3402,7 +6042,11 @@ class Type_handler_enum: public Type_handler_typelib public: virtual ~Type_handler_enum() {} const Name name() const { return m_name_enum; } - virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; } + enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; } + enum_field_types traditional_merge_field_type() const + { + return MYSQL_TYPE_ENUM; + } uint32 calc_pack_length(uint32 length) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; @@ -3414,6 +6058,13 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; @@ -3423,7 +6074,11 @@ class Type_handler_set: public Type_handler_typelib public: virtual ~Type_handler_set() {} const Name name() const { return m_name_set; } - virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; } + enum_field_types real_field_type() const { return MYSQL_TYPE_SET; } + enum_field_types traditional_merge_field_type() const + { + return MYSQL_TYPE_SET; + } uint32 calc_pack_length(uint32 length) const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; @@ -3435,9 +6090,26 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const; }; +// A pseudo type handler, mostly for test purposes for now +class Type_handler_interval_DDhhmmssff: public Type_handler_long_blob +{ +public: + Item *create_typecast_item(THD *thd, Item *item, + const Type_cast_attributes &attr) const; +}; + + + /** A handler for hybrid type functions, e.g. COALESCE(), IF(), IFNULL(), NULLIF(), CASE, @@ -3535,12 +6207,14 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_set type_handler_set; extern MYSQL_PLUGIN_IMPORT Type_handler_string type_handler_string; extern MYSQL_PLUGIN_IMPORT Type_handler_var_string type_handler_var_string; extern MYSQL_PLUGIN_IMPORT Type_handler_varchar type_handler_varchar; +extern MYSQL_PLUGIN_IMPORT Type_handler_hex_hybrid type_handler_hex_hybrid; extern MYSQL_PLUGIN_IMPORT Type_handler_tiny_blob type_handler_tiny_blob; extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob; extern MYSQL_PLUGIN_IMPORT Type_handler_long_blob type_handler_long_blob; extern MYSQL_PLUGIN_IMPORT Type_handler_blob type_handler_blob; +extern MYSQL_PLUGIN_IMPORT Type_handler_bool type_handler_bool; extern MYSQL_PLUGIN_IMPORT Type_handler_tiny type_handler_tiny; extern MYSQL_PLUGIN_IMPORT Type_handler_short type_handler_short; extern MYSQL_PLUGIN_IMPORT Type_handler_int24 type_handler_int24; @@ -3553,6 +6227,7 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_newdecimal type_handler_newdecimal; extern MYSQL_PLUGIN_IMPORT Type_handler_olddecimal type_handler_olddecimal; extern MYSQL_PLUGIN_IMPORT Type_handler_year type_handler_year; +extern MYSQL_PLUGIN_IMPORT Type_handler_year type_handler_year2; extern MYSQL_PLUGIN_IMPORT Type_handler_newdate type_handler_newdate; extern MYSQL_PLUGIN_IMPORT Type_handler_date type_handler_date; extern MYSQL_PLUGIN_IMPORT Type_handler_time type_handler_time; @@ -3567,6 +6242,9 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_blob type_handler_blob; extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob; extern MYSQL_PLUGIN_IMPORT Type_handler_long_blob type_handler_long_blob; +extern MYSQL_PLUGIN_IMPORT Type_handler_interval_DDhhmmssff + type_handler_interval_DDhhmmssff; + class Type_aggregator { bool m_is_commutative; diff --git a/sql/sql_type_int.h b/sql/sql_type_int.h index 7433bd5249f..f9fb163b6a6 100644 --- a/sql/sql_type_int.h +++ b/sql/sql_type_int.h @@ -1,5 +1,4 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. - Copyright (c) 2011, 2016, MariaDB +/* Copyright (c) 2018, 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,11 +17,39 @@ #define SQL_TYPE_INT_INCLUDED -// A longlong/ulonglong hybrid. Good to store results of val_int(). -class Longlong_hybrid +class Null_flag +{ +protected: + bool m_is_null; +public: + bool is_null() const { return m_is_null; } + Null_flag(bool is_null) :m_is_null(is_null) { } +}; + + +class Longlong { protected: longlong m_value; +public: + longlong value() const { return m_value; } + Longlong(longlong nr) :m_value(nr) { } +}; + + +class Longlong_null: public Longlong, public Null_flag +{ +public: + Longlong_null(longlong nr, bool is_null) + :Longlong(nr), Null_flag(is_null) + { } +}; + + +// A longlong/ulonglong hybrid. Good to store results of val_int(). +class Longlong_hybrid: public Longlong +{ +protected: bool m_unsigned; int cmp_signed(const Longlong_hybrid& other) const { @@ -35,9 +62,8 @@ protected: } public: Longlong_hybrid(longlong nr, bool unsigned_flag) - :m_value(nr), m_unsigned(unsigned_flag) + :Longlong(nr), m_unsigned(unsigned_flag) { } - longlong value() const { return m_value; } bool is_unsigned() const { return m_unsigned; } bool is_unsigned_outside_of_signed_range() const { @@ -69,4 +95,16 @@ public: } }; + +class Longlong_hybrid_null: public Longlong_hybrid, + public Null_flag +{ +public: + Longlong_hybrid_null(const Longlong_null &nr, bool unsigned_flag) + :Longlong_hybrid(nr.value(), unsigned_flag), + Null_flag(nr.is_null()) + { } +}; + + #endif // SQL_TYPE_INT_INCLUDED diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 9a036156de6..aee4869bd40 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -76,6 +76,8 @@ static const char *init_syms(udf_func *tmp, char *nm) (void)strmov(end, "_add"); if (!((tmp->func_add= (Udf_func_add) dlsym(tmp->dlhandle, nm)))) return nm; + (void)strmov(end, "_remove"); + tmp->func_remove= (Udf_func_add) dlsym(tmp->dlhandle, nm); } (void) strmov(end,"_deinit"); @@ -565,6 +567,7 @@ int mysql_create_function(THD *thd,udf_func *udf) u_d->func_deinit= udf->func_deinit; u_d->func_clear= udf->func_clear; u_d->func_add= udf->func_add; + u_d->func_remove= udf->func_remove; /* create entry in mysql.func table */ diff --git a/sql/sql_udf.h b/sql/sql_udf.h index 6e6fed2a81a..4fa75759269 100644 --- a/sql/sql_udf.h +++ b/sql/sql_udf.h @@ -47,6 +47,7 @@ typedef struct st_udf_func Udf_func_deinit func_deinit; Udf_func_clear func_clear; Udf_func_add func_add; + Udf_func_add func_remove; ulong usage_count; } udf_func; @@ -131,6 +132,20 @@ class udf_handler :public Sql_alloc func(&initid, &f_args, &is_null, &error); *null_value= (my_bool) (is_null || error); } + bool supports_removal() const + { return MY_TEST(u_d->func_remove); } + void remove(my_bool *null_value) + { + DBUG_ASSERT(u_d->func_remove); + if (get_arguments()) + { + *null_value=1; + return; + } + Udf_func_add func= u_d->func_remove; + func(&initid, &f_args, &is_null, &error); + *null_value= (my_bool) (is_null || error); + } String *val_str(String *str,String *save_str); }; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index edf85c2084b..ca8a5e7a8b3 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -68,7 +68,7 @@ void select_unit::change_select() curr_sel= current_select_number; /* New SELECT processing starts */ DBUG_ASSERT(table->file->inited == 0); - step= thd->lex->current_select->linkage; + step= thd->lex->current_select->get_linkage(); switch (step) { case INTERSECT_TYPE: @@ -248,7 +248,7 @@ bool select_unit::send_eof() { if (step != INTERSECT_TYPE || (thd->lex->current_select->next_select() && - thd->lex->current_select->next_select()->linkage == INTERSECT_TYPE)) + thd->lex->current_select->next_select()->get_linkage() == INTERSECT_TYPE)) { /* it is not INTESECT or next SELECT in the sequence is INTERSECT so no @@ -752,11 +752,11 @@ bool st_select_lex_unit::join_union_type_attributes(THD *thd_arg, been fixed yet. An Item_type_holder must be created based on a fixed Item, so use the inner Item instead. */ - DBUG_ASSERT(item_tmp->fixed || + DBUG_ASSERT(item_tmp->is_fixed() || (item_tmp->type() == Item::REF_ITEM && ((Item_ref *)(item_tmp))->ref_type() == Item_ref::OUTER_REF)); - if (!item_tmp->fixed) + if (!item_tmp->is_fixed()) item_tmp= item_tmp->real_item(); holders[holder_pos].add_argument(item_tmp); } @@ -1422,7 +1422,7 @@ bool st_select_lex_unit::exec() union_result->change_select(); if (fake_select_lex) { - if (sl != &thd->lex->select_lex) + if (sl != thd->lex->first_select_lex()) fake_select_lex->uncacheable|= sl->uncacheable; else fake_select_lex->uncacheable= 0; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 959747acf28..d74da408dfc 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -318,7 +318,7 @@ int mysql_update(THD *thd, SQL_SELECT *select= NULL; SORT_INFO *file_sort= 0; READ_RECORD info; - SELECT_LEX *select_lex= &thd->lex->select_lex; + SELECT_LEX *select_lex= thd->lex->first_select_lex(); ulonglong id; List<Item> all_fields; killed_state killed_status= NOT_KILLED; @@ -375,7 +375,7 @@ int mysql_update(THD *thd, table->covering_keys= table->s->keys_in_use; table->quick_keys.clear_all(); - query_plan.select_lex= &thd->lex->select_lex; + query_plan.select_lex= thd->lex->first_select_lex(); query_plan.table= table; #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Force privilege re-checking for views after they have been opened. */ @@ -977,7 +977,7 @@ update_begin: myf flags= 0; if (table->file->is_fatal_error(error, HA_CHECK_ALL)) - flags|= ME_FATALERROR; /* Other handler errors are fatal */ + flags|= ME_FATAL; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); table->file->print_error(error,MYF(flags)); @@ -1088,7 +1088,7 @@ update_begin: { /* purecov: begin inspected */ prepare_record_for_error_message(loc_error, table); - table->file->print_error(loc_error,MYF(ME_FATALERROR)); + table->file->print_error(loc_error,MYF(ME_FATAL)); error= 1; /* purecov: end */ } @@ -1246,7 +1246,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, TABLE *table= table_list->table; #endif List<Item> all_fields; - SELECT_LEX *select_lex= &thd->lex->select_lex; + SELECT_LEX *select_lex= thd->lex->first_select_lex(); DBUG_ENTER("mysql_prepare_update"); #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -1523,7 +1523,7 @@ int mysql_multi_update_prepare(THD *thd) LEX *lex= thd->lex; TABLE_LIST *table_list= lex->query_tables; TABLE_LIST *tl; - List<Item> *fields= &lex->select_lex.item_list; + List<Item> *fields= &lex->first_select_lex()->item_list; table_map tables_for_update; bool update_view= 0; /* @@ -1565,14 +1565,15 @@ int mysql_multi_update_prepare(THD *thd) if (mysql_handle_derived(lex, DT_PREPARE)) DBUG_RETURN(TRUE); - if (setup_tables_and_check_access(thd, &lex->select_lex.context, - &lex->select_lex.top_join_list, + if (setup_tables_and_check_access(thd, + &lex->first_select_lex()->context, + &lex->first_select_lex()->top_join_list, table_list, - lex->select_lex.leaf_tables, FALSE, - UPDATE_ACL, SELECT_ACL, FALSE)) + lex->first_select_lex()->leaf_tables, + FALSE, UPDATE_ACL, SELECT_ACL, FALSE)) DBUG_RETURN(TRUE); - if (lex->select_lex.handle_derived(thd->lex, DT_MERGE)) + if (lex->first_select_lex()->handle_derived(thd->lex, DT_MERGE)) DBUG_RETURN(TRUE); if (setup_fields_with_no_wrap(thd, Ref_ptr_array(), @@ -1595,13 +1596,14 @@ int mysql_multi_update_prepare(THD *thd) thd->table_map_for_update= tables_for_update= get_table_map(fields); - if (unsafe_key_update(lex->select_lex.leaf_tables, tables_for_update)) + if (unsafe_key_update(lex->first_select_lex()->leaf_tables, + tables_for_update)) DBUG_RETURN(true); /* Setup timestamp handling and locking mode */ - List_iterator<TABLE_LIST> ti(lex->select_lex.leaf_tables); + List_iterator<TABLE_LIST> ti(lex->first_select_lex()->leaf_tables); while ((tl= ti++)) { TABLE *table= tl->table; @@ -1694,7 +1696,7 @@ int mysql_multi_update_prepare(THD *thd) Check that we are not using table that we are updating, but we should skip all tables of UPDATE SELECT itself */ - lex->select_lex.exclude_from_table_unique_test= TRUE; + lex->first_select_lex()->exclude_from_table_unique_test= TRUE; /* We only need SELECT privilege for columns in the values list */ ti.rewind(); while ((tl= ti++)) @@ -1716,7 +1718,7 @@ int mysql_multi_update_prepare(THD *thd) Set exclude_from_table_unique_test value back to FALSE. It is needed for further check in multi_update::prepare whether to use record cache. */ - lex->select_lex.exclude_from_table_unique_test= FALSE; + lex->first_select_lex()->exclude_from_table_unique_test= FALSE; if (lex->save_prep_leaf_tables()) DBUG_RETURN(TRUE); @@ -1745,7 +1747,7 @@ bool mysql_multi_update(THD *thd, DBUG_ENTER("mysql_multi_update"); if (!(*result= new (thd->mem_root) multi_update(thd, table_list, - &thd->lex->select_lex.leaf_tables, + &thd->lex->first_select_lex()->leaf_tables, fields, values, handle_duplicates, ignore))) { @@ -2248,11 +2250,11 @@ int multi_update::prepare2(JOIN *join) { if (item_rowid_table(*it2) != tbl) continue; - Item *fld= new (thd->mem_root) - Item_field(thd, (*it)->get_tmp_table_field()); + Item_field *fld= new (thd->mem_root) + Item_field(thd, (*it)->get_tmp_table_field()); if (!fld) return 1; - fld->set_result_field((*it2)->get_tmp_table_field()); + fld->result_field= (*it2)->get_tmp_table_field(); *it2= fld; } } @@ -2384,7 +2386,7 @@ int multi_update::send_data(List<Item> ¬_used_values) myf flags= 0; if (table->file->is_fatal_error(error, HA_CHECK_ALL)) - flags|= ME_FATALERROR; /* Other handler errors are fatal */ + flags|= ME_FATAL; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); table->file->print_error(error,MYF(flags)); @@ -2539,17 +2541,10 @@ int multi_update::do_updates() not its dependencies */ while(TABLE *tbl= check_opt_it++) - { - if (tbl->vcol_set) - { - bitmap_clear_all(tbl->vcol_set); - for (Field **vf= tbl->vfield; *vf; vf++) - { + if (Field **vf= tbl->vfield) + for (; *vf; vf++) if (bitmap_is_set(tbl->read_set, (*vf)->field_index)) - tbl->mark_virtual_col(*vf); - } - } - } + (*vf)->vcol_info->expr->walk(&Item::register_field_in_read_map, 1, 0); for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local) { @@ -2639,10 +2634,10 @@ int multi_update::do_updates() uint field_num= 0; do { - if (unlikely((local_error= - tbl->file->ha_rnd_pos(tbl->record[0], - (uchar *) tmp_table-> - field[field_num]->ptr)))) + String rowid; + tmp_table->field[field_num]->val_str(&rowid); + if (unlikely((local_error= tbl->file->ha_rnd_pos(tbl->record[0], + (uchar*)rowid.ptr())))) { err_table= tbl; goto err; @@ -2759,7 +2754,7 @@ int multi_update::do_updates() err: { prepare_record_for_error_message(local_error, err_table); - err_table->file->print_error(local_error,MYF(ME_FATALERROR)); + err_table->file->print_error(local_error,MYF(ME_FATAL)); } err2: diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 07230b2205b..e475a3d3719 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -254,7 +254,7 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, LEX *lex= thd->lex; /* first table in list is target VIEW name => cut off it */ TABLE_LIST *tbl; - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); SELECT_LEX *sl; bool res= TRUE; DBUG_ENTER("create_view_precheck"); @@ -323,7 +323,6 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, } } - if (&lex->select_lex != lex->all_selects_list) { /* check tables of subqueries */ for (tbl= tables; tbl; tbl= tbl->next_global) @@ -399,7 +398,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, TABLE_LIST *view= lex->unlink_first_table(&link_to_local); TABLE_LIST *tables= lex->query_tables; TABLE_LIST *tbl; - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); SELECT_LEX *sl; SELECT_LEX_UNIT *unit= &lex->unit; bool res= FALSE; @@ -711,9 +710,10 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, lex->link_first_table_back(view, link_to_local); DBUG_RETURN(0); - -WSREP_ERROR_LABEL: - res= TRUE; +#ifdef WITH_WSREP +wsrep_error_label: + res= true; +#endif err: lex->link_first_table_back(view, link_to_local); @@ -995,7 +995,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, view->algorithm != VIEW_ALGORITHM_TMPTABLE))) { /* TODO: change here when we will support UNIONs */ - for (TABLE_LIST *tbl= lex->select_lex.table_list.first; + for (TABLE_LIST *tbl= lex->first_select_lex()->table_list.first; tbl; tbl= tbl->next_local) { @@ -1114,8 +1114,8 @@ loop_out: UNION */ if (view->updatable_view && - !lex->select_lex.master_unit()->is_unit_op() && - !(lex->select_lex.table_list.first)->next_local && + !lex->first_select_lex()->master_unit()->is_unit_op() && + !(lex->first_select_lex()->table_list.first)->next_local && find_table_in_global_list(lex->query_tables->next_global, &lex->query_tables->db, &lex->query_tables->table_name)) @@ -1162,7 +1162,8 @@ err: bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, bool open_view_no_parse) { - SELECT_LEX *end, *UNINIT_VAR(view_select); + SELECT_LEX_NODE *end; + SELECT_LEX *UNINIT_VAR(view_select); LEX *old_lex, *lex; Query_arena *arena, backup; TABLE_LIST *top_view= table->top_table(); @@ -1361,8 +1362,6 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, lex_start(thd); lex->stmt_lex= old_lex; - view_select= &lex->select_lex; - view_select->select_number= ++thd->lex->stmt_lex->current_select_number; sql_mode_t saved_mode= thd->variables.sql_mode; /* switch off modes which can prevent normal parsing of VIEW @@ -1397,6 +1396,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, parse_status= parse_sql(thd, & parser_state, table->view_creation_ctx); + view_select= lex->first_select_lex(); + /* Restore environment. */ if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) || @@ -1546,7 +1547,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, This may change in future, for example if we enable merging of views with subqueries in select list. */ - view_main_select_tables= lex->select_lex.table_list.first; + view_main_select_tables= lex->first_select_lex()->table_list.first; /* Let us set proper lock type for tables of the view's main @@ -1573,7 +1574,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, /* Fields in this view can be used in upper select in case of merge. */ if (table->select_lex) - table->select_lex->add_where_field(&lex->select_lex); + table->select_lex->add_where_field(lex->first_select_lex()); } /* This method has a dependency on the proper lock type being set, @@ -1595,8 +1596,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query && lex->safe_to_cache_query); /* move SQL_CACHE to whole query */ - if (view_select->options & OPTION_TO_QUERY_CACHE) - old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE; + if (lex->first_select_lex()->options & OPTION_TO_QUERY_CACHE) + old_lex->first_select_lex()->options|= OPTION_TO_QUERY_CACHE; #ifndef NO_EMBEDDED_ACCESS_CHECKS if (table->view_suid) @@ -1678,9 +1679,10 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, tbl->grant.want_privilege= top_view->grant.orig_want_privilege; /* prepare view context */ - lex->select_lex.context.resolve_in_table_list_only(view_main_select_tables); - lex->select_lex.context.outer_context= 0; - lex->select_lex.select_n_having_items+= + lex->first_select_lex()-> + context.resolve_in_table_list_only(view_main_select_tables); + lex->first_select_lex()->context.outer_context= 0; + lex->first_select_lex()->select_n_having_items+= table->select_lex->select_n_having_items; table->where= view_select->where; @@ -1691,12 +1693,13 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, */ if (!table->select_lex->master_unit()->is_unit_op() && table->select_lex->order_list.elements == 0) - table->select_lex->order_list.push_back(&lex->select_lex.order_list); + table->select_lex->order_list. + push_back(&lex->first_select_lex()->order_list); else { if (old_lex->sql_command == SQLCOM_SELECT && (old_lex->describe & DESCRIBE_EXTENDED) && - lex->select_lex.order_list.elements && + lex->first_select_lex()->order_list.elements && !table->select_lex->master_unit()->is_unit_op()) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, @@ -1731,7 +1734,11 @@ ok: lex->unit.include_down(table->select_lex); lex->unit.slave= view_select; // fix include_down initialisation /* global SELECT list linking */ - end= view_select; // primary SELECT_LEX is always last + /* + The primary SELECT_LEX is always last (because parsed first) if WITH not + used, otherwise it is good start point for last element finding + */ + for (end= view_select; end->link_next; end= end->link_next); end->link_next= old_lex->all_selects_list; old_lex->all_selects_list->link_prev= &end->link_next; old_lex->all_selects_list= lex->all_selects_list; @@ -1916,7 +1923,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) */ if ((!view->view && !view->belong_to_view) || thd->lex->sql_command == SQLCOM_INSERT || - thd->lex->select_lex.select_limit == 0) + thd->lex->first_select_lex()->select_limit == 0) DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */ table= view->table; view= view->top_table(); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 46eac699c04..f628ef098a1 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -491,96 +491,6 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, } /** - @brief Creates a new SELECT_LEX for a UNION branch. - - Sets up and initializes a SELECT_LEX structure for a query once the parser - discovers a UNION token. The current SELECT_LEX is pushed on the stack and - the new SELECT_LEX becomes the current one. - - @param lex The parser state. - - @param is_union_distinct True if the union preceding the new select - statement uses UNION DISTINCT. - - @param is_top_level This should be @c TRUE if the newly created SELECT_LEX - is a non-nested statement. - - @return <code>false</code> if successful, <code>true</code> if an error was - reported. In the latter case parsing should stop. - */ -bool LEX::add_select_to_union_list(bool is_union_distinct, - enum sub_select_type type, - bool is_top_level) -{ - const char *type_name= (type == INTERSECT_TYPE ? "INTERSECT" : - (type == EXCEPT_TYPE ? "EXCEPT" : "UNION")); - /* - Only the last SELECT can have INTO. Since the grammar won't allow INTO in - a nested SELECT, we make this check only when creating a top-level SELECT. - */ - if (is_top_level && result) - { - my_error(ER_WRONG_USAGE, MYF(0), type_name, "INTO"); - return TRUE; - } - if (current_select->order_list.first && !current_select->braces) - { - my_error(ER_WRONG_USAGE, MYF(0), type_name, "ORDER BY"); - return TRUE; - } - - if (current_select->explicit_limit && !current_select->braces) - { - my_error(ER_WRONG_USAGE, MYF(0), type_name, "LIMIT"); - return TRUE; - } - if (current_select->linkage == GLOBAL_OPTIONS_TYPE) - { - thd->parse_error(); - return TRUE; - } - if (!is_union_distinct && (type == INTERSECT_TYPE || type == EXCEPT_TYPE)) - { - my_error(ER_WRONG_USAGE, MYF(0), type_name, "ALL"); - return TRUE; - } - /* - Priority implementation, but also trying to keep things as flat - as possible */ - if (type == INTERSECT_TYPE && - (current_select->linkage != INTERSECT_TYPE && - current_select != current_select->master_unit()->first_select()) - && !(thd->variables.sql_mode & MODE_ORACLE)) - { - /* - This and previous SELECTs should go one level down because of - priority - */ - SELECT_LEX *prev= exclude_last_select(); - if (add_unit_in_brackets(prev)) - return TRUE; - return add_select_to_union_list(is_union_distinct, type, 0); - } - else - { - check_automatic_up(type); - } - /* This counter shouldn't be incremented for UNION parts */ - nest_level--; - if (mysql_new_select(this, 0, NULL)) - return TRUE; - mysql_init_select(this); - current_select->linkage= type; - current_select->with_all_modifier= !is_union_distinct; - if (is_union_distinct) /* UNION DISTINCT - remember position */ - current_select->master_unit()->union_distinct= current_select; - else - DBUG_ASSERT(type == UNION_TYPE); - return FALSE; -} - - -/** Create a separate LEX for each assignment if in SP. If we are in SP we want have own LEX for each assignment. @@ -621,6 +531,7 @@ void sp_create_assignment_lex(THD *thd, bool no_lookahead) lex->sphead->m_tmp_query= lip->get_tok_end(); /* Inherit from outer lex. */ lex->option_type= old_lex->option_type; + lex->main_select_push(); } } @@ -642,8 +553,6 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead) if (lex->sphead) { - sp_head *sp= lex->sphead; - if (!lex->var_list.is_empty()) { /* @@ -651,35 +560,22 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead) option setting, so we should construct sp_instr_stmt for it. */ - LEX_STRING qbuff; - sp_instr_stmt *i; Lex_input_stream *lip= &thd->m_parser_state->m_lip; - if (!(i= new (thd->mem_root) - sp_instr_stmt(sp->instructions(), lex->spcont, lex))) - return true; - /* Extract the query statement from the tokenizer. The end is either lip->ptr, if there was no lookahead, lip->tok_end otherwise. */ - if (no_lookahead) - qbuff.length= lip->get_ptr() - sp->m_tmp_query; - else - qbuff.length= lip->get_tok_end() - sp->m_tmp_query; - - if (!(qbuff.str= (char*) alloc_root(thd->mem_root, - qbuff.length + 5))) - return true; - - strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query, - qbuff.length); - qbuff.length+= 4; - i->m_query= qbuff; - if (sp->add_instr(i)) + static const LEX_CSTRING setsp= { STRING_WITH_LEN("SET ") }; + const char *qend= no_lookahead ? lip->get_ptr() : lip->get_tok_end(); + Lex_cstring qbuf(lex->sphead->m_tmp_query, qend); + if (lex->new_sp_instr_stmt(thd, setsp, qbuf)) return true; } + lex->pop_select(); + if (Lex->check_main_unit_semantics()) + return true; enum_var_type inner_option_type= lex->option_type; if (lex->sphead->restore_lex(thd)) return true; @@ -767,6 +663,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) return v; } + %} %union { int num; @@ -791,6 +688,20 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) Lex_for_loop_bounds_st for_loop_bounds; Lex_trim_st trim; vers_history_point_t vers_history_point; + struct + { + enum sub_select_type unit_type; + bool distinct; + } unit_operation; + struct + { + SELECT_LEX *first; + SELECT_LEX *prev_last; + } select_list; + SQL_I_List<ORDER> *select_order; + Lex_select_lock select_lock; + Lex_select_limit select_limit; + Lex_order_limit_lock *order_limit_lock; /* pointers */ Create_field *create_field; @@ -836,6 +747,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) handlerton *db_type; st_select_lex *select_lex; + st_select_lex_unit *select_lex_unit; struct p_elem_val *p_elem_value; class Window_frame *window_frame; class Window_frame_bound *window_frame_bound; @@ -844,7 +756,6 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) /* enums */ enum enum_view_suid view_suid; - enum sub_select_type unit_type; enum Condition_information_item::Name cond_info_item_name; enum enum_diag_condition_item_name diag_condition_item_name; enum Diagnostics_information::Which_area diag_area; @@ -884,10 +795,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 52 shift/reduce conflicts. + Currently there are 48 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 52 +%expect 48 /* Comments for TOKENS. @@ -1044,6 +955,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token LEADING /* SQL-2003-R */ %token LEAVE_SYM %token LEFT /* SQL-2003-R */ +%token LEFT_PAREN_ALT /* INTERNAL */ +%token LEFT_PAREN_WITH /* INTERNAL */ +%token LEFT_PAREN_LIKE /* INTERNAL */ %token LEX_HOSTNAME %token LIKE /* SQL-2003-R */ %token LIMIT @@ -1589,6 +1503,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token <kwd> SQL_CALC_FOUND_ROWS %token <kwd> SQL_NO_CACHE_SYM %token <kwd> SQL_THREAD +%token <kwd> STAGE_SYM %token <kwd> STARTS_SYM %token <kwd> START_SYM /* SQL-2003-R */ %token <kwd> STATEMENT_SYM @@ -1817,7 +1732,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); NCHAR_STRING %type <lex_str_ptr> - opt_table_alias + opt_table_alias_clause + table_alias_clause %type <ident_cli> IDENT @@ -1882,7 +1798,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); opt_temporary all_or_any opt_distinct opt_glimit_clause opt_ignore_leaves fulltext_options union_option opt_not - select_derived_init transaction_access_mode_types + transaction_access_mode_types opt_natural_language_mode opt_query_expansion opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt @@ -2005,11 +1921,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); join_table_list join_table table_factor table_ref esc_table_ref table_primary_ident table_primary_derived - select_derived derived_table_list - select_derived_union - derived_simple_table - derived_query_specification - derived_table_value_constructor + derived_table_list table_reference_list_parens + nested_table_reference_list join_table_parens %type <date_time_type> date_time_type; %type <interval> interval @@ -2043,14 +1956,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); UNDERSCORE_CHARSET %type <select_lex> subselect - get_select_lex get_select_lex_derived - simple_table query_specification - query_term_union_not_ready - query_term_union_ready - query_expression_body - select_paren_derived table_value_constructor + simple_table + query_primary + query_primary_parens + select_into_query_specification + + +%type <select_lex_unit> + query_specification_start + query_expression_body + query_expression + query_expression_unit %type <boolfunc2creator> comp_op @@ -2062,11 +1980,28 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type <virtual_column> opt_check_constraint check_constraint virtual_column_func column_default_expr -%type <unit_type> unit_type_decl + +%type <unit_operation> unit_type_decl + +%type <select_lock> + opt_procedure_or_into + opt_select_lock_type + select_lock_type + opt_lock_wait_timeout_new + +%type <select_limit> opt_limit_clause limit_clause limit_options + +%type <order_limit_lock> + query_expression_tail + order_or_limit + opt_order_limit_lock + +%type <select_order> opt_order_clause order_clause order_list %type <NONE> - analyze_stmt_command - query verb_clause create change select do drop insert replace insert2 + analyze_stmt_command backup + query verb_clause create change select select_into + do drop insert replace insert2 insert_values update delete truncate rename compound_statement show describe load alter optimize keycache preload flush reset purge begin_stmt_mariadb commit rollback savepoint release @@ -2082,7 +2017,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); assign_to_keycache_parts preload_list preload_list_or_parts preload_keys preload_keys_parts select_item_list select_item values_list no_braces - opt_limit_clause delete_limit_clause fields opt_values values + delete_limit_clause fields opt_values values no_braces_with_names opt_values_with_names values_with_names procedure_list procedure_list2 procedure_item field_def handler opt_generated_always @@ -2103,9 +2038,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan single_multi table_wild_list table_wild_one opt_wild - union_clause union_list - subselect_start opt_and charset - subselect_end select_var_list select_var_list_init help + opt_and charset + select_var_list select_var_list_init help opt_extended_describe shutdown opt_format_json prepare prepare_src execute deallocate @@ -2239,8 +2173,8 @@ rule: <-- starts at col 1 query: END_OF_INPUT { - if (likely(!thd->bootstrap) && - unlikely(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT))) + if (!thd->bootstrap && + (!(thd->lex->lex_options & OPTION_LEX_FOUND_COMMENT))) my_yyabort_error((ER_EMPTY_QUERY, MYF(0))); thd->lex->sql_command= SQLCOM_EMPTY_QUERY; @@ -2294,6 +2228,7 @@ statement: alter | analyze | analyze_stmt_command + | backup | binlog_base64_event | call | change @@ -2336,6 +2271,7 @@ statement: | rollback | savepoint | select + | select_into | set | signal_stmt | show @@ -2371,6 +2307,8 @@ prepare: if (unlikely(lex->table_or_sp_used())) my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "PREPARE..FROM")); + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; lex->sql_command= SQLCOM_PREPARE; lex->prepared_stmt_name= $2; } @@ -2393,7 +2331,10 @@ execute: lex->prepared_stmt_name= $2; } execute_using - {} + { + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } | EXECUTE_SYM IMMEDIATE_SYM prepare_src { if (unlikely(Lex->table_or_sp_used())) @@ -2402,7 +2343,10 @@ execute: Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE; } execute_using - {} + { + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; execute_using: @@ -2689,17 +2633,22 @@ connection_name: /* create a table */ create: - create_or_replace opt_temporary TABLE_SYM opt_if_not_exists table_ident + create_or_replace opt_temporary TABLE_SYM opt_if_not_exists { LEX *lex= thd->lex; lex->create_info.init(); - if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, - $1 | $4))) + if (lex->main_select_push()) + MYSQL_YYABORT; + lex->current_select->parsing_place= BEFORE_OPT_LIST; + if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4)) MYSQL_YYABORT; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_UPDATING, - TL_WRITE, - MDL_EXCLUSIVE))) + } + table_ident + { + LEX *lex= thd->lex; + if (!lex->first_select_lex()-> + add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING, + TL_WRITE, MDL_SHARED_UPGRADABLE)) MYSQL_YYABORT; lex->alter_info.reset(); /* @@ -2714,7 +2663,6 @@ create: create_body { LEX *lex= thd->lex; - lex->current_select= &lex->select_lex; if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) && !lex->create_info.db_type) { @@ -2723,22 +2671,24 @@ create: ER_WARN_USING_OTHER_HANDLER, ER_THD(thd, ER_WARN_USING_OTHER_HANDLER), hton_name(lex->create_info.db_type)->str, - $5->table.str); + $6->table.str); } create_table_set_open_action_and_adjust_tables(lex); + Lex->pop_select(); //main select } | create_or_replace opt_temporary SEQUENCE_SYM opt_if_not_exists table_ident { LEX *lex= thd->lex; + if (Lex->main_select_push()) + MYSQL_YYABORT; lex->create_info.init(); if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2, $1 | $4))) MYSQL_YYABORT; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_UPDATING, - TL_WRITE, - MDL_EXCLUSIVE))) + if (!lex->first_select_lex()-> + add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING, + TL_WRITE, MDL_EXCLUSIVE)) MYSQL_YYABORT; /* @@ -2761,8 +2711,9 @@ create: if (unlikely(lex->create_info.seq_create_info->check_and_adjust(1))) { my_error(ER_SEQUENCE_INVALID_DATA, MYF(0), - lex->select_lex.table_list.first->db.str, - lex->select_lex.table_list.first->table_name.str); + lex->first_select_lex()->table_list.first->db.str, + lex->first_select_lex()->table_list.first-> + table_name.str); MYSQL_YYABORT; } @@ -2775,10 +2726,8 @@ create: Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE; Lex->create_info.sequence= 1; - lex->current_select= &lex->select_lex; - if (unlikely((lex->create_info.used_fields & - HA_CREATE_USED_ENGINE) && - !lex->create_info.db_type)) + if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) && + !lex->create_info.db_type) { lex->create_info.use_default_db_type(thd); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -2788,44 +2737,69 @@ create: $5->table.str); } create_table_set_open_action_and_adjust_tables(lex); + Lex->pop_select(); //main select + } + | create_or_replace opt_unique INDEX_SYM opt_if_not_exists + { + if (Lex->main_select_push()) + MYSQL_YYABORT; } - | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident + ident opt_key_algorithm_clause ON table_ident { - if (unlikely(Lex->add_create_index_prepare($8))) + if (Lex->add_create_index_prepare($9)) MYSQL_YYABORT; - if (unlikely(Lex->add_create_index($2, &$5, $6, $1 | $4))) + if (Lex->add_create_index($2, &$6, $7, $1 | $4)) MYSQL_YYABORT; } '(' key_list ')' opt_lock_wait_timeout normal_key_options - opt_index_lock_algorithm { } - | create_or_replace fulltext INDEX_SYM opt_if_not_exists ident + opt_index_lock_algorithm + { + Lex->pop_select(); //main select + } + | create_or_replace fulltext INDEX_SYM + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + opt_if_not_exists ident ON table_ident { - if (unlikely(Lex->add_create_index_prepare($7))) + if (Lex->add_create_index_prepare($8)) MYSQL_YYABORT; - if (unlikely(Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, - $1 | $4))) + if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5)) MYSQL_YYABORT; } '(' key_list ')' opt_lock_wait_timeout fulltext_key_options - opt_index_lock_algorithm { } - | create_or_replace spatial INDEX_SYM opt_if_not_exists ident + opt_index_lock_algorithm + { + Lex->pop_select(); //main select + } + | create_or_replace spatial INDEX_SYM + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + opt_if_not_exists ident ON table_ident { - if (unlikely(Lex->add_create_index_prepare($7))) + if (Lex->add_create_index_prepare($8)) MYSQL_YYABORT; - if (unlikely(Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, - $1 | $4))) + if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5)) MYSQL_YYABORT; } '(' key_list ')' opt_lock_wait_timeout spatial_key_options - opt_index_lock_algorithm { } + opt_index_lock_algorithm + { + Lex->pop_select(); //main select + } | create_or_replace DATABASE opt_if_not_exists ident { Lex->create_info.default_table_charset= NULL; Lex->create_info.used_fields= 0; + if (Lex->main_select_push()) + MYSQL_YYABORT; } opt_create_database_options { @@ -2834,61 +2808,105 @@ create: $1 | $3))) MYSQL_YYABORT; lex->name= $4; + Lex->pop_select(); //main select } | create_or_replace definer_opt opt_view_suid VIEW_SYM opt_if_not_exists table_ident { - if (unlikely(Lex->add_create_view(thd, $1 | $5, - DTYPE_ALGORITHM_UNDEFINED, $3, - $6))) + if (Lex->main_select_push()) + MYSQL_YYABORT; + if (Lex->add_create_view(thd, $1 | $5, + DTYPE_ALGORITHM_UNDEFINED, $3, $6)) MYSQL_YYABORT; } view_list_opt AS view_select - { } + { + Lex->pop_select(); //main select + } | create_or_replace view_algorithm definer_opt opt_view_suid VIEW_SYM opt_if_not_exists table_ident { if (unlikely(Lex->add_create_view(thd, $1 | $6, $2, $4, $7))) MYSQL_YYABORT; + if (Lex->main_select_push()) + MYSQL_YYABORT; } view_list_opt AS view_select - { } + { + Lex->pop_select(); //main select + } | create_or_replace definer_opt TRIGGER_SYM - { Lex->create_info.set($1); } + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + Lex->create_info.set($1); + } trigger_tail - { } + { + Lex->pop_select(); //main select + } | create_or_replace definer_opt PROCEDURE_SYM - { Lex->create_info.set($1); } + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + Lex->create_info.set($1); + } sp_tail - { } + { + Lex->pop_select(); //main select + } | create_or_replace definer_opt EVENT_SYM - { Lex->create_info.set($1); } + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + Lex->create_info.set($1); + } event_tail - { } + { + Lex->pop_select(); //main select + } | create_or_replace definer FUNCTION_SYM { + if (Lex->main_select_push()) + MYSQL_YYABORT; Lex->create_info.set($1); } - sf_tail_not_aggregate - { } + sf_tail + { + Lex->pop_select(); //main select + } | create_or_replace definer AGGREGATE_SYM FUNCTION_SYM { + if (Lex->main_select_push()) + MYSQL_YYABORT; Lex->create_info.set($1); } sf_tail_aggregate - { } + { + Lex->pop_select(); //main select + } | create_or_replace no_definer FUNCTION_SYM - { Lex->create_info.set($1); } + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + Lex->create_info.set($1); + } create_function_tail - { } + { + Lex->pop_select(); //main select + } | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM { + if (Lex->main_select_push()) + MYSQL_YYABORT; Lex->create_info.set($1); } create_aggregate_function_tail - { } - | create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list - opt_require_clause opt_resource_options + { + Lex->pop_select(); //main select + } + | create_or_replace USER_SYM opt_if_not_exists clear_privileges + grant_list opt_require_clause opt_resource_options { if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3))) @@ -2923,6 +2941,7 @@ sf_tail_not_aggregate: } Lex->sphead->set_chistics_agg_type(NOT_AGGREGATE); } + ; sf_tail_aggregate: sf_tail @@ -2933,6 +2952,7 @@ sf_tail_aggregate: } Lex->sphead->set_chistics_agg_type(GROUP_AGGREGATE); } + ; create_function_tail: sf_tail_not_aggregate { } @@ -3289,7 +3309,7 @@ clear_privileges: lex->columns.empty(); lex->grant= lex->grant_tot_col= 0; lex->all_privileges= 0; - lex->select_lex.db= null_clex_str; + lex->first_select_lex()->db= null_clex_str; lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; bzero((char *)&(lex->mqh),sizeof(lex->mqh)); @@ -3814,7 +3834,7 @@ raise_stmt_oracle: signal_stmt: SIGNAL_SYM signal_value opt_set_signal_information { - if (unlikely(Lex->add_signal_statement(thd, $2))) + if (Lex->add_signal_statement(thd, $2)) MYSQL_YYABORT; } ; @@ -4000,6 +4020,7 @@ statement_information_item: if (unlikely($$ == NULL)) MYSQL_YYABORT; } + ; simple_target_specification: ident_cli @@ -4056,6 +4077,7 @@ condition_information_item: if (unlikely($$ == NULL)) MYSQL_YYABORT; } + ; condition_information_item_name: CLASS_ORIGIN_SYM @@ -4185,44 +4207,8 @@ sp_proc_stmt_statement: } statement { - LEX *lex= thd->lex; - Lex_input_stream *lip= YYLIP; - sp_head *sp= lex->sphead; - - sp->m_flags|= sp_get_flags_for_command(lex); - /* "USE db" doesn't work in a procedure */ - if (unlikely(lex->sql_command == SQLCOM_CHANGE_DB)) - my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "USE")); - /* - Don't add an instruction for SET statements, since all - instructions for them were already added during processing - of "set" rule. - */ - DBUG_ASSERT(lex->sql_command != SQLCOM_SET_OPTION || - lex->var_list.is_empty()); - if (lex->sql_command != SQLCOM_SET_OPTION) - { - sp_instr_stmt *i=new (thd->mem_root) - sp_instr_stmt(sp->instructions(), lex->spcont, lex); - if (unlikely(i == NULL)) - MYSQL_YYABORT; - - /* - Extract the query statement from the tokenizer. The - end is either lex->ptr, if there was no lookahead, - lex->tok_end otherwise. - */ - if (yychar == YYEMPTY) - i->m_query.length= lip->get_ptr() - sp->m_tmp_query; - else - i->m_query.length= lip->get_tok_start() - sp->m_tmp_query;; - if (unlikely(!(i->m_query.str= strmake_root(thd->mem_root, - sp->m_tmp_query, - i->m_query.length))) || - unlikely(sp->add_instr(i))) - MYSQL_YYABORT; - } - if (unlikely(sp->restore_lex(thd))) + if (Lex->sp_proc_stmt_statement_finalize(thd, yychar == YYEMPTY) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -4356,7 +4342,7 @@ assignment_source_expr: $$->sp_lex_in_use= true; $$->set_item_and_free_list($3, thd->free_list); thd->free_list= NULL; - if (unlikely($$->sphead->restore_lex(thd))) + if ($$->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -4365,6 +4351,7 @@ for_loop_bound_expr: assignment_source_lex { Lex->sphead->reset_lex(thd, $1); + Lex->current_select->parsing_place= FOR_LOOP_BOUND; } expr { @@ -4374,6 +4361,7 @@ for_loop_bound_expr: $$->set_item_and_free_list($3, NULL); if (unlikely($$->sphead->restore_lex(thd))) MYSQL_YYABORT; + Lex->current_select->parsing_place= NO_MATTER; } ; @@ -4607,7 +4595,8 @@ case_stmt_body: { if (unlikely(Lex->case_stmt_action_expr($2))) MYSQL_YYABORT; - if (unlikely(Lex->sphead->restore_lex(thd))) + + if (Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } simple_when_clause_list @@ -4806,7 +4795,7 @@ while_body: LEX *lex= Lex; if (unlikely(lex->sp_while_loop_expression(thd, $1))) MYSQL_YYABORT; - if (unlikely(lex->sphead->restore_lex(thd))) + if (lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } sp_proc_stmts1 END WHILE_SYM @@ -4829,7 +4818,7 @@ repeat_body: if (unlikely(i == NULL) || unlikely(lex->sphead->add_instr(i))) MYSQL_YYABORT; - if (unlikely(lex->sphead->restore_lex(thd))) + if (lex->sphead->restore_lex(thd)) MYSQL_YYABORT; /* We can shortcut the cont_backpatch here */ i->m_cont_dest= ip+1; @@ -5309,26 +5298,16 @@ size_number: */ create_body: - '(' create_field_list ')' + create_field_list_parens { Lex->create_info.option_list= NULL; } opt_create_table_options opt_create_partitioning opt_create_select {} | opt_create_table_options opt_create_partitioning opt_create_select {} - /* - the following rule is redundant, but there's a shift/reduce - conflict that prevents the rule above from parsing a syntax like - CREATE TABLE t1 (SELECT 1); - */ - | '(' create_select_query_specification ')' - | '(' create_select_query_specification ')' - { Select->set_braces(1);} union_list {} - | '(' create_select_query_specification ')' - { Select->set_braces(1);} union_order_or_limit {} | create_like { Lex->create_info.add(DDL_options_st::OPT_LIKE); - TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd, - $1, NULL, 0, TL_READ, MDL_SHARED_READ); + TABLE_LIST *src_table= Lex->first_select_lex()-> + add_table_to_list(thd, $1, NULL, 0, TL_READ, MDL_SHARED_READ); if (unlikely(! src_table)) MYSQL_YYABORT; /* CREATE TABLE ... LIKE is not allowed for views. */ @@ -5338,7 +5317,7 @@ create_body: create_like: LIKE table_ident { $$= $2; } - | '(' LIKE table_ident ')' { $$= $3; } + | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; } ; opt_create_select: @@ -5347,23 +5326,19 @@ opt_create_select: ; create_select_query_expression: - opt_with_clause SELECT_SYM create_select_part2 opt_table_expression - create_select_part4 - { - Select->set_braces(0); - Select->set_with_clause($1); + query_expression + { + if (Lex->parsed_insert_select($1->first_select())) + MYSQL_YYABORT; } - union_clause - | opt_with_clause SELECT_SYM create_select_part2 - create_select_part3_union_not_ready create_select_part4 + | LEFT_PAREN_WITH with_clause query_expression_body ')' { - Select->set_with_clause($1); + SELECT_LEX *first_select= $3->first_select(); + $3->set_with_clause($2); + $2->attach_to(first_select); + if (Lex->parsed_insert_select(first_select)) + MYSQL_YYABORT; } - | '(' create_select_query_specification ')' - | '(' create_select_query_specification ')' - { Select->set_braces(1);} union_list {} - | '(' create_select_query_specification ')' - { Select->set_braces(1);} union_order_or_limit {} ; opt_create_partitioning: @@ -5446,13 +5421,17 @@ partition_entry: thd->parse_error(ER_PARTITION_ENTRY_ERROR); MYSQL_YYABORT; } - DBUG_ASSERT(Lex->part_info->table); + if (Lex->main_select_push()) + MYSQL_YYABORT; /* We enter here when opening the frm file to translate partition info string into part_info data structure. */ } - partition {} + partition + { + Lex->pop_select(); //main select + } ; partition: @@ -6063,7 +6042,7 @@ opt_versioning_rotation: | INTERVAL_SYM expr interval opt_versioning_interval_start { partition_info *part_info= Lex->part_info; - if (unlikely(part_info->vers_set_interval($2, $3, $4))) + if (unlikely(part_info->vers_set_interval(thd, $2, $3, $4))) { my_error(ER_PART_WRONG_VALUE, MYF(0), Lex->create_last_non_select_table->table_name.str, @@ -6106,56 +6085,6 @@ opt_versioning_interval_start: End of partition parser part */ -create_select_query_specification: - opt_with_clause SELECT_SYM create_select_part2 create_select_part3 - create_select_part4 - { - Select->set_with_clause($1); - } - ; - -create_select_part2: - { - LEX *lex=Lex; - if (lex->sql_command == SQLCOM_INSERT) - lex->sql_command= SQLCOM_INSERT_SELECT; - else if (lex->sql_command == SQLCOM_REPLACE) - lex->sql_command= SQLCOM_REPLACE_SELECT; - /* - The following work only with the local list, the global list - is created correctly in this case - */ - lex->current_select->table_list.save_and_clear(&lex->save_list); - mysql_init_select(lex); - lex->current_select->parsing_place= SELECT_LIST; - } - select_options select_item_list - { - Select->parsing_place= NO_MATTER; - } - ; - -create_select_part3: - opt_table_expression - | create_select_part3_union_not_ready - ; - -create_select_part3_union_not_ready: - table_expression order_or_limit - | order_or_limit - ; - -create_select_part4: - opt_select_lock_type - { - /* - The following work only with the local list, the global list - is created correctly in this case - */ - Lex->current_select->table_list.push_front(&Lex->save_list); - } - ; - opt_as: /* empty */ {} | AS {} @@ -6373,7 +6302,7 @@ create_table_option: } | UNION_SYM opt_equal { - Lex->select_lex.table_list.save_and_clear(&Lex->save_list); + Lex->first_select_lex()->table_list.save_and_clear(&Lex->save_list); } '(' opt_table_list ')' { @@ -6382,8 +6311,8 @@ create_table_option: from the global list. */ LEX *lex=Lex; - lex->create_info.merge_list= lex->select_lex.table_list; - lex->select_lex.table_list= lex->save_list; + lex->create_info.merge_list= lex->first_select_lex()->table_list; + lex->first_select_lex()->table_list= lex->save_list; /* When excluding union list from the global list we assume that elements of the former immediately follow elements which represent @@ -6584,6 +6513,13 @@ create_field_list: } ; +create_field_list_parens: + LEFT_PAREN_ALT field_list ')' + { + Lex->create_last_non_select_table= Lex->last_table(); + } + ; + field_list: field_list_item | field_list ',' field_list_item @@ -6878,6 +6814,8 @@ parse_vcol_expr: Prevent the end user from invoking this command. */ MYSQL_YYABORT_UNLESS(Lex->parse_vcol_expr); + if (Lex->main_select_push()) + MYSQL_YYABORT; } expr { @@ -6885,14 +6823,15 @@ parse_vcol_expr: if (unlikely(!v)) MYSQL_YYABORT; Lex->last_field->vcol_info= v; + Lex->pop_select(); //main select } ; parenthesized_expr: - subselect + remember_tok_start + query_expression { - $$= new (thd->mem_root) Item_singlerow_subselect(thd, $1); - if (unlikely($$ == NULL)) + if (!($$= Lex->create_item_query_expression(thd, $1, $2))) MYSQL_YYABORT; } | expr @@ -7240,10 +7179,12 @@ field_length: opt_field_length: /* empty */ { $$= (char*) 0; /* use default length */ } | field_length { $$= $1; } + ; opt_field_length_default_1: /* empty */ { $$= (char*) "1"; } | field_length { $$= $1; } + ; opt_precision: /* empty */ { $$.set(0, 0); } @@ -7704,12 +7645,14 @@ fulltext_key_opts: opt_USING_key_algorithm: /* Empty*/ { $$= HA_KEY_ALG_UNDEF; } | USING btree_or_rtree { $$= $2; } + ; /* TYPE is a valid identifier, so it's handled differently than USING */ opt_key_algorithm_clause: /* Empty*/ { $$= HA_KEY_ALG_UNDEF; } | USING btree_or_rtree { $$= $2; } | TYPE_SYM btree_or_rtree { $$= $2; } + ; key_using_alg: USING btree_or_rtree @@ -7832,23 +7775,25 @@ alter: Lex->name= null_clex_str; Lex->table_type= TABLE_TYPE_UNKNOWN; Lex->sql_command= SQLCOM_ALTER_TABLE; - Lex->duplicates= DUP_ERROR; - Lex->select_lex.init_order(); + Lex->duplicates= DUP_ERROR; + Lex->first_select_lex()->order_list.empty(); Lex->create_info.init(); Lex->create_info.row_type= ROW_TYPE_NOT_USED; Lex->alter_info.reset(); Lex->no_write_to_binlog= 0; Lex->create_info.storage_media= HA_SM_DEFAULT; + if (Lex->main_select_push()) + MYSQL_YYABORT; DBUG_ASSERT(!Lex->m_sql_cmd); } alter_options TABLE_SYM table_ident opt_lock_wait_timeout { - if (unlikely(!Lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_UPDATING, - TL_READ_NO_INSERT, - MDL_SHARED_UPGRADABLE))) + if (!Lex->first_select_lex()-> + add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING, + TL_READ_NO_INSERT, MDL_SHARED_UPGRADABLE)) MYSQL_YYABORT; - Lex->select_lex.db= (Lex->select_lex.table_list.first)->db; + Lex->first_select_lex()->db= + (Lex->first_select_lex()->table_list.first)->db; Lex->create_last_non_select_table= Lex->last_table(); } alter_commands @@ -7860,11 +7805,14 @@ alter: if (unlikely(Lex->m_sql_cmd == NULL)) MYSQL_YYABORT; } + Lex->pop_select(); //main select } | ALTER DATABASE ident_or_empty { Lex->create_info.default_table_charset= NULL; Lex->create_info.used_fields= 0; + if (Lex->main_select_push()) + MYSQL_YYABORT; } create_database_options { @@ -7874,6 +7822,7 @@ alter: if (lex->name.str == NULL && unlikely(lex->copy_db_to(&lex->name))) MYSQL_YYABORT; + Lex->pop_select(); //main select } | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM { @@ -7889,6 +7838,8 @@ alter: if (unlikely(lex->sphead)) my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE")); + if (Lex->main_select_push()) + MYSQL_YYABORT; lex->sp_chistics.init(); } sp_a_chistics @@ -7897,6 +7848,9 @@ alter: lex->sql_command= SQLCOM_ALTER_PROCEDURE; lex->spname= $3; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } | ALTER FUNCTION_SYM sp_name { @@ -7904,6 +7858,8 @@ alter: if (unlikely(lex->sphead)) my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION")); + if (Lex->main_select_push()) + MYSQL_YYABORT; lex->sp_chistics.init(); } sp_a_chistics @@ -7912,14 +7868,23 @@ alter: lex->sql_command= SQLCOM_ALTER_FUNCTION; lex->spname= $3; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } | ALTER view_algorithm definer_opt opt_view_suid VIEW_SYM table_ident { - if (unlikely(Lex->add_alter_view(thd, $2, $4, $6))) + if (Lex->main_select_push()) + MYSQL_YYABORT; + if (Lex->add_alter_view(thd, $2, $4, $6)) MYSQL_YYABORT; } view_list_opt AS view_select - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } | ALTER definer_opt opt_view_suid VIEW_SYM table_ident /* We have two separate rules for ALTER VIEW rather that @@ -7927,14 +7892,22 @@ alter: with the ALTER EVENT below. */ { - if (unlikely(Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5))) + if (Lex->main_select_push()) + MYSQL_YYABORT; + if (Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5)) MYSQL_YYABORT; } view_list_opt AS view_select - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } | ALTER definer_opt remember_name EVENT_SYM sp_name { - /* + if (Lex->main_select_push()) + MYSQL_YYABORT; + /* It is safe to use Lex->spname because ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO is not allowed. Lex->spname is used in the case of RENAME TO @@ -7966,6 +7939,8 @@ alter: */ Lex->sql_command= SQLCOM_ALTER_EVENT; Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr(); + + Lex->pop_select(); //main select } | ALTER TABLESPACE alter_tablespace_info { @@ -8009,16 +7984,17 @@ alter: lex->create_info.init(); lex->no_write_to_binlog= 0; DBUG_ASSERT(!lex->m_sql_cmd); + if (Lex->main_select_push()) + MYSQL_YYABORT; } table_ident { LEX *lex= Lex; - if (unlikely(!(lex->create_info.seq_create_info= - new (thd->mem_root) sequence_definition())) || - unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_SEQUENCE, - TL_WRITE, - MDL_EXCLUSIVE))) + if (!(lex->create_info.seq_create_info= new (thd->mem_root) + sequence_definition()) || + !lex->first_select_lex()-> + add_table_to_list(thd, $5, NULL, TL_OPTION_SEQUENCE, + TL_WRITE, MDL_EXCLUSIVE)) MYSQL_YYABORT; } sequence_defs @@ -8027,6 +8003,9 @@ alter: Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence($3); if (unlikely(Lex->m_sql_cmd == NULL)) MYSQL_YYABORT; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } ; @@ -8176,16 +8155,17 @@ alter_commands: WITH TABLE_SYM table_ident have_partitioning { LEX *lex= thd->lex; - lex->select_lex.db= $6->db; - if (lex->select_lex.db.str == NULL && - unlikely(lex->copy_db_to(&lex->select_lex.db))) + lex->first_select_lex()->db=$6->db; + if (lex->first_select_lex()->db.str == NULL && + lex->copy_db_to(&lex->first_select_lex()->db)) + { MYSQL_YYABORT; + } lex->name= $6->table; lex->alter_info.partition_flags|= ALTER_PARTITION_EXCHANGE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $6, NULL, - TL_OPTION_UPDATING, - TL_READ_NO_INSERT, - MDL_SHARED_NO_WRITE))) + if (!lex->first_select_lex()-> + add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING, + TL_READ_NO_INSERT, MDL_SHARED_NO_WRITE)) MYSQL_YYABORT; DBUG_ASSERT(!lex->m_sql_cmd); lex->m_sql_cmd= new (thd->mem_root) @@ -8424,9 +8404,9 @@ alter_list_item: | RENAME opt_to table_ident { LEX *lex=Lex; - lex->select_lex.db= $3->db; - if (lex->select_lex.db.str == NULL && - unlikely(lex->copy_db_to(&lex->select_lex.db))) + lex->first_select_lex()->db= $3->db; + if (lex->first_select_lex()->db.str == NULL && + lex->copy_db_to(&lex->first_select_lex()->db)) MYSQL_YYABORT; if (unlikely(check_table_name($3->table.str,$3->table.length, FALSE)) || @@ -8491,6 +8471,7 @@ opt_index_lock_algorithm: | alter_algorithm_option | alter_lock_option alter_algorithm_option | alter_algorithm_option alter_lock_option + ; alter_algorithm_option: ALGORITHM_SYM opt_equal DEFAULT @@ -8549,7 +8530,7 @@ alter_option: Lex->alter_info.requested_lock= Alter_info::ALTER_TABLE_LOCK_NONE; } - + ; opt_restrict: /* empty */ { Lex->drop_mode= DROP_DEFAULT; } @@ -8816,6 +8797,7 @@ persistent_stat_spec: {} | COLUMNS persistent_column_stat_spec INDEXES persistent_index_stat_spec {} + ; persistent_column_stat_spec: ALL {} @@ -9121,8 +9103,8 @@ adm_partition: cache_keys_spec: { - Lex->select_lex.alloc_index_hints(thd); - Select->set_index_hint_type(INDEX_HINT_USE, + Lex->first_select_lex()->alloc_index_hints(thd); + Select->set_index_hint_type(INDEX_HINT_USE, INDEX_HINT_MASK_ALL); } cache_key_list_or_empty @@ -9143,217 +9125,217 @@ opt_ignore_leaves: Select : retrieve data from table */ - select: - opt_with_clause select_init - { - LEX *lex= Lex; - lex->sql_command= SQLCOM_SELECT; - lex->current_select->set_with_clause($1); - } - ; - -select_init: - SELECT_SYM select_options_and_item_list select_init3 - | table_value_constructor - | table_value_constructor union_list - | table_value_constructor union_order_or_limit - | '(' select_paren ')' - | '(' select_paren ')' union_list - | '(' select_paren ')' union_order_or_limit - ; - -union_list_part2: - SELECT_SYM select_options_and_item_list select_init3_union_query_term - | table_value_constructor - | table_value_constructor union_list - | table_value_constructor union_order_or_limit - | '(' select_paren_union_query_term ')' - | '(' select_paren_union_query_term ')' union_list - | '(' select_paren_union_query_term ')' union_order_or_limit - ; - -select_paren: + query_expression_body { - Lex->current_select->set_braces(true); + if (Lex->push_select($1->fake_select_lex ? + $1->fake_select_lex : + $1->first_select())) + MYSQL_YYABORT; } - table_value_constructor + opt_procedure_or_into { - DBUG_ASSERT(Lex->current_select->braces); + Lex->pop_select(); + if ($1->set_lock_to_the_last_select($3)) + MYSQL_YYABORT; + if (Lex->select_finalize($1)) + MYSQL_YYABORT; } - | + | with_clause query_expression_body { - /* - In order to correctly parse UNION's global ORDER BY we need to - set braces before parsing the clause. - */ - Lex->current_select->set_braces(true); + if (Lex->push_select($2->fake_select_lex ? + $2->fake_select_lex : + $2->first_select())) + MYSQL_YYABORT; } - SELECT_SYM select_options_and_item_list select_part3 - opt_select_lock_type + opt_procedure_or_into { - DBUG_ASSERT(Lex->current_select->braces); + Lex->pop_select(); + $2->set_with_clause($1); + $1->attach_to($2->first_select()); + if ($2->set_lock_to_the_last_select($4)) + MYSQL_YYABORT; + if (Lex->select_finalize($2)) + MYSQL_YYABORT; } - | '(' select_paren ')' ; -select_paren_union_query_term: + +select_into: + select_into_query_specification { - /* - In order to correctly parse UNION's global ORDER BY we need to - set braces before parsing the clause. - */ - Lex->current_select->set_braces(true); + if (Lex->push_select($1)) + MYSQL_YYABORT; } - SELECT_SYM select_options_and_item_list select_part3_union_query_term - opt_select_lock_type + opt_order_limit_lock { - DBUG_ASSERT(Lex->current_select->braces); - } - | '(' select_paren_union_query_term ')' + st_select_lex_unit *unit; + if (!(unit= Lex->parsed_body_select($1, $3))) + MYSQL_YYABORT; + if (Lex->select_finalize(unit)) + MYSQL_YYABORT; + } + ; + + +simple_table: + query_specification { $$= $1; } + | table_value_constructor { $$= $1; } ; -select_paren_view: +table_value_constructor: + VALUES + { + if (Lex->parsed_TVC_start()) + MYSQL_YYABORT; + } + values_list + { + if (!($$= Lex->parsed_TVC_end())) + MYSQL_YYABORT; + } + ; + +query_specification_start: + SELECT_SYM { - /* - In order to correctly parse UNION's global ORDER BY we need to - set braces before parsing the clause. - */ - Lex->current_select->set_braces(true); + SELECT_LEX *sel; + LEX *lex= Lex; + if (!(sel= lex->alloc_select(TRUE)) || + lex->push_select(sel)) + MYSQL_YYABORT; + sel->init_select(); + sel->braces= FALSE; } - SELECT_SYM select_options_and_item_list select_part3_view - opt_select_lock_type + select_options { - DBUG_ASSERT(Lex->current_select->braces); + Select->parsing_place= SELECT_LIST; } - | '(' select_paren_view ')' - ; + select_item_list + { + Select->parsing_place= NO_MATTER; + } + ; -/* The equivalent of select_paren for nested queries. */ -select_paren_derived: +query_specification: + query_specification_start + opt_from_clause + opt_where_clause + opt_group_clause + opt_having_clause + opt_window_clause { - Lex->current_select->set_braces(true); + $$= Lex->pop_select(); } - table_value_constructor + ; + +select_into_query_specification: + query_specification_start + into + opt_from_clause + opt_where_clause + opt_group_clause + opt_having_clause + opt_window_clause { - DBUG_ASSERT(Lex->current_select->braces); - $$= Lex->current_select->master_unit()->first_select(); + $$= Lex->pop_select(); } - | + ; + +opt_from_clause: + /* Empty */ + | from_clause + ; + + +query_primary: + simple_table + { $$= $1; } + | query_primary_parens + { $$= $1; } + ; + +query_primary_parens: + '(' query_expression_unit { - Lex->current_select->set_braces(true); + if (Lex->parsed_unit_in_brackets($2)) + MYSQL_YYABORT; } - SELECT_SYM select_part2_derived - opt_table_expression - opt_order_clause - opt_limit_clause - opt_select_lock_type + query_expression_tail ')' { - DBUG_ASSERT(Lex->current_select->braces); - $$= Lex->current_select->master_unit()->first_select(); + $$= Lex->parsed_unit_in_brackets_tail($2, $4); } - | '(' select_paren_derived ')' { $$= $2; } - ; - -select_init3: - opt_table_expression - opt_select_lock_type + | '(' query_primary { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + Lex->push_select($2); } - union_clause - | select_part3_union_not_ready - opt_select_lock_type + query_expression_tail ')' { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_select_in_brackets($2, $4))) + YYABORT; } ; - -select_init3_union_query_term: - opt_table_expression - opt_select_lock_type +query_expression_unit: + query_primary + unit_type_decl + query_primary { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_select_expr_start($1, $3, $2.unit_type, + $2.distinct))) + YYABORT; } - union_clause - | select_part3_union_not_ready_noproc - opt_select_lock_type + | query_expression_unit + unit_type_decl + query_primary { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_select_expr_cont($1, $3, $2.unit_type, + $2.distinct, FALSE))) + YYABORT; } ; - -select_init3_view: - opt_table_expression opt_select_lock_type +query_expression_body: + query_primary { - Lex->current_select->set_braces(false); + Lex->push_select($1); } - | opt_table_expression opt_select_lock_type + query_expression_tail { - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_body_select($1, $3))) + MYSQL_YYABORT; } - union_list_view - | order_or_limit opt_select_lock_type + | query_expression_unit { - Lex->current_select->set_braces(false); + if (Lex->parsed_body_unit($1)) + MYSQL_YYABORT; } - | table_expression order_or_limit opt_select_lock_type + query_expression_tail { - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_body_unit_tail($1, $3))) + MYSQL_YYABORT; } ; -/* - The SELECT parts after select_item_list that cannot be followed by UNION. -*/ - -select_part3: - opt_table_expression - | select_part3_union_not_ready - ; - -select_part3_union_query_term: - opt_table_expression - | select_part3_union_not_ready_noproc - ; - -select_part3_view: - opt_table_expression - | order_or_limit - | table_expression order_or_limit - ; - -select_part3_union_not_ready: - select_part3_union_not_ready_noproc - | table_expression procedure_clause - | table_expression order_or_limit procedure_clause - ; - -select_part3_union_not_ready_noproc: - order_or_limit - | into opt_table_expression opt_order_clause opt_limit_clause - | table_expression into - | table_expression order_or_limit - | table_expression order_or_limit into - ; - -select_options_and_item_list: +query_expression: + opt_with_clause + query_expression_body { - LEX *lex= Lex; - SELECT_LEX *sel= lex->current_select; - if (sel->linkage != UNION_TYPE) - mysql_init_select(lex); - lex->current_select->parsing_place= SELECT_LIST; + if ($1) + { + $2->set_with_clause($1); + $1->attach_to($2->first_select()); + } + $$= $2; } - select_options select_item_list + ; + +subselect: + remember_tok_start + query_expression { - Select->parsing_place= NO_MATTER; + if (!($$= Lex->parsed_subselect($2, $1))) + YYABORT; } ; @@ -9361,18 +9343,6 @@ select_options_and_item_list: /** <table expression>, as in the SQL standard. */ -table_expression: - from_clause - opt_where_clause - opt_group_clause - opt_having_clause - opt_window_clause - ; - -opt_table_expression: - /* Empty */ - | table_expression - ; from_clause: FROM table_reference_list @@ -9421,8 +9391,9 @@ history_point: TIMESTAMP TEXT_STRING { Item *item; - if (!(item= create_temporal_literal(thd, $2.str, $2.length, YYCSCL, - MYSQL_TYPE_DATETIME, true))) + if (!(item= type_handler_datetime.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true))) MYSQL_YYABORT; $$= Vers_history_point(VERS_TIMESTAMP, item); } @@ -9475,59 +9446,68 @@ select_option: query_expression_option | SQL_NO_CACHE_SYM { - /* - Allow this flag only on the first top-level SELECT statement, if - SQL_CACHE wasn't specified, and only once per query. - */ - if (unlikely(Lex->current_select != &Lex->select_lex)) - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE")); - if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)) - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE")); - if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)) + /* + Allow this flag once per query. + */ + if (Select->options & OPTION_NO_QUERY_CACHE) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE")); - - Lex->safe_to_cache_query=0; - Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE; - Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE; + Select->options|= OPTION_NO_QUERY_CACHE; } | SQL_CACHE_SYM { - /* - Allow this flag only on the first top-level SELECT statement, if - SQL_NO_CACHE wasn't specified, and only once per query. - */ - if (unlikely(Lex->current_select != &Lex->select_lex)) - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE")); - if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)) - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE")); - if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)) + /* + Allow this flag once per query. + */ + if (Select->options & OPTION_TO_QUERY_CACHE) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE")); - - Lex->safe_to_cache_query=1; - Lex->select_lex.options|= OPTION_TO_QUERY_CACHE; - Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE; + Select->options|= OPTION_TO_QUERY_CACHE; } ; -opt_select_lock_type: - /* empty */ - | FOR_SYM UPDATE_SYM opt_lock_wait_timeout + +select_lock_type: + FOR_SYM UPDATE_SYM opt_lock_wait_timeout_new { - LEX *lex=Lex; - lex->current_select->lock_type= TL_WRITE; - lex->current_select->set_lock_for_tables(TL_WRITE); - lex->safe_to_cache_query=0; + $$= $3; + $$.defined_lock= TRUE; + $$.update_lock= TRUE; } - | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout + | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout_new { - LEX *lex=Lex; - lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS; - lex->current_select-> - set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS); - lex->safe_to_cache_query=0; + $$= $5; + $$.defined_lock= TRUE; + $$.update_lock= FALSE; } ; +opt_select_lock_type: + /* empty */ + { + $$.empty(); + } + | select_lock_type + { + $$= $1; + } + ; + +opt_lock_wait_timeout_new: + /* empty */ + { + $$.empty(); + } + | WAIT_SYM ulong_num + { + $$.defined_timeout= TRUE; + $$.timeout= $2; + } + | NOWAIT_SYM + { + $$.defined_timeout= TRUE; + $$.timeout= 0; + } + ; + select_item_list: select_item_list ',' select_item | select_item @@ -9606,13 +9586,13 @@ select_alias: opt_default_time_precision: /* empty */ { $$= NOT_FIXED_DEC; } | '(' ')' { $$= NOT_FIXED_DEC; } - | '(' real_ulong_num ')' { $$= $2; }; + | '(' real_ulong_num ')' { $$= $2; } ; opt_time_precision: /* empty */ { $$= 0; } | '(' ')' { $$= 0; } - | '(' real_ulong_num ')' { $$= $2; }; + | '(' real_ulong_num ')' { $$= $2; } ; optional_braces: @@ -10117,6 +10097,7 @@ dyncall_create_element: else $$->len= 0; } + ; dyncall_create_list: dyncall_create_element @@ -10199,7 +10180,21 @@ column_default_non_parenthesized_expr: | param_marker { $$= $1; } | variable | sum_expr + { + if (!Lex->select_stack_top) + { + my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0)); + MYSQL_YYABORT; + } + } | window_func_expr + { + if (!Lex->select_stack_top) + { + my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0)); + MYSQL_YYABORT; + } + } | inverse_distribution_function | ROW_SYM '(' expr ',' expr_list ')' { @@ -10378,7 +10373,7 @@ function_call_keyword_timestamp: } | TIMESTAMP '(' expr ',' expr ')' { - $$= new (thd->mem_root) Item_func_add_time(thd, $3, $5, 1, 0); + $$= new (thd->mem_root) Item_func_timestamp(thd, $3, $5); if (unlikely($$ == NULL)) MYSQL_YYABORT; } @@ -11357,6 +11352,21 @@ window_func: { ((Item_sum *) $1)->mark_as_window_func_sum_expr(); } + | + function_call_generic + { + Item* item = (Item*)$1; + /* Only UDF aggregate here possible */ + if ((item == NULL) || + (item->type() != Item::SUM_FUNC_ITEM) + || (((Item_sum *)item)->sum_func() != Item_sum::UDF_SUM_FUNC)) + { + thd->parse_error(); + MYSQL_YYABORT; + } + + ((Item_sum *) $1)->mark_as_window_func_sum_expr(); + } ; simple_window_func: @@ -11597,7 +11607,7 @@ opt_gconcat_separator: opt_gorder_clause: /* empty */ - | ORDER_SYM BY gorder_list; + | ORDER_SYM BY gorder_list ; gorder_list: @@ -11710,6 +11720,10 @@ cast_type_temporal: DATE_SYM { $$.set(&type_handler_newdate); } | TIME_SYM opt_field_length { $$.set(&type_handler_time2, 0, $2); } | DATETIME opt_field_length { $$.set(&type_handler_datetime2, 0, $2); } + | INTERVAL_SYM DAY_SECOND_SYM field_length + { + $$.set(&type_handler_interval_DDhhmmssff, 0, $3); + } ; opt_expr_list: @@ -11834,10 +11848,15 @@ esc_table_ref: /* Equivalent to <table reference list> in the SQL:2003 standard. */ /* Warning - may return NULL in case of incomplete SELECT */ derived_table_list: - esc_table_ref { $$=$1; } + esc_table_ref + { + $$=$1; + Select->add_joined_table($1); + } | derived_table_list ',' esc_table_ref { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); + Select->add_joined_table($3); } ; @@ -11856,11 +11875,18 @@ join_table: left-associative joins. */ table_ref normal_join table_ref %prec TABLE_REF_PRIORITY - { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; } + { + MYSQL_YYABORT_UNLESS($1 && ($$=$3)); + Select->add_joined_table($1); + Select->add_joined_table($3); + $3->straight=$2; + } | table_ref normal_join table_ref ON { MYSQL_YYABORT_UNLESS($1 && $3); + Select->add_joined_table($1); + Select->add_joined_table($3); /* Change the current name resolution context to a local context. */ if (unlikely(push_new_name_resolution_context(thd, $1, $3))) MYSQL_YYABORT; @@ -11877,6 +11903,8 @@ join_table: USING { MYSQL_YYABORT_UNLESS($1 && $3); + Select->add_joined_table($1); + Select->add_joined_table($3); } '(' using_list ')' { @@ -11887,6 +11915,8 @@ join_table: | table_ref NATURAL inner_join table_factor { MYSQL_YYABORT_UNLESS($1 && ($$=$4)); + Select->add_joined_table($1); + Select->add_joined_table($4); $4->straight=$3; add_join_natural($1,$4,NULL,Select); } @@ -11896,6 +11926,8 @@ join_table: ON { MYSQL_YYABORT_UNLESS($1 && $5); + Select->add_joined_table($1); + Select->add_joined_table($5); /* Change the current name resolution context to a local context. */ if (unlikely(push_new_name_resolution_context(thd, $1, $5))) MYSQL_YYABORT; @@ -11912,6 +11944,8 @@ join_table: | table_ref LEFT opt_outer JOIN_SYM table_factor { MYSQL_YYABORT_UNLESS($1 && $5); + Select->add_joined_table($1); + Select->add_joined_table($5); } USING '(' using_list ')' { @@ -11922,6 +11956,8 @@ join_table: | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor { MYSQL_YYABORT_UNLESS($1 && $6); + Select->add_joined_table($1); + Select->add_joined_table($6); add_join_natural($1,$6,NULL,Select); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; @@ -11932,6 +11968,8 @@ join_table: ON { MYSQL_YYABORT_UNLESS($1 && $5); + Select->add_joined_table($1); + Select->add_joined_table($5); /* Change the current name resolution context to a local context. */ if (unlikely(push_new_name_resolution_context(thd, $1, $5))) MYSQL_YYABORT; @@ -11949,6 +11987,8 @@ join_table: | table_ref RIGHT opt_outer JOIN_SYM table_factor { MYSQL_YYABORT_UNLESS($1 && $5); + Select->add_joined_table($1); + Select->add_joined_table($5); } USING '(' using_list ')' { @@ -11960,6 +12000,8 @@ join_table: | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor { MYSQL_YYABORT_UNLESS($1 && $6); + Select->add_joined_table($1); + Select->add_joined_table($6); add_join_natural($6,$1,NULL,Select); LEX *lex= Lex; if (unlikely(!($$= lex->current_select->convert_right_join()))) @@ -11994,239 +12036,45 @@ use_partition: $$= $3; } ; - -/* - This is a flattening of the rules <table factor> and <table primary> - in the SQL:2003 standard, since we don't have <sample clause> - I.e. - <table factor> ::= <table primary> [ <sample clause> ] -*/ -/* Warning - may return NULL in case of incomplete SELECT */ table_factor: - table_primary_ident - | table_primary_derived + table_primary_ident { $$= $1; } + | table_primary_derived { $$= $1; } + | join_table_parens { $$= $1; } + | table_reference_list_parens { $$= $1; } ; -table_primary_ident: - { - DBUG_ASSERT(Select); - SELECT_LEX *sel= Select; - sel->table_join_options= 0; - } - table_ident opt_use_partition opt_for_system_time_clause opt_table_alias opt_key_definition - { - if (unlikely(!($$= Select->add_table_to_list(thd, $2, $5, - Select->get_table_join_options(), - YYPS->m_lock_type, - YYPS->m_mdl_type, - Select-> - pop_index_hints(), - $3)))) - MYSQL_YYABORT; - TABLE_LIST *tl= $$; - Select->add_joined_table(tl); - if ($4) - tl->vers_conditions= Lex->vers_conditions; - } - ; - - - -/* - Represents a flattening of the following rules from the SQL:2003 - standard. This sub-rule corresponds to the sub-rule - <table primary> ::= ... | <derived table> [ AS ] <correlation name> - - <derived table> ::= <table subquery> - <table subquery> ::= <subquery> - <subquery> ::= <left paren> <query expression> <right paren> - <query expression> ::= [ <with clause> ] <query expression body> - - For the time being we use the non-standard rule - select_derived_union which is a compromise between the standard - and our parser. Possibly this rule could be replaced by our - query_expression_body. -*/ - -table_primary_derived: - '(' get_select_lex select_derived_union ')' opt_for_system_time_clause opt_table_alias +table_reference_list_parens: + '(' table_reference_list_parens ')' { $$= $2; } + | '(' nested_table_reference_list ')' { - /* Use $2 instead of Lex->current_select as derived table will - alter value of Lex->current_select. */ - if (!($3 || $6) && $2->embedding && - !$2->embedding->nested_join->join_list.elements) - { - /* we have a derived table ($3 == NULL) but no alias, - Since we are nested in further parentheses so we - can pass NULL to the outer level parentheses - Permits parsing of "((((select ...))) as xyz)" */ - $$= 0; - } - else if (!$3) - { - /* Handle case of derived table, alias may be NULL if there - are no outer parentheses, add_table_to_list() will throw - error in this case */ - LEX *lex=Lex; - lex->check_automatic_up(UNSPECIFIED_TYPE); - SELECT_LEX *sel= lex->current_select; - SELECT_LEX_UNIT *unit= sel->master_unit(); - lex->current_select= sel= unit->outer_select(); - Table_ident *ti= new (thd->mem_root) Table_ident(unit); - if (unlikely(ti == NULL)) - MYSQL_YYABORT; - if (unlikely(!($$= sel->add_table_to_list(thd, - ti, $6, 0, - TL_READ, - MDL_SHARED_READ)))) - MYSQL_YYABORT; - sel->add_joined_table($$); - lex->pop_context(); - lex->nest_level--; - } - else if (unlikely($6 != NULL)) - { - /* - Tables with or without joins within parentheses cannot - have aliases, and we ruled out derived tables above. - */ - thd->parse_error(); + if (!($$= Select->end_nested_join(thd))) MYSQL_YYABORT; - } - else - { - /* nested join: FROM (t1 JOIN t2 ...), - nest_level is the same as in the outer query */ - $$= $3; - } - /* - Fields in derived table can be used in upper select in - case of merge. We do not add HAVING fields because we do - not merge such derived. We do not add union because - also do not merge them - */ - if ($$ && $$->derived && - !$$->derived->first_select()->next_select()) - $$->select_lex->add_where_field($$->derived->first_select()); - if ($5) - { - MYSQL_YYABORT_UNLESS(!$3); - $$->vers_conditions= Lex->vers_conditions; - } } - /* Represents derived table with WITH clause */ - | '(' get_select_lex subselect_start - with_clause query_expression_body - subselect_end ')' opt_for_system_time_clause opt_table_alias - { - LEX *lex=Lex; - SELECT_LEX *sel= $2; - SELECT_LEX_UNIT *unit= $5->master_unit(); - Table_ident *ti= new (thd->mem_root) Table_ident(unit); - if (unlikely(ti == NULL)) - MYSQL_YYABORT; - $5->set_with_clause($4); - lex->current_select= sel; - if (unlikely(!($$= sel->add_table_to_list(lex->thd, - ti, $9, 0, - TL_READ, - MDL_SHARED_READ)))) - MYSQL_YYABORT; - sel->add_joined_table($$); - if ($8) - $$->vers_conditions= Lex->vers_conditions; - } ; -/* - This rule accepts just about anything. The reason is that we have - empty-producing rules in the beginning of rules, in this case - subselect_start. This forces bison to take a decision which rules to - reduce by long before it has seen any tokens. This approach ties us - to a very limited class of parseable languages, and unfortunately - SQL is not one of them. The chosen 'solution' was this rule, which - produces just about anything, even complete bogus statements, for - instance ( table UNION SELECT 1 ). - Fortunately, we know that the semantic value returned by - select_derived is NULL if it contained a derived table, and a pointer to - the base table's TABLE_LIST if it was a base table. So in the rule - regarding union's, we throw a parse error manually and pretend it - was bison that did it. - - Also worth noting is that this rule concerns query expressions in - the from clause only. Top level select statements and other types of - subqueries have their own union rules. -*/ -select_derived_union: - select_derived - | select_derived union_order_or_limit - { - if (unlikely($1)) - { - thd->parse_error(); - MYSQL_YYABORT; - } - } - | select_derived union_head_non_top +nested_table_reference_list: + table_ref ',' table_ref { - if (unlikely($1)) - { - thd->parse_error(); + if (Select->init_nested_join(thd)) MYSQL_YYABORT; - } - } - union_list_derived_part2 - | derived_simple_table opt_select_lock_type - | derived_simple_table order_or_limit opt_select_lock_type - | derived_simple_table opt_select_lock_type union_list_derived - ; - -union_list_derived_part2: - query_term_union_not_ready { Lex->pop_context(); } - | query_term_union_ready { Lex->pop_context(); } - | query_term_union_ready { Lex->pop_context(); } union_list_derived - ; - -union_list_derived: - union_head_non_top union_list_derived_part2 - ; - - -/* The equivalent of select_init2 for nested queries. */ -select_init2_derived: - select_part2_derived - { - Select->set_braces(0); - } - ; - -/* The equivalent of select_part2 for nested queries. */ -select_part2_derived: - { - LEX *lex= Lex; - SELECT_LEX *sel= lex->current_select; - if (sel->linkage != UNION_TYPE) - mysql_init_select(lex); - lex->current_select->parsing_place= SELECT_LIST; + Select->add_joined_table($1); + Select->add_joined_table($3); + $$= $1->embedding; } - opt_query_expression_options select_item_list + | nested_table_reference_list ',' table_ref { - Select->parsing_place= NO_MATTER; + Select->add_joined_table($3); + $$= $1; } ; -/* handle contents of parentheses in join expression */ -select_derived: - get_select_lex_derived derived_table_list +join_table_parens: + '(' join_table_parens ')' { $$= $2; } + | '(' join_table ')' { LEX *lex= Lex; - /* for normal joins, $2 != NULL and end_nested_join() != NULL, - for derived tables, both must equal NULL */ - - if (unlikely(!($$= $1->end_nested_join(lex->thd)) && $2)) - MYSQL_YYABORT; - if (unlikely(!$2 && $$)) + if (!($$= lex->current_select->nest_last_join(thd))) { thd->parse_error(); MYSQL_YYABORT; @@ -12234,83 +12082,55 @@ select_derived: } ; -derived_simple_table: - derived_query_specification { $$= $1; } - | derived_table_value_constructor { $$= $1; } - ; -/* - Similar to query_specification, but for derived tables. - Example: the inner parenthesized SELECT in this query: - SELECT * FROM (SELECT * FROM t1); -*/ -derived_query_specification: - SELECT_SYM select_derived_init select_derived2 - { - if ($2) - Select->set_braces(1); - $$= NULL; - } - ; -derived_table_value_constructor: - VALUES - { - Lex->tvc_start(); - } - values_list +table_primary_ident: + table_ident opt_use_partition opt_for_system_time_clause + opt_table_alias_clause opt_key_definition { - if (Lex->tvc_finalize_derived()) + SELECT_LEX *sel= Select; + sel->table_join_options= 0; + if (!($$= Select->add_table_to_list(thd, $1, $4, + Select->get_table_join_options(), + YYPS->m_lock_type, + YYPS->m_mdl_type, + Select->pop_index_hints(), + $2))) MYSQL_YYABORT; - $$= NULL; + TABLE_LIST *tl= $$; + if ($3) + tl->vers_conditions= Lex->vers_conditions; } ; -select_derived2: - { - LEX *lex= Lex; - lex->derived_tables|= DERIVED_SUBQUERY; - if (unlikely(!lex->expr_allows_subselect || - lex->sql_command == (int)SQLCOM_PURGE)) - { - thd->parse_error(); - MYSQL_YYABORT; - } - if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE || - unlikely(mysql_new_select(lex, 1, NULL))) - MYSQL_YYABORT; - mysql_init_select(lex); - lex->current_select->linkage= DERIVED_TABLE_TYPE; - lex->current_select->parsing_place= SELECT_LIST; - } - select_options select_item_list - { - Select->parsing_place= NO_MATTER; - } - opt_table_expression - ; +/* + Represents a flattening of the following rules from the SQL:2003 + standard. This sub-rule corresponds to the sub-rule + <table primary> ::= ... | <derived table> [ AS ] <correlation name> -get_select_lex: - /* Empty */ { $$= Select; } - ; + <derived table> ::= <table subquery> + <table subquery> ::= <subquery> + <subquery> ::= <left paren> <query expression> <right paren> + <query expression> ::= [ <with clause> ] <query expression body> -get_select_lex_derived: - get_select_lex + For the time being we use the non-standard rule + select_derived_union which is a compromise between the standard + and our parser. Possibly this rule could be replaced by our + query_expression_body. +*/ + +table_primary_derived: + query_primary_parens opt_for_system_time_clause table_alias_clause { - LEX *lex= Lex; - if (unlikely($1->init_nested_join(lex->thd))) - MYSQL_YYABORT; + if (!($$= Lex->parsed_derived_select($1, $2, $3))) + YYABORT; } - ; - -select_derived_init: + | '(' + query_expression + ')' opt_for_system_time_clause table_alias_clause { - LEX *lex= Lex; - - TABLE_LIST *embedding= lex->current_select->embedding; - $$= embedding && - !embedding->nested_join->join_list.elements; - /* return true if we are deeply nested */ + if (!($$= Lex->parsed_derived_unit($2, $4, $5))) + YYABORT; } ; @@ -12444,9 +12264,14 @@ table_alias: | '=' ; -opt_table_alias: +opt_table_alias_clause: /* empty */ { $$=0; } - | table_alias ident_table_alias + + | table_alias_clause { $$= $1; } + ; + +table_alias_clause: + table_alias ident_table_alias { $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING)); if (unlikely($$ == NULL)) @@ -12542,7 +12367,7 @@ olap_opt: SQL-2003: GROUP BY ... CUBE(col1, col2, col3) */ LEX *lex=Lex; - if (unlikely(lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)) + if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE)) my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH CUBE", "global union parameters")); lex->current_select->olap= CUBE_TYPE; @@ -12559,7 +12384,7 @@ olap_opt: SQL-2003: GROUP BY ... ROLLUP(col1, col2, col3) */ LEX *lex= Lex; - if (unlikely(lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)) + if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE)) my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH ROLLUP", "global union parameters")); lex->current_select->olap= ROLLUP_TYPE; @@ -12611,6 +12436,7 @@ opt_window_ref: if (unlikely(thd->lex->win_ref == NULL)) MYSQL_YYABORT; } + ; opt_window_partition_clause: /* empty */ { } @@ -12619,7 +12445,7 @@ opt_window_partition_clause: opt_window_order_clause: /* empty */ { } - | ORDER_SYM BY order_list + | ORDER_SYM BY order_list { Select->order_list= *($3); } ; opt_window_frame_clause: @@ -12745,70 +12571,35 @@ alter_order_item: opt_order_clause: /* empty */ + { $$= NULL; } | order_clause + { $$= $1; } ; order_clause: ORDER_SYM BY { - LEX *lex=Lex; - SELECT_LEX *sel= lex->current_select; - SELECT_LEX_UNIT *unit= sel-> master_unit(); - if (unlikely(sel->linkage != GLOBAL_OPTIONS_TYPE && - sel->olap != UNSPECIFIED_OLAP_TYPE && - (sel->linkage != UNION_TYPE || sel->braces))) - { - my_error(ER_WRONG_USAGE, MYF(0), - "CUBE/ROLLUP", "ORDER BY"); - MYSQL_YYABORT; - } - if (lex->sql_command != SQLCOM_ALTER_TABLE && - !unit->fake_select_lex) - { - /* - A query of the of the form (SELECT ...) ORDER BY order_list is - executed in the same way as the query - SELECT ... ORDER BY order_list - unless the SELECT construct contains ORDER BY or LIMIT clauses. - Otherwise we create a fake SELECT_LEX if it has not been - created yet. - */ - SELECT_LEX *first_sl= unit->first_select(); - if (unlikely(!unit->is_unit_op() && - (first_sl->order_list.elements || - first_sl->select_limit) && - unit->add_fake_select_lex(thd))) - MYSQL_YYABORT; - } - if (sel->master_unit()->is_unit_op() && !sel->braces) - { - /* - At this point we don't know yet whether this is the last - select in union or not, but we move ORDER BY to - fake_select_lex anyway. If there would be one more select - in union mysql_new_select will correctly throw error. - */ - DBUG_ASSERT(sel->master_unit()->fake_select_lex); - lex->current_select= sel->master_unit()->fake_select_lex; - } + thd->where= "ORDER clause"; } order_list { - + $$= $4; } ; order_list: order_list ',' order_ident order_dir { - if (unlikely(add_order_to_list(thd, $3,(bool) $4))) - MYSQL_YYABORT; - } + $$= $1; + if (add_to_list(thd, *$$, $3,(bool) $4)) + MYSQL_YYABORT; + } | order_ident order_dir { - if (unlikely(add_order_to_list(thd, $1,(bool) $2))) + $$= new (thd->mem_root) SQL_I_List<ORDER>(); + if (add_to_list(thd, *$$, $1, (bool) $2)) MYSQL_YYABORT; - } + } ; order_dir: @@ -12818,63 +12609,62 @@ order_dir: ; opt_limit_clause: - /* empty */ {} - | limit_clause {} + /* empty */ + { $$.empty(); } + | limit_clause + { $$= $1; } ; -limit_clause_init: - LIMIT - { - SELECT_LEX *sel= Select; - if (sel->master_unit()->is_unit_op() && !sel->braces) - { - /* Move LIMIT that belongs to UNION to fake_select_lex */ - Lex->current_select= sel->master_unit()->fake_select_lex; - DBUG_ASSERT(Select); - } - } - ; - limit_clause: - limit_clause_init limit_options + LIMIT limit_options { - SELECT_LEX *sel= Select; - if (!sel->select_limit->basic_const_item() || - sel->select_limit->val_int() > 0) + $$= $2; + if (!$$.select_limit->basic_const_item() || + $$.select_limit->val_int() > 0) Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); } - | limit_clause_init limit_options + | LIMIT limit_options ROWS_SYM EXAMINED_SYM limit_rows_option { + $$= $2; Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); } - | limit_clause_init ROWS_SYM EXAMINED_SYM limit_rows_option + | LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option { + $$.select_limit= 0; + $$.offset_limit= 0; + $$.explicit_limit= 1; Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); } ; +opt_global_limit_clause: + opt_limit_clause + { + Select->explicit_limit= $1.explicit_limit; + Select->select_limit= $1.select_limit; + Select->offset_limit= $1.offset_limit; + } + ; + limit_options: limit_option { - SELECT_LEX *sel= Select; - sel->select_limit= $1; - sel->offset_limit= 0; - sel->explicit_limit= 1; + $$.select_limit= $1; + $$.offset_limit= 0; + $$.explicit_limit= 1; } | limit_option ',' limit_option { - SELECT_LEX *sel= Select; - sel->select_limit= $3; - sel->offset_limit= $1; - sel->explicit_limit= 1; + $$.select_limit= $3; + $$.offset_limit= $1; + $$.explicit_limit= 1; } | limit_option OFFSET_SYM limit_option { - SELECT_LEX *sel= Select; - sel->select_limit= $1; - sel->offset_limit= $3; - sel->explicit_limit= 1; + $$.select_limit= $1; + $$.offset_limit= $3; + $$.explicit_limit= 1; } ; @@ -12919,6 +12709,7 @@ limit_rows_option: LEX *lex=Lex; lex->limit_rows_examined= $1; } + ; delete_limit_clause: /* empty */ @@ -12937,6 +12728,77 @@ delete_limit_clause: | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; } ; +opt_order_limit_lock: + /* empty */ + { $$= NULL; } + | order_or_limit + { + $$= $1; + $$->lock.empty(); + } + | order_or_limit select_lock_type + { + $$= $1; + $$->lock= $2; + } + | select_lock_type + { + $$= new(thd->mem_root) Lex_order_limit_lock; + if (!$$) + YYABORT; + $$->order_list= NULL; + $$->limit.empty(); + $$->lock= $1; + } + ; +query_expression_tail: + opt_order_limit_lock + ; + +opt_procedure_or_into: + /* empty */ + { + $$.empty(); + } + | procedure_clause opt_select_lock_type + { + $$= $2; + } + | into opt_select_lock_type + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WARN_DEPRECATED_SYNTAX, + ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX), + "<select expression> INTO <destination>;", + "'SELECT <select list> INTO <destination>" + " FROM...'"); + $$= $2; + } + ; + + +order_or_limit: + order_clause opt_limit_clause + { + $$= new(thd->mem_root) Lex_order_limit_lock; + if (!$$) + YYABORT; + $$->order_list= $1; + $$->limit= $2; + } + | limit_clause + { + Lex_order_limit_lock *op= $$= new(thd->mem_root) Lex_order_limit_lock; + if (!$$) + YYABORT; + op->order_list= NULL; + op->limit= $1; + $$->order_list= NULL; + $$->limit= $1; + } + ; + + opt_plus: /* empty */ | '+' @@ -12945,6 +12807,7 @@ opt_plus: int_num: opt_plus NUM { int error; $$= (int) my_strtoll10($2.str, (char**) 0, &error); } | '-' NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); } + ; ulong_num: opt_plus NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); } @@ -12968,7 +12831,7 @@ longlong_num: | LONG_NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); } | '-' NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); } | '-' LONG_NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); } - + ; ulonglong_num: opt_plus NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); } @@ -13005,15 +12868,13 @@ bool: ulong_num { $$= $1 != 0; } | TRUE_SYM { $$= 1; } | FALSE_SYM { $$= 0; } - + ; procedure_clause: PROCEDURE_SYM ident /* Procedure name */ { LEX *lex=Lex; - DBUG_ASSERT(&lex->select_lex == lex->current_select); - lex->proc_list.elements=0; lex->proc_list.first=0; lex->proc_list.next= &lex->proc_list.first; @@ -13033,6 +12894,7 @@ procedure_clause: parameters are reduced. */ Lex->expr_allows_subselect= false; + Select->options|= OPTION_PROCEDURE_CLAUSE; } '(' procedure_list ')' { @@ -13116,6 +12978,7 @@ select_outvar: into: INTO into_destination + {} ; into_destination: @@ -13309,10 +13172,11 @@ table_list: table_name: table_ident { - if (unlikely(!Select->add_table_to_list(thd, $1, NULL, - TL_OPTION_UPDATING, - YYPS->m_lock_type, - YYPS->m_mdl_type))) + if (!thd->lex->current_select_or_default()-> + add_table_to_list(thd, $1, NULL, + TL_OPTION_UPDATING, + YYPS->m_lock_type, + YYPS->m_mdl_type)) MYSQL_YYABORT; } ; @@ -13385,17 +13249,24 @@ insert: { LEX *lex= Lex; lex->sql_command= SQLCOM_INSERT; - lex->duplicates= DUP_ERROR; + lex->duplicates= DUP_ERROR; + if (Lex->main_select_push()) + MYSQL_YYABORT; mysql_init_select(lex); + lex->current_select->parsing_place= BEFORE_OPT_LIST; } insert_lock_option opt_ignore insert2 { Select->set_lock_for_tables($3); - Lex->current_select= &Lex->select_lex; + Lex->current_select= Lex->first_select_lex(); } insert_field_spec opt_insert_update - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; replace: @@ -13404,15 +13275,22 @@ replace: LEX *lex=Lex; lex->sql_command = SQLCOM_REPLACE; lex->duplicates= DUP_REPLACE; + if (Lex->main_select_push()) + MYSQL_YYABORT; mysql_init_select(lex); + lex->current_select->parsing_place= BEFORE_OPT_LIST; } replace_lock_option insert2 { Select->set_lock_for_tables($3); - Lex->current_select= &Lex->select_lex; + Lex->current_select= Lex->first_select_lex(); } insert_field_spec - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; insert_lock_option: @@ -13455,15 +13333,14 @@ insert_table: table_name_with_opt_use_partition { LEX *lex=Lex; - lex->field_list.empty(); + //lex->field_list.empty(); lex->many_values.empty(); lex->insert_list=0; }; insert_field_spec: insert_values {} - | '(' ')' insert_values {} - | '(' fields ')' insert_values {} + | insert_field_list insert_values {} | SET { LEX *lex=Lex; @@ -13471,20 +13348,33 @@ insert_field_spec: unlikely(lex->many_values.push_back(lex->insert_list, thd->mem_root))) MYSQL_YYABORT; + lex->current_select->parsing_place= NO_MATTER; } ident_eq_list ; +insert_field_list: + LEFT_PAREN_ALT opt_fields ')' + { + Lex->current_select->parsing_place= AFTER_LIST; + } + ; + +opt_fields: + /* empty */ + | fields + ; + fields: fields ',' insert_ident { Lex->field_list.push_back($3, thd->mem_root); } | insert_ident { Lex->field_list.push_back($1, thd->mem_root); } ; + + insert_values: - VALUES values_list {} - | VALUE_SYM values_list {} - | create_select_query_expression {} + create_select_query_expression {} ; values_list: @@ -13634,6 +13524,8 @@ update: UPDATE_SYM { LEX *lex= Lex; + if (Lex->main_select_push()) + MYSQL_YYABORT; mysql_init_select(lex); lex->sql_command= SQLCOM_UPDATE; lex->duplicates= DUP_ERROR; @@ -13642,13 +13534,14 @@ update: SET update_list { LEX *lex= Lex; - if (lex->select_lex.table_list.elements > 1) + if (lex->first_select_lex()->table_list.elements > 1) lex->sql_command= SQLCOM_UPDATE_MULTI; - else if (unlikely(lex->select_lex.get_table_list()->derived)) + else if (lex->first_select_lex()->get_table_list()->derived) { /* it is single table update and it is update of derived table */ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), - lex->select_lex.get_table_list()->alias.str, "UPDATE"); + lex->first_select_lex()->get_table_list()->alias.str, + "UPDATE"); MYSQL_YYABORT; } /* @@ -13658,7 +13551,14 @@ update: */ Select->set_lock_for_tables($3); } - opt_where_clause opt_order_clause delete_limit_clause {} + opt_where_clause opt_order_clause delete_limit_clause + { + if ($10) + Select->order_list= *($10); + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; update_list: @@ -13705,9 +13605,11 @@ delete: mysql_init_select(lex); YYPS->m_lock_type= TL_WRITE_DEFAULT; YYPS->m_mdl_type= MDL_SHARED_WRITE; + if (Lex->main_select_push()) + MYSQL_YYABORT; lex->ignore= 0; - lex->select_lex.init_order(); + lex->first_select_lex()->order_list.empty(); } delete_part2 ; @@ -13728,6 +13630,7 @@ delete_part2: | HISTORY_SYM delete_single_table opt_delete_system_time { Lex->last_table()->vers_conditions= Lex->vers_conditions; + Lex->pop_select(); //main select } ; @@ -13751,7 +13654,12 @@ single_multi: opt_where_clause opt_order_clause delete_limit_clause - opt_select_expressions {} + opt_select_expressions + { + if ($3) + Select->order_list= *($3); + Lex->pop_select(); //main select + } | table_wild_list { mysql_init_multi_delete(Lex); @@ -13762,6 +13670,9 @@ single_multi: { if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex))) MYSQL_YYABORT; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } | FROM table_alias_ref_list { @@ -13773,6 +13684,9 @@ single_multi: { if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex))) MYSQL_YYABORT; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } ; @@ -13841,9 +13755,9 @@ truncate: LEX* lex= Lex; lex->sql_command= SQLCOM_TRUNCATE; lex->alter_info.reset(); - lex->select_lex.options= 0; - lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED; - lex->select_lex.init_order(); + lex->first_select_lex()->options= 0; + lex->sql_cache= LEX::SQL_CACHE_UNSPECIFIED; + lex->first_select_lex()->order_list.empty(); YYPS->m_lock_type= TL_WRITE; YYPS->m_mdl_type= MDL_EXCLUSIVE; } @@ -13928,6 +13842,8 @@ show: LEX *lex=Lex; lex->wild=0; lex->ident= null_clex_str; + if (Lex->main_select_push()) + MYSQL_YYABORT; mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LIST; lex->create_info.init(); @@ -13935,6 +13851,7 @@ show: show_param { Select->parsing_place= NO_MATTER; + Lex->pop_select(); //main select } ; @@ -13950,40 +13867,40 @@ show_param: { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TABLES; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES)) MYSQL_YYABORT; } | opt_full TRIGGERS_SYM opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TRIGGERS; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS)) MYSQL_YYABORT; } | EVENTS_SYM opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_EVENTS; - lex->select_lex.db= $2; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_EVENTS))) + lex->first_select_lex()->db= $2; + if (prepare_schema_table(thd, lex, 0, SCH_EVENTS)) MYSQL_YYABORT; } | TABLE_SYM STATUS_SYM opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TABLE_STATUS; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TABLES))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_TABLES)) MYSQL_YYABORT; } | OPEN_SYM TABLES opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_OPEN_TABLES; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES)) MYSQL_YYABORT; } | PLUGINS_SYM @@ -14032,12 +13949,13 @@ show_param: LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS; } - opt_limit_clause + opt_global_limit_clause | RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS; - } opt_limit_clause + } + opt_global_limit_clause | keys_or_index from_or_in table_ident opt_db opt_where_clause { LEX *lex= Lex; @@ -14079,13 +13997,13 @@ show_param: LEX_CSTRING var= {STRING_WITH_LEN("error_count")}; (void) create_select_for_variable(thd, &var); } - | WARNINGS opt_limit_clause + | WARNINGS opt_global_limit_clause { Lex->sql_command = SQLCOM_SHOW_WARNS;} - | ERRORS opt_limit_clause + | ERRORS opt_global_limit_clause { Lex->sql_command = SQLCOM_SHOW_ERRORS;} | PROFILES_SYM { Lex->sql_command = SQLCOM_SHOW_PROFILES; } - | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause + | PROFILE_SYM opt_profile_defs opt_profile_args opt_global_limit_clause { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_PROFILE; @@ -14147,7 +14065,7 @@ show_param: { LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL,0))) + if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL,0)) MYSQL_YYABORT; lex->create_info.storage_media= HA_SM_DEFAULT; } @@ -14155,7 +14073,7 @@ show_param: { LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))) + if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0)) MYSQL_YYABORT; lex->table_type= TABLE_TYPE_VIEW; } @@ -14163,7 +14081,7 @@ show_param: { LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))) + if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0)) MYSQL_YYABORT; lex->table_type= TABLE_TYPE_SEQUENCE; } @@ -14380,7 +14298,7 @@ describe: mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LIST; lex->sql_command= SQLCOM_SHOW_FIELDS; - lex->select_lex.db= null_clex_str; + lex->first_select_lex()->db= null_clex_str; lex->verbose= 0; if (unlikely(prepare_schema_table(thd, lex, $2, SCH_COLUMNS))) MYSQL_YYABORT; @@ -14394,12 +14312,13 @@ describe: explainable_command { LEX *lex=Lex; - lex->select_lex.options|= SELECT_DESCRIBE; + lex->first_select_lex()->options|= SELECT_DESCRIBE; } ; explainable_command: select + | select_into | insert | replace | update @@ -14420,6 +14339,8 @@ analyze_stmt_command: opt_extended_describe: EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; } + | EXTENDED_SYM ALL + { Lex->describe|= DESCRIBE_EXTENDED | DESCRIBE_EXTENDED2; } | PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; } | opt_format_json {} ; @@ -14462,8 +14383,7 @@ flush: lex->type= 0; lex->no_write_to_binlog= $2; } - flush_options - {} + flush_options {} ; flush_options: @@ -14480,6 +14400,7 @@ flush_options: opt_table_list opt_flush_lock {} | flush_options_list + {} ; opt_flush_lock: @@ -14565,6 +14486,8 @@ flush_option: { Lex->type|= REFRESH_DES_KEY_FILE; } | RESOURCES { Lex->type|= REFRESH_USER_RESOURCES; } + | SSL_SYM + { Lex->type|= REFRESH_SSL;} | IDENT_sys remember_tok_start { Lex->type|= REFRESH_GENERIC; @@ -14586,6 +14509,21 @@ opt_table_list: | table_list {} ; +backup: + BACKUP_SYM STAGE_SYM ident + { + int type; + if (unlikely(Lex->sphead)) + my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "BACKUP STAGE")); + if ((type= find_type($3.str, &backup_stage_names, + FIND_TYPE_NO_PREFIX)) <= 0) + my_yyabort_error((ER_BACKUP_UNKNOWN_STAGE, MYF(0), $3.str)); + Lex->sql_command= SQLCOM_BACKUP; + Lex->backup_stage= (backup_stages) (type-1); + break; + } + ; + opt_delete_gtid_domain: /* empty */ {} | DELETE_DOMAIN_ID_SYM '=' '(' delete_domain_id_list ')' @@ -14616,6 +14554,7 @@ delete_domain_id: optional_flush_tables_arguments: /* empty */ {$$= 0;} | AND_SYM DISABLE_SYM CHECKPOINT_SYM {$$= REFRESH_CHECKPOINT; } + ; reset: RESET_SYM @@ -14684,6 +14623,8 @@ purge_option: lex->value_list.empty(); lex->value_list.push_front($2, thd->mem_root); lex->sql_command= SQLCOM_PURGE_BEFORE; + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } ; @@ -14708,6 +14649,7 @@ kill_type: /* Empty */ { $$= (int) KILL_HARD_BIT; } | HARD_SYM { $$= (int) KILL_HARD_BIT; } | SOFT_SYM { $$= 0; } + ; kill_option: /* empty */ { $$= (int) KILL_CONNECTION; } @@ -14744,7 +14686,7 @@ use: { LEX *lex=Lex; lex->sql_command=SQLCOM_CHANGE_DB; - lex->select_lex.db= $2; + lex->first_select_lex()->db= $2; } ; @@ -14761,6 +14703,9 @@ load: $2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML"); MYSQL_YYABORT; } + if (lex->main_select_push()) + MYSQL_YYABORT; + mysql_init_select(lex); } load_data_lock opt_local INFILE TEXT_STRING_filesystem { @@ -14791,7 +14736,11 @@ load: opt_xml_rows_identified_by opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec opt_load_data_set_spec - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; data_or_xml: @@ -14989,11 +14938,6 @@ hex_or_bin_String: $1.length); if (unlikely(tmp == NULL)) MYSQL_YYABORT; - /* - it is OK only emulate fix_fields, because we need only - value of constant - */ - tmp->quick_fix_field(); $$= tmp->val_str((String*) 0); } | HEX_STRING @@ -15002,7 +14946,6 @@ hex_or_bin_String: $1.length); if (unlikely(tmp == NULL)) MYSQL_YYABORT; - tmp->quick_fix_field(); $$= tmp->val_str((String*) 0); } | BIN_NUM @@ -15015,7 +14958,6 @@ hex_or_bin_String: it is OK only emulate fix_fields, because we need only value of constant */ - tmp->quick_fix_field(); $$= tmp->val_str((String*) 0); } ; @@ -15164,26 +15106,23 @@ NUM_literal: temporal_literal: DATE_SYM TEXT_STRING { - if (unlikely(!($$= create_temporal_literal(thd, $2.str, $2.length, - YYCSCL, - MYSQL_TYPE_DATE, - true)))) + if (unlikely(!($$= type_handler_newdate.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true)))) MYSQL_YYABORT; } | TIME_SYM TEXT_STRING { - if (unlikely(!($$= create_temporal_literal(thd, $2.str, $2.length, - YYCSCL, - MYSQL_TYPE_TIME, - true)))) + if (unlikely(!($$= type_handler_time2.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true)))) MYSQL_YYABORT; } | TIMESTAMP TEXT_STRING { - if (unlikely(!($$= create_temporal_literal(thd, $2.str, $2.length, - YYCSCL, - MYSQL_TYPE_DATETIME, - true)))) + if (unlikely(!($$= type_handler_datetime.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true)))) MYSQL_YYABORT; } ; @@ -15199,17 +15138,21 @@ opt_with_clause: with_clause: - WITH opt_recursive + WITH opt_recursive { + LEX *lex= Lex; With_clause *with_clause= new With_clause($2, Lex->curr_with_clause); if (unlikely(with_clause == NULL)) MYSQL_YYABORT; - Lex->derived_tables|= DERIVED_WITH; - Lex->curr_with_clause= with_clause; + lex->derived_tables|= DERIVED_WITH; + lex->curr_with_clause= with_clause; with_clause->add_to_list(Lex->with_clauses_list_last_next); + if (lex->current_select && + lex->current_select->parsing_place == BEFORE_OPT_LIST) + lex->current_select->parsing_place= NO_MATTER; } - with_list + with_list { $$= Lex->curr_with_clause; Lex->curr_with_clause= Lex->curr_with_clause->pop(); @@ -15238,15 +15181,14 @@ with_list_element: MYSQL_YYABORT; Lex->with_column_list.empty(); } - AS '(' remember_tok_start subselect remember_tok_end ')' + AS '(' remember_tok_start query_expression remember_tok_end ')' { LEX *lex= thd->lex; const char *query_start= lex->sphead ? lex->sphead->m_tmp_query : thd->query(); char *spec_start= $6 + 1; - With_element *elem= new With_element($1, *$2, $7->master_unit()); - if (unlikely(elem == NULL) || - unlikely(Lex->curr_with_clause->add_with_element(elem))) + With_element *elem= new With_element($1, *$2, $7); + if (elem == NULL || Lex->curr_with_clause->add_with_element(elem)) MYSQL_YYABORT; if (elem->set_unparsed_spec(thd, spec_start, $8, spec_start - query_start)) @@ -16154,6 +16096,7 @@ keyword_sp_var_and_label: | SQL_BUFFER_RESULT | SQL_NO_CACHE_SYM | SQL_THREAD + | STAGE_SYM | STARTS_SYM | STATEMENT_SYM | STATUS_SYM @@ -16222,14 +16165,22 @@ set: SET { LEX *lex=Lex; + if (lex->main_select_push()) + MYSQL_YYABORT; lex->set_stmt_init(); lex->var_list.empty(); sp_create_assignment_lex(thd, yychar == YYEMPTY); } start_option_value_list - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } | SET STATEMENT_SYM { + if (Lex->main_select_push()) + MYSQL_YYABORT; Lex->set_stmt_init(); } set_stmt_option_value_following_option_type_list @@ -16239,6 +16190,9 @@ set: my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT")); lex->stmt_var_list= lex->var_list; lex->var_list.empty(); + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } FOR_SYM verb_clause {} @@ -16585,14 +16539,14 @@ opt_for_user: ; text_or_password: - TEXT_STRING { Lex->definer->pwhash= $1;} + TEXT_STRING { Lex->definer->auth= $1;} | PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->pwtext= $3; } | OLD_PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->pwtext= $3; - Lex->definer->pwhash.str= Item_func_password::alloc(thd, + Lex->definer->auth.str= Item_func_password::alloc(thd, $3.str, $3.length, Item_func_password::OLD); - Lex->definer->pwhash.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; + Lex->definer->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; } ; @@ -16662,7 +16616,7 @@ table_lock_list: ; table_lock: - table_ident opt_table_alias lock_option + table_ident opt_table_alias_clause lock_option { thr_lock_type lock_type= (thr_lock_type) $3; bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE); @@ -16707,27 +16661,37 @@ unlock: */ handler: - HANDLER_SYM table_ident OPEN_SYM opt_table_alias + HANDLER_SYM + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + handler_tail + { + Lex->pop_select(); //main select + } + ; + +handler_tail: + table_ident OPEN_SYM opt_table_alias_clause { LEX *lex= Lex; if (unlikely(lex->sphead)) my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER")); lex->sql_command = SQLCOM_HA_OPEN; - if (unlikely(!lex->current_select->add_table_to_list(thd, $2, $4, - 0))) + if (!lex->current_select->add_table_to_list(thd, $1, $3, 0)) MYSQL_YYABORT; } - | HANDLER_SYM table_ident_nodb CLOSE_SYM + | table_ident_nodb CLOSE_SYM { LEX *lex= Lex; if (unlikely(lex->sphead)) my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER")); lex->sql_command = SQLCOM_HA_CLOSE; - if (unlikely(!lex->current_select->add_table_to_list(thd, $2, 0, - 0))) + if (!lex->current_select->add_table_to_list(thd, $1, 0, 0)) MYSQL_YYABORT; } - | HANDLER_SYM table_ident_nodb READ_SYM + | table_ident_nodb READ_SYM { LEX *lex=Lex; if (unlikely(lex->sphead)) @@ -16741,15 +16705,24 @@ handler: lex->current_select->select_limit= one; lex->current_select->offset_limit= 0; lex->limit_rows_examined= 0; - if (unlikely(!lex->current_select->add_table_to_list(thd, $2, 0, - 0))) + if (!lex->current_select->add_table_to_list(thd, $1, 0, 0)) MYSQL_YYABORT; } - handler_read_or_scan opt_where_clause opt_limit_clause + handler_read_or_scan opt_where_clause opt_global_limit_clause { - Lex->expr_allows_subselect= TRUE; + LEX *lex=Lex; + lex->expr_allows_subselect= TRUE; + if (!lex->current_select->explicit_limit) + { + Item *one= new (thd->mem_root) Item_int(thd, (int32) 1); + if (one == NULL) + MYSQL_YYABORT; + lex->current_select->select_limit= one; + lex->current_select->offset_limit= 0; + lex->limit_rows_examined= 0; + } /* Stored functions are not supported for HANDLER READ. */ - if (unlikely(Lex->uses_stored_routines())) + if (lex->uses_stored_routines()) { my_error(ER_NOT_SUPPORTED_YET, MYF(0), "stored functions in HANDLER ... READ"); @@ -16919,12 +16892,14 @@ grant_command: ; opt_with_admin: - /* nothing */ { Lex->definer = 0; } - | WITH ADMIN_SYM user_or_role { Lex->definer = $3; } + /* nothing */ { Lex->definer = 0; } + | WITH ADMIN_SYM user_or_role { Lex->definer = $3; } + ; opt_with_admin_option: - /* nothing */ { Lex->with_admin_option= false; } - | WITH ADMIN_SYM OPTION { Lex->with_admin_option= true; } + /* nothing */ { Lex->with_admin_option= false; } + | WITH ADMIN_SYM OPTION { Lex->with_admin_option= true; } + ; role_list: grant_role @@ -17160,13 +17135,11 @@ grant_user: { $$= $1; $1->pwtext= $4; - if (unlikely(Lex->sql_command == SQLCOM_REVOKE)) - MYSQL_YYABORT; } | user IDENTIFIED_SYM BY PASSWORD_SYM TEXT_STRING { $$= $1; - $1->pwhash= $5; + $1->auth= $5; } | user IDENTIFIED_SYM via_or_with ident_or_text { @@ -17174,12 +17147,20 @@ grant_user: $1->plugin= $4; $1->auth= empty_clex_str; } - | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as TEXT_STRING_sys + | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as + TEXT_STRING_sys { $$= $1; $1->plugin= $4; $1->auth= $6; } + | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as + PASSWORD_SYM '(' TEXT_STRING ')' + { + $$= $1; + $1->plugin= $4; + $1->pwtext= $8; + } | user_or_role { $$= $1; } ; @@ -17413,212 +17394,27 @@ release: */ unit_type_decl: - UNION_SYM - { $$= UNION_TYPE; } + UNION_SYM union_option + { $$.unit_type= UNION_TYPE; $$.distinct= $2; } | INTERSECT_SYM - { $$= INTERSECT_TYPE; } + { $$.unit_type= INTERSECT_TYPE; $$.distinct= 1; } | EXCEPT_SYM - { $$= EXCEPT_TYPE; } - - -union_clause: - /* empty */ {} - | union_list - ; - -union_list: - unit_type_decl union_option - { - if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, TRUE))) - MYSQL_YYABORT; - } - union_list_part2 - { - /* - Remove from the name resolution context stack the context of the - last select in the union. - */ - Lex->pop_context(); - } - ; - -union_list_view: - unit_type_decl union_option - { - if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, TRUE))) - MYSQL_YYABORT; - } - query_expression_body_view - { - Lex->pop_context(); - } - ; - -union_order_or_limit: - { - LEX *lex= thd->lex; - DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE); - SELECT_LEX *sel= lex->current_select; - SELECT_LEX_UNIT *unit= sel->master_unit(); - SELECT_LEX *fake= unit->fake_select_lex; - if (fake) - { - fake->no_table_names_allowed= 1; - lex->current_select= fake; - } - thd->where= "global ORDER clause"; - } - order_or_limit - { - thd->lex->current_select->no_table_names_allowed= 0; - thd->where= ""; - } - ; - -order_or_limit: - order_clause opt_limit_clause - | limit_clause + { $$.unit_type= EXCEPT_TYPE; $$.distinct= 1; } ; /* Start a UNION, for non-top level query expressions. */ -union_head_non_top: - unit_type_decl union_option - { - if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, FALSE))) - MYSQL_YYABORT; - } - ; - union_option: /* empty */ { $$=1; } | DISTINCT { $$=1; } | ALL { $$=0; } ; -simple_table: - query_specification { $$= $1; } - | table_value_constructor { $$= $1; } - ; - -table_value_constructor: - VALUES - { - Lex->tvc_start(); - } - values_list - { - $$= Lex->current_select; - if (Lex->tvc_finalize()) - MYSQL_YYABORT; - } - ; - -/* - Corresponds to the SQL Standard - <query specification> ::= - SELECT [ <set quantifier> ] <select list> <table expression> - - Notes: - - We allow more options in addition to <set quantifier> - - <table expression> is optional in MariaDB -*/ -query_specification: - SELECT_SYM select_init2_derived opt_table_expression - { - $$= Lex->current_select->master_unit()->first_select(); - } - ; - -query_term_union_not_ready: - simple_table order_or_limit opt_select_lock_type { $$= $1; } - | '(' select_paren_derived ')' union_order_or_limit { $$= $2; } - ; - -query_term_union_ready: - simple_table opt_select_lock_type { $$= $1; } - | '(' select_paren_derived ')' { $$= $2; } - ; - -query_expression_body: - query_term_union_not_ready { $$= $1; } - | query_term_union_ready { $$= $1; } - | query_term_union_ready union_list_derived { $$= $1; } - ; - -/* Corresponds to <query expression> in the SQL:2003 standard. */ -subselect: - subselect_start opt_with_clause query_expression_body subselect_end - { - $3->set_with_clause($2); - $$= $3; - } - ; - -subselect_start: - { - LEX *lex=Lex; - if (unlikely(!lex->expr_allows_subselect || - lex->sql_command == (int)SQLCOM_PURGE)) - { - thd->parse_error(); - MYSQL_YYABORT; - } - /* - we are making a "derived table" for the parenthesis - as we need to have a lex level to fit the union - after the parenthesis, e.g. - (SELECT .. ) UNION ... becomes - SELECT * FROM ((SELECT ...) UNION ...) - */ - if (unlikely(mysql_new_select(Lex, 1, NULL))) - MYSQL_YYABORT; - } - ; - -subselect_end: - { - LEX *lex=Lex; - - lex->check_automatic_up(UNSPECIFIED_TYPE); - lex->pop_context(); - SELECT_LEX *child= lex->current_select; - lex->current_select = lex->current_select->return_after_parsing(); - lex->nest_level--; - lex->current_select->n_child_sum_items += child->n_sum_items; - /* - A subselect can add fields to an outer select. Reserve space for - them. - */ - lex->current_select->select_n_where_fields+= - child->select_n_where_fields; - - /* - Aggregate functions in having clause may add fields to an outer - select. Count them also. - */ - lex->current_select->select_n_having_items+= - child->select_n_having_items; - } - ; - -opt_query_expression_options: - /* empty */ - | query_expression_option_list - ; - -query_expression_option_list: - query_expression_option_list query_expression_option - | query_expression_option - ; - query_expression_option: STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; } | HIGH_PRIORITY { - if (unlikely(Lex->check_simple_select(&$1))) - MYSQL_YYABORT; YYPS->m_lock_type= TL_READ_HIGH_PRIORITY; YYPS->m_mdl_type= MDL_SHARED_READ; Select->options|= SELECT_HIGH_PRIORITY; @@ -17626,18 +17422,8 @@ query_expression_option: | DISTINCT { Select->options|= SELECT_DISTINCT; } | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } - | SQL_BUFFER_RESULT - { - if (unlikely(Lex->check_simple_select(&$1))) - MYSQL_YYABORT; - Select->options|= OPTION_BUFFER_RESULT; - } - | SQL_CALC_FOUND_ROWS - { - if (unlikely(Lex->check_simple_select(&$1))) - MYSQL_YYABORT; - Select->options|= OPTION_FOUND_ROWS; - } + | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; } + | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; } | ALL { Select->options|= SELECT_ALL; } ; @@ -17725,35 +17511,14 @@ view_select: lex->parsing_options.allows_variable= FALSE; lex->create_view->select.str= (char *) YYLIP->get_cpp_ptr(); } - opt_with_clause query_expression_body_view view_check_option + query_expression + view_check_option { - LEX *lex= Lex; - size_t len= YYLIP->get_cpp_ptr() - lex->create_view->select.str; - void *create_view_select= thd->memdup(lex->create_view->select.str, len); - lex->create_view->select.length= len; - lex->create_view->select.str= (char *) create_view_select; - trim_whitespace(thd->charset(), - &lex->create_view->select); - lex->create_view->check= $4; - lex->parsing_options.allows_variable= TRUE; - lex->current_select->set_with_clause($2); + if (Lex->parsed_create_view($2, $3)) + MYSQL_YYABORT; } ; -/* - SQL Standard <query expression body> for VIEWs. - Does not include INTO and PROCEDURE clauses. -*/ -query_expression_body_view: - SELECT_SYM select_options_and_item_list select_init3_view - | table_value_constructor - | table_value_constructor union_order_or_limit - | table_value_constructor union_list_view - | '(' select_paren_view ')' - | '(' select_paren_view ')' union_order_or_limit - | '(' select_paren_view ')' union_list_view - ; - view_check_option: /* empty */ { $$= VIEW_CHECK_NONE; } | WITH CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; } @@ -17852,11 +17617,10 @@ trigger_tail: sp_proc_stmt alternatives are not saving/restoring LEX, so lex->query_tables can be wiped out. */ - if (unlikely(!lex->select_lex. - add_table_to_list(thd, $10, (LEX_CSTRING*) 0, - TL_OPTION_UPDATING, - TL_READ_NO_INSERT, - MDL_SHARED_NO_WRITE))) + if (!lex->first_select_lex()-> + add_table_to_list(thd, $10, (LEX_CSTRING*) 0, + TL_OPTION_UPDATING, TL_READ_NO_INSERT, + MDL_SHARED_NO_WRITE)) MYSQL_YYABORT; } ; @@ -18049,12 +17813,15 @@ opt_migrate: ; install: - INSTALL_SYM PLUGIN_SYM ident SONAME_SYM TEXT_STRING_sys + INSTALL_SYM PLUGIN_SYM opt_if_not_exists ident SONAME_SYM TEXT_STRING_sys { LEX *lex= Lex; + lex->create_info.init(); + if (lex->add_create_options_with_check($3)) + MYSQL_YYABORT; lex->sql_command= SQLCOM_INSTALL_PLUGIN; - lex->comment= $3; - lex->ident= $5; + lex->comment= $4; + lex->ident= $6; } | INSTALL_SYM SONAME_SYM TEXT_STRING_sys { @@ -18066,27 +17833,34 @@ install: ; uninstall: - UNINSTALL_SYM PLUGIN_SYM ident + UNINSTALL_SYM PLUGIN_SYM opt_if_exists ident { LEX *lex= Lex; + lex->check_opt.init(); + if (lex->add_create_options_with_check($3)) + MYSQL_YYABORT; lex->sql_command= SQLCOM_UNINSTALL_PLUGIN; - lex->comment= $3; + lex->comment= $4; } - | UNINSTALL_SYM SONAME_SYM TEXT_STRING_sys + | UNINSTALL_SYM SONAME_SYM opt_if_exists TEXT_STRING_sys { LEX *lex= Lex; + lex->check_opt.init(); + if (lex->add_create_options_with_check($3)) + MYSQL_YYABORT; lex->sql_command= SQLCOM_UNINSTALL_PLUGIN; lex->comment= null_clex_str; - lex->ident= $3; + lex->ident= $4; } ; /* Avoid compiler warning from sql_yacc.cc where yyerrlab1 is not used */ keep_gcc_happy: - IMPOSSIBLE_ACTION - { - YYERROR; - } + IMPOSSIBLE_ACTION + { + YYERROR; + } + ; /** @} (end of group Parser) diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index b8b2a862469..5708962aabe 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -184,6 +184,20 @@ void ORAerror(THD *thd, const char *s) Lex_for_loop_bounds_st for_loop_bounds; Lex_trim_st trim; vers_history_point_t vers_history_point; + struct + { + enum sub_select_type unit_type; + bool distinct; + } unit_operation; + struct + { + SELECT_LEX *first; + SELECT_LEX *prev_last; + } select_list; + SQL_I_List<ORDER> *select_order; + Lex_select_lock select_lock; + Lex_select_limit select_limit; + Lex_order_limit_lock *order_limit_lock; /* pointers */ Create_field *create_field; @@ -229,6 +243,7 @@ void ORAerror(THD *thd, const char *s) handlerton *db_type; st_select_lex *select_lex; + st_select_lex_unit *select_lex_unit; struct p_elem_val *p_elem_value; class Window_frame *window_frame; class Window_frame_bound *window_frame_bound; @@ -238,7 +253,6 @@ void ORAerror(THD *thd, const char *s) /* enums */ enum enum_sp_suid_behaviour sp_suid; enum enum_view_suid view_suid; - enum sub_select_type unit_type; enum Condition_information_item::Name cond_info_item_name; enum enum_diag_condition_item_name diag_condition_item_name; enum Diagnostics_information::Which_area diag_area; @@ -278,10 +292,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 53 shift/reduce conflicts. + Currently there are 49 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 53 +%expect 49 /* Comments for TOKENS. @@ -438,6 +452,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token LEADING /* SQL-2003-R */ %token LEAVE_SYM %token LEFT /* SQL-2003-R */ +%token LEFT_PAREN_ALT /* INTERNAL */ +%token LEFT_PAREN_WITH /* INTERNAL */ +%token LEFT_PAREN_LIKE /* INTERNAL */ %token LEX_HOSTNAME %token LIKE /* SQL-2003-R */ %token LIMIT @@ -983,6 +1000,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token <kwd> SQL_CALC_FOUND_ROWS %token <kwd> SQL_NO_CACHE_SYM %token <kwd> SQL_THREAD +%token <kwd> STAGE_SYM %token <kwd> STARTS_SYM %token <kwd> START_SYM /* SQL-2003-R */ %token <kwd> STATEMENT_SYM @@ -1214,7 +1232,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); NCHAR_STRING %type <lex_str_ptr> - opt_table_alias + opt_table_alias_clause + table_alias_clause %type <ident_cli> IDENT @@ -1283,7 +1302,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); opt_temporary all_or_any opt_distinct opt_glimit_clause opt_ignore_leaves fulltext_options union_option opt_not - select_derived_init transaction_access_mode_types + transaction_access_mode_types opt_natural_language_mode opt_query_expansion opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt @@ -1406,11 +1425,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); join_table_list join_table table_factor table_ref esc_table_ref table_primary_ident table_primary_derived - select_derived derived_table_list - select_derived_union - derived_simple_table - derived_query_specification - derived_table_value_constructor + derived_table_list table_reference_list_parens + nested_table_reference_list join_table_parens %type <date_time_type> date_time_type; %type <interval> interval @@ -1446,14 +1462,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); UNDERSCORE_CHARSET %type <select_lex> subselect - get_select_lex get_select_lex_derived - simple_table query_specification - query_term_union_not_ready - query_term_union_ready - query_expression_body - select_paren_derived table_value_constructor + simple_table + query_primary + query_primary_parens + select_into_query_specification + + +%type <select_lex_unit> + query_specification_start + query_expression_body + query_expression + query_expression_unit %type <boolfunc2creator> comp_op @@ -1465,11 +1486,28 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type <virtual_column> opt_check_constraint check_constraint virtual_column_func column_default_expr -%type <unit_type> unit_type_decl + +%type <unit_operation> unit_type_decl + +%type <select_lock> + opt_procedure_or_into + opt_select_lock_type + select_lock_type + opt_lock_wait_timeout_new + +%type <select_limit> opt_limit_clause limit_clause limit_options + +%type <order_limit_lock> + query_expression_tail + order_or_limit + opt_order_limit_lock + +%type <select_order> opt_order_clause order_clause order_list %type <NONE> - analyze_stmt_command - query verb_clause create change select do drop insert replace insert2 + analyze_stmt_command backup + query verb_clause create change select select_into + do drop insert replace insert2 insert_values update delete truncate rename compound_statement show describe load alter optimize keycache preload flush reset purge begin_stmt_mariadb commit rollback savepoint release @@ -1485,7 +1523,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); assign_to_keycache_parts preload_list preload_list_or_parts preload_keys preload_keys_parts select_item_list select_item values_list no_braces - opt_limit_clause delete_limit_clause fields opt_values values + delete_limit_clause fields opt_values values no_braces_with_names opt_values_with_names values_with_names procedure_list procedure_list2 procedure_item field_def handler opt_generated_always @@ -1506,9 +1544,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan single_multi table_wild_list table_wild_one opt_wild - union_clause union_list - subselect_start opt_and charset - subselect_end select_var_list select_var_list_init help + opt_and charset + select_var_list select_var_list_init help opt_extended_describe shutdown opt_format_json prepare prepare_src execute deallocate @@ -1660,8 +1697,8 @@ rule: <-- starts at col 1 query: END_OF_INPUT { - if (likely(!thd->bootstrap) && - unlikely(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT))) + if (!thd->bootstrap && + (!(thd->lex->lex_options & OPTION_LEX_FOUND_COMMENT))) my_yyabort_error((ER_EMPTY_QUERY, MYF(0))); thd->lex->sql_command= SQLCOM_EMPTY_QUERY; @@ -1715,6 +1752,7 @@ statement: alter | analyze | analyze_stmt_command + | backup | binlog_base64_event | call | change @@ -1757,6 +1795,7 @@ statement: | rollback | savepoint | select + | select_into | set | set_assign | signal_stmt @@ -2111,17 +2150,22 @@ connection_name: /* create a table */ create: - create_or_replace opt_temporary TABLE_SYM opt_if_not_exists table_ident + create_or_replace opt_temporary TABLE_SYM opt_if_not_exists { LEX *lex= thd->lex; lex->create_info.init(); - if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, - $1 | $4))) + if (lex->main_select_push()) + MYSQL_YYABORT; + lex->current_select->parsing_place= BEFORE_OPT_LIST; + if (lex->set_command_with_check(SQLCOM_CREATE_TABLE, $2, $1 | $4)) MYSQL_YYABORT; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_UPDATING, - TL_WRITE, - MDL_EXCLUSIVE))) + } + table_ident + { + LEX *lex= thd->lex; + if (!lex->first_select_lex()-> + add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING, + TL_WRITE, MDL_SHARED_UPGRADABLE)) MYSQL_YYABORT; lex->alter_info.reset(); /* @@ -2136,7 +2180,6 @@ create: create_body { LEX *lex= thd->lex; - lex->current_select= &lex->select_lex; if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) && !lex->create_info.db_type) { @@ -2145,22 +2188,24 @@ create: ER_WARN_USING_OTHER_HANDLER, ER_THD(thd, ER_WARN_USING_OTHER_HANDLER), hton_name(lex->create_info.db_type)->str, - $5->table.str); + $6->table.str); } create_table_set_open_action_and_adjust_tables(lex); + Lex->pop_select(); //main select } | create_or_replace opt_temporary SEQUENCE_SYM opt_if_not_exists table_ident { LEX *lex= thd->lex; + if (Lex->main_select_push()) + MYSQL_YYABORT; lex->create_info.init(); if (unlikely(lex->set_command_with_check(SQLCOM_CREATE_SEQUENCE, $2, $1 | $4))) MYSQL_YYABORT; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_UPDATING, - TL_WRITE, - MDL_EXCLUSIVE))) + if (!lex->first_select_lex()-> + add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING, + TL_WRITE, MDL_EXCLUSIVE)) MYSQL_YYABORT; /* @@ -2183,8 +2228,9 @@ create: if (unlikely(lex->create_info.seq_create_info->check_and_adjust(1))) { my_error(ER_SEQUENCE_INVALID_DATA, MYF(0), - lex->select_lex.table_list.first->db.str, - lex->select_lex.table_list.first->table_name.str); + lex->first_select_lex()->table_list.first->db.str, + lex->first_select_lex()->table_list.first-> + table_name.str); MYSQL_YYABORT; } @@ -2197,10 +2243,8 @@ create: Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE; Lex->create_info.sequence= 1; - lex->current_select= &lex->select_lex; - if (unlikely((lex->create_info.used_fields & - HA_CREATE_USED_ENGINE) && - !lex->create_info.db_type)) + if ((lex->create_info.used_fields & HA_CREATE_USED_ENGINE) && + !lex->create_info.db_type) { lex->create_info.use_default_db_type(thd); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, @@ -2210,44 +2254,69 @@ create: $5->table.str); } create_table_set_open_action_and_adjust_tables(lex); + Lex->pop_select(); //main select } - | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident + | create_or_replace opt_unique INDEX_SYM opt_if_not_exists + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + ident opt_key_algorithm_clause ON table_ident { - if (unlikely(Lex->add_create_index_prepare($8))) + if (Lex->add_create_index_prepare($9)) MYSQL_YYABORT; - if (unlikely(Lex->add_create_index($2, &$5, $6, $1 | $4))) + if (Lex->add_create_index($2, &$6, $7, $1 | $4)) MYSQL_YYABORT; } '(' key_list ')' opt_lock_wait_timeout normal_key_options - opt_index_lock_algorithm { } - | create_or_replace fulltext INDEX_SYM opt_if_not_exists ident + opt_index_lock_algorithm + { + Lex->pop_select(); //main select + } + | create_or_replace fulltext INDEX_SYM + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + opt_if_not_exists ident ON table_ident { - if (unlikely(Lex->add_create_index_prepare($7))) + if (Lex->add_create_index_prepare($8)) MYSQL_YYABORT; - if (unlikely(Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, - $1 | $4))) + if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5)) MYSQL_YYABORT; } '(' key_list ')' opt_lock_wait_timeout fulltext_key_options - opt_index_lock_algorithm { } - | create_or_replace spatial INDEX_SYM opt_if_not_exists ident + opt_index_lock_algorithm + { + Lex->pop_select(); //main select + } + | create_or_replace spatial INDEX_SYM + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + opt_if_not_exists ident ON table_ident { - if (unlikely(Lex->add_create_index_prepare($7))) + if (Lex->add_create_index_prepare($8)) MYSQL_YYABORT; - if (unlikely(Lex->add_create_index($2, &$5, HA_KEY_ALG_UNDEF, - $1 | $4))) + if (Lex->add_create_index($2, &$6, HA_KEY_ALG_UNDEF, $1 | $5)) MYSQL_YYABORT; } '(' key_list ')' opt_lock_wait_timeout spatial_key_options - opt_index_lock_algorithm { } + opt_index_lock_algorithm + { + Lex->pop_select(); //main select + } | create_or_replace DATABASE opt_if_not_exists ident { Lex->create_info.default_table_charset= NULL; Lex->create_info.used_fields= 0; + if (Lex->main_select_push()) + MYSQL_YYABORT; } opt_create_database_options { @@ -2256,54 +2325,96 @@ create: $1 | $3))) MYSQL_YYABORT; lex->name= $4; + Lex->pop_select(); //main select } | create_or_replace definer_opt opt_view_suid VIEW_SYM opt_if_not_exists table_ident { - if (unlikely(Lex->add_create_view(thd, $1 | $5, - DTYPE_ALGORITHM_UNDEFINED, $3, - $6))) + if (Lex->main_select_push()) + MYSQL_YYABORT; + if (Lex->add_create_view(thd, $1 | $5, + DTYPE_ALGORITHM_UNDEFINED, $3, $6)) MYSQL_YYABORT; } view_list_opt AS view_select - { } + { + Lex->pop_select(); //main select + } | create_or_replace view_algorithm definer_opt opt_view_suid VIEW_SYM opt_if_not_exists table_ident { - if (unlikely(Lex->add_create_view(thd, $1 | $6, $2, $4, $7))) + if (Lex->main_select_push()) + MYSQL_YYABORT; + if (Lex->add_create_view(thd, $1 | $6, $2, $4, $7)) MYSQL_YYABORT; } view_list_opt AS view_select - { } + { + Lex->pop_select(); //main select + } | create_or_replace definer_opt TRIGGER_SYM - { Lex->create_info.set($1); } + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + Lex->create_info.set($1); + } trigger_tail - { } + { + Lex->pop_select(); //main select + } | create_or_replace definer_opt PROCEDURE_SYM - { Lex->create_info.set($1); } + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + Lex->create_info.set($1); + } sp_tail_standalone - { } + { + Lex->pop_select(); //main select + } | create_or_replace definer_opt EVENT_SYM - { Lex->create_info.set($1); } + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + Lex->create_info.set($1); + } event_tail - { } + { + Lex->pop_select(); //main select + } | create_or_replace definer FUNCTION_SYM - { Lex->create_info.set($1); } + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + Lex->create_info.set($1); + } sf_tail_standalone - { } + { + Lex->pop_select(); //main select + } | create_or_replace no_definer FUNCTION_SYM - { Lex->create_info.set($1); } + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + Lex->create_info.set($1); + } create_function_tail - { } + { + Lex->pop_select(); //main select + } | create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM { + if (Lex->main_select_push()) + MYSQL_YYABORT; Lex->create_info.set($1); Lex->udf.type= UDFTYPE_AGGREGATE; } udf_tail - { } - | create_or_replace USER_SYM opt_if_not_exists clear_privileges grant_list - opt_require_clause opt_resource_options + { + Lex->pop_select(); //main select + } + | create_or_replace USER_SYM opt_if_not_exists clear_privileges + grant_list opt_require_clause opt_resource_options { if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3))) @@ -2924,7 +3035,7 @@ clear_privileges: lex->columns.empty(); lex->grant= lex->grant_tot_col= 0; lex->all_privileges= 0; - lex->select_lex.db= null_clex_str; + lex->first_select_lex()->db= null_clex_str; lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; bzero((char *)&(lex->mqh),sizeof(lex->mqh)); @@ -3562,7 +3673,7 @@ raise_stmt_oracle: signal_stmt: SIGNAL_SYM signal_value opt_set_signal_information { - if (unlikely(Lex->add_signal_statement(thd, $2))) + if (Lex->add_signal_statement(thd, $2)) MYSQL_YYABORT; } ; @@ -3748,6 +3859,7 @@ statement_information_item: if (unlikely($$ == NULL)) MYSQL_YYABORT; } + ; simple_target_specification: ident_cli @@ -3804,6 +3916,7 @@ condition_information_item: if (unlikely($$ == NULL)) MYSQL_YYABORT; } + ; condition_information_item_name: CLASS_ORIGIN_SYM @@ -3946,44 +4059,8 @@ sp_proc_stmt_statement: } sp_statement { - LEX *lex= thd->lex; - Lex_input_stream *lip= YYLIP; - sp_head *sp= lex->sphead; - - sp->m_flags|= sp_get_flags_for_command(lex); - /* "USE db" doesn't work in a procedure */ - if (unlikely(lex->sql_command == SQLCOM_CHANGE_DB)) - my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "USE")); - /* - Don't add an instruction for SET statements, since all - instructions for them were already added during processing - of "set" rule. - */ - DBUG_ASSERT(lex->sql_command != SQLCOM_SET_OPTION || - lex->var_list.is_empty()); - if (lex->sql_command != SQLCOM_SET_OPTION) - { - sp_instr_stmt *i=new (thd->mem_root) - sp_instr_stmt(sp->instructions(), lex->spcont, lex); - if (unlikely(i == NULL)) - MYSQL_YYABORT; - - /* - Extract the query statement from the tokenizer. The - end is either lex->ptr, if there was no lookahead, - lex->tok_end otherwise. - */ - if (yychar == YYEMPTY) - i->m_query.length= lip->get_ptr() - sp->m_tmp_query; - else - i->m_query.length= lip->get_tok_start() - sp->m_tmp_query;; - if (unlikely(!(i->m_query.str= strmake_root(thd->mem_root, - sp->m_tmp_query, - i->m_query.length))) || - unlikely(sp->add_instr(i))) - MYSQL_YYABORT; - } - if (unlikely(sp->restore_lex(thd))) + if (Lex->sp_proc_stmt_statement_finalize(thd, yychar == YYEMPTY) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -4017,7 +4094,9 @@ sp_proc_stmt_return: ; reset_lex_expr: - { Lex->sphead->reset_lex(thd); } expr { $$= $2; } + { Lex->sphead->reset_lex(thd); } + expr + { $$= $2; } ; sp_proc_stmt_exit_oracle: @@ -4033,14 +4112,14 @@ sp_proc_stmt_exit_oracle: } | EXIT_ORACLE_SYM WHEN_SYM reset_lex_expr { - if (unlikely(Lex->sp_exit_statement(thd, $3)) || - unlikely(Lex->sphead->restore_lex(thd))) + if (Lex->sp_exit_statement(thd, $3) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } | EXIT_ORACLE_SYM label_ident WHEN_SYM reset_lex_expr { - if (unlikely(Lex->sp_exit_statement(thd, &$2, $4)) || - unlikely(Lex->sphead->restore_lex(thd))) + if (Lex->sp_exit_statement(thd, &$2, $4) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -4058,14 +4137,14 @@ sp_proc_stmt_continue_oracle: } | CONTINUE_ORACLE_SYM WHEN_SYM reset_lex_expr { - if (unlikely(Lex->sp_continue_statement(thd, $3)) || - unlikely(Lex->sphead->restore_lex(thd))) + if (Lex->sp_continue_statement(thd, $3) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } | CONTINUE_ORACLE_SYM label_ident WHEN_SYM reset_lex_expr { - if (unlikely(Lex->sp_continue_statement(thd, &$2, $4)) || - unlikely(Lex->sphead->restore_lex(thd))) + if (Lex->sp_continue_statement(thd, &$2, $4) || + Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -4124,7 +4203,7 @@ assignment_source_expr: $$->sp_lex_in_use= true; $$->set_item_and_free_list($3, thd->free_list); thd->free_list= NULL; - if (unlikely($$->sphead->restore_lex(thd))) + if ($$->sphead->restore_lex(thd)) MYSQL_YYABORT; } ; @@ -4133,6 +4212,7 @@ for_loop_bound_expr: assignment_source_lex { Lex->sphead->reset_lex(thd, $1); + Lex->current_select->parsing_place= FOR_LOOP_BOUND; } expr { @@ -4142,6 +4222,7 @@ for_loop_bound_expr: $$->set_item_and_free_list($3, NULL); if (unlikely($$->sphead->restore_lex(thd))) MYSQL_YYABORT; + Lex->current_select->parsing_place= NO_MATTER; } ; @@ -4363,7 +4444,8 @@ case_stmt_body: { if (unlikely(Lex->case_stmt_action_expr($2))) MYSQL_YYABORT; - if (unlikely(Lex->sphead->restore_lex(thd))) + + if (Lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } simple_when_clause_list @@ -4652,7 +4734,7 @@ while_body: LEX *lex= Lex; if (unlikely(lex->sp_while_loop_expression(thd, $1))) MYSQL_YYABORT; - if (unlikely(lex->sphead->restore_lex(thd))) + if (lex->sphead->restore_lex(thd)) MYSQL_YYABORT; } sp_proc_stmts1 END LOOP_SYM @@ -4675,7 +4757,7 @@ repeat_body: if (unlikely(i == NULL) || unlikely(lex->sphead->add_instr(i))) MYSQL_YYABORT; - if (unlikely(lex->sphead->restore_lex(thd))) + if (lex->sphead->restore_lex(thd)) MYSQL_YYABORT; /* We can shortcut the cont_backpatch here */ i->m_cont_dest= ip+1; @@ -5155,26 +5237,16 @@ size_number: */ create_body: - '(' create_field_list ')' + create_field_list_parens { Lex->create_info.option_list= NULL; } opt_create_table_options opt_create_partitioning opt_create_select {} | opt_create_table_options opt_create_partitioning opt_create_select {} - /* - the following rule is redundant, but there's a shift/reduce - conflict that prevents the rule above from parsing a syntax like - CREATE TABLE t1 (SELECT 1); - */ - | '(' create_select_query_specification ')' - | '(' create_select_query_specification ')' - { Select->set_braces(1);} union_list {} - | '(' create_select_query_specification ')' - { Select->set_braces(1);} union_order_or_limit {} | create_like { Lex->create_info.add(DDL_options_st::OPT_LIKE); - TABLE_LIST *src_table= Lex->select_lex.add_table_to_list(thd, - $1, NULL, 0, TL_READ, MDL_SHARED_READ); + TABLE_LIST *src_table= Lex->first_select_lex()-> + add_table_to_list(thd, $1, NULL, 0, TL_READ, MDL_SHARED_READ); if (unlikely(! src_table)) MYSQL_YYABORT; /* CREATE TABLE ... LIKE is not allowed for views. */ @@ -5184,7 +5256,7 @@ create_body: create_like: LIKE table_ident { $$= $2; } - | '(' LIKE table_ident ')' { $$= $3; } + | LEFT_PAREN_LIKE LIKE table_ident ')' { $$= $3; } ; opt_create_select: @@ -5193,23 +5265,19 @@ opt_create_select: ; create_select_query_expression: - opt_with_clause SELECT_SYM create_select_part2 opt_table_expression - create_select_part4 - { - Select->set_braces(0); - Select->set_with_clause($1); + query_expression + { + if (Lex->parsed_insert_select($1->first_select())) + MYSQL_YYABORT; } - union_clause - | opt_with_clause SELECT_SYM create_select_part2 - create_select_part3_union_not_ready create_select_part4 + | LEFT_PAREN_WITH with_clause query_expression_body ')' { - Select->set_with_clause($1); + SELECT_LEX *first_select= $3->first_select(); + $3->set_with_clause($2); + $2->attach_to(first_select); + if (Lex->parsed_insert_select(first_select)) + MYSQL_YYABORT; } - | '(' create_select_query_specification ')' - | '(' create_select_query_specification ')' - { Select->set_braces(1);} union_list {} - | '(' create_select_query_specification ')' - { Select->set_braces(1);} union_order_or_limit {} ; opt_create_partitioning: @@ -5297,8 +5365,13 @@ partition_entry: We enter here when opening the frm file to translate partition info string into part_info data structure. */ + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + partition + { + Lex->pop_select(); //main select } - partition {} ; partition: @@ -5909,7 +5982,7 @@ opt_versioning_rotation: | INTERVAL_SYM expr interval opt_versioning_interval_start { partition_info *part_info= Lex->part_info; - if (unlikely(part_info->vers_set_interval($2, $3, $4))) + if (unlikely(part_info->vers_set_interval(thd, $2, $3, $4))) { my_error(ER_PART_WRONG_VALUE, MYF(0), Lex->create_last_non_select_table->table_name.str, @@ -5952,56 +6025,6 @@ opt_versioning_interval_start: End of partition parser part */ -create_select_query_specification: - opt_with_clause SELECT_SYM create_select_part2 create_select_part3 - create_select_part4 - { - Select->set_with_clause($1); - } - ; - -create_select_part2: - { - LEX *lex=Lex; - if (lex->sql_command == SQLCOM_INSERT) - lex->sql_command= SQLCOM_INSERT_SELECT; - else if (lex->sql_command == SQLCOM_REPLACE) - lex->sql_command= SQLCOM_REPLACE_SELECT; - /* - The following work only with the local list, the global list - is created correctly in this case - */ - lex->current_select->table_list.save_and_clear(&lex->save_list); - mysql_init_select(lex); - lex->current_select->parsing_place= SELECT_LIST; - } - select_options select_item_list - { - Select->parsing_place= NO_MATTER; - } - ; - -create_select_part3: - opt_table_expression - | create_select_part3_union_not_ready - ; - -create_select_part3_union_not_ready: - table_expression order_or_limit - | order_or_limit - ; - -create_select_part4: - opt_select_lock_type - { - /* - The following work only with the local list, the global list - is created correctly in this case - */ - Lex->current_select->table_list.push_front(&Lex->save_list); - } - ; - opt_as: /* empty */ {} | AS {} @@ -6219,7 +6242,7 @@ create_table_option: } | UNION_SYM opt_equal { - Lex->select_lex.table_list.save_and_clear(&Lex->save_list); + Lex->first_select_lex()->table_list.save_and_clear(&Lex->save_list); } '(' opt_table_list ')' { @@ -6228,8 +6251,8 @@ create_table_option: from the global list. */ LEX *lex=Lex; - lex->create_info.merge_list= lex->select_lex.table_list; - lex->select_lex.table_list= lex->save_list; + lex->create_info.merge_list= lex->first_select_lex()->table_list; + lex->first_select_lex()->table_list= lex->save_list; /* When excluding union list from the global list we assume that elements of the former immediately follow elements which represent @@ -6430,6 +6453,13 @@ create_field_list: } ; +create_field_list_parens: + LEFT_PAREN_ALT field_list ')' + { + Lex->create_last_non_select_table= Lex->last_table(); + } + ; + field_list: field_list_item | field_list ',' field_list_item @@ -6724,6 +6754,8 @@ parse_vcol_expr: Prevent the end user from invoking this command. */ MYSQL_YYABORT_UNLESS(Lex->parse_vcol_expr); + if (Lex->main_select_push()) + MYSQL_YYABORT; } expr { @@ -6731,14 +6763,15 @@ parse_vcol_expr: if (unlikely(!v)) MYSQL_YYABORT; Lex->last_field->vcol_info= v; + Lex->pop_select(); //main select } ; parenthesized_expr: - subselect + remember_tok_start + query_expression { - $$= new (thd->mem_root) Item_singlerow_subselect(thd, $1); - if (unlikely($$ == NULL)) + if (!($$= Lex->create_item_query_expression(thd, $1, $2))) MYSQL_YYABORT; } | expr @@ -7138,11 +7171,12 @@ field_length: opt_field_length: /* empty */ { $$= (char*) 0; /* use default length */ } | field_length { $$= $1; } + ; opt_field_length_default_1: /* empty */ { $$= (char*) "1"; } | field_length { $$= $1; } - + ; /* In sql_mode=ORACLE, real size of VARCHAR and CHAR with no length @@ -7164,10 +7198,12 @@ opt_field_length_default_1: opt_field_length_default_sp_param_varchar: /* empty */ { $$.set("4000", "4000"); } | field_length { $$.set($1, NULL); } + ; opt_field_length_default_sp_param_char: /* empty */ { $$.set("2000", "2000"); } | field_length { $$.set($1, NULL); } + ; opt_precision: /* empty */ { $$.set(0, 0); } @@ -7641,12 +7677,14 @@ fulltext_key_opts: opt_USING_key_algorithm: /* Empty*/ { $$= HA_KEY_ALG_UNDEF; } | USING btree_or_rtree { $$= $2; } + ; /* TYPE is a valid identifier, so it's handled differently than USING */ opt_key_algorithm_clause: /* Empty*/ { $$= HA_KEY_ALG_UNDEF; } | USING btree_or_rtree { $$= $2; } | TYPE_SYM btree_or_rtree { $$= $2; } + ; key_using_alg: USING btree_or_rtree @@ -7769,23 +7807,25 @@ alter: Lex->name= null_clex_str; Lex->table_type= TABLE_TYPE_UNKNOWN; Lex->sql_command= SQLCOM_ALTER_TABLE; - Lex->duplicates= DUP_ERROR; - Lex->select_lex.init_order(); + Lex->duplicates= DUP_ERROR; + Lex->first_select_lex()->order_list.empty(); Lex->create_info.init(); Lex->create_info.row_type= ROW_TYPE_NOT_USED; Lex->alter_info.reset(); Lex->no_write_to_binlog= 0; Lex->create_info.storage_media= HA_SM_DEFAULT; + if (Lex->main_select_push()) + MYSQL_YYABORT; DBUG_ASSERT(!Lex->m_sql_cmd); } alter_options TABLE_SYM table_ident opt_lock_wait_timeout { - if (unlikely(!Lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_UPDATING, - TL_READ_NO_INSERT, - MDL_SHARED_UPGRADABLE))) + if (!Lex->first_select_lex()-> + add_table_to_list(thd, $5, NULL, TL_OPTION_UPDATING, + TL_READ_NO_INSERT, MDL_SHARED_UPGRADABLE)) MYSQL_YYABORT; - Lex->select_lex.db= (Lex->select_lex.table_list.first)->db; + Lex->first_select_lex()->db= + (Lex->first_select_lex()->table_list.first)->db; Lex->create_last_non_select_table= Lex->last_table(); } alter_commands @@ -7797,11 +7837,14 @@ alter: if (unlikely(Lex->m_sql_cmd == NULL)) MYSQL_YYABORT; } + Lex->pop_select(); //main select } | ALTER DATABASE ident_or_empty { Lex->create_info.default_table_charset= NULL; Lex->create_info.used_fields= 0; + if (Lex->main_select_push()) + MYSQL_YYABORT; } create_database_options { @@ -7811,6 +7854,7 @@ alter: if (lex->name.str == NULL && unlikely(lex->copy_db_to(&lex->name))) MYSQL_YYABORT; + Lex->pop_select(); //main select } | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM { @@ -7826,6 +7870,8 @@ alter: if (unlikely(lex->sphead)) my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE")); + if (Lex->main_select_push()) + MYSQL_YYABORT; lex->sp_chistics.init(); } sp_a_chistics @@ -7834,6 +7880,9 @@ alter: lex->sql_command= SQLCOM_ALTER_PROCEDURE; lex->spname= $3; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } | ALTER FUNCTION_SYM sp_name { @@ -7841,6 +7890,8 @@ alter: if (unlikely(lex->sphead)) my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION")); + if (Lex->main_select_push()) + MYSQL_YYABORT; lex->sp_chistics.init(); } sp_a_chistics @@ -7849,14 +7900,23 @@ alter: lex->sql_command= SQLCOM_ALTER_FUNCTION; lex->spname= $3; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } | ALTER view_algorithm definer_opt opt_view_suid VIEW_SYM table_ident { - if (unlikely(Lex->add_alter_view(thd, $2, $4, $6))) + if (Lex->main_select_push()) + MYSQL_YYABORT; + if (Lex->add_alter_view(thd, $2, $4, $6)) MYSQL_YYABORT; } view_list_opt AS view_select - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } | ALTER definer_opt opt_view_suid VIEW_SYM table_ident /* We have two separate rules for ALTER VIEW rather that @@ -7864,14 +7924,22 @@ alter: with the ALTER EVENT below. */ { - if (unlikely(Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5))) + if (Lex->main_select_push()) + MYSQL_YYABORT; + if (Lex->add_alter_view(thd, VIEW_ALGORITHM_INHERIT, $3, $5)) MYSQL_YYABORT; } view_list_opt AS view_select - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } | ALTER definer_opt remember_name EVENT_SYM sp_name { - /* + if (Lex->main_select_push()) + MYSQL_YYABORT; + /* It is safe to use Lex->spname because ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO is not allowed. Lex->spname is used in the case of RENAME TO @@ -7903,6 +7971,8 @@ alter: */ Lex->sql_command= SQLCOM_ALTER_EVENT; Lex->stmt_definition_end= (char*)YYLIP->get_cpp_ptr(); + + Lex->pop_select(); //main select } | ALTER TABLESPACE alter_tablespace_info { @@ -7946,16 +8016,17 @@ alter: lex->create_info.init(); lex->no_write_to_binlog= 0; DBUG_ASSERT(!lex->m_sql_cmd); + if (Lex->main_select_push()) + MYSQL_YYABORT; } table_ident { LEX *lex= Lex; - if (unlikely(!(lex->create_info.seq_create_info= - new (thd->mem_root) sequence_definition())) || - unlikely(!lex->select_lex.add_table_to_list(thd, $5, NULL, - TL_OPTION_SEQUENCE, - TL_WRITE, - MDL_EXCLUSIVE))) + if (!(lex->create_info.seq_create_info= new (thd->mem_root) + sequence_definition()) || + !lex->first_select_lex()-> + add_table_to_list(thd, $5, NULL, TL_OPTION_SEQUENCE, + TL_WRITE, MDL_EXCLUSIVE)) MYSQL_YYABORT; } sequence_defs @@ -7964,6 +8035,9 @@ alter: Lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_alter_sequence($3); if (unlikely(Lex->m_sql_cmd == NULL)) MYSQL_YYABORT; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } ; @@ -8113,16 +8187,14 @@ alter_commands: WITH TABLE_SYM table_ident have_partitioning { LEX *lex= thd->lex; - lex->select_lex.db= $6->db; - if (lex->select_lex.db.str == NULL && - unlikely(lex->copy_db_to(&lex->select_lex.db))) + if (lex->first_select_lex()->db.str == NULL && + lex->copy_db_to(&lex->first_select_lex()->db)) MYSQL_YYABORT; lex->name= $6->table; lex->alter_info.partition_flags|= ALTER_PARTITION_EXCHANGE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $6, NULL, - TL_OPTION_UPDATING, - TL_READ_NO_INSERT, - MDL_SHARED_NO_WRITE))) + if (!lex->first_select_lex()-> + add_table_to_list(thd, $6, NULL, TL_OPTION_UPDATING, + TL_READ_NO_INSERT, MDL_SHARED_NO_WRITE)) MYSQL_YYABORT; DBUG_ASSERT(!lex->m_sql_cmd); lex->m_sql_cmd= new (thd->mem_root) @@ -8361,9 +8433,9 @@ alter_list_item: | RENAME opt_to table_ident { LEX *lex=Lex; - lex->select_lex.db= $3->db; - if (lex->select_lex.db.str == NULL && - unlikely(lex->copy_db_to(&lex->select_lex.db))) + lex->first_select_lex()->db= $3->db; + if (lex->first_select_lex()->db.str == NULL && + lex->copy_db_to(&lex->first_select_lex()->db)) MYSQL_YYABORT; if (unlikely(check_table_name($3->table.str,$3->table.length, FALSE)) || @@ -8428,6 +8500,7 @@ opt_index_lock_algorithm: | alter_algorithm_option | alter_lock_option alter_algorithm_option | alter_algorithm_option alter_lock_option + ; alter_algorithm_option: ALGORITHM_SYM opt_equal DEFAULT @@ -8486,7 +8559,7 @@ alter_option: Lex->alter_info.requested_lock= Alter_info::ALTER_TABLE_LOCK_NONE; } - + ; opt_restrict: /* empty */ { Lex->drop_mode= DROP_DEFAULT; } @@ -8753,6 +8826,7 @@ persistent_stat_spec: {} | COLUMNS persistent_column_stat_spec INDEXES persistent_index_stat_spec {} + ; persistent_column_stat_spec: ALL {} @@ -9058,8 +9132,8 @@ adm_partition: cache_keys_spec: { - Lex->select_lex.alloc_index_hints(thd); - Select->set_index_hint_type(INDEX_HINT_USE, + Lex->first_select_lex()->alloc_index_hints(thd); + Select->set_index_hint_type(INDEX_HINT_USE, INDEX_HINT_MASK_ALL); } cache_key_list_or_empty @@ -9080,217 +9154,213 @@ opt_ignore_leaves: Select : retrieve data from table */ - select: - opt_with_clause select_init + query_expression_body { - LEX *lex= Lex; - lex->sql_command= SQLCOM_SELECT; - lex->current_select->set_with_clause($1); - } - ; - -select_init: - SELECT_SYM select_options_and_item_list select_init3 - | table_value_constructor - | table_value_constructor union_list - | table_value_constructor union_order_or_limit - | '(' select_paren ')' - | '(' select_paren ')' union_list - | '(' select_paren ')' union_order_or_limit - ; - -union_list_part2: - SELECT_SYM select_options_and_item_list select_init3_union_query_term - | table_value_constructor - | table_value_constructor union_list - | table_value_constructor union_order_or_limit - | '(' select_paren_union_query_term ')' - | '(' select_paren_union_query_term ')' union_list - | '(' select_paren_union_query_term ')' union_order_or_limit - ; - -select_paren: - { - Lex->current_select->set_braces(true); + if (Lex->push_select($1->fake_select_lex ? + $1->fake_select_lex : + $1->first_select())) + MYSQL_YYABORT; } - table_value_constructor + opt_procedure_or_into { - DBUG_ASSERT(Lex->current_select->braces); + Lex->pop_select(); + if (Lex->select_finalize($1)) + MYSQL_YYABORT; } - | + | with_clause query_expression_body { - /* - In order to correctly parse UNION's global ORDER BY we need to - set braces before parsing the clause. - */ - Lex->current_select->set_braces(true); + if (Lex->push_select($2->fake_select_lex ? + $2->fake_select_lex : + $2->first_select())) + MYSQL_YYABORT; } - SELECT_SYM select_options_and_item_list select_part3 - opt_select_lock_type + opt_procedure_or_into { - DBUG_ASSERT(Lex->current_select->braces); + Lex->pop_select(); + $2->set_with_clause($1); + $1->attach_to($2->first_select()); + if (Lex->select_finalize($2)) + MYSQL_YYABORT; } - | '(' select_paren ')' ; -select_paren_union_query_term: + +select_into: + select_into_query_specification { - /* - In order to correctly parse UNION's global ORDER BY we need to - set braces before parsing the clause. - */ - Lex->current_select->set_braces(true); + if (Lex->push_select($1)) + MYSQL_YYABORT; } - SELECT_SYM select_options_and_item_list select_part3_union_query_term - opt_select_lock_type + opt_order_limit_lock { - DBUG_ASSERT(Lex->current_select->braces); - } - | '(' select_paren_union_query_term ')' + st_select_lex_unit *unit; + if (!(unit= Lex->parsed_body_select($1, $3))) + MYSQL_YYABORT; + if (Lex->select_finalize(unit)) + MYSQL_YYABORT; + } + ; + + +simple_table: + query_specification { $$= $1; } + | table_value_constructor { $$= $1; } ; -select_paren_view: +table_value_constructor: + VALUES + { + if (Lex->parsed_TVC_start()) + MYSQL_YYABORT; + } + values_list + { + if (!($$= Lex->parsed_TVC_end())) + MYSQL_YYABORT; + } + ; + +query_specification_start: + SELECT_SYM { - /* - In order to correctly parse UNION's global ORDER BY we need to - set braces before parsing the clause. - */ - Lex->current_select->set_braces(true); + SELECT_LEX *sel; + LEX *lex= Lex; + if (!(sel= lex->alloc_select(TRUE)) || + lex->push_select(sel)) + MYSQL_YYABORT; + sel->init_select(); + sel->braces= FALSE; } - SELECT_SYM select_options_and_item_list select_part3_view - opt_select_lock_type + select_options { - DBUG_ASSERT(Lex->current_select->braces); + Select->parsing_place= SELECT_LIST; } - | '(' select_paren_view ')' - ; + select_item_list + { + Select->parsing_place= NO_MATTER; + } + ; -/* The equivalent of select_paren for nested queries. */ -select_paren_derived: +query_specification: + query_specification_start + opt_from_clause + opt_where_clause + opt_group_clause + opt_having_clause + opt_window_clause { - Lex->current_select->set_braces(true); + $$= Lex->pop_select(); } - table_value_constructor + ; + +select_into_query_specification: + query_specification_start + into + opt_from_clause + opt_where_clause + opt_group_clause + opt_having_clause + opt_window_clause { - DBUG_ASSERT(Lex->current_select->braces); - $$= Lex->current_select->master_unit()->first_select(); + $$= Lex->pop_select(); } - | + ; + +opt_from_clause: + /* Empty */ + | from_clause + ; + + +query_primary: + simple_table + { $$= $1; } + | query_primary_parens + { $$= $1; } + ; + +query_primary_parens: + '(' query_expression_unit { - Lex->current_select->set_braces(true); + if (Lex->parsed_unit_in_brackets($2)) + MYSQL_YYABORT; } - SELECT_SYM select_part2_derived - opt_table_expression - opt_order_clause - opt_limit_clause - opt_select_lock_type + query_expression_tail ')' { - DBUG_ASSERT(Lex->current_select->braces); - $$= Lex->current_select->master_unit()->first_select(); + $$= Lex->parsed_unit_in_brackets_tail($2, $4); } - | '(' select_paren_derived ')' { $$= $2; } - ; - -select_init3: - opt_table_expression - opt_select_lock_type + | '(' query_primary { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + Lex->push_select($2); } - union_clause - | select_part3_union_not_ready - opt_select_lock_type + query_expression_tail ')' { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_select_in_brackets($2, $4))) + YYABORT; } ; - -select_init3_union_query_term: - opt_table_expression - opt_select_lock_type +query_expression_unit: + query_primary + unit_type_decl + query_primary { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_select_expr_start($1, $3, $2.unit_type, + $2.distinct))) + YYABORT; } - union_clause - | select_part3_union_not_ready_noproc - opt_select_lock_type + | query_expression_unit + unit_type_decl + query_primary { - /* Parentheses carry no meaning here */ - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_select_expr_cont($1, $3, $2.unit_type, + $2.distinct, TRUE))) + YYABORT; } ; - -select_init3_view: - opt_table_expression opt_select_lock_type +query_expression_body: + query_primary { - Lex->current_select->set_braces(false); + Lex->push_select($1); } - | opt_table_expression opt_select_lock_type + query_expression_tail { - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_body_select($1, $3))) + MYSQL_YYABORT; } - union_list_view - | order_or_limit opt_select_lock_type + | query_expression_unit { - Lex->current_select->set_braces(false); + if (Lex->parsed_body_unit($1)) + MYSQL_YYABORT; } - | table_expression order_or_limit opt_select_lock_type + query_expression_tail { - Lex->current_select->set_braces(false); + if (!($$= Lex->parsed_body_unit_tail($1, $3))) + MYSQL_YYABORT; } ; -/* - The SELECT parts after select_item_list that cannot be followed by UNION. -*/ - -select_part3: - opt_table_expression - | select_part3_union_not_ready - ; - -select_part3_union_query_term: - opt_table_expression - | select_part3_union_not_ready_noproc - ; - -select_part3_view: - opt_table_expression - | order_or_limit - | table_expression order_or_limit - ; - -select_part3_union_not_ready: - select_part3_union_not_ready_noproc - | table_expression procedure_clause - | table_expression order_or_limit procedure_clause - ; - -select_part3_union_not_ready_noproc: - order_or_limit - | into opt_table_expression opt_order_clause opt_limit_clause - | table_expression into - | table_expression order_or_limit - | table_expression order_or_limit into - ; - -select_options_and_item_list: +query_expression: + opt_with_clause + query_expression_body { - LEX *lex= Lex; - SELECT_LEX *sel= lex->current_select; - if (sel->linkage != UNION_TYPE) - mysql_init_select(lex); - lex->current_select->parsing_place= SELECT_LIST; + if ($1) + { + $2->set_with_clause($1); + $1->attach_to($2->first_select()); + } + $$= $2; } - select_options select_item_list + ; + +subselect: + remember_tok_start + query_expression { - Select->parsing_place= NO_MATTER; + if (!($$= Lex->parsed_subselect($2, $1))) + YYABORT; } ; @@ -9298,18 +9368,6 @@ select_options_and_item_list: /** <table expression>, as in the SQL standard. */ -table_expression: - from_clause - opt_where_clause - opt_group_clause - opt_having_clause - opt_window_clause - ; - -opt_table_expression: - /* Empty */ - | table_expression - ; from_clause: FROM table_reference_list @@ -9358,8 +9416,9 @@ history_point: TIMESTAMP TEXT_STRING { Item *item; - if (!(item= create_temporal_literal(thd, $2.str, $2.length, YYCSCL, - MYSQL_TYPE_DATETIME, true))) + if (!(item= type_handler_datetime2.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true))) MYSQL_YYABORT; $$= Vers_history_point(VERS_TIMESTAMP, item); } @@ -9412,59 +9471,68 @@ select_option: query_expression_option | SQL_NO_CACHE_SYM { - /* - Allow this flag only on the first top-level SELECT statement, if - SQL_CACHE wasn't specified, and only once per query. - */ - if (unlikely(Lex->current_select != &Lex->select_lex)) - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE")); - if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)) - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE")); - if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)) + /* + Allow this flag once per query. + */ + if (Select->options & OPTION_NO_QUERY_CACHE) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE")); - - Lex->safe_to_cache_query=0; - Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE; - Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE; + Select->options|= OPTION_NO_QUERY_CACHE; } | SQL_CACHE_SYM { - /* - Allow this flag only on the first top-level SELECT statement, if - SQL_NO_CACHE wasn't specified, and only once per query. - */ - if (unlikely(Lex->current_select != &Lex->select_lex)) - my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE")); - if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)) - my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE")); - if (unlikely(Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)) + /* + Allow this flag once per query. + */ + if (Select->options & OPTION_TO_QUERY_CACHE) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE")); - - Lex->safe_to_cache_query=1; - Lex->select_lex.options|= OPTION_TO_QUERY_CACHE; - Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE; + Select->options|= OPTION_TO_QUERY_CACHE; } ; -opt_select_lock_type: - /* empty */ - | FOR_SYM UPDATE_SYM opt_lock_wait_timeout + +select_lock_type: + FOR_SYM UPDATE_SYM opt_lock_wait_timeout_new { - LEX *lex=Lex; - lex->current_select->lock_type= TL_WRITE; - lex->current_select->set_lock_for_tables(TL_WRITE); - lex->safe_to_cache_query=0; + $$= $3; + $$.defined_lock= TRUE; + $$.update_lock= TRUE; } - | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout + | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM opt_lock_wait_timeout_new { - LEX *lex=Lex; - lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS; - lex->current_select-> - set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS); - lex->safe_to_cache_query=0; + $$= $5; + $$.defined_lock= TRUE; + $$.update_lock= FALSE; } ; +opt_select_lock_type: + /* empty */ + { + $$.empty(); + } + | select_lock_type + { + $$= $1; + } + ; + +opt_lock_wait_timeout_new: + /* empty */ + { + $$.empty(); + } + | WAIT_SYM ulong_num + { + $$.defined_timeout= TRUE; + $$.timeout= $2; + } + | NOWAIT_SYM + { + $$.defined_timeout= TRUE; + $$.timeout= 0; + } + ; + select_item_list: select_item_list ',' select_item | select_item @@ -9552,13 +9620,13 @@ select_alias: opt_default_time_precision: /* empty */ { $$= NOT_FIXED_DEC; } | '(' ')' { $$= NOT_FIXED_DEC; } - | '(' real_ulong_num ')' { $$= $2; }; + | '(' real_ulong_num ')' { $$= $2; } ; opt_time_precision: /* empty */ { $$= 0; } | '(' ')' { $$= 0; } - | '(' real_ulong_num ')' { $$= $2; }; + | '(' real_ulong_num ')' { $$= $2; } ; optional_braces: @@ -10063,6 +10131,7 @@ dyncall_create_element: else $$->len= 0; } + ; dyncall_create_list: dyncall_create_element @@ -10145,7 +10214,21 @@ column_default_non_parenthesized_expr: | param_marker { $$= $1; } | variable | sum_expr + { + if (!Lex->select_stack_top) + { + my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0)); + MYSQL_YYABORT; + } + } | window_func_expr + { + if (!Lex->select_stack_top) + { + my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0)); + MYSQL_YYABORT; + } + } | inverse_distribution_function | ROW_SYM '(' expr ',' expr_list ')' { @@ -10324,7 +10407,7 @@ function_call_keyword_timestamp: } | TIMESTAMP '(' expr ',' expr ')' { - $$= new (thd->mem_root) Item_func_add_time(thd, $3, $5, 1, 0); + $$= new (thd->mem_root) Item_func_timestamp(thd, $3, $5); if (unlikely($$ == NULL)) MYSQL_YYABORT; } @@ -11303,6 +11386,21 @@ window_func: { ((Item_sum *) $1)->mark_as_window_func_sum_expr(); } + | + function_call_generic + { + Item* item = (Item*)$1; + /* Only UDF aggregate here possible */ + if ((item == NULL) || + (item->type() != Item::SUM_FUNC_ITEM) + || (((Item_sum *)item)->sum_func() != Item_sum::UDF_SUM_FUNC)) + { + thd->parse_error(); + MYSQL_YYABORT; + } + + ((Item_sum *) $1)->mark_as_window_func_sum_expr(); + } ; simple_window_func: @@ -11543,7 +11641,7 @@ opt_gconcat_separator: opt_gorder_clause: /* empty */ - | ORDER_SYM BY gorder_list; + | ORDER_SYM BY gorder_list ; gorder_list: @@ -11656,6 +11754,10 @@ cast_type_temporal: DATE_SYM { $$.set(&type_handler_newdate); } | TIME_SYM opt_field_length { $$.set(&type_handler_time2, 0, $2); } | DATETIME opt_field_length { $$.set(&type_handler_datetime2, 0, $2); } + | INTERVAL_SYM DAY_SECOND_SYM field_length + { + $$.set(&type_handler_interval_DDhhmmssff, 0, $3); + } ; opt_expr_list: @@ -11780,10 +11882,15 @@ esc_table_ref: /* Equivalent to <table reference list> in the SQL:2003 standard. */ /* Warning - may return NULL in case of incomplete SELECT */ derived_table_list: - esc_table_ref { $$=$1; } + esc_table_ref + { + $$=$1; + Select->add_joined_table($1); + } | derived_table_list ',' esc_table_ref { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); + Select->add_joined_table($3); } ; @@ -11802,11 +11909,18 @@ join_table: left-associative joins. */ table_ref normal_join table_ref %prec TABLE_REF_PRIORITY - { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=$2; } + { + MYSQL_YYABORT_UNLESS($1 && ($$=$3)); + Select->add_joined_table($1); + Select->add_joined_table($3); + $3->straight=$2; + } | table_ref normal_join table_ref ON { MYSQL_YYABORT_UNLESS($1 && $3); + Select->add_joined_table($1); + Select->add_joined_table($3); /* Change the current name resolution context to a local context. */ if (unlikely(push_new_name_resolution_context(thd, $1, $3))) MYSQL_YYABORT; @@ -11823,6 +11937,8 @@ join_table: USING { MYSQL_YYABORT_UNLESS($1 && $3); + Select->add_joined_table($1); + Select->add_joined_table($3); } '(' using_list ')' { @@ -11833,6 +11949,8 @@ join_table: | table_ref NATURAL inner_join table_factor { MYSQL_YYABORT_UNLESS($1 && ($$=$4)); + Select->add_joined_table($1); + Select->add_joined_table($4); $4->straight=$3; add_join_natural($1,$4,NULL,Select); } @@ -11842,6 +11960,8 @@ join_table: ON { MYSQL_YYABORT_UNLESS($1 && $5); + Select->add_joined_table($1); + Select->add_joined_table($5); /* Change the current name resolution context to a local context. */ if (unlikely(push_new_name_resolution_context(thd, $1, $5))) MYSQL_YYABORT; @@ -11858,6 +11978,8 @@ join_table: | table_ref LEFT opt_outer JOIN_SYM table_factor { MYSQL_YYABORT_UNLESS($1 && $5); + Select->add_joined_table($1); + Select->add_joined_table($5); } USING '(' using_list ')' { @@ -11868,6 +11990,8 @@ join_table: | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor { MYSQL_YYABORT_UNLESS($1 && $6); + Select->add_joined_table($1); + Select->add_joined_table($6); add_join_natural($1,$6,NULL,Select); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; @@ -11878,6 +12002,8 @@ join_table: ON { MYSQL_YYABORT_UNLESS($1 && $5); + Select->add_joined_table($1); + Select->add_joined_table($5); /* Change the current name resolution context to a local context. */ if (unlikely(push_new_name_resolution_context(thd, $1, $5))) MYSQL_YYABORT; @@ -11895,6 +12021,8 @@ join_table: | table_ref RIGHT opt_outer JOIN_SYM table_factor { MYSQL_YYABORT_UNLESS($1 && $5); + Select->add_joined_table($1); + Select->add_joined_table($5); } USING '(' using_list ')' { @@ -11906,6 +12034,8 @@ join_table: | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor { MYSQL_YYABORT_UNLESS($1 && $6); + Select->add_joined_table($1); + Select->add_joined_table($6); add_join_natural($6,$1,NULL,Select); LEX *lex= Lex; if (unlikely(!($$= lex->current_select->convert_right_join()))) @@ -11940,238 +12070,45 @@ use_partition: $$= $3; } ; - -/* - This is a flattening of the rules <table factor> and <table primary> - in the SQL:2003 standard, since we don't have <sample clause> - I.e. - <table factor> ::= <table primary> [ <sample clause> ] -*/ -/* Warning - may return NULL in case of incomplete SELECT */ table_factor: - table_primary_ident - | table_primary_derived + table_primary_ident { $$= $1; } + | table_primary_derived { $$= $1; } + | join_table_parens { $$= $1; } + | table_reference_list_parens { $$= $1; } ; -table_primary_ident: - { - DBUG_ASSERT(Select); - SELECT_LEX *sel= Select; - sel->table_join_options= 0; - } - table_ident opt_use_partition opt_for_system_time_clause opt_table_alias opt_key_definition +table_reference_list_parens: + '(' table_reference_list_parens ')' { $$= $2; } + | '(' nested_table_reference_list ')' { - if (unlikely(!($$= Select->add_table_to_list(thd, $2, $5, - Select->get_table_join_options(), - YYPS->m_lock_type, - YYPS->m_mdl_type, - Select-> - pop_index_hints(), - $3)))) + if (!($$= Select->end_nested_join(thd))) MYSQL_YYABORT; - Select->add_joined_table($$); - if ($4) - $$->vers_conditions= Lex->vers_conditions; } ; - - -/* - Represents a flattening of the following rules from the SQL:2003 - standard. This sub-rule corresponds to the sub-rule - <table primary> ::= ... | <derived table> [ AS ] <correlation name> - - <derived table> ::= <table subquery> - <table subquery> ::= <subquery> - <subquery> ::= <left paren> <query expression> <right paren> - <query expression> ::= [ <with clause> ] <query expression body> - - For the time being we use the non-standard rule - select_derived_union which is a compromise between the standard - and our parser. Possibly this rule could be replaced by our - query_expression_body. -*/ - -table_primary_derived: - '(' get_select_lex select_derived_union ')' opt_for_system_time_clause opt_table_alias +nested_table_reference_list: + table_ref ',' table_ref { - /* Use $2 instead of Lex->current_select as derived table will - alter value of Lex->current_select. */ - if (!($3 || $6) && $2->embedding && - !$2->embedding->nested_join->join_list.elements) - { - /* we have a derived table ($3 == NULL) but no alias, - Since we are nested in further parentheses so we - can pass NULL to the outer level parentheses - Permits parsing of "((((select ...))) as xyz)" */ - $$= 0; - } - else if (!$3) - { - /* Handle case of derived table, alias may be NULL if there - are no outer parentheses, add_table_to_list() will throw - error in this case */ - LEX *lex=Lex; - lex->check_automatic_up(UNSPECIFIED_TYPE); - SELECT_LEX *sel= lex->current_select; - SELECT_LEX_UNIT *unit= sel->master_unit(); - lex->current_select= sel= unit->outer_select(); - Table_ident *ti= new (thd->mem_root) Table_ident(unit); - if (unlikely(ti == NULL)) - MYSQL_YYABORT; - if (unlikely(!($$= sel->add_table_to_list(thd, - ti, $6, 0, - TL_READ, - MDL_SHARED_READ)))) - MYSQL_YYABORT; - sel->add_joined_table($$); - lex->pop_context(); - lex->nest_level--; - } - else if (unlikely($6 != NULL)) - { - /* - Tables with or without joins within parentheses cannot - have aliases, and we ruled out derived tables above. - */ - thd->parse_error(); + if (Select->init_nested_join(thd)) MYSQL_YYABORT; - } - else - { - /* nested join: FROM (t1 JOIN t2 ...), - nest_level is the same as in the outer query */ - $$= $3; - } - /* - Fields in derived table can be used in upper select in - case of merge. We do not add HAVING fields because we do - not merge such derived. We do not add union because - also do not merge them - */ - if ($$ && $$->derived && - !$$->derived->first_select()->next_select()) - $$->select_lex->add_where_field($$->derived->first_select()); - if ($5) - { - MYSQL_YYABORT_UNLESS(!$3); - $$->vers_conditions= Lex->vers_conditions; - } - } - /* Represents derived table with WITH clause */ - | '(' get_select_lex subselect_start - with_clause query_expression_body - subselect_end ')' opt_for_system_time_clause opt_table_alias - { - LEX *lex=Lex; - SELECT_LEX *sel= $2; - SELECT_LEX_UNIT *unit= $5->master_unit(); - Table_ident *ti= new (thd->mem_root) Table_ident(unit); - if (unlikely(ti == NULL)) - MYSQL_YYABORT; - $5->set_with_clause($4); - lex->current_select= sel; - if (unlikely(!($$= sel->add_table_to_list(lex->thd, - ti, $9, 0, - TL_READ, - MDL_SHARED_READ)))) - MYSQL_YYABORT; - sel->add_joined_table($$); - if ($8) - $$->vers_conditions= Lex->vers_conditions; - } - ; - -/* - This rule accepts just about anything. The reason is that we have - empty-producing rules in the beginning of rules, in this case - subselect_start. This forces bison to take a decision which rules to - reduce by long before it has seen any tokens. This approach ties us - to a very limited class of parseable languages, and unfortunately - SQL is not one of them. The chosen 'solution' was this rule, which - produces just about anything, even complete bogus statements, for - instance ( table UNION SELECT 1 ). - Fortunately, we know that the semantic value returned by - select_derived is NULL if it contained a derived table, and a pointer to - the base table's TABLE_LIST if it was a base table. So in the rule - regarding union's, we throw a parse error manually and pretend it - was bison that did it. - - Also worth noting is that this rule concerns query expressions in - the from clause only. Top level select statements and other types of - subqueries have their own union rules. -*/ -select_derived_union: - select_derived - | select_derived union_order_or_limit - { - if (unlikely($1)) - { - thd->parse_error(); - MYSQL_YYABORT; - } - } - | select_derived union_head_non_top - { - if (unlikely($1)) - { - thd->parse_error(); - MYSQL_YYABORT; - } - } - union_list_derived_part2 - | derived_simple_table opt_select_lock_type - | derived_simple_table order_or_limit opt_select_lock_type - | derived_simple_table opt_select_lock_type union_list_derived - ; - -union_list_derived_part2: - query_term_union_not_ready { Lex->pop_context(); } - | query_term_union_ready { Lex->pop_context(); } - | query_term_union_ready { Lex->pop_context(); } union_list_derived - ; - -union_list_derived: - union_head_non_top union_list_derived_part2 - ; - - -/* The equivalent of select_init2 for nested queries. */ -select_init2_derived: - select_part2_derived - { - Select->set_braces(0); - } - ; - -/* The equivalent of select_part2 for nested queries. */ -select_part2_derived: - { - LEX *lex= Lex; - SELECT_LEX *sel= lex->current_select; - if (sel->linkage != UNION_TYPE) - mysql_init_select(lex); - lex->current_select->parsing_place= SELECT_LIST; + Select->add_joined_table($1); + Select->add_joined_table($3); + $$= $1->embedding; } - opt_query_expression_options select_item_list + | nested_table_reference_list ',' table_ref { - Select->parsing_place= NO_MATTER; + Select->add_joined_table($3); + $$= $1; } ; -/* handle contents of parentheses in join expression */ -select_derived: - get_select_lex_derived derived_table_list +join_table_parens: + '(' join_table_parens ')' { $$= $2; } + | '(' join_table ')' { LEX *lex= Lex; - /* for normal joins, $2 != NULL and end_nested_join() != NULL, - for derived tables, both must equal NULL */ - - if (unlikely(!($$= $1->end_nested_join(lex->thd)) && $2)) - MYSQL_YYABORT; - if (unlikely(!$2 && $$)) + if (!($$= lex->current_select->nest_last_join(thd))) { thd->parse_error(); MYSQL_YYABORT; @@ -12179,83 +12116,54 @@ select_derived: } ; -derived_simple_table: - derived_query_specification { $$= $1; } - | derived_table_value_constructor { $$= $1; } - ; -/* - Similar to query_specification, but for derived tables. - Example: the inner parenthesized SELECT in this query: - SELECT * FROM (SELECT * FROM t1); -*/ -derived_query_specification: - SELECT_SYM select_derived_init select_derived2 - { - if ($2) - Select->set_braces(1); - $$= NULL; - } - ; -derived_table_value_constructor: - VALUES - { - Lex->tvc_start(); - } - values_list +table_primary_ident: + table_ident opt_use_partition opt_for_system_time_clause + opt_table_alias_clause opt_key_definition { - if (Lex->tvc_finalize_derived()) + SELECT_LEX *sel= Select; + sel->table_join_options= 0; + if (!($$= Select->add_table_to_list(thd, $1, $4, + Select->get_table_join_options(), + YYPS->m_lock_type, + YYPS->m_mdl_type, + Select->pop_index_hints(), + $2))) MYSQL_YYABORT; - $$= NULL; + if ($3) + $$->vers_conditions= Lex->vers_conditions; } ; -select_derived2: - { - LEX *lex= Lex; - lex->derived_tables|= DERIVED_SUBQUERY; - if (unlikely(!lex->expr_allows_subselect || - lex->sql_command == (int)SQLCOM_PURGE)) - { - thd->parse_error(); - MYSQL_YYABORT; - } - if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE || - unlikely(mysql_new_select(lex, 1, NULL))) - MYSQL_YYABORT; - mysql_init_select(lex); - lex->current_select->linkage= DERIVED_TABLE_TYPE; - lex->current_select->parsing_place= SELECT_LIST; - } - select_options select_item_list - { - Select->parsing_place= NO_MATTER; - } - opt_table_expression - ; +/* + Represents a flattening of the following rules from the SQL:2003 + standard. This sub-rule corresponds to the sub-rule + <table primary> ::= ... | <derived table> [ AS ] <correlation name> -get_select_lex: - /* Empty */ { $$= Select; } - ; + <derived table> ::= <table subquery> + <table subquery> ::= <subquery> + <subquery> ::= <left paren> <query expression> <right paren> + <query expression> ::= [ <with clause> ] <query expression body> -get_select_lex_derived: - get_select_lex + For the time being we use the non-standard rule + select_derived_union which is a compromise between the standard + and our parser. Possibly this rule could be replaced by our + query_expression_body. +*/ + +table_primary_derived: + query_primary_parens opt_for_system_time_clause table_alias_clause { - LEX *lex= Lex; - if (unlikely($1->init_nested_join(lex->thd))) - MYSQL_YYABORT; + if (!($$= Lex->parsed_derived_select($1, $2, $3))) + YYABORT; } - ; - -select_derived_init: + | '(' + query_expression + ')' opt_for_system_time_clause table_alias_clause { - LEX *lex= Lex; - - TABLE_LIST *embedding= lex->current_select->embedding; - $$= embedding && - !embedding->nested_join->join_list.elements; - /* return true if we are deeply nested */ + if (!($$= Lex->parsed_derived_unit($2, $4, $5))) + YYABORT; } ; @@ -12389,9 +12297,14 @@ table_alias: | '=' ; -opt_table_alias: +opt_table_alias_clause: /* empty */ { $$=0; } - | table_alias ident_table_alias + + | table_alias_clause { $$= $1; } + ; + +table_alias_clause: + table_alias ident_table_alias { $$= (LEX_CSTRING*) thd->memdup(&$2,sizeof(LEX_STRING)); if (unlikely($$ == NULL)) @@ -12487,7 +12400,7 @@ olap_opt: SQL-2003: GROUP BY ... CUBE(col1, col2, col3) */ LEX *lex=Lex; - if (unlikely(lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)) + if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE)) my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH CUBE", "global union parameters")); lex->current_select->olap= CUBE_TYPE; @@ -12504,7 +12417,7 @@ olap_opt: SQL-2003: GROUP BY ... ROLLUP(col1, col2, col3) */ LEX *lex= Lex; - if (unlikely(lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)) + if (unlikely(lex->current_select->get_linkage() == GLOBAL_OPTIONS_TYPE)) my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH ROLLUP", "global union parameters")); lex->current_select->olap= ROLLUP_TYPE; @@ -12556,6 +12469,7 @@ opt_window_ref: if (unlikely(thd->lex->win_ref == NULL)) MYSQL_YYABORT; } + ; opt_window_partition_clause: /* empty */ { } @@ -12564,7 +12478,7 @@ opt_window_partition_clause: opt_window_order_clause: /* empty */ { } - | ORDER_SYM BY order_list + | ORDER_SYM BY order_list { Select->order_list= *($3); } ; opt_window_frame_clause: @@ -12690,70 +12604,35 @@ alter_order_item: opt_order_clause: /* empty */ + { $$= NULL; } | order_clause + { $$= $1; } ; order_clause: ORDER_SYM BY { - LEX *lex=Lex; - SELECT_LEX *sel= lex->current_select; - SELECT_LEX_UNIT *unit= sel-> master_unit(); - if (unlikely(sel->linkage != GLOBAL_OPTIONS_TYPE && - sel->olap != UNSPECIFIED_OLAP_TYPE && - (sel->linkage != UNION_TYPE || sel->braces))) - { - my_error(ER_WRONG_USAGE, MYF(0), - "CUBE/ROLLUP", "ORDER BY"); - MYSQL_YYABORT; - } - if (lex->sql_command != SQLCOM_ALTER_TABLE && - !unit->fake_select_lex) - { - /* - A query of the of the form (SELECT ...) ORDER BY order_list is - executed in the same way as the query - SELECT ... ORDER BY order_list - unless the SELECT construct contains ORDER BY or LIMIT clauses. - Otherwise we create a fake SELECT_LEX if it has not been - created yet. - */ - SELECT_LEX *first_sl= unit->first_select(); - if (unlikely(!unit->is_unit_op() && - (first_sl->order_list.elements || - first_sl->select_limit) && - unit->add_fake_select_lex(thd))) - MYSQL_YYABORT; - } - if (sel->master_unit()->is_unit_op() && !sel->braces) - { - /* - At this point we don't know yet whether this is the last - select in union or not, but we move ORDER BY to - fake_select_lex anyway. If there would be one more select - in union mysql_new_select will correctly throw error. - */ - DBUG_ASSERT(sel->master_unit()->fake_select_lex); - lex->current_select= sel->master_unit()->fake_select_lex; - } + thd->where= "ORDER clause"; } order_list { - + $$= $4; } ; order_list: order_list ',' order_ident order_dir { - if (unlikely(add_order_to_list(thd, $3,(bool) $4))) - MYSQL_YYABORT; - } + $$= $1; + if (add_to_list(thd, *$$, $3,(bool) $4)) + MYSQL_YYABORT; + } | order_ident order_dir { - if (unlikely(add_order_to_list(thd, $1,(bool) $2))) + $$= new (thd->mem_root) SQL_I_List<ORDER>(); + if (add_to_list(thd, *$$, $1, (bool) $2)) MYSQL_YYABORT; - } + } ; order_dir: @@ -12763,63 +12642,62 @@ order_dir: ; opt_limit_clause: - /* empty */ {} - | limit_clause {} + /* empty */ + { $$.empty(); } + | limit_clause + { $$= $1; } ; -limit_clause_init: - LIMIT - { - SELECT_LEX *sel= Select; - if (sel->master_unit()->is_unit_op() && !sel->braces) - { - /* Move LIMIT that belongs to UNION to fake_select_lex */ - Lex->current_select= sel->master_unit()->fake_select_lex; - DBUG_ASSERT(Select); - } - } - ; - limit_clause: - limit_clause_init limit_options + LIMIT limit_options { - SELECT_LEX *sel= Select; - if (!sel->select_limit->basic_const_item() || - sel->select_limit->val_int() > 0) + $$= $2; + if (!$$.select_limit->basic_const_item() || + $$.select_limit->val_int() > 0) Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); } - | limit_clause_init limit_options + | LIMIT limit_options ROWS_SYM EXAMINED_SYM limit_rows_option { + $$= $2; Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); } - | limit_clause_init ROWS_SYM EXAMINED_SYM limit_rows_option + | LIMIT ROWS_SYM EXAMINED_SYM limit_rows_option { + $$.select_limit= 0; + $$.offset_limit= 0; + $$.explicit_limit= 1; Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); } ; +opt_global_limit_clause: + opt_limit_clause + { + Select->explicit_limit= $1.explicit_limit; + Select->select_limit= $1.select_limit; + Select->offset_limit= $1.offset_limit; + } + ; + limit_options: limit_option { - SELECT_LEX *sel= Select; - sel->select_limit= $1; - sel->offset_limit= 0; - sel->explicit_limit= 1; + $$.select_limit= $1; + $$.offset_limit= 0; + $$.explicit_limit= 1; } | limit_option ',' limit_option { - SELECT_LEX *sel= Select; - sel->select_limit= $3; - sel->offset_limit= $1; - sel->explicit_limit= 1; + $$.select_limit= $3; + $$.offset_limit= $1; + $$.explicit_limit= 1; } | limit_option OFFSET_SYM limit_option { - SELECT_LEX *sel= Select; - sel->select_limit= $1; - sel->offset_limit= $3; - sel->explicit_limit= 1; + $$.select_limit= $1; + $$.offset_limit= $3; + $$.explicit_limit= 1; } ; @@ -12864,6 +12742,7 @@ limit_rows_option: LEX *lex=Lex; lex->limit_rows_examined= $1; } + ; delete_limit_clause: /* empty */ @@ -12882,6 +12761,77 @@ delete_limit_clause: | LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; } ; +opt_order_limit_lock: + /* empty */ + { $$= NULL; } + | order_or_limit + { + $$= $1; + $$->lock.empty(); + } + | order_or_limit select_lock_type + { + $$= $1; + $$->lock= $2; + } + | select_lock_type + { + $$= new(thd->mem_root) Lex_order_limit_lock; + if (!$$) + YYABORT; + $$->order_list= NULL; + $$->limit.empty(); + $$->lock= $1; + } + ; +query_expression_tail: + opt_order_limit_lock + ; + +opt_procedure_or_into: + /* empty */ + { + $$.empty(); + } + | procedure_clause opt_select_lock_type + { + $$= $2; + } + | into opt_select_lock_type + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WARN_DEPRECATED_SYNTAX, + ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX), + "<select expression> INTO <destination>;", + "'SELECT <select list> INTO <destination>" + " FROM...'"); + $$= $2; + } + ; + + +order_or_limit: + order_clause opt_limit_clause + { + $$= new(thd->mem_root) Lex_order_limit_lock; + if (!$$) + YYABORT; + $$->order_list= $1; + $$->limit= $2; + } + | limit_clause + { + Lex_order_limit_lock *op= $$= new(thd->mem_root) Lex_order_limit_lock; + if (!$$) + YYABORT; + op->order_list= NULL; + op->limit= $1; + $$->order_list= NULL; + $$->limit= $1; + } + ; + + opt_plus: /* empty */ | '+' @@ -12890,6 +12840,7 @@ opt_plus: int_num: opt_plus NUM { int error; $$= (int) my_strtoll10($2.str, (char**) 0, &error); } | '-' NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); } + ; ulong_num: opt_plus NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); } @@ -12913,7 +12864,7 @@ longlong_num: | LONG_NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); } | '-' NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); } | '-' LONG_NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); } - + ; ulonglong_num: opt_plus NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); } @@ -12950,15 +12901,13 @@ bool: ulong_num { $$= $1 != 0; } | TRUE_SYM { $$= 1; } | FALSE_SYM { $$= 0; } - + ; procedure_clause: PROCEDURE_SYM ident /* Procedure name */ { LEX *lex=Lex; - DBUG_ASSERT(&lex->select_lex == lex->current_select); - lex->proc_list.elements=0; lex->proc_list.first=0; lex->proc_list.next= &lex->proc_list.first; @@ -12978,6 +12927,7 @@ procedure_clause: parameters are reduced. */ Lex->expr_allows_subselect= false; + Select->options|= OPTION_PROCEDURE_CLAUSE; } '(' procedure_list ')' { @@ -13061,6 +13011,7 @@ select_outvar: into: INTO into_destination + {} ; into_destination: @@ -13270,10 +13221,11 @@ table_list: table_name: table_ident { - if (unlikely(!Select->add_table_to_list(thd, $1, NULL, - TL_OPTION_UPDATING, - YYPS->m_lock_type, - YYPS->m_mdl_type))) + if (!thd->lex->current_select_or_default()-> + add_table_to_list(thd, $1, NULL, + TL_OPTION_UPDATING, + YYPS->m_lock_type, + YYPS->m_mdl_type)) MYSQL_YYABORT; } ; @@ -13346,17 +13298,24 @@ insert: { LEX *lex= Lex; lex->sql_command= SQLCOM_INSERT; - lex->duplicates= DUP_ERROR; + lex->duplicates= DUP_ERROR; + if (Lex->main_select_push()) + MYSQL_YYABORT; mysql_init_select(lex); + lex->current_select->parsing_place= BEFORE_OPT_LIST; } insert_lock_option opt_ignore insert2 { Select->set_lock_for_tables($3); - Lex->current_select= &Lex->select_lex; + Lex->current_select= Lex->first_select_lex(); } insert_field_spec opt_insert_update - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; replace: @@ -13365,15 +13324,22 @@ replace: LEX *lex=Lex; lex->sql_command = SQLCOM_REPLACE; lex->duplicates= DUP_REPLACE; + if (Lex->main_select_push()) + MYSQL_YYABORT; mysql_init_select(lex); + lex->current_select->parsing_place= BEFORE_OPT_LIST; } replace_lock_option insert2 { Select->set_lock_for_tables($3); - Lex->current_select= &Lex->select_lex; + Lex->current_select= Lex->first_select_lex(); } insert_field_spec - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; insert_lock_option: @@ -13416,15 +13382,14 @@ insert_table: table_name_with_opt_use_partition { LEX *lex=Lex; - lex->field_list.empty(); + //lex->field_list.empty(); lex->many_values.empty(); lex->insert_list=0; }; insert_field_spec: insert_values {} - | '(' ')' insert_values {} - | '(' fields ')' insert_values {} + | insert_field_list insert_values {} | SET { LEX *lex=Lex; @@ -13432,20 +13397,33 @@ insert_field_spec: unlikely(lex->many_values.push_back(lex->insert_list, thd->mem_root))) MYSQL_YYABORT; + lex->current_select->parsing_place= NO_MATTER; } ident_eq_list ; +insert_field_list: + LEFT_PAREN_ALT opt_fields ')' + { + Lex->current_select->parsing_place= AFTER_LIST; + } + ; + +opt_fields: + /* empty */ + | fields + ; + fields: fields ',' insert_ident { Lex->field_list.push_back($3, thd->mem_root); } | insert_ident { Lex->field_list.push_back($1, thd->mem_root); } ; + + insert_values: - VALUES values_list {} - | VALUE_SYM values_list {} - | create_select_query_expression {} + create_select_query_expression {} ; values_list: @@ -13595,6 +13573,8 @@ update: UPDATE_SYM { LEX *lex= Lex; + if (Lex->main_select_push()) + MYSQL_YYABORT; mysql_init_select(lex); lex->sql_command= SQLCOM_UPDATE; lex->duplicates= DUP_ERROR; @@ -13603,13 +13583,14 @@ update: SET update_list { LEX *lex= Lex; - if (lex->select_lex.table_list.elements > 1) + if (lex->first_select_lex()->table_list.elements > 1) lex->sql_command= SQLCOM_UPDATE_MULTI; - else if (unlikely(lex->select_lex.get_table_list()->derived)) + else if (lex->first_select_lex()->get_table_list()->derived) { /* it is single table update and it is update of derived table */ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), - lex->select_lex.get_table_list()->alias.str, "UPDATE"); + lex->first_select_lex()->get_table_list()->alias.str, + "UPDATE"); MYSQL_YYABORT; } /* @@ -13619,7 +13600,14 @@ update: */ Select->set_lock_for_tables($3); } - opt_where_clause opt_order_clause delete_limit_clause {} + opt_where_clause opt_order_clause delete_limit_clause + { + if ($10) + Select->order_list= *($10); + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; update_list: @@ -13666,9 +13654,11 @@ delete: mysql_init_select(lex); YYPS->m_lock_type= TL_WRITE_DEFAULT; YYPS->m_mdl_type= MDL_SHARED_WRITE; + if (Lex->main_select_push()) + MYSQL_YYABORT; lex->ignore= 0; - lex->select_lex.init_order(); + lex->first_select_lex()->order_list.empty(); } delete_part2 ; @@ -13712,7 +13702,12 @@ single_multi: opt_where_clause opt_order_clause delete_limit_clause - opt_select_expressions {} + opt_select_expressions + { + if ($3) + Select->order_list= *($3); + Lex->pop_select(); //main select + } | table_wild_list { mysql_init_multi_delete(Lex); @@ -13723,6 +13718,9 @@ single_multi: { if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex))) MYSQL_YYABORT; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } | FROM table_alias_ref_list { @@ -13734,6 +13732,9 @@ single_multi: { if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex))) MYSQL_YYABORT; + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } ; @@ -13802,9 +13803,9 @@ truncate: LEX* lex= Lex; lex->sql_command= SQLCOM_TRUNCATE; lex->alter_info.reset(); - lex->select_lex.options= 0; - lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED; - lex->select_lex.init_order(); + lex->first_select_lex()->options= 0; + lex->sql_cache= LEX::SQL_CACHE_UNSPECIFIED; + lex->first_select_lex()->order_list.empty(); YYPS->m_lock_type= TL_WRITE; YYPS->m_mdl_type= MDL_EXCLUSIVE; } @@ -13896,6 +13897,8 @@ show: LEX *lex=Lex; lex->wild=0; lex->ident= null_clex_str; + if (Lex->main_select_push()) + MYSQL_YYABORT; mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LIST; lex->create_info.init(); @@ -13903,6 +13906,7 @@ show: show_param { Select->parsing_place= NO_MATTER; + Lex->pop_select(); //main select } ; @@ -13918,40 +13922,40 @@ show_param: { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TABLES; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_TABLE_NAMES)) MYSQL_YYABORT; } | opt_full TRIGGERS_SYM opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TRIGGERS; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TRIGGERS))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_TRIGGERS)) MYSQL_YYABORT; } | EVENTS_SYM opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_EVENTS; - lex->select_lex.db= $2; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_EVENTS))) + lex->first_select_lex()->db= $2; + if (prepare_schema_table(thd, lex, 0, SCH_EVENTS)) MYSQL_YYABORT; } | TABLE_SYM STATUS_SYM opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_TABLE_STATUS; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_TABLES))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_TABLES)) MYSQL_YYABORT; } | OPEN_SYM TABLES opt_db wild_and_where { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_OPEN_TABLES; - lex->select_lex.db= $3; - if (unlikely(prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES))) + lex->first_select_lex()->db= $3; + if (prepare_schema_table(thd, lex, 0, SCH_OPEN_TABLES)) MYSQL_YYABORT; } | PLUGINS_SYM @@ -14000,12 +14004,13 @@ show_param: LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS; } - opt_limit_clause + opt_global_limit_clause | RELAYLOG_SYM optional_connection_name EVENTS_SYM binlog_in binlog_from { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_RELAYLOG_EVENTS; - } opt_limit_clause + } + opt_global_limit_clause | keys_or_index from_or_in table_ident opt_db opt_where_clause { LEX *lex= Lex; @@ -14047,13 +14052,13 @@ show_param: LEX_CSTRING var= {STRING_WITH_LEN("error_count")}; (void) create_select_for_variable(thd, &var); } - | WARNINGS opt_limit_clause + | WARNINGS opt_global_limit_clause { Lex->sql_command = SQLCOM_SHOW_WARNS;} - | ERRORS opt_limit_clause + | ERRORS opt_global_limit_clause { Lex->sql_command = SQLCOM_SHOW_ERRORS;} | PROFILES_SYM { Lex->sql_command = SQLCOM_SHOW_PROFILES; } - | PROFILE_SYM opt_profile_defs opt_profile_args opt_limit_clause + | PROFILE_SYM opt_profile_defs opt_profile_args opt_global_limit_clause { LEX *lex= Lex; lex->sql_command= SQLCOM_SHOW_PROFILE; @@ -14115,7 +14120,7 @@ show_param: { LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL,0))) + if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL,0)) MYSQL_YYABORT; lex->create_info.storage_media= HA_SM_DEFAULT; } @@ -14123,7 +14128,7 @@ show_param: { LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))) + if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0)) MYSQL_YYABORT; lex->table_type= TABLE_TYPE_VIEW; } @@ -14131,7 +14136,7 @@ show_param: { LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; - if (unlikely(!lex->select_lex.add_table_to_list(thd, $3, NULL, 0))) + if (!lex->first_select_lex()->add_table_to_list(thd, $3, NULL, 0)) MYSQL_YYABORT; lex->table_type= TABLE_TYPE_SEQUENCE; } @@ -14348,7 +14353,7 @@ describe: mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LIST; lex->sql_command= SQLCOM_SHOW_FIELDS; - lex->select_lex.db= null_clex_str; + lex->first_select_lex()->db= null_clex_str; lex->verbose= 0; if (unlikely(prepare_schema_table(thd, lex, $2, SCH_COLUMNS))) MYSQL_YYABORT; @@ -14362,12 +14367,13 @@ describe: explainable_command { LEX *lex=Lex; - lex->select_lex.options|= SELECT_DESCRIBE; + lex->first_select_lex()->options|= SELECT_DESCRIBE; } ; explainable_command: select + | select_into | insert | replace | update @@ -14388,6 +14394,8 @@ analyze_stmt_command: opt_extended_describe: EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; } + | EXTENDED_SYM ALL + { Lex->describe|= DESCRIBE_EXTENDED | DESCRIBE_EXTENDED2; } | PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; } | opt_format_json {} ; @@ -14430,8 +14438,7 @@ flush: lex->type= 0; lex->no_write_to_binlog= $2; } - flush_options - {} + flush_options {} ; flush_options: @@ -14448,6 +14455,7 @@ flush_options: opt_table_list opt_flush_lock {} | flush_options_list + {} ; opt_flush_lock: @@ -14533,6 +14541,8 @@ flush_option: { Lex->type|= REFRESH_DES_KEY_FILE; } | RESOURCES { Lex->type|= REFRESH_USER_RESOURCES; } + | SSL_SYM + { Lex->type|= REFRESH_SSL;} | IDENT_sys remember_tok_start { Lex->type|= REFRESH_GENERIC; @@ -14554,6 +14564,21 @@ opt_table_list: | table_list {} ; +backup: + BACKUP_SYM STAGE_SYM ident + { + int type; + if (unlikely(Lex->sphead)) + my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "BACKUP STAGE")); + if ((type= find_type($3.str, &backup_stage_names, + FIND_TYPE_NO_PREFIX)) <= 0) + my_yyabort_error((ER_BACKUP_UNKNOWN_STAGE, MYF(0), $3.str)); + Lex->sql_command= SQLCOM_BACKUP; + Lex->backup_stage= (backup_stages) (type-1); + break; + } + ; + opt_delete_gtid_domain: /* empty */ {} | DELETE_DOMAIN_ID_SYM '=' '(' delete_domain_id_list ')' @@ -14584,6 +14609,7 @@ delete_domain_id: optional_flush_tables_arguments: /* empty */ {$$= 0;} | AND_SYM DISABLE_SYM CHECKPOINT_SYM {$$= REFRESH_CHECKPOINT; } + ; reset: RESET_SYM @@ -14676,6 +14702,7 @@ kill_type: /* Empty */ { $$= (int) KILL_HARD_BIT; } | HARD_SYM { $$= (int) KILL_HARD_BIT; } | SOFT_SYM { $$= 0; } + ; kill_option: /* empty */ { $$= (int) KILL_CONNECTION; } @@ -14712,7 +14739,7 @@ use: { LEX *lex=Lex; lex->sql_command=SQLCOM_CHANGE_DB; - lex->select_lex.db= $2; + lex->first_select_lex()->db= $2; } ; @@ -14729,6 +14756,8 @@ load: $2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML"); MYSQL_YYABORT; } + if (Lex->main_select_push()) + MYSQL_YYABORT; } load_data_lock opt_local INFILE TEXT_STRING_filesystem { @@ -14759,7 +14788,11 @@ load: opt_xml_rows_identified_by opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec opt_load_data_set_spec - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } ; data_or_xml: @@ -14957,11 +14990,6 @@ hex_or_bin_String: $1.length); if (unlikely(tmp == NULL)) MYSQL_YYABORT; - /* - it is OK only emulate fix_fields, because we need only - value of constant - */ - tmp->quick_fix_field(); $$= tmp->val_str((String*) 0); } | HEX_STRING @@ -14970,7 +14998,6 @@ hex_or_bin_String: $1.length); if (unlikely(tmp == NULL)) MYSQL_YYABORT; - tmp->quick_fix_field(); $$= tmp->val_str((String*) 0); } | BIN_NUM @@ -14983,7 +15010,6 @@ hex_or_bin_String: it is OK only emulate fix_fields, because we need only value of constant */ - tmp->quick_fix_field(); $$= tmp->val_str((String*) 0); } ; @@ -15132,26 +15158,23 @@ NUM_literal: temporal_literal: DATE_SYM TEXT_STRING { - if (unlikely(!($$= create_temporal_literal(thd, $2.str, $2.length, - YYCSCL, - MYSQL_TYPE_DATE, - true)))) + if (unlikely(!($$= type_handler_newdate.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true)))) MYSQL_YYABORT; } | TIME_SYM TEXT_STRING { - if (unlikely(!($$= create_temporal_literal(thd, $2.str, $2.length, - YYCSCL, - MYSQL_TYPE_TIME, - true)))) + if (unlikely(!($$= type_handler_time2.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true)))) MYSQL_YYABORT; } | TIMESTAMP TEXT_STRING { - if (unlikely(!($$= create_temporal_literal(thd, $2.str, $2.length, - YYCSCL, - MYSQL_TYPE_DATETIME, - true)))) + if (unlikely(!($$= type_handler_datetime2.create_literal_item(thd, + $2.str, $2.length, + YYCSCL, true)))) MYSQL_YYABORT; } ; @@ -15167,17 +15190,21 @@ opt_with_clause: with_clause: - WITH opt_recursive + WITH opt_recursive { + LEX *lex= Lex; With_clause *with_clause= new With_clause($2, Lex->curr_with_clause); if (unlikely(with_clause == NULL)) MYSQL_YYABORT; - Lex->derived_tables|= DERIVED_WITH; - Lex->curr_with_clause= with_clause; + lex->derived_tables|= DERIVED_WITH; + lex->curr_with_clause= with_clause; with_clause->add_to_list(Lex->with_clauses_list_last_next); + if (lex->current_select && + lex->current_select->parsing_place == BEFORE_OPT_LIST) + lex->current_select->parsing_place= NO_MATTER; } - with_list + with_list { $$= Lex->curr_with_clause; Lex->curr_with_clause= Lex->curr_with_clause->pop(); @@ -15206,15 +15233,14 @@ with_list_element: MYSQL_YYABORT; Lex->with_column_list.empty(); } - AS '(' remember_tok_start subselect remember_tok_end ')' + AS '(' remember_tok_start query_expression remember_tok_end ')' { LEX *lex= thd->lex; const char *query_start= lex->sphead ? lex->sphead->m_tmp_query : thd->query(); char *spec_start= $6 + 1; - With_element *elem= new With_element($1, *$2, $7->master_unit()); - if (unlikely(elem == NULL) || - unlikely(Lex->curr_with_clause->add_with_element(elem))) + With_element *elem= new With_element($1, *$2, $7); + if (elem == NULL || Lex->curr_with_clause->add_with_element(elem)) MYSQL_YYABORT; if (elem->set_unparsed_spec(thd, spec_start, $8, spec_start - query_start)) @@ -16159,6 +16185,7 @@ keyword_sp_var_and_label: | SQL_BUFFER_RESULT | SQL_NO_CACHE_SYM | SQL_THREAD + | STAGE_SYM | STARTS_SYM | STATEMENT_SYM | STATUS_SYM @@ -16226,14 +16253,22 @@ set: SET { LEX *lex=Lex; + if (lex->main_select_push()) + MYSQL_YYABORT; lex->set_stmt_init(); lex->var_list.empty(); sp_create_assignment_lex(thd, yychar == YYEMPTY); } start_option_value_list - {} + { + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; + } | SET STATEMENT_SYM { + if (Lex->main_select_push()) + MYSQL_YYABORT; Lex->set_stmt_init(); } set_stmt_option_value_following_option_type_list @@ -16243,6 +16278,9 @@ set: my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT")); lex->stmt_var_list= lex->var_list; lex->var_list.empty(); + Lex->pop_select(); //main select + if (Lex->check_main_unit_semantics()) + MYSQL_YYABORT; } FOR_SYM verb_clause {} @@ -16639,14 +16677,14 @@ opt_for_user: ; text_or_password: - TEXT_STRING { Lex->definer->pwhash= $1;} + TEXT_STRING { Lex->definer->auth= $1;} | PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->pwtext= $3; } | OLD_PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->pwtext= $3; - Lex->definer->pwhash.str= Item_func_password::alloc(thd, + Lex->definer->auth.str= Item_func_password::alloc(thd, $3.str, $3.length, Item_func_password::OLD); - Lex->definer->pwhash.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; + Lex->definer->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; } ; @@ -16716,7 +16754,7 @@ table_lock_list: ; table_lock: - table_ident opt_table_alias lock_option + table_ident opt_table_alias_clause lock_option { thr_lock_type lock_type= (thr_lock_type) $3; bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE); @@ -16761,27 +16799,37 @@ unlock: */ handler: - HANDLER_SYM table_ident OPEN_SYM opt_table_alias + HANDLER_SYM + { + if (Lex->main_select_push()) + MYSQL_YYABORT; + } + handler_tail + { + Lex->pop_select(); //main select + } + ; + +handler_tail: + table_ident OPEN_SYM opt_table_alias_clause { LEX *lex= Lex; if (unlikely(lex->sphead)) my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER")); lex->sql_command = SQLCOM_HA_OPEN; - if (unlikely(!lex->current_select->add_table_to_list(thd, $2, $4, - 0))) + if (!lex->current_select->add_table_to_list(thd, $1, $3, 0)) MYSQL_YYABORT; } - | HANDLER_SYM table_ident_nodb CLOSE_SYM + | table_ident_nodb CLOSE_SYM { LEX *lex= Lex; if (unlikely(lex->sphead)) my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER")); lex->sql_command = SQLCOM_HA_CLOSE; - if (unlikely(!lex->current_select->add_table_to_list(thd, $2, 0, - 0))) + if (!lex->current_select->add_table_to_list(thd, $1, 0, 0)) MYSQL_YYABORT; } - | HANDLER_SYM table_ident_nodb READ_SYM + | table_ident_nodb READ_SYM { LEX *lex=Lex; if (unlikely(lex->sphead)) @@ -16795,15 +16843,24 @@ handler: lex->current_select->select_limit= one; lex->current_select->offset_limit= 0; lex->limit_rows_examined= 0; - if (unlikely(!lex->current_select->add_table_to_list(thd, $2, 0, - 0))) + if (!lex->current_select->add_table_to_list(thd, $1, 0, 0)) MYSQL_YYABORT; } - handler_read_or_scan opt_where_clause opt_limit_clause + handler_read_or_scan opt_where_clause opt_global_limit_clause { - Lex->expr_allows_subselect= TRUE; + LEX *lex=Lex; + lex->expr_allows_subselect= TRUE; + if (!lex->current_select->explicit_limit) + { + Item *one= new (thd->mem_root) Item_int(thd, (int32) 1); + if (one == NULL) + MYSQL_YYABORT; + lex->current_select->select_limit= one; + lex->current_select->offset_limit= 0; + lex->limit_rows_examined= 0; + } /* Stored functions are not supported for HANDLER READ. */ - if (unlikely(Lex->uses_stored_routines())) + if (lex->uses_stored_routines()) { my_error(ER_NOT_SUPPORTED_YET, MYF(0), "stored functions in HANDLER ... READ"); @@ -16973,12 +17030,14 @@ grant_command: ; opt_with_admin: - /* nothing */ { Lex->definer = 0; } - | WITH ADMIN_SYM user_or_role { Lex->definer = $3; } + /* nothing */ { Lex->definer = 0; } + | WITH ADMIN_SYM user_or_role { Lex->definer = $3; } + ; opt_with_admin_option: - /* nothing */ { Lex->with_admin_option= false; } - | WITH ADMIN_SYM OPTION { Lex->with_admin_option= true; } + /* nothing */ { Lex->with_admin_option= false; } + | WITH ADMIN_SYM OPTION { Lex->with_admin_option= true; } + ; role_list: grant_role @@ -17214,13 +17273,11 @@ grant_user: { $$= $1; $1->pwtext= $4; - if (unlikely(Lex->sql_command == SQLCOM_REVOKE)) - MYSQL_YYABORT; } | user IDENTIFIED_SYM BY PASSWORD_SYM TEXT_STRING { $$= $1; - $1->pwhash= $5; + $1->auth= $5; } | user IDENTIFIED_SYM via_or_with ident_or_text { @@ -17228,12 +17285,20 @@ grant_user: $1->plugin= $4; $1->auth= empty_clex_str; } - | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as TEXT_STRING_sys + | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as + TEXT_STRING_sys { $$= $1; $1->plugin= $4; $1->auth= $6; } + | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as + PASSWORD_SYM '(' TEXT_STRING ')' + { + $$= $1; + $1->plugin= $4; + $1->pwtext= $8; + } | user_or_role { $$= $1; } ; @@ -17467,212 +17532,27 @@ release: */ unit_type_decl: - UNION_SYM - { $$= UNION_TYPE; } + UNION_SYM union_option + { $$.unit_type= UNION_TYPE; $$.distinct= $2; } | INTERSECT_SYM - { $$= INTERSECT_TYPE; } + { $$.unit_type= INTERSECT_TYPE; $$.distinct= 1; } | EXCEPT_SYM - { $$= EXCEPT_TYPE; } - - -union_clause: - /* empty */ {} - | union_list - ; - -union_list: - unit_type_decl union_option - { - if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, TRUE))) - MYSQL_YYABORT; - } - union_list_part2 - { - /* - Remove from the name resolution context stack the context of the - last select in the union. - */ - Lex->pop_context(); - } - ; - -union_list_view: - unit_type_decl union_option - { - if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, TRUE))) - MYSQL_YYABORT; - } - query_expression_body_view - { - Lex->pop_context(); - } - ; - -union_order_or_limit: - { - LEX *lex= thd->lex; - DBUG_ASSERT(lex->current_select->linkage != GLOBAL_OPTIONS_TYPE); - SELECT_LEX *sel= lex->current_select; - SELECT_LEX_UNIT *unit= sel->master_unit(); - SELECT_LEX *fake= unit->fake_select_lex; - if (fake) - { - fake->no_table_names_allowed= 1; - lex->current_select= fake; - } - thd->where= "global ORDER clause"; - } - order_or_limit - { - thd->lex->current_select->no_table_names_allowed= 0; - thd->where= ""; - } - ; - -order_or_limit: - order_clause opt_limit_clause - | limit_clause + { $$.unit_type= EXCEPT_TYPE; $$.distinct= 1; } ; /* Start a UNION, for non-top level query expressions. */ -union_head_non_top: - unit_type_decl union_option - { - if (unlikely(Lex->add_select_to_union_list((bool)$2, $1, FALSE))) - MYSQL_YYABORT; - } - ; - union_option: /* empty */ { $$=1; } | DISTINCT { $$=1; } | ALL { $$=0; } ; -simple_table: - query_specification { $$= $1; } - | table_value_constructor { $$= $1; } - ; - -table_value_constructor: - VALUES - { - Lex->tvc_start(); - } - values_list - { - $$= Lex->current_select; - if (Lex->tvc_finalize()) - MYSQL_YYABORT; - } - ; - -/* - Corresponds to the SQL Standard - <query specification> ::= - SELECT [ <set quantifier> ] <select list> <table expression> - - Notes: - - We allow more options in addition to <set quantifier> - - <table expression> is optional in MariaDB -*/ -query_specification: - SELECT_SYM select_init2_derived opt_table_expression - { - $$= Lex->current_select->master_unit()->first_select(); - } - ; - -query_term_union_not_ready: - simple_table order_or_limit opt_select_lock_type { $$= $1; } - | '(' select_paren_derived ')' union_order_or_limit { $$= $2; } - ; - -query_term_union_ready: - simple_table opt_select_lock_type { $$= $1; } - | '(' select_paren_derived ')' { $$= $2; } - ; - -query_expression_body: - query_term_union_not_ready { $$= $1; } - | query_term_union_ready { $$= $1; } - | query_term_union_ready union_list_derived { $$= $1; } - ; - -/* Corresponds to <query expression> in the SQL:2003 standard. */ -subselect: - subselect_start opt_with_clause query_expression_body subselect_end - { - $3->set_with_clause($2); - $$= $3; - } - ; - -subselect_start: - { - LEX *lex=Lex; - if (unlikely(!lex->expr_allows_subselect || - lex->sql_command == (int)SQLCOM_PURGE)) - { - thd->parse_error(); - MYSQL_YYABORT; - } - /* - we are making a "derived table" for the parenthesis - as we need to have a lex level to fit the union - after the parenthesis, e.g. - (SELECT .. ) UNION ... becomes - SELECT * FROM ((SELECT ...) UNION ...) - */ - if (unlikely(mysql_new_select(Lex, 1, NULL))) - MYSQL_YYABORT; - } - ; - -subselect_end: - { - LEX *lex=Lex; - - lex->check_automatic_up(UNSPECIFIED_TYPE); - lex->pop_context(); - SELECT_LEX *child= lex->current_select; - lex->current_select = lex->current_select->return_after_parsing(); - lex->nest_level--; - lex->current_select->n_child_sum_items += child->n_sum_items; - /* - A subselect can add fields to an outer select. Reserve space for - them. - */ - lex->current_select->select_n_where_fields+= - child->select_n_where_fields; - - /* - Aggregate functions in having clause may add fields to an outer - select. Count them also. - */ - lex->current_select->select_n_having_items+= - child->select_n_having_items; - } - ; - -opt_query_expression_options: - /* empty */ - | query_expression_option_list - ; - -query_expression_option_list: - query_expression_option_list query_expression_option - | query_expression_option - ; - query_expression_option: STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; } | HIGH_PRIORITY { - if (unlikely(Lex->check_simple_select(&$1))) - MYSQL_YYABORT; YYPS->m_lock_type= TL_READ_HIGH_PRIORITY; YYPS->m_mdl_type= MDL_SHARED_READ; Select->options|= SELECT_HIGH_PRIORITY; @@ -17681,18 +17561,8 @@ query_expression_option: | UNIQUE_SYM { Select->options|= SELECT_DISTINCT; } | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } - | SQL_BUFFER_RESULT - { - if (unlikely(Lex->check_simple_select(&$1))) - MYSQL_YYABORT; - Select->options|= OPTION_BUFFER_RESULT; - } - | SQL_CALC_FOUND_ROWS - { - if (unlikely(Lex->check_simple_select(&$1))) - MYSQL_YYABORT; - Select->options|= OPTION_FOUND_ROWS; - } + | SQL_BUFFER_RESULT { Select->options|= OPTION_BUFFER_RESULT; } + | SQL_CALC_FOUND_ROWS { Select->options|= OPTION_FOUND_ROWS; } | ALL { Select->options|= SELECT_ALL; } ; @@ -17780,35 +17650,14 @@ view_select: lex->parsing_options.allows_variable= FALSE; lex->create_view->select.str= (char *) YYLIP->get_cpp_ptr(); } - opt_with_clause query_expression_body_view view_check_option + query_expression + view_check_option { - LEX *lex= Lex; - size_t len= YYLIP->get_cpp_ptr() - lex->create_view->select.str; - void *create_view_select= thd->memdup(lex->create_view->select.str, len); - lex->create_view->select.length= len; - lex->create_view->select.str= (char *) create_view_select; - trim_whitespace(thd->charset(), - &lex->create_view->select); - lex->create_view->check= $4; - lex->parsing_options.allows_variable= TRUE; - lex->current_select->set_with_clause($2); + if (Lex->parsed_create_view($2, $3)) + MYSQL_YYABORT; } ; -/* - SQL Standard <query expression body> for VIEWs. - Does not include INTO and PROCEDURE clauses. -*/ -query_expression_body_view: - SELECT_SYM select_options_and_item_list select_init3_view - | table_value_constructor - | table_value_constructor union_order_or_limit - | table_value_constructor union_list_view - | '(' select_paren_view ')' - | '(' select_paren_view ')' union_order_or_limit - | '(' select_paren_view ')' union_list_view - ; - view_check_option: /* empty */ { $$= VIEW_CHECK_NONE; } | WITH CHECK_SYM OPTION { $$= VIEW_CHECK_CASCADED; } @@ -17909,11 +17758,10 @@ trigger_tail: sp_proc_stmt alternatives are not saving/restoring LEX, so lex->query_tables can be wiped out. */ - if (unlikely(!lex->select_lex. - add_table_to_list(thd, $10, (LEX_CSTRING*) 0, - TL_OPTION_UPDATING, - TL_READ_NO_INSERT, - MDL_SHARED_NO_WRITE))) + if (!lex->first_select_lex()-> + add_table_to_list(thd, $10, (LEX_CSTRING*) 0, + TL_OPTION_UPDATING, TL_READ_NO_INSERT, + MDL_SHARED_NO_WRITE)) MYSQL_YYABORT; } ; @@ -18177,10 +18025,11 @@ uninstall: /* Avoid compiler warning from sql_yacc.cc where yyerrlab1 is not used */ keep_gcc_happy: - IMPOSSIBLE_ACTION - { - YYERROR; - } + IMPOSSIBLE_ACTION + { + YYERROR; + } + ; /** @} (end of group Parser) diff --git a/sql/structs.h b/sql/structs.h index 5cc392c33b7..3e29e137376 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -227,12 +227,11 @@ struct AUTHID struct LEX_USER: public AUTHID { - LEX_CSTRING plugin, auth; - LEX_CSTRING pwtext, pwhash; + LEX_CSTRING plugin, auth, pwtext; void reset_auth() { - pwtext.length= pwhash.length= plugin.length= auth.length= 0; - pwtext.str= pwhash.str= 0; + pwtext.length= plugin.length= auth.length= 0; + pwtext.str= 0; plugin.str= auth.str= ""; } }; @@ -773,6 +772,43 @@ public: }; +class st_select_lex; + +class Lex_select_lock +{ +public: + struct + { + uint defined_lock:1; + uint update_lock:1; + uint defined_timeout:1; + }; + ulong timeout; + + + void empty() + { + defined_lock= update_lock= defined_timeout= FALSE; + timeout= 0; + } + void set_to(st_select_lex *sel); +}; + +class Lex_select_limit +{ +public: + bool explicit_limit; + Item *select_limit, *offset_limit; + + void empty() + { + explicit_limit= FALSE; + select_limit= offset_limit= NULL; + } +}; + +struct st_order; + class Load_data_param { protected: @@ -809,4 +845,20 @@ public: }; +class Timeval: public timeval +{ +protected: + Timeval() { } +public: + Timeval(my_time_t sec, ulong usec) + { + tv_sec= sec; + tv_usec= usec; + } + explicit Timeval(const timeval &tv) + :timeval(tv) + { } +}; + + #endif /* STRUCTS_INCLUDED */ diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 369c9a6222a..e8044ef9035 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1942,6 +1942,19 @@ Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_CSTRING *base) } +static Sys_var_uint Sys_gtid_cleanup_batch_size( + "gtid_cleanup_batch_size", + "Normally does not need tuning. How many old rows must accumulate in " + "the mysql.gtid_slave_pos table before a background job will be run to " + "delete them. Can be increased to reduce number of commits if " + "using many different engines with --gtid_pos_auto_engines, or to " + "reduce CPU overhead if using a huge number of different " + "gtid_domain_ids. Can be decreased to reduce number of old rows in the " + "table.", + GLOBAL_VAR(opt_gtid_cleanup_batch_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0,2147483647), DEFAULT(64), BLOCK_SIZE(1)); + + static bool check_slave_parallel_threads(sys_var *self, THD *thd, set_var *var) { @@ -2456,7 +2469,7 @@ static Sys_var_ulong Sys_optimizer_use_condition_selectivity( "5 - additionally use selectivity of certain non-range predicates " "calculated on record samples", SESSION_VAR(optimizer_use_condition_selectivity), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(1, 5), DEFAULT(1), BLOCK_SIZE(1)); + VALID_RANGE(1, 5), DEFAULT(4), BLOCK_SIZE(1)); static Sys_var_ulong Sys_optimizer_search_depth( "optimizer_search_depth", @@ -2496,6 +2509,7 @@ export const char *optimizer_switch_names[]= "orderby_uses_equalities", "condition_pushdown_for_derived", "split_materialized", + "condition_pushdown_for_subquery", "default", NullS }; @@ -2571,13 +2585,15 @@ static Sys_var_ulong Sys_read_buff_size( static bool check_read_only(sys_var *self, THD *thd, set_var *var) { /* Prevent self dead-lock */ - if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction()) + if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction() || + thd->current_backup_stage != BACKUP_FINISHED) { my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); return true; } return false; } + static bool fix_read_only(sys_var *self, THD *thd, enum_var_type type) { bool result= true; @@ -2720,17 +2736,6 @@ static Sys_var_ulong Sys_query_prealloc_size( BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_thd_mem_root)); -#ifdef HAVE_SMEM -static Sys_var_mybool Sys_shared_memory( - "shared_memory", "Enable the shared memory", - READ_ONLY GLOBAL_VAR(opt_enable_shared_memory), CMD_LINE(OPT_ARG), - DEFAULT(FALSE)); - -static Sys_var_charptr Sys_shared_memory_base_name( - "shared_memory_base_name", "Base name of shared memory", - READ_ONLY GLOBAL_VAR(shared_memory_base_name), CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(0)); -#endif // this has to be NO_CMD_LINE as the command-line option has a different name static Sys_var_mybool Sys_skip_external_locking( @@ -3363,6 +3368,7 @@ static const char *sql_mode_names[]= "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", "NO_ENGINE_SUBSTITUTION", "PAD_CHAR_TO_FULL_LENGTH", "EMPTY_STRING_IS_NULL", "SIMULTANEOUS_ASSIGNMENT", + "TIME_ROUND_FRACTIONAL", 0 }; @@ -4052,6 +4058,16 @@ static bool fix_sql_log_bin_after_update(sys_var *self, THD *thd, return FALSE; } +static bool check_session_only_variable(sys_var *self, THD *,set_var *var) +{ + if (unlikely(var->type == OPT_GLOBAL)) + { + my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), self->name.str, "SESSION"); + return true; + } + return false; +} + /** This function checks if the sql_log_bin can be changed, what is possible if: @@ -4067,20 +4083,17 @@ static bool fix_sql_log_bin_after_update(sys_var *self, THD *thd, static bool check_sql_log_bin(sys_var *self, THD *thd, set_var *var) { if (check_has_super(self, thd, var)) - return TRUE; + return true; - if (unlikely(var->type == OPT_GLOBAL)) - { - my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), self->name.str, "SESSION"); - return TRUE; - } + if (check_session_only_variable(self, thd, var)) + return true; if (unlikely(error_if_in_trans_or_substatement(thd, ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN, ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN))) - return TRUE; + return true; - return FALSE; + return false; } static Sys_var_mybool Sys_log_binlog( @@ -5592,6 +5605,27 @@ static Sys_var_int Sys_keepalive_probes( BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL)); + +static bool update_tcp_nodelay(sys_var *self, THD *thd, + enum_var_type type) +{ + DBUG_ASSERT(thd); + + Vio *vio = thd->net.vio; + if (vio) + return (MY_TEST(vio_nodelay(vio, thd->variables.tcp_nodelay))); + + return false; +} + +static Sys_var_mybool Sys_tcp_nodelay( + "tcp_nodelay", + "Set option TCP_NODELAY (disable Nagle's algorithm) on socket", + SESSION_VAR(tcp_nodelay), CMD_LINE(OPT_ARG), + DEFAULT(TRUE),NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_session_only_variable), + ON_UPDATE(update_tcp_nodelay)); + static Sys_var_charptr Sys_ignore_db_dirs( "ignore_db_dirs", "Specifies a directory to add to the ignore list when collecting " @@ -5823,12 +5857,13 @@ static Sys_var_ulong Sys_progress_report_time( VALID_RANGE(0, UINT_MAX), DEFAULT(5), BLOCK_SIZE(1)); const char *use_stat_tables_modes[] = - {"NEVER", "COMPLEMENTARY", "PREFERABLY", 0}; + {"NEVER", "COMPLEMENTARY", "PREFERABLY", + "COMPLEMENTARY_FOR_QUERIES", "PREFERABLY_FOR_QUERIES", 0}; static Sys_var_enum Sys_optimizer_use_stat_tables( "use_stat_tables", "Specifies how to use system statistics tables", SESSION_VAR(use_stat_tables), CMD_LINE(REQUIRED_ARG), - use_stat_tables_modes, DEFAULT(0)); + use_stat_tables_modes, DEFAULT(4)); static Sys_var_ulong Sys_histogram_size( "histogram_size", diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index 373df354268..1c41cc22411 100644 --- a/sql/sys_vars.ic +++ b/sql/sys_vars.ic @@ -2659,7 +2659,8 @@ public: if (!Sys_var_enum::do_check(thd, var)) return false; MYSQL_TIME ltime; - bool res= var->value->get_date(<ime, 0); + Datetime::Options opt(TIME_CONV_NONE, thd); + bool res= var->value->get_date(thd, <ime, opt); if (!res) { var->save_result.ulonglong_value= SYSTEM_TIME_AS_OF; @@ -2676,7 +2677,9 @@ private: { if (var->value) { - res= var->value->get_date(&out.ltime, 0); + THD *thd= current_thd; + Datetime::Options opt(TIME_CONV_NONE, thd); + res= var->value->get_date(thd, &out.ltime, opt); } else // set DEFAULT from global var { diff --git a/sql/table.cc b/sql/table.cc index ce7a34a8fe2..6737e57d728 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -44,6 +44,7 @@ #include "sql_cte.h" #include "ha_sequence.h" #include "sql_show.h" +#include <atomic> /* For MySQL 5.7 virtual fields */ #define MYSQL57_GENERATED_FIELD 128 @@ -69,8 +70,6 @@ LEX_CSTRING GENERAL_LOG_NAME= {STRING_WITH_LEN("general_log")}; LEX_CSTRING SLOW_LOG_NAME= {STRING_WITH_LEN("slow_log")}; LEX_CSTRING TRANSACTION_REG_NAME= {STRING_WITH_LEN("transaction_registry")}; -LEX_CSTRING MYSQL_USER_NAME= {STRING_WITH_LEN("user")}; -LEX_CSTRING MYSQL_DB_NAME= {STRING_WITH_LEN("db")}; LEX_CSTRING MYSQL_PROC_NAME= {STRING_WITH_LEN("proc")}; /* @@ -79,7 +78,7 @@ LEX_CSTRING MYSQL_PROC_NAME= {STRING_WITH_LEN("proc")}; */ static LEX_CSTRING parse_vcol_keyword= { STRING_WITH_LEN("PARSE_VCOL_EXPR ") }; -static int64 last_table_id; +static std::atomic<ulong> last_table_id; /* Functions defined in this file */ @@ -344,8 +343,8 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, */ do { - share->table_map_id=(ulong) my_atomic_add64_explicit(&last_table_id, 1, - MY_MEMORY_ORDER_RELAXED); + share->table_map_id= + last_table_id.fetch_add(1, std::memory_order_relaxed); } while (unlikely(share->table_map_id == ~0UL)); } DBUG_RETURN(share); @@ -917,6 +916,54 @@ static uint upgrade_collation(ulong mysql_version, uint cs_number) } +void Column_definition_attributes::frm_pack_basic(uchar *buff) const +{ + int2store(buff + 3, length); + int2store(buff + 8, pack_flag); + buff[10]= (uchar) unireg_check; +} + + +void Column_definition_attributes::frm_unpack_basic(const uchar *buff) +{ + length= uint2korr(buff + 3); + pack_flag= uint2korr(buff + 8); + unireg_check= (Field::utype) MTYP_TYPENR((uint) buff[10]); +} + + +void Column_definition_attributes::frm_pack_charset(uchar *buff) const +{ + buff[11]= (uchar) (charset->number >> 8); + buff[14]= (uchar) charset->number; +} + + +bool Column_definition_attributes::frm_unpack_charset(TABLE_SHARE *share, + const uchar *buff) +{ + uint cs_org= buff[14] + (((uint) buff[11]) << 8); + uint cs_new= upgrade_collation(share->mysql_version, cs_org); + if (cs_org != cs_new) + share->incompatible_version|= HA_CREATE_USED_CHARSET; + if (cs_new && !(charset= get_charset(cs_new, MYF(0)))) + { + const char *csname= get_charset_name((uint) cs_new); + char tmp[10]; + if (!csname || csname[0] =='?') + { + my_snprintf(tmp, sizeof(tmp), "#%u", cs_new); + csname= tmp; + } + my_printf_error(ER_UNKNOWN_COLLATION, + "Unknown collation '%s' in table '%-.64s' definition", + MYF(0), csname, share->table_name.str); + return true; + } + return false; +} + + /* In MySQL 5.7 the null bits for not stored virtual fields are last. Calculate the position for these bits @@ -1147,6 +1194,38 @@ end: DBUG_RETURN(res); } + +static const Type_handler *old_frm_type_handler(uint pack_flag, + uint interval_nr) +{ + enum_field_types field_type= (enum_field_types) f_packtype(pack_flag); + DBUG_ASSERT(field_type < 16); + + if (!f_is_alpha(pack_flag)) + return Type_handler::get_handler_by_real_type(field_type); + + if (!f_is_packed(pack_flag)) + { + if (field_type == MYSQL_TYPE_DECIMAL) // 3.23 or 4.0 string + return &type_handler_string; + if (field_type == MYSQL_TYPE_VARCHAR) // Since mysql-5.0 + return &type_handler_varchar; + return NULL; // Error (bad frm?) + } + + if (f_is_blob(pack_flag)) + return &type_handler_blob; // QQ: exact type?? + + if (interval_nr) + { + if (f_is_enum(pack_flag)) + return &type_handler_enum; + return &type_handler_set; + } + return Type_handler::get_handler_by_real_type(field_type); +} + + /** Read data from a binary .frm file image into a TABLE_SHARE @@ -1193,8 +1272,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, size_t UNINIT_VAR(options_len); uchar *vcol_screen_pos; const uchar *options= 0; - size_t UNINIT_VAR(gis_options_len); - const uchar *gis_options= 0; + LEX_CUSTRING gis_options= { NULL, 0}; KEY first_keyinfo; uint len; uint ext_key_parts= 0; @@ -1290,10 +1368,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, case EXTRA2_GIS: #ifdef HAVE_SPATIAL { - if (gis_options) + if (gis_options.str) goto err; - gis_options= extra2; - gis_options_len= length; + gis_options.str= extra2; + gis_options.length= length; } #endif /*HAVE_SPATIAL*/ break; @@ -1784,83 +1862,19 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++) { - uint pack_flag, interval_nr, unireg_type, recpos, field_length; - uint vcol_info_length=0; - uint vcol_expr_length=0; - enum_field_types field_type; - CHARSET_INFO *charset=NULL; - Field::geometry_type geom_type= Field::GEOM_GEOMETRY; + uint interval_nr= 0, recpos; LEX_CSTRING comment; LEX_CSTRING name; Virtual_column_info *vcol_info= 0; - uint gis_length, gis_decimals, srid= 0; - Field::utype unireg_check; const Type_handler *handler; uint32 flags= 0; + Column_definition_attributes attr; if (new_frm_ver >= 3) { /* new frm file in 4.1 */ - field_length= uint2korr(strpos+3); recpos= uint3korr(strpos+5); - pack_flag= uint2korr(strpos+8); - unireg_type= (uint) strpos[10]; - interval_nr= (uint) strpos[12]; uint comment_length=uint2korr(strpos+15); - field_type=(enum_field_types) (uint) strpos[13]; - - /* charset and geometry_type share the same byte in frm */ - if (field_type == MYSQL_TYPE_GEOMETRY) - { -#ifdef HAVE_SPATIAL - uint gis_opt_read; - Field_geom::storage_type st_type; - geom_type= (Field::geometry_type) strpos[14]; - charset= &my_charset_bin; - gis_opt_read= gis_field_options_read(gis_options, gis_options_len, - &st_type, &gis_length, &gis_decimals, &srid); - gis_options+= gis_opt_read; - gis_options_len-= gis_opt_read; -#else - goto err; -#endif - } - else - { - uint cs_org= strpos[14] + (((uint) strpos[11]) << 8); - uint cs_new= upgrade_collation(share->mysql_version, cs_org); - if (cs_org != cs_new) - share->incompatible_version|= HA_CREATE_USED_CHARSET; - if (!cs_new) - charset= &my_charset_bin; - else if (!(charset= get_charset(cs_new, MYF(0)))) - { - const char *csname= get_charset_name((uint) cs_new); - char tmp[10]; - if (!csname || csname[0] =='?') - { - my_snprintf(tmp, sizeof(tmp), "#%u", cs_new); - csname= tmp; - } - my_printf_error(ER_UNKNOWN_COLLATION, - "Unknown collation '%s' in table '%-.64s' definition", - MYF(0), csname, share->table_name.str); - goto err; - } - } - - if ((uchar)field_type == (uchar)MYSQL_TYPE_VIRTUAL) - { - if (!interval_nr) // Expect non-null expression - goto err; - /* - MariaDB version 10.0 version. - The interval_id byte in the .frm file stores the length of the - expression statement for a virtual column. - */ - vcol_info_length= interval_nr; - interval_nr= 0; - } if (!comment_length) { @@ -1874,32 +1888,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, comment_pos+= comment_length; } - if (unireg_type & MYSQL57_GENERATED_FIELD) + if ((uchar) strpos[13] == (uchar) MYSQL_TYPE_VIRTUAL) { - unireg_type&= MYSQL57_GENERATED_FIELD; - /* - MySQL 5.7 generated fields - - byte 1 = 1 - byte 2,3 = expr length - byte 4 = stored_in_db - byte 5.. = expr + MariaDB version 10.0 version. + The interval_id byte in the .frm file stores the length of the + expression statement for a virtual column. */ - if ((uint)(vcol_screen_pos)[0] != 1) + uint vcol_info_length= (uint) strpos[12]; + + if (!vcol_info_length) // Expect non-null expression goto err; - vcol_info= new (&share->mem_root) Virtual_column_info(); - vcol_info_length= uint2korr(vcol_screen_pos + 1); - DBUG_ASSERT(vcol_info_length); - vcol_info->stored_in_db= vcol_screen_pos[3]; - vcol_info->utf8= 0; - vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;; - share->virtual_fields++; - vcol_info_length= 0; - } - if (vcol_info_length) - { + attr.frm_unpack_basic(strpos); + if (attr.frm_unpack_charset(share, strpos)) + goto err; /* Old virtual field information before 10.2 @@ -1913,7 +1916,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, vcol_info= new (&share->mem_root) Virtual_column_info(); bool opt_interval_id= (uint)vcol_screen_pos[0] == 2; - field_type= (enum_field_types) (uchar) vcol_screen_pos[1]; + enum_field_types ftype= (enum_field_types) (uchar) vcol_screen_pos[1]; + if (!(handler= Type_handler::get_handler_by_real_type(ftype))) + goto err; if (opt_interval_id) interval_nr= (uint)vcol_screen_pos[3]; else if ((uint)vcol_screen_pos[0] != 1) @@ -1921,26 +1926,63 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, bool stored= vcol_screen_pos[2] & 1; vcol_info->stored_in_db= stored; vcol_info->set_vcol_type(stored ? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL); - vcol_expr_length= vcol_info_length - - (uint)(FRM_VCOL_OLD_HEADER_SIZE(opt_interval_id)); + uint vcol_expr_length= vcol_info_length - + (uint)(FRM_VCOL_OLD_HEADER_SIZE(opt_interval_id)); vcol_info->utf8= 0; // before 10.2.1 the charset was unknown int2store(vcol_screen_pos+1, vcol_expr_length); // for parse_vcol_defs() vcol_screen_pos+= vcol_info_length; share->virtual_fields++; } + else + { + interval_nr= (uint) strpos[12]; + enum_field_types field_type= (enum_field_types) strpos[13]; + if (!(handler= Type_handler::get_handler_by_real_type(field_type))) + goto err; // Not supported field type + if (handler->Column_definition_attributes_frm_unpack(&attr, share, + strpos, + &gis_options)) + goto err; + } + + if (((uint) strpos[10]) & MYSQL57_GENERATED_FIELD) + { + attr.unireg_check= Field::NONE; + + /* + MySQL 5.7 generated fields + + byte 1 = 1 + byte 2,3 = expr length + byte 4 = stored_in_db + byte 5.. = expr + */ + if ((uint)(vcol_screen_pos)[0] != 1) + goto err; + vcol_info= new (&share->mem_root) Virtual_column_info(); + uint vcol_info_length= uint2korr(vcol_screen_pos + 1); + DBUG_ASSERT(vcol_info_length); + vcol_info->stored_in_db= vcol_screen_pos[3]; + vcol_info->utf8= 0; + vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;; + share->virtual_fields++; + } } else { - field_length= (uint) strpos[3]; + attr.length= (uint) strpos[3]; recpos= uint2korr(strpos+4), - pack_flag= uint2korr(strpos+6); - pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files - unireg_type= (uint) strpos[8]; + attr.pack_flag= uint2korr(strpos+6); + attr.pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files + attr.unireg_check= (Field::utype) MTYP_TYPENR((uint) strpos[8]); interval_nr= (uint) strpos[10]; /* old frm file */ - field_type= (enum_field_types) f_packtype(pack_flag); - if (f_is_binary(pack_flag)) + enum_field_types ftype= (enum_field_types) f_packtype(attr.pack_flag); + if (!(handler= Type_handler::get_handler_by_real_type(ftype))) + goto err; // Not supported field type + + if (f_is_binary(attr.pack_flag)) { /* Try to choose the best 4.1 type: @@ -1948,26 +1990,26 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, try to find a binary collation for character set. - for other types (e.g. BLOB) just use my_charset_bin. */ - if (!f_is_blob(pack_flag)) + if (!f_is_blob(attr.pack_flag)) { // 3.23 or 4.0 string - if (!(charset= get_charset_by_csname(share->table_charset->csname, - MY_CS_BINSORT, MYF(0)))) - charset= &my_charset_bin; + if (!(attr.charset= get_charset_by_csname(share->table_charset->csname, + MY_CS_BINSORT, MYF(0)))) + attr.charset= &my_charset_bin; } - else - charset= &my_charset_bin; } else - charset= share->table_charset; + attr.charset= share->table_charset; bzero((char*) &comment, sizeof(comment)); + if ((!(handler= old_frm_type_handler(attr.pack_flag, interval_nr)))) + goto err; // Not supported field type } /* Remove >32 decimals from old files */ if (share->mysql_version < 100200) - pack_flag&= ~FIELDFLAG_LONG_DECIMAL; + attr.pack_flag&= ~FIELDFLAG_LONG_DECIMAL; - if (interval_nr && charset->mbminlen > 1) + if (interval_nr && attr.charset->mbminlen > 1) { /* Unescape UCS2 intervals from HEX notation */ TYPELIB *interval= share->intervals + interval_nr - 1; @@ -1975,17 +2017,18 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } #ifndef TO_BE_DELETED_ON_PRODUCTION - if (field_type == MYSQL_TYPE_NEWDECIMAL && !share->mysql_version) + if (handler->real_field_type() == MYSQL_TYPE_NEWDECIMAL && + !share->mysql_version) { /* Fix pack length of old decimal values from 5.0.3 -> 5.0.4 The difference is that in the old version we stored precision in the .frm table while we now store the display_length */ - uint decimals= f_decimals(pack_flag); - field_length= my_decimal_precision_to_length(field_length, - decimals, - f_is_dec(pack_flag) == 0); + uint decimals= f_decimals(attr.pack_flag); + attr.length= + my_decimal_precision_to_length((uint) attr.length, decimals, + f_is_dec(attr.pack_flag) == 0); sql_print_error("Found incompatible DECIMAL field '%s' in %s; " "Please do \"ALTER TABLE '%s' FORCE\" to fix it!", share->fieldnames.type_names[i], share->table_name.str, @@ -2016,7 +2059,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (flags & VERS_SYSTEM_FIELD) { - switch (field_type) + switch (handler->real_field_type()) { case MYSQL_TYPE_TIMESTAMP2: case MYSQL_TYPE_DATETIME2: @@ -2038,22 +2081,17 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } /* Convert pre-10.2.2 timestamps to use Field::default_value */ - unireg_check= (Field::utype) MTYP_TYPENR(unireg_type); name.str= fieldnames.type_names[i]; name.length= strlen(name.str); - if (!(handler= Type_handler::get_handler_by_real_type(field_type))) - goto err; // Not supported field type + attr.interval= interval_nr ? share->intervals + interval_nr - 1 : NULL; + Record_addr addr(record + recpos, null_pos, null_bit_pos); *field_ptr= reg_field= - make_field(share, &share->mem_root, record+recpos, (uint32) field_length, - null_pos, null_bit_pos, pack_flag, handler, charset, - geom_type, srid, unireg_check, - (interval_nr ? share->intervals+interval_nr-1 : NULL), - &name, flags); + attr.make_field(share, &share->mem_root, &addr, handler, &name, flags); if (!reg_field) // Not supported field type goto err; - if (unireg_check == Field::TIMESTAMP_DNUN_FIELD || - unireg_check == Field::TIMESTAMP_DN_FIELD) + if (attr.unireg_check == Field::TIMESTAMP_DNUN_FIELD || + attr.unireg_check == Field::TIMESTAMP_DN_FIELD) { reg_field->default_value= new (&share->mem_root) Virtual_column_info(); reg_field->default_value->set_vcol_type(VCOL_DEFAULT); @@ -2077,10 +2115,11 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, status_var_increment(thd->status_var.feature_invisible_columns); if (!reg_field->invisible) share->visible_fields++; - if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag)) + if (handler->real_field_type() == MYSQL_TYPE_BIT && + !f_bit_as_char(attr.pack_flag)) { null_bits_are_used= 1; - if ((null_bit_pos+= field_length & 7) > 7) + if ((null_bit_pos+= (uint) (attr.length & 7)) > 7) { null_pos++; null_bit_pos-= 8; @@ -2103,7 +2142,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } } - if (f_no_default(pack_flag)) + if (f_no_default(attr.pack_flag)) reg_field->flags|= NO_DEFAULT_VALUE_FLAG; if (reg_field->unireg_check == Field::NEXT_NUMBER) @@ -2695,7 +2734,7 @@ static bool sql_unusable_for_discovery(THD *thd, handlerton *engine, if (lex->create_info.like()) return 1; // ... create select - if (lex->select_lex.item_list.elements) + if (lex->first_select_lex()->item_list.elements) return 1; // ... temporary if (create_info->tmp_table()) @@ -2884,7 +2923,7 @@ bool fix_session_vcol_expr(THD *thd, Virtual_column_info *vcol) DBUG_RETURN(0); vcol->expr->walk(&Item::cleanup_excluding_fields_processor, 0, 0); - DBUG_ASSERT(!vcol->expr->fixed); + DBUG_ASSERT(!vcol->expr->is_fixed()); DBUG_RETURN(fix_vcol_expr(thd, vcol)); } @@ -2939,7 +2978,7 @@ static bool fix_and_check_vcol_expr(THD *thd, TABLE *table, DBUG_PRINT("info", ("vcol: %p", vcol)); DBUG_ASSERT(func_expr); - if (func_expr->fixed) + if (func_expr->is_fixed()) DBUG_RETURN(0); // nothing to do if (fix_vcol_expr(thd, vcol)) @@ -2983,7 +3022,7 @@ static bool fix_and_check_vcol_expr(THD *thd, TABLE *table, of the statement because the field item does not have a field pointer at that time */ - myf warn= table->s->frm_version < FRM_VER_EXPRESSSIONS ? ME_JUST_WARNING : 0; + myf warn= table->s->frm_version < FRM_VER_EXPRESSSIONS ? ME_WARNING : 0; my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(warn), "AUTO_INCREMENT", vcol->get_vcol_type_name(), res.name); if (!warn) @@ -3440,17 +3479,6 @@ partititon_err: (my_bitmap_map*) bitmaps, share->fields, FALSE); bitmaps+= bitmap_size; - /* Don't allocate vcol_bitmap if we don't need it */ - if (share->virtual_fields) - { - if (!(outparam->def_vcol_set= (MY_BITMAP*) - alloc_root(&outparam->mem_root, sizeof(*outparam->def_vcol_set)))) - goto err; - my_bitmap_init(outparam->def_vcol_set, - (my_bitmap_map*) bitmaps, share->fields, FALSE); - bitmaps+= bitmap_size; - } - my_bitmap_init(&outparam->has_value_set, (my_bitmap_map*) bitmaps, share->fields, FALSE); bitmaps+= bitmap_size; @@ -3531,6 +3559,8 @@ partititon_err: share->no_replicate= TRUE; if (outparam->file->table_cache_type() & HA_CACHE_TBL_NOCACHE) share->not_usable_by_query_cache= TRUE; + if (outparam->file->ha_table_flags() & HA_CAN_ONLINE_BACKUPS) + share->online_backup= 1; } if (share->no_replicate || !binlog_filter->db_ok(share->db.str)) @@ -3653,7 +3683,7 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error, int db_errno) { char buff[FN_REFLEN]; - const myf errortype= ME_ERROR+ME_WAITTANG; // Write fatals error to log + const myf errortype= ME_ERROR_LOG; // Write fatals error to log DBUG_ENTER("open_table_error"); DBUG_PRINT("info", ("error: %d db_errno: %d", error, db_errno)); @@ -4910,7 +4940,7 @@ bool TABLE_LIST::prep_where(THD *thd, Item **conds, if (where) { - if (where->fixed) + if (where->is_fixed()) where->update_used_tables(); else if (where->fix_fields(thd, &where)) DBUG_RETURN(TRUE); @@ -4970,13 +5000,13 @@ bool TABLE_LIST::single_table_updatable() { if (!updatable) return false; - if (view && view->select_lex.table_list.elements == 1) + if (view && view->first_select_lex()->table_list.elements == 1) { /* We need to check deeply only single table views. Multi-table views will be turned to multi-table updates and then checked by leaf tables */ - return (((TABLE_LIST *)view->select_lex.table_list.first)-> + return (((TABLE_LIST *)view->first_select_lex()->table_list.first)-> single_table_updatable()); } return true; @@ -5013,7 +5043,8 @@ merge_on_conds(THD *thd, TABLE_LIST *table, bool is_cascaded) cond= table->on_expr->copy_andor_structure(thd); if (!table->view) DBUG_RETURN(cond); - for (TABLE_LIST *tbl= (TABLE_LIST*)table->view->select_lex.table_list.first; + for (TABLE_LIST *tbl= + (TABLE_LIST*)table->view->first_select_lex()->table_list.first; tbl; tbl= tbl->next_local) { @@ -5055,7 +5086,7 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type) { DBUG_ENTER("TABLE_LIST::prep_check_option"); bool is_cascaded= check_opt_type == VIEW_CHECK_CASCADED; - TABLE_LIST *merge_underlying_list= view->select_lex.get_table_list(); + TABLE_LIST *merge_underlying_list= view->first_select_lex()->get_table_list(); for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) { /* see comment of check_opt_type parameter */ @@ -5173,7 +5204,7 @@ TABLE_LIST *TABLE_LIST::find_underlying_table(TABLE *table_to_find) if (!view) return 0; - for (TABLE_LIST *tbl= view->select_lex.get_table_list(); + for (TABLE_LIST *tbl= view->first_select_lex()->get_table_list(); tbl; tbl= tbl->next_local) { @@ -5235,7 +5266,7 @@ int TABLE_LIST::view_check_option(THD *thd, bool ignore_failure) main_view->db.str); const char *name_table= (main_view->view ? main_view->view_name.str : main_view->table_name.str); - my_error(ER_VIEW_CHECK_FAILED, MYF(ignore_failure ? ME_JUST_WARNING : 0), + my_error(ER_VIEW_CHECK_FAILED, MYF(ignore_failure ? ME_WARNING : 0), name_db, name_table); return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR; } @@ -5279,7 +5310,7 @@ int TABLE::verify_constraints(bool ignore_failure) } field_error.append((*chk)->name.str); my_error(ER_CONSTRAINT_FAILED, - MYF(ignore_failure ? ME_JUST_WARNING : 0), field_error.c_ptr(), + MYF(ignore_failure ? ME_WARNING : 0), field_error.c_ptr(), s->db.str, s->error_table_name()); return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR; } @@ -5371,7 +5402,8 @@ bool TABLE_LIST::set_insert_values(MEM_ROOT *mem_root) { DBUG_PRINT("info", ("setting insert_value for view")); DBUG_ASSERT(is_view_or_derived() && is_merged_derived()); - for (TABLE_LIST *tbl= (TABLE_LIST*)view->select_lex.table_list.first; + for (TABLE_LIST *tbl= + (TABLE_LIST*)view->first_select_lex()->table_list.first; tbl; tbl= tbl->next_local) if (tbl->set_insert_values(mem_root)) @@ -5538,7 +5570,7 @@ void TABLE_LIST::register_want_access(ulong want_access) } if (!view) return; - for (TABLE_LIST *tbl= view->select_lex.get_table_list(); + for (TABLE_LIST *tbl= view->first_select_lex()->get_table_list(); tbl; tbl= tbl->next_local) tbl->register_want_access(want_access); @@ -5730,6 +5762,7 @@ void TABLE_LIST::set_check_materialized() The subtree should be already excluded */ DBUG_ASSERT(!derived->first_select()->first_inner_unit() || + derived->first_select()->first_inner_unit()->with_element || derived->first_select()->first_inner_unit()->first_select()-> exclude_from_table_unique_test); } @@ -5746,14 +5779,14 @@ TABLE *TABLE_LIST::get_real_join_table() break; /* we do not support merging of union yet */ DBUG_ASSERT(tbl->view == NULL || - tbl->view->select_lex.next_select() == NULL); + tbl->view->first_select_lex()->next_select() == NULL); DBUG_ASSERT(tbl->derived == NULL || tbl->derived->first_select()->next_select() == NULL); { List_iterator_fast<TABLE_LIST> ti(tbl->view != NULL ? - tbl->view->select_lex.top_join_list : + tbl->view->first_select_lex()->top_join_list : tbl->derived->first_select()->top_join_list); for (;;) { @@ -5924,7 +5957,7 @@ Item *Field_iterator_view::create_item(THD *thd) Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, LEX_CSTRING *name) { - bool save_wrapper= thd->lex->select_lex.no_wrap_view_item; + bool save_wrapper= thd->lex->first_select_lex()->no_wrap_view_item; Item *field= *field_ref; DBUG_ENTER("create_view_field"); @@ -5935,13 +5968,13 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, ('mysql_schema_table' function). So we can return directly the field. This case happens only for 'show & where' commands. */ - DBUG_ASSERT(field && field->fixed); + DBUG_ASSERT(field && field->is_fixed()); DBUG_RETURN(field); } DBUG_ASSERT(field); thd->lex->current_select->no_wrap_view_item= TRUE; - if (!field->fixed) + if (!field->is_fixed()) { if (field->fix_fields(thd, field_ref)) { @@ -5955,8 +5988,9 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, { DBUG_RETURN(field); } - Name_resolution_context *context= view->view ? &view->view->select_lex.context : - &thd->lex->select_lex.context; + Name_resolution_context *context= (view->view ? + &view->view->first_select_lex()->context: + &thd->lex->first_select_lex()->context); Item *item= (new (thd->mem_root) Item_direct_view_ref(thd, context, field_ref, view->alias.str, name, view)); @@ -6279,13 +6313,12 @@ void TABLE::clear_column_bitmaps() Reset column read/write usage. It's identical to: bitmap_clear_all(&table->def_read_set); bitmap_clear_all(&table->def_write_set); - if (s->virtual_fields) bitmap_clear_all(table->def_vcol_set); The code assumes that the bitmaps are allocated after each other, as guaranteed by open_table_from_share() */ bzero((char*) def_read_set.bitmap, s->column_bitmap_size * (s->virtual_fields ? 3 : 2)); - column_bitmaps_set(&def_read_set, &def_write_set, def_vcol_set); + column_bitmaps_set(&def_read_set, &def_write_set); rpl_write_set= 0; // Safety } @@ -6432,13 +6465,8 @@ void TABLE::mark_columns_needed_for_delete() Field **reg_field; for (reg_field= field ; *reg_field ; reg_field++) { - Field *cur_field= *reg_field; - if (cur_field->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) - { - bitmap_set_bit(read_set, cur_field->field_index); - if (cur_field->vcol_info) - bitmap_set_bit(vcol_set, cur_field->field_index); - } + if ((*reg_field)->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) + mark_column_with_deps(*reg_field); } need_signal= true; } @@ -6517,13 +6545,7 @@ void TABLE::mark_columns_needed_for_update() if (any_written && !all_read) { for (KEY_PART_INFO *kp= k->key_part; kp < kpend; kp++) - { - int idx= kp->fieldnr - 1; - if (bitmap_fast_test_and_set(read_set, idx)) - continue; - if (field[idx]->vcol_info) - mark_virtual_col(field[idx]); - } + mark_column_with_deps(field[kp->fieldnr - 1]); } } need_signal= true; @@ -6720,49 +6742,12 @@ void TABLE::mark_columns_per_binlog_row_image() DBUG_ASSERT(FALSE); } } - /* - We have to ensure that all virtual columns that are part of read set - are calculated. - */ - if (vcol_set) - bitmap_union(vcol_set, read_set); file->column_bitmaps_signal(); } DBUG_VOID_RETURN; } -/* - @brief Mark a column as virtual used by the query - - @param field the field for the column to be marked - - @details - The function marks the column for 'field' as virtual (computed) - in the bitmap vcol_set. - If the column is marked for the first time the expression to compute - the column is traversed and all columns that are occurred there are - marked in the read_set of the table. - - @retval - TRUE if column is marked for the first time - @retval - FALSE otherwise -*/ - -bool TABLE::mark_virtual_col(Field *field) -{ - bool res; - DBUG_ASSERT(field->vcol_info); - if (!(res= bitmap_fast_test_and_set(vcol_set, field->field_index))) - { - Item *vcol_item= field->vcol_info->expr; - DBUG_ASSERT(vcol_item); - vcol_item->walk(&Item::register_field_in_read_map, 1, 0); - } - return res; -} - /* @brief Mark virtual columns for update/insert commands @@ -6804,13 +6789,13 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl { tmp_vfield= *vfield_ptr; if (bitmap_is_set(write_set, tmp_vfield->field_index)) - bitmap_updated|= mark_virtual_col(tmp_vfield); + bitmap_updated|= mark_virtual_column_with_deps(tmp_vfield); else if (tmp_vfield->vcol_info->stored_in_db || (tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG | PART_INDIRECT_KEY_FLAG))) { bitmap_set_bit(write_set, tmp_vfield->field_index); - mark_virtual_col(tmp_vfield); + mark_virtual_column_with_deps(tmp_vfield); bitmap_updated= true; } } @@ -6941,8 +6926,6 @@ void TABLE::mark_columns_used_by_virtual_fields(void) void TABLE::mark_check_constraint_columns_for_read(void) { bitmap_union(read_set, s->check_set); - if (vcol_set) - bitmap_union(vcol_set, s->check_set); } @@ -7696,6 +7679,20 @@ public: } }; + +/* + to satisfy ASSERT_COLUMN_MARKED_FOR_WRITE Field's assert we temporarily + mark field for write before storing the generated value in it +*/ +#ifndef DBUG_OFF +#define DBUG_FIX_WRITE_SET(f) bool _write_set_fixed= !bitmap_fast_test_and_set(write_set, (f)->field_index) +#define DBUG_RESTORE_WRITE_SET(f) if (_write_set_fixed) bitmap_clear_bit(write_set, (f)->field_index) +#else +#define DBUG_FIX_WRITE_SET(f) +#define DBUG_RESTORE_WRITE_SET(f) +#endif + + /* @brief Compute values for virtual columns used in query @@ -7759,17 +7756,17 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) switch (update_mode) { case VCOL_UPDATE_FOR_READ: update= (!vcol_info->stored_in_db && - bitmap_is_set(vcol_set, vf->field_index)); + bitmap_is_set(read_set, vf->field_index)); swap_values= 1; break; case VCOL_UPDATE_FOR_DELETE: case VCOL_UPDATE_FOR_WRITE: - update= bitmap_is_set(vcol_set, vf->field_index); + update= bitmap_is_set(read_set, vf->field_index); break; case VCOL_UPDATE_FOR_REPLACE: update= ((!vcol_info->stored_in_db && (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) && - bitmap_is_set(vcol_set, vf->field_index)) || + bitmap_is_set(read_set, vf->field_index)) || update_all_columns); if (update && (vf->flags & BLOB_FLAG)) { @@ -7789,7 +7786,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) /* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */ update= (!vcol_info->stored_in_db && (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) && - !bitmap_is_set(vcol_set, vf->field_index)); + !bitmap_is_set(read_set, vf->field_index)); swap_values= 1; break; } @@ -7798,8 +7795,10 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode) { int field_error __attribute__((unused)) = 0; /* Compute the actual value of the virtual fields */ + DBUG_FIX_WRITE_SET(vf); if (vcol_info->expr->save_in_field(vf, 0)) field_error= error= 1; + DBUG_RESTORE_WRITE_SET(vf); DBUG_PRINT("info", ("field '%s' - updated error: %d", vf->field_name.str, field_error)); if (swap_values && (vf->flags & BLOB_FLAG)) @@ -7833,7 +7832,9 @@ int TABLE::update_virtual_field(Field *vf) in_use->set_n_backup_active_arena(expr_arena, &backup_arena); bitmap_clear_all(&tmp_set); vf->vcol_info->expr->walk(&Item::update_vcol_processor, 0, &tmp_set); + DBUG_FIX_WRITE_SET(vf); vf->vcol_info->expr->save_in_field(vf, 0); + DBUG_RESTORE_WRITE_SET(vf); in_use->restore_active_arena(expr_arena, &backup_arena); DBUG_RETURN(in_use->is_error()); } @@ -8498,200 +8499,6 @@ double KEY::actual_rec_per_key(uint i) } -/** - @brief - Mark subformulas of a condition unusable for the condition pushed into table - - @param cond The condition whose subformulas are to be marked - - @details - This method recursively traverses the AND-OR condition cond and for each subformula - of the codition it checks whether it can be usable for the extraction of a condition - that can be pushed into this table. The subformulas that are not usable are - marked with the flag NO_EXTRACTION_FL. - @note - This method is called before any call of TABLE_LIST::build_pushable_cond_for_table. - The flag NO_EXTRACTION_FL set in a subformula allows to avoid building clone - for the subformula when extracting the pushable condition. -*/ - -void TABLE_LIST::check_pushable_cond_for_table(Item *cond) -{ - table_map tab_map= table->map; - cond->clear_extraction_flag(); - if (cond->type() == Item::COND_ITEM) - { - bool and_cond= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC; - List_iterator<Item> li(*((Item_cond*) cond)->argument_list()); - uint count= 0; - Item *item; - while ((item=li++)) - { - check_pushable_cond_for_table(item); - if (item->get_extraction_flag() != NO_EXTRACTION_FL) - count++; - else if (!and_cond) - break; - } - if ((and_cond && count == 0) || item) - { - cond->set_extraction_flag(NO_EXTRACTION_FL); - if (and_cond) - li.rewind(); - while ((item= li++)) - item->clear_extraction_flag(); - } - } - else if (!cond->excl_dep_on_table(tab_map)) - cond->set_extraction_flag(NO_EXTRACTION_FL); -} - - -/** - @brief - Build condition extractable from the given one depended only on this table - - @param thd The thread handle - @param cond The condition from which the pushable one is to be extracted - - @details - For the given condition cond this method finds out what condition depended - only on this table can be extracted from cond. If such condition C exists - the method builds the item for it. - The method uses the flag NO_EXTRACTION_FL set by the preliminary call of - the method TABLE_LIST::check_pushable_cond_for_table to figure out whether - a subformula depends only on this table or not. - @note - The built condition C is always implied by the condition cond - (cond => C). The method tries to build the most restictive such - condition (i.e. for any other condition C' such that cond => C' - we have C => C'). - @note - The build item is not ready for usage: substitution for the field items - has to be done and it has to be re-fixed. - - @retval - the built condition pushable into this table if such a condition exists - NULL if there is no such a condition -*/ - -Item* TABLE_LIST::build_pushable_cond_for_table(THD *thd, Item *cond) -{ - table_map tab_map= table->map; - bool is_multiple_equality= cond->type() == Item::FUNC_ITEM && - ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC; - if (cond->get_extraction_flag() == NO_EXTRACTION_FL) - return 0; - if (cond->type() == Item::COND_ITEM) - { - bool cond_and= false; - Item_cond *new_cond; - if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) - { - cond_and= true; - new_cond=new (thd->mem_root) Item_cond_and(thd); - } - else - new_cond= new (thd->mem_root) Item_cond_or(thd); - if (!new_cond) - return 0; - List_iterator<Item> li(*((Item_cond*) cond)->argument_list()); - Item *item; - bool is_fix_needed= false; - while ((item=li++)) - { - if (item->get_extraction_flag() == NO_EXTRACTION_FL) - { - if (!cond_and) - return 0; - continue; - } - Item *fix= build_pushable_cond_for_table(thd, item); - if (!fix && !cond_and) - return 0; - if (!fix) - continue; - - if (fix->type() == Item::COND_ITEM && - ((Item_cond*) fix)->functype() == Item_func::COND_AND_FUNC) - is_fix_needed= true; - - new_cond->argument_list()->push_back(fix, thd->mem_root); - } - if (is_fix_needed && new_cond->fix_fields(thd, 0)) - return 0; - - switch (new_cond->argument_list()->elements) - { - case 0: - return 0; - case 1: - return new_cond->argument_list()->head(); - default: - return new_cond; - } - } - else if (is_multiple_equality) - { - if (!(cond->used_tables() & tab_map)) - return 0; - Item *new_cond= NULL; - int i= 0; - Item_equal *item_equal= (Item_equal *) cond; - Item *left_item = item_equal->get_const(); - Item_equal_fields_iterator it(*item_equal); - Item *item; - if (!left_item) - { - while ((item=it++)) - if (item->used_tables() == tab_map) - { - left_item= item; - break; - } - } - if (!left_item) - return 0; - while ((item=it++)) - { - if (!(item->used_tables() == tab_map)) - continue; - Item_func_eq *eq= 0; - Item *left_item_clone= left_item->build_clone(thd); - Item *right_item_clone= item->build_clone(thd); - if (left_item_clone && right_item_clone) - { - left_item_clone->set_item_equal(NULL); - right_item_clone->set_item_equal(NULL); - eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone, - left_item_clone); - } - if (eq) - { - i++; - switch (i) - { - case 1: - new_cond= eq; - break; - case 2: - new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq); - break; - default: - ((Item_cond_and*)new_cond)->argument_list()->push_back(eq, - thd->mem_root); - } - } - } - if (new_cond) - new_cond->fix_fields(thd, &new_cond); - return new_cond; - } - else if (cond->get_extraction_flag() != NO_EXTRACTION_FL) - return cond->build_clone(thd); - return 0; -} - LEX_CSTRING *fk_option_name(enum_fk_option opt) { static LEX_CSTRING names[]= @@ -8779,7 +8586,7 @@ bool TR_table::update(ulonglong start_id, ulonglong end_id) store(FLD_BEGIN_TS, thd->transaction_time()); thd->set_time(); - timeval end_time= {thd->query_start(), long(thd->query_start_sec_part())}; + timeval end_time= {thd->query_start(), int(thd->query_start_sec_part())}; store(FLD_TRX_ID, start_id); store(FLD_COMMIT_ID, end_id); store(FLD_COMMIT_TS, end_time); @@ -8800,7 +8607,7 @@ bool TR_table::query(ulonglong trx_id) READ_RECORD info; int error; List<TABLE_LIST> dummy; - SELECT_LEX &slex= thd->lex->select_lex; + SELECT_LEX &slex= *(thd->lex->first_select_lex()); Name_resolution_context_backup backup(slex.context, *this); Item *field= newx Item_field(thd, &slex.context, (*this)[FLD_TRX_ID]); Item *value= newx Item_int(thd, trx_id); @@ -8830,7 +8637,7 @@ bool TR_table::query(MYSQL_TIME &commit_time, bool backwards) READ_RECORD info; int error; List<TABLE_LIST> dummy; - SELECT_LEX &slex= thd->lex->select_lex; + SELECT_LEX &slex= *(thd->lex->first_select_lex()); Name_resolution_context_backup backup(slex.context, *this); Item *field= newx Item_field(thd, &slex.context, (*this)[FLD_COMMIT_TS]); Item *value= newx Item_datetime_literal(thd, &commit_time, 6); @@ -8860,7 +8667,7 @@ bool TR_table::query(MYSQL_TIME &commit_time, bool backwards) if (res > 0) { MYSQL_TIME commit_ts; - if ((*this)[FLD_COMMIT_TS]->get_date(&commit_ts, 0)) + if ((*this)[FLD_COMMIT_TS]->get_date(&commit_ts, date_mode_t(0))) { found= false; break; @@ -9079,7 +8886,8 @@ bool Vers_history_point::resolve_unit(THD *thd) return false; if (item->fix_fields_if_needed(thd, &item)) return true; - return item->this_item()->type_handler_for_system_time()-> + return item->this_item()->real_type_handler()-> + type_handler_for_system_time()-> Vers_history_point_resolve_unit(thd, this); } diff --git a/sql/table.h b/sql/table.h index 7236fb91b0f..1720a212a1f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -395,28 +395,6 @@ enum enum_table_category TABLE_CATEGORY_SYSTEM=3, /** - Information schema tables. - These tables are an interface provided by the system - to inspect the system metadata. - These tables do *not* honor: - - LOCK TABLE t FOR READ/WRITE - - FLUSH TABLES WITH READ LOCK - - SET GLOBAL READ_ONLY = ON - as there is no point in locking explicitly - an INFORMATION_SCHEMA table. - Nothing is directly written to information schema tables. - Note that this value is not used currently, - since information schema tables are not shared, - but implemented as session specific temporary tables. - */ - /* - TODO: Fixing the performance issues of I_S will lead - to I_S tables in the table cache, which should use - this table type. - */ - TABLE_CATEGORY_INFORMATION=4, - - /** Log tables. These tables are an interface provided by the system to inspect the system logs. @@ -436,7 +414,33 @@ enum enum_table_category The server implementation perform writes. Log tables are cached in the table cache. */ - TABLE_CATEGORY_LOG=5, + TABLE_CATEGORY_LOG=4, + + /* + Types below are read only tables, not affected by FLUSH TABLES or + MDL locks. + */ + /** + Information schema tables. + These tables are an interface provided by the system + to inspect the system metadata. + These tables do *not* honor: + - LOCK TABLE t FOR READ/WRITE + - FLUSH TABLES WITH READ LOCK + - SET GLOBAL READ_ONLY = ON + as there is no point in locking explicitly + an INFORMATION_SCHEMA table. + Nothing is directly written to information schema tables. + Note that this value is not used currently, + since information schema tables are not shared, + but implemented as session specific temporary tables. + */ + /* + TODO: Fixing the performance issues of I_S will lead + to I_S tables in the table cache, which should use + this table type. + */ + TABLE_CATEGORY_INFORMATION=5, /** Performance schema tables. @@ -460,6 +464,7 @@ enum enum_table_category */ TABLE_CATEGORY_PERFORMANCE=6 }; + typedef enum enum_table_category TABLE_CATEGORY; TABLE_CATEGORY get_table_category(const LEX_CSTRING *db, @@ -727,6 +732,7 @@ struct TABLE_SHARE bool null_field_first; bool system; /* Set if system table (one record) */ bool not_usable_by_query_cache; + bool online_backup; /* Set if on-line backup supported */ bool no_replicate; bool crashed; bool is_view; @@ -1155,8 +1161,6 @@ public: MY_BITMAP cond_set; /* used to mark fields from sargable conditions*/ /* Active column sets */ MY_BITMAP *read_set, *write_set, *rpl_write_set; - /* Set if using virtual fields */ - MY_BITMAP *vcol_set, *def_vcol_set; /* On INSERT: fields that the user specified a value for */ MY_BITMAP has_value_set; @@ -1377,7 +1381,9 @@ public: void mark_columns_needed_for_delete(void); void mark_columns_needed_for_insert(void); void mark_columns_per_binlog_row_image(void); - bool mark_virtual_col(Field *field); + inline bool mark_column_with_deps(Field *field); + inline bool mark_virtual_column_with_deps(Field *field); + inline void mark_virtual_column_deps(Field *field); bool mark_virtual_columns_for_write(bool insert_fl); bool check_virtual_columns_marked_for_read(); bool check_virtual_columns_marked_for_write(); @@ -1399,39 +1405,21 @@ public: if (file) file->column_bitmaps_signal(); } - inline void column_bitmaps_set(MY_BITMAP *read_set_arg, - MY_BITMAP *write_set_arg, - MY_BITMAP *vcol_set_arg) - { - read_set= read_set_arg; - write_set= write_set_arg; - vcol_set= vcol_set_arg; - if (file) - file->column_bitmaps_signal(); - } inline void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg, MY_BITMAP *write_set_arg) { read_set= read_set_arg; write_set= write_set_arg; } - inline void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg, - MY_BITMAP *write_set_arg, - MY_BITMAP *vcol_set_arg) - { - read_set= read_set_arg; - write_set= write_set_arg; - vcol_set= vcol_set_arg; - } inline void use_all_columns() { column_bitmaps_set(&s->all_set, &s->all_set); } + inline void use_all_stored_columns(); inline void default_column_bitmaps() { read_set= &def_read_set; write_set= &def_write_set; - vcol_set= def_vcol_set; /* Note that this may be 0 */ rpl_write_set= 0; } /** Should this instance of the table be reopened? */ @@ -2611,8 +2599,6 @@ struct TABLE_LIST return false; } void set_lock_type(THD* thd, enum thr_lock_type lock); - void check_pushable_cond_for_table(Item *cond); - Item *build_pushable_cond_for_table(THD *thd, Item *cond); void remove_join_columns() { @@ -2966,7 +2952,7 @@ extern LEX_CSTRING INFORMATION_SCHEMA_NAME; extern LEX_CSTRING MYSQL_SCHEMA_NAME; /* table names */ -extern LEX_CSTRING MYSQL_USER_NAME, MYSQL_DB_NAME, MYSQL_PROC_NAME; +extern LEX_CSTRING MYSQL_PROC_NAME; inline bool is_infoschema_db(const LEX_CSTRING *name) { diff --git a/sql/table_cache.cc b/sql/table_cache.cc index cb9583a2440..c23bb53b9a9 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -232,7 +232,7 @@ static void intern_close_table(TABLE *table) uint tc_records(void) { ulong total= 0; - for (ulong i= 0; i < tc_instances; i++) + for (uint32 i= 0; i < tc_instances; i++) { mysql_mutex_lock(&tc[i].LOCK_table_cache); total+= tc[i].records; @@ -277,7 +277,7 @@ static void tc_remove_all_unused_tables(TDC_element *element, */ if (mark_flushed) element->flushed= true; - for (ulong i= 0; i < tc_instances; i++) + for (uint32 i= 0; i < tc_instances; i++) { mysql_mutex_lock(&tc[i].LOCK_table_cache); while ((table= element->free_tables[i].list.pop_front())) @@ -406,7 +406,7 @@ void tc_add_table(THD *thd, TABLE *table) @return TABLE object, or NULL if no unused objects. */ -static TABLE *tc_acquire_table(THD *thd, TDC_element *element) +TABLE *tc_acquire_table(THD *thd, TDC_element *element) { uint32 n_instances= my_atomic_load32_explicit((int32*) &tc_active_instances, @@ -491,7 +491,7 @@ static void tdc_assert_clean_share(TDC_element *element) DBUG_ASSERT(element->m_flush_tickets.is_empty()); DBUG_ASSERT(element->all_tables.is_empty()); #ifndef DBUG_OFF - for (ulong i= 0; i < tc_instances; i++) + for (uint32 i= 0; i < tc_instances; i++) DBUG_ASSERT(element->free_tables[i].list.is_empty()); #endif DBUG_ASSERT(element->all_tables_refs == 0); @@ -564,7 +564,7 @@ static void lf_alloc_constructor(uchar *arg) mysql_cond_init(key_TABLE_SHARE_COND_release, &element->COND_release, 0); element->m_flush_tickets.empty(); element->all_tables.empty(); - for (ulong i= 0; i < tc_instances; i++) + for (uint32 i= 0; i < tc_instances; i++) element->free_tables[i].list.empty(); element->all_tables_refs= 0; element->share= 0; @@ -645,7 +645,7 @@ bool tdc_init(void) void tdc_start_shutdown(void) { - DBUG_ENTER("table_def_start_shutdown"); + DBUG_ENTER("tdc_start_shutdown"); if (tdc_inited) { /* @@ -657,7 +657,7 @@ void tdc_start_shutdown(void) tdc_size= 0; tc_size= 0; /* Free all cached but unused TABLEs and TABLE_SHAREs. */ - close_cached_tables(NULL, NULL, FALSE, LONG_TIMEOUT); + purge_tables(true); } DBUG_VOID_RETURN; } @@ -1094,6 +1094,7 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, TABLE *table; TDC_element *element; uint my_refs= 1; + bool res= false; DBUG_ENTER("tdc_remove_table"); DBUG_PRINT("enter",("name: %s remove_type: %d", table_name, remove_type)); @@ -1101,7 +1102,6 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name, MDL_EXCLUSIVE)); - mysql_mutex_lock(&LOCK_unused_shares); if (!(element= tdc_lock_share(thd, db, table_name))) { @@ -1123,7 +1123,7 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, mysql_mutex_unlock(&LOCK_unused_shares); tdc_delete_share_from_hash(element); - DBUG_RETURN(true); + DBUG_RETURN(false); } mysql_mutex_unlock(&LOCK_unused_shares); @@ -1189,10 +1189,16 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, #endif mysql_mutex_unlock(&element->LOCK_table_share); } + else + { + mysql_mutex_lock(&element->LOCK_table_share); + res= element->ref_count > 1; + mysql_mutex_unlock(&element->LOCK_table_share); + } tdc_release_share(element->share); - DBUG_RETURN(true); + DBUG_RETURN(res); } diff --git a/sql/table_cache.h b/sql/table_cache.h index b41665258c9..148edc84223 100644 --- a/sql/table_cache.h +++ b/sql/table_cache.h @@ -88,7 +88,6 @@ extern bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, const char *db, const char *table_name, bool kill_delayed_threads); - extern int tdc_wait_for_old_version(THD *thd, const char *db, const char *table_name, ulong wait_timeout, uint deadlock_weight, @@ -102,6 +101,7 @@ extern uint tc_records(void); extern void tc_purge(bool mark_flushed= false); extern void tc_add_table(THD *thd, TABLE *table); extern void tc_release_table(TABLE *table); +extern TABLE *tc_acquire_table(THD *thd, TDC_element *element); /** Create a table cache key for non-temporary table. diff --git a/sql/threadpool_win.cc b/sql/threadpool_win.cc index 0cc683c631d..67a8e783208 100644 --- a/sql/threadpool_win.cc +++ b/sql/threadpool_win.cc @@ -70,12 +70,16 @@ static DWORD fls; static bool skip_completion_port_on_success = false; +PTP_CALLBACK_ENVIRON get_threadpool_win_callback_environ() +{ + return pool? &callback_environ: 0; +} + /* Threadpool callbacks. io_completion_callback - handle client request timer_callback - handle wait timeout (kill connection) - shm_read_callback, shm_close_callback - shared memory stuff login_callback - user login (submitted as threadpool work) */ @@ -89,9 +93,6 @@ static void CALLBACK io_completion_callback(PTP_CALLBACK_INSTANCE instance, static void CALLBACK work_callback(PTP_CALLBACK_INSTANCE instance, PVOID context, PTP_WORK work); -static void CALLBACK shm_read_callback(PTP_CALLBACK_INSTANCE instance, - PVOID Context, PTP_WAIT wait,TP_WAIT_RESULT wait_result); - static void pre_callback(PVOID context, PTP_CALLBACK_INSTANCE instance); /* Get current time as Windows time */ @@ -120,7 +121,6 @@ public: PTP_CALLBACK_INSTANCE callback_instance; PTP_IO io; PTP_TIMER timer; - PTP_WAIT shm_read; PTP_WORK work; bool long_callback; @@ -139,7 +139,15 @@ struct TP_connection *new_TP_connection(CONNECT *connect) void TP_pool_win::add(TP_connection *c) { - SubmitThreadpoolWork(((TP_connection_win *)c)->work); + if(FlsGetValue(fls)) + { + /* Inside threadpool(), execute callback directly. */ + tp_callback(c); + } + else + { + SubmitThreadpoolWork(((TP_connection_win *)c)->work); + } } @@ -149,7 +157,6 @@ TP_connection_win::TP_connection_win(CONNECT *c) : callback_instance(0), io(0), timer(0), - shm_read(0), work(0) { } @@ -170,30 +177,20 @@ int TP_connection_win::init() case VIO_TYPE_NAMEDPIPE: handle= (HANDLE)vio->hPipe; break; - case VIO_TYPE_SHARED_MEMORY: - handle= vio->event_server_wrote; - break; default: abort(); } - if (vio_type == VIO_TYPE_SHARED_MEMORY) - { - CHECK_ALLOC_ERROR(shm_read= CreateThreadpoolWait(shm_read_callback, this, &callback_environ)); - } - else + + /* Performance tweaks (s. MSDN documentation)*/ + UCHAR flags= FILE_SKIP_SET_EVENT_ON_HANDLE; + if (skip_completion_port_on_success) { - /* Performance tweaks (s. MSDN documentation)*/ - UCHAR flags= FILE_SKIP_SET_EVENT_ON_HANDLE; - if (skip_completion_port_on_success) - { - flags |= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS; - } - (void)SetFileCompletionNotificationModes(handle, flags); - /* Assign io completion callback */ - CHECK_ALLOC_ERROR(io= CreateThreadpoolIo(handle, io_completion_callback, this, &callback_environ)); + flags |= FILE_SKIP_COMPLETION_PORT_ON_SUCCESS; } - + (void)SetFileCompletionNotificationModes(handle, flags); + /* Assign io completion callback */ + CHECK_ALLOC_ERROR(io= CreateThreadpoolIo(handle, io_completion_callback, this, &callback_environ)); CHECK_ALLOC_ERROR(timer= CreateThreadpoolTimer(timer_callback, this, &callback_environ)); CHECK_ALLOC_ERROR(work= CreateThreadpoolWork(work_callback, this, &callback_environ)); return 0; @@ -214,11 +211,6 @@ int TP_connection_win::start_io() DWORD last_error= 0; int retval; - if (shm_read) - { - SetThreadpoolWait(shm_read, handle, NULL); - return 0; - } StartThreadpoolIo(io); if (vio_type == VIO_TYPE_TCPIP || vio_type == VIO_TYPE_SSL) @@ -297,9 +289,6 @@ TP_connection_win::~TP_connection_win() if (io) CloseThreadpoolIo(io); - if (shm_read) - CloseThreadpoolWait(shm_read); - if (work) CloseThreadpoolWork(work); @@ -312,14 +301,13 @@ TP_connection_win::~TP_connection_win() void TP_connection_win::wait_begin(int type) { - /* Signal to the threadpool whenever callback can run long. Currently, binlog waits are a good candidate, its waits are really long */ if (type == THD_WAIT_BINLOG) { - if (!long_callback) + if (!long_callback && callback_instance) { CallbackMayRunLong(callback_instance); long_callback= true; @@ -332,12 +320,11 @@ void TP_connection_win::wait_end() /* Do we need to do anything ? */ } -/* - This function should be called first whenever a callback is invoked in the +/* + This function should be called first whenever a callback is invoked in the threadpool, does my_thread_init() if not yet done */ -extern ulong thread_created; -static void pre_callback(PVOID context, PTP_CALLBACK_INSTANCE instance) +void tp_win_callback_prolog() { if (FlsGetValue(fls) == NULL) { @@ -347,6 +334,12 @@ static void pre_callback(PVOID context, PTP_CALLBACK_INSTANCE instance) InterlockedIncrement((volatile long *)&tp_stats.num_worker_threads); my_thread_init(); } +} + +extern ulong thread_created; +static void pre_callback(PVOID context, PTP_CALLBACK_INSTANCE instance) +{ + tp_win_callback_prolog(); TP_connection_win *c = (TP_connection_win *)context; c->callback_instance = instance; c->long_callback = false; @@ -420,29 +413,6 @@ static VOID CALLBACK timer_callback(PTP_CALLBACK_INSTANCE instance, } } - -/* - Shared memory read callback. - Invoked when read event is set on connection. -*/ - -static void CALLBACK shm_read_callback(PTP_CALLBACK_INSTANCE instance, - PVOID context, PTP_WAIT wait,TP_WAIT_RESULT wait_result) -{ - TP_connection_win *c= (TP_connection_win *)context; - /* Disarm wait. */ - SetThreadpoolWait(wait, NULL, NULL); - - /* - This is an autoreset event, and one wakeup is eaten already by threadpool, - and the current state is "not set". Thus we need to reset the event again, - or vio_read will hang. - */ - SetEvent(c->handle); - tp_callback(instance, context); -} - - static void CALLBACK work_callback(PTP_CALLBACK_INSTANCE instance, PVOID context, PTP_WORK work) { tp_callback(instance, context); diff --git a/sql/transaction.cc b/sql/transaction.cc index 1c2820200d1..13614d36a73 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -963,7 +963,7 @@ bool trans_xa_commit(THD *thd) We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does. */ - mdl_request.init(MDL_key::COMMIT, "", "", MDL_INTENTION_EXCLUSIVE, + mdl_request.init(MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT, MDL_TRANSACTION); if (thd->mdl_context.acquire_lock(&mdl_request, diff --git a/sql/udf_example.c b/sql/udf_example.c index 6db2b5e737a..bdc995b51fc 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -173,6 +173,13 @@ void avgcost_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error void avgcost_clear( UDF_INIT* initid, char* is_null, char *error ); void avgcost_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); double avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +my_bool avg2_init( UDF_INIT* initid, UDF_ARGS* args, char* message ); +void avg2_deinit( UDF_INIT* initid ); +void avg2_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +void avg2_clear( UDF_INIT* initid, char* is_null, char *error ); +void avg2_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +void avg2_remove( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); +double avg2( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error ); my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message); char *is_const(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error); @@ -1049,6 +1056,138 @@ avgcost( UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)), return data->totalprice/(double)data->totalquantity; } + +/* +** Average 2 (number, sum)*/ +struct avg2_data +{ + ulonglong count; + double sum; +}; + + +my_bool +avg2_init( UDF_INIT* initid, UDF_ARGS* args, char* message ) +{ + struct avg2_data* data; + + if (args->arg_count != 2) + { + strcpy( + message, + "wrong number of arguments: AVG2() requires two arguments" + ); + return 1; + } + + if ((args->arg_type[0] != INT_RESULT) || (args->arg_type[1] != REAL_RESULT) ) + { + strcpy( + message, + "wrong argument type: AVG2() requires an INT and a REAL" + ); + return 1; + } + + /* + ** force arguments to double. + */ + /*args->arg_type[0] = REAL_RESULT; + args->arg_type[1] = REAL_RESULT;*/ + + initid->maybe_null = 0; /* The result may be null */ + initid->decimals = 4; /* We want 4 decimals in the result */ + initid->max_length = 20; /* 6 digits + . + 10 decimals */ + + if (!(data = (struct avg2_data*) malloc(sizeof(struct avg2_data)))) + { + strmov(message,"Couldn't allocate memory"); + return 1; + } + data->count = 0; + data->sum = 0.0; + + initid->ptr = (char*)data; + + return 0; +} + +void +avg2_deinit( UDF_INIT* initid ) +{ + free(initid->ptr); +} + + +/* This is only for MySQL 4.0 compability */ +void +avg2_reset(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message) +{ + avgcost_clear(initid, is_null, message); + avgcost_add(initid, args, is_null, message); +} + +/* This is needed to get things to work in MySQL 4.1.1 and above */ + +void +avg2_clear(UDF_INIT* initid, char* is_null __attribute__((unused)), + char* message __attribute__((unused))) +{ + struct avg2_data* data = (struct avg2_data*)initid->ptr; + data->sum= 0.0; + data->count= 0; +} + + +void +avg2_add(UDF_INIT* initid, UDF_ARGS* args, + char* is_null __attribute__((unused)), + char* message __attribute__((unused))) +{ + if (args->args[0] && args->args[1]) + { + struct avg2_data* data = (struct avg2_data*)initid->ptr; + longlong quantity = *((longlong*)args->args[0]); + double sum = *((double*)args->args[1]); + + data->count += quantity; + data->sum += sum; + } +} + + +void +avg2_remove(UDF_INIT* initid, UDF_ARGS* args, + char* is_null __attribute__((unused)), + char* message __attribute__((unused))) +{ + if (args->args[0] && args->args[1]) + { + struct avg2_data* data = (struct avg2_data*)initid->ptr; + longlong quantity = *((longlong*)args->args[0]); + double sum = *((double*)args->args[1]); + + data->count -= quantity; + data->sum -= sum; + } +} + + +double +avg2( UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)), + char* is_null, char* error __attribute__((unused))) +{ + struct avg2_data* data = (struct avg2_data*)initid->ptr; + if (!data->count) + { + *is_null = 1; + return 0.0; + } + + *is_null = 0; + return data->sum/(double)data->count; +} + my_bool myfunc_argument_name_init(UDF_INIT *initid, UDF_ARGS *args, char *message); char *myfunc_argument_name(UDF_INIT *initid, UDF_ARGS *args, char *result, diff --git a/sql/udf_example.def b/sql/udf_example.def index 74230b638bf..903c2b74893 100644 --- a/sql/udf_example.def +++ b/sql/udf_example.def @@ -23,6 +23,13 @@ EXPORTS avgcost_add avgcost_clear avgcost + avg2_init + avg2_deinit + avg2_reset + avg2_add + avg2_remove + avg2_clear + avg2 is_const is_const_init check_const_len diff --git a/sql/unireg.cc b/sql/unireg.cc index 6540e11578b..4692b2d74d1 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -897,32 +897,12 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields, while ((field=it++)) { uint recpos; - int2store(buff+3, field->length); /* The +1 is here becasue the col offset in .frm file have offset 1 */ recpos= field->offset+1 + (uint) data_offset; int3store(buff+5,recpos); - int2store(buff+8,field->pack_flag); - buff[10]= (uchar) field->unireg_check; buff[12]= (uchar) field->interval_id; - buff[13]= (uchar) field->real_field_type(); - if (field->real_field_type() == MYSQL_TYPE_GEOMETRY) - { - buff[11]= 0; - buff[14]= (uchar) field->geom_type; -#ifndef HAVE_SPATIAL - DBUG_ASSERT(0); // Should newer happen -#endif - } - else if (field->charset) - { - buff[11]= (uchar) (field->charset->number >> 8); - buff[14]= (uchar) field->charset->number; - } - else - { - buff[11]= buff[14]= 0; // Numerical - } - + buff[13]= (uchar) field->type_handler()->real_field_type(); + field->type_handler()->Column_definition_attributes_frm_pack(field, buff); int2store(buff+15, field->comment.length); comment_length+= field->comment.length; set_if_bigger(int_count,field->interval_id); @@ -1043,21 +1023,16 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values while ((field=it++)) { + Record_addr addr(buff + field->offset + data_offset, + null_pos + null_count / 8, null_count & 7); + Column_definition_attributes tmp(*field); + tmp.interval= field->save_interval ? + field->save_interval : field->interval; /* regfield don't have to be deleted as it's allocated on THD::mem_root */ - Field *regfield= make_field(&share, thd->mem_root, - buff+field->offset + data_offset, - (uint32)field->length, - null_pos + null_count / 8, - null_count & 7, - field->pack_flag, - field->type_handler(), - field->charset, - field->geom_type, field->srid, - field->unireg_check, - field->save_interval ? field->save_interval - : field->interval, - &field->field_name, - field->flags); + Field *regfield= tmp.make_field(&share, thd->mem_root, &addr, + field->type_handler(), + &field->field_name, + field->flags); if (!regfield) { error= 1; diff --git a/sql/unireg.h b/sql/unireg.h index 88d0c882824..6f224ab4894 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -56,11 +56,6 @@ #endif #define ER_THD_OR_DEFAULT(thd,X) ((thd) ? ER_THD(thd, (X)) : ER_DEFAULT(X)) - -#define ME_INFO (ME_HOLDTANG | ME_NOREFRESH) -#define ME_ERROR (ME_BELL | ME_NOREFRESH) -#define MYF_RW MYF(MY_WME+MY_NABP) /* Vid my_read & my_write */ - #define SPECIAL_USE_LOCKS 1 /* Lock used databases */ #define SPECIAL_NO_NEW_FUNC 2 /* Skip new functions */ #define SPECIAL_SKIP_SHOW_DB 4 /* Don't allow 'show db' */ diff --git a/sql/vers_string.h b/sql/vers_string.h index 75abd40d5fa..9d8ca358565 100644 --- a/sql/vers_string.h +++ b/sql/vers_string.h @@ -58,6 +58,12 @@ class Lex_cstring : public LEX_CSTRING str= _str; length= _len; } + Lex_cstring(const char *start, const char *end) + { + DBUG_ASSERT(start <= end); + str= start; + length= end - start; + } void set(const char *_str, size_t _len) { str= _str; diff --git a/sql/vers_utils.h b/sql/vers_utils.h index e896f84135e..2bea191da9e 100644 --- a/sql/vers_utils.h +++ b/sql/vers_utils.h @@ -5,43 +5,4 @@ #include "sql_class.h" #include "vers_string.h" -class MDL_auto_lock -{ - THD *thd; - TABLE_LIST &table; - bool error; - -public: - MDL_auto_lock(THD *_thd, TABLE_LIST &_table) : - thd(_thd), table(_table) - { - DBUG_ASSERT(thd); - MDL_request protection_request; - if (thd->global_read_lock.can_acquire_protection()) - { - error= true; - return; - } - protection_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, - MDL_EXPLICIT); - error= thd->mdl_context.acquire_lock(&protection_request, thd->variables.lock_wait_timeout); - if (error) - return; - - table.mdl_request.init(MDL_key::TABLE, table.db.str, table.table_name.str, MDL_EXCLUSIVE, MDL_EXPLICIT); - error= thd->mdl_context.acquire_lock(&table.mdl_request, thd->variables.lock_wait_timeout); - thd->mdl_context.release_lock(protection_request.ticket); - } - ~MDL_auto_lock() - { - if (!error) - { - DBUG_ASSERT(table.mdl_request.ticket); - thd->mdl_context.release_lock(table.mdl_request.ticket); - table.mdl_request.ticket= NULL; - } - } - bool acquire_error() const { return error; } -}; - #endif // VERS_UTILS_INCLUDED diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index e60fa94ba2a..58b30a1e77f 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1363,7 +1363,7 @@ static int create_view_query(THD *thd, uchar** buf, size_t* buf_len) { LEX *lex= thd->lex; - SELECT_LEX *select_lex= &lex->select_lex; + SELECT_LEX *select_lex= lex->first_select_lex(); TABLE_LIST *first_table= select_lex->table_list.first; TABLE_LIST *views = first_table; LEX_USER *definer; @@ -1445,7 +1445,7 @@ static int wsrep_drop_table_query(THD* thd, uchar** buf, size_t* buf_len) { LEX* lex= thd->lex; - SELECT_LEX* select_lex= &lex->select_lex; + SELECT_LEX* select_lex= lex->first_select_lex(); TABLE_LIST* first_table= select_lex->table_list.first; String buff; @@ -1516,7 +1516,7 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table, DBUG_ASSERT(table_list || db); LEX* lex= thd->lex; - SELECT_LEX* select_lex= &lex->select_lex; + SELECT_LEX* select_lex= lex->first_select_lex(); TABLE_LIST* first_table= select_lex->table_list.first; switch (lex->sql_command) @@ -1823,7 +1823,7 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, DBUG_ASSERT(thd->wsrep_exec_mode == LOCAL_STATE); DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno == WSREP_SEQNO_UNDEFINED); - if (thd->global_read_lock.can_acquire_protection()) + if (thd->has_read_only_protection()) { WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lld", thd->query(), (longlong) thd->thread_id); @@ -2746,10 +2746,11 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table, } return(false); - -WSREP_ERROR_LABEL: +#ifdef WITH_WSREP +wsrep_error_label: thd->wsrep_TOI_pre_query= NULL; return (true); +#endif } diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index e648a7f4c69..24306e37ca3 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1266,7 +1266,7 @@ wait_signal: mysql_mutex_unlock(mysql_bin_log.get_log_lock()); } sst_disallow_writes (thd.ptr, false); - thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); + thd.ptr->global_read_lock.unlock_global_read_lock(thd.ptr); locked= false; } err= 0; @@ -1303,7 +1303,7 @@ wait_signal: mysql_mutex_unlock(mysql_bin_log.get_log_lock()); } sst_disallow_writes (thd.ptr, false); - thd.ptr->global_read_lock.unlock_global_read_lock (thd.ptr); + thd.ptr->global_read_lock.unlock_global_read_lock(thd.ptr); } // signal to donor that SST is over diff --git a/storage/archive/azio.c b/storage/archive/azio.c index 0f66b999c94..3529d875f72 100644 --- a/storage/archive/azio.c +++ b/storage/archive/azio.c @@ -866,7 +866,10 @@ int azclose (azio_stream *s) if (s->mode == 'w') { if (do_flush(s, Z_FINISH) != Z_OK) - return destroy(s); + { + destroy(s); + return Z_ERRNO; + } putLong(s->file, s->crc); putLong(s->file, (uLong)(s->in & 0xffffffff)); diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 487c0038239..f97bc52b6a9 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -802,7 +802,7 @@ int ha_archive::create(const char *name, TABLE *table_arg, #endif /* HAVE_READLINK */ { if (create_info->data_file_name) - my_error(WARN_OPTION_IGNORED, MYF(ME_JUST_WARNING), "DATA DIRECTORY"); + my_error(WARN_OPTION_IGNORED, MYF(ME_WARNING), "DATA DIRECTORY"); fn_format(name_buff, name, "", ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME); @@ -811,7 +811,7 @@ int ha_archive::create(const char *name, TABLE *table_arg, /* Archive engine never uses INDEX DIRECTORY. */ if (create_info->index_file_name) - my_error(WARN_OPTION_IGNORED, MYF(ME_JUST_WARNING), "INDEX DIRECTORY"); + my_error(WARN_OPTION_IGNORED, MYF(ME_WARNING), "INDEX DIRECTORY"); /* There is a chance that the file was "discovered". In this case @@ -1737,6 +1737,20 @@ int ha_archive::info(uint flag) } +int ha_archive::extra(enum ha_extra_function operation) +{ + switch (operation) { + case HA_EXTRA_FLUSH: + mysql_mutex_lock(&share->mutex); + share->close_archive_writer(); + mysql_mutex_unlock(&share->mutex); + break; + default: + break; + } + return 0; +} + /* This method tells us that a bulk insert operation is about to occur. We set a flag which will keep write_row from saying that its data is dirty. This in diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h index 56ff566db8c..17649c9c110 100644 --- a/storage/archive/ha_archive.h +++ b/storage/archive/ha_archive.h @@ -108,7 +108,7 @@ public: return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_STATS_RECORDS_IS_EXACT | HA_CAN_EXPORT | - HA_HAS_RECORDS | HA_CAN_REPAIR | + HA_HAS_RECORDS | HA_CAN_REPAIR | HA_SLOW_RND_POS | HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY); } ulong index_flags(uint idx, uint part, bool all_parts) const @@ -148,6 +148,7 @@ public: int read_data_header(azio_stream *file_to_read); void position(const uchar *record); int info(uint); + int extra(enum ha_extra_function operation); void update_create_info(HA_CREATE_INFO *create_info); int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); int optimize(THD* thd, HA_CHECK_OPT* check_opt); diff --git a/storage/blackhole/ha_blackhole.h b/storage/blackhole/ha_blackhole.h index 9a4b34809f8..345d6683938 100644 --- a/storage/blackhole/ha_blackhole.h +++ b/storage/blackhole/ha_blackhole.h @@ -55,7 +55,7 @@ public: { return(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE | - HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | + HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | HA_CAN_ONLINE_BACKUPS | HA_FILE_BASED | HA_CAN_GEOMETRY | HA_CAN_INSERT_DELAYED); } ulong index_flags(uint inx, uint part, bool all_parts) const diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index b781c61cdd1..d3f89aca910 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -2085,9 +2085,8 @@ int ha_connect::MakeRecord(char *buf) DBUG_ENTER("ha_connect::MakeRecord"); if (trace(2)) - htrc("Maps: read=%08X write=%08X vcol=%08X defr=%08X defw=%08X\n", + htrc("Maps: read=%08X write=%08X defr=%08X defw=%08X\n", *table->read_set->bitmap, *table->write_set->bitmap, - (table->vcol_set) ? *table->vcol_set->bitmap : 0, *table->def_read_set.bitmap, *table->def_write_set.bitmap); // Avoid asserts in field::store() for columns that are not updated @@ -2727,37 +2726,40 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) if (!i && (ismul)) return NULL; - switch (args[i]->real_type()) { - case COND::STRING_ITEM: - res= pval->val_str(&tmp); - pp->Value= PlugSubAllocStr(g, NULL, res->ptr(), res->length()); - pp->Type= (pp->Value) ? TYPE_STRING : TYPE_ERROR; - break; - case COND::INT_ITEM: - pp->Type= TYPE_INT; - pp->Value= PlugSubAlloc(g, NULL, sizeof(int)); - *((int*)pp->Value)= (int)pval->val_int(); - break; - case COND::DATE_ITEM: - pp->Type= TYPE_DATE; - pp->Value= PlugSubAlloc(g, NULL, sizeof(int)); - *((int*)pp->Value)= (int)pval->val_int_from_date(); - break; - case COND::REAL_ITEM: - pp->Type= TYPE_DOUBLE; - pp->Value= PlugSubAlloc(g, NULL, sizeof(double)); - *((double*)pp->Value)= pval->val_real(); - break; - case COND::DECIMAL_ITEM: - pp->Type= TYPE_DOUBLE; - pp->Value= PlugSubAlloc(g, NULL, sizeof(double)); - *((double*)pp->Value)= pval->val_real_from_decimal(); - break; + switch (args[i]->real_type()) { + case COND::CONST_ITEM: + switch (args[i]->cmp_type()) { + case STRING_RESULT: + res= pval->val_str(&tmp); + pp->Value= PlugSubAllocStr(g, NULL, res->ptr(), res->length()); + pp->Type= (pp->Value) ? TYPE_STRING : TYPE_ERROR; + break; + case INT_RESULT: + pp->Type= TYPE_INT; + pp->Value= PlugSubAlloc(g, NULL, sizeof(int)); + *((int*)pp->Value)= (int)pval->val_int(); + break; + case TIME_RESULT: + pp->Type= TYPE_DATE; + pp->Value= PlugSubAlloc(g, NULL, sizeof(int)); + *((int*)pp->Value)= (int) Temporal_hybrid(pval).to_longlong(); + break; + case REAL_RESULT: + case DECIMAL_RESULT: + pp->Type= TYPE_DOUBLE; + pp->Value= PlugSubAlloc(g, NULL, sizeof(double)); + *((double*)pp->Value)= pval->val_real(); + break; + case ROW_RESULT: + DBUG_ASSERT(0); + return NULL; + } + break; case COND::CACHE_ITEM: // Possible ??? case COND::NULL_ITEM: // TODO: handle this default: return NULL; - } // endswitch type + } // endswitch type if (trace(1)) htrc("Value type=%hd\n", pp->Type); @@ -3009,12 +3011,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond) Item::Type type= args[i]->real_type(); switch (type) { - case COND::STRING_ITEM: - case COND::INT_ITEM: - case COND::REAL_ITEM: + case COND::CONST_ITEM: case COND::NULL_ITEM: - case COND::DECIMAL_ITEM: - case COND::DATE_ITEM: case COND::CACHE_ITEM: break; default: diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index 6bce46ead95..8504b585ae1 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -544,3 +544,7 @@ public: uint int_table_flags; // Inherited from MyISAM bool enable_activate_all_index; // Inherited from MyISAM }; // end of ha_connect class definition + +#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) +bool MongoEnabled(void); +#endif // JAVA_SUPPORT || CMGO_SUPPORT diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 5aef6d9c660..c41ea0970ed 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -102,10 +102,6 @@ extern "C" HINSTANCE s_hModule; // Saved module handle #endif // !__WIN__ -#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) -bool MongoEnabled(void); -#endif // JAVA_SUPPORT || CMGO_SUPPORT - PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); /***********************************************************************/ diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index 0e092e2fd90..f69dd7989a2 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -1311,12 +1311,28 @@ int ha_tina::info(uint flag) int ha_tina::extra(enum ha_extra_function operation) { DBUG_ENTER("ha_tina::extra"); - if (operation == HA_EXTRA_MARK_AS_LOG_TABLE) - { - mysql_mutex_lock(&share->mutex); - share->is_log_table= TRUE; - mysql_mutex_unlock(&share->mutex); - } + switch (operation) { + case HA_EXTRA_MARK_AS_LOG_TABLE: + { + mysql_mutex_lock(&share->mutex); + share->is_log_table= TRUE; + mysql_mutex_unlock(&share->mutex); + } + break; + case HA_EXTRA_FLUSH: + mysql_mutex_lock(&share->mutex); + if (share->tina_write_opened) + { + (void)write_meta_file(share->meta_file, share->rows_recorded, + share->crashed ? TRUE :FALSE); + mysql_file_close(share->tina_write_filedes, MYF(0)); + share->tina_write_opened= FALSE; + } + mysql_mutex_unlock(&share->mutex); + break; + default: + break; + } DBUG_RETURN(0); } @@ -1385,7 +1401,7 @@ int ha_tina::rnd_end() if (mysql_file_write(update_temp_file, (uchar*) (file_buff->ptr() + (write_begin - file_buff->start())), - (size_t)write_length, MYF_RW)) + (size_t)write_length, MYF(MY_WME+MY_NABP))) goto error; temp_file_length+= write_length; } @@ -1571,7 +1587,7 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt) write_end= MY_MIN(file_buff->end(), current_position); if ((write_end - write_begin) && (mysql_file_write(repair_file, (uchar*)file_buff->ptr(), - (size_t) (write_end - write_begin), MYF_RW))) + (size_t) (write_end - write_begin), MYF(MY_WME+MY_NABP)))) DBUG_RETURN(-1); write_begin= write_end; diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h index c75a64faa52..5b389d984d6 100644 --- a/storage/csv/ha_tina.h +++ b/storage/csv/ha_tina.h @@ -107,7 +107,7 @@ public: { return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_CAN_EXPORT | - HA_CAN_REPAIR); + HA_CAN_REPAIR | HA_SLOW_RND_POS); } ulong index_flags(uint idx, uint part, bool all_parts) const { diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h index 8fe42bd2b08..45318f4c594 100644 --- a/storage/federated/ha_federated.h +++ b/storage/federated/ha_federated.h @@ -146,6 +146,7 @@ public: HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE | HA_NO_TRANSACTIONS /* until fixed by WL#2952 */ | HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY | + HA_CAN_ONLINE_BACKUPS | HA_CAN_REPAIR); } /* diff --git a/storage/federatedx/TODO b/storage/federatedx/TODO deleted file mode 100644 index 71330742f4e..00000000000 --- a/storage/federatedx/TODO +++ /dev/null @@ -1,30 +0,0 @@ -Features - -* Add Pushdown conditions -* Add other network driver interfaces -* Handle large result sets -* Auto-discovery of tables on foreign data sources - -Bugs (http://bugs.mysql.com) - -20026 2006-05-23 FEDERATED lacks support for auto_increment_increment and auto_increment_offset -20724 2006-06-27 FEDERATED does not honour SET INSERT_ID -28269 2007-05-06 Any FEDERATED engine fails to quote reserved words for field names -25509 2007-01-10 Federated: Failure with non-ASCII characters -26697 2007-02-27 Every query to a federated table results in a full scan of MyISAM table. -21360 2006-07-31 Microsoft Windows (Windows/Linux) mysqldump error on federated tables -34189 2008-01-31 Any ALTER TABLE t1 ENGINE=FEDERATED CONNECTION='connectionString' on MyISAM fails -31757 2007-10-22 Any Federated tables break replication Antony Curtis -33953 2008-01-21 Any mysqld dies on search federated table using nullable index with < or <= operator -34015 2008-01-23 Linux Problems with float fields using federated tables -21583 2006-08-11 Linux (Linux) Federated table returns broken strings. -33702 2008-01-05 Accessing a federated table with a non existing server returns random error code -25512 2007-01-10 Federated: CREATE failures -32426 2007-11-16 Any FEDERATED query returns corrupt results for ORDER BY on a TEXT field -25510 2007-01-10 Federated: double trigger activation -33250 2007-12-14 SELECT * FROM really_big_federated_table eats lots of virtual memory (OOM) -14874 2005-11-11 Error 2013: Lost connection to MySQL server with Federated table -25508 2007-01-10 Federated: Failure to Remove Partitioning -27180 2007-03-15 #1030 - Got error 1 from storage engine with big tables -33947 2008-01-20 Any Join on Federated tables with Unique index and IS NOT NULL crashes server -30051 (fixed) CREATE TABLE does not connect and check existence of remote table diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h index 16a1944b172..7eed0fa539e 100644 --- a/storage/federatedx/ha_federatedx.h +++ b/storage/federatedx/ha_federatedx.h @@ -333,7 +333,7 @@ public: return (HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED | HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_CAN_REPAIR | - HA_PRIMARY_KEY_REQUIRED_FOR_DELETE | + HA_PRIMARY_KEY_REQUIRED_FOR_DELETE | HA_CAN_ONLINE_BACKUPS | HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY); } /* diff --git a/storage/heap/ha_heap.h b/storage/heap/ha_heap.h index e17c18c8b14..3a7e0060a05 100644 --- a/storage/heap/ha_heap.h +++ b/storage/heap/ha_heap.h @@ -49,7 +49,7 @@ public: { return (HA_FAST_KEY_READ | HA_NO_BLOBS | HA_NULL_IN_KEY | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | - HA_CAN_SQL_HANDLER | + HA_CAN_SQL_HANDLER | HA_CAN_ONLINE_BACKUPS | HA_REC_NOT_IN_SEQ | HA_CAN_INSERT_DELAYED | HA_NO_TRANSACTIONS | HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT); } diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 0c56008a57a..7d255531b15 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -113,7 +113,6 @@ SET(INNOBASE_SOURCES row/row0purge.cc row/row0row.cc row/row0sel.cc - row/row0trunc.cc row/row0uins.cc row/row0umod.cc row/row0undo.cc @@ -179,7 +178,6 @@ IF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") mtr/mtr0mtr.cc row/row0merge.cc row/row0mysql.cc - row/row0trunc.cc srv/srv0srv.cc COMPILE_FLAGS "-O0" ) diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 96be7349b46..9e71dbe2889 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -57,15 +57,12 @@ btr_can_merge_with_page( buf_block_t** merge_block, /*!< out: the merge block */ mtr_t* mtr); /*!< in: mini-transaction */ -/**************************************************************//** -Report that an index page is corrupted. */ -void -btr_corruption_report( -/*==================*/ - const buf_block_t* block, /*!< in: corrupted block */ - const dict_index_t* index) /*!< in: index tree */ +/** Report that an index page is corrupted. +@param[in] buffer block +@param[in] index tree */ +void btr_corruption_report(const buf_block_t* block, const dict_index_t* index) { - ib::error() + ib::fatal() << "Flag mismatch in page " << block->page.id << " index " << index->name << " of table " << index->table->name; @@ -435,7 +432,7 @@ btr_page_create( ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); if (page_zip) { - page_create_zip(block, index, level, 0, NULL, mtr); + page_create_zip(block, index, level, 0, mtr); } else { page_create(block, mtr, dict_table_is_comp(index->table), dict_index_is_spatial(index)); @@ -1176,21 +1173,18 @@ btr_free_root_check( /** Create the root node for a new index tree. @param[in] type type of the index -@param[in,out] space tablespace where created @param[in] index_id index id -@param[in] index index, or NULL when applying TRUNCATE -log record during recovery -@param[in] btr_redo_create_info used for applying TRUNCATE log -@param[in] mtr mini-transaction handle -record during recovery -@return page number of the created root, FIL_NULL if did not succeed */ +@param[in,out] space tablespace where created +@param[in] index index +@param[in,out] mtr mini-transaction +@return page number of the created root +@retval FIL_NULL if did not succeed */ ulint btr_create( ulint type, fil_space_t* space, index_id_t index_id, dict_index_t* index, - const btr_create_t* btr_redo_create_info, mtr_t* mtr) { buf_block_t* block; @@ -1205,7 +1199,7 @@ btr_create( (for an ibuf tree, not in the root, but on a separate ibuf header page) */ - if (type & DICT_IBUF) { + if (UNIV_UNLIKELY(type & DICT_IBUF)) { /* Allocate first the ibuf header page */ buf_block_t* ibuf_hdr_block = fseg_create( space, 0, @@ -1237,8 +1231,7 @@ btr_create( buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); - flst_init(block->frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, - mtr); + flst_init(block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr); } else { block = fseg_create(space, 0, PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr); @@ -1270,44 +1263,11 @@ btr_create( page_zip = buf_block_get_page_zip(block); if (page_zip) { - if (index != NULL) { - page = page_create_zip(block, index, 0, 0, NULL, mtr); - } else { - /* Create a compressed index page when applying - TRUNCATE log record during recovery */ - ut_ad(btr_redo_create_info != NULL); - - redo_page_compress_t page_comp_info; - - page_comp_info.type = type; - - page_comp_info.index_id = index_id; - - page_comp_info.n_fields = - btr_redo_create_info->n_fields; - - page_comp_info.field_len = - btr_redo_create_info->field_len; - - page_comp_info.fields = btr_redo_create_info->fields; - - page_comp_info.trx_id_pos = - btr_redo_create_info->trx_id_pos; - - page = page_create_zip(block, NULL, 0, 0, - &page_comp_info, mtr); - } + page = page_create_zip(block, index, 0, 0, mtr); } else { - if (index != NULL) { - page = page_create(block, mtr, - dict_table_is_comp(index->table), - dict_index_is_spatial(index)); - } else { - ut_ad(btr_redo_create_info != NULL); - page = page_create( - block, mtr, btr_redo_create_info->format_flags, - type == DICT_SPATIAL); - } + page = page_create(block, mtr, + dict_table_is_comp(index->table), + dict_index_is_spatial(index)); /* Set the level of the new index page */ btr_page_set_level(page, NULL, 0, mtr); } @@ -1319,18 +1279,14 @@ btr_create( btr_page_set_next(page, page_zip, FIL_NULL, mtr); btr_page_set_prev(page, page_zip, FIL_NULL, mtr); - /* We reset the free bits for the page to allow creation of several - trees in the same mtr, otherwise the latch on a bitmap page would - prevent it because of the latching order. - - index will be NULL if we are recreating the table during recovery - on behalf of TRUNCATE. + /* We reset the free bits for the page in a separate + mini-transaction to allow creation of several trees in the + same mtr, otherwise the latch on a bitmap page would prevent + it because of the latching order. Note: Insert Buffering is disabled for temporary tables given that most temporary tables are smaller in size and short-lived. */ - if (!(type & DICT_CLUSTERED) - && (index == NULL || !index->table->is_temporary())) { - + if (!(type & DICT_CLUSTERED) && !index->table->is_temporary()) { ibuf_reset_free_bits(block); } @@ -1672,7 +1628,7 @@ btr_page_reorganize_low( } if (page_zip - && !page_zip_compress(page_zip, page, index, z_level, NULL, mtr)) { + && !page_zip_compress(page_zip, page, index, z_level, mtr)) { /* Restore the old page and exit. */ #if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG @@ -1698,11 +1654,6 @@ btr_page_reorganize_low( goto func_exit; } - if (!recovery && !dict_table_is_locking_disabled(index->table)) { - /* Update the record lock bitmaps */ - lock_move_reorganize_page(block, temp_block); - } - data_size2 = page_get_data_size(page); max_ins_size2 = page_get_max_insert_size_after_reorganize(page, 1); @@ -1726,21 +1677,41 @@ btr_page_reorganize_low( ut_ad(cursor->rec == page_get_infimum_rec(page)); } -func_exit: #ifdef UNIV_ZIP_DEBUG ut_a(!page_zip || page_zip_validate(page_zip, page, index)); #endif /* UNIV_ZIP_DEBUG */ - if (!recovery && page_is_root(temp_page) - && fil_page_get_type(temp_page) == FIL_PAGE_TYPE_INSTANT) { - /* Preserve the PAGE_INSTANT information. */ - ut_ad(!page_zip); - ut_ad(index->is_instant()); - memcpy(FIL_PAGE_TYPE + page, FIL_PAGE_TYPE + temp_page, 2); - memcpy(PAGE_HEADER + PAGE_INSTANT + page, - PAGE_HEADER + PAGE_INSTANT + temp_page, 2); + if (!recovery) { + if (page_is_root(temp_page) + && fil_page_get_type(temp_page) == FIL_PAGE_TYPE_INSTANT) { + /* Preserve the PAGE_INSTANT information. */ + ut_ad(!page_zip); + ut_ad(index->is_instant()); + memcpy(FIL_PAGE_TYPE + page, + FIL_PAGE_TYPE + temp_page, 2); + memcpy(PAGE_HEADER + PAGE_INSTANT + page, + PAGE_HEADER + PAGE_INSTANT + temp_page, 2); + if (!index->table->instant) { + } else if (page_is_comp(page)) { + memcpy(PAGE_NEW_INFIMUM + page, + PAGE_NEW_INFIMUM + temp_page, 8); + memcpy(PAGE_NEW_SUPREMUM + page, + PAGE_NEW_SUPREMUM + temp_page, 8); + } else { + memcpy(PAGE_OLD_INFIMUM + page, + PAGE_OLD_INFIMUM + temp_page, 8); + memcpy(PAGE_OLD_SUPREMUM + page, + PAGE_OLD_SUPREMUM + temp_page, 8); + } + } + + if (!dict_table_is_locking_disabled(index->table)) { + /* Update the record lock bitmaps */ + lock_move_reorganize_page(block, temp_block); + } } +func_exit: buf_block_free(temp_block); /* Restore logging mode */ @@ -1786,6 +1757,14 @@ func_exit: mach_read_from_2(PAGE_HEADER + PAGE_INSTANT + page), MLOG_2BYTES, mtr); + if (!index->table->instant) { + } else if (page_is_comp(page)) { + mlog_log_string(PAGE_NEW_INFIMUM + page, 8, mtr); + mlog_log_string(PAGE_NEW_SUPREMUM + page, 8, mtr); + } else { + mlog_log_string(PAGE_OLD_INFIMUM + page, 8, mtr); + mlog_log_string(PAGE_OLD_SUPREMUM + page, 8, mtr); + } } return(success); @@ -1921,7 +1900,7 @@ btr_page_empty( : 0; if (page_zip) { - page_create_zip(block, index, level, autoinc, NULL, mtr); + page_create_zip(block, index, level, autoinc, mtr); } else { page_create(block, mtr, dict_table_is_comp(index->table), dict_index_is_spatial(index)); @@ -1933,6 +1912,59 @@ btr_page_empty( } } +/** Write instant ALTER TABLE metadata to a root page. +@param[in,out] root clustered index root page +@param[in] index clustered index with instant ALTER TABLE +@param[in,out] mtr mini-transaction */ +void btr_set_instant(buf_block_t* root, const dict_index_t& index, mtr_t* mtr) +{ + ut_ad(index.n_core_fields > 0); + ut_ad(index.n_core_fields < REC_MAX_N_FIELDS); + ut_ad(index.is_instant()); + ut_ad(page_is_root(root->frame)); + + rec_t* infimum = page_get_infimum_rec(root->frame); + rec_t* supremum = page_get_supremum_rec(root->frame); + byte* page_type = root->frame + FIL_PAGE_TYPE; + uint16_t i = page_header_get_field(root->frame, PAGE_INSTANT); + + switch (mach_read_from_2(page_type)) { + case FIL_PAGE_TYPE_INSTANT: + ut_ad(page_get_instant(root->frame) == index.n_core_fields); + if (memcmp(infimum, "infimum", 8) + || memcmp(supremum, "supremum", 8)) { + ut_ad(index.table->instant); + ut_ad(!memcmp(infimum, field_ref_zero, 8)); + ut_ad(!memcmp(supremum, field_ref_zero, 7)); + ut_ad(supremum[7] == index.n_core_null_bytes); + return; + } + break; + default: + ut_ad(!"wrong page type"); + /* fall through */ + case FIL_PAGE_INDEX: + ut_ad(!page_is_comp(root->frame) + || !page_get_instant(root->frame)); + ut_ad(!memcmp(infimum, "infimum", 8)); + ut_ad(!memcmp(supremum, "supremum", 8)); + mlog_write_ulint(page_type, FIL_PAGE_TYPE_INSTANT, + MLOG_2BYTES, mtr); + ut_ad(i <= PAGE_NO_DIRECTION); + i |= index.n_core_fields << 3; + mlog_write_ulint(PAGE_HEADER + PAGE_INSTANT + root->frame, i, + MLOG_2BYTES, mtr); + break; + } + + if (index.table->instant) { + mlog_memset(root, infimum - root->frame, 8, 0, mtr); + mlog_memset(root, supremum - root->frame, 7, 0, mtr); + mlog_write_ulint(&supremum[7], index.n_core_null_bytes, + MLOG_1BYTE, mtr); + } +} + /*************************************************************//** Makes tree one level higher by splitting the root, and inserts the tuple. It is assumed that mtr contains an x-latch on the tree. @@ -2118,11 +2150,7 @@ btr_root_raise_and_insert( if (index->is_instant()) { ut_ad(!root_page_zip); - byte* page_type = root_block->frame + FIL_PAGE_TYPE; - ut_ad(mach_read_from_2(page_type) == FIL_PAGE_INDEX); - mlog_write_ulint(page_type, FIL_PAGE_TYPE_INSTANT, - MLOG_2BYTES, mtr); - page_set_instant(root_block->frame, index->n_core_fields, mtr); + btr_set_instant(root_block, *index, mtr); } /* Set the next node and previous node fields, although @@ -3607,12 +3635,7 @@ btr_lift_page_up( if (page_level == 0 && index->is_instant()) { ut_ad(!father_page_zip); - byte* page_type = father_block->frame + FIL_PAGE_TYPE; - ut_ad(mach_read_from_2(page_type) == FIL_PAGE_INDEX); - mlog_write_ulint(page_type, FIL_PAGE_TYPE_INSTANT, - MLOG_2BYTES, mtr); - page_set_instant(father_block->frame, - index->n_core_fields, mtr); + btr_set_instant(father_block, *index, mtr); } page_level++; @@ -4284,15 +4307,42 @@ btr_discard_only_page_on_level( } #endif /* UNIV_BTR_DEBUG */ + mem_heap_t* heap = NULL; + const rec_t* rec = NULL; + ulint* offsets = NULL; + if (index->table->instant) { + const rec_t* r = page_rec_get_next(page_get_infimum_rec( + block->frame)); + ut_ad(rec_is_metadata(r, *index) == index->is_instant()); + if (rec_is_alter_metadata(r, *index)) { + heap = mem_heap_create(srv_page_size); + offsets = rec_get_offsets(r, index, NULL, true, + ULINT_UNDEFINED, &heap); + rec = rec_copy(mem_heap_alloc(heap, + rec_offs_size(offsets)), + r, offsets); + rec_offs_make_valid(rec, index, true, offsets); + } + } + btr_page_empty(block, buf_block_get_page_zip(block), index, 0, mtr); ut_ad(page_is_leaf(buf_block_get_frame(block))); /* btr_page_empty() is supposed to zero-initialize the field. */ ut_ad(!page_get_instant(block->frame)); if (index->is_primary()) { - /* Concurrent access is prevented by the root_block->lock - X-latch, so this should be safe. */ - index->remove_instant(); + if (rec) { + DBUG_ASSERT(index->table->instant); + DBUG_ASSERT(rec_is_alter_metadata(rec, *index)); + btr_set_instant(block, *index, mtr); + rec = page_cur_insert_rec_low( + page_get_infimum_rec(block->frame), + index, rec, offsets, mtr); + ut_ad(rec); + mem_heap_free(heap); + } else if (index->is_instant()) { + index->clear_instant_add(); + } } else if (!index->table->is_temporary()) { /* We play it safe and reset the free bits for the root */ ibuf_reset_free_bits(block); @@ -4716,14 +4766,32 @@ btr_index_rec_validate( return(FALSE); } + const bool is_alter_metadata = page_is_leaf(page) + && !page_has_prev(page) + && index->is_primary() && index->table->instant + && rec == page_rec_get_next_const(page_get_infimum_rec(page)); + + if (is_alter_metadata + && !rec_is_alter_metadata(rec, page_is_comp(page))) { + btr_index_rec_validate_report(page, rec, index); + + ib::error() << "First record is not ALTER TABLE metadata"; + return FALSE; + } + if (!page_is_comp(page)) { const ulint n_rec_fields = rec_get_n_fields_old(rec); if (n_rec_fields == DICT_FLD__SYS_INDEXES__MERGE_THRESHOLD && index->id == DICT_INDEXES_ID) { /* A record for older SYS_INDEXES table (missing merge_threshold column) is acceptable. */ + } else if (is_alter_metadata) { + if (n_rec_fields != ulint(index->n_fields) + 1) { + goto n_field_mismatch; + } } else if (n_rec_fields < index->n_core_fields || n_rec_fields > index->n_fields) { +n_field_mismatch: btr_index_rec_validate_report(page, rec, index); ib::error() << "Has " << rec_get_n_fields_old(rec) @@ -4742,15 +4810,28 @@ btr_index_rec_validate( offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page), ULINT_UNDEFINED, &heap); + const dict_field_t* field = index->fields; + ut_ad(rec_offs_n_fields(offsets) + == ulint(index->n_fields) + is_alter_metadata); - for (unsigned i = 0; i < index->n_fields; i++) { - dict_field_t* field = dict_index_get_nth_field(index, i); - ulint fixed_size = dict_col_get_fixed_size( - dict_field_get_col(field), - page_is_comp(page)); - + for (unsigned i = 0; i < rec_offs_n_fields(offsets); i++) { rec_get_nth_field_offs(offsets, i, &len); + ulint fixed_size; + + if (is_alter_metadata && i == index->first_user_field()) { + fixed_size = FIELD_REF_SIZE; + if (len != FIELD_REF_SIZE + || !rec_offs_nth_extern(offsets, i)) { + goto len_mismatch; + } + + continue; + } else { + fixed_size = dict_col_get_fixed_size( + field->col, page_is_comp(page)); + } + /* Note that if fixed_size != 0, it equals the length of a fixed-size column in the clustered index. We should adjust it here. @@ -4762,8 +4843,8 @@ btr_index_rec_validate( && (field->prefix_len ? len > field->prefix_len : (fixed_size && len != fixed_size))) { +len_mismatch: btr_index_rec_validate_report(page, rec, index); - ib::error error; error << "Field " << i << " len is " << len @@ -4781,6 +4862,8 @@ btr_index_rec_validate( } return(FALSE); } + + field++; } #ifdef VIRTUAL_INDEX_DEBUG diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 2ce2815acb0..5cb07af3f66 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -94,7 +94,7 @@ PageBulk::init() if (new_page_zip) { page_create_zip(new_block, m_index, m_level, 0, - NULL, &m_mtr); + &m_mtr); memset(FIL_PAGE_PREV + new_page, 0xff, 8); page_zip_write_header(new_page_zip, FIL_PAGE_PREV + new_page, @@ -374,7 +374,7 @@ PageBulk::compress() ut_ad(m_page_zip != NULL); return(page_zip_compress(m_page_zip, m_page, m_index, - page_zip_level, NULL, &m_mtr)); + page_zip_level, &m_mtr)); } /** Get node pointer diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index b8f9a55b148..16d8d43998f 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -457,8 +457,8 @@ unreadable: return DB_CORRUPTION; } - if (info_bits != REC_INFO_MIN_REC_FLAG - || (comp && rec_get_status(rec) != REC_STATUS_COLUMNS_ADDED)) { + if ((info_bits & ~REC_INFO_DELETED_FLAG) != REC_INFO_MIN_REC_FLAG + || (comp && rec_get_status(rec) != REC_STATUS_INSTANT)) { incompatible: ib::error() << "Table " << index->table->name << " contains unrecognizable instant ALTER metadata"; @@ -476,6 +476,72 @@ incompatible: concurrent operations on the table, including table eviction from the cache. */ + if (info_bits & REC_INFO_DELETED_FLAG) { + /* This metadata record includes a BLOB that identifies + any dropped or reordered columns. */ + ulint trx_id_offset = index->trx_id_offset; + if (!trx_id_offset) { + /* The PRIMARY KEY contains variable-length columns. + For the metadata record, variable-length columns are + always written with zero length. The DB_TRX_ID will + start right after any fixed-length columns. */ + for (uint i = index->n_uniq; i--; ) { + trx_id_offset += index->fields[0].fixed_len; + } + } + + const byte* ptr = rec + trx_id_offset + + (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN); + + if (mach_read_from_4(ptr + BTR_EXTERN_LEN)) { + goto incompatible; + } + + uint len = mach_read_from_4(ptr + BTR_EXTERN_LEN + 4); + if (!len + || mach_read_from_4(ptr + BTR_EXTERN_OFFSET) + != FIL_PAGE_DATA + || mach_read_from_4(ptr + BTR_EXTERN_SPACE_ID) + != space->id) { + goto incompatible; + } + + buf_block_t* block = buf_page_get( + page_id_t(space->id, + mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)), + univ_page_size, RW_S_LATCH, mtr); + buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE); + if (fil_page_get_type(block->frame) != FIL_PAGE_TYPE_BLOB + || mach_read_from_4(&block->frame[FIL_PAGE_DATA + + BTR_BLOB_HDR_NEXT_PAGE_NO]) + != FIL_NULL + || mach_read_from_4(&block->frame[FIL_PAGE_DATA + + BTR_BLOB_HDR_PART_LEN]) + != len) { + goto incompatible; + } + + /* The unused part of the BLOB page should be zero-filled. */ + for (const byte* b = block->frame + + (FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE) + len, + * const end = block->frame + srv_page_size + - BTR_EXTERN_LEN; + b < end; ) { + if (*b++) { + goto incompatible; + } + } + + if (index->table->deserialise_columns( + &block->frame[FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE], + len)) { + goto incompatible; + } + + /* Proceed to initialize the default values of + any instantly added columns. */ + } + mem_heap_t* heap = NULL; ulint* offsets = rec_get_offsets(rec, index, NULL, true, ULINT_UNDEFINED, &heap); @@ -489,7 +555,8 @@ inconsistent: record, it is also OK to perform READ UNCOMMITTED and then ignore any extra fields, provided that trx_sys.is_registered(DB_TRX_ID). */ - if (rec_offs_n_fields(offsets) > index->n_fields + if (rec_offs_n_fields(offsets) + > ulint(index->n_fields) + !!index->table->instant && !trx_sys.is_registered(current_trx(), row_get_rec_trx_id(rec, index, offsets))) { @@ -497,10 +564,11 @@ inconsistent: } for (unsigned i = index->n_core_fields; i < index->n_fields; i++) { - ulint len; - const byte* data = rec_get_nth_field(rec, offsets, i, &len); dict_col_t* col = index->fields[i].col; - ut_ad(!col->is_instant()); + const unsigned o = i + !!index->table->instant; + ulint len; + const byte* data = rec_get_nth_field(rec, offsets, o, &len); + ut_ad(!col->is_added()); ut_ad(!col->def_val.data); col->def_val.len = len; switch (len) { @@ -511,7 +579,7 @@ inconsistent: continue; } ut_ad(len != UNIV_SQL_DEFAULT); - if (!rec_offs_nth_extern(offsets, i)) { + if (!rec_offs_nth_extern(offsets, o)) { col->def_val.data = mem_heap_dup( index->table->heap, data, len); } else if (len < BTR_EXTERN_FIELD_REF_SIZE @@ -523,7 +591,7 @@ inconsistent: } else { col->def_val.data = btr_copy_externally_stored_field( &col->def_val.len, data, - dict_table_page_size(index->table), + cur.page_cur.block->page.size, len, index->table->heap); } } @@ -588,30 +656,49 @@ bool btr_cur_instant_root_init(dict_index_t* index, const page_t* page) const uint16_t n = page_get_instant(page); - if (n < index->n_uniq + DATA_ROLL_PTR || n > index->n_fields) { + if (n < index->n_uniq + DATA_ROLL_PTR) { /* The PRIMARY KEY (or hidden DB_ROW_ID) and DB_TRX_ID,DB_ROLL_PTR columns must always be present - as 'core' fields. All fields, including those for - instantly added columns, must be present in the data - dictionary. */ + as 'core' fields. */ return true; } - if (memcmp(page_get_infimum_rec(page), "infimum", 8) - || memcmp(page_get_supremum_rec(page), "supremum", 8)) { - /* In a later format, these fields in a FIL_PAGE_TYPE_INSTANT - root page could be repurposed for something else. */ + if (n > REC_MAX_N_FIELDS) { return true; } index->n_core_fields = n; - ut_ad(!index->is_dummy); - ut_d(index->is_dummy = true); - index->n_core_null_bytes = n == index->n_fields - ? UT_BITS_IN_BYTES(unsigned(index->n_nullable)) - : UT_BITS_IN_BYTES(index->get_n_nullable(n)); - ut_d(index->is_dummy = false); - return false; + + const rec_t* infimum = page_get_infimum_rec(page); + const rec_t* supremum = page_get_supremum_rec(page); + + if (!memcmp(infimum, "infimum", 8) + && !memcmp(supremum, "supremum", 8)) { + if (n > index->n_fields) { + /* All fields, including those for instantly + added columns, must be present in the + data dictionary. */ + return true; + } + + ut_ad(!index->is_dummy); + ut_d(index->is_dummy = true); + index->n_core_null_bytes = UT_BITS_IN_BYTES( + index->get_n_nullable(n)); + ut_d(index->is_dummy = false); + return false; + } + + if (memcmp(infimum, field_ref_zero, 8) + || memcmp(supremum, field_ref_zero, 7)) { + /* The infimum and supremum records must either contain + the original strings, or they must be filled with zero + bytes, except for the bytes that we have repurposed. */ + return true; + } + + index->n_core_null_bytes = supremum[7]; + return index->n_core_null_bytes > 128; } /** Optimistically latches the leaf page or pages requested. @@ -2311,9 +2398,10 @@ need_opposite_intention: ut_ad(index->is_instant()); /* This may be a search tuple for btr_pcur_restore_position(). */ - ut_ad(tuple->info_bits == REC_INFO_METADATA - || tuple->info_bits == REC_INFO_MIN_REC_FLAG); - } else if (rec_is_metadata(btr_cur_get_rec(cursor), index)) { + ut_ad(tuple->is_metadata() + || (tuple->is_metadata(tuple->info_bits + ^ REC_STATUS_INSTANT))); + } else if (rec_is_metadata(btr_cur_get_rec(cursor), *index)) { /* Only user records belong in the adaptive hash index. */ } else { @@ -3160,8 +3248,11 @@ btr_cur_ins_lock_and_undo( roll_ptr = roll_ptr_t(1) << ROLL_PTR_INSERT_FLAG_POS; if (!(flags & BTR_KEEP_SYS_FLAG)) { upd_sys: - row_upd_index_entry_sys_field(entry, index, - DATA_ROLL_PTR, roll_ptr); + dfield_t* r = dtuple_get_nth_field( + entry, index->db_roll_ptr()); + ut_ad(r->len == DATA_ROLL_PTR_LEN); + trx_write_roll_ptr(static_cast<byte*>(r->data), + roll_ptr); } } else { err = trx_undo_report_row_operation(thr, index, entry, @@ -3276,12 +3367,17 @@ btr_cur_optimistic_insert( leaf = page_is_leaf(page); + if (UNIV_UNLIKELY(entry->is_alter_metadata())) { + ut_ad(leaf); + goto convert_big_rec; + } + /* Calculate the record size when entry is converted to a record */ rec_size = rec_get_converted_size(index, entry, n_ext); if (page_zip_rec_needs_ext(rec_size, page_is_comp(page), dtuple_get_n_fields(entry), page_size)) { - +convert_big_rec: /* The record is so big that we have to store some fields externally on separate database pages */ big_rec_vec = dtuple_convert_big_rec(index, 0, entry, &n_ext); @@ -3452,7 +3548,7 @@ fail_err: } else if (index->disable_ahi) { # endif } else if (entry->info_bits & REC_INFO_MIN_REC_FLAG) { - ut_ad(entry->info_bits == REC_INFO_METADATA); + ut_ad(entry->is_metadata()); ut_ad(index->is_instant()); ut_ad(flags == BTR_NO_LOCKING_FLAG); } else { @@ -3584,10 +3680,16 @@ btr_cur_pessimistic_insert( } } + DBUG_ASSERT(!entry->is_alter_metadata() + || !dfield_is_ext( + dtuple_get_nth_field(entry, + index->first_user_field()))); + if (page_zip_rec_needs_ext(rec_get_converted_size(index, entry, n_ext), - dict_table_is_comp(index->table), + index->table->not_redundant(), dtuple_get_n_fields(entry), - dict_table_page_size(index->table))) { + btr_cur_get_block(cursor)->page.size) + || UNIV_UNLIKELY(entry->is_alter_metadata())) { /* The record is so big that we have to store some fields externally on separate database pages */ @@ -3660,7 +3762,7 @@ btr_cur_pessimistic_insert( if (index->disable_ahi); else # endif if (entry->info_bits & REC_INFO_MIN_REC_FLAG) { - ut_ad(entry->info_bits == REC_INFO_METADATA); + ut_ad(entry->is_metadata()); ut_ad(index->is_instant()); ut_ad((flags & ulint(~BTR_KEEP_IBUF_BITMAP)) == BTR_NO_LOCKING_FLAG); @@ -3745,6 +3847,50 @@ btr_cur_upd_lock_and_undo( cmpl_info, rec, offsets, roll_ptr)); } +/** Copy DB_TRX_ID,DB_ROLL_PTR to the redo log. +@param[in] index clustered index +@param[in] trx_id_t DB_TRX_ID +@param[in] roll_ptr DB_ROLL_PTR +@param[in,out] log_ptr redo log buffer +@return current end of the redo log buffer */ +static byte* +btr_cur_log_sys( + const dict_index_t* index, + trx_id_t trx_id, + roll_ptr_t roll_ptr, + byte* log_ptr) +{ + log_ptr += mach_write_compressed(log_ptr, index->db_trx_id()); + /* Yes, we are writing DB_ROLL_PTR,DB_TRX_ID in reverse order, + after emitting the position of DB_TRX_ID in the index. + This is how row_upd_write_sys_vals_to_log() + originally worked, and it is part of the redo log format. */ + trx_write_roll_ptr(log_ptr, roll_ptr); + log_ptr += DATA_ROLL_PTR_LEN; + log_ptr += mach_u64_write_compressed(log_ptr, trx_id); + + return log_ptr; +} + +/** Write DB_TRX_ID,DB_ROLL_PTR to a clustered index entry. +@param[in,out] entry clustered index entry +@param[in] index clustered index +@param[in] trx_id DB_TRX_ID +@param[in] roll_ptr DB_ROLL_PTR */ +static void btr_cur_write_sys( + dtuple_t* entry, + const dict_index_t* index, + trx_id_t trx_id, + roll_ptr_t roll_ptr) +{ + dfield_t* t = dtuple_get_nth_field(entry, index->db_trx_id()); + ut_ad(t->len == DATA_TRX_ID_LEN); + trx_write_trx_id(static_cast<byte*>(t->data), trx_id); + dfield_t* r = dtuple_get_nth_field(entry, index->db_roll_ptr()); + ut_ad(r->len == DATA_ROLL_PTR_LEN); + trx_write_roll_ptr(static_cast<byte*>(r->data), roll_ptr); +} + /***********************************************************//** Writes a redo log record of updating a record in-place. */ void @@ -3784,8 +3930,7 @@ btr_cur_update_in_place_log( log_ptr++; if (dict_index_is_clust(index)) { - log_ptr = row_upd_write_sys_vals_to_log( - index, trx_id, roll_ptr, log_ptr, mtr); + log_ptr = btr_cur_log_sys(index, trx_id, roll_ptr, log_ptr); } else { /* Dummy system fields for a secondary index */ /* TRX_ID Position */ @@ -4138,6 +4283,72 @@ func_exit: return(err); } +/** Trim a metadata record during the rollback of instant ALTER TABLE. +@param[in] entry metadata tuple +@param[in] index primary key +@param[in] update update vector for the rollback */ +ATTRIBUTE_COLD +static void btr_cur_trim_alter_metadata(dtuple_t* entry, + const dict_index_t* index, + const upd_t* update) +{ + ut_ad(index->is_instant()); + ut_ad(update->is_alter_metadata()); + ut_ad(entry->is_alter_metadata()); + + ut_ad(update->fields[0].field_no == index->first_user_field()); + ut_ad(update->fields[0].new_val.ext); + ut_ad(update->fields[0].new_val.len == FIELD_REF_SIZE); + ut_ad(entry->n_fields - 1 == index->n_fields); + + const byte* ptr = static_cast<const byte*>( + update->fields[0].new_val.data); + ut_ad(!mach_read_from_4(ptr + BTR_EXTERN_LEN)); + ut_ad(mach_read_from_4(ptr + BTR_EXTERN_LEN + 4) > 4); + ut_ad(mach_read_from_4(ptr + BTR_EXTERN_OFFSET) == FIL_PAGE_DATA); + ut_ad(mach_read_from_4(ptr + BTR_EXTERN_SPACE_ID) + == index->table->space->id); + + ulint n_fields = update->fields[1].field_no; + ut_ad(n_fields <= index->n_fields); + if (n_fields != index->n_uniq) { + ut_ad(n_fields + >= index->n_core_fields); + entry->n_fields = n_fields; + return; + } + + /* This is based on dict_table_t::deserialise_columns() + and btr_cur_instant_init_low(). */ + mtr_t mtr; + mtr.start(); + buf_block_t* block = buf_page_get( + page_id_t(index->table->space->id, + mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)), + univ_page_size, RW_S_LATCH, &mtr); + buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE); + ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_TYPE_BLOB); + ut_ad(mach_read_from_4(&block->frame[FIL_PAGE_DATA + + BTR_BLOB_HDR_NEXT_PAGE_NO]) + == FIL_NULL); + ut_ad(mach_read_from_4(&block->frame[FIL_PAGE_DATA + + BTR_BLOB_HDR_PART_LEN]) + == mach_read_from_4(ptr + BTR_EXTERN_LEN + 4)); + n_fields = mach_read_from_4( + &block->frame[FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE]) + + index->first_user_field(); + /* Rollback should not increase the number of fields. */ + ut_ad(n_fields <= index->n_fields); + ut_ad(n_fields + 1 <= entry->n_fields); + /* dict_index_t::clear_instant_alter() cannot be invoked while + rollback of an instant ALTER TABLE transaction is in progress + for an is_alter_metadata() record. */ + ut_ad(n_fields >= index->n_core_fields); + + mtr.commit(); + entry->n_fields = n_fields + 1; +} + /** Trim an update tuple due to instant ADD COLUMN, if needed. For normal records, the trailing instantly added fields that match the initial default values are omitted. @@ -4159,13 +4370,12 @@ btr_cur_trim( const que_thr_t* thr) { if (!index->is_instant()) { - } else if (UNIV_UNLIKELY(update->info_bits == REC_INFO_METADATA)) { + } else if (UNIV_UNLIKELY(update->is_metadata())) { /* We are either updating a metadata record - (instantly adding columns to a table where instant ADD was + (instant ALTER TABLE on a table where instant ALTER was already executed) or rolling back such an operation. */ ut_ad(!upd_get_nth_field(update, 0)->orig_len); - ut_ad(upd_get_nth_field(update, 0)->field_no - > index->n_core_fields); + ut_ad(entry->is_metadata()); if (thr->graph->trx->in_rollback) { /* This rollback can occur either as part of @@ -4182,6 +4392,13 @@ btr_cur_trim( first instantly added column logged by innobase_add_instant_try(). */ ut_ad(update->n_fields > 2); + if (update->is_alter_metadata()) { + btr_cur_trim_alter_metadata( + entry, index, update); + return; + } + ut_ad(!entry->is_alter_metadata()); + ulint n_fields = upd_get_nth_field(update, 0) ->field_no; ut_ad(n_fields + 1 >= entry->n_fields); @@ -4267,9 +4484,7 @@ btr_cur_optimistic_update( || trx_is_recv(thr_get_trx(thr))); #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ - const bool is_metadata = update->info_bits == REC_INFO_METADATA; - - if (UNIV_LIKELY(!is_metadata) + if (UNIV_LIKELY(!update->is_metadata()) && !row_upd_changes_field_size_or_external(index, *offsets, update)) { @@ -4295,6 +4510,10 @@ any_extern: return(DB_OVERFLOW); } + if (rec_is_metadata(rec, *index) && index->table->instant) { + goto any_extern; + } + for (i = 0; i < upd_get_n_fields(update); i++) { if (dfield_is_ext(&upd_get_nth_field(update, i)->new_val)) { @@ -4339,7 +4558,7 @@ any_extern: if (page_zip_rec_needs_ext(new_rec_size, page_is_comp(page), dict_index_get_n_fields(index), - dict_table_page_size(index->table))) { + block->page.size)) { goto any_extern; } @@ -4353,10 +4572,10 @@ any_extern: } /* We limit max record size to 16k even for 64k page size. */ - if (new_rec_size >= COMPRESSED_REC_MAX_DATA_SIZE || - (!dict_table_is_comp(index->table) - && new_rec_size >= REDUNDANT_REC_MAX_DATA_SIZE)) { - err = DB_OVERFLOW; + if (new_rec_size >= COMPRESSED_REC_MAX_DATA_SIZE || + (!dict_table_is_comp(index->table) + && new_rec_size >= REDUNDANT_REC_MAX_DATA_SIZE)) { + err = DB_OVERFLOW; goto func_exit; } @@ -4429,8 +4648,8 @@ any_extern: lock_rec_store_on_page_infimum(block, rec); } - if (UNIV_UNLIKELY(is_metadata)) { - ut_ad(new_entry->info_bits == REC_INFO_METADATA); + if (UNIV_UNLIKELY(update->is_metadata())) { + ut_ad(new_entry->is_metadata()); ut_ad(index->is_instant()); /* This can be innobase_add_instant_try() performing a subsequent instant ADD COLUMN, or its rollback by @@ -4445,10 +4664,7 @@ any_extern: page_cur_move_to_prev(page_cursor); if (!(flags & BTR_KEEP_SYS_FLAG)) { - row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR, - roll_ptr); - row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID, - trx_id); + btr_cur_write_sys(new_entry, index, trx_id, roll_ptr); } /* There are no externally stored columns in new_entry */ @@ -4456,7 +4672,7 @@ any_extern: cursor, new_entry, offsets, heap, 0/*n_ext*/, mtr); ut_a(rec); /* <- We calculated above the insert would fit */ - if (UNIV_UNLIKELY(is_metadata)) { + if (UNIV_UNLIKELY(update->is_metadata())) { /* We must empty the PAGE_FREE list, because if this was a rollback, the shortened metadata record would have too many fields, and we would be unable to @@ -4650,8 +4866,25 @@ btr_cur_pessimistic_update( rec, index, *offsets, page_is_leaf(page), ULINT_UNDEFINED, offsets_heap); - dtuple_t* new_entry = row_rec_to_index_entry( - rec, index, *offsets, &n_ext, entry_heap); + dtuple_t* new_entry; + + const bool is_metadata = rec_is_metadata(rec, *index); + + if (UNIV_UNLIKELY(is_metadata)) { + ut_ad(update->is_metadata()); + ut_ad(flags & BTR_NO_LOCKING_FLAG); + ut_ad(index->is_instant()); + new_entry = row_metadata_to_tuple( + rec, index, *offsets, + &n_ext, entry_heap, + update->info_bits, !thr_get_trx(thr)->in_rollback); + ut_ad(new_entry->n_fields + == ulint(index->n_fields) + + update->is_alter_metadata()); + } else { + new_entry = row_rec_to_index_entry(rec, index, *offsets, + &n_ext, entry_heap); + } /* The page containing the clustered index record corresponding to new_entry is latched in mtr. If the @@ -4663,9 +4896,6 @@ btr_cur_pessimistic_update( entry_heap); btr_cur_trim(new_entry, index, update, thr); - const bool is_metadata = new_entry->info_bits - & REC_INFO_MIN_REC_FLAG; - /* We have to set appropriate extern storage bits in the new record to be inserted: we have to remember which fields were such */ @@ -4693,11 +4923,14 @@ btr_cur_pessimistic_update( } if (page_zip_rec_needs_ext( - rec_get_converted_size(index, new_entry, n_ext), - page_is_comp(page), - dict_index_get_n_fields(index), - block->page.size)) { - + rec_get_converted_size(index, new_entry, n_ext), + page_is_comp(page), + dict_index_get_n_fields(index), + block->page.size) + || (UNIV_UNLIKELY(update->is_alter_metadata()) + && !dfield_is_ext(dtuple_get_nth_field( + new_entry, + index->first_user_field())))) { big_rec_vec = dtuple_convert_big_rec(index, update, new_entry, &n_ext); if (UNIV_UNLIKELY(big_rec_vec == NULL)) { @@ -4746,10 +4979,7 @@ btr_cur_pessimistic_update( } if (!(flags & BTR_KEEP_SYS_FLAG)) { - row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR, - roll_ptr); - row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID, - trx_id); + btr_cur_write_sys(new_entry, index, trx_id, roll_ptr); } if (!page_zip) { @@ -4758,10 +4988,10 @@ btr_cur_pessimistic_update( } if (UNIV_UNLIKELY(is_metadata)) { - ut_ad(new_entry->info_bits == REC_INFO_METADATA); + ut_ad(new_entry->is_metadata()); ut_ad(index->is_instant()); /* This can be innobase_add_instant_try() performing a - subsequent instant ADD COLUMN, or its rollback by + subsequent instant ALTER TABLE, or its rollback by row_undo_mod_clust_low(). */ ut_ad(flags & BTR_NO_LOCKING_FLAG); } else { @@ -4810,7 +5040,8 @@ btr_cur_pessimistic_update( btr_cur_get_block(cursor), rec, block); } - if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))) { + if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets)) + || rec_is_alter_metadata(rec, *index)) { /* The new inserted record owns its possible externally stored fields */ btr_cur_unmark_extern_fields( @@ -5020,8 +5251,7 @@ btr_cur_del_mark_set_clust_rec_log( *log_ptr++ = 0; *log_ptr++ = 1; - log_ptr = row_upd_write_sys_vals_to_log( - index, trx_id, roll_ptr, log_ptr, mtr); + log_ptr = btr_cur_log_sys(index, trx_id, roll_ptr, log_ptr); mach_write_to_2(log_ptr, page_offset(rec)); log_ptr += 2; @@ -5453,42 +5683,41 @@ btr_cur_optimistic_delete_func( if (UNIV_UNLIKELY(page_is_root(block->frame) && page_get_n_recs(block->frame) == 1 + (cursor->index->is_instant() - && !rec_is_metadata(rec, cursor->index)))) { + && !rec_is_metadata(rec, *cursor->index)))) { /* The whole index (and table) becomes logically empty. Empty the whole page. That is, if we are deleting the only user record, also delete the metadata record - if one exists (it exists if and only if is_instant()). + if one exists for instant ADD COLUMN (not generic ALTER TABLE). If we are deleting the metadata record and the table becomes empty, clean up the whole page. */ dict_index_t* index = cursor->index; + const rec_t* first_rec = page_rec_get_next_const( + page_get_infimum_rec(block->frame)); ut_ad(!index->is_instant() - || rec_is_metadata( - page_rec_get_next_const( - page_get_infimum_rec(block->frame)), - index)); - if (UNIV_UNLIKELY(rec_get_info_bits(rec, page_rec_is_comp(rec)) - & REC_INFO_MIN_REC_FLAG)) { - /* This should be rolling back instant ADD COLUMN. - If this is a recovered transaction, then - index->is_instant() will hold until the - insert into SYS_COLUMNS is rolled back. */ - ut_ad(index->table->supports_instant()); - ut_ad(index->is_primary()); - } else { - lock_update_delete(block, rec); - } - btr_page_empty(block, buf_block_get_page_zip(block), - index, 0, mtr); - page_cur_set_after_last(block, btr_cur_get_page_cur(cursor)); - - if (index->is_primary()) { - /* Concurrent access is prevented by - root_block->lock X-latch, so this should be - safe. */ - index->remove_instant(); + || rec_is_metadata(first_rec, *index)); + const bool is_metadata = rec_is_metadata(rec, *index); + /* We can remove the metadata when rolling back an + instant ALTER TABLE operation, or when deleting the + last user record on the page such that only metadata for + instant ADD COLUMN (not generic ALTER TABLE) remains. */ + const bool empty_table = is_metadata + || !index->is_instant() + || (first_rec != rec + && rec_is_add_metadata(first_rec, *index)); + if (UNIV_LIKELY(empty_table)) { + if (UNIV_LIKELY(!is_metadata)) { + lock_update_delete(block, rec); + } + btr_page_empty(block, buf_block_get_page_zip(block), + index, 0, mtr); + if (index->is_instant()) { + /* MDEV-17383: free metadata BLOBs! */ + index->clear_instant_alter(); + } + page_cur_set_after_last(block, + btr_cur_get_page_cur(cursor)); + return true; } - - return true; } offsets = rec_get_offsets(rec, cursor->index, offsets, true, @@ -5668,10 +5897,10 @@ btr_cur_pessimistic_delete( } if (page_is_leaf(page)) { - const bool is_metadata = rec_get_info_bits( - rec, page_rec_is_comp(rec)) & REC_INFO_MIN_REC_FLAG; + const bool is_metadata = rec_is_metadata( + rec, page_rec_is_comp(rec)); if (UNIV_UNLIKELY(is_metadata)) { - /* This should be rolling back instant ADD COLUMN. + /* This should be rolling back instant ALTER TABLE. If this is a recovered transaction, then index->is_instant() will hold until the insert into SYS_COLUMNS is rolled back. */ @@ -5687,30 +5916,34 @@ btr_cur_pessimistic_delete( goto discard_page; } } else if (page_get_n_recs(page) == 1 - + (index->is_instant() - && !rec_is_metadata(rec, index))) { + + (index->is_instant() && !is_metadata)) { /* The whole index (and table) becomes logically empty. Empty the whole page. That is, if we are deleting the only user record, also delete the metadata record - if one exists (it exists if and only if is_instant()). - If we are deleting the metadata record and the + if one exists for instant ADD COLUMN + (not generic ALTER TABLE). + If we are deleting the metadata record + (in the rollback of instant ALTER TABLE) and the table becomes empty, clean up the whole page. */ + + const rec_t* first_rec = page_rec_get_next_const( + page_get_infimum_rec(page)); ut_ad(!index->is_instant() - || rec_is_metadata( - page_rec_get_next_const( - page_get_infimum_rec(page)), - index)); - btr_page_empty(block, page_zip, index, 0, mtr); - page_cur_set_after_last(block, - btr_cur_get_page_cur(cursor)); - if (index->is_primary()) { - /* Concurrent access is prevented by - index->lock and root_block->lock - X-latch, so this should be safe. */ - index->remove_instant(); + || rec_is_metadata(first_rec, *index)); + if (is_metadata || !index->is_instant() + || (first_rec != rec + && rec_is_add_metadata(first_rec, *index))) { + btr_page_empty(block, page_zip, index, 0, mtr); + if (index->is_instant()) { + /* MDEV-17383: free metadata BLOBs! */ + index->clear_instant_alter(); + } + page_cur_set_after_last( + block, + btr_cur_get_page_cur(cursor)); + ret = TRUE; + goto return_after_reservations; } - ret = TRUE; - goto return_after_reservations; } if (UNIV_LIKELY(!is_metadata)) { @@ -7293,8 +7526,8 @@ btr_store_big_rec_extern_fields( ut_ad(buf_block_get_frame(rec_block) == page_align(rec)); ut_a(dict_index_is_clust(index)); - ut_a(dict_table_page_size(index->table) - .equals_to(rec_block->page.size)); + ut_ad(dict_table_page_size(index->table) + .equals_to(rec_block->page.size)); btr_blob_log_check_t redo_log(pcur, btr_mtr, offsets, &rec_block, &rec, op); @@ -7339,15 +7572,13 @@ btr_store_big_rec_extern_fields( } #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ - const page_size_t page_size(dict_table_page_size(index->table)); - /* Space available in compressed page to carry blob data */ - const ulint payload_size_zip = page_size.physical() + const ulint payload_size_zip = rec_block->page.size.physical() - FIL_PAGE_DATA; /* Space available in uncompressed page to carry blob data */ - const ulint payload_size = page_size.physical() - - FIL_PAGE_DATA - BTR_BLOB_HDR_SIZE - FIL_PAGE_DATA_END; + const ulint payload_size = payload_size_zip + - (BTR_BLOB_HDR_SIZE + FIL_PAGE_DATA_END); /* We have to create a file segment to the tablespace for each field and put the pointer to the field in rec */ @@ -7540,16 +7771,20 @@ btr_store_big_rec_extern_fields( + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, rec_page_no, MLOG_4BYTES, &mtr); - - /* Zero out the unused part of the page. */ - memset(page + page_zip_get_size(page_zip) - - c_stream.avail_out, - 0, c_stream.avail_out); mlog_log_string(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, page_zip_get_size(page_zip) - - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, + - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + - c_stream.avail_out, &mtr); + /* Zero out the unused part of the page. */ + if (c_stream.avail_out) { + mlog_memset(block, + page_zip_get_size(page_zip) + - c_stream.avail_out, + c_stream.avail_out, + 0, &mtr); + } /* Copy the page to compressed storage, because it will be flushed to disk from there. */ diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 41661d226e1..3f898f7d033 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -151,13 +151,20 @@ btr_pcur_store_position( rec = page_rec_get_prev(rec); ut_ad(!page_rec_is_infimum(rec)); - ut_ad(!rec_is_metadata(rec, index)); + if (UNIV_UNLIKELY(rec_is_metadata(rec, *index))) { + ut_ad(index->table->instant); + ut_ad(page_get_n_recs(block->frame) == 1); + ut_ad(page_is_leaf(page)); + ut_ad(page_get_page_no(page) == index->page); + cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; + return; + } cursor->rel_pos = BTR_PCUR_AFTER; } else if (page_rec_is_infimum_low(offs)) { rec = page_rec_get_next(rec); - if (rec_is_metadata(rec, index)) { + if (rec_is_metadata(rec, *index)) { rec = page_rec_get_next(rec); ut_ad(!page_rec_is_supremum(rec)); } @@ -167,10 +174,25 @@ btr_pcur_store_position( cursor->rel_pos = BTR_PCUR_ON; } - cursor->old_rec = dict_index_copy_rec_order_prefix( - index, rec, &cursor->old_n_fields, - &cursor->old_rec_buf, &cursor->buf_size); + if (index->is_ibuf()) { + ut_ad(!index->table->not_redundant()); + cursor->old_n_fields = rec_get_n_fields_old(rec); + } else if (page_rec_is_leaf(rec)) { + cursor->old_n_fields = dict_index_get_n_unique_in_tree(index); + } else if (index->is_spatial()) { + ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index) + == DICT_INDEX_SPATIAL_NODEPTR_SIZE); + /* For R-tree, we have to compare + the child page numbers as well. */ + cursor->old_n_fields = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1; + } else { + cursor->old_n_fields = dict_index_get_n_unique_in_tree(index); + } + cursor->old_rec = rec_copy_prefix_to_buf(rec, index, + cursor->old_n_fields, + &cursor->old_rec_buf, + &cursor->buf_size); cursor->block_when_stored = block; /* Function try to check if block is S/X latch. */ diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 9c2dedeef9e..37a839727ec 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -1190,7 +1190,7 @@ retry: rec = page_get_infimum_rec(page); rec = page_rec_get_next_low(rec, page_is_comp(page)); - if (rec_is_metadata(rec, index)) { + if (rec_is_metadata(rec, *index)) { rec = page_rec_get_next_low(rec, page_is_comp(page)); } @@ -1398,7 +1398,7 @@ btr_search_build_page_hash_index( rec = page_rec_get_next_const(page_get_infimum_rec(page)); - if (rec_is_metadata(rec, index)) { + if (rec_is_metadata(rec, *index)) { rec = page_rec_get_next_const(rec); if (!--n_recs) return; } @@ -1862,7 +1862,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) n_bytes, index->id); } - if (!page_rec_is_infimum(rec) && !rec_is_metadata(rec, index)) { + if (!page_rec_is_infimum(rec) && !rec_is_metadata(rec, *index)) { offsets = rec_get_offsets( rec, index, offsets, true, btr_search_get_n_fields(n_fields, n_bytes), &heap); diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index d1e008d8be4..452a591e1c3 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -35,12 +35,9 @@ Created 11/5/1995 Heikki Tuuri #include "mach0data.h" #include "page0size.h" #include "buf0buf.h" +#include "buf0checksum.h" #include <string.h> -#ifdef UNIV_NONINL -#include "buf0buf.ic" -#endif - #ifndef UNIV_INNOCHECKSUM #include "mem0mem.h" #include "btr0btr.h" @@ -60,19 +57,14 @@ Created 11/5/1995 Heikki Tuuri #include "dict0dict.h" #include "log0recv.h" #include "srv0mon.h" +#include "fil0pagecompress.h" +#include "fsp0pagecompress.h" #endif /* !UNIV_INNOCHECKSUM */ #include "page0zip.h" #include "sync0sync.h" #include "buf0dump.h" -#include <new> #include <map> #include <sstream> -#ifndef UNIV_INNOCHECKSUM -#include "fil0pagecompress.h" -#include "fsp0pagecompress.h" -#endif -#include "ut0byte.h" -#include <new> #ifdef UNIV_LINUX #include <stdlib.h> @@ -765,11 +757,7 @@ buf_page_is_checksum_valid_crc32( return false; } - return checksum_field1 == crc32 -#ifdef INNODB_BUG_ENDIAN_CRC32 - || checksum_field1 == buf_calc_page_crc32(read_buf, true) -#endif - ; + return checksum_field1 == crc32; } /** Checks if the page is in innodb checksum format. @@ -898,29 +886,6 @@ buf_page_is_checksum_valid_none( && checksum_field1 == BUF_NO_CHECKSUM_MAGIC); } -#ifdef INNODB_BUG_ENDIAN_CRC32 -/** Validate the CRC-32C checksum of a page. -@param[in] page buffer page (srv_page_size bytes) -@param[in] checksum CRC-32C checksum stored on page -@return computed checksum */ -static uint32_t buf_page_check_crc32(const byte* page, uint32_t checksum) -{ - uint32_t crc32 = buf_calc_page_crc32(page); - - if (checksum != crc32) { - crc32 = buf_calc_page_crc32(page, true); - } - - return crc32; -} -#else /* INNODB_BUG_ENDIAN_CRC32 */ -/** Validate the CRC-32C checksum of a page. -@param[in] page buffer page (srv_page_size bytes) -@param[in] checksum CRC-32C checksum stored on page -@return computed checksum */ -# define buf_page_check_crc32(page, checksum) buf_calc_page_crc32(page) -#endif /* INNODB_BUG_ENDIAN_CRC32 */ - /** Check if a page is corrupt. @param[in] check_lsn whether the LSN should be checked @param[in] read_buf database page @@ -1099,8 +1064,7 @@ buf_page_is_corrupted( if (srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_CRC32) { - crc32 = buf_page_check_crc32(read_buf, - checksum_field2); + crc32 = buf_calc_page_crc32(read_buf); crc32_inited = true; if (checksum_field2 != crc32 @@ -1114,8 +1078,7 @@ buf_page_is_corrupted( if (checksum_field2 != buf_calc_page_old_checksum(read_buf)) { - crc32 = buf_page_check_crc32( - read_buf, checksum_field2); + crc32 = buf_calc_page_crc32(read_buf); crc32_inited = true; if (checksum_field2 != crc32) { @@ -1131,8 +1094,7 @@ buf_page_is_corrupted( == SRV_CHECKSUM_ALGORITHM_CRC32) { if (!crc32_inited) { - crc32 = buf_page_check_crc32( - read_buf, checksum_field2); + crc32 = buf_calc_page_crc32(read_buf); crc32_inited = true; } @@ -1149,8 +1111,7 @@ buf_page_is_corrupted( != buf_calc_page_new_checksum(read_buf)) { if (!crc32_inited) { - crc32 = buf_page_check_crc32( - read_buf, checksum_field2); + crc32 = buf_calc_page_crc32(read_buf); crc32_inited = true; } @@ -1257,12 +1218,6 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) << page_zip_calc_checksum( read_buf, page_size.physical(), SRV_CHECKSUM_ALGORITHM_CRC32) -#ifdef INNODB_BUG_ENDIAN_CRC32 - << "/" - << page_zip_calc_checksum( - read_buf, page_size.physical(), - SRV_CHECKSUM_ALGORITHM_CRC32, true) -#endif << ", " << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_INNODB) @@ -1288,10 +1243,6 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) } else { const uint32_t crc32 = buf_calc_page_crc32(read_buf); -#ifdef INNODB_BUG_ENDIAN_CRC32 - const uint32_t crc32_legacy = buf_calc_page_crc32(read_buf, - true); -#endif /* INNODB_BUG_ENDIAN_CRC32 */ ulint page_type = fil_page_get_type(read_buf); ib::info() << "Uncompressed page, stored checksum in field1 " @@ -1301,9 +1252,6 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_CRC32) << " " << crc32 -#ifdef INNODB_BUG_ENDIAN_CRC32 - << "/" << crc32_legacy -#endif << ", " << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_INNODB) << " " @@ -1321,9 +1269,6 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_CRC32) << " " << crc32 -#ifdef INNODB_BUG_ENDIAN_CRC32 - << "/" << crc32_legacy -#endif << ", " << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_INNODB) << " " @@ -3960,12 +3905,6 @@ buf_zip_decompress( << ", crc32: " << page_zip_calc_checksum( frame, size, SRV_CHECKSUM_ALGORITHM_CRC32) -#ifdef INNODB_BUG_ENDIAN_CRC32 - << "/" - << page_zip_calc_checksum( - frame, size, SRV_CHECKSUM_ALGORITHM_CRC32, - true) -#endif << " innodb: " << page_zip_calc_checksum( frame, size, SRV_CHECKSUM_ALGORITHM_INNODB) @@ -6122,7 +6061,6 @@ database_corrupted: && !recv_no_ibuf_operations && (bpage->id.space() == 0 || !is_predefined_tablespace(bpage->id.space())) - && !srv_is_tablespace_truncated(bpage->id.space()) && fil_page_get_type(frame) == FIL_PAGE_INDEX && page_is_leaf(frame)) { diff --git a/storage/innobase/buf/buf0checksum.cc b/storage/innobase/buf/buf0checksum.cc index 6c103c4f44b..daff452de08 100644 --- a/storage/innobase/buf/buf0checksum.cc +++ b/storage/innobase/buf/buf0checksum.cc @@ -39,35 +39,6 @@ ha_innodb.cc:12251: error: cannot convert 'srv_checksum_algorithm_t*' to 'long unsigned int*' in initialization */ ulong srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_INNODB; -#ifdef INNODB_BUG_ENDIAN_CRC32 -/** Calculate the CRC32 checksum of a page. The value is stored to the page -when it is written to a file and also checked for a match when reading from -the file. Note that we must be careful to calculate the same value on all -architectures. -@param[in] page buffer page (srv_page_size bytes) -@param[in] bug_endian whether to use big endian byteorder -when converting byte strings to integers, for bug-compatibility with -big-endian architecture running MySQL 5.6, MariaDB 10.0 or MariaDB 10.1 -@return CRC-32C */ -uint32_t buf_calc_page_crc32(const byte* page, bool bug_endian) -{ - return bug_endian - ? ut_crc32_legacy_big_endian( - page + FIL_PAGE_OFFSET, - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION - - FIL_PAGE_OFFSET) - ^ ut_crc32_legacy_big_endian(page + FIL_PAGE_DATA, - srv_page_size - - (FIL_PAGE_DATA - + FIL_PAGE_END_LSN_OLD_CHKSUM)) - : ut_crc32(page + FIL_PAGE_OFFSET, - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION - - FIL_PAGE_OFFSET) - ^ ut_crc32(page + FIL_PAGE_DATA, - srv_page_size - - (FIL_PAGE_DATA + FIL_PAGE_END_LSN_OLD_CHKSUM)); -} -#else /** Calculate the CRC32 checksum of a page. The value is stored to the page when it is written to a file and also checked for a match when reading from the file. Note that we must be careful to calculate the same value on all @@ -88,7 +59,6 @@ uint32_t buf_calc_page_crc32(const byte* page) srv_page_size - (FIL_PAGE_DATA + FIL_PAGE_END_LSN_OLD_CHKSUM)); } -#endif /** Calculate a checksum which is stored to the page when it is written to a file. Note that we must be careful to calculate the same value on diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 785ec21a7bf..0eaa746deb8 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -569,12 +569,9 @@ buf_dblwr_process() if (page_no >= space->size) { - /* Do not report the warning if the tablespace - is scheduled for truncation or was truncated - and we have parsed an MLOG_TRUNCATE record. */ - if (!srv_is_tablespace_truncated(space_id) - && !srv_was_tablespace_truncated(space) - && !srv_is_undo_tablespace(space_id)) { + /* Do not report the warning for undo + tablespaces, because they can be truncated in place. */ + if (!srv_is_undo_tablespace(space_id)) { ib::warn() << "A copy of page " << page_id << " in the doublewrite buffer slot " << page_no_dblwr diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index 3edb6c6ee98..9454b57f59e 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -95,11 +95,9 @@ buffer buf_pool if it is not already there, in which case does nothing. Sets the io_fix flag and sets an exclusive lock on the buffer frame. The flag is cleared and the x-lock released by an i/o-handler thread. -@param[out] err DB_SUCCESS, DB_TABLESPACE_DELETED or - DB_TABLESPACE_TRUNCATED if we are trying - to read from a non-existent tablespace, a - tablespace which is just now being dropped, - or a tablespace which is truncated +@param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED + if we are trying + to read from a non-existent tablespace @param[in] sync true if synchronous aio is desired @param[in] type IO type, SIMULATED, IGNORE_MISSING @param[in] mode BUF_READ_IBUF_PAGES_ONLY, ..., @@ -187,20 +185,8 @@ buf_read_page_low( } if (*err != DB_SUCCESS) { - if (*err == DB_TABLESPACE_TRUNCATED) { - /* Remove the page which is outside the - truncated tablespace bounds when recovering - from a crash happened during a truncation */ - buf_read_page_handle_error(bpage); - if (recv_recovery_on) { - mutex_enter(&recv_sys->mutex); - ut_ad(recv_sys->n_addrs > 0); - recv_sys->n_addrs--; - mutex_exit(&recv_sys->mutex); - } - return(0); - } else if (IORequest::ignore_missing(type) - || *err == DB_TABLESPACE_DELETED) { + if (IORequest::ignore_missing(type) + || *err == DB_TABLESPACE_DELETED) { buf_read_page_handle_error(bpage); return(0); } @@ -369,7 +355,6 @@ read_ahead: switch (err) { case DB_SUCCESS: - case DB_TABLESPACE_TRUNCATED: case DB_ERROR: break; case DB_TABLESPACE_DELETED: @@ -472,7 +457,6 @@ buf_read_page_background( switch (err) { case DB_SUCCESS: - case DB_TABLESPACE_TRUNCATED: case DB_ERROR: break; case DB_TABLESPACE_DELETED: @@ -755,7 +739,6 @@ buf_read_ahead_linear( switch (err) { case DB_SUCCESS: - case DB_TABLESPACE_TRUNCATED: case DB_TABLESPACE_DELETED: case DB_ERROR: break; @@ -853,7 +836,6 @@ tablespace_deleted: switch(err) { case DB_SUCCESS: - case DB_TABLESPACE_TRUNCATED: case DB_ERROR: break; case DB_TABLESPACE_DELETED: diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc index cc14664821f..c3e727267eb 100644 --- a/storage/innobase/data/data0data.cc +++ b/storage/innobase/data/data0data.cc @@ -58,7 +58,12 @@ void dtuple_t::trim(const dict_index_t& index) for (; i > index.n_core_fields; i--) { const dfield_t* dfield = dtuple_get_nth_field(this, i - 1); const dict_col_t* col = dict_index_get_nth_col(&index, i - 1); - ut_ad(col->is_instant()); + + if (col->is_dropped()) { + continue; + } + + ut_ad(col->is_added()); ulint len = dfield_get_len(dfield); if (len != col->def_val.len) { break; @@ -596,7 +601,6 @@ dtuple_convert_big_rec( mem_heap_t* heap; big_rec_t* vector; dfield_t* dfield; - dict_field_t* ifield; ulint size; ulint n_fields; ulint local_len; @@ -606,14 +610,7 @@ dtuple_convert_big_rec( return(NULL); } - if (!dict_table_has_atomic_blobs(index->table)) { - /* up to MySQL 5.1: store a 768-byte prefix locally */ - local_len = BTR_EXTERN_FIELD_REF_SIZE - + DICT_ANTELOPE_MAX_INDEX_COL_LEN; - } else { - /* new-format table: do not store any BLOB prefix locally */ - local_len = BTR_EXTERN_FIELD_REF_SIZE; - } + ut_ad(index->n_uniq > 0); ut_a(dtuple_check_typed_no_assert(entry)); @@ -636,24 +633,41 @@ dtuple_convert_big_rec( stored externally */ n_fields = 0; + ulint longest_i; + + const bool mblob = entry->is_alter_metadata(); + ut_ad(entry->n_fields >= index->first_user_field() + mblob); + ut_ad(entry->n_fields - mblob <= index->n_fields); + + if (mblob) { + longest_i = index->first_user_field(); + dfield = dtuple_get_nth_field(entry, longest_i); + local_len = BTR_EXTERN_FIELD_REF_SIZE; + goto ext_write; + } + + if (!dict_table_has_atomic_blobs(index->table)) { + /* up to MySQL 5.1: store a 768-byte prefix locally */ + local_len = BTR_EXTERN_FIELD_REF_SIZE + + DICT_ANTELOPE_MAX_INDEX_COL_LEN; + } else { + /* new-format table: do not store any BLOB prefix locally */ + local_len = BTR_EXTERN_FIELD_REF_SIZE; + } while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry, *n_ext), - dict_table_is_comp(index->table), + index->table->not_redundant(), dict_index_get_n_fields(index), dict_table_page_size(index->table))) { - - ulint i; - ulint longest = 0; - ulint longest_i = ULINT_MAX; - byte* data; - - for (i = dict_index_get_n_unique_in_tree(index); - i < dtuple_get_n_fields(entry); i++) { + longest_i = 0; + for (ulint i = index->first_user_field(), longest = 0; + i + mblob < entry->n_fields; i++) { ulint savings; + dfield = dtuple_get_nth_field(entry, i + mblob); - dfield = dtuple_get_nth_field(entry, i); - ifield = dict_index_get_nth_field(index, i); + const dict_field_t* ifield = dict_index_get_nth_field( + index, i); /* Skip fixed-length, NULL, externally stored, or short columns */ @@ -695,7 +709,7 @@ skip_field: continue; } - if (!longest) { + if (!longest_i) { /* Cannot shorten more */ mem_heap_free(heap); @@ -708,9 +722,8 @@ skip_field: We store the first bytes locally to the record. Then we can calculate all ordering fields in all indexes from locally stored data. */ - dfield = dtuple_get_nth_field(entry, longest_i); - ifield = dict_index_get_nth_field(index, longest_i); +ext_write: local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE; vector->append( @@ -721,7 +734,8 @@ skip_field: + local_prefix_len)); /* Allocate the locally stored part of the column. */ - data = static_cast<byte*>(mem_heap_alloc(heap, local_len)); + byte* data = static_cast<byte*>( + mem_heap_alloc(heap, local_len)); /* Copy the local prefix. */ memcpy(data, dfield_get_data(dfield), local_prefix_len); @@ -735,7 +749,6 @@ skip_field: UNIV_MEM_ALLOC(data + local_prefix_len, BTR_EXTERN_FIELD_REF_SIZE); #endif - dfield_set_data(dfield, data, local_len); dfield_set_ext(dfield); diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index e5bf33593ed..7a9b8556c1a 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, MariaDB Corporation. +Copyright (c) 2016, 2018, MariaDB Corporation. 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 @@ -64,52 +64,14 @@ dict_hdr_get_new_id( (not assigned if NULL) */ index_id_t* index_id, /*!< out: index id (not assigned if NULL) */ - ulint* space_id, /*!< out: space id + ulint* space_id) /*!< out: space id (not assigned if NULL) */ - const dict_table_t* table, /*!< in: table */ - bool disable_redo) /*!< in: if true and table - object is NULL - then disable-redo */ { dict_hdr_t* dict_hdr; ib_id_t id; mtr_t mtr; mtr_start(&mtr); - if (table) { - if (table->is_temporary()) { - mtr.set_log_mode(MTR_LOG_NO_REDO); - } - } else if (disable_redo) { - /* In non-read-only mode we need to ensure that space-id header - page is written to disk else if page is removed from buffer - cache and re-loaded it would assign temporary tablespace id - to another tablespace. - This is not a case with read-only mode as there is no new object - that is created except temporary tablespace. */ - mtr.set_log_mode(srv_read_only_mode - ? MTR_LOG_NONE : MTR_LOG_NO_REDO); - } - - /* Server started and let's say space-id = x - - table created with file-per-table - - space-id = x + 1 - - crash - Case 1: If it was redo logged then we know that it will be - restored to x + 1 - Case 2: if not redo-logged - Header will have the old space-id = x - This is OK because on restart there is no object with - space id = x + 1 - Case 3: - space-id = x (on start) - space-id = x+1 (temp-table allocation) - no redo logging - space-id = x+2 (non-temp-table allocation), this get's - redo logged. - If there is a crash there will be only 2 entries - x (original) and x+2 (new) and disk hdr will be updated - to reflect x + 2 entry. - We cannot allocate the same space id to different objects. */ dict_hdr = dict_hdr_get(&mtr); if (table_id) { @@ -212,7 +174,7 @@ dict_hdr_create( /*--------------------------*/ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, fil_system.sys_space, DICT_TABLES_ID, - dict_ind_redundant, NULL, mtr); + dict_ind_redundant, mtr); if (root_page_no == FIL_NULL) { return(FALSE); @@ -223,7 +185,7 @@ dict_hdr_create( /*--------------------------*/ root_page_no = btr_create(DICT_UNIQUE, fil_system.sys_space, DICT_TABLE_IDS_ID, - dict_ind_redundant, NULL, mtr); + dict_ind_redundant, mtr); if (root_page_no == FIL_NULL) { return(FALSE); @@ -234,7 +196,7 @@ dict_hdr_create( /*--------------------------*/ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, fil_system.sys_space, DICT_COLUMNS_ID, - dict_ind_redundant, NULL, mtr); + dict_ind_redundant, mtr); if (root_page_no == FIL_NULL) { return(FALSE); @@ -245,7 +207,7 @@ dict_hdr_create( /*--------------------------*/ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, fil_system.sys_space, DICT_INDEXES_ID, - dict_ind_redundant, NULL, mtr); + dict_ind_redundant, mtr); if (root_page_no == FIL_NULL) { return(FALSE); @@ -256,7 +218,7 @@ dict_hdr_create( /*--------------------------*/ root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE, fil_system.sys_space, DICT_FIELDS_ID, - dict_ind_redundant, NULL, mtr); + dict_ind_redundant, mtr); if (root_page_no == FIL_NULL) { return(FALSE); diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index 25a90342f78..b1ddb7032ab 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -352,10 +352,12 @@ dict_build_table_def_step( { ut_ad(mutex_own(&dict_sys->mutex)); dict_table_t* table = node->table; + trx_t* trx = thr_get_trx(thr); ut_ad(!table->is_temporary()); ut_ad(!table->space); ut_ad(table->space_id == ULINT_UNDEFINED); - dict_table_assign_new_id(table, thr_get_trx(thr)); + dict_hdr_get_new_id(&table->id, NULL, NULL); + trx->table_id = table->id; /* Always set this bit for all new created tables */ DICT_TF2_FLAG_SET(table, DICT_TF2_FTS_AUX_HEX_NAME); @@ -368,8 +370,6 @@ dict_build_table_def_step( ut_ad(DICT_TF_GET_ZIP_SSIZE(table->flags) == 0 || dict_table_has_atomic_blobs(table)); - trx_t* trx = thr_get_trx(thr); - ut_ad(trx->table_id); mtr_t mtr; trx_undo_t* undo = trx->rsegs.m_redo.undo; if (undo && !undo->table_id @@ -397,7 +397,7 @@ dict_build_table_def_step( } /* Get a new tablespace ID */ ulint space_id; - dict_hdr_get_new_id(NULL, NULL, &space_id, table, false); + dict_hdr_get_new_id(NULL, NULL, &space_id); DBUG_EXECUTE_IF( "ib_create_table_fail_out_of_space_ids", @@ -745,7 +745,7 @@ dict_build_index_def_step( ut_ad((UT_LIST_GET_LEN(table->indexes) > 0) || dict_index_is_clust(index)); - dict_hdr_get_new_id(NULL, &index->id, NULL, table, false); + dict_hdr_get_new_id(NULL, &index->id, NULL); /* Inherit the space id from the table; we store all indexes of a table in the same tablespace */ @@ -785,7 +785,7 @@ dict_build_index_def( ut_ad((UT_LIST_GET_LEN(table->indexes) > 0) || dict_index_is_clust(index)); - dict_hdr_get_new_id(NULL, &index->id, NULL, table, false); + dict_hdr_get_new_id(NULL, &index->id, NULL); /* Note that the index was created by this transaction. */ index->trx_id = trx->id; @@ -859,7 +859,7 @@ dict_create_index_tree_step( node->page_no = btr_create( index->type, index->table->space, - index->id, index, NULL, &mtr); + index->id, index, &mtr); if (node->page_no == FIL_NULL) { err = DB_OUT_OF_FILE_SPACE; @@ -905,7 +905,7 @@ dict_create_index_tree_in_mem( ut_ad(!(index->table->flags2 & DICT_TF2_DISCARDED)); index->page = btr_create(index->type, index->table->space, - index->id, index, NULL, &mtr); + index->id, index, &mtr); mtr_commit(&mtr); index->trx_id = trx->id; @@ -971,13 +971,6 @@ dict_drop_index_tree( return(false); } - /* If tablespace is scheduled for truncate, do not try to drop - the indexes in that tablespace. There is a truncate fixup action - which will take care of it. */ - if (srv_is_tablespace_truncated(space)) { - return(false); - } - btr_free_if_exists(page_id_t(space, root_page_no), page_size, mach_read_from_8(ptr), mtr); @@ -1053,7 +1046,7 @@ dict_recreate_index_tree( ulint root_page_no = (index->type & DICT_FTS) ? FIL_NULL : btr_create(type, table->space, - index_id, index, NULL, mtr); + index_id, index, mtr); index->page = unsigned(root_page_no); return root_page_no; } @@ -2134,6 +2127,8 @@ dict_create_add_foreigns_to_dictionary( return(DB_ERROR); } + error = DB_SUCCESS; + for (dict_foreign_set::const_iterator it = local_fk_set.begin(); it != local_fk_set.end(); ++it) { @@ -2145,12 +2140,11 @@ dict_create_add_foreigns_to_dictionary( table->name.m_name, foreign, trx); if (error != DB_SUCCESS) { - - return(error); + break; } } - return(DB_SUCCESS); + return error; } /****************************************************************//** @@ -2382,15 +2376,3 @@ dict_delete_tablespace_and_datafiles( return(err); } - -/** Assign a new table ID and put it into the table cache and the transaction. -@param[in,out] table Table that needs an ID -@param[in,out] trx Transaction */ -void -dict_table_assign_new_id( - dict_table_t* table, - trx_t* trx) -{ - dict_hdr_get_new_id(&table->id, NULL, NULL, table, false); - trx->table_id = table->id; -} diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index c6f6455be73..dd4a56c365e 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -406,6 +406,27 @@ dict_table_stats_unlock( } } + +/** Open a persistent table. +@param[in] table_id persistent table identifier +@param[in] ignore_err errors to ignore +@param[in] cached_only whether to skip loading +@return persistent table +@retval NULL if not found */ +static dict_table_t* dict_table_open_on_id_low( + table_id_t table_id, + dict_err_ignore_t ignore_err, + bool cached_only) +{ + dict_table_t* table = dict_sys->get_table(table_id); + + if (!table && !cached_only) { + table = dict_load_table_on_id(table_id, ignore_err); + } + + return table; +} + /**********************************************************************//** Try to drop any indexes after an aborted index creation. This can also be after a server kill during DROP INDEX. */ @@ -1084,20 +1105,19 @@ dict_init(void) dict_operation_lock = static_cast<rw_lock_t*>( ut_zalloc_nokey(sizeof(*dict_operation_lock))); - dict_sys = static_cast<dict_sys_t*>(ut_zalloc_nokey(sizeof(*dict_sys))); + dict_sys = new (ut_zalloc_nokey(sizeof(*dict_sys))) dict_sys_t(); UT_LIST_INIT(dict_sys->table_LRU, &dict_table_t::table_LRU); UT_LIST_INIT(dict_sys->table_non_LRU, &dict_table_t::table_LRU); mutex_create(LATCH_ID_DICT_SYS, &dict_sys->mutex); - dict_sys->table_hash = hash_create( - buf_pool_get_curr_size() - / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE)); + const ulint hash_size = buf_pool_get_curr_size() + / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE); - dict_sys->table_id_hash = hash_create( - buf_pool_get_curr_size() - / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE)); + dict_sys->table_hash = hash_create(hash_size); + dict_sys->table_id_hash = hash_create(hash_size); + dict_sys->temp_id_hash = hash_create(hash_size); rw_lock_create(dict_operation_lock_key, dict_operation_lock, SYNC_DICT_OPERATION); @@ -1257,8 +1277,7 @@ dict_table_add_system_columns( } /** Add the table definition to the data dictionary cache */ -void -dict_table_t::add_to_cache() +void dict_table_t::add_to_cache() { ut_ad(dict_lru_validate()); ut_ad(mutex_own(&dict_sys->mutex)); @@ -1266,7 +1285,6 @@ dict_table_t::add_to_cache() cached = TRUE; ulint fold = ut_fold_string(name.m_name); - ulint id_fold = ut_fold_ull(id); /* Look for a table with the same name: error if such exists */ { @@ -1284,31 +1302,30 @@ dict_table_t::add_to_cache() ut_ad(table2 == NULL); #endif /* UNIV_DEBUG */ } + HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold, + this); /* Look for a table with the same id: error if such exists */ + hash_table_t* id_hash = is_temporary() + ? dict_sys->temp_id_hash : dict_sys->table_id_hash; + const ulint id_fold = ut_fold_ull(id); { dict_table_t* table2; - HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold, + HASH_SEARCH(id_hash, id_hash, id_fold, dict_table_t*, table2, ut_ad(table2->cached), table2->id == id); ut_a(table2 == NULL); #ifdef UNIV_DEBUG /* Look for the same table pointer with a different id */ - HASH_SEARCH_ALL(id_hash, dict_sys->table_id_hash, + HASH_SEARCH_ALL(id_hash, id_hash, dict_table_t*, table2, ut_ad(table2->cached), table2 == this); ut_ad(table2 == NULL); #endif /* UNIV_DEBUG */ - } - - /* Add table to hash table of tables */ - HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold, - this); - /* Add table to hash table of tables based on table id */ - HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash, id_fold, - this); + HASH_INSERT(dict_table_t, id_hash, id_hash, id_fold, this); + } if (can_be_evicted) { UT_LIST_ADD_FIRST(dict_sys->table_LRU, this); @@ -1433,7 +1450,7 @@ dict_make_room_in_cache( ut_ad(0); } };); - dict_table_remove_from_cache_low(table, TRUE); + dict_table_remove_from_cache(table, true); ++n_evicted; } @@ -1955,6 +1972,7 @@ dict_table_change_id_in_cache( ut_ad(table); ut_ad(mutex_own(&dict_sys->mutex)); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + ut_ad(!table->is_temporary()); /* Remove the table from the hash table of id's */ @@ -1967,14 +1985,11 @@ dict_table_change_id_in_cache( ut_fold_ull(table->id), table); } -/**********************************************************************//** -Removes a table object from the dictionary cache. */ -void -dict_table_remove_from_cache_low( -/*=============================*/ - dict_table_t* table, /*!< in, own: table */ - ibool lru_evict) /*!< in: TRUE if table being evicted - to make room in the table LRU list */ +/** Evict a table definition from the InnoDB data dictionary cache. +@param[in,out] table cached table definition to be evicted +@param[in] lru whether this is part of least-recently-used eviction +@param[in] keep whether to keep (not free) the object */ +void dict_table_remove_from_cache(dict_table_t* table, bool lru, bool keep) { dict_foreign_t* foreign; dict_index_t* index; @@ -2007,7 +2022,7 @@ dict_table_remove_from_cache_low( index != NULL; index = UT_LIST_GET_LAST(table->indexes)) { - dict_index_remove_from_cache_low(table, index, lru_evict); + dict_index_remove_from_cache_low(table, index, lru); } /* Remove table from the hash tables of tables */ @@ -2015,8 +2030,10 @@ dict_table_remove_from_cache_low( HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash, ut_fold_string(table->name.m_name), table); - HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash, - ut_fold_ull(table->id), table); + hash_table_t* id_hash = table->is_temporary() + ? dict_sys->temp_id_hash : dict_sys->table_id_hash; + const ulint id_fold = ut_fold_ull(table->id); + HASH_DELETE(dict_table_t, id_hash, id_hash, id_fold, table); /* Remove table from LRU or non-LRU list. */ if (table->can_be_evicted) { @@ -2029,7 +2046,7 @@ dict_table_remove_from_cache_low( ut_ad(dict_lru_validate()); - if (lru_evict && table->drop_aborted) { + if (lru && table->drop_aborted) { /* When evicting the table definition, drop the orphan indexes from the data dictionary and free the index pages. */ @@ -2054,17 +2071,9 @@ dict_table_remove_from_cache_low( UT_DELETE(table->vc_templ); } - dict_mem_table_free(table); -} - -/**********************************************************************//** -Removes a table object from the dictionary cache. */ -void -dict_table_remove_from_cache( -/*=========================*/ - dict_table_t* table) /*!< in, own: table */ -{ - dict_table_remove_from_cache_low(table, FALSE); + if (!keep) { + dict_mem_table_free(table); + } } /****************************************************************//** @@ -5453,46 +5462,6 @@ dict_index_build_node_ptr( return(tuple); } -/**********************************************************************//** -Copies an initial segment of a physical record, long enough to specify an -index entry uniquely. -@return pointer to the prefix record */ -rec_t* -dict_index_copy_rec_order_prefix( -/*=============================*/ - const dict_index_t* index, /*!< in: index */ - const rec_t* rec, /*!< in: record for which to - copy prefix */ - ulint* n_fields,/*!< out: number of fields copied */ - byte** buf, /*!< in/out: memory buffer for the - copied prefix, or NULL */ - ulint* buf_size)/*!< in/out: buffer size */ -{ - ulint n; - - UNIV_PREFETCH_R(rec); - - if (dict_index_is_ibuf(index)) { - ut_ad(!dict_table_is_comp(index->table)); - n = rec_get_n_fields_old(rec); - } else { - if (page_rec_is_leaf(rec)) { - n = dict_index_get_n_unique_in_tree(index); - } else if (dict_index_is_spatial(index)) { - ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index) - == DICT_INDEX_SPATIAL_NODEPTR_SIZE); - /* For R-tree, we have to compare - the child page numbers as well. */ - n = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1; - } else { - n = dict_index_get_n_unique_in_tree(index); - } - } - - *n_fields = n; - return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size)); -} - /** Convert a physical record into a search tuple. @param[in] rec index record (not necessarily in an index page) @param[in] index index @@ -6546,17 +6515,17 @@ dict_resize() /* all table entries are in table_LRU and table_non_LRU lists */ hash_table_free(dict_sys->table_hash); hash_table_free(dict_sys->table_id_hash); + hash_table_free(dict_sys->temp_id_hash); - dict_sys->table_hash = hash_create( - buf_pool_get_curr_size() - / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE)); - - dict_sys->table_id_hash = hash_create( - buf_pool_get_curr_size() - / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE)); + const ulint hash_size = buf_pool_get_curr_size() + / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE); + dict_sys->table_hash = hash_create(hash_size); + dict_sys->table_id_hash = hash_create(hash_size); + dict_sys->temp_id_hash = hash_create(hash_size); for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table; table = UT_LIST_GET_NEXT(table_LRU, table)) { + ut_ad(!table->is_temporary()); ulint fold = ut_fold_string(table->name.m_name); ulint id_fold = ut_fold_ull(table->id); @@ -6575,8 +6544,10 @@ dict_resize() HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold, table); - HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash, - id_fold, table); + hash_table_t* id_hash = table->is_temporary() + ? dict_sys->temp_id_hash : dict_sys->table_id_hash; + + HASH_INSERT(dict_table_t, id_hash, id_hash, id_fold, table); } mutex_exit(&dict_sys->mutex); @@ -6599,7 +6570,7 @@ dict_close(void) /* Free the hash elements. We don't remove them from the table because we are going to destroy the table anyway. */ - for (ulint i = 0; i < hash_get_n_cells(dict_sys->table_id_hash); i++) { + for (ulint i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) { dict_table_t* table; table = static_cast<dict_table_t*>( @@ -6620,6 +6591,7 @@ dict_close(void) /* The elements are the same instance as in dict_sys->table_hash, therefore we don't delete the individual elements. */ hash_table_free(dict_sys->table_id_hash); + hash_table_free(dict_sys->temp_id_hash); mutex_exit(&dict_sys->mutex); mutex_free(&dict_sys->mutex); diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 3056f73f0cb..485c0f22577 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -190,8 +190,6 @@ dict_mem_table_create( || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) { table->fts = fts_create(table); table->fts->cache = fts_cache_create(table); - } else { - table->fts = NULL; } new(&table->foreign_set) dict_foreign_set(); @@ -531,6 +529,14 @@ dict_mem_table_col_rename_low( = dict_index_get_nth_field( index, i); + ut_ad(!field->name + == field->col->is_dropped()); + if (!field->name) { + /* dropped columns lack a name */ + ut_ad(index->is_instant()); + continue; + } + /* if is_virtual and that in field->col does not match, continue */ if ((!is_virtual) != @@ -715,6 +721,7 @@ dict_mem_fill_column_struct( column->mbmaxlen = mbmaxlen; column->def_val.data = NULL; column->def_val.len = UNIV_SQL_DEFAULT; + ut_ad(!column->is_dropped()); } /**********************************************************************//** @@ -1191,293 +1198,122 @@ operator<< (std::ostream& out, const dict_foreign_set& fk_set) return(out); } -/** Adjust clustered index metadata for instant ADD COLUMN. -@param[in] clustered index definition after instant ADD COLUMN */ -inline void dict_index_t::instant_add_field(const dict_index_t& instant) +/** Reconstruct the clustered index fields. */ +inline void dict_index_t::reconstruct_fields() { DBUG_ASSERT(is_primary()); - DBUG_ASSERT(instant.is_primary()); - DBUG_ASSERT(!instant.is_instant()); - DBUG_ASSERT(n_def == n_fields); - DBUG_ASSERT(instant.n_def == instant.n_fields); - - DBUG_ASSERT(type == instant.type); - DBUG_ASSERT(trx_id_offset == instant.trx_id_offset); - DBUG_ASSERT(n_user_defined_cols == instant.n_user_defined_cols); - DBUG_ASSERT(n_uniq == instant.n_uniq); - DBUG_ASSERT(instant.n_fields > n_fields); - DBUG_ASSERT(instant.n_def > n_def); - DBUG_ASSERT(instant.n_nullable >= n_nullable); - DBUG_ASSERT(instant.n_core_fields >= n_core_fields); - DBUG_ASSERT(instant.n_core_null_bytes >= n_core_null_bytes); - - n_fields = instant.n_fields; - n_def = instant.n_def; - n_nullable = instant.n_nullable; - fields = static_cast<dict_field_t*>( - mem_heap_dup(heap, instant.fields, n_fields * sizeof *fields)); - - ut_d(unsigned n_null = 0); - - for (unsigned i = 0; i < n_fields; i++) { - DBUG_ASSERT(fields[i].same(instant.fields[i])); - const dict_col_t* icol = instant.fields[i].col; - DBUG_ASSERT(!icol->is_virtual()); - dict_col_t* col = fields[i].col = &table->cols[ - icol - instant.table->cols]; - fields[i].name = col->name(*table); - ut_d(n_null += col->is_nullable()); - } - ut_ad(n_null == n_nullable); -} + n_fields += table->instant->n_dropped; + n_def += table->instant->n_dropped; -/** Adjust metadata for instant ADD COLUMN. -@param[in] table table definition after instant ADD COLUMN */ -void dict_table_t::instant_add_column(const dict_table_t& table) -{ - DBUG_ASSERT(!table.cached); - DBUG_ASSERT(table.n_def == table.n_cols); - DBUG_ASSERT(table.n_t_def == table.n_t_cols); - DBUG_ASSERT(n_def == n_cols); - DBUG_ASSERT(n_t_def == n_t_cols); - DBUG_ASSERT(table.n_cols > n_cols); - ut_ad(mutex_own(&dict_sys->mutex)); - - const char* end = table.col_names; - for (unsigned i = table.n_cols; i--; ) end += strlen(end) + 1; - - col_names = static_cast<char*>( - mem_heap_dup(heap, table.col_names, - ulint(end - table.col_names))); - const dict_col_t* const old_cols = cols; - const dict_col_t* const old_cols_end = cols + n_cols; - cols = static_cast<dict_col_t*>(mem_heap_dup(heap, table.cols, - table.n_cols - * sizeof *cols)); - - /* Preserve the default values of previously instantly - added columns. */ - for (unsigned i = unsigned(n_cols) - DATA_N_SYS_COLS; i--; ) { - cols[i].def_val = old_cols[i].def_val; - } + const unsigned n_first = first_user_field(); + + dict_field_t* tfields = static_cast<dict_field_t*>( + mem_heap_zalloc(heap, n_fields * sizeof *fields)); + + memcpy(tfields, fields, n_first * sizeof *fields); - /* Copy the new default values to this->heap. */ - for (unsigned i = n_cols; i < table.n_cols; i++) { - dict_col_t& c = cols[i - DATA_N_SYS_COLS]; - DBUG_ASSERT(c.is_instant()); - if (c.def_val.len == 0) { - c.def_val.data = field_ref_zero; - } else if (const void*& d = c.def_val.data) { - d = mem_heap_dup(heap, d, c.def_val.len); + n_nullable = 0; + ulint n_core_null = 0; + const bool comp = dict_table_is_comp(table); + const auto* field_map_it = table->instant->field_map; + for (unsigned i = n_first, j = 0; i < n_fields; ) { + dict_field_t& f = tfields[i++]; + auto c = *field_map_it++; + if (c.is_dropped()) { + f.col = &table->instant->dropped[j++]; + DBUG_ASSERT(f.col->is_dropped()); + f.fixed_len = dict_col_get_fixed_size(f.col, comp); } else { - DBUG_ASSERT(c.def_val.len == UNIV_SQL_NULL); + DBUG_ASSERT(!c.is_not_null()); + const auto old = std::find_if( + fields + n_first, fields + n_fields, + [c](const dict_field_t& o) + { return o.col->ind == c.ind(); }); + ut_ad(old >= &fields[n_first]); + ut_ad(old < &fields[n_fields]); + DBUG_ASSERT(!old->prefix_len); + DBUG_ASSERT(old->col == &table->cols[c.ind()]); + f = *old; } - } - const unsigned old_n_cols = n_cols; - const unsigned n_add = unsigned(table.n_cols - n_cols); - - n_t_def += n_add; - n_t_cols += n_add; - n_cols = table.n_cols; - n_def = n_cols; - - for (unsigned i = n_v_def; i--; ) { - const dict_v_col_t& v = v_cols[i]; - for (ulint n = v.num_base; n--; ) { - dict_col_t*& base = v.base_col[n]; - if (!base->is_virtual()) { - DBUG_ASSERT(base >= old_cols); - size_t n = size_t(base - old_cols); - DBUG_ASSERT(n + DATA_N_SYS_COLS < old_n_cols); - base = &cols[n]; - } + f.col->clear_instant(); + if (f.col->is_nullable()) { + n_nullable++; + n_core_null += i <= n_core_fields; } } - dict_index_t* index = dict_table_get_first_index(this); - - index->instant_add_field(*dict_table_get_first_index(&table)); - - while ((index = dict_table_get_next_index(index)) != NULL) { - for (unsigned i = 0; i < index->n_fields; i++) { - dict_field_t& field = index->fields[i]; - if (field.col < old_cols - || field.col >= old_cols_end) { - DBUG_ASSERT(field.col->is_virtual()); - } else { - /* Secondary indexes may contain user - columns and DB_ROW_ID (if there is - GEN_CLUST_INDEX instead of PRIMARY KEY), - but not DB_TRX_ID,DB_ROLL_PTR. */ - DBUG_ASSERT(field.col >= old_cols); - size_t n = size_t(field.col - old_cols); - DBUG_ASSERT(n + DATA_N_SYS_COLS <= old_n_cols); - if (n + DATA_N_SYS_COLS >= old_n_cols) { - /* Replace DB_ROW_ID */ - n += n_add; - } - field.col = &cols[n]; - DBUG_ASSERT(!field.col->is_virtual()); - field.name = field.col->name(*this); - } - } - } + fields = tfields; + n_core_null_bytes = UT_BITS_IN_BYTES(n_core_null); } -/** Roll back instant_add_column(). -@param[in] old_n_cols original n_cols -@param[in] old_cols original cols -@param[in] old_col_names original col_names */ -void -dict_table_t::rollback_instant( - unsigned old_n_cols, - dict_col_t* old_cols, - const char* old_col_names) +/** Reconstruct dropped or reordered columns. +@param[in] metadata data from serialise_columns() +@param[in] len length of the metadata, in bytes +@return whether parsing the metadata failed */ +bool dict_table_t::deserialise_columns(const byte* metadata, ulint len) { - ut_ad(mutex_own(&dict_sys->mutex)); - dict_index_t* index = indexes.start; - /* index->is_instant() does not necessarily hold here, because - the table may have been emptied */ - DBUG_ASSERT(old_n_cols >= DATA_N_SYS_COLS); - DBUG_ASSERT(n_cols >= old_n_cols); - DBUG_ASSERT(n_cols == n_def); - DBUG_ASSERT(index->n_def == index->n_fields); - - const unsigned n_remove = n_cols - old_n_cols; - - for (unsigned i = index->n_fields - n_remove; i < index->n_fields; - i++) { - if (index->fields[i].col->is_nullable()) { - index->n_nullable--; - } - } + DBUG_ASSERT(!instant); - index->n_fields -= n_remove; - index->n_def = index->n_fields; - if (index->n_core_fields > index->n_fields) { - index->n_core_fields = index->n_fields; - index->n_core_null_bytes - = UT_BITS_IN_BYTES(unsigned(index->n_nullable)); - } + unsigned num_non_pk_fields = mach_read_from_4(metadata); + metadata += 4; - const dict_col_t* const new_cols = cols; - const dict_col_t* const new_cols_end = cols + n_cols; - - cols = old_cols; - col_names = old_col_names; - n_cols = old_n_cols; - n_def = old_n_cols; - n_t_def -= n_remove; - n_t_cols -= n_remove; - - for (unsigned i = n_v_def; i--; ) { - const dict_v_col_t& v = v_cols[i]; - for (ulint n = v.num_base; n--; ) { - dict_col_t*& base = v.base_col[n]; - if (!base->is_virtual()) { - base = &cols[base - new_cols]; - } - } + if (num_non_pk_fields >= REC_MAX_N_FIELDS - 3) { + return true; } - do { - for (unsigned i = 0; i < index->n_fields; i++) { - dict_field_t& field = index->fields[i]; - if (field.col < new_cols - || field.col >= new_cols_end) { - DBUG_ASSERT(field.col->is_virtual()); - } else { - DBUG_ASSERT(field.col >= new_cols); - size_t n = size_t(field.col - new_cols); - DBUG_ASSERT(n <= n_cols); - if (n + DATA_N_SYS_COLS >= n_cols) { - n -= n_remove; - } - field.col = &cols[n]; - DBUG_ASSERT(!field.col->is_virtual()); - field.name = field.col->name(*this); - } - } - } while ((index = dict_table_get_next_index(index)) != NULL); -} + dict_index_t* index = UT_LIST_GET_FIRST(indexes); -/** Trim the instantly added columns when an insert into SYS_COLUMNS -is rolled back during ALTER TABLE or recovery. -@param[in] n number of surviving non-system columns */ -void dict_table_t::rollback_instant(unsigned n) -{ - ut_ad(mutex_own(&dict_sys->mutex)); - dict_index_t* index = indexes.start; - DBUG_ASSERT(index->is_instant()); - DBUG_ASSERT(index->n_def == index->n_fields); - DBUG_ASSERT(n_cols == n_def); - DBUG_ASSERT(n >= index->n_uniq); - DBUG_ASSERT(n_cols > n + DATA_N_SYS_COLS); - const unsigned n_remove = n_cols - n - DATA_N_SYS_COLS; - - char* names = const_cast<char*>(dict_table_get_col_name(this, n)); - const char* sys = names; - for (unsigned i = n_remove; i--; ) { - sys += strlen(sys) + 1; + if (num_non_pk_fields < unsigned(index->n_fields) + - index->first_user_field()) { + return true; } - static const char system[] = "DB_ROW_ID\0DB_TRX_ID\0DB_ROLL_PTR"; - DBUG_ASSERT(!memcmp(sys, system, sizeof system)); - for (unsigned i = index->n_fields - n_remove; i < index->n_fields; - i++) { - if (index->fields[i].col->is_nullable()) { - index->n_nullable--; + + field_map_element_t* field_map = static_cast<field_map_element_t*>( + mem_heap_alloc(heap, + num_non_pk_fields * sizeof *field_map)); + + unsigned n_dropped_cols = 0; + + for (unsigned i = 0; i < num_non_pk_fields; i++) { + auto c = field_map[i] = mach_read_from_2(metadata); + metadata += 2; + + if (field_map[i].is_dropped()) { + if (c.ind() > DICT_MAX_FIXED_COL_LEN + 1) { + return true; + } + n_dropped_cols++; + } else if (c >= n_cols) { + return true; } } - index->n_fields -= n_remove; - index->n_def = index->n_fields; - memmove(names, sys, sizeof system); - memmove(cols + n, cols + n_cols - DATA_N_SYS_COLS, - DATA_N_SYS_COLS * sizeof *cols); - n_cols -= n_remove; - n_def = n_cols; - n_t_cols -= n_remove; - n_t_def -= n_remove; - - for (unsigned i = DATA_N_SYS_COLS; i--; ) { - cols[n_cols - i].ind--; - } - if (dict_index_is_auto_gen_clust(index)) { - DBUG_ASSERT(index->n_uniq == 1); - dict_field_t* field = index->fields; - field->name = sys; - field->col = dict_table_get_sys_col(this, DATA_ROW_ID); - field++; - field->name = sys + sizeof "DB_ROW_ID"; - field->col = dict_table_get_sys_col(this, DATA_TRX_ID); - field++; - field->name = sys + sizeof "DB_ROW_ID\0DB_TRX_ID"; - field->col = dict_table_get_sys_col(this, DATA_ROLL_PTR); - - /* Replace the DB_ROW_ID column in secondary indexes. */ - while ((index = dict_table_get_next_index(index)) != NULL) { - field = &index->fields[index->n_fields - 1]; - DBUG_ASSERT(field->col->mtype == DATA_SYS); - DBUG_ASSERT(field->col->prtype - == DATA_NOT_NULL + DATA_TRX_ID); - field->col--; - field->name = sys; + dict_col_t* dropped_cols = static_cast<dict_col_t*>(mem_heap_zalloc( + heap, n_dropped_cols * sizeof(dict_col_t))); + instant = new (mem_heap_alloc(heap, sizeof *instant)) dict_instant_t(); + instant->n_dropped = n_dropped_cols; + instant->dropped = dropped_cols; + instant->field_map = field_map; + + dict_col_t* col = dropped_cols; + for (unsigned i = 0; i < num_non_pk_fields; i++) { + if (field_map[i].is_dropped()) { + auto fixed_len = field_map[i].ind(); + DBUG_ASSERT(fixed_len <= DICT_MAX_FIXED_COL_LEN + 1); + (col++)->set_dropped(field_map[i].is_not_null(), + fixed_len == 1, + fixed_len > 1 ? fixed_len - 1 + : 0); } - - return; } + DBUG_ASSERT(col == &dropped_cols[n_dropped_cols]); - dict_field_t* field = &index->fields[index->n_uniq]; - field->name = sys + sizeof "DB_ROW_ID"; - field->col = dict_table_get_sys_col(this, DATA_TRX_ID); - field++; - field->name = sys + sizeof "DB_ROW_ID\0DB_TRX_ID"; - field->col = dict_table_get_sys_col(this, DATA_ROLL_PTR); + UT_LIST_GET_FIRST(indexes)->reconstruct_fields(); + return false; } - /** Check if record in clustered index is historical row. @param[in] rec clustered row @param[in] offsets offsets diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index e5c2b91cfdf..57802912569 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -23,16 +23,16 @@ Created Jonas Oreland Google Modified Jan Lindström jan.lindstrom@mariadb.com *******************************************************/ -#include "fil0fil.h" +#include "fil0crypt.h" #include "mtr0types.h" #include "mach0data.h" -#include "page0size.h" #include "page0zip.h" -#ifndef UNIV_INNOCHECKSUM -#include "fil0crypt.h" +#include "buf0checksum.h" +#ifdef UNIV_INNOCHECKSUM +# include "buf0buf.h" +#else #include "srv0srv.h" #include "srv0start.h" -#include "log0recv.h" #include "mtr0mtr.h" #include "mtr0log.h" #include "ut0ut.h" @@ -2556,11 +2556,7 @@ fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size) SRV_CHECKSUM_ALGORITHM_CRC32); } - return checksum == buf_calc_page_crc32(page) -#ifdef INNODB_BUG_ENDIAN_CRC32 - || checksum == buf_calc_page_crc32(page, true) -#endif - ; + return checksum == buf_calc_page_crc32(page); case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: if (page_size.is_compressed()) { return checksum == page_zip_calc_checksum( @@ -2591,9 +2587,6 @@ fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size) } return checksum == buf_calc_page_crc32(page) -#ifdef INNODB_BUG_ENDIAN_CRC32 - || checksum == buf_calc_page_crc32(page, true) -#endif || checksum == buf_calc_page_new_checksum(page); } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 0c2ee5203cf..9c4f1a0290d 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -42,7 +42,6 @@ Created 10/25/1995 Heikki Tuuri #include "os0file.h" #include "page0zip.h" #include "row0mysql.h" -#include "row0trunc.h" #include "srv0start.h" #include "trx0purge.h" #include "buf0lru.h" @@ -166,9 +165,6 @@ ulint fil_n_pending_log_flushes = 0; /** Number of pending tablespace flushes */ ulint fil_n_pending_tablespace_flushes = 0; -/** The null file address */ -const fil_addr_t fil_addr_null = {FIL_NULL, 0}; - /** The tablespace memory cache. This variable is NULL before the module is initialized. */ fil_system_t fil_system; @@ -515,7 +511,6 @@ bool fil_node_t::read_page0(bool first) ut_free(buf2); return false; } - srv_stats.page0_read.add(1); const ulint space_id = fsp_header_get_space_id(page); ulint flags = fsp_header_get_flags(page); const ulint size = fsp_header_get_field(page, FSP_SIZE); @@ -595,8 +590,7 @@ static bool fil_node_open_file(fil_node_t* node) if (first_time_open || (space->purpose == FIL_TYPE_TABLESPACE && node == UT_LIST_GET_FIRST(space->chain) - && srv_startup_is_before_trx_rollback_phase - && !undo::Truncate::was_tablespace_truncated(space->id))) { + && srv_startup_is_before_trx_rollback_phase)) { /* We do not know the size of the file yet. First we open the file in the normal mode, no async I/O here, for simplicity. Then do some checks, and close the @@ -4180,7 +4174,7 @@ fil_report_invalid_page_access( @param[in] message message for aio handler if non-sync aio used, else ignored @param[in] ignore_missing_space true=ignore missing space duging read -@return DB_SUCCESS, DB_TABLESPACE_DELETED or DB_TABLESPACE_TRUNCATED +@return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do i/o on a tablespace which does not exist */ dberr_t fil_io( @@ -4312,19 +4306,6 @@ fil_io( break; } else { - if (space->id != TRX_SYS_SPACE - && UT_LIST_GET_LEN(space->chain) == 1 - && (srv_is_tablespace_truncated(space->id) - || srv_was_tablespace_truncated(space)) - && req_type.is_read()) { - - /* Handle page which is outside the truncated - tablespace bounds when recovering from a crash - happened during a truncation */ - mutex_exit(&fil_system.mutex); - return(DB_TABLESPACE_TRUNCATED); - } - cur_page_no -= node->size; node = UT_LIST_GET_NEXT(chain, node); @@ -5044,116 +5025,6 @@ fil_names_clear( return(do_write); } -/** Truncate a single-table tablespace. The tablespace must be cached -in the memory cache. -@param space_id space id -@param dir_path directory path -@param tablename the table name in the usual - databasename/tablename format of InnoDB -@param flags tablespace flags -@param trunc_to_default truncate to default size if tablespace - is being newly re-initialized. -@return DB_SUCCESS or error */ -dberr_t -truncate_t::truncate( -/*=================*/ - ulint space_id, - const char* dir_path, - const char* tablename, - ulint flags, - bool trunc_to_default) -{ - dberr_t err = DB_SUCCESS; - char* path; - - ut_a(!is_system_tablespace(space_id)); - - if (FSP_FLAGS_HAS_DATA_DIR(flags)) { - ut_ad(dir_path != NULL); - path = fil_make_filepath(dir_path, tablename, IBD, true); - } else { - path = fil_make_filepath(NULL, tablename, IBD, false); - } - - if (path == NULL) { - return(DB_OUT_OF_MEMORY); - } - - mutex_enter(&fil_system.mutex); - - fil_space_t* space = fil_space_get_by_id(space_id); - - /* The following code must change when InnoDB supports - multiple datafiles per tablespace. */ - ut_a(UT_LIST_GET_LEN(space->chain) == 1); - - fil_node_t* node = UT_LIST_GET_FIRST(space->chain); - - if (trunc_to_default) { - space->size = node->size = FIL_IBD_FILE_INITIAL_SIZE; - } - - const bool already_open = node->is_open(); - - if (!already_open) { - - bool ret; - - node->handle = os_file_create_simple_no_error_handling( - innodb_data_file_key, path, OS_FILE_OPEN, - OS_FILE_READ_WRITE, - space->purpose != FIL_TYPE_TEMPORARY - && srv_read_only_mode, &ret); - - if (!ret) { - ib::error() << "Failed to open tablespace file " - << path << "."; - - ut_free(path); - - return(DB_ERROR); - } - - ut_a(node->is_open()); - } - - os_offset_t trunc_size = trunc_to_default - ? FIL_IBD_FILE_INITIAL_SIZE - : space->size; - - const bool success = os_file_truncate( - path, node->handle, trunc_size << srv_page_size_shift); - - if (!success) { - ib::error() << "Cannot truncate file " << path - << " in TRUNCATE TABLESPACE."; - err = DB_ERROR; - } - - space->stop_new_ops = false; - - /* If we opened the file in this function, close it. */ - if (!already_open) { - bool closed = os_file_close(node->handle); - - if (!closed) { - - ib::error() << "Failed to close tablespace file " - << path << "."; - - err = DB_ERROR; - } else { - node->handle = OS_FILE_CLOSED; - } - } - - mutex_exit(&fil_system.mutex); - - ut_free(path); - - return(err); -} - /* Unit Tests */ #ifdef UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH #define MF fil_make_filepath diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 6ef6764ebb4..09342918753 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -621,8 +621,7 @@ fsp_space_modify_check( case MTR_LOG_NO_REDO: ut_ad(space->purpose == FIL_TYPE_TEMPORARY || space->purpose == FIL_TYPE_IMPORT - || my_atomic_loadlint(&space->redo_skipped_count) - || srv_is_tablespace_truncated(space->id)); + || my_atomic_loadlint(&space->redo_skipped_count)); return; case MTR_LOG_ALL: /* We may only write redo log for a persistent tablespace. */ @@ -728,23 +727,23 @@ void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr) mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_ID + block->frame, space->id, MLOG_4BYTES, mtr); - mlog_write_ulint(FSP_HEADER_OFFSET + FSP_NOT_USED + block->frame, 0, - MLOG_4BYTES, mtr); + ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_NOT_USED + + block->frame)); mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SIZE + block->frame, size, MLOG_4BYTES, mtr); - mlog_write_ulint(FSP_HEADER_OFFSET + FSP_FREE_LIMIT + block->frame, 0, - MLOG_4BYTES, mtr); + ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT + + block->frame)); mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + block->frame, space->flags & ~FSP_FLAGS_MEM_MASK, MLOG_4BYTES, mtr); - mlog_write_ulint(FSP_HEADER_OFFSET + FSP_FRAG_N_USED + block->frame, 0, - MLOG_4BYTES, mtr); + ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FRAG_N_USED + + block->frame)); - flst_init(FSP_HEADER_OFFSET + FSP_FREE + block->frame, mtr); - flst_init(FSP_HEADER_OFFSET + FSP_FREE_FRAG + block->frame, mtr); - flst_init(FSP_HEADER_OFFSET + FSP_FULL_FRAG + block->frame, mtr); - flst_init(FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL + block->frame, mtr); - flst_init(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE + block->frame, mtr); + flst_init(block, FSP_HEADER_OFFSET + FSP_FREE, mtr); + flst_init(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG, mtr); + flst_init(block, FSP_HEADER_OFFSET + FSP_FULL_FRAG, mtr); + flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL, mtr); + flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, mtr); mlog_write_ull(FSP_HEADER_OFFSET + FSP_SEG_ID + block->frame, 1, mtr); @@ -1078,13 +1077,6 @@ fsp_fill_free_list( mtr_start(&ibuf_mtr); ibuf_mtr.set_named_space(space); - /* Avoid logging while truncate table - fix-up is active. */ - if (srv_is_tablespace_truncated(space->id)) { - mtr_set_log_mode( - &ibuf_mtr, MTR_LOG_NO_REDO); - } - const page_id_t page_id( space->id, i + FSP_IBUF_BITMAP_OFFSET); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index b4eac793a3a..598a4e4843e 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -3282,7 +3282,7 @@ fts_fetch_doc_from_rec( doc->text.f_str = btr_rec_copy_externally_stored_field( clust_rec, offsets, - dict_table_page_size(table), + btr_pcur_get_block(pcur)->page.size, clust_pos, &doc->text.f_len, static_cast<mem_heap_t*>( doc->self_heap->arg)); @@ -3714,13 +3714,6 @@ fts_get_max_doc_id( if (!page_is_empty(btr_pcur_get_page(&pcur))) { const rec_t* rec = NULL; - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - ulint* offsets = offsets_; - mem_heap_t* heap = NULL; - ulint len; - const void* data; - - rec_offs_init(offsets_); do { rec = btr_pcur_get_rec(&pcur); @@ -3730,18 +3723,11 @@ fts_get_max_doc_id( } } while (btr_pcur_move_to_prev(&pcur, &mtr)); - if (!rec) { + if (!rec || rec_is_metadata(rec, *index)) { goto func_exit; } - ut_ad(!rec_is_metadata(rec, index)); - offsets = rec_get_offsets( - rec, index, offsets, true, ULINT_UNDEFINED, &heap); - - data = rec_get_nth_field(rec, offsets, 0, &len); - - doc_id = static_cast<doc_id_t>(fts_read_doc_id( - static_cast<const byte*>(data))); + doc_id = fts_read_doc_id(rec); } func_exit: @@ -5223,49 +5209,23 @@ fts_get_doc_id_from_row( } /** Extract the doc id from the record that belongs to index. -@param[in] table table -@param[in] rec record contains FTS_DOC_ID +@param[in] rec record containing FTS_DOC_ID @param[in] index index of rec -@param[in] heap heap memory +@param[in] offsets rec_get_offsets(rec,index) @return doc id that was extracted from rec */ doc_id_t fts_get_doc_id_from_rec( - dict_table_t* table, const rec_t* rec, const dict_index_t* index, - mem_heap_t* heap) -{ - ulint len; - const byte* data; - ulint col_no; - doc_id_t doc_id = 0; - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - ulint* offsets = offsets_; - mem_heap_t* my_heap = heap; - - ut_a(table->fts->doc_col != ULINT_UNDEFINED); - - rec_offs_init(offsets_); - - offsets = rec_get_offsets( - rec, index, offsets, true, ULINT_UNDEFINED, &my_heap); - - col_no = dict_col_get_index_pos( - &table->cols[table->fts->doc_col], index); - - ut_ad(col_no != ULINT_UNDEFINED); - - data = rec_get_nth_field(rec, offsets, col_no, &len); - - ut_a(len == 8); - ut_ad(8 == sizeof(doc_id)); - doc_id = static_cast<doc_id_t>(mach_read_from_8(data)); - - if (my_heap && !heap) { - mem_heap_free(my_heap); - } - - return(doc_id); + const ulint* offsets) +{ + ulint f = dict_col_get_index_pos( + &index->table->cols[index->table->fts->doc_col], index); + ulint len; + doc_id_t doc_id = mach_read_from_8( + rec_get_nth_field(rec, offsets, f, &len)); + ut_ad(len == 8); + return doc_id; } /*********************************************************************//** diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc index 3e77165ac31..05474b02cbd 100644 --- a/storage/innobase/fut/fut0lst.cc +++ b/storage/innobase/fut/fut0lst.cc @@ -58,8 +58,8 @@ flst_add_to_empty( flst_write_addr(base + FLST_LAST, node_addr, mtr); /* Set prev and next fields of node to add */ - flst_write_addr(node + FLST_PREV, fil_addr_null, mtr); - flst_write_addr(node + FLST_NEXT, fil_addr_null, mtr); + flst_zero_addr(node + FLST_PREV, mtr); + flst_zero_addr(node + FLST_NEXT, mtr); /* Update len of base node */ mlog_write_ulint(base + FLST_LEN, 1, MLOG_4BYTES, mtr); diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index be67239e177..9c10108a3f3 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -746,14 +746,15 @@ rtr_adjust_upper_level( prev_page_no = btr_page_get_prev(page, mtr); next_page_no = btr_page_get_next(page, mtr); space = block->page.id.space(); - const page_size_t& page_size = dict_table_page_size(index->table); + ut_ad(block->page.size.equals_to(dict_table_page_size(index->table))); /* Update page links of the level */ if (prev_page_no != FIL_NULL) { page_id_t prev_page_id(space, prev_page_no); buf_block_t* prev_block = btr_block_get( - prev_page_id, page_size, RW_X_LATCH, index, mtr); + prev_page_id, block->page.size, RW_X_LATCH, + index, mtr); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(prev_block->frame) == page_is_comp(page)); ut_a(btr_page_get_next(prev_block->frame, mtr) @@ -769,7 +770,8 @@ rtr_adjust_upper_level( page_id_t next_page_id(space, next_page_no); buf_block_t* next_block = btr_block_get( - next_page_id, page_size, RW_X_LATCH, index, mtr); + next_page_id, block->page.size, RW_X_LATCH, + index, mtr); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(next_block->frame) == page_is_comp(page)); ut_a(btr_page_get_prev(next_block->frame, mtr) @@ -914,7 +916,7 @@ rtr_split_page_move_rec_list( mtr_set_log_mode(mtr, log_mode); if (!page_zip_compress(new_page_zip, new_page, index, - page_zip_level, NULL, mtr)) { + page_zip_level, mtr)) { ulint ret_pos; /* Before trying to reorganize the page, diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index d90088f2c5e..0bb5eb13a12 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -97,7 +97,6 @@ this program; if not, write to the Free Software Foundation, Inc., #include "row0mysql.h" #include "row0quiesce.h" #include "row0sel.h" -#include "row0trunc.h" #include "row0upd.h" #include "fil0crypt.h" #include "ut0timer.h" @@ -1029,8 +1028,6 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_pages_created, SHOW_LONG}, {"pages_read", (char*) &export_vars.innodb_pages_read, SHOW_LONG}, - {"pages0_read", - (char*) &export_vars.innodb_page0_read, SHOW_LONG}, {"pages_written", (char*) &export_vars.innodb_pages_written, SHOW_LONG}, {"row_lock_current_waits", @@ -2914,8 +2911,9 @@ ha_innobase::ha_innobase( | HA_CAN_EXPORT | HA_CAN_RTREEKEYS | HA_CAN_TABLES_WITHOUT_ROLLBACK + | HA_CAN_ONLINE_BACKUPS | HA_CONCURRENT_OPTIMIZE - | (srv_force_primary_key ? HA_WANTS_PRIMARY_KEY : 0) + | (srv_force_primary_key ? HA_REQUIRE_PRIMARY_KEY : 0) ), m_start_of_scan(), m_mysql_has_locked() @@ -5330,7 +5328,7 @@ ha_innobase::keys_to_use_for_scanning() /****************************************************************//** Ensures that if there's a concurrent inplace ADD INDEX, being-indexed virtual columns are computed. They are not marked as indexed in the old table, so the -server won't add them to the vcol_set automatically */ +server won't add them to the read_set automatically */ void ha_innobase::column_bitmaps_signal() /*================================*/ @@ -5350,7 +5348,7 @@ ha_innobase::column_bitmaps_signal() if (col->ord_part || (dict_index_is_online_ddl(clust_index) && row_log_col_is_indexed(clust_index, num_v))) { - table->mark_virtual_col(table->vfield[j]); + table->mark_virtual_column_with_deps(table->vfield[j]); } num_v++; } @@ -6076,6 +6074,14 @@ initialize_auto_increment(dict_table_t* table, const Field* field) int ha_innobase::open(const char* name, int, uint) { + /* TODO: If trx_rollback_recovered(bool all=false) is ever + removed, the first-time open() must hold (or acquire and release) + a table lock that conflicts with trx_resurrect_table_locks(), + to ensure that any recovered incomplete ALTER TABLE will have been + rolled back. Otherwise, dict_table_t::instant could be cleared by + the rollback invoking dict_index_t::clear_instant_alter() while + open table handles exist in client connections. */ + dict_table_t* ib_table; char norm_name[FN_REFLEN]; dict_err_ignore_t ignore_err = DICT_ERR_IGNORE_NONE; @@ -9490,12 +9496,14 @@ ha_innobase::change_active_index( } #endif } else { - dtuple_set_n_fields(m_prebuilt->search_tuple, - m_prebuilt->index->n_fields); + ulint n_fields = dict_index_get_n_unique_in_tree( + m_prebuilt->index); + + dtuple_set_n_fields(m_prebuilt->search_tuple, n_fields); dict_index_copy_types( m_prebuilt->search_tuple, m_prebuilt->index, - m_prebuilt->index->n_fields); + n_fields); /* If it's FTS query and FTS_DOC_ID exists FTS_DOC_ID field is always added to read_set. */ @@ -10684,9 +10692,8 @@ prepare_vcol_for_base_setup( ut_ad(col->base_col == NULL); MY_BITMAP *old_read_set = field->table->read_set; - MY_BITMAP *old_vcol_set = field->table->vcol_set; - field->table->read_set = field->table->vcol_set = &field->table->tmp_set; + field->table->read_set = &field->table->tmp_set; bitmap_clear_all(&field->table->tmp_set); field->vcol_info->expr->walk( @@ -10698,7 +10705,6 @@ prepare_vcol_for_base_setup( * col->base_col))); } field->table->read_set= old_read_set; - field->table->vcol_set= old_vcol_set; } @@ -11062,9 +11068,8 @@ err_col: dict_table_add_system_columns(table, heap); if (table->is_temporary()) { - /* Get a new table ID. FIXME: Make this a private - sequence, not shared with persistent tables! */ - dict_table_assign_new_id(table, m_trx); + m_trx->table_id = table->id + = dict_sys->get_temporary_table_id(); ut_ad(dict_tf_get_rec_format(table->flags) != REC_FORMAT_COMPRESSED); table->space_id = SRV_TMP_SPACE_ID; @@ -11747,7 +11752,7 @@ create_table_info_t::parse_table_name( } if (m_create_info->index_file_name) { - my_error(WARN_OPTION_IGNORED, ME_JUST_WARNING, + my_error(WARN_OPTION_IGNORED, ME_WARNING, "INDEX DIRECTORY"); } @@ -17283,7 +17288,7 @@ innodb_internal_table_validate( DBUG_EXECUTE_IF("innodb_evict_autoinc_table", mutex_enter(&dict_sys->mutex); - dict_table_remove_from_cache_low(user_table, TRUE); + dict_table_remove_from_cache(user_table, true); mutex_exit(&dict_sys->mutex); ); } @@ -20972,10 +20977,10 @@ ib_senderrf( switch (level) { case IB_LOG_LEVEL_INFO: - l = ME_JUST_INFO; + l = ME_NOTE; break; case IB_LOG_LEVEL_WARN: - l = ME_JUST_WARNING; + l = ME_WARNING; break; case IB_LOG_LEVEL_ERROR: sd_notifyf(0, "STATUS=InnoDB: Error: %s", str); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 1e9e6dbda12..4d9eb00995e 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -136,6 +136,673 @@ static const alter_table_operations INNOBASE_ALTER_INSTANT | ALTER_COLUMN_UNVERSIONED | ALTER_DROP_VIRTUAL_COLUMN; +/** Acquire a page latch on the possible metadata record, +to prevent concurrent invocation of dict_index_t::clear_instant_alter() +by purge when the table turns out to be empty. +@param[in,out] index clustered index +@param[in,out] mtr mini-transaction */ +static void instant_metadata_lock(dict_index_t& index, mtr_t& mtr) +{ + DBUG_ASSERT(index.is_primary()); + + if (!index.is_instant()) { + /* dict_index_t::clear_instant_alter() cannot be called. + No need for a latch. */ + return; + } + + btr_cur_t btr_cur; + btr_cur_open_at_index_side(true, &index, BTR_SEARCH_LEAF, + &btr_cur, 0, &mtr); + ut_ad(page_cur_is_before_first(btr_cur_get_page_cur(&btr_cur))); + ut_ad(page_is_leaf(btr_cur_get_page(&btr_cur))); + ut_ad(!page_has_prev(btr_cur_get_page(&btr_cur))); + ut_ad(!buf_block_get_page_zip(btr_cur_get_block(&btr_cur))); +} + +/** Initialize instant->field_map. +@tparam replace_dropped whether to point clustered index fields +to instant->dropped[] +@param[in] table table definition to copy from */ +template<bool replace_dropped> +inline void dict_table_t::init_instant(const dict_table_t& table) +{ + const dict_index_t& oindex = *table.indexes.start; + dict_index_t& index = *indexes.start; + const unsigned u = index.first_user_field(); + DBUG_ASSERT(u == oindex.first_user_field()); + DBUG_ASSERT(index.n_fields >= oindex.n_fields); + + field_map_element_t* field_map_it = static_cast<field_map_element_t*>( + mem_heap_zalloc(heap, (index.n_fields - u) + * sizeof *field_map_it)); + instant->field_map = field_map_it; + + ut_d(unsigned n_drop = 0); + ut_d(unsigned n_nullable = 0); + for (unsigned i = u; i < index.n_fields; i++) { + auto& f = index.fields[i]; + DBUG_ASSERT(dict_col_get_fixed_size(f.col, not_redundant()) + <= DICT_MAX_FIXED_COL_LEN); + ut_d(n_nullable += f.col->is_nullable()); + + if (!f.col->is_dropped()) { + (*field_map_it++).set_ind(f.col->ind); + continue; + } + + auto fixed_len = dict_col_get_fixed_size( + f.col, not_redundant()); + field_map_it->set_dropped(); + if (!f.col->is_nullable()) { + field_map_it->set_not_null(); + } + field_map_it->set_ind(fixed_len + ? uint16_t(fixed_len + 1) + : f.col->len > 255); + field_map_it++; + ut_ad(f.col >= table.instant->dropped); + ut_ad(f.col < table.instant->dropped + + table.instant->n_dropped); + ut_d(n_drop++); + if (replace_dropped) { + size_t d = f.col - table.instant->dropped; + ut_ad(f.col == &table.instant->dropped[d]); + ut_ad(d <= instant->n_dropped); + f.col = &instant->dropped[d]; + } + } + ut_ad(n_drop == n_dropped()); + ut_ad(field_map_it == &instant->field_map[index.n_fields - u]); + ut_ad(index.n_nullable == n_nullable); +} + +/** Set is_instant() before instant_column(). +@param[in] old previous table definition +@param[in] col_map map from old.cols[] and old.v_cols[] to this +@param[out] first_alter_pos 0, or 1 + first changed column position */ +inline void dict_table_t::prepare_instant(const dict_table_t& old, + const ulint* col_map, + unsigned& first_alter_pos) +{ + DBUG_ASSERT(!is_instant()); + DBUG_ASSERT(n_dropped() == 0); + DBUG_ASSERT(old.n_cols == old.n_def); + DBUG_ASSERT(n_cols == n_def); + DBUG_ASSERT(old.supports_instant()); + DBUG_ASSERT(!persistent_autoinc + || persistent_autoinc == old.persistent_autoinc); + /* supports_instant() does not necessarily hold here, + in case ROW_FORMAT=COMPRESSED according to the + MariaDB data dictionary, and ALTER_OPTIONS was not set. + If that is the case, the instant ALTER TABLE would keep + the InnoDB table in its current format. */ + + dict_index_t& oindex = *old.indexes.start; + dict_index_t& index = *indexes.start; + first_alter_pos = 0; + + mtr_t mtr; + mtr.start(); + /* Protect oindex.n_core_fields and others, so that + purge cannot invoke dict_index_t::clear_instant_alter(). */ + instant_metadata_lock(oindex, mtr); + + for (unsigned i = 0; i + DATA_N_SYS_COLS < old.n_cols; i++) { + if (col_map[i] != i) { + first_alter_pos = 1 + i; + goto add_metadata; + } + } + + if (!old.instant) { + /* Columns were not dropped or reordered. + Therefore columns must have been added at the end, + or modified instantly in place. */ + DBUG_ASSERT(index.n_fields >= oindex.n_fields); + DBUG_ASSERT(index.n_fields > oindex.n_fields + || !not_redundant()); +#ifdef UNIV_DEBUG + if (index.n_fields == oindex.n_fields) { + ut_ad(!not_redundant()); + for (unsigned i = index.n_fields; i--; ) { + ut_ad(index.fields[i].col->same_format( + *oindex.fields[i].col)); + } + } +#endif +set_core_fields: + index.n_core_fields = oindex.n_core_fields; + index.n_core_null_bytes = oindex.n_core_null_bytes; + } else { +add_metadata: + const unsigned n_old_drop = old.n_dropped(); + unsigned n_drop = n_old_drop; + for (unsigned i = old.n_cols; i--; ) { + if (col_map[i] == ULINT_UNDEFINED) { + DBUG_ASSERT(i + DATA_N_SYS_COLS + < uint(old.n_cols)); + n_drop++; + } + } + + instant = new (mem_heap_alloc(heap, sizeof(dict_instant_t))) + dict_instant_t(); + instant->n_dropped = n_drop; + if (n_drop) { + instant->dropped + = static_cast<dict_col_t*>( + mem_heap_alloc(heap, n_drop + * sizeof(dict_col_t))); + if (n_old_drop) { + memcpy(instant->dropped, old.instant->dropped, + n_old_drop * sizeof(dict_col_t)); + } + } else { + instant->dropped = NULL; + } + + unsigned d = n_old_drop; + + for (unsigned i = 0; i < old.n_cols; i++) { + if (col_map[i] == ULINT_UNDEFINED) { + (new (&instant->dropped[d++]) + dict_col_t(old.cols[i]))->set_dropped(); + } + } +#ifndef DBUG_OFF + for (unsigned i = 0; i < n_drop; i++) { + DBUG_ASSERT(instant->dropped[i].is_dropped()); + } +#endif + DBUG_ASSERT(d == n_drop); + const uint n_fields = index.n_fields + n_dropped(); + + DBUG_ASSERT(n_fields >= oindex.n_fields); + dict_field_t* fields = static_cast<dict_field_t*>( + mem_heap_zalloc(heap, n_fields * sizeof *fields)); + d = n_old_drop; + uint i = 0, j = 0, n_nullable = 0; + ut_d(uint core_null = 0); + for (; i < oindex.n_fields; i++) { + DBUG_ASSERT(j <= i); + dict_field_t&f = fields[i] = oindex.fields[i]; + if (f.col->is_dropped()) { + /* The column has been instantly + dropped earlier. */ + DBUG_ASSERT(f.col >= old.instant->dropped); + { + size_t d = f.col + - old.instant->dropped; + DBUG_ASSERT(d < n_old_drop); + DBUG_ASSERT(&old.instant->dropped[d] + == f.col); + DBUG_ASSERT(!f.name); + f.col = instant->dropped + d; + } + if (f.col->is_nullable()) { +found_nullable: + n_nullable++; + ut_d(core_null + += i < oindex.n_core_fields); + } + continue; + } + + const ulint col_ind = col_map[f.col->ind]; + if (col_ind != ULINT_UNDEFINED) { + if (index.fields[j].col->ind != col_ind) { + /* The fields for instantly + added columns must be placed + last in the clustered index. + Keep pre-existing fields in + the same position. */ + uint k; + for (k = j + 1; k < index.n_fields; + k++) { + if (index.fields[k].col->ind + == col_ind) { + goto found_j; + } + } + DBUG_ASSERT(!"no such col"); +found_j: + std::swap(index.fields[j], + index.fields[k]); + } + DBUG_ASSERT(index.fields[j].col->ind + == col_ind); + fields[i] = index.fields[j++]; + DBUG_ASSERT(!fields[i].col->is_dropped()); + DBUG_ASSERT(fields[i].name + == fields[i].col->name(*this)); + if (fields[i].col->is_nullable()) { + goto found_nullable; + } + continue; + } + + /* This column is being dropped. */ + DBUG_ASSERT(d < n_drop); + f.col = &instant->dropped[d++]; + f.name = NULL; + if (f.col->is_nullable()) { + goto found_nullable; + } + } + ut_ad(UT_BITS_IN_BYTES(core_null) == oindex.n_core_null_bytes); + DBUG_ASSERT(i >= oindex.n_core_fields); + DBUG_ASSERT(j <= i); + DBUG_ASSERT(n_fields - (i - j) == index.n_fields); + std::sort(index.fields + j, index.fields + index.n_fields, + [](const dict_field_t& a, const dict_field_t& b) + { return a.col->ind < b.col->ind; }); + DBUG_ASSERT(d == n_drop); + for (; i < n_fields; i++) { + fields[i] = index.fields[j++]; + n_nullable += fields[i].col->is_nullable(); + DBUG_ASSERT(!fields[i].col->is_dropped()); + DBUG_ASSERT(fields[i].name + == fields[i].col->name(*this)); + } + DBUG_ASSERT(j == index.n_fields); + index.n_fields = index.n_def = n_fields; + index.fields = fields; + DBUG_ASSERT(n_nullable >= index.n_nullable); + DBUG_ASSERT(n_nullable >= oindex.n_nullable); + index.n_nullable = n_nullable; + goto set_core_fields; + } + + DBUG_ASSERT(n_cols + n_dropped() >= old.n_cols + old.n_dropped()); + DBUG_ASSERT(n_dropped() >= old.n_dropped()); + DBUG_ASSERT(index.n_core_fields == oindex.n_core_fields); + DBUG_ASSERT(index.n_core_null_bytes == oindex.n_core_null_bytes); + mtr.commit(); +} + +/** Adjust index metadata for instant ADD/DROP/reorder COLUMN. +@param[in] clustered index definition after instant ALTER TABLE */ +inline void dict_index_t::instant_add_field(const dict_index_t& instant) +{ + DBUG_ASSERT(is_primary()); + DBUG_ASSERT(instant.is_primary()); + DBUG_ASSERT(!has_virtual()); + DBUG_ASSERT(!instant.has_virtual()); + DBUG_ASSERT(instant.n_core_fields <= instant.n_fields); + DBUG_ASSERT(n_def == n_fields); + DBUG_ASSERT(instant.n_def == instant.n_fields); + DBUG_ASSERT(type == instant.type); + DBUG_ASSERT(trx_id_offset == instant.trx_id_offset); + DBUG_ASSERT(n_user_defined_cols == instant.n_user_defined_cols); + DBUG_ASSERT(n_uniq == instant.n_uniq); + DBUG_ASSERT(instant.n_fields >= n_fields); + DBUG_ASSERT(instant.n_nullable >= n_nullable); + /* dict_table_t::prepare_instant() initialized n_core_fields + to be equal. However, after that purge could have emptied the + table and invoked dict_index_t::clear_instant_alter(). */ + DBUG_ASSERT(instant.n_core_fields <= n_core_fields); + DBUG_ASSERT(instant.n_core_null_bytes <= n_core_null_bytes); + DBUG_ASSERT(instant.n_core_fields == n_core_fields + || (!is_instant() && instant.is_instant())); + DBUG_ASSERT(instant.n_core_null_bytes == n_core_null_bytes + || (!is_instant() && instant.is_instant())); + + /* instant will have all fields (including ones for columns + that have been or are being instantly dropped) in the same position + as this index. Fields for any added columns are appended at the end. */ +#ifndef DBUG_OFF + for (unsigned i = 0; i < n_fields; i++) { + DBUG_ASSERT(fields[i].same(instant.fields[i])); + DBUG_ASSERT(instant.fields[i].col->same_format(*fields[i] + .col)); + /* Instant conversion from NULL to NOT NULL is not allowed. */ + DBUG_ASSERT(!fields[i].col->is_nullable() + || instant.fields[i].col->is_nullable()); + DBUG_ASSERT(fields[i].col->is_nullable() + == instant.fields[i].col->is_nullable() + || !table->not_redundant()); + } +#endif + n_fields = instant.n_fields; + n_def = instant.n_def; + n_nullable = instant.n_nullable; + fields = static_cast<dict_field_t*>( + mem_heap_dup(heap, instant.fields, n_fields * sizeof *fields)); + + ut_d(unsigned n_null = 0); + ut_d(unsigned n_dropped = 0); + + for (unsigned i = 0; i < n_fields; i++) { + const dict_col_t* icol = instant.fields[i].col; + dict_field_t& f = fields[i]; + ut_d(n_null += icol->is_nullable()); + DBUG_ASSERT(!icol->is_virtual()); + if (icol->is_dropped()) { + ut_d(n_dropped++); + f.col->set_dropped(); + f.name = NULL; + } else { + f.col = &table->cols[icol - instant.table->cols]; + f.name = f.col->name(*table); + } + } + + ut_ad(n_null == n_nullable); + ut_ad(n_dropped == instant.table->n_dropped()); +} + +/** Adjust table metadata for instant ADD/DROP/reorder COLUMN. +@param[in] table altered table (with dropped columns) +@param[in] col_map mapping from cols[] and v_cols[] to table */ +inline void dict_table_t::instant_column(const dict_table_t& table, + const ulint* col_map) +{ + DBUG_ASSERT(!table.cached); + DBUG_ASSERT(table.n_def == table.n_cols); + DBUG_ASSERT(table.n_t_def == table.n_t_cols); + DBUG_ASSERT(n_def == n_cols); + DBUG_ASSERT(n_t_def == n_t_cols); + DBUG_ASSERT(n_v_def == n_v_cols); + DBUG_ASSERT(table.n_v_def == table.n_v_cols); + DBUG_ASSERT(table.n_cols + table.n_dropped() >= n_cols + n_dropped()); + DBUG_ASSERT(!table.persistent_autoinc + || persistent_autoinc == table.persistent_autoinc); + ut_ad(mutex_own(&dict_sys->mutex)); + + { + const char* end = table.col_names; + for (unsigned i = table.n_cols; i--; ) end += strlen(end) + 1; + + col_names = static_cast<char*>( + mem_heap_dup(heap, table.col_names, + ulint(end - table.col_names))); + } + const dict_col_t* const old_cols = cols; + cols = static_cast<dict_col_t*>(mem_heap_dup(heap, table.cols, + table.n_cols + * sizeof *cols)); + + /* Preserve the default values of previously instantly added + columns, or copy the new default values to this->heap. */ + for (ulint i = 0; i < ulint(table.n_cols); i++) { + dict_col_t& c = cols[i]; + + if (const dict_col_t* o = find(old_cols, col_map, n_cols, i)) { + c.def_val = o->def_val; + DBUG_ASSERT(!((c.prtype ^ o->prtype) + & ~(DATA_NOT_NULL | DATA_VERSIONED))); + DBUG_ASSERT(c.mtype == o->mtype); + DBUG_ASSERT(c.len >= o->len); + continue; + } + + DBUG_ASSERT(c.is_added()); + if (c.def_val.len <= sizeof field_ref_zero + && !memcmp(c.def_val.data, field_ref_zero, + c.def_val.len)) { + c.def_val.data = field_ref_zero; + } else if (const void*& d = c.def_val.data) { + d = mem_heap_dup(heap, d, c.def_val.len); + } else { + DBUG_ASSERT(c.def_val.len == UNIV_SQL_NULL); + } + } + + n_t_def += table.n_cols - n_cols; + n_t_cols += table.n_cols - n_cols; + n_def = table.n_cols; + + const dict_v_col_t* const old_v_cols = v_cols; + + if (const char* end = table.v_col_names) { + for (unsigned i = table.n_v_cols; i--; ) { + end += strlen(end) + 1; + } + + v_col_names = static_cast<char*>( + mem_heap_dup(heap, table.v_col_names, + ulint(end - table.v_col_names))); + v_cols = static_cast<dict_v_col_t*>( + mem_heap_dup(heap, table.v_cols, + table.n_v_cols * sizeof *v_cols)); + } else { + ut_ad(table.n_v_cols == 0); + v_col_names = NULL; + v_cols = NULL; + } + + n_t_def += table.n_v_cols - n_v_cols; + n_t_cols += table.n_v_cols - n_v_cols; + n_v_def = table.n_v_cols; + + for (unsigned i = 0; i < n_v_def; i++) { + dict_v_col_t& v = v_cols[i]; + v.v_indexes = UT_NEW_NOKEY(dict_v_idx_list()); + v.base_col = static_cast<dict_col_t**>( + mem_heap_dup(heap, v.base_col, + v.num_base * sizeof *v.base_col)); + + for (ulint n = v.num_base; n--; ) { + dict_col_t*& base = v.base_col[n]; + if (base->is_virtual()) { + } else if (base >= table.cols + && base < table.cols + table.n_cols) { + /* The base column was instantly added. */ + size_t c = base - table.cols; + DBUG_ASSERT(base == &table.cols[c]); + base = &cols[c]; + } else { + DBUG_ASSERT(base >= old_cols); + size_t c = base - old_cols; + DBUG_ASSERT(c + DATA_N_SYS_COLS < n_cols); + DBUG_ASSERT(base == &old_cols[c]); + DBUG_ASSERT(col_map[c] + DATA_N_SYS_COLS + < n_cols); + base = &cols[col_map[c]]; + } + } + } + + dict_index_t* index = dict_table_get_first_index(this); + + index->instant_add_field(*dict_table_get_first_index(&table)); + + if (instant || table.instant) { + /* FIXME: add instant->heap, and transfer ownership here */ + if (!instant) { + instant = new (mem_heap_zalloc(heap, sizeof *instant)) + dict_instant_t(); + goto dup_dropped; + } else if (n_dropped() < table.n_dropped()) { +dup_dropped: + instant->dropped = static_cast<dict_col_t*>( + mem_heap_dup(heap, table.instant->dropped, + table.instant->n_dropped + * sizeof *instant->dropped)); + instant->n_dropped = table.instant->n_dropped; + } else if (table.instant->n_dropped) { + memcpy(instant->dropped, table.instant->dropped, + table.instant->n_dropped + * sizeof *instant->dropped); + } + + init_instant<true>(table); + } + + while ((index = dict_table_get_next_index(index)) != NULL) { + if (index->to_be_dropped) { + continue; + } + for (unsigned i = 0; i < index->n_fields; i++) { + dict_field_t& f = index->fields[i]; + if (f.col >= table.cols + && f.col < table.cols + table.n_cols) { + /* This is an instantly added column + in a newly added index. */ + DBUG_ASSERT(!f.col->is_virtual()); + size_t c = f.col - table.cols; + DBUG_ASSERT(f.col == &table.cols[c]); + f.col = &cols[c]; + } else if (f.col >= &table.v_cols->m_col + && f.col < &table.v_cols[n_v_cols].m_col) { + /* This is an instantly added virtual column + in a newly added index. */ + DBUG_ASSERT(f.col->is_virtual()); + size_t c = reinterpret_cast<dict_v_col_t*>( + f.col) - table.v_cols; + DBUG_ASSERT(f.col == &table.v_cols[c].m_col); + f.col = &v_cols[c].m_col; + } else if (f.col < old_cols + || f.col >= old_cols + n_cols) { + DBUG_ASSERT(f.col->is_virtual()); + f.col = &v_cols[col_map[ + reinterpret_cast<dict_v_col_t*>( + f.col) + - old_v_cols + n_cols]].m_col; + } else { + f.col = &cols[col_map[f.col - old_cols]]; + DBUG_ASSERT(!f.col->is_virtual()); + } + f.name = f.col->name(*this); + if (f.col->is_virtual()) { + reinterpret_cast<dict_v_col_t*>(f.col) + ->v_indexes->push_back( + dict_v_idx_t(index, i)); + } + } + } + + n_cols = table.n_cols; + n_v_cols = table.n_v_cols; +} + +/** Find the old column number for the given new column position. +@param[in] col_map column map from old column to new column +@param[in] pos new column position +@param[in] n number of columns present in the column map +@return old column position for the given new column position. */ +static ulint find_old_col_no(const ulint* col_map, ulint pos, ulint n) +{ + do { + ut_ad(n); + } while (col_map[--n] != pos); + return n; +} + +/** Roll back instant_column(). +@param[in] old_n_cols original n_cols +@param[in] old_cols original cols +@param[in] old_col_names original col_names +@param[in] old_instant original instant structure +@param[in] old_fields original fields +@param[in] old_n_fields original number of fields +@param[in] old_n_v_cols original n_v_cols +@param[in] old_v_cols original v_cols +@param[in] old_v_col_names original v_col_names +@param[in] col_map column map */ +inline void dict_table_t::rollback_instant( + unsigned old_n_cols, + dict_col_t* old_cols, + const char* old_col_names, + dict_instant_t* old_instant, + dict_field_t* old_fields, + unsigned old_n_fields, + unsigned old_n_v_cols, + dict_v_col_t* old_v_cols, + const char* old_v_col_names, + const ulint* col_map) +{ + ut_ad(mutex_own(&dict_sys->mutex)); + ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X)); + dict_index_t* index = indexes.start; + mtr_t mtr; + mtr.start(); + /* Prevent concurrent execution of dict_index_t::clear_instant_alter() + by acquiring a latch on the leftmost leaf page. */ + instant_metadata_lock(*index, mtr); + /* index->is_instant() does not necessarily hold here, because + the table may have been emptied */ + DBUG_ASSERT(old_n_cols >= DATA_N_SYS_COLS); + DBUG_ASSERT(n_cols == n_def); + DBUG_ASSERT(index->n_def == index->n_fields); + DBUG_ASSERT(index->n_core_fields <= index->n_fields); + DBUG_ASSERT(instant || !old_instant); + + instant = old_instant; + + index->n_nullable = 0; + + for (unsigned i = old_n_fields; i--; ) { + if (old_fields[i].col->is_nullable()) { + index->n_nullable++; + } + } + + for (unsigned i = n_v_cols; i--; ) { + UT_DELETE(v_cols[i].v_indexes); + } + + index->n_def = index->n_fields = old_n_fields; + if (index->n_core_fields > old_n_fields) { + index->n_core_fields = old_n_fields; + index->n_core_null_bytes = UT_BITS_IN_BYTES(index->n_nullable); + } + + const dict_col_t* const new_cols = cols; + const dict_col_t* const new_cols_end = cols + n_cols; + const dict_v_col_t* const new_v_cols = v_cols; + const dict_v_col_t* const new_v_cols_end = v_cols + n_v_cols; + + cols = old_cols; + col_names = old_col_names; + v_cols = old_v_cols; + v_col_names = old_v_col_names; + n_def = n_cols = old_n_cols; + n_v_def = n_v_cols = old_n_v_cols; + n_t_def = n_t_cols = n_cols + n_v_cols; + + index->fields = old_fields; + mtr.commit(); + + while ((index = dict_table_get_next_index(index)) != NULL) { + if (index->to_be_dropped) { + /* instant_column() did not adjust these indexes. */ + continue; + } + + for (unsigned i = 0; i < index->n_fields; i++) { + dict_field_t& f = index->fields[i]; + if (f.col->is_virtual()) { + DBUG_ASSERT(f.col >= &new_v_cols->m_col); + DBUG_ASSERT(f.col < &new_v_cols_end->m_col); + size_t n = size_t( + reinterpret_cast<dict_v_col_t*>(f.col) + - new_v_cols); + DBUG_ASSERT(n <= n_v_cols); + + ulint old_col_no = find_old_col_no( + col_map + n_cols, n, n_v_cols); + DBUG_ASSERT(old_col_no <= n_v_cols); + f.col = &v_cols[old_col_no].m_col; + DBUG_ASSERT(f.col->is_virtual()); + } else { + DBUG_ASSERT(f.col >= new_cols); + DBUG_ASSERT(f.col < new_cols_end); + size_t n = size_t(f.col - new_cols); + DBUG_ASSERT(n <= n_cols); + + ulint old_col_no = find_old_col_no(col_map, + n, n_cols); + DBUG_ASSERT(old_col_no < n_cols); + f.col = &cols[old_col_no]; + DBUG_ASSERT(!f.col->is_virtual()); + } + f.name = f.col->name(*this); + } + } +} + struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx { /** Dummy query graph */ @@ -174,7 +841,7 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx dict_table_t* old_table; /** table where the indexes are being created or dropped */ dict_table_t* new_table; - /** table definition for instant ADD COLUMN */ + /** table definition for instant ADD/DROP/reorder COLUMN */ dict_table_t* instant_table; /** mapping of old column numbers to new ones, or NULL */ const ulint* col_map; @@ -208,7 +875,20 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx dict_col_t* const old_cols; /** original column names of the table */ const char* const old_col_names; - + /** original instantly dropped or reordered columns */ + dict_instant_t* const old_instant; + /** original index fields */ + dict_field_t* const old_fields; + /** size of old_fields */ + const unsigned old_n_fields; + /** original number of virtual columns in the table */ + const unsigned old_n_v_cols; + /** original virtual columns of the table */ + dict_v_col_t* const old_v_cols; + /** original virtual column names of the table */ + const char* const old_v_col_names; + /** 0, or 1 + first column whose position changes in instant ALTER */ + unsigned first_alter_pos; /** Allow non-null conversion. (1) Alter ignore should allow the conversion irrespective of sql mode. @@ -265,6 +945,13 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx old_n_cols(prebuilt_arg->table->n_cols), old_cols(prebuilt_arg->table->cols), old_col_names(prebuilt_arg->table->col_names), + old_instant(prebuilt_arg->table->instant), + old_fields(prebuilt_arg->table->indexes.start->fields), + old_n_fields(prebuilt_arg->table->indexes.start->n_fields), + old_n_v_cols(prebuilt_arg->table->n_v_cols), + old_v_cols(prebuilt_arg->table->v_cols), + old_v_col_names(prebuilt_arg->table->v_col_names), + first_alter_pos(0), allow_not_null(allow_not_null_flag), page_compression_level(page_compressed ? (page_compression_level_arg @@ -297,6 +984,9 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx rw_lock_free(&index->lock); dict_mem_index_free(index); } + for (unsigned i = old_n_v_cols; i--; ) { + UT_DELETE(old_v_cols[i].v_indexes); + } dict_mem_table_free(instant_table); } mem_heap_free(heap); @@ -321,14 +1011,23 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx { DBUG_ASSERT(need_rebuild()); DBUG_ASSERT(!is_instant()); - DBUG_ASSERT(old_table->n_cols == old_table->n_def); - DBUG_ASSERT(new_table->n_cols == new_table->n_def); DBUG_ASSERT(old_table->n_cols == old_n_cols); - DBUG_ASSERT(new_table->n_cols > old_table->n_cols); - instant_table = new_table; + instant_table = new_table; new_table = old_table; export_vars.innodb_instant_alter_column++; + + instant_table->prepare_instant(*old_table, col_map, + first_alter_pos); + } + + /** Adjust table metadata for instant ADD/DROP/reorder COLUMN. */ + void instant_column() + { + DBUG_ASSERT(is_instant()); + DBUG_ASSERT(old_n_fields + == old_table->indexes.start->n_fields); + old_table->instant_column(*instant_table, col_map); } /** Revert prepare_instant() if the transaction is rolled back. */ @@ -336,7 +1035,12 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx { if (!is_instant()) return; old_table->rollback_instant(old_n_cols, - old_cols, old_col_names); + old_cols, old_col_names, + old_instant, + old_fields, old_n_fields, + old_n_v_cols, old_v_cols, + old_v_col_names, + col_map); } /** @return whether this is instant ALTER TABLE */ @@ -666,21 +1370,72 @@ check_v_col_in_order( } /** Determine if an instant operation is possible for altering columns. +@param[in] ib_table InnoDB table definition @param[in] ha_alter_info the ALTER TABLE operation @param[in] table table definition before ALTER TABLE */ static bool instant_alter_column_possible( + const dict_table_t& ib_table, const Alter_inplace_info* ha_alter_info, const TABLE* table) { + if (!ib_table.supports_instant()) { + return false; + } +#if 1 // MDEV-17459: adjust fts_fetch_doc_from_rec() and friends; remove this + if (ib_table.fts) { + return false; + } +#endif + const dict_index_t* index = ib_table.indexes.start; + if (ha_alter_info->handler_flags & ALTER_ADD_STORED_BASE_COLUMN) { + List_iterator_fast<Create_field> cf_it( + ha_alter_info->alter_info->create_list); + uint n_add = 0; + while (const Create_field* cf = cf_it++) { + n_add += !cf->field; + } + if (index->n_fields >= REC_MAX_N_USER_FIELDS + DATA_N_SYS_COLS + - n_add) { + return false; + } + } +#if 1 // MDEV-17468: fix bugs with indexed virtual columns & remove this + ut_ad(index->is_primary()); + ut_ad(!index->has_virtual()); + while ((index = index->indexes.next) != NULL) { + if (index->has_virtual()) { + ut_ad(ib_table.n_v_cols); + return false; + } + } +#endif // Making table system-versioned instantly is not implemented yet. if (ha_alter_info->handler_flags & ALTER_ADD_SYSTEM_VERSIONING) { return false; } - if (~ha_alter_info->handler_flags & ALTER_ADD_STORED_BASE_COLUMN) { - return false; + static constexpr alter_table_operations avoid_rebuild + = ALTER_ADD_STORED_BASE_COLUMN + | ALTER_DROP_STORED_COLUMN + | ALTER_STORED_COLUMN_ORDER + | ALTER_COLUMN_NULLABLE; + + if (!(ha_alter_info->handler_flags & avoid_rebuild)) { + alter_table_operations flags = ha_alter_info->handler_flags + & ~avoid_rebuild; + /* None of the flags are set that we can handle + specially to avoid rebuild. In this case, we can + allow ALGORITHM=INSTANT, except if some requested + operation requires that the table be rebuilt. */ + if (flags & INNOBASE_ALTER_REBUILD) { + return false; + } + if ((flags & ALTER_OPTIONS) + && alter_options_need_rebuild(ha_alter_info, table)) { + return false; + } } /* At the moment, we disallow ADD [UNIQUE] INDEX together with @@ -702,12 +1457,26 @@ instant_alter_column_possible( columns. */ if (ha_alter_info->handler_flags & ((INNOBASE_ALTER_REBUILD | INNOBASE_ONLINE_CREATE) - & ~ALTER_ADD_STORED_BASE_COLUMN & ~ALTER_OPTIONS)) { + & ~ALTER_DROP_STORED_COLUMN + & ~ALTER_STORED_COLUMN_ORDER + & ~ALTER_ADD_STORED_BASE_COLUMN + & ~ALTER_COLUMN_NULLABLE + & ~ALTER_OPTIONS)) { return false; } - return !(ha_alter_info->handler_flags & ALTER_OPTIONS) - || !alter_options_need_rebuild(ha_alter_info, table); + if ((ha_alter_info->handler_flags & ALTER_OPTIONS) + && alter_options_need_rebuild(ha_alter_info, table)) { + return false; + } + + if ((ha_alter_info->handler_flags + & ALTER_COLUMN_NULLABLE) + && ib_table.not_redundant()) { + return false; + } + + return true; } /** Check whether the non-const default value for the field @@ -1014,6 +1783,8 @@ ha_innobase::check_if_supported_inplace_alter( DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } + const bool supports_instant = instant_alter_column_possible( + *m_prebuilt->table, ha_alter_info, table); bool add_drop_v_cols = false; /* If there is add or drop virtual columns, we will support operations @@ -1041,7 +1812,13 @@ ha_innobase::check_if_supported_inplace_alter( */ | ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX | ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX); - + if (supports_instant) { + flags &= ~(ALTER_DROP_STORED_COLUMN +#if 0 /* MDEV-17468: remove check_v_col_in_order() and fix the code */ + | ALTER_ADD_STORED_BASE_COLUMN +#endif + | ALTER_STORED_COLUMN_ORDER); + } if (flags != 0 || IF_PARTITIONING((altered_table->s->partition_info_str && altered_table->s->partition_info_str_len), 0) @@ -1222,8 +1999,8 @@ ha_innobase::check_if_supported_inplace_alter( constant DEFAULT expression. */ cf_it.rewind(); Field **af = altered_table->field; - bool add_column_not_last = false; - uint n_stored_cols = 0, n_add_cols = 0; + bool fts_need_rebuild = false; + const bool need_rebuild = innobase_need_rebuild(ha_alter_info, table); while (Create_field* cf = cf_it++) { DBUG_ASSERT(cf->field @@ -1271,45 +2048,34 @@ ha_innobase::check_if_supported_inplace_alter( goto next_column; } - ha_alter_info->unsupported_reason - = my_get_err_msg( - ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL); - } else if (!is_non_const_value(*af)) { - - n_add_cols++; - - if (af < &altered_table->field[table_share->fields]) { - add_column_not_last = true; - } - - if (set_default_value(*af)) { - goto next_column; + ha_alter_info->unsupported_reason = my_get_err_msg( + ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL); + } else if (!is_non_const_value(*af) + && set_default_value(*af)) { + if (m_prebuilt->table->fts + && innobase_fulltext_exist(altered_table) + && !my_strcasecmp(system_charset_info, + (*af)->field_name.str, + FTS_DOC_ID_COL_NAME)) { + /* If a hidden FTS_DOC_ID column exists + (because of FULLTEXT INDEX), it cannot + be replaced with a user-created one + except when using ALGORITHM=COPY. */ + goto cannot_create_many_fulltext_index; } + goto next_column; } DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); next_column: - n_stored_cols += (*af++)->stored_in_db(); - } - - if (!add_column_not_last - && uint(m_prebuilt->table->n_cols) - DATA_N_SYS_COLS + n_add_cols - == n_stored_cols - && m_prebuilt->table->supports_instant() - && instant_alter_column_possible(ha_alter_info, table)) { - - DBUG_RETURN(HA_ALTER_INPLACE_INSTANT); + af++; } - if (!(ha_alter_info->handler_flags & ~(INNOBASE_ALTER_INSTANT - | INNOBASE_INPLACE_IGNORE))) { + if (supports_instant) { DBUG_RETURN(HA_ALTER_INPLACE_INSTANT); } - bool fts_need_rebuild = false; - const bool need_rebuild = innobase_need_rebuild(ha_alter_info, table); - if (!online) { /* We already determined that only a non-locking operation is possible. */ @@ -2294,9 +3060,9 @@ innobase_row_to_mysql( } } if (table->vfield) { - my_bitmap_map* old_vcol_set = tmp_use_all_columns(table, table->vcol_set); + my_bitmap_map* old_read_set = tmp_use_all_columns(table, table->read_set); table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_READ); - tmp_restore_column_map(table->vcol_set, old_vcol_set); + tmp_restore_column_map(table->read_set, old_read_set); } } @@ -3370,12 +4136,13 @@ innobase_build_col_map( } } - ut_ad(!is_v); - innobase_build_col_map_add( - heap, dtuple_get_nth_field(defaults, i), - altered_table->field[i + num_v], - NULL, - dict_table_is_comp(new_table)); + if (!is_v) { + innobase_build_col_map_add( + heap, dtuple_get_nth_field(defaults, i), + altered_table->field[i + num_v], + NULL, + dict_table_is_comp(new_table)); + } found_col: if (is_v) { num_v++; @@ -3843,13 +4610,12 @@ prepare_inplace_add_virtual( ha_innobase_inplace_ctx* ctx; ulint i = 0; ulint j = 0; - const Create_field* new_field; ctx = static_cast<ha_innobase_inplace_ctx*> (ha_alter_info->handler_ctx); - ctx->num_to_add_vcol = altered_table->s->fields - + ctx->num_to_drop_vcol - table->s->fields; + ctx->num_to_add_vcol = altered_table->s->virtual_fields + + ctx->num_to_drop_vcol - table->s->virtual_fields; ctx->add_vcol = static_cast<dict_v_col_t*>( mem_heap_zalloc(ctx->heap, ctx->num_to_add_vcol @@ -3861,43 +4627,21 @@ prepare_inplace_add_virtual( List_iterator_fast<Create_field> cf_it( ha_alter_info->alter_info->create_list); - while ((new_field = (cf_it++)) != NULL) { - const Field* field = new_field->field; - ulint old_i; - - for (old_i = 0; table->field[old_i]; old_i++) { - const Field* n_field = table->field[old_i]; - if (field == n_field) { - break; - } - } - - i++; + while (const Create_field* new_field = cf_it++) { + const Field* field = altered_table->field[i++]; - if (table->field[old_i]) { + if (new_field->field || !innobase_is_v_fld(field)) { continue; } - ut_ad(!field); - - ulint col_len; ulint is_unsigned; - ulint field_type; ulint charset_no; - - field = altered_table->field[i - 1]; - ulint col_type = get_innobase_type_from_mysql_type( &is_unsigned, field); - - if (!innobase_is_v_fld(field)) { - continue; - } - - col_len = field->pack_length(); - field_type = (ulint) field->type(); + ulint col_len = field->pack_length(); + ulint field_type = (ulint) field->type(); if (!field->real_maybe_null()) { field_type |= DATA_NOT_NULL; @@ -3939,7 +4683,6 @@ prepare_inplace_add_virtual( } } - ctx->add_vcol[j].m_col.prtype = dtype_form_prtype( field_type, charset_no); @@ -3958,6 +4701,7 @@ prepare_inplace_add_virtual( /* No need to track the list */ ctx->add_vcol[j].v_indexes = NULL; + /* MDEV-17468: Do this on ctx->instant_table later */ innodb_base_col_setup(ctx->old_table, field, &ctx->add_vcol[j]); j++; } @@ -4084,33 +4828,96 @@ prepare_inplace_drop_virtual( @param[in] pos virtual column column no @param[in] base_pos base column pos @param[in] trx transaction -@return DB_SUCCESS if successful, otherwise error code */ -static -dberr_t -innobase_insert_sys_virtual( +@retval false on success +@retval true on failure (my_error() will have been called) */ +static bool innobase_insert_sys_virtual( const dict_table_t* table, ulint pos, ulint base_pos, trx_t* trx) { pars_info_t* info = pars_info_create(); - pars_info_add_ull_literal(info, "id", table->id); + pars_info_add_int4_literal(info, "pos", pos); + pars_info_add_int4_literal(info, "base_pos", base_pos); + + if (DB_SUCCESS != que_eval_sql( + info, + "PROCEDURE P () IS\n" + "BEGIN\n" + "INSERT INTO SYS_VIRTUAL VALUES (:id, :pos, :base_pos);\n" + "END;\n", + FALSE, trx)) { + my_error(ER_INTERNAL_ERROR, MYF(0), + "InnoDB: ADD COLUMN...VIRTUAL"); + return true; + } + + return false; +} +/** Insert a record to the SYS_COLUMNS dictionary table. +@param[in] table_id table id +@param[in] pos position of the column +@param[in] field_name field name +@param[in] mtype main type +@param[in] prtype precise type +@param[in] len fixed length in bytes, or 0 +@param[in] n_base number of base columns of virtual columns, or 0 +@param[in] update whether to update instead of inserting +@retval false on success +@retval true on failure (my_error() will have been called) */ +static bool innodb_insert_sys_columns( + table_id_t table_id, + ulint pos, + const char* field_name, + ulint mtype, + ulint prtype, + ulint len, + ulint n_base, + trx_t* trx, + bool update = false) +{ + pars_info_t* info = pars_info_create(); + pars_info_add_ull_literal(info, "id", table_id); pars_info_add_int4_literal(info, "pos", pos); + pars_info_add_str_literal(info, "name", field_name); + pars_info_add_int4_literal(info, "mtype", mtype); + pars_info_add_int4_literal(info, "prtype", prtype); + pars_info_add_int4_literal(info, "len", len); + pars_info_add_int4_literal(info, "base", n_base); + + if (update) { + if (DB_SUCCESS != que_eval_sql( + info, + "PROCEDURE UPD_COL () IS\n" + "BEGIN\n" + "UPDATE SYS_COLUMNS SET\n" + "NAME=:name, MTYPE=:mtype, PRTYPE=:prtype, " + "LEN=:len, PREC=:base\n" + "WHERE TABLE_ID=:id AND POS=:pos;\n" + "END;\n", FALSE, trx)) { + my_error(ER_INTERNAL_ERROR, MYF(0), + "InnoDB: Updating SYS_COLUMNS failed"); + return true; + } - pars_info_add_int4_literal(info, "base_pos", base_pos); + return false; + } - dberr_t error = que_eval_sql( - info, - "PROCEDURE P () IS\n" - "BEGIN\n" - "INSERT INTO SYS_VIRTUAL VALUES" - "(:id, :pos, :base_pos);\n" - "END;\n", - FALSE, trx); + if (DB_SUCCESS != que_eval_sql( + info, + "PROCEDURE ADD_COL () IS\n" + "BEGIN\n" + "INSERT INTO SYS_COLUMNS VALUES" + "(:id,:pos,:name,:mtype,:prtype,:len,:base);\n" + "END;\n", FALSE, trx)) { + my_error(ER_INTERNAL_ERROR, MYF(0), + "InnoDB: Insert into SYS_COLUMNS failed"); + return true; + } - return(error); + return false; } /** Update INNODB SYS_COLUMNS on new virtual columns @@ -4118,10 +4925,9 @@ innobase_insert_sys_virtual( @param[in] col_name column name @param[in] vcol virtual column @param[in] trx transaction -@return DB_SUCCESS if successful, otherwise error code */ -static -dberr_t -innobase_add_one_virtual( +@retval false on success +@retval true on failure (my_error() will have been called) */ +static bool innobase_add_one_virtual( const dict_table_t* table, const char* col_name, dict_v_col_t* vcol, @@ -4129,67 +4935,41 @@ innobase_add_one_virtual( { ulint pos = dict_create_v_col_pos(vcol->v_pos, vcol->m_col.ind); - ulint mtype = vcol->m_col.mtype; - ulint prtype = vcol->m_col.prtype; - ulint len = vcol->m_col.len; - pars_info_t* info = pars_info_create(); - - pars_info_add_ull_literal(info, "id", table->id); - - pars_info_add_int4_literal(info, "pos", pos); - - pars_info_add_str_literal(info, "name", col_name); - pars_info_add_int4_literal(info, "mtype", mtype); - pars_info_add_int4_literal(info, "prtype", prtype); - pars_info_add_int4_literal(info, "len", len); - pars_info_add_int4_literal(info, "prec", vcol->num_base); - - dberr_t error = que_eval_sql( - info, - "PROCEDURE P () IS\n" - "BEGIN\n" - "INSERT INTO SYS_COLUMNS VALUES" - "(:id, :pos, :name, :mtype, :prtype, :len, :prec);\n" - "END;\n", - FALSE, trx); - if (error != DB_SUCCESS) { - return(error); + if (innodb_insert_sys_columns(table->id, pos, col_name, + vcol->m_col.mtype, vcol->m_col.prtype, + vcol->m_col.len, vcol->num_base, trx)) { + return true; } for (ulint i = 0; i < vcol->num_base; i++) { - error = innobase_insert_sys_virtual( - table, pos, vcol->base_col[i]->ind, trx); - if (error != DB_SUCCESS) { - return(error); + if (innobase_insert_sys_virtual( + table, pos, vcol->base_col[i]->ind, trx)) { + return true; } } - return(error); + return false; } /** Update SYS_TABLES.N_COLS in the data dictionary. @param[in] user_table InnoDB table -@param[in] n_cols the new value of SYS_TABLES.N_COLS +@param[in] n the new value of SYS_TABLES.N_COLS @param[in] trx transaction @return whether the operation failed */ -static -bool -innodb_update_n_cols(const dict_table_t* table, ulint n_cols, trx_t* trx) +static bool innodb_update_cols(const dict_table_t* table, ulint n, trx_t* trx) { pars_info_t* info = pars_info_create(); - pars_info_add_int4_literal(info, "n", n_cols); + pars_info_add_int4_literal(info, "n", n); pars_info_add_ull_literal(info, "id", table->id); - dberr_t err = que_eval_sql(info, - "PROCEDURE UPDATE_N_COLS () IS\n" - "BEGIN\n" - "UPDATE SYS_TABLES SET N_COLS = :n" - " WHERE ID = :id;\n" - "END;\n", FALSE, trx); - - if (err != DB_SUCCESS) { + if (DB_SUCCESS != que_eval_sql(info, + "PROCEDURE UPDATE_N_COLS () IS\n" + "BEGIN\n" + "UPDATE SYS_TABLES SET N_COLS = :n" + " WHERE ID = :id;\n" + "END;\n", FALSE, trx)) { my_error(ER_INTERNAL_ERROR, MYF(0), "InnoDB: Updating SYS_TABLES.N_COLS failed"); return true; @@ -4207,281 +4987,47 @@ innodb_update_n_cols(const dict_table_t* table, ulint n_cols, trx_t* trx) static bool innobase_add_virtual_try( - Alter_inplace_info* ha_alter_info, - const dict_table_t* user_table, - trx_t* trx) + const Alter_inplace_info* ha_alter_info, + const dict_table_t* user_table, + trx_t* trx) { - ha_innobase_inplace_ctx* ctx; - dberr_t err = DB_SUCCESS; - - ctx = static_cast<ha_innobase_inplace_ctx*>( + ha_innobase_inplace_ctx* ctx = static_cast<ha_innobase_inplace_ctx*>( ha_alter_info->handler_ctx); for (ulint i = 0; i < ctx->num_to_add_vcol; i++) { - - err = innobase_add_one_virtual( - user_table, ctx->add_vcol_name[i], - &ctx->add_vcol[i], trx); - - if (err != DB_SUCCESS) { - my_error(ER_INTERNAL_ERROR, MYF(0), - "InnoDB: ADD COLUMN...VIRTUAL"); - return(true); + if (innobase_add_one_virtual( + user_table, ctx->add_vcol_name[i], + &ctx->add_vcol[i], trx)) { + return true; } } - - ulint n_col = unsigned(user_table->n_cols) - DATA_N_SYS_COLS; - ulint n_v_col = unsigned(user_table->n_v_cols) - + ctx->num_to_add_vcol - ctx->num_to_drop_vcol; - ulint new_n = dict_table_encode_n_col(n_col, n_v_col) - + (unsigned(user_table->flags & DICT_TF_COMPACT) << 31); - - return innodb_update_n_cols(user_table, new_n, trx); + return false; } -/** Insert into SYS_COLUMNS and insert/update the hidden metadata record -for instant ADD COLUMN. -@param[in,out] ctx ALTER TABLE context for the current partition -@param[in] altered_table MySQL table that is being altered -@param[in] table MySQL table as it is before the ALTER operation -@param[in,out] trx dictionary transaction -@retval true failure -@retval false success */ -static -bool -innobase_add_instant_try( - ha_innobase_inplace_ctx*ctx, - const TABLE* altered_table, - const TABLE* table, - trx_t* trx) +/** Delete metadata from SYS_COLUMNS and SYS_VIRTUAL. +@param[in] id table id +@param[in] pos first SYS_COLUMNS.POS +@param[in,out] trx data dictionary transaction +@retval true Failure +@retval false Success. */ +static bool innobase_instant_drop_cols(table_id_t id, ulint pos, trx_t* trx) { - DBUG_ASSERT(!ctx->need_rebuild()); - - if (!ctx->is_instant()) return false; - - DBUG_ASSERT(altered_table->s->fields > table->s->fields); - DBUG_ASSERT(ctx->old_table->n_cols == ctx->old_n_cols); - - dict_table_t* user_table = ctx->old_table; - user_table->instant_add_column(*ctx->instant_table); - dict_index_t* index = dict_table_get_first_index(user_table); - /* The table may have been emptied and may have lost its - 'instant-add-ness' during this instant ADD COLUMN. */ - - /* Construct a table row of default values for the stored columns. */ - dtuple_t* row = dtuple_create(ctx->heap, user_table->n_cols); - dict_table_copy_types(row, user_table); - Field** af = altered_table->field; - Field** const end = altered_table->field + altered_table->s->fields; - - for (uint i = 0; af < end; af++) { - if (!(*af)->stored_in_db()) { - continue; - } - - dict_col_t* col = dict_table_get_nth_col(user_table, i); - DBUG_ASSERT(!strcmp((*af)->field_name.str, - dict_table_get_col_name(user_table, i))); - - dfield_t* d = dtuple_get_nth_field(row, i); - - if (col->is_instant()) { - dfield_set_data(d, col->def_val.data, - col->def_val.len); - } else if ((*af)->real_maybe_null()) { - /* Store NULL for nullable 'core' columns. */ - dfield_set_null(d); - } else { - switch ((*af)->type()) { - case MYSQL_TYPE_VARCHAR: - case MYSQL_TYPE_GEOMETRY: - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_LONG_BLOB: - /* Store the empty string for 'core' - variable-length NOT NULL columns. */ - dfield_set_data(d, field_ref_zero, 0); - break; - default: - /* For fixed-length NOT NULL 'core' columns, - get a dummy default value from SQL. Note that - we will preserve the old values of these - columns when updating the metadata - record, to avoid unnecessary updates. */ - ulint len = (*af)->pack_length(); - DBUG_ASSERT(d->type.mtype != DATA_INT - || len <= 8); - row_mysql_store_col_in_innobase_format( - d, d->type.mtype == DATA_INT - ? static_cast<byte*>( - mem_heap_alloc(ctx->heap, len)) - : NULL, true, (*af)->ptr, len, - dict_table_is_comp(user_table)); - } - } - - if (i + DATA_N_SYS_COLS < ctx->old_n_cols) { - i++; - continue; - } - - pars_info_t* info = pars_info_create(); - pars_info_add_ull_literal(info, "id", user_table->id); - pars_info_add_int4_literal(info, "pos", i); - pars_info_add_str_literal(info, "name", (*af)->field_name.str); - pars_info_add_int4_literal(info, "mtype", d->type.mtype); - pars_info_add_int4_literal(info, "prtype", d->type.prtype); - pars_info_add_int4_literal(info, "len", d->type.len); + pars_info_t* info = pars_info_create(); + pars_info_add_ull_literal(info, "id", id); + pars_info_add_int4_literal(info, "pos", pos); - dberr_t err = que_eval_sql( + dberr_t err = que_eval_sql( info, - "PROCEDURE ADD_COL () IS\n" + "PROCEDURE DELETE_COL () IS\n" "BEGIN\n" - "INSERT INTO SYS_COLUMNS VALUES" - "(:id,:pos,:name,:mtype,:prtype,:len,0);\n" + "DELETE FROM SYS_COLUMNS WHERE\n" + "TABLE_ID = :id AND POS >= :pos;\n" + "DELETE FROM SYS_VIRTUAL WHERE TABLE_ID = :id;\n" "END;\n", FALSE, trx); - if (err != DB_SUCCESS) { - my_error(ER_INTERNAL_ERROR, MYF(0), - "InnoDB: Insert into SYS_COLUMNS failed"); - return(true); - } - - i++; - } - - if (innodb_update_n_cols(user_table, dict_table_encode_n_col( - unsigned(user_table->n_cols) - - DATA_N_SYS_COLS, - user_table->n_v_cols) - | (user_table->flags & DICT_TF_COMPACT) << 31, - trx)) { - return true; - } - - unsigned i = unsigned(user_table->n_cols) - DATA_N_SYS_COLS; - byte trx_id[DATA_TRX_ID_LEN], roll_ptr[DATA_ROLL_PTR_LEN]; - dfield_set_data(dtuple_get_nth_field(row, i++), field_ref_zero, - DATA_ROW_ID_LEN); - dfield_set_data(dtuple_get_nth_field(row, i++), trx_id, sizeof trx_id); - dfield_set_data(dtuple_get_nth_field(row, i),roll_ptr,sizeof roll_ptr); - DBUG_ASSERT(i + 1 == user_table->n_cols); - - trx_write_trx_id(trx_id, trx->id); - /* The DB_ROLL_PTR will be assigned later, when allocating undo log. - Silence a Valgrind warning in dtuple_validate() when - row_ins_clust_index_entry_low() searches for the insert position. */ - memset(roll_ptr, 0, sizeof roll_ptr); - - dtuple_t* entry = row_build_index_entry(row, NULL, index, ctx->heap); - entry->info_bits = REC_INFO_METADATA; - - mtr_t mtr; - mtr.start(); - index->set_modified(mtr); - btr_pcur_t pcur; - btr_pcur_open_at_index_side(true, index, BTR_MODIFY_TREE, &pcur, true, - 0, &mtr); - ut_ad(btr_pcur_is_before_first_on_page(&pcur)); - btr_pcur_move_to_next_on_page(&pcur); - - buf_block_t* block = btr_pcur_get_block(&pcur); - ut_ad(page_is_leaf(block->frame)); - ut_ad(!page_has_prev(block->frame)); - ut_ad(!buf_block_get_page_zip(block)); - const rec_t* rec = btr_pcur_get_rec(&pcur); - que_thr_t* thr = pars_complete_graph_for_exec( - NULL, trx, ctx->heap, NULL); - - dberr_t err; - if (rec_is_metadata(rec, index)) { - ut_ad(page_rec_is_user_rec(rec)); - if (!page_has_next(block->frame) - && page_rec_is_last(rec, block->frame)) { - goto empty_table; - } - /* Extend the record with the instantly added columns. */ - const unsigned n = user_table->n_cols - ctx->old_n_cols; - /* Reserve room for DB_TRX_ID,DB_ROLL_PTR and any - non-updated off-page columns in case they are moved off - page as a result of the update. */ - upd_t* update = upd_create(index->n_fields, ctx->heap); - update->n_fields = n; - update->info_bits = REC_INFO_METADATA; - /* Add the default values for instantly added columns */ - for (unsigned i = 0; i < n; i++) { - upd_field_t* uf = upd_get_nth_field(update, i); - unsigned f = index->n_fields - n + i; - uf->field_no = f; - uf->new_val = entry->fields[f]; - } - ulint* offsets = NULL; - mem_heap_t* offsets_heap = NULL; - big_rec_t* big_rec; - err = btr_cur_pessimistic_update( - BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, - btr_pcur_get_btr_cur(&pcur), - &offsets, &offsets_heap, ctx->heap, - &big_rec, update, UPD_NODE_NO_ORD_CHANGE, - thr, trx->id, &mtr); - if (big_rec) { - if (err == DB_SUCCESS) { - err = btr_store_big_rec_extern_fields( - &pcur, offsets, big_rec, &mtr, - BTR_STORE_UPDATE); - } - - dtuple_big_rec_free(big_rec); - } - if (offsets_heap) { - mem_heap_free(offsets_heap); - } - btr_pcur_close(&pcur); - goto func_exit; - } else if (page_rec_is_supremum(rec)) { -empty_table: - /* The table is empty. */ - ut_ad(page_is_root(block->frame)); - btr_page_empty(block, NULL, index, 0, &mtr); - index->remove_instant(); - err = DB_SUCCESS; - goto func_exit; - } - - /* Convert the table to the instant ADD COLUMN format. */ - ut_ad(user_table->is_instant()); - mtr.commit(); - mtr.start(); - index->set_modified(mtr); - if (page_t* root = btr_root_get(index, &mtr)) { - if (fil_page_get_type(root) != FIL_PAGE_INDEX) { - DBUG_ASSERT(!"wrong page type"); - goto err_exit; - } - - DBUG_ASSERT(!page_is_comp(root) || !page_get_instant(root)); - mlog_write_ulint(root + FIL_PAGE_TYPE, - FIL_PAGE_TYPE_INSTANT, MLOG_2BYTES, - &mtr); - page_set_instant(root, index->n_core_fields, &mtr); - mtr.commit(); - mtr.start(); - index->set_modified(mtr); - err = row_ins_clust_index_entry_low( - BTR_NO_LOCKING_FLAG, BTR_MODIFY_TREE, index, - index->n_uniq, entry, 0, thr, false); - } else { -err_exit: - err = DB_CORRUPTION; - } - -func_exit: - mtr.commit(); - if (err != DB_SUCCESS) { - my_error_innodb(err, table->s->table_name.str, - user_table->flags); + my_error(ER_INTERNAL_ERROR, MYF(0), + "InnoDB: DELETE from SYS_COLUMNS/SYS_VIRTUAL failed"); return true; } @@ -4659,9 +5205,9 @@ innobase_drop_one_virtual_sys_virtual( static bool innobase_drop_virtual_try( - Alter_inplace_info* ha_alter_info, - const dict_table_t* user_table, - trx_t* trx) + const Alter_inplace_info* ha_alter_info, + const dict_table_t* user_table, + trx_t* trx) { ha_innobase_inplace_ctx* ctx; dberr_t err = DB_SUCCESS; @@ -4694,14 +5240,451 @@ innobase_drop_virtual_try( } } + return false; +} + +/** Serialise metadata of dropped or reordered columns. +@param[in,out] heap memory heap for allocation +@param[out] field data field with the metadata */ +inline +void dict_table_t::serialise_columns(mem_heap_t* heap, dfield_t* field) const +{ + DBUG_ASSERT(instant); + const dict_index_t& index = *UT_LIST_GET_FIRST(indexes); + unsigned n_fixed = index.first_user_field(); + unsigned num_non_pk_fields = index.n_fields - n_fixed; + + ulint len = 4 + num_non_pk_fields * 2; + + byte* data = static_cast<byte*>(mem_heap_alloc(heap, len)); + + dfield_set_data(field, data, len); + + mach_write_to_4(data, num_non_pk_fields); + + data += 4; + + for (ulint i = n_fixed; i < index.n_fields; i++) { + mach_write_to_2(data, instant->field_map[i - n_fixed]); + data += 2; + } +} + +/** Construct the metadata record for instant ALTER TABLE. +@param[in] row dummy or default values for existing columns +@param[in,out] heap memory heap for allocations +@return metadata record */ +inline +dtuple_t* +dict_index_t::instant_metadata(const dtuple_t& row, mem_heap_t* heap) const +{ + ut_ad(is_primary()); + dtuple_t* entry; + + if (!table->instant) { + entry = row_build_index_entry(&row, NULL, this, heap); + entry->info_bits = REC_INFO_METADATA_ADD; + return entry; + } + + entry = dtuple_create(heap, n_fields + 1); + entry->n_fields_cmp = n_uniq; + entry->info_bits = REC_INFO_METADATA_ALTER; + + const dict_field_t* field = fields; + + for (uint i = 0; i <= n_fields; i++, field++) { + dfield_t* dfield = dtuple_get_nth_field(entry, i); + + if (i == first_user_field()) { + table->serialise_columns(heap, dfield); + dfield->type.metadata_blob_init(); + field--; + continue; + } + + ut_ad(!field->col->is_virtual()); + + if (field->col->is_dropped()) { + dict_col_copy_type(field->col, &dfield->type); + if (field->col->is_nullable()) { + dfield_set_null(dfield); + } else { + dfield_set_data(dfield, field_ref_zero, + field->fixed_len); + } + continue; + } + + const dfield_t* s = dtuple_get_nth_field(&row, field->col->ind); + ut_ad(dict_col_type_assert_equal(field->col, &s->type)); + *dfield = *s; + + if (dfield_is_null(dfield)) { + continue; + } + + if (dfield_is_ext(dfield)) { + ut_ad(i > first_user_field()); + ut_ad(!field->prefix_len); + ut_ad(dfield->len >= FIELD_REF_SIZE); + dfield_set_len(dfield, dfield->len - FIELD_REF_SIZE); + } + + if (!field->prefix_len) { + continue; + } + + ut_ad(field->col->ord_part); + ut_ad(i < n_uniq); + + ulint len = dtype_get_at_most_n_mbchars( + field->col->prtype, + field->col->mbminlen, field->col->mbmaxlen, + field->prefix_len, dfield->len, + static_cast<char*>(dfield_get_data(dfield))); + dfield_set_len(dfield, len); + } + + return entry; +} + +/** Insert or update SYS_COLUMNS and the hidden metadata record +for instant ALTER TABLE. +@param[in] ha_alter_info ALTER TABLE context +@param[in,out] ctx ALTER TABLE context for the current partition +@param[in] altered_table MySQL table that is being altered +@param[in] table MySQL table as it is before the ALTER operation +@param[in,out] trx dictionary transaction +@retval true failure +@retval false success */ +static bool innobase_instant_try( + const Alter_inplace_info* ha_alter_info, + ha_innobase_inplace_ctx* ctx, + const TABLE* altered_table, + const TABLE* table, + trx_t* trx) +{ + DBUG_ASSERT(!ctx->need_rebuild()); + + if (!ctx->is_instant()) return false; + + dict_table_t* user_table = ctx->old_table; + + dict_index_t* index = dict_table_get_first_index(user_table); + mtr_t mtr; + mtr.start(); + /* Prevent purge from calling dict_index_t::clear_instant_alter(), + to protect index->n_core_fields, index->table->instant and others + from changing during ctx->instant_column(). */ + instant_metadata_lock(*index, mtr); + const unsigned n_old_fields = index->n_fields; + const dict_col_t* old_cols = user_table->cols; + DBUG_ASSERT(user_table->n_cols == ctx->old_n_cols); + + ctx->instant_column(); + + DBUG_ASSERT(index->n_fields >= n_old_fields); + /* Release the page latch. Between this and the next + btr_pcur_open_at_index_side(), data fields such as + index->n_core_fields and index->table->instant could change, + but we would handle that in empty_table: below. */ + mtr.commit(); + /* The table may have been emptied and may have lost its + 'instantness' during this ALTER TABLE. */ + + /* Construct a table row of default values for the stored columns. */ + dtuple_t* row = dtuple_create(ctx->heap, user_table->n_cols); + dict_table_copy_types(row, user_table); + Field** af = altered_table->field; + Field** const end = altered_table->field + altered_table->s->fields; + ut_d(List_iterator_fast<Create_field> cf_it( + ha_alter_info->alter_info->create_list)); + if (ctx->first_alter_pos + && innobase_instant_drop_cols(user_table->id, + ctx->first_alter_pos - 1, trx)) { + return true; + } + for (uint i = 0; af < end; af++) { + if (!(*af)->stored_in_db()) { + ut_d(cf_it++); + continue; + } + + const dict_col_t* old = dict_table_t::find(old_cols, + ctx->col_map, + ctx->old_n_cols, i); + DBUG_ASSERT(!old || i >= ctx->old_n_cols - DATA_N_SYS_COLS + || old->ind == i + || (ctx->first_alter_pos + && old->ind >= ctx->first_alter_pos - 1)); + + dfield_t* d = dtuple_get_nth_field(row, i); + const dict_col_t* col = dict_table_get_nth_col(user_table, i); + DBUG_ASSERT(!col->is_virtual()); + DBUG_ASSERT(!col->is_dropped()); + DBUG_ASSERT(col->mtype != DATA_SYS); + DBUG_ASSERT(!strcmp((*af)->field_name.str, + dict_table_get_col_name(user_table, i))); + DBUG_ASSERT(old || col->is_added()); + + if (col->is_added()) { + dfield_set_data(d, col->def_val.data, + col->def_val.len); + } else if ((*af)->real_maybe_null()) { + /* Store NULL for nullable 'core' columns. */ + dfield_set_null(d); + } else { + switch ((*af)->type()) { + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_GEOMETRY: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_LONG_BLOB: + /* Store the empty string for 'core' + variable-length NOT NULL columns. */ + dfield_set_data(d, field_ref_zero, 0); + break; + default: + /* For fixed-length NOT NULL 'core' columns, + get a dummy default value from SQL. Note that + we will preserve the old values of these + columns when updating the metadata + record, to avoid unnecessary updates. */ + ulint len = (*af)->pack_length(); + DBUG_ASSERT(d->type.mtype != DATA_INT + || len <= 8); + row_mysql_store_col_in_innobase_format( + d, d->type.mtype == DATA_INT + ? static_cast<byte*>( + mem_heap_alloc(ctx->heap, len)) + : NULL, true, (*af)->ptr, len, + dict_table_is_comp(user_table)); + } + } + + ut_d(const Create_field* new_field = cf_it++); + /* new_field->field would point to an existing column. + If it is NULL, the column was added by this ALTER TABLE. */ + ut_ad(!new_field->field == !old); + + bool update = old && (!ctx->first_alter_pos + || i < ctx->first_alter_pos - 1); + DBUG_ASSERT(!old || col->same_format(*old)); + if (update + && old->prtype == d->type.prtype) { + /* The record is already present in SYS_COLUMNS. */ + } else if (innodb_insert_sys_columns(user_table->id, i, + (*af)->field_name.str, + d->type.mtype, + d->type.prtype, + d->type.len, 0, trx, + update)) { + return true; + } + + i++; + } + + if (innodb_update_cols(user_table, dict_table_encode_n_col( + unsigned(user_table->n_cols) + - DATA_N_SYS_COLS, + user_table->n_v_cols) + | (user_table->flags & DICT_TF_COMPACT) << 31, + trx)) { + return true; + } - ulint n_col = unsigned(user_table->n_cols) - DATA_N_SYS_COLS; - ulint n_v_col = unsigned(user_table->n_v_cols) - - ctx->num_to_drop_vcol; - ulint new_n = dict_table_encode_n_col(n_col, n_v_col) - | ((user_table->flags & DICT_TF_COMPACT) << 31); + if (ctx->first_alter_pos) { +add_all_virtual: + for (uint i = 0; i < user_table->n_v_cols; i++) { + if (innobase_add_one_virtual( + user_table, + dict_table_get_v_col_name(user_table, i), + &user_table->v_cols[i], trx)) { + return true; + } + } + } else if (ha_alter_info->handler_flags & ALTER_DROP_VIRTUAL_COLUMN) { + if (innobase_instant_drop_cols(user_table->id, 65536, trx)) { + return true; + } + goto add_all_virtual; + } else if ((ha_alter_info->handler_flags & ALTER_ADD_VIRTUAL_COLUMN) + && innobase_add_virtual_try(ha_alter_info, user_table, + trx)) { + return true; + } - return innodb_update_n_cols(user_table, new_n, trx); + unsigned i = unsigned(user_table->n_cols) - DATA_N_SYS_COLS; + DBUG_ASSERT(i >= altered_table->s->stored_fields); + DBUG_ASSERT(i <= altered_table->s->stored_fields + 1); + if (i > altered_table->s->fields) { + const dict_col_t& fts_doc_id = user_table->cols[i - 1]; + DBUG_ASSERT(!strcmp(fts_doc_id.name(*user_table), + FTS_DOC_ID_COL_NAME)); + DBUG_ASSERT(!fts_doc_id.is_nullable()); + DBUG_ASSERT(fts_doc_id.len == 8); + dfield_set_data(dtuple_get_nth_field(row, i - 1), + field_ref_zero, fts_doc_id.len); + } + byte trx_id[DATA_TRX_ID_LEN], roll_ptr[DATA_ROLL_PTR_LEN]; + dfield_set_data(dtuple_get_nth_field(row, i++), field_ref_zero, + DATA_ROW_ID_LEN); + dfield_set_data(dtuple_get_nth_field(row, i++), trx_id, sizeof trx_id); + dfield_set_data(dtuple_get_nth_field(row, i),roll_ptr,sizeof roll_ptr); + DBUG_ASSERT(i + 1 == user_table->n_cols); + + trx_write_trx_id(trx_id, trx->id); + /* The DB_ROLL_PTR will be assigned later, when allocating undo log. + Silence a Valgrind warning in dtuple_validate() when + row_ins_clust_index_entry_low() searches for the insert position. */ + memset(roll_ptr, 0, sizeof roll_ptr); + + dtuple_t* entry = index->instant_metadata(*row, ctx->heap); + mtr.start(); + index->set_modified(mtr); + btr_pcur_t pcur; + btr_pcur_open_at_index_side(true, index, BTR_MODIFY_TREE, &pcur, true, + 0, &mtr); + ut_ad(btr_pcur_is_before_first_on_page(&pcur)); + btr_pcur_move_to_next_on_page(&pcur); + + buf_block_t* block = btr_pcur_get_block(&pcur); + ut_ad(page_is_leaf(block->frame)); + ut_ad(!page_has_prev(block->frame)); + ut_ad(!buf_block_get_page_zip(block)); + const rec_t* rec = btr_pcur_get_rec(&pcur); + que_thr_t* thr = pars_complete_graph_for_exec( + NULL, trx, ctx->heap, NULL); + + dberr_t err = DB_SUCCESS; + if (rec_is_metadata(rec, *index)) { + ut_ad(page_rec_is_user_rec(rec)); + if (!page_has_next(block->frame) + && page_rec_is_last(rec, block->frame)) { + goto empty_table; + } + + /* Ensure that the root page is in the correct format. */ + buf_block_t* root = btr_root_block_get(index, RW_X_LATCH, + &mtr); + DBUG_ASSERT(root); + DBUG_ASSERT(!root->page.encrypted); + if (fil_page_get_type(root->frame) != FIL_PAGE_TYPE_INSTANT) { + DBUG_ASSERT(!"wrong page type"); + err = DB_CORRUPTION; + goto func_exit; + } + + btr_set_instant(root, *index, &mtr); + + /* Extend the record with any added columns. */ + uint n = uint(index->n_fields) - n_old_fields; + /* Reserve room for DB_TRX_ID,DB_ROLL_PTR and any + non-updated off-page columns in case they are moved off + page as a result of the update. */ + const unsigned f = user_table->instant != NULL; + upd_t* update = upd_create(index->n_fields + f, ctx->heap); + update->n_fields = n + f; + update->info_bits = f + ? REC_INFO_METADATA_ALTER + : REC_INFO_METADATA_ADD; + if (f) { + upd_field_t* uf = upd_get_nth_field(update, 0); + uf->field_no = index->first_user_field(); + uf->new_val = entry->fields[uf->field_no]; + DBUG_ASSERT(!dfield_is_ext(&uf->new_val)); + DBUG_ASSERT(!dfield_is_null(&uf->new_val)); + } + + /* Add the default values for instantly added columns */ + unsigned j = f; + + for (unsigned k = n_old_fields; k < index->n_fields; k++) { + upd_field_t* uf = upd_get_nth_field(update, j++); + uf->field_no = k + f; + uf->new_val = entry->fields[k + f]; + + ut_ad(j <= n + f); + } + + ut_ad(j == n + f); + + ulint* offsets = NULL; + mem_heap_t* offsets_heap = NULL; + big_rec_t* big_rec; + err = btr_cur_pessimistic_update( + BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, + btr_pcur_get_btr_cur(&pcur), + &offsets, &offsets_heap, ctx->heap, + &big_rec, update, UPD_NODE_NO_ORD_CHANGE, + thr, trx->id, &mtr); + + offsets = rec_get_offsets( + btr_pcur_get_rec(&pcur), index, offsets, + true, ULINT_UNDEFINED, &offsets_heap); + if (big_rec) { + if (err == DB_SUCCESS) { + err = btr_store_big_rec_extern_fields( + &pcur, offsets, big_rec, &mtr, + BTR_STORE_UPDATE); + } + + dtuple_big_rec_free(big_rec); + } + if (offsets_heap) { + mem_heap_free(offsets_heap); + } + btr_pcur_close(&pcur); + goto func_exit; + } else if (page_rec_is_supremum(rec)) { +empty_table: + /* The table is empty. */ + ut_ad(page_is_root(block->frame)); + /* MDEV-17383: free metadata BLOBs! */ + btr_page_empty(block, NULL, index, 0, &mtr); + index->clear_instant_alter(); + goto func_exit; + } else if (!user_table->is_instant()) { + ut_ad(!user_table->not_redundant()); + goto func_exit; + } + + /* Convert the table to the instant ALTER TABLE format. */ + mtr.commit(); + mtr.start(); + index->set_modified(mtr); + if (buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, &mtr)) { + if (root->page.encrypted + || fil_page_get_type(root->frame) != FIL_PAGE_INDEX) { + DBUG_ASSERT(!"wrong page type"); + goto err_exit; + } + + btr_set_instant(root, *index, &mtr); + mtr.commit(); + mtr.start(); + index->set_modified(mtr); + err = row_ins_clust_index_entry_low( + BTR_NO_LOCKING_FLAG, BTR_MODIFY_TREE, index, + index->n_uniq, entry, 0, thr, false); + } else { +err_exit: + err = DB_CORRUPTION; + } + +func_exit: + mtr.commit(); + + if (err != DB_SUCCESS) { + my_error_innodb(err, table->s->table_name.str, + user_table->flags); + return true; + } + + return false; } /** Adjust the create index column number from "New table" to @@ -5298,20 +6281,15 @@ new_clustered_failed: == !!new_clustered); } - if (ctx->need_rebuild() && user_table->supports_instant()) { - if (!instant_alter_column_possible(ha_alter_info, old_table)) { - goto not_instant_add_column; - } - - for (uint i = uint(ctx->old_table->n_cols) - DATA_N_SYS_COLS; - i--; ) { - if (ctx->col_map[i] != i) { - goto not_instant_add_column; - } - } - - DBUG_ASSERT(ctx->new_table->n_cols > ctx->old_table->n_cols); + DBUG_ASSERT(!ctx->need_rebuild() + || !ctx->new_table->persistent_autoinc); + if (ctx->need_rebuild() && instant_alter_column_possible( + *user_table, ha_alter_info, old_table) +#if 1 // MDEV-17459: adjust fts_fetch_doc_from_rec() and friends; remove this + && !innobase_fulltext_exist(altered_table) +#endif + ) { for (uint a = 0; a < ctx->num_to_add_index; a++) { ctx->add_index[a]->table = ctx->new_table; ctx->add_index[a] = dict_index_add_to_cache( @@ -5319,6 +6297,7 @@ new_clustered_failed: &error, add_v); ut_a(error == DB_SUCCESS); } + DBUG_ASSERT(ha_alter_info->key_count /* hidden GEN_CLUST_INDEX in InnoDB */ + dict_index_is_auto_gen_clust( @@ -5330,6 +6309,7 @@ new_clustered_failed: altered_table->key_info) != FTS_EXIST_DOC_ID_INDEX) == ctx->num_to_add_index); + ctx->num_to_add_index = 0; ctx->add_index = NULL; @@ -5360,26 +6340,11 @@ new_clustered_failed: DBUG_ASSERT(!strcmp((*af)->field_name.str, dict_table_get_col_name(ctx->new_table, i))); - DBUG_ASSERT(!col->is_instant()); + DBUG_ASSERT(!col->is_added()); if (new_field->field) { - ut_d(const dict_col_t* old_col - = dict_table_get_nth_col(user_table, i)); - ut_d(const dict_index_t* index - = user_table->indexes.start); - DBUG_SLOW_ASSERT(col->mtype == old_col->mtype); - ut_ad(col->prtype == old_col->prtype - || col->prtype - == (old_col->prtype & ~DATA_VERSIONED)); - DBUG_SLOW_ASSERT(col->mbminlen - == old_col->mbminlen); - DBUG_SLOW_ASSERT(col->mbmaxlen - == old_col->mbmaxlen); - DBUG_SLOW_ASSERT(col->len >= old_col->len); - DBUG_SLOW_ASSERT(old_col->is_instant() - == (dict_col_get_clust_pos( - old_col, index) - >= index->n_core_fields)); + /* This is a pre-existing column, + possibly at a different position. */ } else if ((*af)->is_real_null()) { /* DEFAULT NULL */ col->def_val.len = UNIV_SQL_NULL; @@ -5447,11 +6412,15 @@ new_clustered_failed: ctx->new_table, i), FTS_DOC_ID_COL_NAME))); + if (altered_table->found_next_number_field) { + ctx->new_table->persistent_autoinc + = ctx->old_table->persistent_autoinc; + } + ctx->prepare_instant(); } if (ctx->need_rebuild()) { -not_instant_add_column: DBUG_ASSERT(ctx->need_rebuild()); DBUG_ASSERT(!ctx->is_instant()); DBUG_ASSERT(num_fts_index <= 1); @@ -5580,7 +6549,6 @@ new_table_failed: ut_ad(new_clust_index->n_core_null_bytes == UT_BITS_IN_BYTES(new_clust_index->n_nullable)); - DBUG_ASSERT(!ctx->new_table->persistent_autoinc); if (const Field* ai = altered_table->found_next_number_field) { const unsigned col_no = innodb_col_no(ai); @@ -7713,10 +8681,11 @@ err_exit: index = dict_table_get_next_index(index)) { for (ulint i = 0; i < dict_index_get_n_fields(index); i++) { - if (my_strcasecmp( - system_charset_info, - dict_index_get_nth_field(index, i)->name, - from)) { + const dict_field_t& f = index->fields[i]; + DBUG_ASSERT(!f.name == f.col->is_dropped()); + + if (!f.name || my_strcasecmp(system_charset_info, + f.name, from)) { continue; } @@ -9047,23 +10016,36 @@ commit_try_norebuild( } #endif /* MYSQL_RENAME_INDEX */ - if ((ha_alter_info->handler_flags - & ALTER_DROP_VIRTUAL_COLUMN) - && innobase_drop_virtual_try(ha_alter_info, ctx->old_table, trx)) { - DBUG_RETURN(true); - } + if (!ctx->is_instant() && ha_alter_info->handler_flags + & (ALTER_DROP_VIRTUAL_COLUMN | ALTER_ADD_VIRTUAL_COLUMN)) { + if ((ha_alter_info->handler_flags & ALTER_DROP_VIRTUAL_COLUMN) + && innobase_drop_virtual_try(ha_alter_info, ctx->old_table, + trx)) { + DBUG_RETURN(true); + } - if ((ha_alter_info->handler_flags - & ALTER_ADD_VIRTUAL_COLUMN) - && innobase_add_virtual_try(ha_alter_info, ctx->old_table, trx)) { - DBUG_RETURN(true); - } + if ((ha_alter_info->handler_flags & ALTER_ADD_VIRTUAL_COLUMN) + && innobase_add_virtual_try(ha_alter_info, ctx->old_table, + trx)) { + DBUG_RETURN(true); + } - if (innobase_add_instant_try(ctx, altered_table, old_table, trx)) { - DBUG_RETURN(true); + ulint n_col = unsigned(ctx->old_table->n_cols) + - DATA_N_SYS_COLS; + ulint n_v_col = unsigned(ctx->old_table->n_v_cols) + + ctx->num_to_add_vcol - ctx->num_to_drop_vcol; + + if (innodb_update_cols( + ctx->old_table, + dict_table_encode_n_col(n_col, n_v_col) + | unsigned(ctx->old_table->flags & DICT_TF_COMPACT) + << 31, trx)) { + DBUG_RETURN(true); + } } - DBUG_RETURN(false); + DBUG_RETURN(innobase_instant_try(ha_alter_info, ctx, altered_table, + old_table, trx)); } /** Commit the changes to the data dictionary cache @@ -9224,6 +10206,50 @@ commit_cache_norebuild( if (!ctx->is_instant()) { innobase_rename_or_enlarge_columns_cache( ha_alter_info, table, ctx->new_table); + } else { + ut_ad(ctx->col_map); + + if (fts_t* fts = ctx->new_table->fts) { + ut_ad(fts->doc_col != ULINT_UNDEFINED); + ut_ad(ctx->new_table->n_cols > DATA_N_SYS_COLS); + const ulint c = ctx->col_map[fts->doc_col]; + ut_ad(c < ulint(ctx->new_table->n_cols) + - DATA_N_SYS_COLS); + ut_d(const dict_col_t& col = ctx->new_table->cols[c]); + ut_ad(!col.is_nullable()); + ut_ad(!col.is_virtual()); + ut_ad(!col.is_added()); + ut_ad(col.prtype & DATA_UNSIGNED); + ut_ad(col.mtype == DATA_INT); + ut_ad(col.len == 8); + ut_ad(col.ord_part); + fts->doc_col = c; + } + + if (ha_alter_info->handler_flags & ALTER_DROP_STORED_COLUMN) { + const dict_index_t* index = ctx->new_table->indexes.start; + + for (const dict_field_t* f = index->fields, + * const end = f + index->n_fields; + f != end; f++) { + dict_col_t& c = *f->col; + if (c.is_dropped()) { + c.set_dropped(!c.is_nullable(), + DATA_LARGE_MTYPE(c.mtype) + || (!f->fixed_len + && c.len > 255), + f->fixed_len); + } + } + + DBUG_ASSERT(!ctx->instant_table->persistent_autoinc + || ctx->new_table->persistent_autoinc + == ctx->instant_table->persistent_autoinc); + + if (!ctx->instant_table->persistent_autoinc) { + ctx->new_table->persistent_autoinc = 0; + } + } } if (ha_alter_info->handler_flags & ALTER_COLUMN_UNVERSIONED) { @@ -9929,6 +10955,9 @@ foreign_fail: } } + /* MDEV-17468: Avoid this at least when ctx->is_instant(). + Currently dict_load_column_low() is the only place where + num_base for virtual columns is assigned to nonzero. */ if (ctx0->num_to_drop_vcol || ctx0->num_to_add_vcol) { DBUG_ASSERT(ctx0->old_table->get_ref_count() == 1); @@ -9946,6 +10975,12 @@ foreign_fail: tb_name[strlen(m_prebuilt->table->name.m_name)] = 0; dict_table_close(m_prebuilt->table, true, false); + if (ctx0->is_instant()) { + for (unsigned i = ctx0->old_n_v_cols; i--; ) { + UT_DELETE(ctx0->old_v_cols[i].v_indexes); + } + const_cast<unsigned&>(ctx0->old_n_v_cols) = 0; + } dict_table_remove_from_cache(m_prebuilt->table); m_prebuilt->table = dict_table_open_on_name( tb_name, TRUE, TRUE, DICT_ERR_IGNORE_NONE); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 261fbb05c63..ff7081ffc2a 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -911,10 +911,7 @@ ibuf_set_free_bits_func( ut_ad(0); break; case FIL_TYPE_TABLESPACE: - /* Avoid logging while fixing up truncate of table. */ - if (!srv_is_tablespace_truncated(block->page.id.space())) { - break; - } + break; /* fall through */ case FIL_TYPE_TEMPORARY: case FIL_TYPE_IMPORT: diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index b99e7e4c522..39175fc1f1d 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -172,24 +172,19 @@ record is in spatial index */ | BTR_LATCH_FOR_DELETE \ | BTR_MODIFY_EXTERNAL))) -/**************************************************************//** -Report that an index page is corrupted. */ -void -btr_corruption_report( -/*==================*/ - const buf_block_t* block, /*!< in: corrupted block */ - const dict_index_t* index) /*!< in: index tree */ - ATTRIBUTE_COLD __attribute__((nonnull)); +/** Report that an index page is corrupted. +@param[in] buffer block +@param[in] index tree */ +ATTRIBUTE_COLD ATTRIBUTE_NORETURN __attribute__((nonnull)) +void btr_corruption_report(const buf_block_t* block,const dict_index_t* index); /** Assert that a B-tree page is not corrupted. @param block buffer block containing a B-tree page @param index the B-tree index */ -#define btr_assert_not_corrupted(block, index) \ - if ((ibool) !!page_is_comp(buf_block_get_frame(block)) \ - != dict_table_is_comp((index)->table)) { \ - btr_corruption_report(block, index); \ - ut_error; \ - } +#define btr_assert_not_corrupted(block, index) \ + if (!!page_is_comp(buf_block_get_frame(block)) \ + != index->table->not_redundant()) \ + btr_corruption_report(block, index) /**************************************************************//** Gets the root node of a tree and sx-latches it for segment access. @@ -358,19 +353,16 @@ btr_node_ptr_get_child_page_no( @param[in] type type of the index @param[in,out] space tablespace where created @param[in] index_id index id -@param[in] index index, or NULL when applying TRUNCATE -log record during recovery -@param[in] btr_redo_create_info used for applying TRUNCATE log -@param[in] mtr mini-transaction handle -record during recovery -@return page number of the created root, FIL_NULL if did not succeed */ +@param[in] index index +@param[in,out] mtr mini-transaction +@return page number of the created root +@retval FIL_NULL if did not succeed */ ulint btr_create( ulint type, fil_space_t* space, index_id_t index_id, dict_index_t* index, - const btr_create_t* btr_redo_create_info, mtr_t* mtr); /** Free a persistent index tree if it exists. @@ -421,6 +413,12 @@ void btr_write_autoinc(dict_index_t* index, ib_uint64_t autoinc, bool reset = false) MY_ATTRIBUTE((nonnull)); +/** Write instant ALTER TABLE metadata to a root page. +@param[in,out] root clustered index root page +@param[in] index clustered index with instant ALTER TABLE +@param[in,out] mtr mini-transaction */ +void btr_set_instant(buf_block_t* root, const dict_index_t& index, mtr_t* mtr); + /*************************************************************//** Makes tree one level higher by splitting the root, and inserts the tuple. It is assumed that mtr contains an x-latch on the tree. diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h index f8685d34764..fa59275dbff 100644 --- a/storage/innobase/include/btr0types.h +++ b/storage/innobase/include/btr0types.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -55,35 +56,4 @@ in the index record. */ #define BTR_EXTERN_LOCAL_STORED_MAX_SIZE \ (BTR_EXTERN_FIELD_REF_SIZE * 2) -/** The information is used for creating a new index tree when -applying TRUNCATE log record during recovery */ -struct btr_create_t { - - explicit btr_create_t(const byte* const ptr) - : - format_flags(), - n_fields(), - field_len(), - fields(ptr), - trx_id_pos(ULINT_UNDEFINED) - { - /* Do nothing */ - } - - /** Page format */ - ulint format_flags; - - /** Numbr of index fields */ - ulint n_fields; - - /** The length of the encoded meta-data */ - ulint field_len; - - /** Field meta-data, encoded. */ - const byte* const fields; - - /** Position of trx-id column. */ - ulint trx_id_pos; -}; - #endif diff --git a/storage/innobase/include/buf0buddy.h b/storage/innobase/include/buf0buddy.h index 7ee837d6d2e..ed275ab1870 100644 --- a/storage/innobase/include/buf0buddy.h +++ b/storage/innobase/include/buf0buddy.h @@ -26,11 +26,6 @@ Created December 2006 by Marko Makela #ifndef buf0buddy_h #define buf0buddy_h -#ifdef UNIV_MATERIALIZE -# undef UNIV_INLINE -# define UNIV_INLINE -#endif - #include "buf0types.h" /**********************************************************************//** diff --git a/storage/innobase/include/buf0buddy.ic b/storage/innobase/include/buf0buddy.ic index d166ab8441c..7eb739a99db 100644 --- a/storage/innobase/include/buf0buddy.ic +++ b/storage/innobase/include/buf0buddy.ic @@ -23,11 +23,6 @@ Binary buddy allocator for compressed pages Created December 2006 by Marko Makela *******************************************************/ -#ifdef UNIV_MATERIALIZE -# undef UNIV_INLINE -# define UNIV_INLINE -#endif - #include "buf0buf.h" #include "buf0buddy.h" @@ -132,8 +127,3 @@ buf_buddy_free( buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size)); } - -#ifdef UNIV_MATERIALIZE -# undef UNIV_INLINE -# define UNIV_INLINE UNIV_INLINE_ORIGINAL -#endif diff --git a/storage/innobase/include/buf0checksum.h b/storage/innobase/include/buf0checksum.h index 06eb37906d2..6b2e4c86990 100644 --- a/storage/innobase/include/buf0checksum.h +++ b/storage/innobase/include/buf0checksum.h @@ -29,18 +29,6 @@ Created Aug 11, 2011 Vasil Dimov #include "buf0types.h" -#ifdef INNODB_BUG_ENDIAN_CRC32 -/** Calculate the CRC32 checksum of a page. The value is stored to the page -when it is written to a file and also checked for a match when reading from -the file. Note that we must be careful to calculate the same value on all -architectures. -@param[in] page buffer page (srv_page_size bytes) -@param[in] bug_endian whether to use big endian byteorder -when converting byte strings to integers, for bug-compatibility with -big-endian architecture running MySQL 5.6, MariaDB 10.0 or MariaDB 10.1 -@return CRC-32C */ -uint32_t buf_calc_page_crc32(const byte* page, bool bug_endian = false); -#else /** Calculate the CRC32 checksum of a page. The value is stored to the page when it is written to a file and also checked for a match when reading from the file. Note that we must be careful to calculate the same value on all @@ -48,7 +36,6 @@ architectures. @param[in] page buffer page (srv_page_size bytes) @return CRC-32C */ uint32_t buf_calc_page_crc32(const byte* page); -#endif /** Calculate a checksum which is stored to the page when it is written to a file. Note that we must be careful to calculate the same value on diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index 15c7ac9866a..8505505270b 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -643,6 +643,33 @@ struct dtuple_t { inserted or updated. @param[in] index index possibly with instantly added columns */ void trim(const dict_index_t& index); + + /** + @param info_bits the info_bits of a data tuple + @return whether this is a hidden metadata record + for instant ADD COLUMN or ALTER TABLE */ + static bool is_alter_metadata(ulint info_bits) + { + return UNIV_UNLIKELY(info_bits == REC_INFO_METADATA_ALTER); + } + + /** + @param info_bits the info_bits of a data tuple + @return whether this is a hidden metadata record + for instant ADD COLUMN or ALTER TABLE */ + static bool is_metadata(ulint info_bits) + { + return UNIV_UNLIKELY((info_bits & ~REC_INFO_DELETED_FLAG) + == REC_INFO_METADATA_ADD); + } + + /** @return whether this is a hidden metadata record + for instant ALTER TABLE (not only ADD COLUMN) */ + bool is_alter_metadata() const { return is_alter_metadata(info_bits); } + + /** @return whether this is a hidden metadata record + for instant ADD COLUMN or ALTER TABLE */ + bool is_metadata() const { return is_metadata(info_bits); } }; /** A slot for a field in a big rec vector */ diff --git a/storage/innobase/include/data0type.h b/storage/innobase/include/data0type.h index b999106fee0..3b3ac9d1885 100644 --- a/storage/innobase/include/data0type.h +++ b/storage/innobase/include/data0type.h @@ -554,11 +554,55 @@ struct dtype_t{ { return (prtype & DATA_VERSIONED) == DATA_VERS_END; } + + /** Set the type of the BLOB in the hidden metadata record. */ + void metadata_blob_init() + { + prtype = DATA_NOT_NULL; + mtype = DATA_BLOB; + len = 0; + mbminlen = 0; + mbmaxlen = 0; + } }; /** The DB_TRX_ID,DB_ROLL_PTR values for "no history is available" */ extern const byte reset_trx_id[DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN]; +/** Info bit denoting the predefined minimum record: this bit is set +if and only if the record is the first user record on a non-leaf +B-tree page that is the leftmost page on its level +(PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */ +#define REC_INFO_MIN_REC_FLAG 0x10UL +/** The delete-mark flag in info bits */ +#define REC_INFO_DELETED_FLAG 0x20UL + +/** Record status values for ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED */ +enum rec_comp_status_t { + /** User record (PAGE_LEVEL=0, heap>=PAGE_HEAP_NO_USER_LOW) */ + REC_STATUS_ORDINARY = 0, + /** Node pointer record (PAGE_LEVEL>=0, heap>=PAGE_HEAP_NO_USER_LOW) */ + REC_STATUS_NODE_PTR = 1, + /** The page infimum pseudo-record (heap=PAGE_HEAP_NO_INFIMUM) */ + REC_STATUS_INFIMUM = 2, + /** The page supremum pseudo-record (heap=PAGE_HEAP_NO_SUPREMUM) */ + REC_STATUS_SUPREMUM = 3, + /** Clustered index record that has been inserted or updated + after instant ADD COLUMN (more than dict_index_t::n_core_fields) */ + REC_STATUS_INSTANT = 4 +}; + +/** The dtuple_t::info_bits of the hidden metadata of instant ADD COLUMN. +@see rec_is_metadata() +@see rec_is_alter_metadata() */ +static const byte REC_INFO_METADATA_ADD + = REC_INFO_MIN_REC_FLAG | REC_STATUS_INSTANT; + +/** The dtuple_t::info_bits of the hidden metadata of instant ALTER TABLE. +@see rec_is_metadata() */ +static const byte REC_INFO_METADATA_ALTER + = REC_INFO_METADATA_ADD | REC_INFO_DELETED_FLAG; + #include "data0type.ic" #endif diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index ec8e29d458c..2110018b6d4 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -135,8 +135,6 @@ enum dberr_t { DB_FTS_TOO_MANY_WORDS_IN_PHRASE, /*< Too many words in a phrase */ - DB_TABLESPACE_TRUNCATED, /*!< tablespace was truncated */ - DB_DECRYPTION_FAILED, /* Tablespace encrypted and decrypt operation failed because of missing key management plugin, diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h index d683afcdc7e..d9d4b3d69d5 100644 --- a/storage/innobase/include/dict0boot.h +++ b/storage/innobase/include/dict0boot.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -50,12 +51,8 @@ dict_hdr_get_new_id( (not assigned if NULL) */ index_id_t* index_id, /*!< out: index id (not assigned if NULL) */ - ulint* space_id, /*!< out: space id + ulint* space_id); /*!< out: space id (not assigned if NULL) */ - const dict_table_t* table, /*!< in: table */ - bool disable_redo); /*!< in: if true and table - object is NULL - then disable-redo */ /**********************************************************************//** Writes the current value of the row id counter to the dictionary header file page. */ @@ -124,13 +121,6 @@ dict_is_sys_table( /* The following is a secondary index on SYS_TABLES */ #define DICT_TABLE_IDS_ID 5 -#define DICT_HDR_FIRST_ID 10 /* the ids for tables etc. start - from this number, except for basic - system tables and their above defined - indexes; ibuf tables and indexes are - assigned as the id the number - DICT_IBUF_ID_MIN plus the space id */ - /* The offset of the dictionary header on the page */ #define DICT_HDR FSEG_PAGE_DATA diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h index 75ef4f09dbb..8c941d494c1 100644 --- a/storage/innobase/include/dict0crea.h +++ b/storage/innobase/include/dict0crea.h @@ -67,14 +67,6 @@ dict_create_table_step( /*===================*/ que_thr_t* thr); /*!< in: query thread */ -/** Assign a new table ID and put it into the table cache and the transaction. -@param[in,out] table Table that needs an ID -@param[in,out] trx Transaction */ -void -dict_table_assign_new_id( - dict_table_t* table, - trx_t* trx); - /***********************************************************//** Creates an index. This is a high-level function used in SQL execution graphs. diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index bf9fcd70f18..3530f6bd4d2 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -31,13 +31,15 @@ Created 1/8/1996 Heikki Tuuri #include "data0data.h" #include "dict0mem.h" #include "fsp0fsp.h" +#include <atomic> #include <deque> -#include "dict0pagecompress.h" extern bool innodb_table_stats_not_found; extern bool innodb_index_stats_not_found; -#include "sync0rw.h" +/** the first table or index ID for other than hard-coded system tables */ +#define DICT_HDR_FIRST_ID 10 + /********************************************************************//** Get the database name length in a table name. @return database name length */ @@ -360,21 +362,12 @@ dict_table_add_system_columns( dict_table_t* table, /*!< in/out: table */ mem_heap_t* heap) /*!< in: temporary heap */ MY_ATTRIBUTE((nonnull)); -/**********************************************************************//** -Removes a table object from the dictionary cache. */ -void -dict_table_remove_from_cache( -/*=========================*/ - dict_table_t* table) /*!< in, own: table */ - MY_ATTRIBUTE((nonnull)); -/**********************************************************************//** -Removes a table object from the dictionary cache. */ -void -dict_table_remove_from_cache_low( -/*=============================*/ - dict_table_t* table, /*!< in, own: table */ - ibool lru_evict) /*!< in: TRUE if table being evicted - to make room in the table LRU list */ +/** Evict a table definition from the InnoDB data dictionary cache. +@param[in,out] table cached table definition to be evicted +@param[in] lru whether this is part of least-recently-used evictiono +@param[in] keep whether to keep (not free) the object */ +void dict_table_remove_from_cache(dict_table_t* table, bool lru = false, + bool keep = false) MY_ATTRIBUTE((nonnull)); /**********************************************************************//** Renames a table object. @@ -684,65 +677,14 @@ do { \ dict_table_skip_corrupt_index(index); \ } while (0) -/********************************************************************//** -Check whether the index is the clustered index. -@return nonzero for clustered index, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_clust( -/*================*/ - const dict_index_t* index) /*!< in: index */ - MY_ATTRIBUTE((warn_unused_result)); - -/** Check if index is auto-generated clustered index. -@param[in] index index - -@return true if index is auto-generated clustered index. */ -UNIV_INLINE -bool -dict_index_is_auto_gen_clust( - const dict_index_t* index); - -/********************************************************************//** -Check whether the index is unique. -@return nonzero for unique index, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_unique( -/*=================*/ - const dict_index_t* index) /*!< in: index */ - MY_ATTRIBUTE((warn_unused_result)); -/********************************************************************//** -Check whether the index is a Spatial Index. -@return nonzero for Spatial Index, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_spatial( -/*==================*/ - const dict_index_t* index) /*!< in: index */ - MY_ATTRIBUTE((warn_unused_result)); - +#define dict_index_is_clust(index) (index)->is_clust() +#define dict_index_is_auto_gen_clust(index) (index)->is_gen_clust() +#define dict_index_is_unique(index) (index)->is_unique() +#define dict_index_is_spatial(index) (index)->is_spatial() +#define dict_index_is_ibuf(index) (index)->is_ibuf() +#define dict_index_is_sec_or_ibuf(index) !(index)->is_primary() #define dict_index_has_virtual(index) (index)->has_virtual() -/********************************************************************//** -Check whether the index is the insert buffer tree. -@return nonzero for insert buffer, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_ibuf( -/*===============*/ - const dict_index_t* index) /*!< in: index */ - MY_ATTRIBUTE((warn_unused_result)); -/********************************************************************//** -Check whether the index is a secondary index or the insert buffer tree. -@return nonzero for insert buffer, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_sec_or_ibuf( -/*======================*/ - const dict_index_t* index) /*!< in: index */ - MY_ATTRIBUTE((warn_unused_result)); - /** Get all the FTS indexes on a table. @param[in] table table @param[out] indexes all FTS indexes on this table @@ -899,15 +841,8 @@ dict_index_get_min_size( /*====================*/ const dict_index_t* index) /*!< in: index */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -/********************************************************************//** -Check whether the table uses the compact page format. -@return TRUE if table uses the compact page format */ -UNIV_INLINE -bool -dict_table_is_comp( -/*===============*/ - const dict_table_t* table) /*!< in: table */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); + +#define dict_table_is_comp(table) (table)->not_redundant() /** Determine if a table uses atomic BLOBs (no locally stored prefix). @param[in] table InnoDB table @@ -1260,16 +1195,6 @@ dict_table_get_nth_col_pos( ulint n, /*!< in: column number */ ulint* prefix_col_pos) /*!< out: col num if prefix */ MY_ATTRIBUTE((nonnull(1), warn_unused_result)); -/********************************************************************//** -Returns the position of a system column in an index. -@return position, ULINT_UNDEFINED if not contained */ -UNIV_INLINE -ulint -dict_index_get_sys_col_pos( -/*=======================*/ - const dict_index_t* index, /*!< in: index */ - ulint type) /*!< in: DATA_ROW_ID, ... */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); /*******************************************************************//** Adds a column to index. */ void @@ -1367,21 +1292,6 @@ dict_index_build_node_ptr( ulint level) /*!< in: level of rec in tree: 0 means leaf level */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -/**********************************************************************//** -Copies an initial segment of a physical record, long enough to specify an -index entry uniquely. -@return pointer to the prefix record */ -rec_t* -dict_index_copy_rec_order_prefix( -/*=============================*/ - const dict_index_t* index, /*!< in: index */ - const rec_t* rec, /*!< in: record for which to - copy prefix */ - ulint* n_fields,/*!< out: number of fields copied */ - byte** buf, /*!< in/out: memory buffer for the - copied prefix, or NULL */ - ulint* buf_size)/*!< in/out: buffer size */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); /** Convert a physical record into a search tuple. @param[in] rec index record (not necessarily in an index page) @param[in] index index @@ -1637,8 +1547,10 @@ struct dict_sys_t{ the log records */ hash_table_t* table_hash; /*!< hash table of the tables, based on name */ - hash_table_t* table_id_hash; /*!< hash table of the tables, based - on id */ + /** hash table of persistent table IDs */ + hash_table_t* table_id_hash; + /** hash table of temporary table IDs */ + hash_table_t* temp_id_hash; dict_table_t* sys_tables; /*!< SYS_TABLES table */ dict_table_t* sys_columns; /*!< SYS_COLUMNS table */ dict_table_t* sys_indexes; /*!< SYS_INDEXES table */ @@ -1652,6 +1564,52 @@ struct dict_sys_t{ UT_LIST_BASE_NODE_T(dict_table_t) table_non_LRU; /*!< List of tables that can't be evicted from the cache */ + + /** @return a new temporary table ID */ + table_id_t get_temporary_table_id() { + return temp_table_id.fetch_add(1, std::memory_order_relaxed); + } + + /** Look up a temporary table. + @param id temporary table ID + @return temporary table + @retval NULL if the table does not exist + (should only happen during the rollback of CREATE...SELECT) */ + dict_table_t* get_temporary_table(table_id_t id) + { + ut_ad(mutex_own(&mutex)); + dict_table_t* table; + ulint fold = ut_fold_ull(id); + HASH_SEARCH(id_hash, temp_id_hash, fold, dict_table_t*, table, + ut_ad(table->cached), table->id == id); + if (UNIV_LIKELY(table != NULL)) { + DBUG_ASSERT(table->is_temporary()); + DBUG_ASSERT(table->id >= DICT_HDR_FIRST_ID); + table->acquire(); + } + return table; + } + + /** Look up a persistent table. + @param id table ID + @return table + @retval NULL if not cached */ + dict_table_t* get_table(table_id_t id) + { + ut_ad(mutex_own(&mutex)); + dict_table_t* table; + ulint fold = ut_fold_ull(id); + HASH_SEARCH(id_hash, table_id_hash, fold, dict_table_t*, table, + ut_ad(table->cached), table->id == id); + DBUG_ASSERT(!table || !table->is_temporary()); + return table; + } + + dict_sys_t() : temp_table_id(DICT_HDR_FIRST_ID) {} + +private: + /** the sequence of temporary table IDs */ + std::atomic<table_id_t> temp_table_id; }; /** dummy index for ROW_FORMAT=REDUNDANT supremum and infimum records */ diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 78e16774a09..76eb6995799 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -25,6 +25,7 @@ Created 1/8/1996 Heikki Tuuri ***********************************************************************/ #include "fsp0sysspace.h" +#include "dict0pagecompress.h" /*********************************************************************//** Gets the minimum number of bytes per character. @@ -255,89 +256,6 @@ dict_table_get_next_index( #endif /* UNIV_DEBUG */ /********************************************************************//** -Check whether the index is the clustered index. -@return nonzero for clustered index, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_clust( -/*================*/ - const dict_index_t* index) /*!< in: index */ -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - return(index->type & DICT_CLUSTERED); -} - -/** Check if index is auto-generated clustered index. -@param[in] index index - -@return true if index is auto-generated clustered index. */ -UNIV_INLINE -bool -dict_index_is_auto_gen_clust( - const dict_index_t* index) -{ - return(index->type == DICT_CLUSTERED); -} - -/********************************************************************//** -Check whether the index is unique. -@return nonzero for unique index, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_unique( -/*=================*/ - const dict_index_t* index) /*!< in: index */ -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - return(index->type & DICT_UNIQUE); -} - -/********************************************************************//** -Check whether the index is a Spatial Index. -@return nonzero for Spatial Index, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_spatial( -/*==================*/ - const dict_index_t* index) /*!< in: index */ -{ - ut_ad(index); - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - return ulint(UNIV_EXPECT(index->type & DICT_SPATIAL, 0)); -} - -/********************************************************************//** -Check whether the index is the insert buffer tree. -@return nonzero for insert buffer, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_ibuf( -/*===============*/ - const dict_index_t* index) /*!< in: index */ -{ - ut_ad(index); - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - return(index->type & DICT_IBUF); -} - -/********************************************************************//** -Check whether the index is a secondary index or the insert buffer tree. -@return nonzero for insert buffer, zero for other indexes */ -UNIV_INLINE -ulint -dict_index_is_sec_or_ibuf( -/*======================*/ - const dict_index_t* index) /*!< in: index */ -{ - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - return((index->type & (DICT_CLUSTERED | DICT_IBUF)) != DICT_CLUSTERED); -} - -/********************************************************************//** Gets the number of user-defined non-virtual columns in a table in the dictionary cache. @return number of user-defined (e.g., not ROW_ID) non-virtual @@ -484,7 +402,8 @@ dict_table_get_nth_v_col( ut_ad(table); ut_ad(pos < table->n_v_def); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); - ut_ad(!table->v_cols[pos].m_col.is_instant()); + ut_ad(!table->v_cols[pos].m_col.is_added()); + ut_ad(!table->v_cols[pos].m_col.is_dropped()); return &table->v_cols[pos]; } @@ -525,19 +444,6 @@ dict_table_get_sys_col_no( return unsigned(table->n_cols) + (sys - DATA_N_SYS_COLS); } -/********************************************************************//** -Check whether the table uses the compact page format. -@return TRUE if table uses the compact page format */ -UNIV_INLINE -bool -dict_table_is_comp( -/*===============*/ - const dict_table_t* table) /*!< in: table */ -{ - ut_ad(table); - return (table->flags & DICT_TF_COMPACT) != 0; -} - /************************************************************************ Check if the table has an FTS index. */ UNIV_INLINE @@ -1013,31 +919,6 @@ dict_index_get_nth_field( } #endif /* UNIV_DEBUG */ -/********************************************************************//** -Returns the position of a system column in an index. -@return position, ULINT_UNDEFINED if not contained */ -UNIV_INLINE -ulint -dict_index_get_sys_col_pos( -/*=======================*/ - const dict_index_t* index, /*!< in: index */ - ulint type) /*!< in: DATA_ROW_ID, ... */ -{ - ut_ad(index); - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - ut_ad(!dict_index_is_ibuf(index)); - - if (dict_index_is_clust(index)) { - - return(dict_col_get_clust_pos( - dict_table_get_sys_col(index->table, type), - index)); - } - - return(dict_index_get_nth_col_pos( - index, dict_table_get_sys_col_no(index->table, type), NULL)); -} - /*********************************************************************//** Gets the field column. @return field->col, pointer to the table column */ diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 63cf5c8bbec..940680b6100 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -47,6 +47,7 @@ Created 1/8/1996 Heikki Tuuri #include "os0once.h" #include "fil0fil.h" #include "fil0crypt.h" +#include <sql_const.h> #include <set> #include <algorithm> #include <iterator> @@ -584,6 +585,10 @@ struct dict_col_t{ this column. Our current max limit is 3072 (REC_VERSION_56_MAX_INDEX_COL_LEN) bytes. */ +private: + /** Special value of ind for a dropped column */ + static const unsigned DROPPED = 1023; +public: /** Detach the column from an index. @param[in] index index to be detached from */ @@ -627,29 +632,72 @@ struct dict_col_t{ } /** @return whether this is an instantly-added column */ - bool is_instant() const + bool is_added() const { DBUG_ASSERT(def_val.len != UNIV_SQL_DEFAULT || !def_val.data); return def_val.len != UNIV_SQL_DEFAULT; } + /** Flag the column instantly dropped */ + void set_dropped() { ind = DROPPED; } + /** Flag the column instantly dropped. + @param[in] not_null whether the column was NOT NULL + @param[in] len2 whether the length exceeds 255 bytes + @param[in] fixed_len the fixed length in bytes, or 0 */ + void set_dropped(bool not_null, bool len2, unsigned fixed) + { + DBUG_ASSERT(!len2 || !fixed); + prtype = not_null + ? DATA_NOT_NULL | DATA_BINARY_TYPE + : DATA_BINARY_TYPE; + if (fixed) { + mtype = DATA_FIXBINARY; + len = fixed; + } else { + mtype = DATA_BINARY; + len = len2 ? 65535 : 255; + } + mbminlen = mbmaxlen = 0; + ind = DROPPED; + ord_part = 0; + max_prefix = 0; + } + /** @return whether the column was instantly dropped */ + bool is_dropped() const { return ind == DROPPED; } + /** @return whether the column was instantly dropped + @param[in] index the clustered index */ + inline bool is_dropped(const dict_index_t& index) const; + /** Get the default value of an instantly-added column. @param[out] len value length (in bytes), or UNIV_SQL_NULL @return default value @retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */ const byte* instant_value(ulint* len) const { - DBUG_ASSERT(is_instant()); + DBUG_ASSERT(is_added()); *len = def_val.len; return static_cast<const byte*>(def_val.data); } /** Remove the 'instant ADD' status of the column */ - void remove_instant() + void clear_instant() { - DBUG_ASSERT(is_instant()); def_val.len = UNIV_SQL_DEFAULT; def_val.data = NULL; } + + /** Determine if the columns have the same format + except for is_nullable() and is_versioned(). + @param[in] other column to compare to + @return whether the columns have the same format */ + bool same_format(const dict_col_t& other) const + { + return mtype == other.mtype + && len >= other.len + && mbminlen == other.mbminlen + && mbmaxlen == other.mbmaxlen + && !((prtype ^ other.prtype) + & ~(DATA_NOT_NULL | DATA_VERSIONED)); + } }; /** Index information put in a list of virtual column structure. Index @@ -850,7 +898,7 @@ to start with. */ /** Data structure for an index. Most fields will be initialized to 0, NULL or FALSE in dict_mem_index_create(). */ -struct dict_index_t{ +struct dict_index_t { index_id_t id; /*!< id of the index */ mem_heap_t* heap; /*!< memory heap */ id_name_t name; /*!< index name */ @@ -1039,7 +1087,7 @@ struct dict_index_t{ page cannot be read or decrypted */ inline bool is_readable() const; - /** @return whether instant ADD COLUMN is in effect */ + /** @return whether instant ALTER TABLE is in effect */ inline bool is_instant() const; /** @return whether the index is the primary key index @@ -1049,9 +1097,38 @@ struct dict_index_t{ return DICT_CLUSTERED == (type & (DICT_CLUSTERED | DICT_IBUF)); } + /** @return whether this is a generated clustered index */ + bool is_gen_clust() const { return type == DICT_CLUSTERED; } + + /** @return whether this is a clustered index */ + bool is_clust() const { return type & DICT_CLUSTERED; } + + /** @return whether this is a unique index */ + bool is_unique() const { return type & DICT_UNIQUE; } + + /** @return whether this is a spatial index */ + bool is_spatial() const { return UNIV_UNLIKELY(type & DICT_SPATIAL); } + + /** @return whether this is the change buffer */ + bool is_ibuf() const { return UNIV_UNLIKELY(type & DICT_IBUF); } + /** @return whether the index includes virtual columns */ bool has_virtual() const { return type & DICT_VIRTUAL; } + /** @return the position of DB_TRX_ID */ + unsigned db_trx_id() const { + DBUG_ASSERT(is_primary()); + DBUG_ASSERT(n_uniq); + DBUG_ASSERT(n_uniq <= MAX_REF_PARTS); + return n_uniq; + } + /** @return the position of DB_ROLL_PTR */ + unsigned db_roll_ptr() const { return db_trx_id() + 1; } + + /** @return the offset of the metadata BLOB field, + or the first user field after the PRIMARY KEY,DB_TRX_ID,DB_ROLL_PTR */ + unsigned first_user_field() const { return db_trx_id() + 2; } + /** @return whether the index is corrupted */ inline bool is_corrupted() const; @@ -1097,24 +1174,20 @@ struct dict_index_t{ return fields[n].col->instant_value(len); } - /** Adjust clustered index metadata for instant ADD COLUMN. - @param[in] clustered index definition after instant ADD COLUMN */ - void instant_add_field(const dict_index_t& instant); - - /** Remove the 'instant ADD' status of a clustered index. - Protected by index root page x-latch or table X-lock. */ - void remove_instant() - { - DBUG_ASSERT(is_primary()); - if (!is_instant()) { - return; - } - for (unsigned i = n_core_fields; i < n_fields; i++) { - fields[i].col->remove_instant(); - } - n_core_fields = n_fields; - n_core_null_bytes = UT_BITS_IN_BYTES(unsigned(n_nullable)); - } + /** Adjust index metadata for instant ADD/DROP/reorder COLUMN. + @param[in] clustered index definition after instant ALTER TABLE */ + inline void instant_add_field(const dict_index_t& instant); + /** Remove instant ADD COLUMN metadata. */ + inline void clear_instant_add(); + /** Remove instant ALTER TABLE metadata. */ + inline void clear_instant_alter(); + + /** Construct the metadata record for instant ALTER TABLE. + @param[in] row dummy or default values for existing columns + @param[in,out] heap memory heap for allocations + @return metadata record */ + inline dtuple_t* + instant_metadata(const dtuple_t& row, mem_heap_t* heap) const; /** Check if record in clustered index is historical row. @param[in] rec clustered row @@ -1129,6 +1202,9 @@ struct dict_index_t{ @return true on error */ bool vers_history_row(const rec_t* rec, bool &history_row); + + /** Reconstruct the clustered index fields. */ + inline void reconstruct_fields(); }; /** Detach a column from an index. @@ -1463,6 +1539,64 @@ struct dict_vcol_templ_t { dict_vcol_templ_t() : vtempl(0), mysql_table_query_id(~0ULL) {} }; +/** Metadata on clustered index fields starting from first_user_field() */ +class field_map_element_t +{ + /** Number of bits for representing a column number */ + static constexpr uint16_t IND_BITS = 10; + + /** Set if the column of the field has been instantly dropped */ + static constexpr uint16_t DROPPED = 1U << (IND_BITS + 5); + + /** Set if the column was dropped and originally declared NOT NULL */ + static constexpr uint16_t NOT_NULL = 1U << (IND_BITS + 4); + + /** Column index (if !(data & DROPPED)): table->cols[data & IND], + or field length (if (data & DROPPED)): + (data & IND) = 0 if variable-length with max_len < 256 bytes; + (data & IND) = 1 if variable-length with max_len > 255 bytes; + (data & IND) = 1 + L otherwise, with L=fixed length of the column */ + static constexpr uint16_t IND = (1U << IND_BITS) - 1; + + /** Field metadata */ + uint16_t data; + + void clear_not_null() { data &= ~NOT_NULL; } +public: + bool is_dropped() const { return data & DROPPED; } + void set_dropped() { data |= DROPPED; } + bool is_not_null() const { return data & NOT_NULL; } + void set_not_null() { ut_ad(is_dropped()); data |= NOT_NULL; } + uint16_t ind() const { return data & IND; } + void set_ind(uint16_t i) + { + DBUG_ASSERT(i <= IND); + DBUG_ASSERT(!ind()); + data |= i; + } + field_map_element_t& operator= (uint16_t value) + { + data = value; + return *this; + } + operator uint16_t() { return data; } +}; + +static_assert(sizeof(field_map_element_t) == 2, + "Size mismatch for a persistent data item!"); + +/** Instantly dropped or reordered columns */ +struct dict_instant_t +{ + /** Number of dropped columns */ + unsigned n_dropped; + /** Dropped columns */ + dict_col_t* dropped; + /** Map of clustered index non-PK fields[i - first_user_field()] + to table columns */ + field_map_element_t* field_map; +}; + /** These are used when MySQL FRM and InnoDB data dictionary are in inconsistent state. */ typedef enum { @@ -1505,6 +1639,9 @@ struct dict_table_t { return flags2 & DICT_TF2_TEMPORARY; } + /** @return whether the table is not in ROW_FORMAT=REDUNDANT */ + bool not_redundant() const { return flags & DICT_TF_COMPACT; } + /** @return whether this table is readable @retval true normally @retval false if this is a single-table tablespace @@ -1516,35 +1653,89 @@ struct dict_table_t { return(UNIV_LIKELY(!file_unreadable)); } - /** @return whether instant ADD COLUMN is in effect */ + /** @return whether instant ALTER TABLE is in effect */ bool is_instant() const { return(UT_LIST_GET_FIRST(indexes)->is_instant()); } - /** @return whether the table supports instant ADD COLUMN */ + /** @return whether the table supports instant ALTER TABLE */ bool supports_instant() const { return(!(flags & DICT_TF_MASK_ZIP_SSIZE)); } - /** Adjust metadata for instant ADD COLUMN. - @param[in] table table definition after instant ADD COLUMN */ - void instant_add_column(const dict_table_t& table); + /** @return the number of instantly dropped columns */ + unsigned n_dropped() const { return instant ? instant->n_dropped : 0; } + + /** Look up an old column. + @param[in] cols the old columns of the table + @param[in] col_map map from old table columns to altered ones + @param[in] n_cols number of old columns + @param[in] i the number of the new column + @return old column + @retval NULL if column i was added to the table */ + static const dict_col_t* find(const dict_col_t* cols, + const ulint* col_map, ulint n_cols, + ulint i) + { + for (ulint o = n_cols; o--; ) { + if (col_map[o] == i) { + return &cols[o]; + } + } + return NULL; + } - /** Roll back instant_add_column(). - @param[in] old_n_cols original n_cols - @param[in] old_cols original cols - @param[in] old_col_names original col_names */ - void rollback_instant( + /** Serialise metadata of dropped or reordered columns. + @param[in,out] heap memory heap for allocation + @param[out] field data field with the metadata */ + inline void serialise_columns(mem_heap_t* heap, dfield_t* field) const; + + /** Reconstruct dropped or reordered columns. + @param[in] metadata data from serialise_columns() + @param[in] len length of the metadata, in bytes + @return whether parsing the metadata failed */ + bool deserialise_columns(const byte* metadata, ulint len); + + /** Set is_instant() before instant_column(). + @param[in] old previous table definition + @param[in] col_map map from old.cols[] + and old.v_cols[] to this + @param[out] first_alter_pos 0, or + 1 + first changed column position */ + inline void prepare_instant(const dict_table_t& old, + const ulint* col_map, + unsigned& first_alter_pos); + + /** Adjust table metadata for instant ADD/DROP/reorder COLUMN. + @param[in] table table on which prepare_instant() was invoked + @param[in] col_map mapping from cols[] and v_cols[] to table */ + inline void instant_column(const dict_table_t& table, + const ulint* col_map); + + /** Roll back instant_column(). + @param[in] old_n_cols original n_cols + @param[in] old_cols original cols + @param[in] old_col_names original col_names + @param[in] old_instant original instant structure + @param[in] old_fields original fields + @param[in] old_n_fields original number of fields + @param[in] old_n_v_cols original n_v_cols + @param[in] old_v_cols original v_cols + @param[in] old_v_col_names original v_col_names + @param[in] col_map column map */ + inline void rollback_instant( unsigned old_n_cols, dict_col_t* old_cols, - const char* old_col_names); - - /** Trim the instantly added columns when an insert into SYS_COLUMNS - is rolled back during ALTER TABLE or recovery. - @param[in] n number of surviving non-system columns */ - void rollback_instant(unsigned n); + const char* old_col_names, + dict_instant_t* old_instant, + dict_field_t* old_fields, + unsigned old_n_fields, + unsigned old_n_v_cols, + dict_v_col_t* old_v_cols, + const char* old_v_col_names, + const ulint* col_map); /** Add the table definition to the data dictionary cache */ void add_to_cache(); @@ -1572,6 +1763,14 @@ struct dict_table_t { ut_ad(fk_checks > 0); } +private: + /** Initialize instant->field_map. + @tparam replace_dropped whether to point clustered index fields + to instant->dropped[] + @param[in] table table definition to copy from */ + template<bool replace_dropped = false> + inline void init_instant(const dict_table_t& table); +public: /** Id of the table. */ table_id_t id; @@ -1686,6 +1885,9 @@ struct dict_table_t { reason s_cols is a part of dict_table_t */ dict_s_col_list* s_cols; + /** Instantly dropped or reordered columns, or NULL if none */ + dict_instant_t* instant; + /** Column names packed in a character string "name1\0name2\0...nameN\0". Until the string contains n_cols, it will be allocated from a temporary heap. The final string will be allocated @@ -1967,12 +2169,15 @@ inline bool dict_index_t::is_readable() const { return table->is_readable(); } inline bool dict_index_t::is_instant() const { ut_ad(n_core_fields > 0); - ut_ad(n_core_fields <= n_fields); + ut_ad(n_core_fields <= n_fields || table->n_dropped()); ut_ad(n_core_fields == n_fields || (type & ~(DICT_UNIQUE | DICT_CORRUPT)) == DICT_CLUSTERED); ut_ad(n_core_fields == n_fields || table->supports_instant()); ut_ad(n_core_fields == n_fields || !table->is_temporary()); - return(n_core_fields != n_fields); + ut_ad(!table->instant || !table->is_temporary()); + + return n_core_fields != n_fields + || (is_primary() && table->instant); } inline bool dict_index_t::is_corrupted() const @@ -1982,6 +2187,72 @@ inline bool dict_index_t::is_corrupted() const || (table && table->corrupted)); } +inline void dict_index_t::clear_instant_add() +{ + DBUG_ASSERT(is_primary()); + DBUG_ASSERT(is_instant()); + DBUG_ASSERT(!table->instant); + for (unsigned i = n_core_fields; i < n_fields; i++) { + fields[i].col->clear_instant(); + } + n_core_fields = n_fields; + n_core_null_bytes = UT_BITS_IN_BYTES(unsigned(n_nullable)); +} + +inline void dict_index_t::clear_instant_alter() +{ + DBUG_ASSERT(is_primary()); + DBUG_ASSERT(n_fields == n_def); + + if (!table->instant) { + if (is_instant()) { + clear_instant_add(); + } + return; + } + +#ifndef DBUG_OFF + for (unsigned i = first_user_field(); i--; ) { + DBUG_ASSERT(!fields[i].col->is_dropped()); + DBUG_ASSERT(!fields[i].col->is_nullable()); + } +#endif + dict_field_t* const begin = &fields[first_user_field()]; + dict_field_t* end = &fields[n_fields]; + + for (dict_field_t* d = begin; d < end; ) { + /* Move fields for dropped columns to the end. */ + if (!d->col->is_dropped()) { + d++; + } else { + if (d->col->is_nullable()) { + n_nullable--; + } + + std::swap(*d, *--end); + } + } + + DBUG_ASSERT(&fields[n_fields - table->n_dropped()] == end); + n_core_fields = n_fields = n_def = end - fields; + n_core_null_bytes = UT_BITS_IN_BYTES(n_nullable); + std::sort(begin, end, [](const dict_field_t& a, const dict_field_t& b) + { return a.col->ind < b.col->ind; }); + table->instant = NULL; +} + +/** @return whether the column was instantly dropped +@param[in] index the clustered index */ +inline bool dict_col_t::is_dropped(const dict_index_t& index) const +{ + DBUG_ASSERT(index.is_primary()); + DBUG_ASSERT(!is_dropped() == !index.table->instant); + DBUG_ASSERT(!is_dropped() || (this >= index.table->instant->dropped + && this < index.table->instant->dropped + + index.table->instant->n_dropped)); + return is_dropped(); +} + /*******************************************************************//** Initialise the table lock list. */ void diff --git a/storage/innobase/include/dict0priv.h b/storage/innobase/include/dict0priv.h index b216a16c181..8eda44bd3f2 100644 --- a/storage/innobase/include/dict0priv.h +++ b/storage/innobase/include/dict0priv.h @@ -45,18 +45,6 @@ dict_table_check_if_in_cache_low( /*=============================*/ const char* table_name); /*!< in: table name */ -/**********************************************************************//** -Returns a table object based on table id. -@return table, NULL if does not exist */ -UNIV_INLINE -dict_table_t* -dict_table_open_on_id_low( -/*=====================*/ - table_id_t table_id, /*!< in: table id */ - dict_err_ignore_t ignore_err, /*!< in: errors to ignore - when loading the table */ - ibool open_only_if_in_cache); - #include "dict0priv.ic" #endif /* dict0priv.h */ diff --git a/storage/innobase/include/dict0priv.ic b/storage/innobase/include/dict0priv.ic index fb7af2772fc..6d7fbf07394 100644 --- a/storage/innobase/include/dict0priv.ic +++ b/storage/innobase/include/dict0priv.ic @@ -25,7 +25,6 @@ Created Wed 13 Oct 2010 16:10:14 EST Sunny Bains #include "dict0dict.h" #include "dict0load.h" -#include "dict0priv.h" /**********************************************************************//** Gets a table; loads it to the dictionary cache if necessary. A low-level @@ -64,40 +63,6 @@ dict_table_get_low( } /**********************************************************************//** -Returns a table object based on table id. -@return table, NULL if does not exist */ -UNIV_INLINE -dict_table_t* -dict_table_open_on_id_low( -/*======================*/ - table_id_t table_id, /*!< in: table id */ - dict_err_ignore_t ignore_err, /*!< in: errors to ignore - when loading the table */ - ibool open_only_if_in_cache) -{ - dict_table_t* table; - ulint fold; - - ut_ad(mutex_own(&dict_sys->mutex)); - - /* Look for the table name in the hash table */ - fold = ut_fold_ull(table_id); - - HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold, - dict_table_t*, table, ut_ad(table->cached), - table->id == table_id); - if (table == NULL && !open_only_if_in_cache) { - table = dict_load_table_on_id(table_id, ignore_err); - } - - ut_ad(!table || table->cached); - - /* TODO: should get the type information from MySQL */ - - return(table); -} - -/**********************************************************************//** Checks if a table is in the dictionary cache. @return table, NULL if not found */ UNIV_INLINE diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h index 77445fb8a0e..e520f189d63 100644 --- a/storage/innobase/include/fil0crypt.h +++ b/storage/innobase/include/fil0crypt.h @@ -26,11 +26,9 @@ Created 04/01/2015 Jan Lindström #ifndef fil0crypt_h #define fil0crypt_h -#ifndef UNIV_INNOCHECKSUM #include "os0event.h" #include "my_crypt.h" #include "fil0fil.h" -#endif /*! UNIV_INNOCHECKSUM */ /** * Magic pattern in start of crypt data on page 0 diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 91f50d70e5d..fa4d3c12aa9 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -27,18 +27,17 @@ Created 10/25/1995 Heikki Tuuri #ifndef fil0fil_h #define fil0fil_h +#include "page0size.h" + #ifndef UNIV_INNOCHECKSUM #include "log0recv.h" #include "dict0types.h" -#include "page0size.h" // Forward declaration extern my_bool srv_use_doublewrite_buf; extern struct buf_dblwr_t* buf_dblwr; class page_id_t; -struct trx_t; -class truncate_t; /** Structure containing encryption specification */ struct fil_space_crypt_t; @@ -385,19 +384,12 @@ typedef byte fil_faddr_t; /*!< 'type' definition in C: an address #define FIL_ADDR_BYTE 4U /* then comes 2-byte byte offset within page*/ #define FIL_ADDR_SIZE 6U /* address size is 6 bytes */ -#ifndef UNIV_INNOCHECKSUM - /** File space address */ struct fil_addr_t { ulint page; /*!< page number within a space */ ulint boffset; /*!< byte offset within the page */ }; -/** The null file address */ -extern const fil_addr_t fil_addr_null; - -#endif /* !UNIV_INNOCHECKSUM */ - /** The byte offsets on a file page for various variables @{ */ #define FIL_PAGE_SPACE_OR_CHKSUM 0 /*!< in < MySQL-4.0.14 space id the page belongs to (== 0) but in later @@ -1081,7 +1073,7 @@ fil_space_extend( @param[in] message message for aio handler if non-sync aio used, else ignored @param[in] ignore_missing_space true=ignore missing space during read -@return DB_SUCCESS, DB_TABLESPACE_DELETED or DB_TABLESPACE_TRUNCATED +@return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do i/o on a tablespace which does not exist */ dberr_t fil_io( diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 76c7762fac3..9b502f1f546 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -28,15 +28,15 @@ Created 12/18/1995 Heikki Tuuri #define fsp0fsp_h #include "fsp0types.h" +#include "fut0lst.h" +#include "ut0byte.h" #ifndef UNIV_INNOCHECKSUM - -#include "fut0lst.h" #include "mtr0mtr.h" #include "page0types.h" #include "rem0types.h" -#include "ut0byte.h" - +#else +# include "mach0data.h" #endif /* !UNIV_INNOCHECKSUM */ /** @return the PAGE_SSIZE flags for the current innodb_page_size */ diff --git a/storage/innobase/include/fsp0types.h b/storage/innobase/include/fsp0types.h index 642bd20e67e..d99ca14fe9a 100644 --- a/storage/innobase/include/fsp0types.h +++ b/storage/innobase/include/fsp0types.h @@ -27,10 +27,6 @@ Created May 26, 2009 Vasil Dimov #ifndef fsp0types_h #define fsp0types_h -#include "univ.i" - -#ifndef UNIV_INNOCHECKSUM - /** The fil_space_t::id of the redo log. All persistent tablespaces have a smaller fil_space_t::id. */ #define SRV_LOG_SPACE_FIRST_ID 0xFFFFFFF0U @@ -50,7 +46,6 @@ fseg_alloc_free_page) */ #define FSP_NO_DIR ((byte)113) /*!< no order */ /* @} */ -#endif /* !UNIV_INNOCHECKSUM */ /** File space extent size in pages page size | file space extent size ----------+----------------------- @@ -73,7 +68,6 @@ page size | file space extent size offset */ #define FSEG_PAGE_DATA FIL_PAGE_DATA -#ifndef UNIV_INNOCHECKSUM /** @name File segment header The file segment header points to the inode describing the file segment. */ /* @{ */ @@ -88,6 +82,7 @@ typedef byte fseg_header_t; header, in bytes */ /* @} */ +#ifndef UNIV_INNOCHECKSUM #ifdef UNIV_DEBUG struct mtr_t; diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index 4c4647dba95..9a10375759c 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2017, MariaDB Corporation. +Copyright (c) 2016, 2018, MariaDB Corporation. 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 @@ -610,17 +610,15 @@ fts_get_doc_id_from_row( want to extract.*/ /** Extract the doc id from the record that belongs to index. -@param[in] table table -@param[in] rec record contains FTS_DOC_ID +@param[in] rec record containing FTS_DOC_ID @param[in] index index of rec -@param[in] heap heap memory +@param[in] offsets rec_get_offsets(rec,index) @return doc id that was extracted from rec */ doc_id_t fts_get_doc_id_from_rec( - dict_table_t* table, - const rec_t* rec, - const dict_index_t* index, - mem_heap_t* heap); + const rec_t* rec, + const dict_index_t* index, + const ulint* offsets); /** Add new fts doc id to the update vector. @param[in] table the table that contains the FTS index. diff --git a/storage/innobase/include/fut0fut.h b/storage/innobase/include/fut0fut.h index 497b6ac5114..d8072708089 100644 --- a/storage/innobase/include/fut0fut.h +++ b/storage/innobase/include/fut0fut.h @@ -27,7 +27,6 @@ Created 12/13/1995 Heikki Tuuri #ifndef fut0fut_h #define fut0fut_h -#include "fil0fil.h" #include "mtr0mtr.h" /** Gets a pointer to a file address and latches the page. diff --git a/storage/innobase/include/fut0lst.h b/storage/innobase/include/fut0lst.h index 092889fc42c..7432df20034 100644 --- a/storage/innobase/include/fut0lst.h +++ b/storage/innobase/include/fut0lst.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -26,11 +27,11 @@ Created 11/28/1995 Heikki Tuuri #ifndef fut0lst_h #define fut0lst_h -#ifndef UNIV_INNOCHECKSUM - -#include "fil0fil.h" -#include "mtr0mtr.h" - +#ifdef UNIV_INNOCHECKSUM +# include "fil0fil.h" +#else +#include "fut0fut.h" +#include "mtr0log.h" /* The C 'types' of base node and list node: these should be used to write self-documenting code. Of course, the sizeof macro cannot be @@ -39,14 +40,55 @@ applied to these types! */ typedef byte flst_base_node_t; typedef byte flst_node_t; -/* The physical size of a list base node in bytes */ -#define FLST_BASE_NODE_SIZE (4 + 2 * FIL_ADDR_SIZE) #endif /* !UNIV_INNOCHECKSUM */ +/* The physical size of a list base node in bytes */ +#define FLST_BASE_NODE_SIZE (4 + 2 * FIL_ADDR_SIZE) /* The physical size of a list node in bytes */ #define FLST_NODE_SIZE (2 * FIL_ADDR_SIZE) #ifndef UNIV_INNOCHECKSUM +/* We define the field offsets of a node for the list */ +#define FLST_PREV 0 /* 6-byte address of the previous list element; + the page part of address is FIL_NULL, if no + previous element */ +#define FLST_NEXT FIL_ADDR_SIZE /* 6-byte address of the next + list element; the page part of address + is FIL_NULL, if no next element */ + +/* We define the field offsets of a base node for the list */ +#define FLST_LEN 0 /* 32-bit list length field */ +#define FLST_FIRST 4 /* 6-byte address of the first element + of the list; undefined if empty list */ +#define FLST_LAST (4 + FIL_ADDR_SIZE) /* 6-byte address of the + last element of the list; undefined + if empty list */ + +/** Initialize a zero-initialized list base node. +@param[in,out] block file page +@param[in] ofs byte offset of the list base node +@param[in,out] mtr mini-transaction */ +inline void flst_init(buf_block_t* block, uint16_t ofs, mtr_t* mtr) +{ + ut_ad(0 == mach_read_from_2(FLST_LEN + ofs + block->frame)); + ut_ad(0 == mach_read_from_2(FLST_FIRST + FIL_ADDR_BYTE + ofs + + block->frame)); + ut_ad(0 == mach_read_from_2(FLST_LAST + FIL_ADDR_BYTE + ofs + + block->frame)); + compile_time_assert(FIL_NULL == 0xffU * 0x1010101U); + mlog_memset(block, FLST_FIRST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr); + mlog_memset(block, FLST_LAST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr); +} + +/** Write a null file address. +@param[in,out] faddr file address to be zeroed otu +@param[in,out] mtr mini-transaction */ +inline void flst_zero_addr(fil_faddr_t* faddr, mtr_t* mtr) +{ + mlog_memset(faddr + FIL_ADDR_PAGE, 4, 0xff, mtr); + mlog_write_ulint(faddr + FIL_ADDR_BYTE, 0, MLOG_2BYTES, mtr); +} + /********************************************************************//** Initializes a list base node. */ UNIV_INLINE diff --git a/storage/innobase/include/fut0lst.ic b/storage/innobase/include/fut0lst.ic index 5c9a9ca94c1..3a978b8f75a 100644 --- a/storage/innobase/include/fut0lst.ic +++ b/storage/innobase/include/fut0lst.ic @@ -23,26 +23,8 @@ File-based list utilities Created 11/28/1995 Heikki Tuuri ***********************************************************************/ -#include "fut0fut.h" -#include "mtr0log.h" #include "buf0buf.h" -/* We define the field offsets of a node for the list */ -#define FLST_PREV 0 /* 6-byte address of the previous list element; - the page part of address is FIL_NULL, if no - previous element */ -#define FLST_NEXT FIL_ADDR_SIZE /* 6-byte address of the next - list element; the page part of address - is FIL_NULL, if no next element */ - -/* We define the field offsets of a base node for the list */ -#define FLST_LEN 0 /* 32-bit list length field */ -#define FLST_FIRST 4 /* 6-byte address of the first element - of the list; undefined if empty list */ -#define FLST_LAST (4 + FIL_ADDR_SIZE) /* 6-byte address of the - last element of the list; undefined - if empty list */ - /********************************************************************//** Writes a file address. */ UNIV_INLINE @@ -101,8 +83,8 @@ flst_init( | MTR_MEMO_PAGE_SX_FIX)); mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr); - flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr); - flst_write_addr(base + FLST_LAST, fil_addr_null, mtr); + flst_zero_addr(base + FLST_FIRST, mtr); + flst_zero_addr(base + FLST_LAST, mtr); } /** Get the length of a list. diff --git a/storage/innobase/include/log0crypt.h b/storage/innobase/include/log0crypt.h index d972ca01491..359896c2fc5 100644 --- a/storage/innobase/include/log0crypt.h +++ b/storage/innobase/include/log0crypt.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (C) 2014, 2017, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2014, 2018, MariaDB Corporation. 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 @@ -73,14 +73,23 @@ UNIV_INTERN bool log_crypt_read_checkpoint_buf(const byte* buf); +/** log_crypt() operation code */ +enum log_crypt_t { + /** encrypt a log block without rotating key */ + LOG_ENCRYPT, + /** decrypt a log block */ + LOG_DECRYPT, + /** attempt to rotate the key, and encrypt a log block */ + LOG_ENCRYPT_ROTATE_KEY +}; + /** Encrypt or decrypt log blocks. @param[in,out] buf log blocks to encrypt or decrypt @param[in] lsn log sequence number of the start of the buffer @param[in] size size of the buffer, in bytes -@param[in] decrypt whether to decrypt instead of encrypting */ -UNIV_INTERN -void -log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt = false); +@param[in] op whether to decrypt, encrypt, or rotate key and encrypt +@return whether the operation succeeded (encrypt always does) */ +bool log_crypt(byte* buf, lsn_t lsn, ulint size, log_crypt_t op = LOG_ENCRYPT); /** Encrypt or decrypt a temporary file block. @param[in] src block to encrypt or decrypt diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index d213a6c0884..3d28cacbfe0 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -160,19 +160,16 @@ bool log_set_capacity(ulonglong file_size) MY_ATTRIBUTE((warn_unused_result)); -/******************************************************//** -This function is called, e.g., when a transaction wants to commit. It checks -that the log has been written to the log file up to the last log entry written -by the transaction. If there is a flush running, it waits and checks if the -flush flushed enough. If not, starts a new flush. */ -void -log_write_up_to( -/*============*/ - lsn_t lsn, /*!< in: log sequence number up to which - the log should be written, LSN_MAX if not specified */ - bool flush_to_disk); - /*!< in: true if we want the written log - also to be flushed to disk */ +/** Ensure that the log has been written to the log file up to a given +log entry (such as that of a transaction commit). Start a new write, or +wait and check if an already running write is covering the request. +@param[in] lsn log sequence number that should be +included in the redo log file write +@param[in] flush_to_disk whether the written log should also +be flushed to the file system +@param[in] rotate_key whether to rotate the encryption key */ +void log_write_up_to(lsn_t lsn, bool flush_to_disk, bool rotate_key = false); + /** write to the log file up to the last log entry. @param[in] sync whether we want the written log also to be flushed to disk. */ @@ -414,13 +411,14 @@ extern my_bool innodb_log_checksums; #define LOG_BLOCK_HDR_SIZE 12 /* size of the log block header in bytes */ -/* Offsets of a log block trailer from the end of the block */ +#define LOG_BLOCK_KEY 4 /* encryption key version + before LOG_BLOCK_CHECKSUM; + in LOG_HEADER_FORMAT_ENC_10_4 only */ #define LOG_BLOCK_CHECKSUM 4 /* 4 byte checksum of the log block contents; in InnoDB versions < 3.23.52 this did not contain the checksum but the same value as - .._HDR_NO */ -#define LOG_BLOCK_TRL_SIZE 4 /* trailer size in bytes */ + LOG_BLOCK_HDR_NO */ /** Offsets inside the checkpoint pages (redo log format version 1) @{ */ /** Checkpoint number */ @@ -482,11 +480,9 @@ MariaDB 10.2.18 and later will use the 10.3 format, but LOG_HEADER_SUBFORMAT 1 instead of 0. MariaDB 10.3 will use subformat 0 (5.7-style TRUNCATE) or 2 (MDEV-13564 backup-friendly TRUNCATE). */ #define LOG_HEADER_FORMAT_10_3 103 -/** The redo log format identifier corresponding to the current format version. -Stored in LOG_HEADER_FORMAT. */ -#define LOG_HEADER_FORMAT_CURRENT LOG_HEADER_FORMAT_10_3 -/** Future MariaDB 10.4 log format */ #define LOG_HEADER_FORMAT_10_4 104 +/** The MariaDB 10.4.0 log format (only with innodb_encrypt_log=ON) */ +#define LOG_HEADER_FORMAT_ENC_10_4 (104U | 1U << 31) /** Encrypted MariaDB redo log */ #define LOG_HEADER_FORMAT_ENCRYPTED (1U<<31) @@ -556,7 +552,7 @@ struct log_t{ struct files { /** number of files */ ulint n_files; - /** format of the redo log: e.g., LOG_HEADER_FORMAT_CURRENT */ + /** format of the redo log: e.g., LOG_HEADER_FORMAT_10_4 */ uint32_t format; /** redo log subformat: 0 with separately logged TRUNCATE, 2 with fully redo-logged TRUNCATE (1 in MariaDB 10.2) */ @@ -713,11 +709,34 @@ public: /** @return whether the redo log is encrypted */ bool is_encrypted() const { return(log.is_encrypted()); } - bool is_initialised() { return m_initialised; } + bool is_initialised() const { return m_initialised; } /** Complete an asynchronous checkpoint write. */ void complete_checkpoint(); + /** @return the log block header + trailer size */ + unsigned framing_size() const + { + return log.format == LOG_HEADER_FORMAT_ENC_10_4 + ? LOG_BLOCK_HDR_SIZE + LOG_BLOCK_KEY + LOG_BLOCK_CHECKSUM + : LOG_BLOCK_HDR_SIZE + LOG_BLOCK_CHECKSUM; + } + /** @return the log block payload size */ + unsigned payload_size() const + { + return log.format == LOG_HEADER_FORMAT_ENC_10_4 + ? OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE - LOG_BLOCK_CHECKSUM - + LOG_BLOCK_KEY + : OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE - LOG_BLOCK_CHECKSUM; + } + /** @return the log block trailer offset */ + unsigned trailer_offset() const + { + return log.format == LOG_HEADER_FORMAT_ENC_10_4 + ? OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM - LOG_BLOCK_KEY + : OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM; + } + /** Initialise the redo log subsystem. */ void create(); diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic index 87d55f9e01d..60e6958d592 100644 --- a/storage/innobase/include/log0log.ic +++ b/storage/innobase/include/log0log.ic @@ -215,7 +215,7 @@ log_block_calc_checksum_format_0( sum = 1; sh = 0; - for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) { + for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM; i++) { ulint b = (ulint) block[i]; sum &= 0x7FFFFFFFUL; sum += b; @@ -237,7 +237,7 @@ ulint log_block_calc_checksum_crc32( const byte* block) { - return(ut_crc32(block, OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE)); + return ut_crc32(block, OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM); } /** Calculates the checksum for a log block using the "no-op" algorithm. @@ -338,7 +338,7 @@ log_reserve_and_write_fast( #endif /* UNIV_LOG_LSN_DEBUG */ + log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE; - if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { + if (data_len >= log_sys.trailer_offset()) { /* The string does not fit within the current log block or the log block would become full */ diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 89485b7f31d..5fe00d65f2c 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -143,10 +143,6 @@ corresponding to MLOG_INDEX_LOAD. */ extern void (*log_optimized_ddl_op)(ulint space_id); -/** Report backup-unfriendly TRUNCATE operation (with separate log file), -corresponding to MLOG_TRUNCATE. */ -extern void (*log_truncate)(); - /** Report an operation to create, delete, or rename a file during backup. @param[in] space_id tablespace identifier @param[in] flags tablespace flags (NULL if not create) diff --git a/storage/innobase/include/mach0data.h b/storage/innobase/include/mach0data.h index bcf71ea6b17..96e8d629021 100644 --- a/storage/innobase/include/mach0data.h +++ b/storage/innobase/include/mach0data.h @@ -29,11 +29,10 @@ Created 11/28/1995 Heikki Tuuri #define mach0data_h #include "univ.i" +#include "mtr0types.h" #ifndef UNIV_INNOCHECKSUM -#include "mtr0types.h" - /* The data and all fields are always stored in a database file in the same format: ascii, big-endian, ... . All data in the files MUST be accessed using the functions in this diff --git a/storage/innobase/include/mtr0log.h b/storage/innobase/include/mtr0log.h index d2de11b3470..4cb7ea4eb64 100644 --- a/storage/innobase/include/mtr0log.h +++ b/storage/innobase/include/mtr0log.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -71,6 +72,23 @@ mlog_log_string( byte* ptr, /*!< in: pointer written to */ ulint len, /*!< in: string length */ mtr_t* mtr); /*!< in: mini-transaction handle */ + +/** Initialize a string of bytes. +@param[in,out] b buffer page +@param[in] ofs byte offset from block->frame +@param[in] len length of the data to write +@param[in] val the data byte to write +@param[in,out] mtr mini-transaction */ +void +mlog_memset(buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr); + +/** Initialize a string of bytes. +@param[in,out] byte byte address +@param[in] len length of the data to write +@param[in] val the data byte to write +@param[in,out] mtr mini-transaction */ +void mlog_memset(byte* b, ulint len, byte val, mtr_t* mtr); + /********************************************************//** Writes initial part of a log record consisting of one-byte item type and four-byte space and page numbers. */ @@ -188,7 +206,7 @@ mlog_parse_initial_log_record( ulint* space, /*!< out: space id */ ulint* page_no);/*!< out: page number */ /********************************************************//** -Parses a log record written by mlog_write_ulint or mlog_write_ull. +Parses a log record written by mlog_write_ulint, mlog_write_ull, mlog_memset. @return parsed record end, NULL if not a complete record */ byte* mlog_parse_nbytes( diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h index eaf838aaa76..39ed707267d 100644 --- a/storage/innobase/include/mtr0types.h +++ b/storage/innobase/include/mtr0types.h @@ -216,7 +216,8 @@ enum mlog_id_t { /** initialize a file page */ MLOG_INIT_FILE_PAGE2 = 59, - /** Table is being truncated. (Marked only for file-per-table) */ + /** Table is being truncated. (Was used in 10.2 and 10.3; + not supported for crash-upgrade to 10.4 or later.) */ MLOG_TRUNCATE = 60, /** notify that an index tree is being loaded without writing @@ -227,8 +228,11 @@ enum mlog_id_t { of a ROW_FORMAT=COMPRESSED table */ MLOG_ZIP_WRITE_TRX_ID = 62, + /** initialize a page with a string of identical bytes */ + MLOG_MEMSET = 63, + /** biggest value (used in assertions) */ - MLOG_BIGGEST_TYPE = MLOG_ZIP_WRITE_TRX_ID, + MLOG_BIGGEST_TYPE = MLOG_MEMSET, /** log record for writing/updating crypt data of a tablespace */ diff --git a/storage/innobase/include/page0cur.ic b/storage/innobase/include/page0cur.ic index 86e560395f3..b5812560093 100644 --- a/storage/innobase/include/page0cur.ic +++ b/storage/innobase/include/page0cur.ic @@ -24,12 +24,7 @@ The page cursor Created 10/4/1994 Heikki Tuuri *************************************************************************/ -#include "page0page.h" -#include "buf0types.h" - #ifdef UNIV_DEBUG -# include "rem0cmp.h" - /*********************************************************//** Gets pointer to the page frame where the cursor is positioned. @return page */ @@ -280,6 +275,7 @@ page_cur_tuple_insert( *offsets = rec_get_offsets(rec, index, *offsets, page_is_leaf(cursor->block->frame), ULINT_UNDEFINED, heap); + ut_ad(size == rec_offs_size(*offsets)); if (buf_block_get_page_zip(cursor->block)) { rec = page_cur_insert_rec_zip( diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index 58115b767d2..bc6ab0cb848 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -27,28 +27,23 @@ Created 2/2/1994 Heikki Tuuri #define page0page_h #include "page0types.h" -#ifndef UNIV_INNOCHECKSUM +#include "fsp0fsp.h" #include "fil0fil.h" #include "buf0buf.h" -#include "data0data.h" -#include "dict0dict.h" #include "rem0rec.h" -#endif /* !UNIV_INNOCHECKSUM*/ -#include "fsp0fsp.h" #ifndef UNIV_INNOCHECKSUM +#include "dict0dict.h" +#include "data0data.h" #include "mtr0mtr.h" -#ifdef UNIV_MATERIALIZE -#undef UNIV_INLINE -#define UNIV_INLINE -#endif - /* PAGE HEADER =========== Index page header starts at the first offset left free by the FIL-module */ typedef byte page_header_t; +#else +# include "mach0data.h" #endif /* !UNIV_INNOCHECKSUM */ #define PAGE_HEADER FSEG_PAGE_DATA /* index page header starts at this @@ -1023,13 +1018,6 @@ page_get_direction(const page_t* page) inline uint16_t page_get_instant(const page_t* page); -/** Assign the PAGE_INSTANT field. -@param[in,out] page clustered index root page -@param[in] n original number of clustered index fields -@param[in,out] mtr mini-transaction */ -inline -void -page_set_instant(page_t* page, unsigned n, mtr_t* mtr); /**********************************************************//** Create an uncompressed B-tree index page. @@ -1057,10 +1045,6 @@ page_create_zip( ulint level, /*!< in: the B-tree level of the page */ trx_id_t max_trx_id, /*!< in: PAGE_MAX_TRX_ID */ - const redo_page_compress_t* page_comp_info, - /*!< in: used for applying - TRUNCATE log - record during recovery */ mtr_t* mtr); /*!< in/out: mini-transaction handle */ /**********************************************************//** @@ -1351,11 +1335,6 @@ const rec_t* page_find_rec_max_not_deleted( const page_t* page); -#ifdef UNIV_MATERIALIZE -#undef UNIV_INLINE -#define UNIV_INLINE UNIV_INLINE_ORIGINAL -#endif - #endif /* !UNIV_INNOCHECKSUM */ #include "page0page.ic" diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index 307803367c0..ad0ea913af9 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -29,18 +29,10 @@ Created 2/2/1994 Heikki Tuuri #ifndef UNIV_INNOCHECKSUM #include "mach0data.h" -#ifdef UNIV_DEBUG -# include "log0recv.h" -#endif /* !UNIV_DEBUG */ #include "rem0cmp.h" #include "mtr0log.h" #include "page0zip.h" -#ifdef UNIV_MATERIALIZE -#undef UNIV_INLINE -#define UNIV_INLINE -#endif - /*************************************************************//** Returns the max trx id field value. */ UNIV_INLINE @@ -1098,29 +1090,6 @@ page_get_instant(const page_t* page) #endif /* UNIV_DEBUG */ return(i >> 3); } - -/** Assign the PAGE_INSTANT field. -@param[in,out] page clustered index root page -@param[in] n original number of clustered index fields -@param[in,out] mtr mini-transaction */ -inline -void -page_set_instant(page_t* page, unsigned n, mtr_t* mtr) -{ - ut_ad(fil_page_get_type(page) == FIL_PAGE_TYPE_INSTANT); - ut_ad(n > 0); - ut_ad(n < REC_MAX_N_FIELDS); - uint16_t i = page_header_get_field(page, PAGE_INSTANT); - ut_ad(i <= PAGE_NO_DIRECTION); - i |= n << 3; - mlog_write_ulint(PAGE_HEADER + PAGE_INSTANT + page, i, - MLOG_2BYTES, mtr); -} #endif /* !UNIV_INNOCHECKSUM */ -#ifdef UNIV_MATERIALIZE -#undef UNIV_INLINE -#define UNIV_INLINE UNIV_INLINE_ORIGINAL -#endif - #endif diff --git a/storage/innobase/include/page0size.h b/storage/innobase/include/page0size.h index 981f8743960..08d072822bf 100644 --- a/storage/innobase/include/page0size.h +++ b/storage/innobase/include/page0size.h @@ -34,7 +34,7 @@ Created Nov 14, 2013 Vasil Dimov /** A BLOB field reference full of zero, for use in assertions and tests.Initially, BLOB field references are set to zero, in dtuple_convert_big_rec(). */ -extern const byte field_ref_zero[FIELD_REF_SIZE]; +extern const byte field_ref_zero[UNIV_PAGE_SIZE_MAX]; #define PAGE_SIZE_T_SIZE_BITS 17 diff --git a/storage/innobase/include/page0types.h b/storage/innobase/include/page0types.h index 47d66df2758..0913a50fee2 100644 --- a/storage/innobase/include/page0types.h +++ b/storage/innobase/include/page0types.h @@ -83,18 +83,6 @@ enum page_cur_mode_t { PAGE_CUR_RTREE_GET_FATHER = 14 }; - -/** The information used for compressing a page when applying -TRUNCATE log record during recovery */ -struct redo_page_compress_t { - ulint type; /*!< index type */ - index_id_t index_id; /*!< index id */ - ulint n_fields; /*!< number of index fields */ - ulint field_len; /*!< the length of index field */ - const byte* fields; /*!< index field information */ - ulint trx_id_pos; /*!< position of trx-id column. */ -}; - /** Compressed page descriptor */ struct page_zip_des_t { diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h index bb9bb049c22..1e11897482f 100644 --- a/storage/innobase/include/page0zip.h +++ b/storage/innobase/include/page0zip.h @@ -2,7 +2,7 @@ Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -28,27 +28,11 @@ Created June 2005 by Marko Makela #ifndef page0zip_h #define page0zip_h -#ifdef UNIV_MATERIALIZE -# undef UNIV_INLINE -# define UNIV_INLINE -#endif - -#ifdef UNIV_INNOCHECKSUM -#include "buf0buf.h" -#include "ut0crc32.h" -#include "buf0checksum.h" -#include "mach0data.h" -#include "zlib.h" -#endif /* UNIV_INNOCHECKSUM */ +#include "buf0types.h" #ifndef UNIV_INNOCHECKSUM #include "mtr0types.h" #include "page0types.h" -#endif /* !UNIV_INNOCHECKSUM */ - -#include "buf0types.h" - -#ifndef UNIV_INNOCHECKSUM #include "dict0types.h" #include "srv0srv.h" #include "trx0types.h" @@ -163,10 +147,6 @@ page_zip_compress( dict_index_t* index, /*!< in: index of the B-tree node */ ulint level, /*!< in: commpression level */ - const redo_page_compress_t* page_comp_info, - /*!< in: used for applying - TRUNCATE log - record during recovery */ mtr_t* mtr); /*!< in/out: mini-transaction, or NULL */ @@ -518,12 +498,7 @@ uint32_t page_zip_calc_checksum( const void* data, ulint size, - srv_checksum_algorithm_t algo -#ifdef INNODB_BUG_ENDIAN_CRC32 - /** for crc32, use the big-endian bug-compatible crc32 variant */ - , bool use_legacy_big_endian = false -#endif -); + srv_checksum_algorithm_t algo); /**********************************************************************//** Verify a compressed page's checksum. @@ -568,11 +543,6 @@ void page_zip_reset_stat_per_index(); /*===========================*/ -#ifdef UNIV_MATERIALIZE -# undef UNIV_INLINE -# define UNIV_INLINE UNIV_INLINE_ORIGINAL -#endif - #include "page0zip.ic" #endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/page0zip.ic b/storage/innobase/include/page0zip.ic index b3ebc5dcf51..10a311089dc 100644 --- a/storage/innobase/include/page0zip.ic +++ b/storage/innobase/include/page0zip.ic @@ -25,11 +25,6 @@ Compressed page interface Created June 2005 by Marko Makela *******************************************************/ -#ifdef UNIV_MATERIALIZE -# undef UNIV_INLINE -# define UNIV_INLINE -#endif - #include "page0zip.h" #include "mtr0log.h" #include "page0page.h" @@ -414,7 +409,7 @@ page_zip_parse_compress_no_data( was successful. Crash in this case. */ if (page - && !page_zip_compress(page_zip, page, index, level, NULL, NULL)) { + && !page_zip_compress(page_zip, page, index, level, NULL)) { ut_error; } @@ -437,8 +432,3 @@ page_zip_reset_stat_per_index() mutex_exit(&page_zip_stat_per_index_mutex); } - -#ifdef UNIV_MATERIALIZE -# undef UNIV_INLINE -# define UNIV_INLINE UNIV_INLINE_ORIGINAL -#endif diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 3a541289a61..fdcae3818bc 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -38,15 +38,6 @@ Created 5/30/1994 Heikki Tuuri #include <ostream> #include <sstream> -/* Info bit denoting the predefined minimum record: this bit is set -if and only if the record is the first user record on a non-leaf -B-tree page that is the leftmost page on its level -(PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */ -#define REC_INFO_MIN_REC_FLAG 0x10UL -/* The deleted flag in info bits */ -#define REC_INFO_DELETED_FLAG 0x20UL /* when bit is set to 1, it means the - record has been delete marked */ - /* Number of extra bytes in an old-style record, in addition to the data and the offsets */ #define REC_N_OLD_EXTRA_BYTES 6 @@ -54,26 +45,6 @@ in addition to the data and the offsets */ in addition to the data and the offsets */ #define REC_N_NEW_EXTRA_BYTES 5 -/** Record status values for ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED */ -enum rec_comp_status_t { - /** User record (PAGE_LEVEL=0, heap>=PAGE_HEAP_NO_USER_LOW) */ - REC_STATUS_ORDINARY = 0, - /** Node pointer record (PAGE_LEVEL>=0, heap>=PAGE_HEAP_NO_USER_LOW) */ - REC_STATUS_NODE_PTR = 1, - /** The page infimum pseudo-record (heap=PAGE_HEAP_NO_INFIMUM) */ - REC_STATUS_INFIMUM = 2, - /** The page supremum pseudo-record (heap=PAGE_HEAP_NO_SUPREMUM) */ - REC_STATUS_SUPREMUM = 3, - /** Clustered index record that has been inserted or updated - after instant ADD COLUMN (more than dict_index_t::n_core_fields) */ - REC_STATUS_COLUMNS_ADDED = 4 -}; - -/** The dtuple_t::info_bits of the metadata pseudo-record. -@see rec_is_metadata() */ -static const byte REC_INFO_METADATA - = REC_INFO_MIN_REC_FLAG | REC_STATUS_COLUMNS_ADDED; - #define REC_NEW_STATUS 3 /* This is single byte bit-field */ #define REC_NEW_STATUS_MASK 0x7UL #define REC_NEW_STATUS_SHIFT 0 @@ -295,7 +266,7 @@ rec_comp_status_t rec_get_status(const rec_t* rec) { byte bits = rec[-REC_NEW_STATUS] & REC_NEW_STATUS_MASK; - ut_ad(bits <= REC_STATUS_COLUMNS_ADDED); + ut_ad(bits <= REC_STATUS_INSTANT); return static_cast<rec_comp_status_t>(bits); } @@ -306,12 +277,12 @@ inline void rec_set_status(rec_t* rec, byte bits) { - ut_ad(bits <= REC_STATUS_COLUMNS_ADDED); + ut_ad(bits <= REC_STATUS_INSTANT); rec[-REC_NEW_STATUS] = (rec[-REC_NEW_STATUS] & ~REC_NEW_STATUS_MASK) | bits; } -/** Get the length of added field count in a REC_STATUS_COLUMNS_ADDED record. +/** Get the length of added field count in a REC_STATUS_INSTANT record. @param[in] n_add_field number of added fields, minus one @return storage size of the field count, in bytes */ inline unsigned rec_get_n_add_field_len(ulint n_add_field) @@ -320,8 +291,8 @@ inline unsigned rec_get_n_add_field_len(ulint n_add_field) return n_add_field < 0x80 ? 1 : 2; } -/** Set the added field count in a REC_STATUS_COLUMNS_ADDED record. -@param[in,out] header variable header of a REC_STATUS_COLUMNS_ADDED record +/** Set the added field count in a REC_STATUS_INSTANT record. +@param[in,out] header variable header of a REC_STATUS_INSTANT record @param[in] n_add number of added fields, minus 1 @return record header before the number of added fields */ inline void rec_set_n_add_field(byte*& header, ulint n_add) @@ -780,20 +751,89 @@ rec_offs_comp(const ulint* offsets) } /** Determine if the record is the metadata pseudo-record -in the clustered index. +in the clustered index for instant ADD COLUMN or ALTER TABLE. +@param[in] rec leaf page record +@param[in] comp 0 if ROW_FORMAT=REDUNDANT, else nonzero +@return whether the record is the metadata pseudo-record */ +inline bool rec_is_metadata(const rec_t* rec, ulint comp) +{ + bool is = !!(rec_get_info_bits(rec, comp) & REC_INFO_MIN_REC_FLAG); + ut_ad(!is || !comp || rec_get_status(rec) == REC_STATUS_INSTANT); + return is; +} + +/** Determine if the record is the metadata pseudo-record +in the clustered index for instant ADD COLUMN or ALTER TABLE. @param[in] rec leaf page record @param[in] index index of the record @return whether the record is the metadata pseudo-record */ -inline bool rec_is_metadata(const rec_t* rec, const dict_index_t* index) +inline bool rec_is_metadata(const rec_t* rec, const dict_index_t& index) { - bool is = rec_get_info_bits(rec, dict_table_is_comp(index->table)) - & REC_INFO_MIN_REC_FLAG; - ut_ad(!is || index->is_instant()); - ut_ad(!is || !dict_table_is_comp(index->table) - || rec_get_status(rec) == REC_STATUS_COLUMNS_ADDED); + bool is = rec_is_metadata(rec, dict_table_is_comp(index.table)); + ut_ad(!is || index.is_instant()); return is; } +/** Determine if the record is the metadata pseudo-record +in the clustered index for instant ADD COLUMN (not other ALTER TABLE). +@param[in] rec leaf page record +@param[in] comp 0 if ROW_FORMAT=REDUNDANT, else nonzero +@return whether the record is the metadata pseudo-record */ +inline bool rec_is_add_metadata(const rec_t* rec, ulint comp) +{ + bool is = rec_get_info_bits(rec, comp) == REC_INFO_MIN_REC_FLAG; + ut_ad(!is || !comp || rec_get_status(rec) == REC_STATUS_INSTANT); + return is; +} + +/** Determine if the record is the metadata pseudo-record +in the clustered index for instant ADD COLUMN (not other ALTER TABLE). +@param[in] rec leaf page record +@param[in] index index of the record +@return whether the record is the metadata pseudo-record */ +inline bool rec_is_add_metadata(const rec_t* rec, const dict_index_t& index) +{ + bool is = rec_is_add_metadata(rec, dict_table_is_comp(index.table)); + ut_ad(!is || index.is_instant()); + return is; +} + +/** Determine if the record is the metadata pseudo-record +in the clustered index for instant ALTER TABLE (not plain ADD COLUMN). +@param[in] rec leaf page record +@param[in] comp 0 if ROW_FORMAT=REDUNDANT, else nonzero +@return whether the record is the ALTER TABLE metadata pseudo-record */ +inline bool rec_is_alter_metadata(const rec_t* rec, ulint comp) +{ + bool is = !(~rec_get_info_bits(rec, comp) + & (REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG)); + ut_ad(!is || rec_is_metadata(rec, comp)); + return is; +} + +/** Determine if the record is the metadata pseudo-record +in the clustered index for instant ALTER TABLE (not plain ADD COLUMN). +@param[in] rec leaf page record +@param[in] index index of the record +@return whether the record is the ALTER TABLE metadata pseudo-record */ +inline bool rec_is_alter_metadata(const rec_t* rec, const dict_index_t& index) +{ + bool is = rec_is_alter_metadata(rec, dict_table_is_comp(index.table)); + ut_ad(!is || index.is_dummy || index.is_instant()); + return is; +} + +/** Determine if a record is delete-marked (not a metadata pseudo-record). +@param[in] rec record +@param[in] comp nonzero if ROW_FORMAT!=REDUNDANT +@return whether the record is a delete-marked user record */ +inline bool rec_is_delete_marked(const rec_t* rec, ulint comp) +{ + return (rec_get_info_bits(rec, comp) + & (REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG)) + == REC_INFO_DELETED_FLAG; +} + /** Get the nth field from an index. @param[in] rec index record @param[in] index index @@ -811,6 +851,7 @@ rec_get_nth_cfield( ulint* len) { ut_ad(rec_offs_validate(rec, index, offsets)); + if (!rec_offs_nth_default(offsets, n)) { return rec_get_nth_field(rec, offsets, n, len); } @@ -957,7 +998,7 @@ rec_copy( @param[in] fields data fields @param[in] n_fields number of data fields @param[out] extra record header size -@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED +@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT @return total size, in bytes */ ulint rec_get_converted_size_temp( @@ -974,7 +1015,7 @@ rec_get_converted_size_temp( @param[in,out] offsets offsets to the fields; in: rec_offs_n_fields(offsets) @param[in] n_core number of core fields (index->n_core_fields) @param[in] def_val default values for non-core fields -@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED */ +@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT */ void rec_init_offsets_temp( const rec_t* rec, @@ -1001,8 +1042,7 @@ rec_init_offsets_temp( @param[in] index clustered or secondary index @param[in] fields data fields @param[in] n_fields number of data fields -@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED -*/ +@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT */ void rec_convert_dtuple_to_temp( rec_t* rec, @@ -1065,21 +1105,20 @@ rec_get_converted_size_comp_prefix( ulint n_fields,/*!< in: number of data fields */ ulint* extra) /*!< out: extra size */ MY_ATTRIBUTE((warn_unused_result, nonnull(1,2))); -/**********************************************************//** -Determines the size of a data tuple in ROW_FORMAT=COMPACT. + +/** Determine the size of a record in ROW_FORMAT=COMPACT. +@param[in] index record descriptor. dict_table_is_comp() + is assumed to hold, even if it doesn't +@param[in] tuple logical record +@param[out] extra extra size @return total size */ ulint rec_get_converted_size_comp( -/*========================*/ - const dict_index_t* index, /*!< in: record descriptor; - dict_table_is_comp() is - assumed to hold, even if - it does not */ - rec_comp_status_t status, /*!< in: status bits of the record */ - const dfield_t* fields, /*!< in: array of data fields */ - ulint n_fields,/*!< in: number of data fields */ - ulint* extra) /*!< out: extra size */ - MY_ATTRIBUTE((nonnull(1,3))); + const dict_index_t* index, + const dtuple_t* tuple, + ulint* extra) + MY_ATTRIBUTE((nonnull(1,2))); + /**********************************************************//** The following function returns the size of a data tuple when converted to a physical record. diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index 41794582f37..f86643ddd62 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -67,7 +67,7 @@ most significant bytes and bits are written below less significant. 001=REC_STATUS_NODE_PTR 010=REC_STATUS_INFIMUM 011=REC_STATUS_SUPREMUM - 100=REC_STATUS_COLUMNS_ADDED + 100=REC_STATUS_INSTANT 1xx=reserved 5 bits heap number 4 8 bits heap number @@ -453,7 +453,7 @@ rec_get_n_fields( } switch (rec_get_status(rec)) { - case REC_STATUS_COLUMNS_ADDED: + case REC_STATUS_INSTANT: case REC_STATUS_ORDINARY: return(dict_index_get_n_fields(index)); case REC_STATUS_NODE_PTR: @@ -549,19 +549,6 @@ rec_set_n_owned_new( } } -#ifdef UNIV_DEBUG -/** Check if the info bits are valid. -@param[in] bits info bits to check -@return true if valid */ -inline -bool -rec_info_bits_valid( - ulint bits) -{ - return(0 == (bits & ~(REC_INFO_DELETED_FLAG | REC_INFO_MIN_REC_FLAG))); -} -#endif /* UNIV_DEBUG */ - /******************************************************//** The following function is used to retrieve the info bits of a record. @return info bits */ @@ -575,7 +562,6 @@ rec_get_info_bits( const ulint val = rec_get_bit_field_1( rec, comp ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS, REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT); - ut_ad(rec_info_bits_valid(val)); return(val); } @@ -588,7 +574,6 @@ rec_set_info_bits_old( rec_t* rec, /*!< in: old-style physical record */ ulint bits) /*!< in: info bits */ { - ut_ad(rec_info_bits_valid(bits)); rec_set_bit_field_1(rec, bits, REC_OLD_INFO_BITS, REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT); } @@ -601,7 +586,6 @@ rec_set_info_bits_new( rec_t* rec, /*!< in/out: new-style physical record */ ulint bits) /*!< in: info bits */ { - ut_ad(rec_info_bits_valid(bits)); rec_set_bit_field_1(rec, bits, REC_NEW_INFO_BITS, REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT); } @@ -894,7 +878,6 @@ rec_get_nth_field_offs( if SQL null; UNIV_SQL_DEFAULT is default value */ { ulint offs; - ulint length; ut_ad(n < rec_offs_n_fields(offsets)); ut_ad(len); @@ -904,7 +887,7 @@ rec_get_nth_field_offs( offs = rec_offs_base(offsets)[n] & REC_OFFS_MASK; } - length = rec_offs_base(offsets)[1 + n]; + ulint length = rec_offs_base(offsets)[1 + n]; if (length & REC_OFFS_SQL_NULL) { length = UNIV_SQL_NULL; @@ -1263,8 +1246,9 @@ rec_offs_data_size( ulint size; ut_ad(rec_offs_validate(NULL, NULL, offsets)); - size = rec_offs_base(offsets)[rec_offs_n_fields(offsets)] - & REC_OFFS_MASK; + + ulint n = rec_offs_n_fields(offsets); + size = rec_offs_base(offsets)[n] & REC_OFFS_MASK; ut_ad(size < srv_page_size); return(size); } @@ -1405,24 +1389,20 @@ rec_get_converted_size( } else if (index->table->id == DICT_INDEXES_ID) { /* The column SYS_INDEXES.MERGE_THRESHOLD was instantly added in MariaDB 10.2.2 (MySQL 5.7). */ + ut_ad(!index->table->is_temporary()); ut_ad(index->n_fields == DICT_NUM_FIELDS__SYS_INDEXES); ut_ad(dtuple->n_fields == DICT_NUM_FIELDS__SYS_INDEXES || dtuple->n_fields == DICT_FLD__SYS_INDEXES__MERGE_THRESHOLD); } else { ut_ad(dtuple->n_fields >= index->n_core_fields); - ut_ad(dtuple->n_fields <= index->n_fields); + ut_ad(dtuple->n_fields <= index->n_fields + || dtuple->is_alter_metadata()); } #endif if (dict_table_is_comp(index->table)) { - return(rec_get_converted_size_comp( - index, - static_cast<rec_comp_status_t>( - dtuple->info_bits - & REC_NEW_STATUS_MASK), - dtuple->fields, - dtuple->n_fields, NULL)); + return rec_get_converted_size_comp(index, dtuple, NULL); } data_size = dtuple_get_data_size(dtuple, 0); diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h index 630a40b0765..932accc46b0 100644 --- a/storage/innobase/include/row0row.h +++ b/storage/innobase/include/row0row.h @@ -74,6 +74,7 @@ row_get_rec_roll_ptr( #define ROW_BUILD_FOR_PURGE 1 /*!< build row for purge. */ #define ROW_BUILD_FOR_UNDO 2 /*!< build row for undo. */ #define ROW_BUILD_FOR_INSERT 3 /*!< build row for insert. */ + /*****************************************************************//** When an insert or purge to a table is performed, this function builds the entry to be inserted into or purged from an index on the table. @@ -227,6 +228,26 @@ row_rec_to_index_entry( mem_heap_t* heap) /*!< in: memory heap from which the memory needed is allocated */ MY_ATTRIBUTE((warn_unused_result)); + +/** Convert a metadata record to a data tuple. +@param[in] rec metadata record +@param[in] index clustered index after instant ALTER TABLE +@param[in] offsets rec_get_offsets(rec) +@param[out] n_ext number of externally stored fields +@param[in,out] heap memory heap for allocations +@param[in] info_bits the info_bits after an update +@param[in] pad whether to pad to index->n_fields */ +dtuple_t* +row_metadata_to_tuple( + const rec_t* rec, + const dict_index_t* index, + const ulint* offsets, + ulint* n_ext, + mem_heap_t* heap, + ulint info_bits, + bool pad) + MY_ATTRIBUTE((nonnull,warn_unused_result)); + /*******************************************************************//** Builds from a secondary index record a row reference with which we can search the clustered index record. diff --git a/storage/innobase/include/row0row.ic b/storage/innobase/include/row0row.ic index e1a3b5f6a1a..c9db1d2a37e 100644 --- a/storage/innobase/include/row0row.ic +++ b/storage/innobase/include/row0row.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -39,16 +39,12 @@ row_get_trx_id_offset( const dict_index_t* index, /*!< in: clustered index */ const ulint* offsets)/*!< in: record offsets */ { - ulint pos; ulint offset; ulint len; - ut_ad(dict_index_is_clust(index)); ut_ad(rec_offs_validate(NULL, index, offsets)); - pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); - - offset = rec_get_nth_field_offs(offsets, pos, &len); + offset = rec_get_nth_field_offs(offsets, index->db_trx_id(), &len); ut_ad(len == DATA_TRX_ID_LEN); diff --git a/storage/innobase/include/row0trunc.h b/storage/innobase/include/row0trunc.h deleted file mode 100644 index a7592f33cf7..00000000000 --- a/storage/innobase/include/row0trunc.h +++ /dev/null @@ -1,416 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, MariaDB Corporation. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file include/row0trunc.h -TRUNCATE implementation - -Created 2013-04-25 Krunal Bauskar -*******************************************************/ - -#ifndef row0trunc_h -#define row0trunc_h - -#include "row0mysql.h" -#include "dict0boot.h" -#include "fil0fil.h" -#include "srv0start.h" - -#include <vector> - -/** The information of TRUNCATE log record. -This class handles the recovery stage of TRUNCATE table. */ -class truncate_t { - -public: - /** - Constructor - - @param old_table_id old table id assigned to table before truncate - @param new_table_id new table id that will be assigned to table - after truncate - @param dir_path directory path */ - truncate_t( - table_id_t old_table_id, - table_id_t new_table_id, - const char* dir_path); - - /** - Constructor - - @param log_file_name parse the log file during recovery to populate - information related to table to truncate */ - truncate_t(const char* log_file_name); - - /** - Consturctor - - @param space_id space in which table reisde - @param name table name - @param tablespace_flags tablespace flags use for recreating tablespace - @param log_flags page format flag - @param recv_lsn lsn of redo log record. */ - truncate_t( - ulint space_id, - const char* name, - ulint tablespace_flags, - ulint log_flags, - lsn_t recv_lsn); - - /** Destructor */ - ~truncate_t(); - - /** The index information of MLOG_FILE_TRUNCATE redo record */ - struct index_t { - - /* Default copy constructor and destructor should be OK. */ - - index_t(); - - /** - Set the truncate log values for a compressed table. - @return DB_CORRUPTION or error code */ - dberr_t set(const dict_index_t* index); - - typedef std::vector<byte, ut_allocator<byte> > fields_t; - - /** Index id */ - index_id_t m_id; - - /** Index type */ - ulint m_type; - - /** Root Page Number */ - ulint m_root_page_no; - - /** New Root Page Number. - Note: This field is not persisted to TRUNCATE log but used - during truncate table fix-up for updating SYS_XXXX tables. */ - ulint m_new_root_page_no; - - /** Number of index fields */ - ulint m_n_fields; - - /** DATA_TRX_ID column position. */ - ulint m_trx_id_pos; - - /** Compressed table field meta data, encode by - page_zip_fields_encode. Empty for non-compressed tables. - Should be NUL terminated. */ - fields_t m_fields; - }; - - /** - @return the directory path, can be NULL */ - const char* get_dir_path() const - { - return(m_dir_path); - } - - /** - Register index information - - @param index index information logged as part of truncate log. */ - void add(index_t& index) - { - m_indexes.push_back(index); - } - - /** - Add table to truncate post recovery. - - @param ptr table information need to complete truncate of table. */ - static void add(truncate_t* ptr) - { - s_tables.push_back(ptr); - } - - /** - Clear registered index vector */ - void clear() - { - m_indexes.clear(); - } - - /** - @return old table id of the table to truncate */ - table_id_t old_table_id() const - { - return(m_old_table_id); - } - - /** - @return new table id of the table to truncate */ - table_id_t new_table_id() const - { - return(m_new_table_id); - } - - /** - Update root page number in SYS_XXXX tables. - - @param trx transaction object - @param table_id table id for which information needs to - be updated. - @param reserve_dict_mutex if TRUE, acquire/release - dict_sys->mutex around call to pars_sql. - @param mark_index_corrupted if true, then mark index corrupted - @return DB_SUCCESS or error code */ - dberr_t update_root_page_no( - trx_t* trx, - table_id_t table_id, - ibool reserve_dict_mutex, - bool mark_index_corrupted) const; - - /** Create an index for a table. - @param[in] table_name table name, for which to create - the index - @param[in,out] space tablespace - @param[in] index_type type of index to truncate - @param[in] index_id id of index to truncate - @param[in] btr_redo_create_info control info for ::btr_create() - @param[in,out] mtr mini-transaction covering the - create index - @return root page no or FIL_NULL on failure */ - inline ulint create_index( - const char* table_name, - fil_space_t* space, - ulint index_type, - index_id_t index_id, - const btr_create_t& btr_redo_create_info, - mtr_t* mtr) const; - - /** Create the indexes for a table - @param[in] table_name table name, for which to create the - indexes - @param[in,out] space tablespace - @param[in] format_flags page format flags - @return DB_SUCCESS or error code. */ - inline dberr_t create_indexes( - const char* table_name, - fil_space_t* space, - ulint format_flags); - - /** Check if index has been modified since TRUNCATE log snapshot - was recorded. - @param[in] space tablespace - @param[in] root_page_no index root page number - @return true if modified else false */ - inline bool is_index_modified_since_logged( - const fil_space_t* space, - ulint root_page_no) const; - - /** Drop indexes for a table. - @param[in,out] space tablespace - @return DB_SUCCESS or error code. */ - void drop_indexes(fil_space_t* space) const; - - /** - Parses log record during recovery - @param start_ptr buffer containing log body to parse - @param end_ptr buffer end - - @return DB_SUCCESS or error code */ - dberr_t parse( - byte* start_ptr, - const byte* end_ptr); - - /** Parse MLOG_TRUNCATE log record from REDO log file during recovery. - @param[in,out] start_ptr buffer containing log body to parse - @param[in] end_ptr buffer end - @param[in] space_id tablespace identifier - @return parsed upto or NULL. */ - static byte* parse_redo_entry( - byte* start_ptr, - const byte* end_ptr, - ulint space_id); - - /** - Write a log record for truncating a single-table tablespace. - - @param start_ptr buffer to write log record - @param end_ptr buffer end - @param space_id space id - @param tablename the table name in the usual - databasename/tablename format of InnoDB - @param flags tablespace flags - @param format_flags page format - @param lsn lsn while logging */ - dberr_t write( - byte* start_ptr, - byte* end_ptr, - ulint space_id, - const char* tablename, - ulint flags, - ulint format_flags, - lsn_t lsn) const; - - /** - @return number of indexes parsed from the truncate log record */ - size_t indexes() const; - - /** - Truncate a single-table tablespace. The tablespace must be cached - in the memory cache. - - Note: This is defined in fil0fil.cc because it needs to access some - types that are local to that file. - - @param space_id space id - @param dir_path directory path - @param tablename the table name in the usual - databasename/tablename format of InnoDB - @param flags tablespace flags - @param default_size if true, truncate to default size if tablespace - is being newly re-initialized. - @return DB_SUCCESS or error */ - static dberr_t truncate( - ulint space_id, - const char* dir_path, - const char* tablename, - ulint flags, - bool default_size); - - /** - Fix the table truncate by applying information parsed from TRUNCATE log. - Fix-up includes re-creating table (drop and re-create indexes) - @return error code or DB_SUCCESS */ - static dberr_t fixup_tables_in_system_tablespace(); - - /** - Fix the table truncate by applying information parsed from TRUNCATE log. - Fix-up includes re-creating tablespace. - @return error code or DB_SUCCESS */ - static dberr_t fixup_tables_in_non_system_tablespace(); - - /** - Check whether a tablespace was truncated during recovery - @param space_id tablespace id to check - @return true if the tablespace was truncated */ - static bool is_tablespace_truncated(ulint space_id); - - /** Was tablespace truncated (on crash before checkpoint). - If the MLOG_TRUNCATE redo-record is still available then tablespace - was truncated and checkpoint is yet to happen. - @param[in] space_id tablespace id to check. - @return true if tablespace was truncated. */ - static bool was_tablespace_truncated(ulint space_id); - - /** Get the lsn associated with space. - @param[in] space_id tablespace id to check. - @return associated lsn. */ - static lsn_t get_truncated_tablespace_init_lsn(ulint space_id); - -private: - typedef std::vector<index_t, ut_allocator<index_t> > indexes_t; - - /** Space ID of tablespace */ - ulint m_space_id; - - /** ID of table that is being truncated. */ - table_id_t m_old_table_id; - - /** New ID that will be assigned to table on truncation. */ - table_id_t m_new_table_id; - - /** Data dir path of tablespace */ - char* m_dir_path; - - /** Table name */ - char* m_tablename; - - /** Tablespace Flags */ - ulint m_tablespace_flags; - - /** Format flags (log flags; stored in page-no field of header) */ - ulint m_format_flags; - - /** Index meta-data */ - indexes_t m_indexes; - - /** LSN of TRUNCATE log record. */ - lsn_t m_log_lsn; - - /** Log file name. */ - char* m_log_file_name; - - /** Encryption information of the table */ - fil_encryption_t m_encryption; - uint32_t m_key_id; - - /** Vector of tables to truncate. */ - typedef std::vector<truncate_t*, ut_allocator<truncate_t*> > - tables_t; - - /** Information about tables to truncate post recovery */ - static tables_t s_tables; - - /** Information about truncated table - This is case when truncate is complete but checkpoint hasn't. */ - typedef std::map<ulint, lsn_t> truncated_tables_t; - static truncated_tables_t s_truncated_tables; - -public: - /** If true then fix-up of table is active and so while creating - index instead of grabbing information from dict_index_t, grab it - from parsed truncate log record. */ - static bool s_fix_up_active; -}; - -/** -Parse truncate log file. */ -class TruncateLogParser { - -public: - - /** - Scan and Parse truncate log files. - - @param dir_path look for log directory in following path - @return DB_SUCCESS or error code. */ - static dberr_t scan_and_parse( - const char* dir_path); - -private: - typedef std::vector<char*, ut_allocator<char*> > - trunc_log_files_t; - -private: - /** - Scan to find out truncate log file from the given directory path. - - @param dir_path look for log directory in following path. - @param log_files cache to hold truncate log file name found. - @return DB_SUCCESS or error code. */ - static dberr_t scan( - const char* dir_path, - trunc_log_files_t& log_files); - - /** - Parse the log file and populate table to truncate information. - (Add this table to truncate information to central vector that is then - used by truncate fix-up routine to fix-up truncate action of the table.) - - @param log_file_name log file to parse - @return DB_SUCCESS or error code. */ - static dberr_t parse( - const char* log_file_name); -}; - -#endif /* row0trunc_h */ diff --git a/storage/innobase/include/row0undo.h b/storage/innobase/include/row0undo.h index 5ac2c7c5ee0..6aa7ebaa339 100644 --- a/storage/innobase/include/row0undo.h +++ b/storage/innobase/include/row0undo.h @@ -82,17 +82,20 @@ that index record. */ enum undo_exec { UNDO_NODE_FETCH_NEXT = 1, /*!< we should fetch the next undo log record */ - UNDO_NODE_INSERT, /*!< undo a fresh insert of a - row to a table */ - UNDO_NODE_MODIFY /*!< undo a modify operation - (DELETE or UPDATE) on a row - of a table */ + /** rollback an insert into persistent table */ + UNDO_INSERT_PERSISTENT, + /** rollback an update (or delete) in a persistent table */ + UNDO_UPDATE_PERSISTENT, + /** rollback an insert into temporary table */ + UNDO_INSERT_TEMPORARY, + /** rollback an update (or delete) in a temporary table */ + UNDO_UPDATE_TEMPORARY, }; /** Undo node structure */ struct undo_node_t{ que_common_t common; /*!< node type: QUE_NODE_UNDO */ - enum undo_exec state; /*!< node execution state */ + undo_exec state; /*!< rollback execution state */ trx_t* trx; /*!< trx for which undo is done */ roll_ptr_t roll_ptr;/*!< roll pointer to undo log record */ trx_undo_rec_t* undo_rec;/*!< undo log record */ diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index 742f897f3ec..f21b3416ef6 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -100,19 +100,6 @@ upd_get_field_by_field_no( bool is_virtual) /*!< in: if it is a virtual column */ MY_ATTRIBUTE((warn_unused_result)); /*********************************************************************//** -Writes into the redo log the values of trx id and roll ptr and enough info -to determine their positions within a clustered index record. -@return new pointer to mlog */ -byte* -row_upd_write_sys_vals_to_log( -/*==========================*/ - dict_index_t* index, /*!< in: clustered index */ - trx_id_t trx_id, /*!< in: transaction id */ - roll_ptr_t roll_ptr,/*!< in: roll ptr of the undo log record */ - byte* log_ptr,/*!< pointer to a buffer of size > 20 opened - in mlog */ - mtr_t* mtr); /*!< in: mtr */ -/*********************************************************************//** Updates the trx id and roll ptr field in a clustered index record when a row is updated or marked deleted. */ UNIV_INLINE @@ -127,18 +114,6 @@ row_upd_rec_sys_fields( const trx_t* trx, /*!< in: transaction */ roll_ptr_t roll_ptr);/*!< in: DB_ROLL_PTR to the undo log */ /*********************************************************************//** -Sets the trx id or roll ptr field of a clustered index entry. */ -void -row_upd_index_entry_sys_field( -/*==========================*/ - dtuple_t* entry, /*!< in/out: index entry, where the memory - buffers for sys fields are already allocated: - the function just copies the new values to - them */ - dict_index_t* index, /*!< in: clustered index */ - ulint type, /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */ - ib_uint64_t val); /*!< in: value to write */ -/*********************************************************************//** Creates an update node for a query graph. @return own: update node */ upd_node_t* @@ -489,6 +464,14 @@ struct upd_t{ return false; } + /** @return whether this is for a hidden metadata record + for instant ALTER TABLE */ + bool is_metadata() const { return dtuple_t::is_metadata(info_bits); } + /** @return whether this is for a hidden metadata record + for instant ALTER TABLE (not only ADD COLUMN) */ + bool is_alter_metadata() const + { return dtuple_t::is_alter_metadata(info_bits); } + #ifdef UNIV_DEBUG bool validate() const { @@ -502,7 +485,6 @@ struct upd_t{ return(true); } #endif // UNIV_DEBUG - }; /** Kinds of update operation */ diff --git a/storage/innobase/include/row0upd.ic b/storage/innobase/include/row0upd.ic index 5e43a272388..403c39250cb 100644 --- a/storage/innobase/include/row0upd.ic +++ b/storage/innobase/include/row0upd.ic @@ -167,13 +167,13 @@ row_upd_rec_sys_fields( const trx_t* trx, /*!< in: transaction */ roll_ptr_t roll_ptr)/*!< in: DB_ROLL_PTR to the undo log */ { - ut_ad(dict_index_is_clust(index)); + ut_ad(index->is_primary()); ut_ad(rec_offs_validate(rec, index, offsets)); - if (page_zip) { - ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); + if (UNIV_LIKELY_NULL(page_zip)) { page_zip_write_trx_id_and_roll_ptr(page_zip, rec, offsets, - pos, trx->id, roll_ptr); + index->db_trx_id(), + trx->id, roll_ptr); } else { ulint offset = index->trx_id_offset; diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 069ab5cf93a..474634ef5e6 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -177,7 +177,6 @@ enum monitor_id_t { MONITOR_OVLD_INDEX_PAGES_WRITTEN, MONITOR_OVLD_NON_INDEX_PAGES_WRITTEN, MONITOR_OVLD_PAGES_READ, - MONITOR_OVLD_PAGES0_READ, MONITOR_OVLD_INDEX_SEC_REC_CLUSTER_READS, MONITOR_OVLD_INDEX_SEC_REC_CLUSTER_READS_AVOIDED, MONITOR_OVLD_BYTE_READ, @@ -300,7 +299,6 @@ enum monitor_id_t { MONITOR_TRX_COMMIT_UNDO, MONITOR_TRX_ROLLBACK, MONITOR_TRX_ROLLBACK_SAVEPOINT, - MONITOR_TRX_ROLLBACK_ACTIVE, MONITOR_TRX_ACTIVE, MONITOR_RSEG_HISTORY_LEN, MONITOR_NUM_UNDO_SLOT_USED, diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index c6873ca8938..3af456b4b1a 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -47,7 +47,6 @@ Created 10/10/1995 Heikki Tuuri #include "que0types.h" #include "trx0types.h" #include "srv0conc.h" -#include "buf0checksum.h" #include "fil0fil.h" #include "mysql/psi/mysql_stage.h" @@ -176,9 +175,6 @@ struct srv_stats_t /** Number of times prefix optimization avoided triggering cluster lookup */ ulint_ctr_64_t n_sec_rec_cluster_reads_avoided; - /** Number of times page 0 is read from tablespace */ - ulint_ctr_64_t page0_read; - /** Number of encryption_get_latest_key_version calls */ ulint_ctr_64_t n_key_requests; @@ -900,23 +896,6 @@ srv_purge_wakeup(); /** Shut down the purge threads. */ void srv_purge_shutdown(); -/** Check if tablespace is being truncated. -(Ignore system-tablespace as we don't re-create the tablespace -and so some of the action that are suppressed by this function -for independent tablespace are not applicable to system-tablespace). -@param space_id space_id to check for truncate action -@return true if being truncated, false if not being - truncated or tablespace is system-tablespace. */ -bool -srv_is_tablespace_truncated(ulint space_id); - -/** Check if tablespace was truncated. -@param[in] space space object to check for truncate action -@return true if tablespace was truncated and we still have an active -MLOG_TRUNCATE REDO log record. */ -bool -srv_was_tablespace_truncated(const fil_space_t* space); - #ifdef UNIV_DEBUG /** Disables master thread. It's used by: SET GLOBAL innodb_master_thread_disabled_debug = 1 (0). @@ -971,7 +950,6 @@ struct export_var_t{ ulint innodb_page_size; /*!< srv_page_size */ ulint innodb_pages_created; /*!< buf_pool->stat.n_pages_created */ ulint innodb_pages_read; /*!< buf_pool->stat.n_pages_read*/ - ulint innodb_page0_read; /*!< srv_stats.page0_read */ ulint innodb_pages_written; /*!< buf_pool->stat.n_pages_written */ ulint innodb_row_lock_waits; /*!< srv_n_lock_wait_count */ ulint innodb_row_lock_current_waits; /*!< srv_n_lock_wait_current_count */ diff --git a/storage/innobase/include/sync0arr.ic b/storage/innobase/include/sync0arr.ic index cd1d8e27625..d8f24cb4279 100644 --- a/storage/innobase/include/sync0arr.ic +++ b/storage/innobase/include/sync0arr.ic @@ -44,8 +44,7 @@ sync_array_get() return(sync_wait_array[0]); } - return(sync_wait_array[default_indexer_t<>::get_rnd_index() - % sync_array_size]); + return(sync_wait_array[get_rnd_value() % sync_array_size]); } /******************************************************************//** diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 43d771c646b..6d1649c0a9c 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -135,202 +135,6 @@ private: TrxUndoRsegs::const_iterator m_iter; }; -/* Namespace to hold all the related functions and variables need for truncate -of undo tablespace. */ -namespace undo { - - typedef std::vector<ulint> undo_spaces_t; - typedef std::vector<trx_rseg_t*> rseg_for_trunc_t; - - /** Mark completion of undo truncate action by writing magic number to - the log file and then removing it from the disk. - If we are going to remove it from disk then why write magic number ? - This is to safeguard from unlink (file-system) anomalies that will keep - the link to the file even after unlink action is successfull and - ref-count = 0. - @param[in] space_id id of the undo tablespace to truncate.*/ - void done(ulint space_id); - - /** Check if TRUNCATE_DDL_LOG file exist. - @param[in] space_id id of the undo tablespace. - @return true if exist else false. */ - bool is_log_present(ulint space_id); - - /** Track UNDO tablespace mark for truncate. */ - class Truncate { - public: - void create() - { - m_undo_for_trunc = ULINT_UNDEFINED; - m_scan_start = 1; - m_purge_rseg_truncate_frequency = - ulint(srv_purge_rseg_truncate_frequency); - } - - /** Clear the cached rollback segment. Normally done - when purge is about to shutdown. */ - void clear() - { - reset(); - rseg_for_trunc_t temp; - m_rseg_for_trunc.swap(temp); - } - - /** Is tablespace selected for truncate. - @return true if undo tablespace is marked for truncate */ - bool is_marked() const - { - return(!(m_undo_for_trunc == ULINT_UNDEFINED)); - } - - /** Mark the tablespace for truncate. - @param[in] undo_id tablespace for truncate. */ - void mark(ulint undo_id) - { - m_undo_for_trunc = undo_id; - - m_scan_start = (undo_id + 1) - % (srv_undo_tablespaces_active + 1); - if (m_scan_start == 0) { - /* Note: UNDO tablespace ids starts from 1. */ - m_scan_start = 1; - } - - /* We found an UNDO-tablespace to truncate so set the - local purge rseg truncate frequency to 1. This will help - accelerate the purge action and in turn truncate. */ - m_purge_rseg_truncate_frequency = 1; - } - - /** Get the tablespace marked for truncate. - @return tablespace id marked for truncate. */ - ulint get_marked_space_id() const - { - return(m_undo_for_trunc); - } - - /** Add rseg to truncate vector. - @param[in,out] rseg rseg for truncate */ - void add_rseg_to_trunc(trx_rseg_t* rseg) - { - m_rseg_for_trunc.push_back(rseg); - } - - /** Get number of rsegs registered for truncate. - @return return number of rseg that belongs to tablespace mark - for truncate. */ - ulint rsegs_size() const - { - return(m_rseg_for_trunc.size()); - } - - /** Get ith registered rseg. - @param[in] id index of rseg to get. - @return reference to registered rseg. */ - trx_rseg_t* get_ith_rseg(ulint id) - { - ut_ad(id < m_rseg_for_trunc.size()); - return(m_rseg_for_trunc.at(id)); - } - - /** Reset for next rseg truncate. */ - void reset() - { - m_undo_for_trunc = ULINT_UNDEFINED; - m_rseg_for_trunc.clear(); - - /* Sync with global value as we are done with - truncate now. */ - m_purge_rseg_truncate_frequency = static_cast<ulint>( - srv_purge_rseg_truncate_frequency); - } - - /** Get the tablespace id to start scanning from. - @return id of UNDO tablespace to start scanning from. */ - ulint get_scan_start() const - { - return(m_scan_start); - } - - /** Check if the tablespace needs fix-up (based on presence of - DDL truncate log) - @param space_id space id of the undo tablespace to check - @return true if fix up is needed else false */ - bool needs_fix_up(ulint space_id) const - { - return(is_log_present(space_id)); - } - - /** Add undo tablespace to truncate vector. - @param[in] space_id space id of tablespace to - truncate */ - static void add_space_to_trunc_list(ulint space_id) - { - s_spaces_to_truncate.push_back(space_id); - } - - /** Clear the truncate vector. */ - static void clear_trunc_list() - { - s_spaces_to_truncate.clear(); - } - - /** Is tablespace marked for truncate. - @param[in] space_id space id to check - @return true if marked for truncate, else false. */ - static bool is_tablespace_truncated(ulint space_id) - { - return(std::find(s_spaces_to_truncate.begin(), - s_spaces_to_truncate.end(), space_id) - != s_spaces_to_truncate.end()); - } - - /** Was a tablespace truncated at startup - @param[in] space_id space id to check - @return whether space_id was truncated at startup */ - static bool was_tablespace_truncated(ulint space_id) - { - return(std::find(s_fix_up_spaces.begin(), - s_fix_up_spaces.end(), - space_id) - != s_fix_up_spaces.end()); - } - - /** Get local rseg purge truncate frequency - @return rseg purge truncate frequency. */ - ulint get_rseg_truncate_frequency() const - { - return(m_purge_rseg_truncate_frequency); - } - - private: - /** UNDO tablespace is mark for truncate. */ - ulint m_undo_for_trunc; - - /** rseg that resides in UNDO tablespace is marked for - truncate. */ - rseg_for_trunc_t m_rseg_for_trunc; - - /** Start scanning for UNDO tablespace from this space_id. - This is to avoid bias selection of one tablespace always. */ - ulint m_scan_start; - - /** Rollback segment(s) purge frequency. This is local - value maintained along with global value. It is set to global - value on start but when tablespace is marked for truncate it - is updated to 1 and then minimum value among 2 is used by - purge action. */ - ulint m_purge_rseg_truncate_frequency; - - /** List of UNDO tablespace(s) to truncate. */ - static undo_spaces_t s_spaces_to_truncate; - public: - /** Undo tablespaces that were truncated at startup */ - static undo_spaces_t s_fix_up_spaces; - }; /* class Truncate */ - -}; /* namespace undo */ - /** The control structure used in the purge operation */ class purge_sys_t { @@ -412,9 +216,14 @@ public: by the pq_mutex */ PQMutex pq_mutex; /*!< Mutex protecting purge_queue */ - undo::Truncate undo_trunc; /*!< Track UNDO tablespace marked - for truncate. */ - + /** Undo tablespace file truncation (only accessed by the + srv_purge_coordinator_thread) */ + struct { + /** The undo tablespace that is currently being truncated */ + fil_space_t* current; + /** The undo tablespace that was last truncated */ + fil_space_t* last; + } truncate; /** Constructor. diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h index b74b56eae98..93432cde74e 100644 --- a/storage/innobase/include/trx0roll.h +++ b/storage/innobase/include/trx0roll.h @@ -51,16 +51,6 @@ trx_savept_take( /*============*/ trx_t* trx); /*!< in: transaction */ -/** Get the last undo log record of a transaction (for rollback). -@param[in,out] trx transaction -@param[out] roll_ptr DB_ROLL_PTR to the undo record -@param[in,out] heap memory heap for allocation -@return undo log record copied to heap -@retval NULL if none left or the roll_limit (savepoint) was reached */ -trx_undo_rec_t* -trx_roll_pop_top_rec_of_trx(trx_t* trx, roll_ptr_t* roll_ptr, mem_heap_t* heap) - MY_ATTRIBUTE((nonnull, warn_unused_result)); - /** Report progress when rolling back a row of a recovered transaction. */ void trx_roll_report_progress(); /*******************************************************************//** diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 9fb65c19911..2c6b610f930 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -478,6 +478,7 @@ Check transaction state */ ut_ad(!(t)->read_view.is_open()); \ ut_ad((t)->lock.wait_thr == NULL); \ ut_ad(UT_LIST_GET_LEN((t)->lock.trx_locks) == 0); \ + ut_ad(UT_LIST_GET_LEN((t)->lock.evicted_tables) == 0); \ ut_ad((t)->dict_operation == TRX_DICT_OP_NONE); \ } while(0) @@ -602,6 +603,9 @@ struct trx_lock_t { lock_list table_locks; /*!< All table locks requested by this transaction, including AUTOINC locks */ + /** List of pending trx_t::evict_table() */ + UT_LIST_BASE_NODE_T(dict_table_t) evicted_tables; + bool cancel; /*!< true if the transaction is being rolled back either via deadlock detection or due to lock timeout. The @@ -1108,6 +1112,10 @@ public: return(assign_temp_rseg()); } + /** Evict a table definition due to the rollback of ALTER TABLE. + @param[in] table_id table identifier */ + void evict_table(table_id_t table_id); + bool is_referenced() { diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h index 60b0517db0d..f3c52fff7b5 100644 --- a/storage/innobase/include/trx0undo.h +++ b/storage/innobase/include/trx0undo.h @@ -79,27 +79,22 @@ trx_undo_trx_id_is_insert( /*======================*/ const byte* trx_id) /*!< in: DB_TRX_ID, followed by DB_ROLL_PTR */ MY_ATTRIBUTE((warn_unused_result)); -/*****************************************************************//** -Writes a roll ptr to an index page. In case that the size changes in -some future version, this function should be used instead of -mach_write_... */ -UNIV_INLINE -void -trx_write_roll_ptr( -/*===============*/ - byte* ptr, /*!< in: pointer to memory where - written */ - roll_ptr_t roll_ptr); /*!< in: roll ptr */ -/*****************************************************************//** -Reads a roll ptr from an index page. In case that the roll ptr size -changes in some future version, this function should be used instead of -mach_read_... +/** Write DB_ROLL_PTR. +@param[out] ptr buffer +@param[in] roll_ptr DB_ROLL_PTR value */ +inline void trx_write_roll_ptr(byte* ptr, roll_ptr_t roll_ptr) +{ + compile_time_assert(DATA_ROLL_PTR_LEN == 7); + mach_write_to_7(ptr, roll_ptr); +} +/** Read DB_ROLL_PTR. +@param[in] ptr buffer @return roll ptr */ -UNIV_INLINE -roll_ptr_t -trx_read_roll_ptr( -/*==============*/ - const byte* ptr); /*!< in: pointer to memory from where to read */ +inline roll_ptr_t trx_read_roll_ptr(const byte* ptr) +{ + compile_time_assert(DATA_ROLL_PTR_LEN == 7); + return mach_read_from_7(ptr); +} /** Gets an undo log page and x-latches it. @param[in] page_id page id @@ -185,9 +180,7 @@ trx_undo_free_last_page(trx_undo_t* undo, mtr_t* mtr) @param[in,out] undo undo log @param[in] limit all undo logs after this limit will be discarded @param[in] is_temp whether this is temporary undo log */ -void -trx_undo_truncate_end(trx_undo_t* undo, undo_no_t limit, bool is_temp) - MY_ATTRIBUTE((nonnull)); +void trx_undo_truncate_end(trx_undo_t& undo, undo_no_t limit, bool is_temp); /** Truncate the head of an undo log. NOTE that only whole pages are freed; the header page is not diff --git a/storage/innobase/include/trx0undo.ic b/storage/innobase/include/trx0undo.ic index ac8af61be09..f6106ffddfa 100644 --- a/storage/innobase/include/trx0undo.ic +++ b/storage/innobase/include/trx0undo.ic @@ -103,37 +103,6 @@ trx_undo_trx_id_is_insert( return bool(trx_id[DATA_TRX_ID_LEN] >> 7); } -/*****************************************************************//** -Writes a roll ptr to an index page. In case that the size changes in -some future version, this function should be used instead of -mach_write_... */ -UNIV_INLINE -void -trx_write_roll_ptr( -/*===============*/ - byte* ptr, /*!< in: pointer to memory where - written */ - roll_ptr_t roll_ptr) /*!< in: roll ptr */ -{ - compile_time_assert(DATA_ROLL_PTR_LEN == 7); - mach_write_to_7(ptr, roll_ptr); -} - -/*****************************************************************//** -Reads a roll ptr from an index page. In case that the roll ptr size -changes in some future version, this function should be used instead of -mach_read_... -@return roll ptr */ -UNIV_INLINE -roll_ptr_t -trx_read_roll_ptr( -/*==============*/ - const byte* ptr) /*!< in: pointer to memory from where to read */ -{ - compile_time_assert(DATA_ROLL_PTR_LEN == 7); - return(mach_read_from_7(ptr)); -} - /** Gets an undo log page and x-latches it. @param[in] page_id page id @param[in,out] mtr mini-transaction diff --git a/storage/innobase/include/ut0counter.h b/storage/innobase/include/ut0counter.h index ab694386099..653515a3d7d 100644 --- a/storage/innobase/include/ut0counter.h +++ b/storage/innobase/include/ut0counter.h @@ -29,8 +29,8 @@ Created 2012/04/12 by Sunny Bains #define ut0counter_h #include "os0thread.h" +#include <atomic> #include "my_rdtsc.h" -#include "my_atomic.h" /** CPU cache line size */ #ifdef CPU_LEVEL1_DCACHE_LINESIZE @@ -42,120 +42,79 @@ Created 2012/04/12 by Sunny Bains /** Default number of slots to use in ib_counter_t */ #define IB_N_SLOTS 64 -/** Get the offset into the counter array. */ -template <typename Type, int N> -struct generic_indexer_t { - /** @return offset within m_counter */ - static size_t offset(size_t index) UNIV_NOTHROW - { - return(((index % N) + 1) * (CACHE_LINE_SIZE / sizeof(Type))); - } -}; +/** Use the result of my_timer_cycles(), which mainly uses RDTSC for cycles +as a random value. See the comments for my_timer_cycles() */ +/** @return result from RDTSC or similar functions. */ +static inline size_t +get_rnd_value() +{ + size_t c = static_cast<size_t>(my_timer_cycles()); + + if (c != 0) { + return c; + } -/** Use the result of my_timer_cycles(), which mainly uses RDTSC for cycles, -to index into the counter array. See the comments for my_timer_cycles() */ -template <typename Type=ulint, int N=1> -struct counter_indexer_t : public generic_indexer_t<Type, N> { - /** @return result from RDTSC or similar functions. */ - static size_t get_rnd_index() UNIV_NOTHROW - { - size_t c = static_cast<size_t>(my_timer_cycles()); - - if (c != 0) { - return(c); - } else { - /* We may go here if my_timer_cycles() returns 0, - so we have to have the plan B for the counter. */ + /* We may go here if my_timer_cycles() returns 0, + so we have to have the plan B for the counter. */ #if !defined(_WIN32) - return(size_t(os_thread_get_curr_id())); + return (size_t)os_thread_get_curr_id(); #else - LARGE_INTEGER cnt; - QueryPerformanceCounter(&cnt); + LARGE_INTEGER cnt; + QueryPerformanceCounter(&cnt); - return(static_cast<size_t>(cnt.QuadPart)); + return static_cast<size_t>(cnt.QuadPart); #endif /* !_WIN32 */ - } - } +} - /** @return a random offset to the array */ - static size_t get_rnd_offset() UNIV_NOTHROW - { - return(generic_indexer_t<Type, N>::offset(get_rnd_index())); - } -}; - -#define default_indexer_t counter_indexer_t - -/** Class for using fuzzy counters. The counter is relaxed atomic +/** Class for using fuzzy counters. The counter is multi-instance relaxed atomic so the results are not guaranteed to be 100% accurate but close enough. Creates an array of counters and separates each element by the CACHE_LINE_SIZE bytes */ -template < - typename Type, - int N = IB_N_SLOTS, - template<typename, int> class Indexer = default_indexer_t> -struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t -{ +template <typename Type, int N = IB_N_SLOTS> +struct ib_counter_t { /** Increment the counter by 1. */ - void inc() UNIV_NOTHROW { add(1); } + void inc() { add(1); } /** Increment the counter by 1. @param[in] index a reasonably thread-unique identifier */ - void inc(size_t index) UNIV_NOTHROW { add(index, 1); } + void inc(size_t index) { add(index, 1); } /** Add to the counter. @param[in] n amount to be added */ - void add(Type n) UNIV_NOTHROW { add(m_policy.get_rnd_offset(), n); } + void add(Type n) { add(get_rnd_value(), n); } /** Add to the counter. @param[in] index a reasonably thread-unique identifier @param[in] n amount to be added */ - void add(size_t index, Type n) UNIV_NOTHROW { - size_t i = m_policy.offset(index); - - ut_ad(i < UT_ARR_SIZE(m_counter)); - - if (sizeof(Type) == 8) { - my_atomic_add64_explicit( - reinterpret_cast<int64*>(&m_counter[i]), - static_cast<int64>(n), MY_MEMORY_ORDER_RELAXED); - } else if (sizeof(Type) == 4) { - my_atomic_add32_explicit( - reinterpret_cast<int32*>(&m_counter[i]), - static_cast<int32>(n), MY_MEMORY_ORDER_RELAXED); - } - compile_time_assert(sizeof(Type) == 8 || sizeof(Type) == 4); + void add(size_t index, Type n) { + index = index % N; + + ut_ad(index < UT_ARR_SIZE(m_counter)); + + m_counter[index].value.fetch_add(n, std::memory_order_relaxed); } - /* @return total value - not 100% accurate, since it is relaxed atomic. */ - operator Type() const UNIV_NOTHROW { + /* @return total value - not 100% accurate, since it is relaxed atomic*/ + operator Type() const { Type total = 0; - for (size_t i = 0; i < N; ++i) { - if (sizeof(Type) == 8) { - total += static_cast< - Type>(my_atomic_load64_explicit( - reinterpret_cast<int64*>(const_cast<Type*>( - &m_counter[m_policy.offset(i)])), - MY_MEMORY_ORDER_RELAXED)); - } else if (sizeof(Type) == 4) { - total += static_cast< - Type>(my_atomic_load32_explicit( - reinterpret_cast<int32*>(const_cast<Type*>( - &m_counter[m_policy.offset(i)])), - MY_MEMORY_ORDER_RELAXED)); - } + for (const auto &counter : m_counter) { + total += counter.value.load(std::memory_order_relaxed); } return(total); } private: - /** Indexer into the array */ - Indexer<Type, N>m_policy; - - /** Slot 0 is unused. */ - Type m_counter[(N + 1) * (CACHE_LINE_SIZE / sizeof(Type))]; + /** Atomic which occupies whole CPU cache line */ + union ib_counter_element_t { + std::atomic<Type> value; + byte padding[CACHE_LINE_SIZE]; + }; + static_assert(sizeof(ib_counter_element_t) == CACHE_LINE_SIZE, ""); + + /** Array of counter elements */ + MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_element_t m_counter[N]; }; #endif /* ut0counter_h */ diff --git a/storage/innobase/include/ut0crc32.h b/storage/innobase/include/ut0crc32.h index b8fc4168dfd..8c04ae0dcc6 100644 --- a/storage/innobase/include/ut0crc32.h +++ b/storage/innobase/include/ut0crc32.h @@ -47,12 +47,6 @@ typedef uint32_t (*ut_crc32_func_t)(const byte* ptr, ulint len); /** Pointer to CRC32 calculation function. */ extern ut_crc32_func_t ut_crc32; -#ifdef INNODB_BUG_ENDIAN_CRC32 -/** Pointer to CRC32 calculation function, which uses big-endian byte order -when converting byte strings to integers internally. */ -extern uint32_t ut_crc32_legacy_big_endian(const byte* buf, ulint len); -#endif /* INNODB_BUG_ENDIAN_CRC32 */ - /** Text description of CRC32 implementation */ extern const char* ut_crc32_implementation; diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index 1614d3ead6d..813b5f5c198 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -175,12 +175,6 @@ ut_2_power_up( ulint n) /*!< in: number != 0 */ MY_ATTRIBUTE((const)); -/** Determine how many bytes (groups of 8 bits) are needed to -store the given number of bits. -@param b in: bits -@return number of bytes (octets) needed to represent b */ -#define UT_BITS_IN_BYTES(b) (((b) + 7) / 8) - /**********************************************************//** Returns system time. We do not specify the format of the time returned: the only way to manipulate it is to use the function ut_difftime. @@ -239,6 +233,12 @@ ut_difftime( #endif /* !UNIV_INNOCHECKSUM */ +/** Determine how many bytes (groups of 8 bits) are needed to +store the given number of bits. +@param b in: bits +@return number of bytes (octets) needed to represent b */ +#define UT_BITS_IN_BYTES(b) (((b) + 7) / 8) + /** Determines if a number is zero or a power of two. @param[in] n number @return nonzero if n is zero or a power of two; zero otherwise */ diff --git a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake index 33b73813b0e..85ae3bbc025 100644 --- a/storage/innobase/innodb.cmake +++ b/storage/innobase/innodb.cmake @@ -121,11 +121,6 @@ ELSEIF(WITH_INNODB_ROOT_GUESS) ADD_DEFINITIONS(-DBTR_CUR_ADAPT) ENDIF() -OPTION(WITH_INNODB_BUG_ENDIAN_CRC32 "Weaken innodb_checksum_algorithm=crc32 by supporting upgrade from big-endian systems running 5.6/10.0/10.1" ${IS_BIG_ENDIAN}) -IF(WITH_INNODB_BUG_ENDIAN_CRC32) - ADD_DEFINITIONS(-DINNODB_BUG_ENDIAN_CRC32) -ENDIF() - OPTION(WITH_INNODB_EXTRA_DEBUG "Enable extra InnoDB debug checks" OFF) IF(WITH_INNODB_EXTRA_DEBUG) ADD_DEFINITIONS(-DUNIV_ZIP_DEBUG) diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index c8707955a5d..51d6dedf512 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -333,7 +333,7 @@ lock_report_trx_id_insanity( trx_id_t max_trx_id) /*!< in: trx_sys.get_max_trx_id() */ { ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); ib::error() << "Transaction id " << trx_id @@ -356,7 +356,7 @@ lock_check_trx_id_sanity( const ulint* offsets) /*!< in: rec_get_offsets(rec, index) */ { ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); trx_id_t max_trx_id = trx_sys.get_max_trx_id(); ut_ad(max_trx_id || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN); @@ -385,7 +385,7 @@ lock_clust_rec_cons_read_sees( ut_ad(dict_index_is_clust(index)); ut_ad(page_rec_is_user_rec(rec)); ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); /* Temp-tables are not shared across connections and multiple transactions from different connections cannot simultaneously @@ -424,7 +424,7 @@ lock_sec_rec_cons_read_sees( { ut_ad(page_rec_is_user_rec(rec)); ut_ad(!index->is_primary()); - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); /* NOTE that we might call this function while holding the search system latch. */ @@ -1218,7 +1218,7 @@ lock_sec_rec_some_has_impl( ut_ad(!dict_index_is_clust(index)); ut_ad(page_rec_is_user_rec(rec)); ut_ad(rec_offs_validate(rec, index, offsets)); - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); max_trx_id = page_get_max_trx_id(page); @@ -4253,6 +4253,7 @@ lock_check_dict_lock( const lock_t* lock) /*!< in: lock to check */ { if (lock_get_type_low(lock) == LOCK_REC) { + ut_ad(!lock->index->table->is_temporary()); /* Check if the transcation locked a record in a system table in X mode. It should have set @@ -4266,9 +4267,8 @@ lock_check_dict_lock( } else { ut_ad(lock_get_type_low(lock) & LOCK_TABLE); - const dict_table_t* table; - - table = lock->un_member.tab_lock.table; + const dict_table_t* table = lock->un_member.tab_lock.table; + ut_ad(!table->is_temporary()); /* Check if the transcation locked a system table in IX mode. It should have set the dict_op code @@ -5320,7 +5320,7 @@ lock_rec_insert_check_and_lock( trx_t* trx = thr_get_trx(thr); const rec_t* next_rec = page_rec_get_next_const(rec); ulint heap_no = page_rec_get_heap_no(next_rec); - ut_ad(!rec_is_metadata(next_rec, index)); + ut_ad(!rec_is_metadata(next_rec, *index)); lock_mutex_enter(); /* Because this code is invoked for a running transaction by @@ -5448,7 +5448,7 @@ lock_rec_convert_impl_to_expl_for_trx( { ut_ad(trx->is_referenced()); ut_ad(page_rec_is_leaf(rec)); - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); DEBUG_SYNC_C("before_lock_rec_convert_impl_to_expl_for_trx"); @@ -5572,7 +5572,7 @@ lock_rec_convert_impl_to_expl( ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets)); ut_ad(page_rec_is_leaf(rec)); - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); if (dict_index_is_clust(index)) { trx_id_t trx_id; @@ -5649,7 +5649,7 @@ lock_clust_rec_modify_check_and_lock( return(DB_SUCCESS); } - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); ut_ad(!index->table->is_temporary()); heap_no = rec_offs_comp(offsets) @@ -5705,7 +5705,7 @@ lock_sec_rec_modify_check_and_lock( ut_ad(block->frame == page_align(rec)); ut_ad(mtr->is_named_space(index->table->space)); ut_ad(page_rec_is_leaf(rec)); - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); if (flags & BTR_NO_LOCKING_FLAG) { @@ -5799,7 +5799,7 @@ lock_sec_rec_read_check_and_lock( return(DB_SUCCESS); } - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); heap_no = page_rec_get_heap_no(rec); /* Some transaction may have an implicit x-lock on the record only @@ -5861,7 +5861,7 @@ lock_clust_rec_read_check_and_lock( || gap_mode == LOCK_REC_NOT_GAP); ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(page_rec_is_leaf(rec)); - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); if ((flags & BTR_NO_LOCKING_FLAG) || srv_read_only_mode @@ -6132,10 +6132,8 @@ lock_get_table_id( /*==============*/ const lock_t* lock) /*!< in: lock */ { - dict_table_t* table; - - table = lock_get_table(lock); - + dict_table_t* table = lock_get_table(lock); + ut_ad(!table->is_temporary()); return(table->id); } diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc index dff9661c6eb..7ad39da29ec 100644 --- a/storage/innobase/log/log0crypt.cc +++ b/storage/innobase/log/log0crypt.cc @@ -82,19 +82,62 @@ log_block_get_start_lsn( return start_lsn; } +/** Generate crypt key from crypt msg. +@param[in,out] info encryption key +@param[in] upgrade whether to use the key in MariaDB 10.1 format +@return whether the operation was successful */ +static bool init_crypt_key(crypt_info_t* info, bool upgrade = false) +{ + byte mysqld_key[MY_AES_MAX_KEY_LENGTH]; + uint keylen = sizeof mysqld_key; + + compile_time_assert(16 == sizeof info->crypt_key); + + if (uint rc = encryption_key_get(LOG_DEFAULT_ENCRYPTION_KEY, + info->key_version, mysqld_key, + &keylen)) { + ib::error() + << "Obtaining redo log encryption key version " + << info->key_version << " failed (" << rc + << "). Maybe the key or the required encryption " + "key management plugin was not found."; + return false; + } + + if (upgrade) { + while (keylen < sizeof mysqld_key) { + mysqld_key[keylen++] = 0; + } + } + + uint dst_len; + int err= my_aes_crypt(MY_AES_ECB, + ENCRYPTION_FLAG_NOPAD | ENCRYPTION_FLAG_ENCRYPT, + info->crypt_msg.bytes, sizeof info->crypt_msg, + info->crypt_key.bytes, &dst_len, + mysqld_key, keylen, NULL, 0); + + if (err != MY_AES_OK || dst_len != MY_AES_BLOCK_SIZE) { + ib::error() << "Getting redo log crypto key failed: err = " + << err << ", len = " << dst_len; + return false; + } + + return true; +} + /** Encrypt or decrypt log blocks. @param[in,out] buf log blocks to encrypt or decrypt @param[in] lsn log sequence number of the start of the buffer @param[in] size size of the buffer, in bytes -@param[in] decrypt whether to decrypt instead of encrypting */ -UNIV_INTERN -void -log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt) +@param[in] op whether to decrypt, encrypt, or rotate key and encrypt +@return whether the operation succeeded (encrypt always does) */ +bool log_crypt(byte* buf, lsn_t lsn, ulint size, log_crypt_t op) { ut_ad(size % OS_FILE_LOG_BLOCK_SIZE == 0); + ut_ad(ulint(buf) % OS_FILE_LOG_BLOCK_SIZE == 0); ut_a(info.key_version); - uint dst_len; uint32_t aes_ctr_iv[MY_AES_BLOCK_SIZE / sizeof(uint32_t)]; compile_time_assert(sizeof(uint32_t) == 4); @@ -103,7 +146,8 @@ log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt) for (const byte* const end = buf + size; buf != end; buf += OS_FILE_LOG_BLOCK_SIZE, lsn += OS_FILE_LOG_BLOCK_SIZE) { - uint32_t dst[(OS_FILE_LOG_BLOCK_SIZE - LOG_CRYPT_HDR_SIZE) + uint32_t dst[(OS_FILE_LOG_BLOCK_SIZE - LOG_CRYPT_HDR_SIZE + - LOG_BLOCK_CHECKSUM) / sizeof(uint32_t)]; /* The log block number is not encrypted. */ @@ -123,64 +167,61 @@ log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt) ut_ad(log_block_get_start_lsn(lsn, log_block_get_hdr_no(buf)) == lsn); + byte* key_ver = &buf[OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_KEY + - LOG_BLOCK_CHECKSUM]; + const uint dst_size + = log_sys.log.format == LOG_HEADER_FORMAT_ENC_10_4 + ? sizeof dst - LOG_BLOCK_KEY + : sizeof dst; + if (log_sys.log.format == LOG_HEADER_FORMAT_ENC_10_4) { + const uint key_version = info.key_version; + switch (op) { + case LOG_ENCRYPT_ROTATE_KEY: + info.key_version + = encryption_key_get_latest_version( + LOG_DEFAULT_ENCRYPTION_KEY); + if (key_version != info.key_version + && !init_crypt_key(&info)) { + info.key_version = key_version; + } + /* fall through */ + case LOG_ENCRYPT: + mach_write_to_4(key_ver, info.key_version); + break; + case LOG_DECRYPT: + info.key_version = mach_read_from_4(key_ver); + if (key_version != info.key_version + && !init_crypt_key(&info)) { + return false; + } + } +#ifndef DBUG_OFF + if (key_version != info.key_version) { + DBUG_PRINT("ib_log", ("key_version: %x -> %x", + key_version, + info.key_version)); + } +#endif /* !DBUG_OFF */ + } + ut_ad(LOG_CRYPT_HDR_SIZE + dst_size + == log_sys.trailer_offset()); + + uint dst_len; int rc = encryption_crypt( - buf + LOG_CRYPT_HDR_SIZE, sizeof dst, + buf + LOG_CRYPT_HDR_SIZE, dst_size, reinterpret_cast<byte*>(dst), &dst_len, const_cast<byte*>(info.crypt_key.bytes), sizeof info.crypt_key, reinterpret_cast<byte*>(aes_ctr_iv), sizeof aes_ctr_iv, - decrypt + op == LOG_DECRYPT ? ENCRYPTION_FLAG_DECRYPT | ENCRYPTION_FLAG_NOPAD : ENCRYPTION_FLAG_ENCRYPT | ENCRYPTION_FLAG_NOPAD, LOG_DEFAULT_ENCRYPTION_KEY, info.key_version); - ut_a(rc == MY_AES_OK); - ut_a(dst_len == sizeof dst); - memcpy(buf + LOG_CRYPT_HDR_SIZE, dst, sizeof dst); - } -} - -/** Generate crypt key from crypt msg. -@param[in,out] info encryption key -@param[in] upgrade whether to use the key in MariaDB 10.1 format -@return whether the operation was successful */ -static bool init_crypt_key(crypt_info_t* info, bool upgrade = false) -{ - byte mysqld_key[MY_AES_MAX_KEY_LENGTH]; - uint keylen = sizeof mysqld_key; - - compile_time_assert(16 == sizeof info->crypt_key); - - if (uint rc = encryption_key_get(LOG_DEFAULT_ENCRYPTION_KEY, - info->key_version, mysqld_key, - &keylen)) { - ib::error() - << "Obtaining redo log encryption key version " - << info->key_version << " failed (" << rc - << "). Maybe the key or the required encryption " - "key management plugin was not found."; - return false; - } - - if (upgrade) { - while (keylen < sizeof mysqld_key) { - mysqld_key[keylen++] = 0; - } - } - - uint dst_len; - int err= my_aes_crypt(MY_AES_ECB, - ENCRYPTION_FLAG_NOPAD | ENCRYPTION_FLAG_ENCRYPT, - info->crypt_msg.bytes, sizeof info->crypt_msg, - info->crypt_key.bytes, &dst_len, - mysqld_key, keylen, NULL, 0); - - if (err != MY_AES_OK || dst_len != MY_AES_BLOCK_SIZE) { - ib::error() << "Getting redo log crypto key failed: err = " - << err << ", len = " << dst_len; - return false; + ut_a(dst_len == dst_size); + memcpy(buf + LOG_CRYPT_HDR_SIZE, dst, dst_size); } return true; diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 3119a110f74..9e05383bfc6 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -258,9 +258,9 @@ log_calculate_actual_len( { ut_ad(log_mutex_own()); + const ulint framing_size = log_sys.framing_size(); /* actual length stored per block */ - const ulint len_per_blk = OS_FILE_LOG_BLOCK_SIZE - - (LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE); + const ulint len_per_blk = OS_FILE_LOG_BLOCK_SIZE - framing_size; /* actual data length in last block already written */ ulint extra_len = (log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE); @@ -269,8 +269,7 @@ log_calculate_actual_len( extra_len -= LOG_BLOCK_HDR_SIZE; /* total extra length for block header and trailer */ - extra_len = ((len + extra_len) / len_per_blk) - * (LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE); + extra_len = ((len + extra_len) / len_per_blk) * framing_size; return(len + extra_len); } @@ -402,26 +401,24 @@ log_write_low( ulint str_len) /*!< in: string length */ { ulint len; - ulint data_len; - byte* log_block; ut_ad(log_mutex_own()); + const ulint trailer_offset = log_sys.trailer_offset(); part_loop: /* Calculate a part length */ - data_len = (log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE) + str_len; + ulint data_len = (log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE) + str_len; - if (data_len <= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { + if (data_len <= trailer_offset) { /* The string fits within the current log block */ len = str_len; } else { - data_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; + data_len = trailer_offset; - len = OS_FILE_LOG_BLOCK_SIZE - - (log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE) - - LOG_BLOCK_TRL_SIZE; + len = trailer_offset + - log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE; } memcpy(log_sys.buf + log_sys.buf_free, str, len); @@ -429,18 +426,18 @@ part_loop: str_len -= len; str = str + len; - log_block = static_cast<byte*>( + byte* log_block = static_cast<byte*>( ut_align_down(log_sys.buf + log_sys.buf_free, OS_FILE_LOG_BLOCK_SIZE)); log_block_set_data_len(log_block, data_len); - if (data_len == OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { + if (data_len == trailer_offset) { /* This block became full */ log_block_set_data_len(log_block, OS_FILE_LOG_BLOCK_SIZE); log_block_set_checkpoint_no(log_block, log_sys.next_checkpoint_no); - len += LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE; + len += log_sys.framing_size(); log_sys.lsn += len; @@ -668,8 +665,7 @@ void log_t::files::create(ulint n_files) this->n_files= n_files; format= srv_encrypt_log - ? LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED - : LOG_HEADER_FORMAT_CURRENT; + ? LOG_HEADER_FORMAT_ENC_10_4 : LOG_HEADER_FORMAT_10_4; subformat= 2; file_size= srv_log_file_size; lsn= LOG_START_LSN; @@ -702,8 +698,8 @@ log_file_header_flush( ut_ad(log_write_mutex_own()); ut_ad(!recv_no_log_write); ut_a(nth_file < log_sys.log.n_files); - ut_ad((log_sys.log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) - == LOG_HEADER_FORMAT_CURRENT); + ut_ad(log_sys.log.format == LOG_HEADER_FORMAT_10_4 + || log_sys.log.format == LOG_HEADER_FORMAT_ENC_10_4); buf = log_sys.log.file_header_bufs[nth_file]; @@ -940,11 +936,9 @@ wait and check if an already running write is covering the request. @param[in] lsn log sequence number that should be included in the redo log file write @param[in] flush_to_disk whether the written log should also -be flushed to the file system */ -void -log_write_up_to( - lsn_t lsn, - bool flush_to_disk) +be flushed to the file system +@param[in] rotate_key whether to rotate the encryption key */ +void log_write_up_to(lsn_t lsn, bool flush_to_disk, bool rotate_key) { #ifdef UNIV_DEBUG ulint loop_count = 0; @@ -953,6 +947,7 @@ log_write_up_to( lsn_t write_lsn; ut_ad(!srv_read_only_mode); + ut_ad(!rotate_key || flush_to_disk); if (recv_no_ibuf_operations) { /* Recovery is running and no operations on the log files are @@ -1097,7 +1092,8 @@ loop: if (log_sys.is_encrypted()) { log_crypt(write_buf + area_start, log_sys.write_lsn, - area_end - area_start); + area_end - area_start, + rotate_key ? LOG_ENCRYPT_ROTATE_KEY : LOG_ENCRYPT); } /* Do the write to the log files */ @@ -1505,7 +1501,7 @@ log_checkpoint( log_mutex_exit(); - log_write_up_to(flush_lsn, true); + log_write_up_to(flush_lsn, true, true); DBUG_EXECUTE_IF( "using_wa_checkpoint_middle", @@ -2080,13 +2076,9 @@ log_pad_current_log_block(void) /* We retrieve lsn only because otherwise gcc crashed on HP-UX */ lsn = log_reserve_and_open(OS_FILE_LOG_BLOCK_SIZE); - pad_length = OS_FILE_LOG_BLOCK_SIZE - - (log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE) - - LOG_BLOCK_TRL_SIZE; - if (pad_length - == (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE - - LOG_BLOCK_TRL_SIZE)) { - + pad_length = log_sys.trailer_offset() + - log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE; + if (pad_length == log_sys.payload_size()) { pad_length = 0; } diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index afcd9079480..23dfc4afa0f 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -52,7 +52,6 @@ Created 9/20/1997 Heikki Tuuri #include "trx0undo.h" #include "trx0rec.h" #include "fil0fil.h" -#include "row0trunc.h" #include "buf0rea.h" #include "srv0srv.h" #include "srv0start.h" @@ -201,10 +200,6 @@ corresponding to MLOG_INDEX_LOAD. */ void (*log_optimized_ddl_op)(ulint space_id); -/** Report backup-unfriendly TRUNCATE operation (with separate log file), -corresponding to MLOG_TRUNCATE. */ -void (*log_truncate)(); - /** Report an operation to create, delete, or rename a file during backup. @param[in] space_id tablespace identifier @param[in] flags tablespace flags (NULL if not create) @@ -813,21 +808,24 @@ loop: << log_block_get_checkpoint_no(buf) << " expected: " << crc << " found: " << cksum; +fail: end_lsn = *start_lsn; success = false; break; } - if (is_encrypted()) { - log_crypt(buf, *start_lsn, - OS_FILE_LOG_BLOCK_SIZE, true); + if (is_encrypted() + && !log_crypt(buf, *start_lsn, + OS_FILE_LOG_BLOCK_SIZE, + LOG_DECRYPT)) { + goto fail; } } ulint dl = log_block_get_data_len(buf); if (dl < LOG_BLOCK_HDR_SIZE - || (dl > OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE - && dl != OS_FILE_LOG_BLOCK_SIZE)) { + || (dl != OS_FILE_LOG_BLOCK_SIZE + && dl > log_sys.trailer_offset())) { recv_sys->found_corrupt_log = true; end_lsn = *start_lsn; break; @@ -1028,54 +1026,6 @@ static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt) return(DB_SUCCESS); } -/** Determine if a redo log from MariaDB 10.4 is clean. -@return error code -@retval DB_SUCCESS if the redo log is clean -@retval DB_CORRUPTION if the redo log is corrupted -@retval DB_ERROR if the redo log is not empty */ -static dberr_t recv_log_recover_10_4() -{ - ut_ad(!log_sys.is_encrypted()); - const lsn_t lsn = log_sys.log.lsn; - log_mutex_enter(); - const lsn_t source_offset = log_sys.log.calc_lsn_offset(lsn); - log_mutex_exit(); - const ulint page_no - = (ulint) (source_offset / univ_page_size.physical()); - byte* buf = log_sys.buf; - - fil_io(IORequestLogRead, true, - page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no), - univ_page_size, - (ulint) ((source_offset & ~(OS_FILE_LOG_BLOCK_SIZE - 1)) - % univ_page_size.physical()), - OS_FILE_LOG_BLOCK_SIZE, buf, NULL); - - if (log_block_calc_checksum(buf) != log_block_get_checksum(buf)) { - return DB_CORRUPTION; - } - - /* On a clean shutdown, the redo log will be logically empty - after the checkpoint lsn. */ - - if (log_block_get_data_len(buf) - != (source_offset & (OS_FILE_LOG_BLOCK_SIZE - 1))) { - return DB_ERROR; - } - - /* Mark the redo log for downgrading. */ - srv_log_file_size = 0; - recv_sys->parse_start_lsn = recv_sys->recovered_lsn - = recv_sys->scanned_lsn - = recv_sys->mlog_checkpoint_lsn = lsn; - log_sys.last_checkpoint_lsn = log_sys.next_checkpoint_lsn - = log_sys.lsn = log_sys.write_lsn - = log_sys.current_flush_lsn = log_sys.flushed_to_disk_lsn - = lsn; - log_sys.next_checkpoint_no = 0; - return DB_SUCCESS; -} - /** Find the latest checkpoint in the log header. @param[out] max_field LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2 @return error code or DB_SUCCESS */ @@ -1116,11 +1066,10 @@ recv_find_max_checkpoint(ulint* max_field) return(recv_find_max_checkpoint_0(max_field)); case LOG_HEADER_FORMAT_10_2: case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED: - case LOG_HEADER_FORMAT_CURRENT: - case LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED: + case LOG_HEADER_FORMAT_10_3: + case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: case LOG_HEADER_FORMAT_10_4: - /* We can only parse the unencrypted LOG_HEADER_FORMAT_10_4. - The encrypted format uses a larger redo log block trailer. */ + case LOG_HEADER_FORMAT_10_4 | LOG_HEADER_FORMAT_ENCRYPTED: break; default: ib::error() << "Unsupported redo log format." @@ -1185,19 +1134,7 @@ recv_find_max_checkpoint(ulint* max_field) return(DB_ERROR); } - if (log_sys.log.format == LOG_HEADER_FORMAT_10_4) { - dberr_t err = recv_log_recover_10_4(); - if (err != DB_SUCCESS) { - ib::error() - << "Downgrade after a crash is not supported." - " The redo log was created with " << creator - << (err == DB_ERROR - ? "." : ", and it appears corrupted."); - } - return err; - } - - return DB_SUCCESS; + return(DB_SUCCESS); } /** Try to parse a single log record body and also applies it if @@ -1245,14 +1182,10 @@ recv_parse_or_apply_log_rec_body( } return(ptr + 8); case MLOG_TRUNCATE: - if (log_truncate) { - ut_ad(srv_operation != SRV_OPERATION_NORMAL); - log_truncate(); - recv_sys->found_corrupt_fs = true; - return NULL; - } - return(truncate_t::parse_redo_entry(ptr, end_ptr, space_id)); - + ib::error() << "Cannot crash-upgrade from " + "old-style TRUNCATE TABLE"; + recv_sys->found_corrupt_log = true; + return NULL; default: break; } @@ -1306,6 +1239,7 @@ parse_log: break; #endif /* UNIV_LOG_LSN_DEBUG */ case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES: + case MLOG_MEMSET: #ifdef UNIV_DEBUG if (page && page_type == FIL_PAGE_TYPE_ALLOCATED && end_ptr >= ptr + 2) { @@ -1835,13 +1769,10 @@ recv_recover_page(bool just_read_in, buf_block_t* block) page_t* page; page_zip_des_t* page_zip; recv_addr_t* recv_addr; - recv_t* recv; - byte* buf; lsn_t start_lsn; lsn_t end_lsn; lsn_t page_lsn; lsn_t page_newest_lsn; - ibool modification_to_page; mtr_t mtr; mutex_enter(&(recv_sys->mutex)); @@ -1916,57 +1847,19 @@ recv_recover_page(bool just_read_in, buf_block_t* block) page_lsn = page_newest_lsn; } - modification_to_page = FALSE; start_lsn = end_lsn = 0; - recv = UT_LIST_GET_FIRST(recv_addr->rec_list); fil_space_t* space = fil_space_acquire(block->page.id.space()); - while (recv) { + for (recv_t* recv = UT_LIST_GET_FIRST(recv_addr->rec_list); + recv; recv = UT_LIST_GET_NEXT(rec_list, recv)) { end_lsn = recv->end_lsn; ut_ad(end_lsn <= log_sys.log.scanned_lsn); - if (recv->len > RECV_DATA_BLOCK_SIZE) { - /* We have to copy the record body to a separate - buffer */ - - buf = static_cast<byte*>(ut_malloc_nokey(recv->len)); - - recv_data_copy_to_buf(buf, recv); - } else { - buf = ((byte*)(recv->data)) + sizeof(recv_data_t); - } - - /* If per-table tablespace was truncated and there exist REDO - records before truncate that are to be applied as part of - recovery (checkpoint didn't happen since truncate was done) - skip such records using lsn check as they may not stand valid - post truncate. - LSN at start of truncate is recorded and any redo record - with LSN less than recorded LSN is skipped. - Note: We can't skip complete recv_addr as same page may have - valid REDO records post truncate those needs to be applied. */ - - /* Ignore applying the redo logs for tablespace that is - truncated. Post recovery there is fixup action that will - restore the tablespace back to normal state. - Applying redo at this stage can result in error given that - redo will have action recorded on page before tablespace - was re-inited and that would lead to an error while applying - such action. */ - if (recv->start_lsn >= page_lsn - && !srv_is_tablespace_truncated(space->id) - && !(srv_was_tablespace_truncated(space) - && recv->start_lsn - < truncate_t::get_truncated_tablespace_init_lsn( - space->id))) { - - lsn_t end_lsn; - - if (!modification_to_page) { - - modification_to_page = TRUE; + ut_ad(recv->start_lsn); + if (recv->start_lsn >= page_lsn) { + if (!start_lsn) { start_lsn = recv->start_lsn; } @@ -1982,29 +1875,41 @@ recv_recover_page(bool just_read_in, buf_block_t* block) << " len " << recv->len << " page " << block->page.id); + byte* buf; + + if (recv->len > RECV_DATA_BLOCK_SIZE) { + /* We have to copy the record body to + a separate buffer */ + + buf = static_cast<byte*>(ut_malloc_nokey( + recv->len)); + + recv_data_copy_to_buf(buf, recv); + } else { + buf = reinterpret_cast<byte*>(recv->data) + + sizeof *recv->data; + } + recv_parse_or_apply_log_rec_body( recv->type, buf, buf + recv->len, block->page.id.space(), - block->page.id.page_no(), - true, block, &mtr); + block->page.id.page_no(), true, block, &mtr); - end_lsn = recv->start_lsn + recv->len; + lsn_t end_lsn = recv->start_lsn + recv->len; mach_write_to_8(FIL_PAGE_LSN + page, end_lsn); mach_write_to_8(srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM + page, end_lsn); if (page_zip) { - mach_write_to_8(FIL_PAGE_LSN - + page_zip->data, end_lsn); + mach_write_to_8(FIL_PAGE_LSN + page_zip->data, + end_lsn); } - } - if (recv->len > RECV_DATA_BLOCK_SIZE) { - ut_free(buf); + if (recv->len > RECV_DATA_BLOCK_SIZE) { + ut_free(buf); + } } - - recv = UT_LIST_GET_NEXT(rec_list, recv); } space->release(); @@ -2018,9 +1923,7 @@ recv_recover_page(bool just_read_in, buf_block_t* block) } #endif /* UNIV_ZIP_DEBUG */ - if (modification_to_page) { - ut_a(block); - + if (start_lsn) { log_flush_order_mutex_enter(); buf_flush_recv_note_modification(block, start_lsn, end_lsn); log_flush_order_mutex_exit(); @@ -2131,6 +2034,17 @@ void recv_apply_hashed_log_recs(bool last_batch) ut_d(recv_no_log_write = recv_no_ibuf_operations); if (ulint n = recv_sys->n_addrs) { + if (!log_sys.log.subformat && !srv_force_recovery + && srv_undo_tablespaces_open) { + ib::error() << "Recovery of separately logged" + " TRUNCATE operations is no longer supported." + " Set innodb_force_recovery=1" + " if no *trunc.log files exist"; + recv_sys->found_corrupt_log = true; + mutex_exit(&recv_sys->mutex); + return; + } + const char* msg = last_batch ? "Starting final batch to recover " : "Starting a batch to recover "; @@ -2156,15 +2070,6 @@ void recv_apply_hashed_log_recs(bool last_batch) recv_addr = static_cast<recv_addr_t*>( HASH_GET_NEXT(addr_hash, recv_addr))) { - if (srv_is_tablespace_truncated(recv_addr->space)) { - /* Avoid applying REDO log for the tablespace - that is schedule for TRUNCATE. */ - ut_a(recv_sys->n_addrs); - recv_addr->state = RECV_DISCARDED; - recv_sys->n_addrs--; - continue; - } - if (recv_addr->state == RECV_DISCARDED || !UT_LIST_GET_LEN(recv_addr->rec_list)) { ut_a(recv_sys->n_addrs); @@ -2364,17 +2269,12 @@ recv_calc_lsn_on_data_add( ib_uint64_t len) /*!< in: this many bytes of data is added, log block headers not included */ { - ulint frag_len; - ib_uint64_t lsn_len; - - frag_len = (lsn % OS_FILE_LOG_BLOCK_SIZE) - LOG_BLOCK_HDR_SIZE; - ut_ad(frag_len < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE - - LOG_BLOCK_TRL_SIZE); - lsn_len = len; - lsn_len += (lsn_len + frag_len) - / (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE - - LOG_BLOCK_TRL_SIZE) - * (LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE); + unsigned frag_len = (lsn % OS_FILE_LOG_BLOCK_SIZE) - LOG_BLOCK_HDR_SIZE; + unsigned payload_size = log_sys.payload_size(); + ut_ad(frag_len < payload_size); + lsn_t lsn_len = len; + lsn_len += (lsn_len + frag_len) / payload_size + * (OS_FILE_LOG_BLOCK_SIZE - payload_size); return(lsn + lsn_len); } @@ -2833,11 +2733,7 @@ bool recv_sys_add_to_parsing_buf(const byte* log_block, lsn_t scanned_lsn) start_offset = LOG_BLOCK_HDR_SIZE; } - end_offset = data_len; - - if (end_offset > OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) { - end_offset = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; - } + end_offset = std::min<ulint>(data_len, log_sys.trailer_offset()); ut_ad(start_offset <= end_offset); @@ -3936,6 +3832,9 @@ static const char* get_mlog_string(mlog_id_t type) case MLOG_TRUNCATE: return("MLOG_TRUNCATE"); + case MLOG_MEMSET: + return("MLOG_MEMSET"); + case MLOG_FILE_WRITE_CRYPT_DATA: return("MLOG_FILE_WRITE_CRYPT_DATA"); } diff --git a/storage/innobase/mtr/mtr0log.cc b/storage/innobase/mtr/mtr0log.cc index 6baf1f06bf9..c9a6de8c902 100644 --- a/storage/innobase/mtr/mtr0log.cc +++ b/storage/innobase/mtr/mtr0log.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -121,7 +121,7 @@ mlog_parse_initial_log_record( } /********************************************************//** -Parses a log record written by mlog_write_ulint or mlog_write_ull. +Parses a log record written by mlog_write_ulint, mlog_write_ull, mlog_memset. @return parsed record end, NULL if not a complete record or a corrupt record */ byte* mlog_parse_nbytes( @@ -137,29 +137,43 @@ mlog_parse_nbytes( ulint val; ib_uint64_t dval; - ut_a(type <= MLOG_8BYTES); + ut_ad(type <= MLOG_8BYTES || type == MLOG_MEMSET); ut_a(!page || !page_zip || !fil_page_index_page_check(page)); if (end_ptr < ptr + 2) { - - return(NULL); + return NULL; } offset = mach_read_from_2(ptr); ptr += 2; - if (offset >= srv_page_size) { - recv_sys->found_corrupt_log = TRUE; - - return(NULL); + if (UNIV_UNLIKELY(offset >= srv_page_size)) { + goto corrupt; } - if (type == MLOG_8BYTES) { + switch (type) { + case MLOG_MEMSET: + if (end_ptr < ptr + 3) { + return NULL; + } + val = mach_read_from_2(ptr); + ptr += 2; + if (UNIV_UNLIKELY(offset + val > srv_page_size)) { + goto corrupt; + } + if (page) { + memset(page + offset, *ptr, val); + if (page_zip) { + memset(static_cast<page_zip_des_t*>(page_zip) + ->data + offset, *ptr, val); + } + } + return const_cast<byte*>(++ptr); + case MLOG_8BYTES: dval = mach_u64_parse_compressed(&ptr, end_ptr); if (ptr == NULL) { - - return(NULL); + return NULL; } if (page) { @@ -171,14 +185,13 @@ mlog_parse_nbytes( mach_write_to_8(page + offset, dval); } - return(const_cast<byte*>(ptr)); + return const_cast<byte*>(ptr); + default: + val = mach_parse_compressed(&ptr, end_ptr); } - val = mach_parse_compressed(&ptr, end_ptr); - if (ptr == NULL) { - - return(NULL); + return NULL; } switch (type) { @@ -221,11 +234,11 @@ mlog_parse_nbytes( break; default: corrupt: - recv_sys->found_corrupt_log = TRUE; + recv_sys->found_corrupt_log = true; ptr = NULL; } - return(const_cast<byte*>(ptr)); + return const_cast<byte*>(ptr); } /********************************************************//** @@ -409,6 +422,72 @@ mlog_parse_string( return(ptr + len); } +/** Initialize a string of bytes. +@param[in,out] b buffer page +@param[in] ofs byte offset from block->frame +@param[in] len length of the data to write +@param[in] val the data byte to write +@param[in,out] mtr mini-transaction */ +void +mlog_memset(buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr) +{ + ut_ad(len); + ut_ad(ofs <= ulint(srv_page_size)); + ut_ad(ofs + len <= ulint(srv_page_size)); + memset(ofs + b->frame, val, len); + + mtr->set_modified(); + switch (mtr->get_log_mode()) { + case MTR_LOG_NONE: + case MTR_LOG_NO_REDO: + return; + case MTR_LOG_SHORT_INSERTS: + ut_ad(0); + /* fall through */ + case MTR_LOG_ALL: + break; + } + + byte* l = mtr->get_log()->open(11 + 2 + 2 + 1); + l = mlog_write_initial_log_record_low( + MLOG_MEMSET, b->page.id.space(), b->page.id.page_no(), l, mtr); + mach_write_to_2(l, ofs); + mach_write_to_2(l + 2, len); + l[4] = val; + mlog_close(mtr, l + 5); +} + +/** Initialize a string of bytes. +@param[in,out] byte byte address +@param[in] len length of the data to write +@param[in] val the data byte to write +@param[in,out] mtr mini-transaction */ +void mlog_memset(byte* b, ulint len, byte val, mtr_t* mtr) +{ + ut_ad(len); + ut_ad(page_offset(b) + len <= ulint(srv_page_size)); + memset(b, val, len); + + mtr->set_modified(); + switch (mtr->get_log_mode()) { + case MTR_LOG_NONE: + case MTR_LOG_NO_REDO: + return; + case MTR_LOG_SHORT_INSERTS: + ut_ad(0); + /* fall through */ + case MTR_LOG_ALL: + break; + } + + byte* l = mtr->get_log()->open(11 + 2 + 2 + 1); + l = mlog_write_initial_log_record_fast(b, MLOG_MEMSET, l, mtr); + mach_write_to_2(l, page_offset(b)); + mach_write_to_2(l + 2, len); + l[4] = val; + mlog_close(mtr, l + 5); +} + /********************************************************//** Opens a buffer for mlog, writes the initial log record and, if needed, the field lengths of an index. diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 92b1aa38a81..3084ba387fb 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -28,10 +28,10 @@ Created 11/26/1995 Heikki Tuuri #include "buf0buf.h" #include "buf0flu.h" +#include "fsp0sysspace.h" #include "page0types.h" #include "mtr0log.h" #include "log0log.h" -#include "row0trunc.h" #include "log0recv.h" @@ -677,8 +677,7 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line) ut_ad(get_log_mode() != MTR_LOG_NO_REDO || space->purpose == FIL_TYPE_TEMPORARY || space->purpose == FIL_TYPE_IMPORT - || my_atomic_loadlint(&space->redo_skipped_count) > 0 - || srv_is_tablespace_truncated(space->id)); + || my_atomic_loadlint(&space->redo_skipped_count) > 0); } ut_ad(space); diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index b4775d19e1d..25b2d202168 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -735,7 +735,7 @@ up_slot_match: & REC_INFO_MIN_REC_FLAG)) { ut_ad(!page_has_prev(page_align(mid_rec))); ut_ad(!page_rec_is_leaf(mid_rec) - || rec_is_metadata(mid_rec, index)); + || rec_is_metadata(mid_rec, *index)); cmp = 1; goto low_rec_match; } @@ -1368,7 +1368,7 @@ use_heap: switch (rec_get_status(current_rec)) { case REC_STATUS_ORDINARY: case REC_STATUS_NODE_PTR: - case REC_STATUS_COLUMNS_ADDED: + case REC_STATUS_INSTANT: case REC_STATUS_INFIMUM: break; case REC_STATUS_SUPREMUM: @@ -1377,7 +1377,7 @@ use_heap: switch (rec_get_status(insert_rec)) { case REC_STATUS_ORDINARY: case REC_STATUS_NODE_PTR: - case REC_STATUS_COLUMNS_ADDED: + case REC_STATUS_INSTANT: break; case REC_STATUS_INFIMUM: case REC_STATUS_SUPREMUM: @@ -1564,7 +1564,7 @@ page_cur_insert_rec_zip( get rid of the modification log. */ page_create_zip(page_cur_get_block(cursor), index, page_header_get_field(page, PAGE_LEVEL), - 0, NULL, mtr); + 0, mtr); ut_ad(!page_header_get_ptr(page, PAGE_FREE)); if (page_zip_available( @@ -1639,7 +1639,7 @@ page_cur_insert_rec_zip( if (!log_compressed) { if (page_zip_compress( page_zip, page, index, - level, NULL, NULL)) { + level, NULL)) { page_cur_insert_rec_write_log( insert_rec, rec_size, cursor->rec, index, mtr); @@ -1785,17 +1785,11 @@ too_small: columns of free_rec, in case it will not be overwritten by insert_rec. */ - ulint trx_id_col; ulint trx_id_offs; ulint len; - trx_id_col = dict_index_get_sys_col_pos(index, - DATA_TRX_ID); - ut_ad(trx_id_col > 0); - ut_ad(trx_id_col != ULINT_UNDEFINED); - - trx_id_offs = rec_get_nth_field_offs(foffsets, - trx_id_col, &len); + trx_id_offs = rec_get_nth_field_offs( + foffsets, index->db_trx_id(), &len); ut_ad(len == DATA_TRX_ID_LEN); if (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN + trx_id_offs @@ -1811,7 +1805,7 @@ too_small: ut_ad(free_rec + trx_id_offs + DATA_TRX_ID_LEN == rec_get_nth_field(free_rec, foffsets, - trx_id_col + 1, &len)); + index->db_roll_ptr(), &len)); ut_ad(len == DATA_ROLL_PTR_LEN); } diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index f56d944697f..b93773197c9 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -29,8 +29,8 @@ Created 2/2/1994 Heikki Tuuri #include "page0cur.h" #include "page0zip.h" #include "buf0buf.h" +#include "buf0checksum.h" #include "btr0btr.h" -#include "row0trunc.h" #include "srv0srv.h" #include "lock0lock.h" #include "fut0lst.h" @@ -454,22 +454,15 @@ page_create_zip( ulint level, /*!< in: the B-tree level of the page */ trx_id_t max_trx_id, /*!< in: PAGE_MAX_TRX_ID */ - const redo_page_compress_t* page_comp_info, - /*!< in: used for applying - TRUNCATE log - record during recovery */ mtr_t* mtr) /*!< in/out: mini-transaction handle */ { page_t* page; page_zip_des_t* page_zip = buf_block_get_page_zip(block); - bool is_spatial; ut_ad(block); ut_ad(page_zip); - ut_ad(index == NULL || dict_table_is_comp(index->table)); - is_spatial = index ? dict_index_is_spatial(index) - : page_comp_info->type & DICT_SPATIAL; + ut_ad(dict_table_is_comp(index->table)); /* PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC are always 0 for temporary tables. */ @@ -487,22 +480,11 @@ page_create_zip( || !dict_index_is_sec_or_ibuf(index) || index->table->is_temporary()); - page = page_create_low(block, TRUE, is_spatial); + page = page_create_low(block, TRUE, dict_index_is_spatial(index)); mach_write_to_2(PAGE_HEADER + PAGE_LEVEL + page, level); mach_write_to_8(PAGE_HEADER + PAGE_MAX_TRX_ID + page, max_trx_id); - if (truncate_t::s_fix_up_active) { - /* Compress the index page created when applying - TRUNCATE log during recovery */ - if (!page_zip_compress(page_zip, page, index, page_zip_level, - page_comp_info, NULL)) { - /* The compression of a newly created - page should always succeed. */ - ut_error; - } - - } else if (!page_zip_compress(page_zip, page, index, - page_zip_level, NULL, mtr)) { + if (!page_zip_compress(page_zip, page, index, page_zip_level, mtr)) { /* The compression of a newly created page should always succeed. */ ut_error; @@ -546,7 +528,7 @@ page_create_empty( ut_ad(!index->table->is_temporary()); page_create_zip(block, index, page_header_get_field(page, PAGE_LEVEL), - max_trx_id, NULL, mtr); + max_trx_id, mtr); } else { page_create(block, mtr, page_is_comp(page), dict_index_is_spatial(index)); @@ -721,11 +703,8 @@ page_copy_rec_list_end( if (new_page_zip) { mtr_set_log_mode(mtr, log_mode); - if (!page_zip_compress(new_page_zip, - new_page, - index, - page_zip_level, - NULL, mtr)) { + if (!page_zip_compress(new_page_zip, new_page, index, + page_zip_level, mtr)) { /* Before trying to reorganize the page, store the number of preceding records on the page. */ ulint ret_pos @@ -887,7 +866,7 @@ page_copy_rec_list_start( goto zip_reorganize;); if (!page_zip_compress(new_page_zip, new_page, index, - page_zip_level, NULL, mtr)) { + page_zip_level, mtr)) { ulint ret_pos; #ifndef DBUG_OFF zip_reorganize: @@ -1826,6 +1805,7 @@ page_print_list( count = 0; for (;;) { offsets = rec_get_offsets(cur.rec, index, offsets, + page_rec_is_leaf(cur.rec), ULINT_UNDEFINED, &heap); page_rec_print(cur.rec, offsets); @@ -1848,6 +1828,7 @@ page_print_list( if (count + pr_n >= n_recs) { offsets = rec_get_offsets(cur.rec, index, offsets, + page_rec_is_leaf(cur.rec), ULINT_UNDEFINED, &heap); page_rec_print(cur.rec, offsets); } diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 05889b617bc..96f5603853b 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -25,39 +25,31 @@ Compressed page interface Created June 2005 by Marko Makela *******************************************************/ -#include "page0size.h" #include "page0zip.h" +#include "page0size.h" +#include "page0page.h" +#include "buf0checksum.h" /** A BLOB field reference full of zero, for use in assertions and tests. Initially, BLOB field references are set to zero, in dtuple_convert_big_rec(). */ -const byte field_ref_zero[FIELD_REF_SIZE] = { - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -}; +const byte field_ref_zero[UNIV_PAGE_SIZE_MAX] = { 0, }; + +#include "ut0crc32.h" +#include "zlib.h" #ifndef UNIV_INNOCHECKSUM -#include "page0page.h" #include "mtr0log.h" #include "dict0dict.h" #include "btr0cur.h" -#include "page0types.h" #include "log0recv.h" #include "row0row.h" -#include "row0trunc.h" -#include "zlib.h" -#include "buf0buf.h" -#include "buf0types.h" -#include "buf0checksum.h" #include "btr0sea.h" #include "dict0boot.h" #include "lock0lock.h" #include "srv0srv.h" #include "buf0lru.h" #include "srv0mon.h" -#include "ut0crc32.h" #include <map> #include <algorithm> @@ -106,11 +98,11 @@ Compare at most sizeof(field_ref_zero) bytes. @param s in: size of the memory block, in bytes */ #define ASSERT_ZERO(b, s) \ ut_ad(!memcmp(b, field_ref_zero, \ - ut_min(static_cast<size_t>(s), sizeof field_ref_zero))); + std::min<size_t>(s, sizeof field_ref_zero))); /** Assert that a BLOB pointer is filled with zero bytes. @param b in: BLOB pointer */ #define ASSERT_ZERO_BLOB(b) \ - ut_ad(!memcmp(b, field_ref_zero, sizeof field_ref_zero)) + ut_ad(!memcmp(b, field_ref_zero, FIELD_REF_SIZE)) /* Enable some extra debugging output. This code can be enabled independently of any UNIV_ debugging conditions. */ @@ -1248,17 +1240,11 @@ page_zip_compress( dict_index_t* index, /*!< in: index of the B-tree node */ ulint level, /*!< in: commpression level */ - const redo_page_compress_t* page_comp_info, - /*!< in: used for applying - TRUNCATE log - record during recovery */ mtr_t* mtr) /*!< in/out: mini-transaction, or NULL */ { z_stream c_stream; int err; - ulint n_fields; /* number of index fields - needed */ byte* fields; /*!< index field information */ byte* buf; /*!< compressed payload of the page */ @@ -1273,7 +1259,6 @@ page_zip_compress( ulint n_blobs = 0; byte* storage; /* storage of uncompressed columns */ - index_id_t ind_id; uintmax_t usec = ut_time_us(NULL); #ifdef PAGE_ZIP_COMPRESS_DBG FILE* logfile = NULL; @@ -1288,10 +1273,8 @@ page_zip_compress( ut_a(fil_page_index_page_check(page)); ut_ad(page_simple_validate_new((page_t*) page)); ut_ad(page_zip_simple_validate(page_zip)); - ut_ad(!index - || (index - && dict_table_is_comp(index->table) - && !dict_index_is_ibuf(index))); + ut_ad(dict_table_is_comp(index->table)); + ut_ad(!dict_index_is_ibuf(index)); UNIV_MEM_ASSERT_RW(page, srv_page_size); @@ -1311,18 +1294,10 @@ page_zip_compress( == PAGE_NEW_SUPREMUM); } - if (truncate_t::s_fix_up_active) { - ut_ad(page_comp_info != NULL); - n_fields = page_comp_info->n_fields; - ind_id = page_comp_info->index_id; - } else { - if (page_is_leaf(page)) { - n_fields = dict_index_get_n_fields(index); - } else { - n_fields = dict_index_get_n_unique_in_tree_nonleaf(index); - } - ind_id = index->id; - } + const ulint n_fields = page_is_leaf(page) + ? dict_index_get_n_fields(index) + : dict_index_get_n_unique_in_tree_nonleaf(index); + index_id_t ind_id = index->id; /* The dense directory excludes the infimum and supremum records. */ n_dense = ulint(page_dir_get_n_heap(page)) - PAGE_HEAP_NO_USER_LOW; @@ -1433,20 +1408,8 @@ page_zip_compress( /* Dense page directory and uncompressed columns, if any */ if (page_is_leaf(page)) { - if ((index && dict_index_is_clust(index)) - || (page_comp_info - && (page_comp_info->type & DICT_CLUSTERED))) { - - if (index) { - trx_id_col = dict_index_get_sys_col_pos( - index, DATA_TRX_ID); - ut_ad(trx_id_col > 0); - ut_ad(trx_id_col != ULINT_UNDEFINED); - } else if (page_comp_info - && (page_comp_info->type - & DICT_CLUSTERED)) { - trx_id_col = page_comp_info->trx_id_pos; - } + if (dict_index_is_clust(index)) { + trx_id_col = index->db_trx_id(); slot_size = PAGE_ZIP_DIR_SLOT_SIZE + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN; @@ -1454,10 +1417,6 @@ page_zip_compress( } else { /* Signal the absence of trx_id in page_zip_fields_encode() */ - if (index) { - ut_ad(dict_index_get_sys_col_pos( - index, DATA_TRX_ID) == ULINT_UNDEFINED); - } trx_id_col = 0; slot_size = PAGE_ZIP_DIR_SLOT_SIZE; } @@ -1471,19 +1430,9 @@ page_zip_compress( goto zlib_error; } - c_stream.avail_out -= static_cast<uInt>(n_dense * slot_size); - if (truncate_t::s_fix_up_active) { - ut_ad(page_comp_info != NULL); - c_stream.avail_in = static_cast<uInt>( - page_comp_info->field_len); - for (ulint i = 0; i < page_comp_info->field_len; i++) { - fields[i] = page_comp_info->fields[i]; - } - } else { - c_stream.avail_in = static_cast<uInt>( - page_zip_fields_encode( - n_fields, index, trx_id_col, fields)); - } + c_stream.avail_out -= uInt(n_dense * slot_size); + c_stream.avail_in = uInt(page_zip_fields_encode(n_fields, index, + trx_id_col, fields)); c_stream.next_in = fields; if (UNIV_LIKELY(!trx_id_col)) { @@ -1637,7 +1586,7 @@ err_exit: mutex_exit(&page_zip_stat_per_index_mutex); } - if (page_is_leaf(page) && !truncate_t::s_fix_up_active) { + if (page_is_leaf(page)) { dict_index_zip_success(index); } @@ -2169,6 +2118,10 @@ page_zip_apply_log( rec_get_offsets_reverse(data, index, hs & REC_STATUS_NODE_PTR, offsets); + /* Silence a debug assertion in rec_offs_make_valid(). + This will be overwritten in page_zip_set_extra_bytes(), + called by page_zip_decompress_low(). */ + ut_d(rec[-REC_NEW_INFO_BITS] = 0); rec_offs_make_valid(rec, index, is_leaf, offsets); /* Copy the extra bytes (backwards). */ @@ -3770,29 +3723,25 @@ page_zip_write_rec( ulint len; if (dict_index_is_clust(index)) { - ulint trx_id_col; - - trx_id_col = dict_index_get_sys_col_pos(index, - DATA_TRX_ID); - ut_ad(trx_id_col != ULINT_UNDEFINED); - /* Store separately trx_id, roll_ptr and the BTR_EXTERN_FIELD_REF of each BLOB column. */ if (rec_offs_any_extern(offsets)) { data = page_zip_write_rec_ext( page_zip, page, rec, index, offsets, create, - trx_id_col, heap_no, storage, data); + index->db_trx_id(), heap_no, + storage, data); } else { /* Locate trx_id and roll_ptr. */ const byte* src = rec_get_nth_field(rec, offsets, - trx_id_col, &len); + index->db_trx_id(), + &len); ut_ad(len == DATA_TRX_ID_LEN); ut_ad(src + DATA_TRX_ID_LEN == rec_get_nth_field( rec, offsets, - trx_id_col + 1, &len)); + index->db_roll_ptr(), &len)); ut_ad(len == DATA_ROLL_PTR_LEN); /* Log the preceding fields. */ @@ -3820,8 +3769,6 @@ page_zip_write_rec( } else { /* Leaf page of a secondary index: no externally stored columns */ - ut_ad(dict_index_get_sys_col_pos(index, DATA_TRX_ID) - == ULINT_UNDEFINED); ut_ad(!rec_offs_any_extern(offsets)); /* Log the entire record. */ @@ -4807,9 +4754,7 @@ page_zip_reorganize( /* Restore logging. */ mtr_set_log_mode(mtr, log_mode); - if (!page_zip_compress(page_zip, page, index, - page_zip_level, NULL, mtr)) { - + if (!page_zip_compress(page_zip, page, index, page_zip_level, mtr)) { buf_block_free(temp_block); return(FALSE); } @@ -4985,12 +4930,7 @@ uint32_t page_zip_calc_checksum( const void* data, ulint size, - srv_checksum_algorithm_t algo -#ifdef INNODB_BUG_ENDIAN_CRC32 - /** for crc32, use the big-endian bug-compatible crc32 variant */ - , bool use_legacy_big_endian -#endif -) + srv_checksum_algorithm_t algo) { uLong adler; const Bytef* s = static_cast<const byte*>(data); @@ -5002,19 +4942,6 @@ page_zip_calc_checksum( case SRV_CHECKSUM_ALGORITHM_CRC32: case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: ut_ad(size > FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); -#ifdef INNODB_BUG_ENDIAN_CRC32 - if (use_legacy_big_endian) { - return ut_crc32_legacy_big_endian(s + FIL_PAGE_OFFSET, - FIL_PAGE_LSN - - FIL_PAGE_OFFSET) - ^ ut_crc32_legacy_big_endian( - s + FIL_PAGE_TYPE, 2) - ^ ut_crc32_legacy_big_endian( - s + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, - size - - FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - } -#endif return ut_crc32(s + FIL_PAGE_OFFSET, FIL_PAGE_LSN - FIL_PAGE_OFFSET) ^ ut_crc32(s + FIL_PAGE_TYPE, 2) @@ -5132,11 +5059,6 @@ page_zip_verify_checksum( switch (curr_algo) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: -#ifdef INNODB_BUG_ENDIAN_CRC32 - return stored == page_zip_calc_checksum(data, size, curr_algo, - true); -#endif - /* fall through */ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: case SRV_CHECKSUM_ALGORITHM_STRICT_NONE: return FALSE; @@ -5145,26 +5067,15 @@ page_zip_verify_checksum( return(TRUE); } - return -#ifdef INNODB_BUG_ENDIAN_CRC32 - stored == page_zip_calc_checksum(data, size, curr_algo, - true) || -#endif - stored == page_zip_calc_checksum( - data, size, SRV_CHECKSUM_ALGORITHM_INNODB); + return stored == page_zip_calc_checksum( + data, size, SRV_CHECKSUM_ALGORITHM_INNODB); case SRV_CHECKSUM_ALGORITHM_INNODB: if (stored == BUF_NO_CHECKSUM_MAGIC) { return TRUE; } return stored == page_zip_calc_checksum( - data, size, SRV_CHECKSUM_ALGORITHM_CRC32) -#ifdef INNODB_BUG_ENDIAN_CRC32 - || stored == page_zip_calc_checksum( - data, size, - SRV_CHECKSUM_ALGORITHM_CRC32, true) -#endif - ; + data, size, SRV_CHECKSUM_ALGORITHM_CRC32); case SRV_CHECKSUM_ALGORITHM_NONE: return TRUE; } diff --git a/storage/innobase/rem/rem0cmp.cc b/storage/innobase/rem/rem0cmp.cc index 6b914c46ecf..623d0bd1aa9 100644 --- a/storage/innobase/rem/rem0cmp.cc +++ b/storage/innobase/rem/rem0cmp.cc @@ -797,7 +797,7 @@ cmp_dtuple_rec_with_match_bytes( & rec_get_info_bits(rec, rec_offs_comp(offsets)))) { ut_ad(page_rec_is_first(rec, page_align(rec))); ut_ad(!page_has_prev(page_align(rec))); - ut_ad(rec_is_metadata(rec, index)); + ut_ad(rec_is_metadata(rec, *index)); return 1; } diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 495c29e4805..19764318c1a 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -169,7 +169,7 @@ rec_get_n_extern_new( ut_ad(!index->table->supports_instant() || index->is_dummy); ut_ad(!index->is_instant()); ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY - || rec_get_status(rec) == REC_STATUS_COLUMNS_ADDED); + || rec_get_status(rec) == REC_STATUS_INSTANT); ut_ad(n == ULINT_UNDEFINED || n <= dict_index_get_n_fields(index)); if (n == ULINT_UNDEFINED) { @@ -231,8 +231,8 @@ rec_get_n_extern_new( return(n_extern); } -/** Get the added field count in a REC_STATUS_COLUMNS_ADDED record. -@param[in,out] header variable header of a REC_STATUS_COLUMNS_ADDED record +/** Get the added field count in a REC_STATUS_INSTANT record. +@param[in,out] header variable header of a REC_STATUS_INSTANT record @return number of added fields */ static inline unsigned rec_get_n_add_field(const byte*& header) { @@ -253,18 +253,18 @@ static inline unsigned rec_get_n_add_field(const byte*& header) enum rec_leaf_format { /** Temporary file record */ REC_LEAF_TEMP, - /** Temporary file record, with added columns - (REC_STATUS_COLUMNS_ADDED) */ - REC_LEAF_TEMP_COLUMNS_ADDED, + /** Temporary file record, with added columns (REC_STATUS_INSTANT) */ + REC_LEAF_TEMP_INSTANT, /** Normal (REC_STATUS_ORDINARY) */ REC_LEAF_ORDINARY, - /** With added columns (REC_STATUS_COLUMNS_ADDED) */ - REC_LEAF_COLUMNS_ADDED + /** With add or drop columns (REC_STATUS_INSTANT) */ + REC_LEAF_INSTANT }; /** Determine the offset to each field in a leaf-page record in ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED. This is a special case of rec_init_offsets() and rec_get_offsets_func(). +@tparam mblob whether the record includes a metadata BLOB @param[in] rec leaf-page record @param[in] index the index that the record belongs in @param[in] n_core number of core fields (index->n_core_fields) @@ -272,6 +272,7 @@ This is a special case of rec_init_offsets() and rec_get_offsets_func(). NULL to refer to index->fields[].col->def_val @param[in,out] offsets offsets, with valid rec_offs_n_fields(offsets) @param[in] format record format */ +template<bool mblob = false> static inline void rec_init_offsets_comp_ordinary( @@ -293,12 +294,32 @@ rec_init_offsets_comp_ordinary( ut_ad(n_core > 0); ut_ad(index->n_fields >= n_core); ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable)); - ut_ad(format == REC_LEAF_TEMP || format == REC_LEAF_TEMP_COLUMNS_ADDED + ut_ad(format == REC_LEAF_TEMP || format == REC_LEAF_TEMP_INSTANT || dict_table_is_comp(index->table)); - ut_ad(format != REC_LEAF_TEMP_COLUMNS_ADDED + ut_ad(format != REC_LEAF_TEMP_INSTANT || index->n_fields == rec_offs_n_fields(offsets)); ut_d(ulint n_null= 0); + if (mblob) { + ut_ad(index->is_dummy || index->table->instant); + ut_ad(index->is_dummy || index->is_instant()); + ut_ad(rec_offs_n_fields(offsets) + <= ulint(index->n_fields) + 1); + ut_ad(!def_val); + ut_ad(format == REC_LEAF_INSTANT); + nulls -= REC_N_NEW_EXTRA_BYTES; + n_fields = n_core + 1 + rec_get_n_add_field(nulls); + ut_ad(n_fields <= ulint(index->n_fields) + 1); + const ulint n_nullable = index->get_n_nullable(n_fields - 1); + const ulint n_null_bytes = UT_BITS_IN_BYTES(n_nullable); + ut_d(n_null = n_nullable); + ut_ad(n_null <= index->n_nullable); + ut_ad(n_null_bytes >= index->n_core_null_bytes + || n_core < index->n_core_fields); + lens = --nulls - n_null_bytes; + goto start; + } + switch (format) { case REC_LEAF_TEMP: if (dict_table_is_comp(index->table)) { @@ -312,17 +333,15 @@ rec_init_offsets_comp_ordinary( ordinary: lens = --nulls - index->n_core_null_bytes; - ut_d(n_null = std::min(index->n_core_null_bytes * 8U, - index->n_nullable)); + ut_d(n_null = std::min<uint>(index->n_core_null_bytes * 8U, + index->n_nullable)); break; - case REC_LEAF_COLUMNS_ADDED: - /* We would have !index->is_instant() when rolling back - an instant ADD COLUMN operation. */ + case REC_LEAF_INSTANT: nulls -= REC_N_NEW_EXTRA_BYTES; ut_ad(index->is_instant()); /* fall through */ - case REC_LEAF_TEMP_COLUMNS_ADDED: - n_fields = n_core + 1 + rec_get_n_add_field(nulls); + case REC_LEAF_TEMP_INSTANT: + n_fields = n_core + rec_get_n_add_field(nulls) + 1; ut_ad(n_fields <= index->n_fields); const ulint n_nullable = index->get_n_nullable(n_fields); const ulint n_null_bytes = UT_BITS_IN_BYTES(n_nullable); @@ -333,26 +352,34 @@ ordinary: lens = --nulls - n_null_bytes; } -#ifdef UNIV_DEBUG +start: /* We cannot invoke rec_offs_make_valid() if format==REC_LEAF_TEMP. Similarly, rec_offs_validate() will fail in that case, because it invokes rec_get_status(). */ - offsets[2] = (ulint) rec; - offsets[3] = (ulint) index; -#endif /* UNIV_DEBUG */ + ut_d(offsets[2] = ulint(rec)); + ut_d(offsets[3] = ulint(index)); /* read the lengths of fields 0..n_fields */ + ulint len; ulint i = 0; - do { - const dict_field_t* field - = dict_index_get_nth_field(index, i); - const dict_col_t* col - = dict_field_get_col(field); - ulint len; + const dict_field_t* field = index->fields; - /* set default value flag */ - if (i < n_fields) { - } else if (def_val) { + do { + if (mblob) { + if (i == index->first_user_field()) { + offs += FIELD_REF_SIZE; + len = offs | REC_OFFS_EXTERNAL; + any |= REC_OFFS_EXTERNAL; + field--; + continue; + } else if (i >= n_fields) { + len = offs | REC_OFFS_DEFAULT; + any |= REC_OFFS_DEFAULT; + continue; + } + } else if (i < n_fields) { + /* The field is present, and will be covered below. */ + } else if (!mblob && def_val) { const dict_col_t::def_t& d = def_val[i - n_core]; if (!d.data) { len = offs | REC_OFFS_SQL_NULL; @@ -362,21 +389,22 @@ ordinary: any |= REC_OFFS_DEFAULT; } - goto resolved; + continue; } else { - ulint dlen; - if (!index->instant_field_value(i, &dlen)) { + if (!index->instant_field_value(i, &len)) { + ut_ad(len == UNIV_SQL_NULL); len = offs | REC_OFFS_SQL_NULL; - ut_ad(dlen == UNIV_SQL_NULL); } else { len = offs | REC_OFFS_DEFAULT; any |= REC_OFFS_DEFAULT; } - goto resolved; + continue; } - if (!(col->prtype & DATA_NOT_NULL)) { + const dict_col_t* col = field->col; + + if (col->is_nullable()) { /* nullable field => read the null flag */ ut_ad(n_null--); @@ -392,7 +420,7 @@ ordinary: the length to zero and enable the SQL NULL flag in offsets[]. */ len = offs | REC_OFFS_SQL_NULL; - goto resolved; + continue; } null_mask <<= 1; } @@ -423,16 +451,15 @@ ordinary: len = offs; } - goto resolved; + continue; } len = offs += len; } else { len = offs += field->fixed_len; } -resolved: - rec_offs_base(offsets)[i + 1] = len; - } while (++i < rec_offs_n_fields(offsets)); + } while (field++, rec_offs_base(offsets)[++i] = len, + i < rec_offs_n_fields(offsets)); *rec_offs_base(offsets) = ulint(rec - (lens + 1)) | REC_OFFS_COMPACT | any; @@ -451,7 +478,10 @@ rec_offs_make_valid( bool leaf, ulint* offsets) { - ut_ad(rec_offs_n_fields(offsets) + const bool is_alter_metadata = leaf + && rec_is_alter_metadata(rec, *index); + ut_ad(is_alter_metadata + || rec_offs_n_fields(offsets) <= (leaf ? dict_index_get_n_fields(index) : dict_index_get_n_unique_in_tree_nonleaf(index) + 1) @@ -469,7 +499,8 @@ rec_offs_make_valid( || n >= rec_offs_n_fields(offsets)); for (; n < rec_offs_n_fields(offsets); n++) { ut_ad(leaf); - ut_ad(rec_offs_base(offsets)[1 + n] & REC_OFFS_DEFAULT); + ut_ad(is_alter_metadata + || rec_offs_base(offsets)[1 + n] & REC_OFFS_DEFAULT); } offsets[2] = ulint(rec); offsets[3] = ulint(index); @@ -509,14 +540,18 @@ rec_offs_validate( } } if (index) { - ulint max_n_fields; ut_ad(ulint(index) == offsets[3]); - max_n_fields = ut_max( + ulint max_n_fields = ut_max( dict_index_get_n_fields(index), dict_index_get_n_unique_in_tree(index) + 1); if (comp && rec) { switch (rec_get_status(rec)) { - case REC_STATUS_COLUMNS_ADDED: + case REC_STATUS_INSTANT: + ut_ad(index->is_instant() || index->is_dummy); + ut_ad(max_n_fields == index->n_fields); + max_n_fields += index->table->instant + || index->is_dummy; + break; case REC_STATUS_ORDINARY: break; case REC_STATUS_NODE_PTR: @@ -530,14 +565,19 @@ rec_offs_validate( default: ut_error; } + } else if (max_n_fields == index->n_fields + && (index->is_dummy + || (index->is_instant() + && index->table->instant))) { + max_n_fields++; } /* index->n_def == 0 for dummy indexes if !comp */ - ut_a(!comp || index->n_def); - ut_a(!index->n_def || i <= max_n_fields); + ut_ad(!comp || index->n_def); + ut_ad(!index->n_def || i <= max_n_fields); } while (i--) { ulint curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK; - ut_a(curr <= last); + ut_ad(curr <= last); last = curr; } return(TRUE); @@ -598,12 +638,12 @@ rec_init_offsets( = dict_index_get_n_unique_in_tree_nonleaf( index); break; - case REC_STATUS_COLUMNS_ADDED: + case REC_STATUS_INSTANT: ut_ad(leaf); rec_init_offsets_comp_ordinary(rec, index, offsets, index->n_core_fields, NULL, - REC_LEAF_COLUMNS_ADDED); + REC_LEAF_INSTANT); return; case REC_STATUS_ORDINARY: ut_ad(leaf); @@ -780,6 +820,7 @@ rec_get_offsets_func( { ulint n; ulint size; + bool alter_metadata = false; ut_ad(rec); ut_ad(index); @@ -788,10 +829,12 @@ rec_get_offsets_func( if (dict_table_is_comp(index->table)) { switch (UNIV_EXPECT(rec_get_status(rec), REC_STATUS_ORDINARY)) { - case REC_STATUS_COLUMNS_ADDED: + case REC_STATUS_INSTANT: + alter_metadata = rec_is_alter_metadata(rec, true); + /* fall through */ case REC_STATUS_ORDINARY: ut_ad(leaf); - n = dict_index_get_n_fields(index); + n = dict_index_get_n_fields(index) + alter_metadata; break; case REC_STATUS_NODE_PTR: /* Node pointer records consist of the @@ -835,7 +878,8 @@ rec_get_offsets_func( || dict_index_is_ibuf(index) || n == n_fields /* btr_pcur_restore_position() */ || (n + (index->id == DICT_INDEXES_ID) - >= index->n_core_fields && n <= index->n_fields)); + >= index->n_core_fields && n <= index->n_fields + + unsigned(rec_is_alter_metadata(rec, false)))); if (is_user_rec && leaf && n < index->n_fields) { ut_ad(!index->is_dummy); @@ -865,8 +909,24 @@ rec_get_offsets_func( } rec_offs_set_n_fields(offsets, n); - rec_init_offsets(rec, index, leaf, offsets); - return(offsets); + + if (UNIV_UNLIKELY(alter_metadata) + && dict_table_is_comp(index->table)) { + ut_d(offsets[2] = ulint(rec)); + ut_d(offsets[3] = ulint(index)); + ut_ad(leaf); + ut_ad(index->is_dummy || index->table->instant); + ut_ad(index->is_dummy || index->is_instant()); + ut_ad(rec_offs_n_fields(offsets) + <= ulint(index->n_fields) + 1); + rec_init_offsets_comp_ordinary<true>(rec, index, offsets, + index->n_core_fields, + NULL, + REC_LEAF_INSTANT); + } else { + rec_init_offsets(rec, index, leaf, offsets); + } + return offsets; } /******************************************************//** @@ -1044,36 +1104,45 @@ rec_get_nth_field_offs_old( return(os); } -/**********************************************************//** -Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT. +/** Determine the size of a data tuple prefix in ROW_FORMAT=COMPACT. +@tparam mblob whether the record includes a metadata BLOB +@param[in] index record descriptor; dict_table_is_comp() + is assumed to hold, even if it doesn't +@param[in] dfield array of data fields +@param[in] n_fields number of data fields +@param[out] extra extra size +@param[in] status status flags +@param[in] temp whether this is a temporary file record @return total size */ -MY_ATTRIBUTE((warn_unused_result, nonnull(1,2))) +template<bool mblob = false> static inline ulint rec_get_converted_size_comp_prefix_low( -/*===================================*/ - const dict_index_t* index, /*!< in: record descriptor; - dict_table_is_comp() is - assumed to hold, even if - it does not */ - const dfield_t* fields, /*!< in: array of data fields */ - ulint n_fields,/*!< in: number of data fields */ - ulint* extra, /*!< out: extra size */ - rec_comp_status_t status, /*!< in: status flags */ - bool temp) /*!< in: whether this is a - temporary file record */ + const dict_index_t* index, + const dfield_t* dfield, + ulint n_fields, + ulint* extra, + rec_comp_status_t status, + bool temp) { ulint extra_size = temp ? 0 : REC_N_NEW_EXTRA_BYTES; - ulint data_size; - ulint i; ut_ad(n_fields > 0); - ut_ad(n_fields <= dict_index_get_n_fields(index)); + ut_ad(n_fields <= dict_index_get_n_fields(index) + mblob); ut_d(ulint n_null = index->n_nullable); ut_ad(status == REC_STATUS_ORDINARY || status == REC_STATUS_NODE_PTR - || status == REC_STATUS_COLUMNS_ADDED); + || status == REC_STATUS_INSTANT); - if (status == REC_STATUS_COLUMNS_ADDED - && (!temp || n_fields > index->n_core_fields)) { + if (mblob) { + ut_ad(!temp); + ut_ad(index->table->instant); + ut_ad(index->is_instant()); + ut_ad(status == REC_STATUS_INSTANT); + ut_ad(n_fields == ulint(index->n_fields) + 1); + extra_size += UT_BITS_IN_BYTES(index->n_nullable) + + rec_get_n_add_field_len(n_fields - 1 + - index->n_core_fields); + } else if (status == REC_STATUS_INSTANT + && (!temp || n_fields > index->n_core_fields)) { ut_ad(index->is_instant()); ut_ad(UT_BITS_IN_BYTES(n_null) >= index->n_core_null_bytes); extra_size += UT_BITS_IN_BYTES(index->get_n_nullable(n_fields)) @@ -1084,7 +1153,7 @@ rec_get_converted_size_comp_prefix_low( extra_size += index->n_core_null_bytes; } - data_size = 0; + ulint data_size = 0; if (temp && dict_table_is_comp(index->table)) { /* No need to do adjust fixed_len=0. We only need to @@ -1092,48 +1161,50 @@ rec_get_converted_size_comp_prefix_low( temp = false; } + const dfield_t* const end = dfield + n_fields; /* read the lengths of fields 0..n */ - for (i = 0; i < n_fields; i++) { - const dict_field_t* field; - ulint len; - ulint fixed_len; - const dict_col_t* col; + for (ulint i = 0; dfield < end; i++, dfield++) { + if (mblob && i == index->first_user_field()) { + data_size += FIELD_REF_SIZE; + ++dfield; + } - field = dict_index_get_nth_field(index, i); - len = dfield_get_len(&fields[i]); - col = dict_field_get_col(field); + ulint len = dfield_get_len(dfield); + const dict_field_t* field = dict_index_get_nth_field(index, i); #ifdef UNIV_DEBUG - dtype_t* type; - - type = dfield_get_type(&fields[i]); if (dict_index_is_spatial(index)) { - if (DATA_GEOMETRY_MTYPE(col->mtype) && i == 0) { - ut_ad(type->prtype & DATA_GIS_MBR); + if (DATA_GEOMETRY_MTYPE(field->col->mtype) && i == 0) { + ut_ad(dfield->type.prtype & DATA_GIS_MBR); } else { - ut_ad(type->mtype == DATA_SYS_CHILD - || dict_col_type_assert_equal(col, type)); + ut_ad(dfield->type.mtype == DATA_SYS_CHILD + || dict_col_type_assert_equal( + field->col, &dfield->type)); } } else { - ut_ad(dict_col_type_assert_equal(col, type)); + ut_ad(field->col->is_dropped() + || dict_col_type_assert_equal(field->col, + &dfield->type)); } #endif /* All NULLable fields must be included in the n_null count. */ - ut_ad((col->prtype & DATA_NOT_NULL) || n_null--); + ut_ad(!field->col->is_nullable() || n_null--); - if (dfield_is_null(&fields[i])) { + if (dfield_is_null(dfield)) { /* No length is stored for NULL fields. */ - ut_ad(!(col->prtype & DATA_NOT_NULL)); + ut_ad(field->col->is_nullable()); continue; } - ut_ad(len <= col->len || DATA_LARGE_MTYPE(col->mtype) - || (col->len == 0 && col->mtype == DATA_VARCHAR)); + ut_ad(len <= field->col->len + || DATA_LARGE_MTYPE(field->col->mtype) + || (field->col->len == 0 + && field->col->mtype == DATA_VARCHAR)); - fixed_len = field->fixed_len; + ulint fixed_len = field->fixed_len; if (temp && fixed_len - && !dict_col_get_fixed_size(col, temp)) { + && !dict_col_get_fixed_size(field->col, temp)) { fixed_len = 0; } /* If the maximum length of a variable-length field @@ -1148,25 +1219,27 @@ rec_get_converted_size_comp_prefix_low( ut_ad(len <= fixed_len); if (dict_index_is_spatial(index)) { - ut_ad(type->mtype == DATA_SYS_CHILD - || !col->mbmaxlen - || len >= col->mbminlen - * fixed_len / col->mbmaxlen); + ut_ad(dfield->type.mtype == DATA_SYS_CHILD + || !field->col->mbmaxlen + || len >= field->col->mbminlen + * fixed_len / field->col->mbmaxlen); } else { - ut_ad(type->mtype != DATA_SYS_CHILD); - ut_ad(!col->mbmaxlen - || len >= col->mbminlen - * fixed_len / col->mbmaxlen); + ut_ad(dfield->type.mtype != DATA_SYS_CHILD); + + ut_ad(field->col->is_dropped() + || !field->col->mbmaxlen + || len >= field->col->mbminlen + * fixed_len / field->col->mbmaxlen); } /* dict_index_add_col() should guarantee this */ ut_ad(!field->prefix_len || fixed_len == field->prefix_len); #endif /* UNIV_DEBUG */ - } else if (dfield_is_ext(&fields[i])) { - ut_ad(DATA_BIG_COL(col)); + } else if (dfield_is_ext(dfield)) { + ut_ad(DATA_BIG_COL(field->col)); extra_size += 2; - } else if (len < 128 || !DATA_BIG_COL(col)) { + } else if (len < 128 || !DATA_BIG_COL(field->col)) { extra_size++; } else { /* For variable-length columns, we look up the @@ -1202,43 +1275,51 @@ rec_get_converted_size_comp_prefix( REC_STATUS_ORDINARY, false)); } -/**********************************************************//** -Determines the size of a data tuple in ROW_FORMAT=COMPACT. +/** Determine the size of a record in ROW_FORMAT=COMPACT. +@param[in] index record descriptor. dict_table_is_comp() + is assumed to hold, even if it doesn't +@param[in] tuple logical record +@param[out] extra extra size @return total size */ ulint rec_get_converted_size_comp( -/*========================*/ - const dict_index_t* index, /*!< in: record descriptor; - dict_table_is_comp() is - assumed to hold, even if - it does not */ - rec_comp_status_t status, /*!< in: status bits of the record */ - const dfield_t* fields, /*!< in: array of data fields */ - ulint n_fields,/*!< in: number of data fields */ - ulint* extra) /*!< out: extra size */ + const dict_index_t* index, + const dtuple_t* tuple, + ulint* extra) { - ut_ad(n_fields > 0); + ut_ad(tuple->n_fields > 0); + + rec_comp_status_t status = rec_comp_status_t(tuple->info_bits + & REC_NEW_STATUS_MASK); switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) { case REC_STATUS_ORDINARY: - if (n_fields > index->n_core_fields) { + ut_ad(!tuple->is_metadata()); + if (tuple->n_fields > index->n_core_fields) { ut_ad(index->is_instant()); - status = REC_STATUS_COLUMNS_ADDED; + status = REC_STATUS_INSTANT; } /* fall through */ - case REC_STATUS_COLUMNS_ADDED: - ut_ad(n_fields >= index->n_core_fields); - ut_ad(n_fields <= index->n_fields); + case REC_STATUS_INSTANT: + ut_ad(tuple->n_fields >= index->n_core_fields); + if (tuple->is_alter_metadata()) { + return rec_get_converted_size_comp_prefix_low<true>( + index, tuple->fields, tuple->n_fields, + extra, status, false); + } + ut_ad(tuple->n_fields <= index->n_fields); return rec_get_converted_size_comp_prefix_low( - index, fields, n_fields, extra, status, false); + index, tuple->fields, tuple->n_fields, + extra, status, false); case REC_STATUS_NODE_PTR: - n_fields--; - ut_ad(n_fields == dict_index_get_n_unique_in_tree_nonleaf( - index)); - ut_ad(dfield_get_len(&fields[n_fields]) == REC_NODE_PTR_SIZE); + ut_ad(tuple->n_fields - 1 + == dict_index_get_n_unique_in_tree_nonleaf(index)); + ut_ad(dfield_get_len(&tuple->fields[tuple->n_fields - 1]) + == REC_NODE_PTR_SIZE); return REC_NODE_PTR_SIZE /* child page number */ + rec_get_converted_size_comp_prefix_low( - index, fields, n_fields, extra, status, false); + index, tuple->fields, tuple->n_fields - 1, + extra, status, false); case REC_STATUS_INFIMUM: case REC_STATUS_SUPREMUM: /* not supported */ @@ -1416,33 +1497,30 @@ rec_convert_dtuple_to_rec_old( } /** Convert a data tuple into a ROW_FORMAT=COMPACT record. +@tparam mblob whether the record includes a metadata BLOB @param[out] rec converted record @param[in] index index -@param[in] fields data fields to convert +@param[in] field data fields to convert @param[in] n_fields number of data fields @param[in] status rec_get_status(rec) @param[in] temp whether to use the format for temporary files in index creation */ +template<bool mblob = false> static inline void rec_convert_dtuple_to_rec_comp( rec_t* rec, const dict_index_t* index, - const dfield_t* fields, + const dfield_t* field, ulint n_fields, rec_comp_status_t status, bool temp) { - const dfield_t* field; - const dtype_t* type; byte* end; byte* nulls = temp ? rec - 1 : rec - (REC_N_NEW_EXTRA_BYTES + 1); byte* UNINIT_VAR(lens); - ulint len; - ulint i; ulint UNINIT_VAR(n_node_ptr_field); - ulint fixed_len; ulint null_mask = 1; ut_ad(n_fields > 0); @@ -1451,8 +1529,22 @@ rec_convert_dtuple_to_rec_comp( ut_d(ulint n_null = index->n_nullable); + if (mblob) { + ut_ad(!temp); + ut_ad(index->table->instant); + ut_ad(index->is_instant()); + ut_ad(status == REC_STATUS_INSTANT); + ut_ad(n_fields == ulint(index->n_fields) + 1); + rec_set_n_add_field(nulls, n_fields - 1 + - index->n_core_fields); + rec_set_heap_no_new(rec, PAGE_HEAP_NO_USER_LOW); + rec_set_status(rec, REC_STATUS_INSTANT); + n_node_ptr_field = ULINT_UNDEFINED; + lens = nulls - UT_BITS_IN_BYTES(index->n_nullable); + goto start; + } switch (status) { - case REC_STATUS_COLUMNS_ADDED: + case REC_STATUS_INSTANT: ut_ad(index->is_instant()); ut_ad(n_fields > index->n_core_fields); rec_set_n_add_field(nulls, n_fields - 1 @@ -1462,19 +1554,24 @@ rec_convert_dtuple_to_rec_comp( ut_ad(n_fields <= dict_index_get_n_fields(index)); if (!temp) { rec_set_heap_no_new(rec, PAGE_HEAP_NO_USER_LOW); - rec_set_status(rec, n_fields == index->n_core_fields - ? REC_STATUS_ORDINARY - : REC_STATUS_COLUMNS_ADDED); - } if (dict_table_is_comp(index->table)) { + + rec_set_status( + rec, n_fields == index->n_core_fields + ? REC_STATUS_ORDINARY + : REC_STATUS_INSTANT); + } + + if (dict_table_is_comp(index->table)) { /* No need to do adjust fixed_len=0. We only need to adjust it for ROW_FORMAT=REDUNDANT. */ temp = false; } n_node_ptr_field = ULINT_UNDEFINED; + lens = nulls - (index->is_instant() ? UT_BITS_IN_BYTES(index->get_n_nullable( - n_fields)) + n_fields)) : UT_BITS_IN_BYTES( unsigned(index->n_nullable))); break; @@ -1484,8 +1581,8 @@ rec_convert_dtuple_to_rec_comp( rec_set_status(rec, status); ut_ad(n_fields == dict_index_get_n_unique_in_tree_nonleaf(index) + 1); - ut_d(n_null = std::min(index->n_core_null_bytes * 8U, - index->n_nullable)); + ut_d(n_null = std::min<uint>(index->n_core_null_bytes * 8U, + index->n_nullable)); n_node_ptr_field = n_fields - 1; lens = nulls - index->n_core_null_bytes; break; @@ -1495,30 +1592,33 @@ rec_convert_dtuple_to_rec_comp( return; } +start: end = rec; /* clear the SQL-null flags */ memset(lens + 1, 0, ulint(nulls - lens)); + const dfield_t* const fend = field + n_fields; /* Store the data and the offsets */ - - for (i = 0; i < n_fields; i++) { - const dict_field_t* ifield; - dict_col_t* col = NULL; - - field = &fields[i]; - - type = dfield_get_type(field); - len = dfield_get_len(field); - - if (UNIV_UNLIKELY(i == n_node_ptr_field)) { - ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL); + for (ulint i = 0; field < fend; i++, field++) { + ulint len = dfield_get_len(field); + + if (mblob) { + if (i == index->first_user_field()) { + ut_ad(len == FIELD_REF_SIZE); + ut_ad(dfield_is_ext(field)); + memcpy(end, dfield_get_data(field), len); + end += len; + len = dfield_get_len(++field); + } + } else if (UNIV_UNLIKELY(i == n_node_ptr_field)) { + ut_ad(field->type.prtype & DATA_NOT_NULL); ut_ad(len == REC_NODE_PTR_SIZE); memcpy(end, dfield_get_data(field), len); end += REC_NODE_PTR_SIZE; break; } - if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { + if (!(field->type.prtype & DATA_NOT_NULL)) { /* nullable field */ ut_ad(n_null--); @@ -1541,11 +1641,12 @@ rec_convert_dtuple_to_rec_comp( /* only nullable fields can be null */ ut_ad(!dfield_is_null(field)); - ifield = dict_index_get_nth_field(index, i); - fixed_len = ifield->fixed_len; - col = ifield->col; + const dict_field_t* ifield + = dict_index_get_nth_field(index, i); + ulint fixed_len = ifield->fixed_len; + if (temp && fixed_len - && !dict_col_get_fixed_size(col, temp)) { + && !dict_col_get_fixed_size(ifield->col, temp)) { fixed_len = 0; } @@ -1557,23 +1658,23 @@ rec_convert_dtuple_to_rec_comp( it is 128 or more, or when the field is stored externally. */ if (fixed_len) { ut_ad(len <= fixed_len); - ut_ad(!col->mbmaxlen - || len >= col->mbminlen - * fixed_len / col->mbmaxlen); + ut_ad(!ifield->col->mbmaxlen + || len >= ifield->col->mbminlen + * fixed_len / ifield->col->mbmaxlen); ut_ad(!dfield_is_ext(field)); } else if (dfield_is_ext(field)) { - ut_ad(DATA_BIG_COL(col)); + ut_ad(DATA_BIG_COL(ifield->col)); ut_ad(len <= REC_ANTELOPE_MAX_INDEX_COL_LEN - + BTR_EXTERN_FIELD_REF_SIZE); + + BTR_EXTERN_FIELD_REF_SIZE); *lens-- = (byte) (len >> 8) | 0xc0; *lens-- = (byte) len; } else { - ut_ad(len <= dtype_get_len(type) - || DATA_LARGE_MTYPE(dtype_get_mtype(type)) + ut_ad(len <= field->type.len + || DATA_LARGE_MTYPE(field->type.mtype) || !strcmp(index->name, FTS_INDEX_TABLE_IND_NAME)); if (len < 128 || !DATA_BIG_LEN_MTYPE( - dtype_get_len(type), dtype_get_mtype(type))) { + field->type.len, field->type.mtype)) { *lens-- = (byte) len; } else { @@ -1606,24 +1707,37 @@ rec_convert_dtuple_to_rec_new( ut_ad(!(dtuple->info_bits & ~(REC_NEW_STATUS_MASK | REC_INFO_DELETED_FLAG | REC_INFO_MIN_REC_FLAG))); - rec_comp_status_t status = static_cast<rec_comp_status_t>( - dtuple->info_bits & REC_NEW_STATUS_MASK); - if (status == REC_STATUS_ORDINARY - && dtuple->n_fields > index->n_core_fields) { - ut_ad(index->is_instant()); - status = REC_STATUS_COLUMNS_ADDED; - } ulint extra_size; - rec_get_converted_size_comp( - index, status, dtuple->fields, dtuple->n_fields, &extra_size); - rec_t* rec = buf + extra_size; + if (UNIV_UNLIKELY(dtuple->is_alter_metadata())) { + ut_ad((dtuple->info_bits & REC_NEW_STATUS_MASK) + == REC_STATUS_INSTANT); + rec_get_converted_size_comp_prefix_low<true>( + index, dtuple->fields, dtuple->n_fields, + &extra_size, REC_STATUS_INSTANT, false); + buf += extra_size; + rec_convert_dtuple_to_rec_comp<true>( + buf, index, dtuple->fields, dtuple->n_fields, + REC_STATUS_INSTANT, false); + } else { + rec_get_converted_size_comp(index, dtuple, &extra_size); + buf += extra_size; + rec_comp_status_t status = rec_comp_status_t( + dtuple->info_bits & REC_NEW_STATUS_MASK); + if (status == REC_STATUS_ORDINARY + && dtuple->n_fields > index->n_core_fields) { + ut_ad(index->is_instant()); + status = REC_STATUS_INSTANT; + } - rec_convert_dtuple_to_rec_comp( - rec, index, dtuple->fields, dtuple->n_fields, status, false); - rec_set_info_bits_new(rec, dtuple->info_bits & ~REC_NEW_STATUS_MASK); - return(rec); + rec_convert_dtuple_to_rec_comp( + buf, index, dtuple->fields, dtuple->n_fields, + status, false); + } + + rec_set_info_bits_new(buf, dtuple->info_bits & ~REC_NEW_STATUS_MASK); + return buf; } /*********************************************************//** @@ -1662,7 +1776,7 @@ rec_convert_dtuple_to_rec( @param[in] fields data fields @param[in] n_fields number of data fields @param[out] extra record header size -@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED +@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT @return total size, in bytes */ ulint rec_get_converted_size_temp( @@ -1682,7 +1796,7 @@ rec_get_converted_size_temp( @param[in,out] offsets offsets to the fields; in: rec_offs_n_fields(offsets) @param[in] n_core number of core fields (index->n_core_fields) @param[in] def_val default values for non-core fields -@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED */ +@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT */ void rec_init_offsets_temp( const rec_t* rec, @@ -1693,14 +1807,14 @@ rec_init_offsets_temp( rec_comp_status_t status) { ut_ad(status == REC_STATUS_ORDINARY - || status == REC_STATUS_COLUMNS_ADDED); + || status == REC_STATUS_INSTANT); /* The table may have been converted to plain format if it was emptied during an ALTER TABLE operation. */ ut_ad(index->n_core_fields == n_core || !index->is_instant()); ut_ad(index->n_core_fields >= n_core); rec_init_offsets_comp_ordinary(rec, index, offsets, n_core, def_val, - status == REC_STATUS_COLUMNS_ADDED - ? REC_LEAF_TEMP_COLUMNS_ADDED + status == REC_STATUS_INSTANT + ? REC_LEAF_TEMP_INSTANT : REC_LEAF_TEMP); } @@ -1726,7 +1840,7 @@ rec_init_offsets_temp( @param[in] index clustered or secondary index @param[in] fields data fields @param[in] n_fields number of data fields -@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED +@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT */ void rec_convert_dtuple_to_temp( @@ -1896,13 +2010,15 @@ rec_copy_prefix_to_buf( ut_ad(n_fields <= dict_index_get_n_unique_in_tree_nonleaf(index)); break; - case REC_STATUS_COLUMNS_ADDED: + case REC_STATUS_INSTANT: /* We would have !index->is_instant() when rolling back an instant ADD COLUMN operation. */ ut_ad(index->is_instant() || page_rec_is_metadata(rec)); + ut_ad(n_fields <= index->first_user_field()); nulls++; const ulint n_rec = ulint(index->n_core_fields) + 1 - + rec_get_n_add_field(nulls); + + rec_get_n_add_field(nulls) + - rec_is_alter_metadata(rec, true); instant_omit = ulint(&rec[-REC_N_NEW_EXTRA_BYTES] - nulls); ut_ad(instant_omit == 1 || instant_omit == 2); nullf = nulls; @@ -1991,7 +2107,7 @@ rec_copy_prefix_to_buf( /* copy the fixed-size header and the record prefix */ memcpy(b - REC_N_NEW_EXTRA_BYTES, rec - REC_N_NEW_EXTRA_BYTES, prefix_len + REC_N_NEW_EXTRA_BYTES); - ut_ad(rec_get_status(b) == REC_STATUS_COLUMNS_ADDED); + ut_ad(rec_get_status(b) == REC_STATUS_INSTANT); rec_set_status(b, REC_STATUS_ORDINARY); return b; } else { @@ -2518,8 +2634,6 @@ rec_get_trx_id( const rec_t* rec, const dict_index_t* index) { - ulint trx_id_col - = dict_index_get_sys_col_pos(index, DATA_TRX_ID); const byte* trx_id; ulint len; mem_heap_t* heap = NULL; @@ -2527,15 +2641,10 @@ rec_get_trx_id( rec_offs_init(offsets_); ulint* offsets = offsets_; - ut_ad(trx_id_col <= MAX_REF_PARTS); - ut_ad(dict_index_is_clust(index)); - ut_ad(trx_id_col > 0); - ut_ad(trx_id_col != ULINT_UNDEFINED); - offsets = rec_get_offsets(rec, index, offsets, true, - trx_id_col + 1, &heap); + index->db_trx_id() + 1, &heap); - trx_id = rec_get_nth_field(rec, offsets, trx_id_col, &len); + trx_id = rec_get_nth_field(rec, offsets, index->db_trx_id(), &len); ut_ad(len == DATA_TRX_ID_LEN); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 5a4321e5fe7..4e9f16a502f 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1459,7 +1459,7 @@ IndexPurge::open() UNIV_NOTHROW btr_pcur_open_at_index_side( true, m_index, BTR_MODIFY_LEAF, &m_pcur, true, 0, &m_mtr); btr_pcur_move_to_next_user_rec(&m_pcur, &m_mtr); - if (rec_is_metadata(btr_pcur_get_rec(&m_pcur), m_index)) { + if (rec_is_metadata(btr_pcur_get_rec(&m_pcur), *m_index)) { ut_ad(btr_pcur_is_on_user_rec(&m_pcur)); /* Skip the metadata pseudo-record. */ } else { @@ -2224,17 +2224,15 @@ row_import_adjust_root_pages_of_secondary_indexes( } /*****************************************************************//** -Ensure that dict_sys->row_id exceeds SELECT MAX(DB_ROW_ID). -@return error code */ -static MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t +Ensure that dict_sys->row_id exceeds SELECT MAX(DB_ROW_ID). */ +MY_ATTRIBUTE((nonnull)) static +void row_import_set_sys_max_row_id( /*==========================*/ row_prebuilt_t* prebuilt, /*!< in/out: prebuilt from handler */ const dict_table_t* table) /*!< in: table to import */ { - dberr_t err; const rec_t* rec; mtr_t mtr; btr_pcur_t pcur; @@ -2242,7 +2240,8 @@ row_import_set_sys_max_row_id( dict_index_t* index; index = dict_table_get_first_index(table); - ut_a(dict_index_is_clust(index)); + ut_ad(index->is_primary()); + ut_ad(dict_index_is_auto_gen_clust(index)); mtr_start(&mtr); @@ -2263,57 +2262,17 @@ row_import_set_sys_max_row_id( /* Check for empty table. */ if (page_rec_is_infimum(rec)) { /* The table is empty. */ - err = DB_SUCCESS; - } else if (rec_is_metadata(rec, index)) { + } else if (rec_is_metadata(rec, *index)) { /* The clustered index contains the metadata record only, that is, the table is empty. */ - err = DB_SUCCESS; } else { - ulint len; - const byte* field; - mem_heap_t* heap = NULL; - ulint offsets_[1 + REC_OFFS_HEADER_SIZE]; - ulint* offsets; - - rec_offs_init(offsets_); - - offsets = rec_get_offsets( - rec, index, offsets_, true, ULINT_UNDEFINED, &heap); - - field = rec_get_nth_field( - rec, offsets, - dict_index_get_sys_col_pos(index, DATA_ROW_ID), - &len); - - if (len == DATA_ROW_ID_LEN) { - row_id = mach_read_from_6(field); - err = DB_SUCCESS; - } else { - err = DB_CORRUPTION; - } - - if (heap != NULL) { - mem_heap_free(heap); - } + row_id = mach_read_from_6(rec); } btr_pcur_close(&pcur); mtr_commit(&mtr); - DBUG_EXECUTE_IF("ib_import_set_max_rowid_failure", - err = DB_CORRUPTION;); - - if (err != DB_SUCCESS) { - ib_errf(prebuilt->trx->mysql_thd, - IB_LOG_LEVEL_WARN, - ER_INNODB_INDEX_CORRUPT, - "Index `%s` corruption detected, invalid DB_ROW_ID" - " in index.", index->name()); - - return(err); - - } else if (row_id > 0) { - + if (row_id) { /* Update the system row id if the imported index row id is greater than the max system row id. */ @@ -2326,8 +2285,6 @@ row_import_set_sys_max_row_id( mutex_exit(&dict_sys->mutex); } - - return(DB_SUCCESS); } /*****************************************************************//** @@ -4071,12 +4028,7 @@ row_import_for_mysql( any DB_ROW_ID stored in the table. */ if (prebuilt->clust_index_was_generated) { - - err = row_import_set_sys_max_row_id(prebuilt, table); - - if (err != DB_SUCCESS) { - return(row_import_error(prebuilt, trx, err)); - } + row_import_set_sys_max_row_id(prebuilt, table); } ib::info() << "Phase III - Flush changes to disk"; diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index bf454fbb505..27df0a9249d 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1270,8 +1270,10 @@ row_ins_foreign_check_on_constraint( } if (table->fts) { - doc_id = fts_get_doc_id_from_rec(table, clust_rec, - clust_index, tmp_heap); + doc_id = fts_get_doc_id_from_rec( + clust_rec, clust_index, + rec_get_offsets(clust_rec, clust_index, NULL, true, + ULINT_UNDEFINED, &tmp_heap)); } if (node->is_delete @@ -2591,25 +2593,32 @@ row_ins_clust_index_entry_low( } else { index->set_modified(mtr); - if (mode == BTR_MODIFY_LEAF - && dict_index_is_online_ddl(index)) { - mode = BTR_MODIFY_LEAF_ALREADY_S_LATCHED; - mtr_s_lock(dict_index_get_lock(index), &mtr); - } + if (UNIV_UNLIKELY(entry->is_metadata())) { + ut_ad(index->is_instant()); + ut_ad(!dict_index_is_online_ddl(index)); + ut_ad(mode == BTR_MODIFY_TREE); + } else { + if (mode == BTR_MODIFY_LEAF + && dict_index_is_online_ddl(index)) { + mode = BTR_MODIFY_LEAF_ALREADY_S_LATCHED; + mtr_s_lock(dict_index_get_lock(index), &mtr); + } - if (unsigned ai = index->table->persistent_autoinc) { - /* Prepare to persist the AUTO_INCREMENT value - from the index entry to PAGE_ROOT_AUTO_INC. */ - const dfield_t* dfield = dtuple_get_nth_field( - entry, ai - 1); - auto_inc = dfield_is_null(dfield) - ? 0 - : row_parse_int(static_cast<const byte*>( + if (unsigned ai = index->table->persistent_autoinc) { + /* Prepare to persist the AUTO_INCREMENT value + from the index entry to PAGE_ROOT_AUTO_INC. */ + const dfield_t* dfield = dtuple_get_nth_field( + entry, ai - 1); + if (!dfield_is_null(dfield)) { + auto_inc = row_parse_int( + static_cast<const byte*>( dfield->data), dfield->len, dfield->type.mtype, dfield->type.prtype & DATA_UNSIGNED); + } + } } } @@ -2639,7 +2648,7 @@ row_ins_clust_index_entry_low( #endif /* UNIV_DEBUG */ if (UNIV_UNLIKELY(entry->info_bits != 0)) { - ut_ad(entry->info_bits == REC_INFO_METADATA); + ut_ad(entry->is_metadata()); ut_ad(flags == BTR_NO_LOCKING_FLAG); ut_ad(index->is_instant()); ut_ad(!dict_index_is_online_ddl(index)); @@ -2647,28 +2656,18 @@ row_ins_clust_index_entry_low( const rec_t* rec = btr_cur_get_rec(cursor); - switch (rec_get_info_bits(rec, page_rec_is_comp(rec)) - & (REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG)) { - case REC_INFO_MIN_REC_FLAG: + if (rec_get_info_bits(rec, page_rec_is_comp(rec)) + & REC_INFO_MIN_REC_FLAG) { thr_get_trx(thr)->error_info = index; err = DB_DUPLICATE_KEY; goto err_exit; - case REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG: - /* The metadata record never carries the delete-mark - in MariaDB Server 10.3. - If a table loses its 'instantness', it happens - by the rollback of this first-time insert, or - by a call to btr_page_empty() on the root page - when the table becomes empty. */ - err = DB_CORRUPTION; - goto err_exit; - default: - ut_ad(!row_ins_must_modify_rec(cursor)); - goto do_insert; } + + ut_ad(!row_ins_must_modify_rec(cursor)); + goto do_insert; } - if (rec_is_metadata(btr_cur_get_rec(cursor), index)) { + if (rec_is_metadata(btr_cur_get_rec(cursor), *index)) { goto do_insert; } @@ -3454,6 +3453,23 @@ row_ins_index_entry_set_vals( ut_ad(dtuple_get_n_fields(row) == dict_table_get_n_cols(index->table)); row_field = dtuple_get_nth_v_field(row, v_col->v_pos); + } else if (col->is_dropped()) { + ut_ad(index->is_primary()); + + if (!(col->prtype & DATA_NOT_NULL)) { + field->data = NULL; + field->len = UNIV_SQL_NULL; + field->type.prtype = DATA_BINARY_TYPE; + } else { + ut_ad(col->len <= sizeof field_ref_zero); + dfield_set_data(field, field_ref_zero, + col->len); + field->type.prtype = DATA_NOT_NULL; + } + + field->type.mtype = col->len + ? DATA_FIXBINARY : DATA_BINARY; + continue; } else { row_field = dtuple_get_nth_field( row, ind_field->col->ind); @@ -3463,7 +3479,7 @@ row_ins_index_entry_set_vals( /* Check column prefix indexes */ if (ind_field != NULL && ind_field->prefix_len > 0 - && dfield_get_len(row_field) != UNIV_SQL_NULL) { + && len != UNIV_SQL_NULL) { const dict_col_t* col = dict_field_get_col(ind_field); @@ -3517,7 +3533,8 @@ row_ins_index_entry_step( ut_ad(dtuple_check_typed(node->row)); - err = row_ins_index_entry_set_vals(node->index, node->entry, node->row); + err = row_ins_index_entry_set_vals(node->index, node->entry, + node->row); if (err != DB_SUCCESS) { DBUG_RETURN(err); diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 3ad4aff8b24..1f9d4b6b8b4 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -683,9 +683,9 @@ row_log_table_delete( fields of the record. */ heap = mem_heap_create( DATA_TRX_ID_LEN - + DTUPLE_EST_ALLOC(unsigned(new_index->n_uniq) + 2)); - old_pk = tuple = dtuple_create( - heap, unsigned(new_index->n_uniq) + 2); + + DTUPLE_EST_ALLOC(new_index->first_user_field())); + old_pk = tuple = dtuple_create(heap, + new_index->first_user_field()); dict_index_copy_types(tuple, new_index, tuple->n_fields); dtuple_set_n_fields_cmp(tuple, new_index->n_uniq); @@ -850,7 +850,7 @@ row_log_table_low_redundant( const bool is_instant = index->online_log->is_instant(index); rec_comp_status_t status = is_instant - ? REC_STATUS_COLUMNS_ADDED : REC_STATUS_ORDINARY; + ? REC_STATUS_INSTANT : REC_STATUS_ORDINARY; size = rec_get_converted_size_temp( index, tuple->fields, tuple->n_fields, &extra_size, status); @@ -904,7 +904,7 @@ row_log_table_low_redundant( *b++ = static_cast<byte>(extra_size); } - if (status == REC_STATUS_COLUMNS_ADDED) { + if (status == REC_STATUS_INSTANT) { ut_ad(is_instant); if (n_fields <= index->online_log->n_core_fields) { status = REC_STATUS_ORDINARY; @@ -969,7 +969,7 @@ row_log_table_low( ut_ad(!"wrong page type"); } #endif /* UNIV_DEBUG */ - ut_ad(!rec_is_metadata(rec, index)); + ut_ad(!rec_is_metadata(rec, *index)); ut_ad(page_rec_is_leaf(rec)); ut_ad(!page_is_comp(page_align(rec)) == !rec_offs_comp(offsets)); /* old_pk=row_log_table_get_pk() [not needed in INSERT] is a prefix @@ -992,7 +992,7 @@ row_log_table_low( ut_ad(page_is_comp(page_align(rec))); ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY - || rec_get_status(rec) == REC_STATUS_COLUMNS_ADDED); + || rec_get_status(rec) == REC_STATUS_INSTANT); const ulint omit_size = REC_N_NEW_EXTRA_BYTES; @@ -1066,7 +1066,7 @@ row_log_table_low( if (is_instant) { *b++ = fake_extra_size - ? REC_STATUS_COLUMNS_ADDED + ? REC_STATUS_INSTANT : rec_get_status(rec); } else { ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY); @@ -1243,19 +1243,16 @@ row_log_table_get_pk( ulint trx_id_offs = index->trx_id_offset; if (!trx_id_offs) { - ulint pos = dict_index_get_sys_col_pos( - index, DATA_TRX_ID); ulint len; - ut_ad(pos > 0); if (!offsets) { offsets = rec_get_offsets( rec, index, NULL, true, - pos + 1, heap); + index->db_trx_id() + 1, heap); } trx_id_offs = rec_get_nth_field_offs( - offsets, pos, &len); + offsets, index->db_trx_id(), &len); ut_ad(len == DATA_TRX_ID_LEN); } @@ -1558,11 +1555,17 @@ row_log_table_apply_convert_mrec( const dict_col_t* col = dict_field_get_col(ind_field); + if (col->is_dropped()) { + /* the column was instantly dropped earlier */ + ut_ad(index->table->instant); + continue; + } + ulint col_no = log->col_map[dict_col_get_no(col)]; if (col_no == ULINT_UNDEFINED) { - /* dropped column */ + /* the column is being dropped now */ continue; } @@ -1918,8 +1921,7 @@ row_log_table_apply_delete( btr_pcur_t pcur; ulint* offsets; - ut_ad(rec_offs_n_fields(moffsets) - == dict_index_get_n_unique(index) + 2); + ut_ad(rec_offs_n_fields(moffsets) == index->first_user_field()); ut_ad(!rec_offs_any_extern(moffsets)); /* Convert the row to a search tuple. */ @@ -2482,8 +2484,7 @@ row_log_table_apply_op( /* The ROW_T_DELETE record was converted by rec_convert_dtuple_to_temp() using new_index. */ ut_ad(!new_index->is_instant()); - rec_offs_set_n_fields(offsets, - unsigned(new_index->n_uniq) + 2); + rec_offs_set_n_fields(offsets, new_index->first_user_field()); rec_init_offsets_temp(mrec, new_index, offsets); next_mrec = mrec + rec_offs_data_size(offsets); if (next_mrec > mrec_end) { @@ -2575,7 +2576,7 @@ row_log_table_apply_op( rec_convert_dtuple_to_temp() using new_index. */ ut_ad(!new_index->is_instant()); rec_offs_set_n_fields(offsets, - unsigned(new_index->n_uniq) + 2); + new_index->first_user_field()); rec_init_offsets_temp(mrec, new_index, offsets); next_mrec = mrec + rec_offs_data_size(offsets); @@ -2585,13 +2586,12 @@ row_log_table_apply_op( /* Copy the PRIMARY KEY fields and DB_TRX_ID, DB_ROLL_PTR from mrec to old_pk. */ - old_pk = dtuple_create( - heap, unsigned(new_index->n_uniq) + 2); + old_pk = dtuple_create(heap, + new_index->first_user_field()); dict_index_copy_types(old_pk, new_index, old_pk->n_fields); - for (ulint i = 0; - i < dict_index_get_n_unique(new_index) + 2; + for (ulint i = 0; i < new_index->first_user_field(); i++) { const void* field; ulint len; @@ -2742,8 +2742,8 @@ row_log_table_apply_ops( dict_index_t* new_index = dict_table_get_first_index( new_table); const ulint i = 1 + REC_OFFS_HEADER_SIZE - + ut_max(dict_index_get_n_fields(index), - dict_index_get_n_unique(new_index) + 2); + + std::max<ulint>(index->n_fields, + new_index->first_user_field()); const ulint new_trx_id_col = dict_col_get_clust_pos( dict_table_get_sys_col(new_table, DATA_TRX_ID), new_index); trx_t* trx = thr_get_trx(thr); @@ -3203,7 +3203,8 @@ row_log_allocate( log->head.total = 0; log->path = path; log->n_core_fields = index->n_core_fields; - ut_ad(!table || log->is_instant(index) == index->is_instant()); + ut_ad(!table || log->is_instant(index) + == (index->n_core_fields < index->n_fields)); log->allow_not_null = allow_not_null; log->old_table = old_table; log->n_rows = 0; diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index f5a690ce2f2..17f8d6cd082 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1862,7 +1862,7 @@ row_merge_read_clustered_index( btr_pcur_open_at_index_side( true, clust_index, BTR_SEARCH_LEAF, &pcur, true, 0, &mtr); btr_pcur_move_to_next_user_rec(&pcur, &mtr); - if (rec_is_metadata(btr_pcur_get_rec(&pcur), clust_index)) { + if (rec_is_metadata(btr_pcur_get_rec(&pcur), *clust_index)) { ut_ad(btr_pcur_is_on_user_rec(&pcur)); /* Skip the metadata pseudo-record. */ } else { diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 5b69663b0db..c88bfcb7e1c 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -34,7 +34,6 @@ Created 9/17/2000 Heikki Tuuri #include "btr0sea.h" #include "dict0boot.h" #include "dict0crea.h" -#include <sql_const.h> #include "dict0dict.h" #include "dict0load.h" #include "dict0priv.h" @@ -329,6 +328,7 @@ row_mysql_read_geometry( ulint col_len) /*!< in: MySQL format length */ { byte* data; + ut_ad(col_len > 8); *len = mach_read_from_n_little_endian(ref, col_len - 8); @@ -828,7 +828,8 @@ row_create_prebuilt( clust_index = dict_table_get_first_index(table); /* Make sure that search_tuple is long enough for clustered index */ - ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields); + ut_a(2 * unsigned(table->n_cols) >= unsigned(clust_index->n_fields) + - clust_index->table->n_dropped()); ref_len = dict_index_get_n_unique(clust_index); @@ -2841,11 +2842,15 @@ row_mysql_table_id_reassign( dberr_t err; pars_info_t* info = pars_info_create(); - dict_hdr_get_new_id(new_id, NULL, NULL, table, false); + dict_hdr_get_new_id(new_id, NULL, NULL); pars_info_add_ull_literal(info, "old_id", table->id); pars_info_add_ull_literal(info, "new_id", *new_id); + /* Note: This cannot be rolled back. Rollback would see the + UPDATE SYS_INDEXES as two operations: DELETE and INSERT. + It would invoke btr_free_if_exists() when rolling back the + INSERT, effectively dropping all indexes of the table. */ err = que_eval_sql( info, "PROCEDURE RENUMBER_TABLE_PROC () IS\n" @@ -3134,6 +3139,12 @@ row_discard_tablespace_for_mysql( err = row_discard_tablespace_foreign_key_checks(trx, table); if (err == DB_SUCCESS) { + /* Note: This cannot be rolled back. + Rollback would see the UPDATE SYS_INDEXES + as two operations: DELETE and INSERT. + It would invoke btr_free_if_exists() + when rolling back the INSERT, effectively + dropping all indexes of the table. */ err = row_discard_tablespace(trx, table); } } diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 5699c8b2f56..f0652ed3d54 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -127,33 +127,32 @@ row_purge_remove_clust_if_poss_low( purge_node_t* node, /*!< in/out: row purge node */ ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */ { - dict_index_t* index; - bool success = true; - mtr_t mtr; - rec_t* rec; - mem_heap_t* heap = NULL; - ulint* offsets; - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - rec_offs_init(offsets_); - ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S) || node->vcol_info.is_used()); - index = dict_table_get_first_index(node->table); + dict_index_t* index = dict_table_get_first_index(node->table); log_free_check(); - mtr_start(&mtr); - index->set_modified(mtr); + + mtr_t mtr; + mtr.start(); if (!row_purge_reposition_pcur(mode, node, &mtr)) { /* The record was already removed. */ - goto func_exit; + mtr.commit(); + return true; } - rec = btr_pcur_get_rec(&node->pcur); + ut_d(const bool was_instant = !!index->table->instant); + index->set_modified(mtr); - offsets = rec_get_offsets( + rec_t* rec = btr_pcur_get_rec(&node->pcur); + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + rec_offs_init(offsets_); + mem_heap_t* heap = NULL; + ulint* offsets = rec_get_offsets( rec, index, offsets_, true, ULINT_UNDEFINED, &heap); + bool success = true; if (node->roll_ptr != row_get_rec_roll_ptr(rec, index, offsets)) { /* Someone else has modified the record later: do not remove */ @@ -186,6 +185,10 @@ row_purge_remove_clust_if_poss_low( } } + /* Prove that dict_index_t::clear_instant_alter() was + not called with index->table->instant != NULL. */ + ut_ad(!was_instant || index->table->instant); + func_exit: if (heap) { mem_heap_free(heap); @@ -845,8 +848,9 @@ static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr) became purgeable) */ if (node->roll_ptr == row_get_rec_roll_ptr(rec, index, offsets)) { - ut_ad(!rec_get_deleted_flag(rec, - rec_offs_comp(offsets))); + ut_ad(!rec_get_deleted_flag( + rec, rec_offs_comp(offsets)) + || rec_is_alter_metadata(rec, *index)); DBUG_LOG("purge", "reset DB_TRX_ID=" << ib::hex(row_get_rec_trx_id( rec, index, offsets))); diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc index 352407b6ee5..d77cc1e33dc 100644 --- a/storage/innobase/row/row0quiesce.cc +++ b/storage/innobase/row/row0quiesce.cc @@ -70,17 +70,16 @@ row_quiesce_write_index_fields( return(DB_IO_ERROR); } + const char* field_name = field->name ? field->name : ""; /* Include the NUL byte in the length. */ - ib_uint32_t len = static_cast<ib_uint32_t>(strlen(field->name) + 1); - ut_a(len > 1); - + ib_uint32_t len = static_cast<ib_uint32_t>(strlen(field_name) + 1); mach_write_to_4(row, len); DBUG_EXECUTE_IF("ib_export_io_write_failure_10", close(fileno(file));); if (fwrite(row, 1, sizeof(len), file) != sizeof(len) - || fwrite(field->name, 1, len, file) != len) { + || fwrite(field_name, 1, len, file) != len) { ib_senderrf( thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index d419fd9998f..3c03f8277ae 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -197,7 +197,7 @@ row_build_index_entry_low( { dtuple_t* entry; ulint entry_len; - ulint i; + ulint i = 0; ulint num_v = 0; entry_len = dict_index_get_n_fields(index); @@ -217,90 +217,87 @@ row_build_index_entry_low( } else { dtuple_set_n_fields_cmp( entry, dict_index_get_n_unique_in_tree(index)); - } + if (dict_index_is_spatial(index)) { + /* Set the MBR field */ + if (!row_build_spatial_index_key( + index, ext, + dtuple_get_nth_field(entry, 0), + dtuple_get_nth_field( + row, + dict_index_get_nth_field(index, i) + ->col->ind), flag, heap)) { + return NULL; + } - for (i = 0; i < entry_len + num_v; i++) { - const dict_field_t* ind_field = NULL; - const dict_col_t* col; - ulint col_no = 0; - dfield_t* dfield; - dfield_t* dfield2; - ulint len; - - if (i >= entry_len) { - /* This is to insert new rows to cluster index */ - ut_ad(dict_index_is_clust(index) - && flag == ROW_BUILD_FOR_INSERT); - dfield = dtuple_get_nth_v_field(entry, i - entry_len); - col = &dict_table_get_nth_v_col( - index->table, i - entry_len)->m_col; + i = 1; + } + } - } else { - ind_field = dict_index_get_nth_field(index, i); - col = ind_field->col; - col_no = dict_col_get_no(col); - dfield = dtuple_get_nth_field(entry, i); + for (; i < entry_len; i++) { + const dict_field_t& f = index->fields[i]; + dfield_t* dfield = dtuple_get_nth_field(entry, i); + + if (f.col->is_dropped()) { + ut_ad(index->is_primary()); + ut_ad(index->is_instant()); + ut_ad(!f.col->is_virtual()); + dict_col_copy_type(f.col, &dfield->type); + if (f.col->is_nullable()) { + dfield_set_null(dfield); + } else { + dfield_set_data(dfield, field_ref_zero, + f.fixed_len); + } + continue; } - compile_time_assert(DATA_MISSING == 0); + const dfield_t* dfield2; - if (col->is_virtual()) { - const dict_v_col_t* v_col - = reinterpret_cast<const dict_v_col_t*>(col); + if (f.col->is_virtual()) { + const dict_v_col_t* v_col + = reinterpret_cast<const dict_v_col_t*>(f.col); ut_ad(v_col->v_pos < dtuple_get_n_v_fields(row)); dfield2 = dtuple_get_nth_v_field(row, v_col->v_pos); ut_ad(dfield_is_null(dfield2) || dfield_get_len(dfield2) == 0 || dfield2->data); + ut_ad(!dfield_is_ext(dfield2)); + if (UNIV_UNLIKELY(dfield2->type.mtype + == DATA_MISSING)) { + ut_ad(flag == ROW_BUILD_FOR_PURGE); + return(NULL); + } } else { - dfield2 = dtuple_get_nth_field(row, col_no); - ut_ad(dfield_get_type(dfield2)->mtype == DATA_MISSING - || (!(dfield_get_type(dfield2)->prtype - & DATA_VIRTUAL))); - } - - if (UNIV_UNLIKELY(dfield_get_type(dfield2)->mtype - == DATA_MISSING)) { - /* The field has not been initialized in the row. - This should be from trx_undo_rec_get_partial_row(). */ - return(NULL); - } - -#ifdef UNIV_DEBUG - if (dfield_get_type(dfield2)->prtype & DATA_VIRTUAL - && dict_index_is_clust(index)) { - ut_ad(flag == ROW_BUILD_FOR_INSERT); - } -#endif /* UNIV_DEBUG */ - - /* Special handle spatial index, set the first field - which is for store MBR. */ - if (dict_index_is_spatial(index) && i == 0) { - if (!row_build_spatial_index_key( - index, ext, dfield, dfield2, flag, heap)) { - return NULL; + dfield2 = dtuple_get_nth_field(row, f.col->ind); + if (UNIV_UNLIKELY(dfield2->type.mtype + == DATA_MISSING)) { + /* The field has not been initialized in + the row. This should be from + trx_undo_rec_get_partial_row(). */ + return(NULL); } - continue; + ut_ad(!(dfield2->type.prtype & DATA_VIRTUAL)); } - len = dfield_get_len(dfield2); + compile_time_assert(DATA_MISSING == 0); - dfield_copy(dfield, dfield2); + *dfield = *dfield2; if (dfield_is_null(dfield)) { continue; } - if ((!ind_field || ind_field->prefix_len == 0) + ulint len = dfield_get_len(dfield); + + if (f.prefix_len == 0 && (!dfield_is_ext(dfield) || dict_index_is_clust(index))) { /* The dfield_copy() above suffices for columns that are stored in-page, or for clustered index record columns that are not - part of a column prefix in the PRIMARY KEY, - or for virtaul columns in cluster index record. */ + part of a column prefix in the PRIMARY KEY. */ continue; } @@ -311,11 +308,11 @@ row_build_index_entry_low( index record with an off-page column is when it is a column prefix index. If atomic_blobs, also fully indexed long columns may be stored off-page. */ - ut_ad(col->ord_part); + ut_ad(f.col->ord_part); - if (ext && !col->is_virtual()) { + if (ext && !f.col->is_virtual()) { /* See if the column is stored externally. */ - const byte* buf = row_ext_lookup(ext, col_no, + const byte* buf = row_ext_lookup(ext, f.col->ind, &len); if (UNIV_LIKELY_NULL(buf)) { if (UNIV_UNLIKELY(buf == field_ref_zero)) { @@ -324,7 +321,7 @@ row_build_index_entry_low( dfield_set_data(dfield, buf, len); } - if (ind_field->prefix_len == 0) { + if (f.prefix_len == 0) { /* If ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED, we can have a secondary index on an entire column @@ -351,16 +348,33 @@ row_build_index_entry_low( } /* If a column prefix index, take only the prefix. */ - if (ind_field->prefix_len) { + if (f.prefix_len) { len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminlen, col->mbmaxlen, - ind_field->prefix_len, len, + f.col->prtype, + f.col->mbminlen, f.col->mbmaxlen, + f.prefix_len, len, static_cast<char*>(dfield_get_data(dfield))); dfield_set_len(dfield, len); } } - return(entry); + for (i = num_v; i--; ) { + ut_ad(index->is_primary()); + ut_ad(flag == ROW_BUILD_FOR_INSERT); + dfield_t* dfield = dtuple_get_nth_v_field(entry, i); + const dict_v_col_t* v_col = dict_table_get_nth_v_col( + index->table, i); + ut_ad(!v_col->m_col.is_dropped()); + ut_ad(v_col->v_pos < dtuple_get_n_v_fields(row)); + const dfield_t* dfield2 = dtuple_get_nth_v_field( + row, v_col->v_pos); + ut_ad(dfield_is_null(dfield2) || + dfield_get_len(dfield2) == 0 || dfield2->data); + ut_ad(dfield2->type.mtype != DATA_MISSING); + *dfield = *dfield2; + } + + return entry; } /** An inverse function to row_build_index_entry. Builds a row from a @@ -497,11 +511,23 @@ row_build_low( j = 0; + const dict_field_t* ind_field = index->fields; + for (ulint i = 0; i < rec_offs_n_fields(offsets); i++) { - const dict_field_t* ind_field - = dict_index_get_nth_field(index, i); + if (i == index->first_user_field() + && rec_is_alter_metadata(rec, *index)) { + ut_ad(rec_offs_nth_extern(offsets, i)); + ut_d(ulint len); + ut_d(rec_get_nth_field_offs(offsets, i, &len)); + ut_ad(len == FIELD_REF_SIZE); + continue; + } + + ut_ad(ind_field < &index->fields[index->n_fields]); - if (ind_field->prefix_len) { + const dict_col_t* col = dict_field_get_col(ind_field); + + if ((ind_field++)->prefix_len) { /* Column prefixes can only occur in key fields, which cannot be stored externally. For a column prefix, there should also be the full @@ -511,10 +537,11 @@ row_build_low( continue; } - const dict_col_t* col - = dict_field_get_col(ind_field); - ulint col_no - = dict_col_get_no(col); + if (col->is_dropped()) { + continue; + } + + ulint col_no = dict_col_get_no(col); if (col_map) { col_no = col_map[col_no]; @@ -526,6 +553,7 @@ row_build_low( } dfield_t* dfield = dtuple_get_nth_field(row, col_no); + const void* field = rec_get_nth_field( copy, offsets, i, &len); if (len == UNIV_SQL_DEFAULT) { @@ -669,15 +697,19 @@ row_build_w_add_vcol( } /** Convert an index record to a data tuple. -@tparam def whether the index->instant_field_value() needs to be accessed -@param[in] rec index record -@param[in] index index -@param[in] offsets rec_get_offsets(rec, index) -@param[out] n_ext number of externally stored columns -@param[in,out] heap memory heap for allocations +@tparam metadata whether the index->instant_field_value() needs to be accessed +@tparam mblob 1 if rec_is_alter_metadata(); +2 if we want converted metadata corresponding to info_bits +@param[in] rec index record +@param[in] index index +@param[in] offsets rec_get_offsets(rec, index) +@param[out] n_ext number of externally stored columns +@param[in,out] heap memory heap for allocations +@param[in] info_bits (only used if mblob=2) +@param[in] pad (only used if mblob=2) @return index entry built; does not set info_bits, and the data fields in the entry will point directly to rec */ -template<bool def> +template<bool metadata, int mblob = 0> static inline dtuple_t* row_rec_to_index_entry_impl( @@ -685,44 +717,66 @@ row_rec_to_index_entry_impl( const dict_index_t* index, const ulint* offsets, ulint* n_ext, - mem_heap_t* heap) + mem_heap_t* heap, + ulint info_bits = 0, + bool pad = false) { - dtuple_t* entry; - dfield_t* dfield; - ulint i; - const byte* field; - ulint len; - ulint rec_len; - ut_ad(rec != NULL); ut_ad(heap != NULL); ut_ad(index != NULL); - ut_ad(def || !rec_offs_any_default(offsets)); - + ut_ad(!mblob || index->is_primary()); + ut_ad(!mblob || !index->table->is_temporary()); + ut_ad(!mblob || !dict_index_is_spatial(index)); + compile_time_assert(!mblob || metadata); + compile_time_assert(mblob <= 2); /* Because this function may be invoked by row0merge.cc on a record whose header is in different format, the check rec_offs_validate(rec, index, offsets) must be avoided here. */ ut_ad(n_ext); *n_ext = 0; - rec_len = rec_offs_n_fields(offsets); - - entry = dtuple_create(heap, rec_len); + const bool got = mblob == 2 && rec_is_alter_metadata(rec, *index); + ulint rec_len = rec_offs_n_fields(offsets); + if (mblob == 2) { + ut_ad(info_bits == REC_INFO_METADATA_ALTER + || info_bits == REC_INFO_METADATA_ADD); + ut_ad(rec_len <= ulint(index->n_fields + got)); + if (pad) { + rec_len = ulint(index->n_fields) + + (info_bits == REC_INFO_METADATA_ALTER); + } else if (!got && info_bits == REC_INFO_METADATA_ALTER) { + rec_len++; + } + } else { + ut_ad(info_bits == 0); + ut_ad(!pad); + } + dtuple_t* entry = dtuple_create(heap, rec_len); + dfield_t* dfield = entry->fields; dtuple_set_n_fields_cmp(entry, dict_index_get_n_unique_in_tree(index)); - ut_ad(rec_len == dict_index_get_n_fields(index) + ut_ad(mblob == 2 + || rec_len == dict_index_get_n_fields(index) + uint(mblob == 1) /* a record for older SYS_INDEXES table (missing merge_threshold column) is acceptable. */ - || (index->table->id == DICT_INDEXES_ID + || (!index->table->is_temporary() + && index->table->id == DICT_INDEXES_ID && rec_len == dict_index_get_n_fields(index) - 1)); - dict_index_copy_types(entry, index, rec_len); - - for (i = 0; i < rec_len; i++) { + ulint i; + for (i = 0; i < (mblob ? index->first_user_field() : rec_len); + i++, dfield++) { + dict_col_copy_type(dict_index_get_nth_col(index, i), + &dfield->type); + if (!mblob + && dict_index_is_spatial(index) + && DATA_GEOMETRY_MTYPE(dfield->type.mtype)) { + dfield->type.prtype |= DATA_GIS_MBR; + } - dfield = dtuple_get_nth_field(entry, i); - field = def + ulint len; + const byte* field = metadata ? rec_get_nth_cfield(rec, index, offsets, i, &len) : rec_get_nth_field(rec, offsets, i, &len); @@ -730,12 +784,80 @@ row_rec_to_index_entry_impl( if (rec_offs_nth_extern(offsets, i)) { dfield_set_ext(dfield); - (*n_ext)++; + ++*n_ext; + } + } + + if (mblob) { + ulint len; + const byte* field; + ulint j = i; + + if (mblob == 2) { + const bool want = info_bits == REC_INFO_METADATA_ALTER; + if (got == want) { + if (got) { + goto copy_metadata; + } + } else { + if (want) { + /* Allocate a placeholder for + adding metadata in an update. */ + len = FIELD_REF_SIZE; + field = static_cast<byte*>( + mem_heap_zalloc(heap, len)); + /* In reality there is one fewer + field present in the record. */ + rec_len--; + goto init_metadata; + } + + /* Skip the undesired metadata blob + (for example, when rolling back an + instant ALTER TABLE). */ + i++; + } + goto copy_user_fields; + } +copy_metadata: + ut_ad(rec_offs_nth_extern(offsets, i)); + field = rec_get_nth_field(rec, offsets, i++, &len); +init_metadata: + dfield->type.metadata_blob_init(); + ut_ad(len == FIELD_REF_SIZE); + dfield_set_data(dfield, field, len); + dfield_set_ext(dfield++); + ++*n_ext; +copy_user_fields: + for (; i < rec_len; i++, dfield++) { + dict_col_copy_type(dict_index_get_nth_col(index, j++), + &dfield->type); + if (mblob == 2 && pad + && i >= rec_offs_n_fields(offsets)) { + field = index->instant_field_value(j - 1, + &len); + dfield_set_data(dfield, field, len); + continue; + } + + field = rec_get_nth_field(rec, offsets, i, &len); + dfield_set_data(dfield, field, len); + + if (rec_offs_nth_extern(offsets, i)) { + dfield_set_ext(dfield); + ++*n_ext; + } } } + if (mblob == 2) { + ulint n_fields = ulint(dfield - entry->fields); + ut_ad(entry->n_fields >= n_fields); + entry->n_fields = n_fields; + } + ut_ad(dfield == entry->fields + entry->n_fields); ut_ad(dtuple_check_typed(entry)); - return(entry); + return entry; } /** Convert an index record to a data tuple. @@ -771,25 +893,26 @@ row_rec_to_index_entry( mem_heap_t* heap) /*!< in: memory heap from which the memory needed is allocated */ { - dtuple_t* entry; - byte* buf; - const rec_t* copy_rec; - ut_ad(rec != NULL); ut_ad(heap != NULL); ut_ad(index != NULL); ut_ad(rec_offs_validate(rec, index, offsets)); /* Take a copy of rec to heap */ - buf = static_cast<byte*>( - mem_heap_alloc(heap, rec_offs_size(offsets))); - - copy_rec = rec_copy(buf, rec, offsets); + const rec_t* copy_rec = rec_copy( + static_cast<byte*>(mem_heap_alloc(heap, + rec_offs_size(offsets))), + rec, offsets); rec_offs_make_valid(copy_rec, index, true, const_cast<ulint*>(offsets)); - entry = row_rec_to_index_entry_impl<true>( - copy_rec, index, offsets, n_ext, heap); + + dtuple_t* entry = rec_is_alter_metadata(copy_rec, *index) + ? row_rec_to_index_entry_impl<true,1>( + copy_rec, index, offsets, n_ext, heap) + : row_rec_to_index_entry_impl<true>( + copy_rec, index, offsets, n_ext, heap); + rec_offs_make_valid(rec, index, true, const_cast<ulint*>(offsets)); @@ -799,6 +922,51 @@ row_rec_to_index_entry( return(entry); } +/** Convert a metadata record to a data tuple. +@param[in] rec metadata record +@param[in] index clustered index after instant ALTER TABLE +@param[in] offsets rec_get_offsets(rec) +@param[out] n_ext number of externally stored fields +@param[in,out] heap memory heap for allocations +@param[in] info_bits the info_bits after an update +@param[in] pad whether to pad to index->n_fields */ +dtuple_t* +row_metadata_to_tuple( + const rec_t* rec, + const dict_index_t* index, + const ulint* offsets, + ulint* n_ext, + mem_heap_t* heap, + ulint info_bits, + bool pad) +{ + ut_ad(info_bits == REC_INFO_METADATA_ALTER + || info_bits == REC_INFO_METADATA_ADD); + ut_ad(rec_is_metadata(rec, *index)); + ut_ad(rec_offs_validate(rec, index, offsets)); + + const rec_t* copy_rec = rec_copy( + static_cast<byte*>(mem_heap_alloc(heap, + rec_offs_size(offsets))), + rec, offsets); + + rec_offs_make_valid(copy_rec, index, true, + const_cast<ulint*>(offsets)); + + dtuple_t* entry = info_bits == REC_INFO_METADATA_ALTER + || rec_is_alter_metadata(copy_rec, *index) + ? row_rec_to_index_entry_impl<true,2>( + copy_rec, index, offsets, n_ext, heap, info_bits, pad) + : row_rec_to_index_entry_impl<true>( + copy_rec, index, offsets, n_ext, heap); + + rec_offs_make_valid(rec, index, true, + const_cast<ulint*>(offsets)); + + dtuple_set_info_bits(entry, info_bits); + return entry; +} + /*******************************************************************//** Builds from a secondary index record a row reference with which we can search the clustered index record. @@ -1033,7 +1201,7 @@ row_search_on_row_ref( index = dict_table_get_first_index(table); if (UNIV_UNLIKELY(ref->info_bits != 0)) { - ut_ad(ref->info_bits == REC_INFO_METADATA); + ut_ad(ref->is_metadata()); ut_ad(ref->n_fields <= index->n_uniq); btr_pcur_open_at_index_side(true, index, mode, pcur, true, 0, mtr); diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 58b063a3b05..c997b01846c 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -1487,7 +1487,7 @@ row_sel_try_search_shortcut( const rec_t* rec = btr_pcur_get_rec(&(plan->pcur)); - if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, index)) { + if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) { retry: rw_lock_s_unlock(ahi_latch); return(SEL_RETRY); @@ -1787,7 +1787,7 @@ skip_lock: goto next_rec; } - if (rec_is_metadata(rec, index)) { + if (rec_is_metadata(rec, *index)) { /* Skip the metadata pseudo-record. */ cost_counter++; goto next_rec; @@ -2693,44 +2693,6 @@ row_sel_convert_mysql_key_to_innobase( } /**************************************************************//** -Stores the row id to the prebuilt struct. */ -static -void -row_sel_store_row_id_to_prebuilt( -/*=============================*/ - row_prebuilt_t* prebuilt, /*!< in/out: prebuilt */ - const rec_t* index_rec, /*!< in: record */ - const dict_index_t* index, /*!< in: index of the record */ - const ulint* offsets) /*!< in: rec_get_offsets - (index_rec, index) */ -{ - const byte* data; - ulint len; - - ut_ad(rec_offs_validate(index_rec, index, offsets)); - - data = rec_get_nth_field( - index_rec, offsets, - dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len); - - if (UNIV_UNLIKELY(len != DATA_ROW_ID_LEN)) { - - ib::error() << "Row id field is wrong length " << len << " in" - " index " << index->name - << " of table " << index->table->name - << ", Field number " - << dict_index_get_sys_col_pos(index, DATA_ROW_ID) - << ", record:"; - - rec_print_new(stderr, index_rec, offsets); - putc('\n', stderr); - ut_error; - } - - ut_memcpy(prebuilt->row_id, data, len); -} - -/**************************************************************//** Stores a non-SQL-NULL field in the MySQL format. The counterpart of this function is row_mysql_store_col_in_innobase_format() in row0mysql.cc. */ void @@ -3212,7 +3174,7 @@ row_sel_store_mysql_rec( if (dict_index_is_clust(index) || prebuilt->fts_doc_id_in_read_set) { prebuilt->fts_doc_id = fts_get_doc_id_from_rec( - prebuilt->table, rec, index, NULL); + rec, index, offsets); } } @@ -3364,7 +3326,7 @@ row_sel_get_clust_rec_for_mysql( and is it not unsafe to use RW_NO_LATCH here? */ buf_block_t* block = buf_page_get_gen( btr_pcur_get_block(prebuilt->pcur)->page.id, - dict_table_page_size(sec_index->table), + btr_pcur_get_block(prebuilt->pcur)->page.size, RW_NO_LATCH, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err); mem_heap_t* heap = mem_heap_create(256); @@ -3562,7 +3524,7 @@ sel_restore_position_for_mysql( next: if (btr_pcur_move_to_next(pcur, mtr) && rec_is_metadata(btr_pcur_get_rec(pcur), - pcur->btr_cur.index)) { + *pcur->btr_cur.index)) { btr_pcur_move_to_next(pcur, mtr); } @@ -3578,7 +3540,7 @@ next: prev: if (btr_pcur_is_on_user_rec(pcur) && !moves_up && !rec_is_metadata(btr_pcur_get_rec(pcur), - pcur->btr_cur.index)) { + *pcur->btr_cur.index)) { btr_pcur_move_to_prev(pcur, mtr); } return true; @@ -3855,7 +3817,7 @@ row_sel_try_search_shortcut_for_mysql( BTR_SEARCH_LEAF, pcur, ahi_latch, mtr); rec = btr_pcur_get_rec(pcur); - if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, index)) { + if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) { retry: rw_lock_s_unlock(ahi_latch); return(SEL_RETRY); @@ -5492,11 +5454,19 @@ use_covering_index: } } - if (prebuilt->clust_index_was_generated) { - row_sel_store_row_id_to_prebuilt( - prebuilt, result_rec, - result_rec == rec ? index : clust_index, - offsets); + if (!prebuilt->clust_index_was_generated) { + } else if (result_rec != rec || index->is_primary()) { + memcpy(prebuilt->row_id, result_rec, DATA_ROW_ID_LEN); + } else { + ulint len; + const byte* data = rec_get_nth_field( + result_rec, offsets, index->n_fields - 1, + &len); + ut_ad(dict_index_get_nth_col(index, + index->n_fields - 1) + ->prtype == (DATA_ROW_ID | DATA_NOT_NULL)); + ut_ad(len == DATA_ROW_ID_LEN); + memcpy(prebuilt->row_id, data, DATA_ROW_ID_LEN); } } diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc deleted file mode 100644 index ce98717b3c9..00000000000 --- a/storage/innobase/row/row0trunc.cc +++ /dev/null @@ -1,1966 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2013, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file row/row0trunc.cc -TRUNCATE implementation - -Created 2013-04-12 Sunny Bains -*******************************************************/ - -#include "row0trunc.h" -#include "btr0sea.h" -#include "pars0pars.h" -#include "btr0pcur.h" -#include "dict0crea.h" -#include "dict0stats.h" -#include "dict0stats_bg.h" -#include "lock0lock.h" -#include "fts0fts.h" -#include "ibuf0ibuf.h" -#include "os0file.h" -#include "que0que.h" -#include "trx0undo.h" - -/* FIXME: For temporary tables, use a simple approach of btr_free() -and btr_create() of each index tree. */ - -/* FIXME: For persistent tables, remove this code in MDEV-11655 -and use a combination of the transactional DDL log to make atomic the -low-level operations ha_innobase::delete_table(), ha_innobase::create(). */ - -bool truncate_t::s_fix_up_active = false; -truncate_t::tables_t truncate_t::s_tables; -truncate_t::truncated_tables_t truncate_t::s_truncated_tables; - -/** -Iterator over the the raw records in an index, doesn't support MVCC. */ -class IndexIterator { - -public: - /** - Iterate over an indexes records - @param index index to iterate over */ - explicit IndexIterator(dict_index_t* index) - : - m_index(index) - { - /* Do nothing */ - } - - /** - Search for key. Position the cursor on a record GE key. - @return DB_SUCCESS or error code. */ - dberr_t search(dtuple_t& key, bool noredo) - { - mtr_start(&m_mtr); - - if (noredo) { - mtr_set_log_mode(&m_mtr, MTR_LOG_NO_REDO); - } - - btr_pcur_open_on_user_rec( - m_index, - &key, - PAGE_CUR_GE, - BTR_MODIFY_LEAF, - &m_pcur, &m_mtr); - - return(DB_SUCCESS); - } - - /** - Iterate over all the records - @return DB_SUCCESS or error code */ - template <typename Callback> - dberr_t for_each(Callback& callback) - { - dberr_t err = DB_SUCCESS; - - for (;;) { - - if (!btr_pcur_is_on_user_rec(&m_pcur) - || !callback.match(&m_pcur)) { - - /* The end of of the index has been reached. */ - err = DB_END_OF_INDEX; - break; - } - - rec_t* rec = btr_pcur_get_rec(&m_pcur); - - if (!rec_get_deleted_flag(rec, FALSE)) { - - err = callback(&m_mtr, &m_pcur); - - if (err != DB_SUCCESS) { - break; - } - } - - btr_pcur_move_to_next_user_rec(&m_pcur, &m_mtr); - } - - btr_pcur_close(&m_pcur); - mtr_commit(&m_mtr); - - return(err == DB_END_OF_INDEX ? DB_SUCCESS : err); - } - -private: - // Disable copying - IndexIterator(const IndexIterator&); - IndexIterator& operator=(const IndexIterator&); - -private: - mtr_t m_mtr; - btr_pcur_t m_pcur; - dict_index_t* m_index; -}; - -/** SysIndex table iterator, iterate over records for a table. */ -class SysIndexIterator { - -public: - /** - Iterate over all the records that match the table id. - @return DB_SUCCESS or error code */ - template <typename Callback> - dberr_t for_each(Callback& callback) const - { - dict_index_t* sys_index; - byte buf[DTUPLE_EST_ALLOC(1)]; - dtuple_t* tuple = - dtuple_create_from_mem(buf, sizeof(buf), 1, 0); - dfield_t* dfield = dtuple_get_nth_field(tuple, 0); - - dfield_set_data( - dfield, - callback.table_id(), - sizeof(*callback.table_id())); - - sys_index = dict_table_get_first_index(dict_sys->sys_indexes); - - dict_index_copy_types(tuple, sys_index, 1); - - IndexIterator iterator(sys_index); - - /* Search on the table id and position the cursor - on GE table_id. */ - iterator.search(*tuple, callback.get_logging_status()); - - return(iterator.for_each(callback)); - } -}; - -/** Generic callback abstract class. */ -class Callback -{ - -public: - /** - Constructor - @param table_id id of the table being operated. - @param noredo if true turn off logging. */ - Callback(table_id_t table_id, bool noredo) - : - m_id(), - m_noredo(noredo) - { - /* Convert to storage byte order. */ - mach_write_to_8(&m_id, table_id); - } - - /** - Destructor */ - virtual ~Callback() - { - /* Do nothing */ - } - - /** - @param pcur persistent cursor used for iteration - @return true if the table id column matches. */ - bool match(btr_pcur_t* pcur) const - { - ulint len; - const byte* field; - rec_t* rec = btr_pcur_get_rec(pcur); - - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_INDEXES__TABLE_ID, &len); - - ut_ad(len == 8); - - return(memcmp(&m_id, field, len) == 0); - } - - /** - @return pointer to table id storage format buffer */ - const table_id_t* table_id() const - { - return(&m_id); - } - - /** - @return return if logging needs to be turned off. */ - bool get_logging_status() const - { - return(m_noredo); - } - -protected: - // Disably copying - Callback(const Callback&); - Callback& operator=(const Callback&); - -protected: - /** Table id in storage format */ - table_id_t m_id; - - /** Turn off logging. */ - const bool m_noredo; -}; - -/** -Scan to find out truncate log file from the given directory path. - -@param dir_path look for log directory in following path. -@param log_files cache to hold truncate log file name found. -@return DB_SUCCESS or error code. */ -dberr_t -TruncateLogParser::scan( - const char* dir_path, - trunc_log_files_t& log_files) -{ - os_file_dir_t dir; - os_file_stat_t fileinfo; - dberr_t err = DB_SUCCESS; - const ulint dir_len = strlen(dir_path); - - /* Scan and look out for the truncate log files. */ - dir = os_file_opendir(dir_path, true); - if (dir == NULL) { - return(DB_IO_ERROR); - } - - while (fil_file_readdir_next_file( - &err, dir_path, dir, &fileinfo) == 0) { - - ulint nm_len = strlen(fileinfo.name); - - if (fileinfo.type == OS_FILE_TYPE_FILE - && nm_len > sizeof "ib_trunc.log" - && (0 == strncmp(fileinfo.name + nm_len - - ((sizeof "trunc.log") - 1), - "trunc.log", (sizeof "trunc.log") - 1)) - && (0 == strncmp(fileinfo.name, "ib_", 3))) { - - if (fileinfo.size == 0) { - /* Truncate log not written. Remove the file. */ - os_file_delete( - innodb_log_file_key, fileinfo.name); - continue; - } - - /* Construct file name by appending directory path */ - ulint sz = dir_len + 22 + 22 + sizeof "ib_trunc.log"; - char* log_file_name = UT_NEW_ARRAY_NOKEY(char, sz); - if (log_file_name == NULL) { - err = DB_OUT_OF_MEMORY; - break; - } - memset(log_file_name, 0, sz); - - strncpy(log_file_name, dir_path, dir_len); - ulint log_file_name_len = strlen(log_file_name); - if (log_file_name[log_file_name_len - 1] - != OS_PATH_SEPARATOR) { - - log_file_name[log_file_name_len] - = OS_PATH_SEPARATOR; - log_file_name_len = strlen(log_file_name); - } - strcat(log_file_name, fileinfo.name); - log_files.push_back(log_file_name); - } - } - - os_file_closedir(dir); - - return(err); -} - -/** -Parse the log file and populate table to truncate information. -(Add this table to truncate information to central vector that is then - used by truncate fix-up routine to fix-up truncate action of the table.) - -@param log_file_name log file to parse -@return DB_SUCCESS or error code. */ -dberr_t -TruncateLogParser::parse( - const char* log_file_name) -{ - dberr_t err = DB_SUCCESS; - truncate_t* truncate = NULL; - - /* Open the file and read magic-number to findout if truncate action - was completed. */ - bool ret; - os_file_t handle = os_file_create_simple( - innodb_log_file_key, log_file_name, - OS_FILE_OPEN, OS_FILE_READ_ONLY, srv_read_only_mode, &ret); - if (!ret) { - ib::error() << "Error opening truncate log file: " - << log_file_name; - return(DB_IO_ERROR); - } - - ulint sz = srv_page_size; - void* buf = ut_zalloc_nokey(sz + srv_page_size); - if (buf == 0) { - os_file_close(handle); - return(DB_OUT_OF_MEMORY); - } - - IORequest request(IORequest::READ); - - /* Align the memory for file i/o if we might have O_DIRECT set*/ - byte* log_buf = static_cast<byte*>(ut_align(buf, srv_page_size)); - - do { - err = os_file_read(request, handle, log_buf, 0, sz); - - if (err != DB_SUCCESS) { - os_file_close(handle); - break; - } - - if (mach_read_from_4(log_buf) == 32743712) { - - /* Truncate action completed. Avoid parsing the file. */ - os_file_close(handle); - - os_file_delete(innodb_log_file_key, log_file_name); - break; - } - - if (truncate == NULL) { - truncate = UT_NEW_NOKEY(truncate_t(log_file_name)); - if (truncate == NULL) { - os_file_close(handle); - err = DB_OUT_OF_MEMORY; - break; - } - } - - err = truncate->parse(log_buf + 4, log_buf + sz - 4); - - if (err != DB_SUCCESS) { - - ut_ad(err == DB_FAIL); - - ut_free(buf); - buf = 0; - - sz *= 2; - - buf = ut_zalloc_nokey(sz + srv_page_size); - - if (buf == 0) { - os_file_close(handle); - err = DB_OUT_OF_MEMORY; - UT_DELETE(truncate); - truncate = NULL; - break; - } - - log_buf = static_cast<byte*>( - ut_align(buf, srv_page_size)); - } - } while (err != DB_SUCCESS); - - ut_free(buf); - - if (err == DB_SUCCESS && truncate != NULL) { - truncate_t::add(truncate); - os_file_close(handle); - } - - return(err); -} - -/** -Scan and Parse truncate log files. - -@param dir_path look for log directory in following path -@return DB_SUCCESS or error code. */ -dberr_t -TruncateLogParser::scan_and_parse( - const char* dir_path) -{ - dberr_t err; - trunc_log_files_t log_files; - - /* Scan and trace all the truncate log files. */ - err = TruncateLogParser::scan(dir_path, log_files); - - /* Parse truncate lof files if scan was successful. */ - if (err == DB_SUCCESS) { - - for (ulint i = 0; - i < log_files.size() && err == DB_SUCCESS; - i++) { - err = TruncateLogParser::parse(log_files[i]); - } - } - - trunc_log_files_t::const_iterator end = log_files.end(); - for (trunc_log_files_t::const_iterator it = log_files.begin(); - it != end; - ++it) { - if (*it != NULL) { - UT_DELETE_ARRAY(*it); - } - } - log_files.clear(); - - return(err); -} - -/** Callback to drop indexes during TRUNCATE */ -class DropIndex : public Callback { - -public: - /** - Constructor - - @param[in,out] table Table to truncate - @param[in] noredo whether to disable redo logging */ - DropIndex(dict_table_t* table, bool noredo) - : - Callback(table->id, noredo), - m_table(table) - { - /* No op */ - } - - /** - @param mtr mini-transaction covering the read - @param pcur persistent cursor used for reading - @return DB_SUCCESS or error code */ - dberr_t operator()(mtr_t* mtr, btr_pcur_t* pcur) const; - -private: - /** Table to be truncated */ - dict_table_t* m_table; -}; - -/** Callback to create the indexes during TRUNCATE */ -class CreateIndex : public Callback { - -public: - /** - Constructor - - @param[in,out] table Table to truncate - @param[in] noredo whether to disable redo logging */ - CreateIndex(dict_table_t* table, bool noredo) - : - Callback(table->id, noredo), - m_table(table) - { - /* No op */ - } - - /** - Create the new index and update the root page number in the - SysIndex table. - - @param mtr mini-transaction covering the read - @param pcur persistent cursor used for reading - @return DB_SUCCESS or error code */ - dberr_t operator()(mtr_t* mtr, btr_pcur_t* pcur) const; - -private: - // Disably copying - CreateIndex(const CreateIndex&); - CreateIndex& operator=(const CreateIndex&); - -private: - /** Table to be truncated */ - dict_table_t* m_table; -}; - -/** Check for presence of table-id in SYS_XXXX tables. */ -class TableLocator : public Callback { - -public: - /** - Constructor - @param table_id table_id to look for */ - explicit TableLocator(table_id_t table_id) - : - Callback(table_id, false), - m_table_found() - { - /* No op */ - } - - /** - @return true if table is found */ - bool is_table_found() const - { - return(m_table_found); - } - - /** - Look for table-id in SYS_XXXX tables without loading the table. - - @param pcur persistent cursor used for reading - @return DB_SUCCESS */ - dberr_t operator()(mtr_t*, btr_pcur_t*) - { - m_table_found = true; - return(DB_SUCCESS); - } - -private: - /** Set to true if table is present */ - bool m_table_found; -}; - -/** -Drop an index in the table. - -@param mtr mini-transaction covering the read -@param pcur persistent cursor used for reading -@return DB_SUCCESS or error code */ -dberr_t -DropIndex::operator()(mtr_t* mtr, btr_pcur_t* pcur) const -{ - rec_t* rec = btr_pcur_get_rec(pcur); - - bool freed = dict_drop_index_tree(rec, pcur, mtr); - -#ifdef UNIV_DEBUG - { - ulint len; - const byte* field; - ulint index_type; - - field = rec_get_nth_field_old( - btr_pcur_get_rec(pcur), DICT_FLD__SYS_INDEXES__TYPE, - &len); - ut_ad(len == 4); - - index_type = mach_read_from_4(field); - - if (index_type & DICT_CLUSTERED) { - /* Clustered index */ - DBUG_EXECUTE_IF("ib_trunc_crash_on_drop_of_clust_index", - log_buffer_flush_to_disk(); - os_thread_sleep(2000000); - DBUG_SUICIDE();); - } else if (index_type & DICT_UNIQUE) { - /* Unique index */ - DBUG_EXECUTE_IF("ib_trunc_crash_on_drop_of_uniq_index", - log_buffer_flush_to_disk(); - os_thread_sleep(2000000); - DBUG_SUICIDE();); - } else if (index_type == 0) { - /* Secondary index */ - DBUG_EXECUTE_IF("ib_trunc_crash_on_drop_of_sec_index", - log_buffer_flush_to_disk(); - os_thread_sleep(2000000); - DBUG_SUICIDE();); - } - } -#endif /* UNIV_DEBUG */ - - DBUG_EXECUTE_IF("ib_err_trunc_drop_index", return DB_ERROR;); - - if (freed) { - - /* We will need to commit and restart the - mini-transaction in order to avoid deadlocks. - The dict_drop_index_tree() call has freed - a page in this mini-transaction, and the rest - of this loop could latch another index page.*/ - const mtr_log_t log_mode = mtr->get_log_mode(); - mtr_commit(mtr); - - mtr_start(mtr); - mtr->set_log_mode(log_mode); - - btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr); - } else { - if (!m_table->space) { - return DB_ERROR; - } - } - - return(DB_SUCCESS); -} - -/** -Create the new index and update the root page number in the -SysIndex table. - -@param mtr mini-transaction covering the read -@param pcur persistent cursor used for reading -@return DB_SUCCESS or error code */ -dberr_t -CreateIndex::operator()(mtr_t* mtr, btr_pcur_t* pcur) const -{ - ulint root_page_no; - - root_page_no = dict_recreate_index_tree(m_table, pcur, mtr); - -#ifdef UNIV_DEBUG - { - ulint len; - const byte* field; - ulint index_type; - - field = rec_get_nth_field_old( - btr_pcur_get_rec(pcur), DICT_FLD__SYS_INDEXES__TYPE, - &len); - ut_ad(len == 4); - - index_type = mach_read_from_4(field); - - if (index_type & DICT_CLUSTERED) { - /* Clustered index */ - DBUG_EXECUTE_IF( - "ib_trunc_crash_on_create_of_clust_index", - log_buffer_flush_to_disk(); - os_thread_sleep(2000000); - DBUG_SUICIDE();); - } else if (index_type & DICT_UNIQUE) { - /* Unique index */ - DBUG_EXECUTE_IF( - "ib_trunc_crash_on_create_of_uniq_index", - log_buffer_flush_to_disk(); - os_thread_sleep(2000000); - DBUG_SUICIDE();); - } else if (index_type == 0) { - /* Secondary index */ - DBUG_EXECUTE_IF( - "ib_trunc_crash_on_create_of_sec_index", - log_buffer_flush_to_disk(); - os_thread_sleep(2000000); - DBUG_SUICIDE();); - } - } -#endif /* UNIV_DEBUG */ - - DBUG_EXECUTE_IF("ib_err_trunc_create_index", return DB_ERROR;); - - if (root_page_no != FIL_NULL) { - - rec_t* rec = btr_pcur_get_rec(pcur); - - page_rec_write_field( - rec, DICT_FLD__SYS_INDEXES__PAGE_NO, - root_page_no, mtr); - - /* We will need to commit and restart the - mini-transaction in order to avoid deadlocks. - The dict_create_index_tree() call has allocated - a page in this mini-transaction, and the rest of - this loop could latch another index page. */ - mtr_commit(mtr); - - mtr_start(mtr); - - btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr); - - } else { - if (!m_table->space) { - return(DB_ERROR); - } - } - - return(DB_SUCCESS); -} - -/** -Update system table to reflect new table id. -@param old_table_id old table id -@param new_table_id new table id -@param reserve_dict_mutex if TRUE, acquire/release - dict_sys->mutex around call to pars_sql. -@param trx transaction -@return error code or DB_SUCCESS */ -static MY_ATTRIBUTE((warn_unused_result)) -dberr_t -row_truncate_update_table_id( - table_id_t old_table_id, - table_id_t new_table_id, - ibool reserve_dict_mutex, - trx_t* trx) -{ - pars_info_t* info = NULL; - dberr_t err = DB_SUCCESS; - - /* Scan the SYS_XXXX table and update to reflect new table-id. */ - info = pars_info_create(); - pars_info_add_ull_literal(info, "old_id", old_table_id); - pars_info_add_ull_literal(info, "new_id", new_table_id); - - err = que_eval_sql( - info, - "PROCEDURE RENUMBER_TABLE_ID_PROC () IS\n" - "BEGIN\n" - "UPDATE SYS_TABLES" - " SET ID = :new_id\n" - " WHERE ID = :old_id;\n" - "UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n" - " WHERE TABLE_ID = :old_id;\n" - "UPDATE SYS_INDEXES" - " SET TABLE_ID = :new_id\n" - " WHERE TABLE_ID = :old_id;\n" - "UPDATE SYS_VIRTUAL" - " SET TABLE_ID = :new_id\n" - " WHERE TABLE_ID = :old_id;\n" - "END;\n", reserve_dict_mutex, trx); - - return(err); -} - -/** -Get the table id to truncate. -@param truncate_t old/new table id of table to truncate -@return table_id_t table_id to use in SYS_XXXX table update. */ -static MY_ATTRIBUTE((warn_unused_result)) -table_id_t -row_truncate_get_trunc_table_id( - const truncate_t& truncate) -{ - TableLocator tableLocator(truncate.old_table_id()); - - SysIndexIterator().for_each(tableLocator); - - return(tableLocator.is_table_found() ? - truncate.old_table_id(): truncate.new_table_id()); -} - -/** -Update system table to reflect new table id and root page number. -@param truncate_t old/new table id of table to truncate - and updated root_page_no of indexes. -@param new_table_id new table id -@param reserve_dict_mutex if TRUE, acquire/release - dict_sys->mutex around call to pars_sql. -@param mark_index_corrupted if true, then mark index corrupted. -@return error code or DB_SUCCESS */ -static MY_ATTRIBUTE((warn_unused_result)) -dberr_t -row_truncate_update_sys_tables_during_fix_up( - const truncate_t& truncate, - table_id_t new_table_id, - ibool reserve_dict_mutex, - bool mark_index_corrupted) -{ - trx_t* trx = trx_create(); - - trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); - - table_id_t table_id = row_truncate_get_trunc_table_id(truncate); - - /* Step-1: Update the root-page-no */ - - dberr_t err; - - err = truncate.update_root_page_no( - trx, table_id, reserve_dict_mutex, mark_index_corrupted); - - if (err != DB_SUCCESS) { - return(err); - } - - /* Step-2: Update table-id. */ - - err = row_truncate_update_table_id( - table_id, new_table_id, reserve_dict_mutex, trx); - - if (err == DB_SUCCESS) { - dict_mutex_enter_for_mysql(); - - /* Remove the table with old table_id from cache. */ - dict_table_t* old_table = dict_table_open_on_id( - table_id, true, DICT_TABLE_OP_NORMAL); - - if (old_table != NULL) { - dict_table_close(old_table, true, false); - dict_table_remove_from_cache(old_table); - } - - /* Open table with new table_id and set table as - corrupted if it has FTS index. */ - - dict_table_t* table = dict_table_open_on_id( - new_table_id, true, DICT_TABLE_OP_NORMAL); - ut_ad(table->id == new_table_id); - - bool has_internal_doc_id = - dict_table_has_fts_index(table) - || DICT_TF2_FLAG_IS_SET( - table, DICT_TF2_FTS_HAS_DOC_ID); - - if (has_internal_doc_id) { - trx->dict_operation_lock_mode = RW_X_LATCH; - fts_check_corrupt(table, trx); - trx->dict_operation_lock_mode = 0; - } - - dict_table_close(table, true, false); - dict_mutex_exit_for_mysql(); - } - - trx_commit_for_mysql(trx); - trx_free(trx); - - return(err); -} - -/********************************************************//** -Recreates table indexes by applying -TRUNCATE log record during recovery. -@return DB_SUCCESS or error code */ -static -dberr_t -fil_recreate_table( -/*===============*/ - ulint format_flags, /*!< in: page format */ - const char* name, /*!< in: table name */ - truncate_t& truncate) /*!< in: The information of - TRUNCATE log record */ -{ - ut_ad(!truncate_t::s_fix_up_active); - truncate_t::s_fix_up_active = true; - - /* Step-1: Scan for active indexes from REDO logs and drop - all the indexes using low level function that take root_page_no - and space-id. */ - truncate.drop_indexes(fil_system.sys_space); - - /* Step-2: Scan for active indexes and re-create them. */ - dberr_t err = truncate.create_indexes( - name, fil_system.sys_space, format_flags); - if (err != DB_SUCCESS) { - ib::info() << "Recovery failed for TRUNCATE TABLE '" - << name << "' within the system tablespace"; - } - - truncate_t::s_fix_up_active = false; - - return(err); -} - -/********************************************************//** -Recreates the tablespace and table indexes by applying -TRUNCATE log record during recovery. -@return DB_SUCCESS or error code */ -static -dberr_t -fil_recreate_tablespace( -/*====================*/ - ulint space_id, /*!< in: space id */ - ulint format_flags, /*!< in: page format */ - ulint flags, /*!< in: tablespace flags */ - const char* name, /*!< in: table name */ - truncate_t& truncate, /*!< in: The information of - TRUNCATE log record */ - lsn_t recv_lsn) /*!< in: the end LSN of - the log record */ -{ - dberr_t err = DB_SUCCESS; - mtr_t mtr; - - ut_ad(!truncate_t::s_fix_up_active); - truncate_t::s_fix_up_active = true; - - /* Step-1: Invalidate buffer pool pages belonging to the tablespace - to re-create. */ - buf_LRU_flush_or_remove_pages(space_id, NULL); - - /* Remove all insert buffer entries for the tablespace */ - ibuf_delete_for_discarded_space(space_id); - - /* Step-2: truncate tablespace (reset the size back to original or - default size) of tablespace. */ - err = truncate.truncate( - space_id, truncate.get_dir_path(), name, flags, true); - - if (err != DB_SUCCESS) { - - ib::info() << "Cannot access .ibd file for table '" - << name << "' with tablespace " << space_id - << " while truncating"; - return(DB_ERROR); - } - - fil_space_t* space = fil_space_acquire(space_id); - if (!space) { - ib::info() << "Missing .ibd file for table '" << name - << "' with tablespace " << space_id; - return(DB_ERROR); - } - - const page_size_t page_size(space->flags); - - /* Step-3: Initialize Header. */ - if (page_size.is_compressed()) { - byte* buf; - page_t* page; - - buf = static_cast<byte*>( - ut_zalloc_nokey(3U << srv_page_size_shift)); - - /* Align the memory for file i/o */ - page = static_cast<byte*>(ut_align(buf, srv_page_size)); - - flags |= FSP_FLAGS_PAGE_SSIZE(); - - fsp_header_init_fields(page, space_id, flags); - - mach_write_to_4( - page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id); - - page_zip_des_t page_zip; - page_zip_set_size(&page_zip, page_size.physical()); - page_zip.data = page + srv_page_size; - -#ifdef UNIV_DEBUG - page_zip.m_start = -#endif /* UNIV_DEBUG */ - page_zip.m_end = page_zip.m_nonempty = page_zip.n_blobs = 0; - buf_flush_init_for_writing(NULL, page, &page_zip, 0); - - err = fil_io(IORequestWrite, true, page_id_t(space_id, 0), - page_size, 0, page_size.physical(), page_zip.data, - NULL); - - ut_free(buf); - - if (err != DB_SUCCESS) { - ib::info() << "Failed to clean header of the" - " table '" << name << "' with tablespace " - << space_id; - goto func_exit; - } - } - - mtr_start(&mtr); - /* Don't log the operation while fixing up table truncate operation - as crash at this level can still be sustained with recovery restarting - from last checkpoint. */ - mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); - - /* Initialize the first extent descriptor page and - the second bitmap page for the new tablespace. */ - fsp_header_init(space, FIL_IBD_FILE_INITIAL_SIZE, &mtr); - mtr_commit(&mtr); - - /* Step-4: Re-Create Indexes to newly re-created tablespace. - This operation will restore tablespace back to what it was - when it was created during CREATE TABLE. */ - err = truncate.create_indexes(name, space, format_flags); - if (err != DB_SUCCESS) { - goto func_exit; - } - - /* Step-5: Write new created pages into ibd file handle and - flush it to disk for the tablespace, in case i/o-handler thread - deletes the bitmap page from buffer. */ - mtr_start(&mtr); - - mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); - - for (ulint page_no = 0; - page_no < UT_LIST_GET_FIRST(space->chain)->size; ++page_no) { - - const page_id_t cur_page_id(space_id, page_no); - - buf_block_t* block = buf_page_get(cur_page_id, page_size, - RW_X_LATCH, &mtr); - - byte* page = buf_block_get_frame(block); - - if (!FSP_FLAGS_GET_ZIP_SSIZE(flags)) { - ut_ad(!page_size.is_compressed()); - - buf_flush_init_for_writing( - block, page, NULL, recv_lsn); - - err = fil_io(IORequestWrite, true, cur_page_id, - page_size, 0, srv_page_size, page, NULL); - } else { - ut_ad(page_size.is_compressed()); - - /* We don't want to rewrite empty pages. */ - - if (fil_page_get_type(page) != 0) { - page_zip_des_t* page_zip = - buf_block_get_page_zip(block); - - buf_flush_init_for_writing( - block, page, page_zip, recv_lsn); - - err = fil_io(IORequestWrite, true, - cur_page_id, - page_size, 0, - page_size.physical(), - page_zip->data, NULL); - } else { -#ifdef UNIV_DEBUG - const byte* data = block->page.zip.data; - - /* Make sure that the page is really empty */ - for (ulint i = 0; - i < page_size.physical(); - ++i) { - - ut_a(data[i] == 0); - } -#endif /* UNIV_DEBUG */ - } - } - - if (err != DB_SUCCESS) { - ib::info() << "Cannot write page " << page_no - << " into a .ibd file for table '" - << name << "' with tablespace " << space_id; - } - } - - mtr_commit(&mtr); - - truncate_t::s_fix_up_active = false; -func_exit: - space->release(); - return(err); -} - -/** -Fix the table truncate by applying information parsed from TRUNCATE log. -Fix-up includes re-creating table (drop and re-create indexes) -@return error code or DB_SUCCESS */ -dberr_t -truncate_t::fixup_tables_in_system_tablespace() -{ - dberr_t err = DB_SUCCESS; - - /* Using the info cached during REDO log scan phase fix the - table truncate. */ - - for (tables_t::iterator it = s_tables.begin(); - it != s_tables.end();) { - - if ((*it)->m_space_id == TRX_SYS_SPACE) { - /* Step-1: Drop and re-create indexes. */ - ib::info() << "Completing truncate for table with " - "id (" << (*it)->m_old_table_id << ") " - "residing in the system tablespace."; - - err = fil_recreate_table( - (*it)->m_format_flags, - (*it)->m_tablename, - **it); - - /* Step-2: Update the SYS_XXXX tables to reflect - this new table_id and root_page_no. */ - table_id_t new_id; - - dict_hdr_get_new_id(&new_id, NULL, NULL, NULL, true); - - err = row_truncate_update_sys_tables_during_fix_up( - **it, new_id, TRUE, - (err == DB_SUCCESS) ? false : true); - - if (err != DB_SUCCESS) { - break; - } - - os_file_delete( - innodb_log_file_key, (*it)->m_log_file_name); - UT_DELETE(*it); - it = s_tables.erase(it); - } else { - ++it; - } - } - - /* Also clear the map used to track tablespace truncated. */ - s_truncated_tables.clear(); - - return(err); -} - -/** -Fix the table truncate by applying information parsed from TRUNCATE log. -Fix-up includes re-creating tablespace. -@return error code or DB_SUCCESS */ -dberr_t -truncate_t::fixup_tables_in_non_system_tablespace() -{ - dberr_t err = DB_SUCCESS; - - /* Using the info cached during REDO log scan phase fix the - table truncate. */ - tables_t::iterator end = s_tables.end(); - - for (tables_t::iterator it = s_tables.begin(); it != end; ++it) { - - /* All tables in the system tablespace have already been - done and erased from this list. */ - ut_a((*it)->m_space_id != TRX_SYS_SPACE); - - /* Drop tablespace, drop indexes and re-create indexes. */ - - ib::info() << "Completing truncate for table with " - "id (" << (*it)->m_old_table_id << ") " - "residing in file-per-table tablespace with " - "id (" << (*it)->m_space_id << ")"; - - fil_space_t* space = fil_space_get((*it)->m_space_id); - - if (!space) { - /* Create the database directory for name, - if it does not exist yet */ - fil_create_directory_for_tablename( - (*it)->m_tablename); - - space = fil_ibd_create((*it)->m_space_id, - (*it)->m_tablename, - (*it)->m_dir_path, - (*it)->m_tablespace_flags, - FIL_IBD_FILE_INITIAL_SIZE, - (*it)->m_encryption, - (*it)->m_key_id, &err); - if (!space) { - /* If checkpoint is not yet done - and table is dropped and then we might - still have REDO entries for this table - which are INVALID. Ignore them. */ - ib::warn() << "Failed to create" - " tablespace for " - << (*it)->m_space_id - << " space-id"; - err = DB_ERROR; - break; - } - } - - err = fil_recreate_tablespace( - (*it)->m_space_id, - (*it)->m_format_flags, - (*it)->m_tablespace_flags, - (*it)->m_tablename, - **it, log_get_lsn()); - - /* Step-2: Update the SYS_XXXX tables to reflect new - table-id and root_page_no. */ - table_id_t new_id; - - dict_hdr_get_new_id(&new_id, NULL, NULL, NULL, true); - - err = row_truncate_update_sys_tables_during_fix_up( - **it, new_id, TRUE, (err == DB_SUCCESS) ? false : true); - - if (err != DB_SUCCESS) { - break; - } - } - - if (err == DB_SUCCESS && s_tables.size() > 0) { - - log_make_checkpoint_at(LSN_MAX, TRUE); - } - - for (ulint i = 0; i < s_tables.size(); ++i) { - os_file_delete( - innodb_log_file_key, s_tables[i]->m_log_file_name); - UT_DELETE(s_tables[i]); - } - - s_tables.clear(); - - return(err); -} - -/** -Constructor - -@param old_table_id old table id assigned to table before truncate -@param new_table_id new table id that will be assigned to table - after truncate -@param dir_path directory path */ - -truncate_t::truncate_t( - table_id_t old_table_id, - table_id_t new_table_id, - const char* dir_path) - : - m_space_id(), - m_old_table_id(old_table_id), - m_new_table_id(new_table_id), - m_dir_path(), - m_tablename(), - m_tablespace_flags(), - m_format_flags(), - m_indexes(), - m_log_lsn(), - m_log_file_name(), - /* JAN: TODO: Encryption */ - m_encryption(FIL_ENCRYPTION_DEFAULT), - m_key_id(FIL_DEFAULT_ENCRYPTION_KEY) -{ - if (dir_path != NULL) { - m_dir_path = mem_strdup(dir_path); - } -} - -/** -Consturctor - -@param log_file_name parse the log file during recovery to populate - information related to table to truncate */ -truncate_t::truncate_t( - const char* log_file_name) - : - m_space_id(), - m_old_table_id(), - m_new_table_id(), - m_dir_path(), - m_tablename(), - m_tablespace_flags(), - m_format_flags(), - m_indexes(), - m_log_lsn(), - m_log_file_name(), - /* JAN: TODO: Encryption */ - m_encryption(FIL_ENCRYPTION_DEFAULT), - m_key_id(FIL_DEFAULT_ENCRYPTION_KEY) - -{ - m_log_file_name = mem_strdup(log_file_name); - if (m_log_file_name == NULL) { - ib::fatal() << "Failed creating truncate_t; out of memory"; - } -} - -/** Constructor */ - -truncate_t::index_t::index_t() - : - m_id(), - m_type(), - m_root_page_no(FIL_NULL), - m_new_root_page_no(FIL_NULL), - m_n_fields(), - m_trx_id_pos(ULINT_UNDEFINED), - m_fields() -{ - /* Do nothing */ -} - -/** Destructor */ - -truncate_t::~truncate_t() -{ - if (m_dir_path != NULL) { - ut_free(m_dir_path); - m_dir_path = NULL; - } - - if (m_tablename != NULL) { - ut_free(m_tablename); - m_tablename = NULL; - } - - if (m_log_file_name != NULL) { - ut_free(m_log_file_name); - m_log_file_name = NULL; - } - - m_indexes.clear(); -} - -/** -@return number of indexes parsed from the log record */ - -size_t -truncate_t::indexes() const -{ - return(m_indexes.size()); -} - -/** -Update root page number in SYS_XXXX tables. - -@param trx transaction object -@param table_id table id for which information needs to - be updated. -@param reserve_dict_mutex if TRUE, acquire/release - dict_sys->mutex around call to pars_sql. -@param mark_index_corrupted if true, then mark index corrupted. -@return DB_SUCCESS or error code */ - -dberr_t -truncate_t::update_root_page_no( - trx_t* trx, - table_id_t table_id, - ibool reserve_dict_mutex, - bool mark_index_corrupted) const -{ - indexes_t::const_iterator end = m_indexes.end(); - - dberr_t err = DB_SUCCESS; - - for (indexes_t::const_iterator it = m_indexes.begin(); - it != end; - ++it) { - - pars_info_t* info = pars_info_create(); - - pars_info_add_int4_literal( - info, "page_no", it->m_new_root_page_no); - - pars_info_add_ull_literal(info, "table_id", table_id); - - pars_info_add_ull_literal( - info, "index_id", - (mark_index_corrupted ? IB_ID_MAX : it->m_id)); - - err = que_eval_sql( - info, - "PROCEDURE RENUMBER_IDX_PAGE_NO_PROC () IS\n" - "BEGIN\n" - "UPDATE SYS_INDEXES" - " SET PAGE_NO = :page_no\n" - " WHERE TABLE_ID = :table_id" - " AND ID = :index_id;\n" - "END;\n", reserve_dict_mutex, trx); - - if (err != DB_SUCCESS) { - break; - } - } - - return(err); -} - -/** -Check whether a tablespace was truncated during recovery -@param space_id tablespace id to check -@return true if the tablespace was truncated */ - -bool -truncate_t::is_tablespace_truncated(ulint space_id) -{ - tables_t::iterator end = s_tables.end(); - - for (tables_t::iterator it = s_tables.begin(); it != end; ++it) { - - if ((*it)->m_space_id == space_id) { - - return(true); - } - } - - return(false); -} - -/** Was tablespace truncated (on crash before checkpoint). -If the MLOG_TRUNCATE redo-record is still available then tablespace -was truncated and checkpoint is yet to happen. -@param[in] space_id tablespace id to check. -@return true if tablespace is was truncated. */ -bool -truncate_t::was_tablespace_truncated(ulint space_id) -{ - return(s_truncated_tables.find(space_id) != s_truncated_tables.end()); -} - -/** Get the lsn associated with space. -@param[in] space_id tablespace id to check. -@return associated lsn. */ -lsn_t -truncate_t::get_truncated_tablespace_init_lsn(ulint space_id) -{ - ut_ad(was_tablespace_truncated(space_id)); - - return(s_truncated_tables.find(space_id)->second); -} - -/** -Parses log record during recovery -@param start_ptr buffer containing log body to parse -@param end_ptr buffer end - -@return DB_SUCCESS or error code */ - -dberr_t -truncate_t::parse( - byte* start_ptr, - const byte* end_ptr) -{ - /* Parse lsn, space-id, format-flags and tablespace-flags. */ - if (end_ptr < start_ptr + (8 + 4 + 4 + 4)) { - return(DB_FAIL); - } - - m_log_lsn = mach_read_from_8(start_ptr); - start_ptr += 8; - - m_space_id = mach_read_from_4(start_ptr); - start_ptr += 4; - - m_format_flags = mach_read_from_4(start_ptr); - start_ptr += 4; - - m_tablespace_flags = mach_read_from_4(start_ptr); - start_ptr += 4; - - /* Parse table-name. */ - if (end_ptr < start_ptr + (2)) { - return(DB_FAIL); - } - - ulint n_tablename_len = mach_read_from_2(start_ptr); - start_ptr += 2; - - if (n_tablename_len > 0) { - if (end_ptr < start_ptr + n_tablename_len) { - return(DB_FAIL); - } - m_tablename = mem_strdup(reinterpret_cast<char*>(start_ptr)); - ut_ad(m_tablename[n_tablename_len - 1] == 0); - start_ptr += n_tablename_len; - } - - - /* Parse and read old/new table-id, number of indexes */ - if (end_ptr < start_ptr + (8 + 8 + 2 + 2)) { - return(DB_FAIL); - } - - ut_ad(m_indexes.empty()); - - m_old_table_id = mach_read_from_8(start_ptr); - start_ptr += 8; - - m_new_table_id = mach_read_from_8(start_ptr); - start_ptr += 8; - - ulint n_indexes = mach_read_from_2(start_ptr); - start_ptr += 2; - - /* Parse the remote directory from TRUNCATE log record */ - { - ulint n_tabledirpath_len = mach_read_from_2(start_ptr); - start_ptr += 2; - - if (end_ptr < start_ptr + n_tabledirpath_len) { - return(DB_FAIL); - } - - if (n_tabledirpath_len > 0) { - - m_dir_path = mem_strdup(reinterpret_cast<char*>(start_ptr)); - ut_ad(m_dir_path[n_tabledirpath_len - 1] == 0); - start_ptr += n_tabledirpath_len; - } - } - - /* Parse index ids and types from TRUNCATE log record */ - for (ulint i = 0; i < n_indexes; ++i) { - index_t index; - - if (end_ptr < start_ptr + (8 + 4 + 4 + 4)) { - return(DB_FAIL); - } - - index.m_id = mach_read_from_8(start_ptr); - start_ptr += 8; - - index.m_type = mach_read_from_4(start_ptr); - start_ptr += 4; - - index.m_root_page_no = mach_read_from_4(start_ptr); - start_ptr += 4; - - index.m_trx_id_pos = mach_read_from_4(start_ptr); - start_ptr += 4; - - if (!(index.m_type & DICT_FTS)) { - m_indexes.push_back(index); - } - } - - ut_ad(!m_indexes.empty()); - - if (FSP_FLAGS_GET_ZIP_SSIZE(m_tablespace_flags)) { - - /* Parse the number of index fields from TRUNCATE log record */ - for (ulint i = 0; i < m_indexes.size(); ++i) { - - if (end_ptr < start_ptr + (2 + 2)) { - return(DB_FAIL); - } - - m_indexes[i].m_n_fields = mach_read_from_2(start_ptr); - start_ptr += 2; - - ulint len = mach_read_from_2(start_ptr); - start_ptr += 2; - - if (end_ptr < start_ptr + len) { - return(DB_FAIL); - } - - index_t& index = m_indexes[i]; - - /* Should be NUL terminated. */ - ut_ad((start_ptr)[len - 1] == 0); - - index_t::fields_t::iterator end; - - end = index.m_fields.end(); - - index.m_fields.insert( - end, start_ptr, &(start_ptr)[len]); - - start_ptr += len; - } - } - - return(DB_SUCCESS); -} - -/** Parse log record from REDO log file during recovery. -@param[in,out] start_ptr buffer containing log body to parse -@param[in] end_ptr buffer end -@param[in] space_id tablespace identifier -@return parsed upto or NULL. */ -byte* -truncate_t::parse_redo_entry( - byte* start_ptr, - const byte* end_ptr, - ulint space_id) -{ - lsn_t lsn; - - /* Parse space-id, lsn */ - if (end_ptr < (start_ptr + 8)) { - return(NULL); - } - - lsn = mach_read_from_8(start_ptr); - start_ptr += 8; - - /* Tablespace can't exist in both state. - (scheduled-for-truncate, was-truncated). */ - if (!is_tablespace_truncated(space_id)) { - - truncated_tables_t::iterator it = - s_truncated_tables.find(space_id); - - if (it == s_truncated_tables.end()) { - s_truncated_tables.insert( - std::pair<ulint, lsn_t>(space_id, lsn)); - } else { - it->second = lsn; - } - } - - return(start_ptr); -} - -/** -Set the truncate log values for a compressed table. -@param index index from which recreate infoormation needs to be extracted -@return DB_SUCCESS or error code */ - -dberr_t -truncate_t::index_t::set( - const dict_index_t* index) -{ - /* Get trx-id column position (set only for clustered index) */ - if (dict_index_is_clust(index)) { - m_trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); - ut_ad(m_trx_id_pos > 0); - ut_ad(m_trx_id_pos != ULINT_UNDEFINED); - } else { - m_trx_id_pos = 0; - } - - /* Original logic set this field differently if page is not leaf. - For truncate case this being first page to get created it is - always a leaf page and so we don't need that condition here. */ - m_n_fields = dict_index_get_n_fields(index); - - /* See requirements of page_zip_fields_encode for size. */ - ulint encoded_buf_size = (m_n_fields + 1) * 2; - byte* encoded_buf = UT_NEW_ARRAY_NOKEY(byte, encoded_buf_size); - - if (encoded_buf == NULL) { - return(DB_OUT_OF_MEMORY); - } - - ulint len = page_zip_fields_encode( - m_n_fields, index, m_trx_id_pos, encoded_buf); - ut_a(len <= encoded_buf_size); - - /* Append the encoded fields data. */ - m_fields.insert(m_fields.end(), &encoded_buf[0], &encoded_buf[len]); - - /* NUL terminate the encoded data */ - m_fields.push_back(0); - - UT_DELETE_ARRAY(encoded_buf); - - return(DB_SUCCESS); -} - -/** Create an index for a table. -@param[in] table_name table name, for which to create -the index -@param[in] space tablespace -@param[in] page_size page size of the .ibd file -@param[in] index_type type of index to truncate -@param[in] index_id id of index to truncate -@param[in] btr_redo_create_info control info for ::btr_create() -@param[in,out] mtr mini-transaction covering the -create index -@return root page no or FIL_NULL on failure */ -inline ulint -truncate_t::create_index( - const char* table_name, - fil_space_t* space, - ulint index_type, - index_id_t index_id, - const btr_create_t& btr_redo_create_info, - mtr_t* mtr) const -{ - ulint root_page_no = btr_create( - index_type, space, index_id, - NULL, &btr_redo_create_info, mtr); - - if (root_page_no == FIL_NULL) { - - ib::info() << "innodb_force_recovery was set to " - << srv_force_recovery << ". Continuing crash recovery" - " even though we failed to create index " << index_id - << " for compressed table '" << table_name << "' with" - " file " << space->chain.start->name; - } - - return(root_page_no); -} - -/** Check if index has been modified since TRUNCATE log snapshot -was recorded. -@param[in] space tablespace -@param[in] root_page_no index root page number -@return true if modified else false */ -inline -bool -truncate_t::is_index_modified_since_logged( - const fil_space_t* space, - ulint root_page_no) const -{ - dberr_t err; - mtr_t mtr; - - mtr_start(&mtr); - - /* Root page could be in free state if truncate crashed after drop_index - and page was not allocated for any other object. */ - buf_block_t* block= buf_page_get_gen( - page_id_t(space->id, root_page_no), page_size_t(space->flags), - RW_X_LATCH, NULL, - BUF_GET_POSSIBLY_FREED, __FILE__, __LINE__, &mtr, &err); - if (!block) return true; - - page_t* root = buf_block_get_frame(block); - -#ifdef UNIV_DEBUG - /* If the root page has been freed as part of truncate drop_index action - and not yet allocated for any object still the pagelsn > snapshot lsn */ - if (block->page.file_page_was_freed) { - ut_ad(mach_read_from_8(root + FIL_PAGE_LSN) > m_log_lsn); - } -#endif /* UNIV_DEBUG */ - - lsn_t page_lsn = mach_read_from_8(root + FIL_PAGE_LSN); - - mtr_commit(&mtr); - - if (page_lsn > m_log_lsn) { - return(true); - } - - return(false); -} - -/** Drop indexes for a table. -@param[in,out] space tablespace */ -void truncate_t::drop_indexes(fil_space_t* space) const -{ - mtr_t mtr; - - indexes_t::const_iterator end = m_indexes.end(); - const page_size_t page_size(space->flags); - - for (indexes_t::const_iterator it = m_indexes.begin(); - it != end; - ++it) { - - ulint root_page_no = it->m_root_page_no; - - if (is_index_modified_since_logged(space, root_page_no)) { - /* Page has been modified since TRUNCATE log snapshot - was recorded so not safe to drop the index. */ - continue; - } - - mtr_start(&mtr); - - if (space->id != TRX_SYS_SPACE) { - /* Do not log changes for single-table - tablespaces, we are in recovery mode. */ - mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); - } - - if (root_page_no != FIL_NULL) { - const page_id_t root_page_id(space->id, root_page_no); - - btr_free_if_exists( - root_page_id, page_size, it->m_id, &mtr); - } - - /* If tree is already freed then we might return immediately - in which case we need to release the lock we have acquired - on root_page. */ - mtr_commit(&mtr); - } -} - - -/** Create the indexes for a table -@param[in] table_name table name, for which to create the indexes -@param[in,out] space tablespace -@param[in] format_flags page format flags -@return DB_SUCCESS or error code. */ -inline dberr_t -truncate_t::create_indexes( - const char* table_name, - fil_space_t* space, - ulint format_flags) -{ - mtr_t mtr; - - mtr_start(&mtr); - - if (space->id != TRX_SYS_SPACE) { - /* Do not log changes for single-table tablespaces, we - are in recovery mode. */ - mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); - } - - /* Create all new index trees with table format, index ids, index - types, number of index fields and index field information taken - out from the TRUNCATE log record. */ - - ulint root_page_no = FIL_NULL; - indexes_t::iterator end = m_indexes.end(); - for (indexes_t::iterator it = m_indexes.begin(); - it != end; - ++it) { - - btr_create_t btr_redo_create_info( - FSP_FLAGS_GET_ZIP_SSIZE(space->flags) - ? &it->m_fields[0] : NULL); - - btr_redo_create_info.format_flags = format_flags; - - if (FSP_FLAGS_GET_ZIP_SSIZE(space->flags)) { - - btr_redo_create_info.n_fields = it->m_n_fields; - /* Skip the NUL appended field */ - btr_redo_create_info.field_len = - it->m_fields.size() - 1; - btr_redo_create_info.trx_id_pos = it->m_trx_id_pos; - } - - root_page_no = create_index( - table_name, space, it->m_type, it->m_id, - btr_redo_create_info, &mtr); - - if (root_page_no == FIL_NULL) { - break; - } - - it->m_new_root_page_no = root_page_no; - } - - mtr_commit(&mtr); - - return(root_page_no == FIL_NULL ? DB_ERROR : DB_SUCCESS); -} - -/** -Write a TRUNCATE log record for fixing up table if truncate crashes. -@param start_ptr buffer to write log record -@param end_ptr buffer end -@param space_id space id -@param tablename the table name in the usual databasename/tablename - format of InnoDB -@param flags tablespace flags -@param format_flags page format -@param lsn lsn while logging -@return DB_SUCCESS or error code */ - -dberr_t -truncate_t::write( - byte* start_ptr, - byte* end_ptr, - ulint space_id, - const char* tablename, - ulint flags, - ulint format_flags, - lsn_t lsn) const -{ - if (end_ptr < start_ptr) { - return(DB_FAIL); - } - - /* LSN, Type, Space-ID, format-flag (also know as log_flag. - Stored in page_no field), tablespace flags */ - if (end_ptr < (start_ptr + (8 + 4 + 4 + 4))) { - return(DB_FAIL); - } - - mach_write_to_8(start_ptr, lsn); - start_ptr += 8; - - mach_write_to_4(start_ptr, space_id); - start_ptr += 4; - - mach_write_to_4(start_ptr, format_flags); - start_ptr += 4; - - mach_write_to_4(start_ptr, flags); - start_ptr += 4; - - /* Name of the table. */ - /* Include the NUL in the log record. */ - ulint len = strlen(tablename) + 1; - if (end_ptr < (start_ptr + (len + 2))) { - return(DB_FAIL); - } - - mach_write_to_2(start_ptr, len); - start_ptr += 2; - - memcpy(start_ptr, tablename, len - 1); - start_ptr += len; - - DBUG_EXECUTE_IF("ib_trunc_crash_while_writing_redo_log", - DBUG_SUICIDE();); - - /* Old/New Table-ID, Number of Indexes and Tablespace dir-path-name. */ - /* Write the remote directory of the table into mtr log */ - len = m_dir_path != NULL ? strlen(m_dir_path) + 1 : 0; - if (end_ptr < (start_ptr + (len + 8 + 8 + 2 + 2))) { - return(DB_FAIL); - } - - /* Write out old-table-id. */ - mach_write_to_8(start_ptr, m_old_table_id); - start_ptr += 8; - - /* Write out new-table-id. */ - mach_write_to_8(start_ptr, m_new_table_id); - start_ptr += 8; - - /* Write out the number of indexes. */ - mach_write_to_2(start_ptr, m_indexes.size()); - start_ptr += 2; - - /* Write the length (NUL included) of the .ibd path. */ - mach_write_to_2(start_ptr, len); - start_ptr += 2; - - if (m_dir_path != NULL) { - memcpy(start_ptr, m_dir_path, len - 1); - start_ptr += len; - } - - /* Indexes information (id, type) */ - /* Write index ids, type, root-page-no into mtr log */ - for (ulint i = 0; i < m_indexes.size(); ++i) { - - if (end_ptr < (start_ptr + (8 + 4 + 4 + 4))) { - return(DB_FAIL); - } - - mach_write_to_8(start_ptr, m_indexes[i].m_id); - start_ptr += 8; - - mach_write_to_4(start_ptr, m_indexes[i].m_type); - start_ptr += 4; - - mach_write_to_4(start_ptr, m_indexes[i].m_root_page_no); - start_ptr += 4; - - mach_write_to_4(start_ptr, m_indexes[i].m_trx_id_pos); - start_ptr += 4; - } - - /* If tablespace compressed then field info of each index. */ - if (FSP_FLAGS_GET_ZIP_SSIZE(flags)) { - - for (ulint i = 0; i < m_indexes.size(); ++i) { - - ulint len = m_indexes[i].m_fields.size(); - if (end_ptr < (start_ptr + (len + 2 + 2))) { - return(DB_FAIL); - } - - mach_write_to_2( - start_ptr, m_indexes[i].m_n_fields); - start_ptr += 2; - - mach_write_to_2(start_ptr, len); - start_ptr += 2; - - const byte* ptr = &m_indexes[i].m_fields[0]; - memcpy(start_ptr, ptr, len - 1); - start_ptr += len; - } - } - - return(DB_SUCCESS); -} diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index b2679c87dae..0fdb740db04 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -65,7 +65,6 @@ row_undo_ins_remove_clust_rec( /*==========================*/ undo_node_t* node) /*!< in: undo node */ { - btr_cur_t* btr_cur; ibool success; dberr_t err; ulint n_tries = 0; @@ -73,15 +72,27 @@ row_undo_ins_remove_clust_rec( dict_index_t* index = node->pcur.btr_cur.index; bool online; - ut_ad(dict_index_is_clust(index)); + ut_ad(index->is_primary()); ut_ad(node->trx->in_rollback); mtr.start(); if (index->table->is_temporary()) { ut_ad(node->rec_type == TRX_UNDO_INSERT_REC); mtr.set_log_mode(MTR_LOG_NO_REDO); + ut_ad(!dict_index_is_online_ddl(index)); + ut_ad(index->table->id >= DICT_HDR_FIRST_ID); + online = false; } else { index->set_modified(mtr); + online = dict_index_is_online_ddl(index); + if (online) { + ut_ad(node->rec_type == TRX_UNDO_INSERT_REC); + ut_ad(node->trx->dict_operation_lock_mode + != RW_X_LATCH); + ut_ad(node->table->id != DICT_INDEXES_ID); + ut_ad(node->table->id != DICT_COLUMNS_ID); + mtr_s_lock(dict_index_get_lock(index), &mtr); + } } /* This is similar to row_undo_mod_clust(). The DDL thread may @@ -90,104 +101,69 @@ row_undo_ins_remove_clust_rec( purged. However, we can log the removal out of sync with the B-tree modification. */ - online = dict_index_is_online_ddl(index); - if (online) { - ut_ad(node->trx->dict_operation_lock_mode - != RW_X_LATCH); - ut_ad(node->table->id != DICT_INDEXES_ID); - mtr_s_lock(dict_index_get_lock(index), &mtr); - } - success = btr_pcur_restore_position( online ? BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED - : BTR_MODIFY_LEAF, &node->pcur, &mtr); + : (node->rec_type == TRX_UNDO_INSERT_METADATA) + ? BTR_MODIFY_TREE : BTR_MODIFY_LEAF, &node->pcur, &mtr); ut_a(success); - btr_cur = btr_pcur_get_btr_cur(&node->pcur); + rec_t* rec = btr_pcur_get_rec(&node->pcur); - ut_ad(rec_get_trx_id(btr_cur_get_rec(btr_cur), btr_cur->index) - == node->trx->id); - ut_ad(!rec_get_deleted_flag( - btr_cur_get_rec(btr_cur), - dict_table_is_comp(btr_cur->index->table))); + ut_ad(rec_get_trx_id(rec, index) == node->trx->id); + ut_ad(!rec_get_deleted_flag(rec, index->table->not_redundant()) + || rec_is_alter_metadata(rec, index->table->not_redundant())); + ut_ad(rec_is_metadata(rec, index->table->not_redundant()) + == (node->rec_type == TRX_UNDO_INSERT_METADATA)); if (online && dict_index_is_online_ddl(index)) { - const rec_t* rec = btr_cur_get_rec(btr_cur); mem_heap_t* heap = NULL; const ulint* offsets = rec_get_offsets( rec, index, NULL, true, ULINT_UNDEFINED, &heap); row_log_table_delete(rec, index, offsets, NULL); mem_heap_free(heap); - } - - switch (node->table->id) { - case DICT_INDEXES_ID: - ut_ad(!online); - ut_ad(node->trx->dict_operation_lock_mode == RW_X_LATCH); - ut_ad(node->rec_type == TRX_UNDO_INSERT_REC); - - dict_drop_index_tree( - btr_pcur_get_rec(&node->pcur), &(node->pcur), &mtr); - - mtr.commit(); + } else { + switch (node->table->id) { + case DICT_INDEXES_ID: + ut_ad(!online); + ut_ad(node->trx->dict_operation_lock_mode + == RW_X_LATCH); + ut_ad(node->rec_type == TRX_UNDO_INSERT_REC); - mtr.start(); + dict_drop_index_tree(rec, &node->pcur, &mtr); + mtr.commit(); - success = btr_pcur_restore_position( - BTR_MODIFY_LEAF, &node->pcur, &mtr); - ut_a(success); - break; - case DICT_COLUMNS_ID: - /* This is rolling back an INSERT into SYS_COLUMNS. - If it was part of an instant ADD COLUMN operation, we - must modify the table definition. At this point, any - corresponding operation to the metadata record will have - been rolled back. */ - ut_ad(!online); - ut_ad(node->trx->dict_operation_lock_mode == RW_X_LATCH); - ut_ad(node->rec_type == TRX_UNDO_INSERT_REC); - const rec_t* rec = btr_pcur_get_rec(&node->pcur); - if (rec_get_n_fields_old(rec) - != DICT_NUM_FIELDS__SYS_COLUMNS) { - break; - } - ulint len; - const byte* data = rec_get_nth_field_old( - rec, DICT_FLD__SYS_COLUMNS__TABLE_ID, &len); - if (len != 8) { - break; - } - const table_id_t table_id = mach_read_from_8(data); - data = rec_get_nth_field_old(rec, DICT_FLD__SYS_COLUMNS__POS, - &len); - if (len != 4) { - break; - } - const unsigned pos = mach_read_from_4(data); - if (pos == 0 || pos >= (1U << 16)) { - break; - } - dict_table_t* table = dict_table_open_on_id( - table_id, true, DICT_TABLE_OP_OPEN_ONLY_IF_CACHED); - if (!table) { + mtr.start(); + success = btr_pcur_restore_position( + BTR_MODIFY_LEAF, &node->pcur, &mtr); + ut_a(success); break; + case DICT_COLUMNS_ID: + /* This is rolling back an INSERT into SYS_COLUMNS. + If it was part of an instant ALTER TABLE operation, we + must evict the table definition, so that it can be + reloaded after the dictionary operation has been + completed. At this point, any corresponding operation + to the metadata record will have been rolled back. */ + ut_ad(!online); + ut_ad(node->trx->dict_operation_lock_mode + == RW_X_LATCH); + ut_ad(node->rec_type == TRX_UNDO_INSERT_REC); + if (rec_get_n_fields_old(rec) + != DICT_NUM_FIELDS__SYS_COLUMNS) { + break; + } + ulint len; + const byte* data = rec_get_nth_field_old( + rec, DICT_FLD__SYS_COLUMNS__TABLE_ID, &len); + if (len != 8) { + break; + } + node->trx->evict_table(mach_read_from_8(data)); } - - dict_index_t* index = dict_table_get_first_index(table); - - if (index && index->is_instant() - && DATA_N_SYS_COLS + 1 + pos == table->n_cols) { - /* This is the rollback of an instant ADD COLUMN. - Remove the column from the dictionary cache, - but keep the system columns. */ - table->rollback_instant(pos); - } - - dict_table_close(table, true, false); } - if (btr_cur_optimistic_delete(btr_cur, 0, &mtr)) { + if (btr_cur_optimistic_delete(&node->pcur.btr_cur, 0, &mtr)) { err = DB_SUCCESS; goto func_exit; } @@ -207,7 +183,8 @@ retry: &node->pcur, &mtr); ut_a(success); - btr_cur_pessimistic_delete(&err, FALSE, btr_cur, 0, true, &mtr); + btr_cur_pessimistic_delete(&err, FALSE, &node->pcur.btr_cur, 0, true, + &mtr); /* The delete operation may fail if we have little file space left: TODO: easiest to crash the database @@ -226,29 +203,34 @@ retry: } func_exit: - btr_pcur_commit_specify_mtr(&node->pcur, &mtr); if (err == DB_SUCCESS && node->rec_type == TRX_UNDO_INSERT_METADATA) { /* When rolling back the very first instant ADD COLUMN operation, reset the root page to the basic state. */ ut_ad(!index->table->is_temporary()); - mtr.start(); if (page_t* root = btr_root_get(index, &mtr)) { byte* page_type = root + FIL_PAGE_TYPE; ut_ad(mach_read_from_2(page_type) == FIL_PAGE_TYPE_INSTANT || mach_read_from_2(page_type) == FIL_PAGE_INDEX); - index->set_modified(mtr); mlog_write_ulint(page_type, FIL_PAGE_INDEX, MLOG_2BYTES, &mtr); byte* instant = PAGE_INSTANT + PAGE_HEADER + root; mlog_write_ulint(instant, page_ptr_get_direction(instant + 1), MLOG_2BYTES, &mtr); + rec_t* infimum = page_get_infimum_rec(root); + rec_t* supremum = page_get_supremum_rec(root); + static const byte str[8 + 8] = "supremuminfimum"; + if (memcmp(infimum, str + 8, 8) + || memcmp(supremum, str, 8)) { + mlog_write_string(infimum, str + 8, 8, &mtr); + mlog_write_string(supremum, str, 8, &mtr); + } } - mtr.commit(); } + btr_pcur_commit_specify_mtr(&node->pcur, &mtr); return(err); } @@ -388,14 +370,10 @@ retry: return(err); } -/***********************************************************//** -Parses the row reference and other info in a fresh insert undo record. */ -static -void -row_undo_ins_parse_undo_rec( -/*========================*/ - undo_node_t* node, /*!< in/out: row undo node */ - ibool dict_locked) /*!< in: TRUE if own dict_sys->mutex */ +/** Parse an insert undo record. +@param[in,out] node row rollback state +@param[in] dict_locked whether the data dictionary cache is locked */ +static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked) { dict_index_t* clust_index; byte* ptr; @@ -404,18 +382,28 @@ row_undo_ins_parse_undo_rec( ulint dummy; bool dummy_extern; - ut_ad(node); + ut_ad(node->state == UNDO_INSERT_PERSISTENT + || node->state == UNDO_INSERT_TEMPORARY); + ut_ad(node->trx->in_rollback); + ut_ad(trx_undo_roll_ptr_is_insert(node->roll_ptr)); ptr = trx_undo_rec_get_pars(node->undo_rec, &node->rec_type, &dummy, &dummy_extern, &undo_no, &table_id); node->update = NULL; - node->table = dict_table_open_on_id( - table_id, dict_locked, DICT_TABLE_OP_NORMAL); + if (node->state == UNDO_INSERT_PERSISTENT) { + node->table = dict_table_open_on_id(table_id, dict_locked, + DICT_TABLE_OP_NORMAL); + } else if (!dict_locked) { + mutex_enter(&dict_sys->mutex); + node->table = dict_sys->get_temporary_table(table_id); + mutex_exit(&dict_sys->mutex); + } else { + node->table = dict_sys->get_temporary_table(table_id); + } - /* Skip the UNDO if we can't find the table or the .ibd file. */ - if (UNIV_UNLIKELY(node->table == NULL)) { - return; + if (!node->table) { + return false; } switch (node->rec_type) { @@ -454,6 +442,7 @@ close_table: connection, instead of doing this rollback. */ dict_table_close(node->table, dict_locked, FALSE); node->table = NULL; + return false; } else { ut_ad(!node->table->skip_alter_undo); clust_index = dict_table_get_first_index(node->table); @@ -485,6 +474,8 @@ close_table: goto close_table; } } + + return true; } /***************************************************************//** @@ -561,18 +552,10 @@ row_undo_ins( que_thr_t* thr) /*!< in: query thread */ { dberr_t err; - ibool dict_locked; - - ut_ad(node->state == UNDO_NODE_INSERT); - ut_ad(node->trx->in_rollback); - ut_ad(trx_undo_roll_ptr_is_insert(node->roll_ptr)); + bool dict_locked = node->trx->dict_operation_lock_mode == RW_X_LATCH; - dict_locked = node->trx->dict_operation_lock_mode == RW_X_LATCH; - - row_undo_ins_parse_undo_rec(node, dict_locked); - - if (node->table == NULL) { - return(DB_SUCCESS); + if (!row_undo_ins_parse_undo_rec(node, dict_locked)) { + return DB_SUCCESS; } /* Iterate over all the indexes and undo the insert.*/ @@ -595,26 +578,19 @@ row_undo_ins( break; } - /* fall through */ - case TRX_UNDO_INSERT_METADATA: log_free_check(); if (node->table->id == DICT_INDEXES_ID) { - ut_ad(node->rec_type == TRX_UNDO_INSERT_REC); - + ut_ad(!node->table->is_temporary()); if (!dict_locked) { mutex_enter(&dict_sys->mutex); } - } - - // FIXME: We need to update the dict_index_t::space and - // page number fields too. - err = row_undo_ins_remove_clust_rec(node); - - if (node->table->id == DICT_INDEXES_ID - && !dict_locked) { - - mutex_exit(&dict_sys->mutex); + err = row_undo_ins_remove_clust_rec(node); + if (!dict_locked) { + mutex_exit(&dict_sys->mutex); + } + } else { + err = row_undo_ins_remove_clust_rec(node); } if (err == DB_SUCCESS && node->table->stat_initialized) { @@ -634,6 +610,12 @@ row_undo_ins( node->table, node->trx->mysql_thd); } } + break; + + case TRX_UNDO_INSERT_METADATA: + log_free_check(); + ut_ad(!node->table->is_temporary()); + err = row_undo_ins_remove_clust_rec(node); } dict_table_close(node->table, dict_locked, FALSE); diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 41079450159..7ff64929080 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -111,6 +111,9 @@ row_undo_mod_clust_low( ut_ad(rec_get_trx_id(btr_cur_get_rec(btr_cur), btr_cur_get_index(btr_cur)) == thr_get_trx(thr)->id); + ut_ad(node->ref != &trx_undo_metadata + || node->update->info_bits == REC_INFO_METADATA_ADD + || node->update->info_bits == REC_INFO_METADATA_ALTER); if (mode != BTR_MODIFY_LEAF && dict_index_is_online_ddl(btr_cur_get_index(btr_cur))) { @@ -131,6 +134,7 @@ row_undo_mod_clust_low( btr_cur, offsets, offsets_heap, node->update, node->cmpl_info, thr, thr_get_trx(thr)->id, mtr); + ut_ad(err != DB_SUCCESS || node->ref != &trx_undo_metadata); } else { big_rec_t* dummy_big_rec; @@ -143,6 +147,52 @@ row_undo_mod_clust_low( node->cmpl_info, thr, thr_get_trx(thr)->id, mtr); ut_a(!dummy_big_rec); + + static const byte + INFIMUM[8] = {'i','n','f','i','m','u','m',0}, + SUPREMUM[8] = {'s','u','p','r','e','m','u','m'}; + + if (err == DB_SUCCESS + && node->ref == &trx_undo_metadata + && btr_cur_get_index(btr_cur)->table->instant + && node->update->info_bits == REC_INFO_METADATA_ADD) { + if (page_t* root = btr_root_get( + btr_cur_get_index(btr_cur), mtr)) { + byte* infimum; + byte *supremum; + if (page_is_comp(root)) { + infimum = PAGE_NEW_INFIMUM + root; + supremum = PAGE_NEW_SUPREMUM + root; + } else { + infimum = PAGE_OLD_INFIMUM + root; + supremum = PAGE_OLD_SUPREMUM + root; + } + + ut_ad(!memcmp(infimum, INFIMUM, 8) + == !memcmp(supremum, SUPREMUM, 8)); + + if (memcmp(infimum, INFIMUM, 8)) { + mlog_write_string(infimum, INFIMUM, + 8, mtr); + mlog_write_string(supremum, SUPREMUM, + 8, mtr); + } + } + } + } + + if (err == DB_SUCCESS + && btr_cur_get_index(btr_cur)->table->id == DICT_COLUMNS_ID) { + /* This is rolling back an UPDATE or DELETE on SYS_COLUMNS. + If it was part of an instant ALTER TABLE operation, we + must evict the table definition, so that it can be + reloaded after the dictionary operation has been + completed. At this point, any corresponding operation + to the metadata record will have been rolled back. */ + const dfield_t& table_id = *dtuple_get_nth_field(node->row, 0); + ut_ad(dfield_get_len(&table_id) == 8); + node->trx->evict_table(mach_read_from_8(static_cast<byte*>( + table_id.data))); } return(err); @@ -399,22 +449,34 @@ row_undo_mod_clust( goto mtr_commit_exit; } + ulint trx_id_offset = index->trx_id_offset; ulint trx_id_pos = index->n_uniq ? index->n_uniq : 1; - ut_ad(index->n_uniq <= MAX_REF_PARTS); - /* Reserve enough offsets for the PRIMARY KEY and 2 columns - so that we can access DB_TRX_ID, DB_ROLL_PTR. */ + /* Reserve enough offsets for the PRIMARY KEY and + 2 columns so that we can access DB_TRX_ID, DB_ROLL_PTR. */ ulint offsets_[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS + 2]; - rec_offs_init(offsets_); - offsets = rec_get_offsets( - rec, index, offsets_, true, trx_id_pos + 2, &heap); - ulint len; - ulint trx_id_offset = rec_get_nth_field_offs( - offsets, trx_id_pos, &len); - ut_ad(len == DATA_TRX_ID_LEN); + if (trx_id_offset) { + } else if (rec_is_metadata(rec, *index)) { + ut_ad(!buf_block_get_page_zip(btr_pcur_get_block( + &node->pcur))); + for (unsigned i = index->first_user_field(); i--; ) { + trx_id_offset += index->fields[i].fixed_len; + } + } else { + ut_ad(index->n_uniq <= MAX_REF_PARTS); + rec_offs_init(offsets_); + offsets = rec_get_offsets( + rec, index, offsets_, true, trx_id_pos + 2, + &heap); + ulint len; + trx_id_offset = rec_get_nth_field_offs( + offsets, trx_id_pos, &len); + ut_ad(len == DATA_TRX_ID_LEN); + } if (trx_read_trx_id(rec + trx_id_offset) == node->new_trx_id) { ut_ad(!rec_get_deleted_flag( - rec, dict_table_is_comp(node->table))); + rec, dict_table_is_comp(node->table)) + || rec_is_alter_metadata(rec, *index)); index->set_modified(mtr); if (page_zip_des_t* page_zip = buf_block_get_page_zip( btr_pcur_get_block(&node->pcur))) { @@ -436,8 +498,6 @@ mtr_commit_exit: btr_pcur_commit_specify_mtr(pcur, &mtr); func_exit: - node->state = UNDO_NODE_FETCH_NEXT; - if (offsets_heap) { mem_heap_free(offsets_heap); } @@ -1139,14 +1199,10 @@ row_undo_mod_upd_exist_sec( return(err); } -/***********************************************************//** -Parses the row reference and other info in a modify undo log record. */ -static MY_ATTRIBUTE((nonnull)) -void -row_undo_mod_parse_undo_rec( -/*========================*/ - undo_node_t* node, /*!< in: row undo node */ - ibool dict_locked) /*!< in: TRUE if own dict_sys->mutex */ +/** Parse an update undo record. +@param[in,out] node row rollback state +@param[in] dict_locked whether the data dictionary cache is locked */ +static bool row_undo_mod_parse_undo_rec(undo_node_t* node, bool dict_locked) { dict_index_t* clust_index; byte* ptr; @@ -1159,19 +1215,28 @@ row_undo_mod_parse_undo_rec( ulint cmpl_info; bool dummy_extern; + ut_ad(node->state == UNDO_UPDATE_PERSISTENT + || node->state == UNDO_UPDATE_TEMPORARY); + ut_ad(node->trx->in_rollback); + ut_ad(!trx_undo_roll_ptr_is_insert(node->roll_ptr)); + ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info, &dummy_extern, &undo_no, &table_id); node->rec_type = type; - node->table = dict_table_open_on_id( - table_id, dict_locked, DICT_TABLE_OP_NORMAL); - - /* TODO: other fixes associated with DROP TABLE + rollback in the - same table by another user */ + if (node->state == UNDO_UPDATE_PERSISTENT) { + node->table = dict_table_open_on_id(table_id, dict_locked, + DICT_TABLE_OP_NORMAL); + } else if (!dict_locked) { + mutex_enter(&dict_sys->mutex); + node->table = dict_sys->get_temporary_table(table_id); + mutex_exit(&dict_sys->mutex); + } else { + node->table = dict_sys->get_temporary_table(table_id); + } - if (node->table == NULL) { - /* Table was dropped */ - return; + if (!node->table) { + return false; } ut_ad(!node->table->skip_alter_undo); @@ -1189,7 +1254,7 @@ close_table: connection, instead of doing this rollback. */ dict_table_close(node->table, dict_locked, FALSE); node->table = NULL; - return; + return false; } clust_index = dict_table_get_first_index(node->table); @@ -1208,16 +1273,21 @@ close_table: ut_ad(!node->ref->info_bits); if (node->update->info_bits & REC_INFO_MIN_REC_FLAG) { - /* This must be an undo log record for a subsequent - instant ALTER TABLE, extending the metadata record. */ - ut_ad(clust_index->is_instant()); - if (node->update->info_bits != REC_INFO_MIN_REC_FLAG) { + if ((node->update->info_bits & ~REC_INFO_DELETED_FLAG) + != REC_INFO_MIN_REC_FLAG) { ut_ad(!"wrong info_bits in undo log record"); goto close_table; } - node->update->info_bits = REC_INFO_METADATA; - const_cast<dtuple_t*>(node->ref)->info_bits - = REC_INFO_METADATA; + /* This must be an undo log record for a subsequent + instant ALTER TABLE, extending the metadata record. */ + ut_ad(clust_index->is_instant()); + ut_ad(clust_index->table->instant + || !(node->update->info_bits & REC_INFO_DELETED_FLAG)); + node->ref = &trx_undo_metadata; + node->update->info_bits = (node->update->info_bits + & REC_INFO_DELETED_FLAG) + ? REC_INFO_METADATA_ALTER + : REC_INFO_METADATA_ADD; } if (!row_undo_search_clust_to_pcur(node)) { @@ -1255,6 +1325,8 @@ close_table: (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) ? NULL : ptr); } + + return true; } /***********************************************************//** @@ -1267,34 +1339,19 @@ row_undo_mod( que_thr_t* thr) /*!< in: query thread */ { dberr_t err; - ibool dict_locked; - - ut_ad(node != NULL); - ut_ad(thr != NULL); - ut_ad(node->state == UNDO_NODE_MODIFY); - ut_ad(node->trx->in_rollback); - ut_ad(!trx_undo_roll_ptr_is_insert(node->roll_ptr)); - - dict_locked = thr_get_trx(thr)->dict_operation_lock_mode == RW_X_LATCH; - ut_ad(thr_get_trx(thr) == node->trx); + const bool dict_locked = node->trx->dict_operation_lock_mode + == RW_X_LATCH; - row_undo_mod_parse_undo_rec(node, dict_locked); - - if (node->table == NULL) { - /* It is already undone, or will be undone by another query - thread, or table was dropped */ - - node->state = UNDO_NODE_FETCH_NEXT; - - return(DB_SUCCESS); + if (!row_undo_mod_parse_undo_rec(node, dict_locked)) { + return DB_SUCCESS; } node->index = dict_table_get_first_index(node->table); ut_ad(dict_index_is_clust(node->index)); if (node->ref->info_bits) { - ut_ad(node->ref->info_bits == REC_INFO_METADATA); + ut_ad(node->ref->is_metadata()); goto rollback_clust; } diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 9b88f950917..2b8187171f9 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -217,7 +217,8 @@ row_undo_search_clust_to_pcur( log, first mark them DATA_MISSING. So we will know if the value gets updated */ if (node->table->n_v_cols - && node->state != UNDO_NODE_INSERT + && (node->state == UNDO_UPDATE_PERSISTENT + || node->state == UNDO_UPDATE_TEMPORARY) && !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { for (ulint i = 0; i < dict_table_get_n_v_cols(node->table); i++) { @@ -227,13 +228,15 @@ row_undo_search_clust_to_pcur( } if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) { - ut_ad(node->row->info_bits == REC_INFO_MIN_REC_FLAG + ut_ad((node->row->info_bits & ~REC_INFO_DELETED_FLAG) + == REC_INFO_MIN_REC_FLAG || node->row->info_bits == 0); node->undo_row = dtuple_copy(node->row, node->heap); row_upd_replace(node->undo_row, &node->undo_ext, clust_index, node->update, node->heap); } else { - ut_ad((node->row->info_bits == REC_INFO_MIN_REC_FLAG) + ut_ad(((node->row->info_bits & ~REC_INFO_DELETED_FLAG) + == REC_INFO_MIN_REC_FLAG) == (node->rec_type == TRX_UNDO_INSERT_METADATA)); node->undo_row = NULL; node->undo_ext = NULL; @@ -251,6 +254,149 @@ func_exit: return(found); } +/** Try to truncate the undo logs. +@param[in,out] trx transaction */ +static void row_undo_try_truncate(trx_t* trx) +{ + if (trx_undo_t* undo = trx->rsegs.m_redo.undo) { + ut_ad(undo->rseg == trx->rsegs.m_redo.rseg); + trx_undo_truncate_end(*undo, trx->undo_no, false); + } + + if (trx_undo_t* undo = trx->rsegs.m_noredo.undo) { + ut_ad(undo->rseg == trx->rsegs.m_noredo.rseg); + trx_undo_truncate_end(*undo, trx->undo_no, true); + } +} + +/** Get the latest undo log record for rollback. +@param[in,out] node rollback context +@return whether an undo log record was fetched */ +static bool row_undo_rec_get(undo_node_t* node) +{ + trx_t* trx = node->trx; + + if (trx->pages_undone) { + trx->pages_undone = 0; + row_undo_try_truncate(trx); + } + + trx_undo_t* undo = NULL; + trx_undo_t* insert = trx->rsegs.m_redo.old_insert; + trx_undo_t* update = trx->rsegs.m_redo.undo; + trx_undo_t* temp = trx->rsegs.m_noredo.undo; + const undo_no_t limit = trx->roll_limit; + + ut_ad(!insert || !update || insert->empty() || update->empty() + || insert->top_undo_no != update->top_undo_no); + ut_ad(!insert || !temp || insert->empty() || temp->empty() + || insert->top_undo_no != temp->top_undo_no); + ut_ad(!update || !temp || update->empty() || temp->empty() + || update->top_undo_no != temp->top_undo_no); + + if (UNIV_LIKELY_NULL(insert) + && !insert->empty() && limit <= insert->top_undo_no) { + undo = insert; + } + + if (update && !update->empty() && update->top_undo_no >= limit) { + if (!undo) { + undo = update; + } else if (undo->top_undo_no < update->top_undo_no) { + undo = update; + } + } + + if (temp && !temp->empty() && temp->top_undo_no >= limit) { + if (!undo) { + undo = temp; + } else if (undo->top_undo_no < temp->top_undo_no) { + undo = temp; + } + } + + if (undo == NULL) { + row_undo_try_truncate(trx); + /* Mark any ROLLBACK TO SAVEPOINT completed, so that + if the transaction object is committed and reused + later, we will default to a full ROLLBACK. */ + trx->roll_limit = 0; + trx->in_rollback = false; + return false; + } + + ut_ad(!undo->empty()); + ut_ad(limit <= undo->top_undo_no); + + node->roll_ptr = trx_undo_build_roll_ptr( + false, undo->rseg->id, undo->top_page_no, undo->top_offset); + + mtr_t mtr; + mtr.start(); + + page_t* undo_page = trx_undo_page_get_s_latched( + page_id_t(undo->rseg->space->id, undo->top_page_no), &mtr); + + ulint offset = undo->top_offset; + + trx_undo_rec_t* prev_rec = trx_undo_get_prev_rec( + undo_page + offset, undo->hdr_page_no, undo->hdr_offset, + true, &mtr); + + if (prev_rec == NULL) { + undo->top_undo_no = IB_ID_MAX; + ut_ad(undo->empty()); + } else { + page_t* prev_rec_page = page_align(prev_rec); + + if (prev_rec_page != undo_page) { + + trx->pages_undone++; + } + + undo->top_page_no = page_get_page_no(prev_rec_page); + undo->top_offset = ulint(prev_rec - prev_rec_page); + undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec); + ut_ad(!undo->empty()); + } + + { + const trx_undo_rec_t* undo_rec = undo_page + offset; + node->undo_rec = trx_undo_rec_copy(undo_rec, node->heap); + } + + mtr.commit(); + + switch (trx_undo_rec_get_type(node->undo_rec)) { + case TRX_UNDO_INSERT_METADATA: + /* This record type was introduced in MDEV-11369 + instant ADD COLUMN, which was implemented after + MDEV-12288 removed the insert_undo log. There is no + instant ADD COLUMN for temporary tables. Therefore, + this record can only be present in the main undo log. */ + ut_ad(undo == update); + /* fall through */ + case TRX_UNDO_RENAME_TABLE: + ut_ad(undo == insert || undo == update); + /* fall through */ + case TRX_UNDO_INSERT_REC: + ut_ad(undo == insert || undo == update || undo == temp); + node->roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS; + node->state = undo == temp + ? UNDO_INSERT_TEMPORARY : UNDO_INSERT_PERSISTENT; + break; + default: + ut_ad(undo == update || undo == temp); + node->state = undo == temp + ? UNDO_UPDATE_TEMPORARY : UNDO_UPDATE_PERSISTENT; + break; + } + + trx->undo_no = node->undo_no = trx_undo_rec_get_undo_no( + node->undo_rec); + return true; +} + /***********************************************************//** Fetches an undo log record and does the undo for the recorded operation. If none left, or a partial rollback completed, returns control to the @@ -263,23 +409,12 @@ row_undo( undo_node_t* node, /*!< in: row undo node */ que_thr_t* thr) /*!< in: query thread */ { - trx_t* trx = node->trx; - ut_ad(trx->in_rollback); - - if (node->state == UNDO_NODE_FETCH_NEXT) { - - node->undo_rec = trx_roll_pop_top_rec_of_trx( - trx, &node->roll_ptr, node->heap); - - if (!node->undo_rec) { - /* Rollback completed for this query thread */ - thr->run_node = que_node_get_parent(node); - return(DB_SUCCESS); - } + ut_ad(node->trx->in_rollback); - node->undo_no = trx_undo_rec_get_undo_no(node->undo_rec); - node->state = trx_undo_roll_ptr_is_insert(node->roll_ptr) - ? UNDO_NODE_INSERT : UNDO_NODE_MODIFY; + if (node->state == UNDO_NODE_FETCH_NEXT && !row_undo_rec_get(node)) { + /* Rollback completed for this query thread */ + thr->run_node = que_node_get_parent(node); + return DB_SUCCESS; } /* Prevent DROP TABLE etc. while we are rolling back this row. @@ -287,31 +422,33 @@ row_undo( then we already have dict_operation_lock locked in x-mode. Do not try to lock again, because that would cause a hang. */ + trx_t* trx = node->trx; const bool locked_data_dict = (trx->dict_operation_lock_mode == 0); if (locked_data_dict) { - row_mysql_freeze_data_dictionary(trx); } dberr_t err; - if (node->state == UNDO_NODE_INSERT) { - + switch (node->state) { + case UNDO_INSERT_PERSISTENT: + case UNDO_INSERT_TEMPORARY: err = row_undo_ins(node, thr); - - node->state = UNDO_NODE_FETCH_NEXT; - } else { - ut_ad(node->state == UNDO_NODE_MODIFY); + break; + case UNDO_UPDATE_PERSISTENT: + case UNDO_UPDATE_TEMPORARY: err = row_undo_mod(node, thr); + break; + case UNDO_NODE_FETCH_NEXT: + ut_ad(!"wrong state"); } if (locked_data_dict) { - row_mysql_unfreeze_data_dictionary(trx); } - /* Do some cleanup */ + node->state = UNDO_NODE_FETCH_NEXT; btr_pcur_close(&(node->pcur)); mem_heap_empty(node->heap); diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index a60694c6613..b4f2b91881a 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -495,39 +495,6 @@ row_upd_rec_sys_fields_in_recovery( } } -/*********************************************************************//** -Sets the trx id or roll ptr field of a clustered index entry. */ -void -row_upd_index_entry_sys_field( -/*==========================*/ - dtuple_t* entry, /*!< in/out: index entry, where the memory - buffers for sys fields are already allocated: - the function just copies the new values to - them */ - dict_index_t* index, /*!< in: clustered index */ - ulint type, /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */ - ib_uint64_t val) /*!< in: value to write */ -{ - dfield_t* dfield; - byte* field; - ulint pos; - - ut_ad(dict_index_is_clust(index)); - - pos = dict_index_get_sys_col_pos(index, type); - - dfield = dtuple_get_nth_field(entry, pos); - field = static_cast<byte*>(dfield_get_data(dfield)); - - if (type == DATA_TRX_ID) { - ut_ad(val > 0); - trx_write_trx_id(field, val); - } else { - ut_ad(type == DATA_ROLL_PTR); - trx_write_roll_ptr(field, val); - } -} - /***********************************************************//** Returns TRUE if row update changes size of some field in index or if some field to be updated is stored externally in rec or update. @@ -680,7 +647,7 @@ row_upd_rec_in_place( switch (rec_get_status(rec)) { case REC_STATUS_ORDINARY: break; - case REC_STATUS_COLUMNS_ADDED: + case REC_STATUS_INSTANT: ut_ad(index->is_instant()); break; case REC_STATUS_NODE_PTR: @@ -731,35 +698,6 @@ row_upd_rec_in_place( } /*********************************************************************//** -Writes into the redo log the values of trx id and roll ptr and enough info -to determine their positions within a clustered index record. -@return new pointer to mlog */ -byte* -row_upd_write_sys_vals_to_log( -/*==========================*/ - dict_index_t* index, /*!< in: clustered index */ - trx_id_t trx_id, /*!< in: transaction id */ - roll_ptr_t roll_ptr,/*!< in: roll ptr of the undo log record */ - byte* log_ptr,/*!< pointer to a buffer of size > 20 opened - in mlog */ - mtr_t* mtr MY_ATTRIBUTE((unused))) /*!< in: mtr */ -{ - ut_ad(dict_index_is_clust(index)); - ut_ad(mtr); - - log_ptr += mach_write_compressed(log_ptr, - dict_index_get_sys_col_pos( - index, DATA_TRX_ID)); - - trx_write_roll_ptr(log_ptr, roll_ptr); - log_ptr += DATA_ROLL_PTR_LEN; - - log_ptr += mach_u64_write_compressed(log_ptr, trx_id); - - return(log_ptr); -} - -/*********************************************************************//** Parses the log data of system field values. @return log data end or NULL */ byte* @@ -1053,7 +991,6 @@ row_upd_build_difference_binary( ulint len; upd_t* update; ulint n_diff; - ulint trx_id_pos; ulint i; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint n_fld = dtuple_get_n_fields(entry); @@ -1068,10 +1005,6 @@ row_upd_build_difference_binary( n_diff = 0; - trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); - ut_ad(dict_index_get_sys_col_pos(index, DATA_ROLL_PTR) - == trx_id_pos + 1); - if (!offsets) { offsets = rec_get_offsets(rec, index, offsets_, true, ULINT_UNDEFINED, &heap); @@ -1086,16 +1019,9 @@ row_upd_build_difference_binary( /* NOTE: we compare the fields as binary strings! (No collation) */ - if (no_sys) { - /* TRX_ID */ - if (i == trx_id_pos) { - continue; - } - - /* DB_ROLL_PTR */ - if (i == trx_id_pos + 1) { - continue; - } + if (no_sys && (i == index->db_trx_id() + || i == index->db_roll_ptr())) { + continue; } if (!dfield_is_ext(dfield) @@ -1254,7 +1180,7 @@ row_upd_index_replace_new_col_val( len = dfield_get_len(dfield); data = static_cast<const byte*>(dfield_get_data(dfield)); - if (field->prefix_len > 0) { + if (field && field->prefix_len > 0) { ibool fetch_ext = dfield_is_ext(dfield) && len < (ulint) field->prefix_len + BTR_EXTERN_FIELD_REF_SIZE; @@ -1320,6 +1246,57 @@ row_upd_index_replace_new_col_val( } } +/** Apply an update vector to an metadata entry. +@param[in,out] entry clustered index metadata record to be updated +@param[in] index index of the entry +@param[in] update update vector built for the entry +@param[in,out] heap memory heap for copying off-page columns */ +static +void +row_upd_index_replace_metadata( + dtuple_t* entry, + const dict_index_t* index, + const upd_t* update, + mem_heap_t* heap) +{ + ut_ad(!index->table->skip_alter_undo); + ut_ad(update->is_alter_metadata()); + ut_ad(entry->info_bits == update->info_bits); + ut_ad(entry->n_fields == ulint(index->n_fields) + 1); + const page_size_t& page_size = dict_table_page_size(index->table); + const ulint first = index->first_user_field(); + ut_d(bool found_mblob = false); + + for (ulint i = upd_get_n_fields(update); i--; ) { + const upd_field_t* uf = upd_get_nth_field(update, i); + ut_ad(!upd_fld_is_virtual_col(uf)); + ut_ad(uf->field_no >= first - 2); + ulint f = uf->field_no; + dfield_t* dfield = dtuple_get_nth_field(entry, f); + + if (f == first) { + ut_d(found_mblob = true); + ut_ad(!dfield_is_null(&uf->new_val)); + ut_ad(dfield_is_ext(dfield)); + ut_ad(dfield_get_len(dfield) == FIELD_REF_SIZE); + ut_ad(!dfield_is_null(dfield)); + dfield_set_data(dfield, uf->new_val.data, + uf->new_val.len); + if (dfield_is_ext(&uf->new_val)) { + dfield_set_ext(dfield); + } + continue; + } + + f -= f > first; + const dict_field_t* field = dict_index_get_nth_field(index, f); + row_upd_index_replace_new_col_val(dfield, field, field->col, + uf, heap, page_size); + } + + ut_ad(found_mblob); +} + /** Apply an update vector to an index entry. @param[in,out] entry index entry to be updated; the clustered index record must be covered by a lock or a page latch to prevent @@ -1335,6 +1312,12 @@ row_upd_index_replace_new_col_vals_index_pos( mem_heap_t* heap) { ut_ad(!index->table->skip_alter_undo); + ut_ad(!entry->is_metadata() || entry->info_bits == update->info_bits); + + if (UNIV_UNLIKELY(entry->is_alter_metadata())) { + row_upd_index_replace_metadata(entry, index, update, heap); + return; + } const page_size_t& page_size = dict_table_page_size(index->table); @@ -2560,10 +2543,10 @@ row_upd_sec_step( } #ifdef UNIV_DEBUG -# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \ - row_upd_clust_rec_by_insert_inherit_func(rec,offsets,entry,update) +# define row_upd_clust_rec_by_insert_inherit(rec,index,offsets,entry,update) \ + row_upd_clust_rec_by_insert_inherit_func(rec,index,offsets,entry,update) #else /* UNIV_DEBUG */ -# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \ +# define row_upd_clust_rec_by_insert_inherit(rec,index,offsets,entry,update) \ row_upd_clust_rec_by_insert_inherit_func(rec,entry,update) #endif /* UNIV_DEBUG */ /*******************************************************************//** @@ -2578,6 +2561,7 @@ row_upd_clust_rec_by_insert_inherit_func( /*=====================================*/ const rec_t* rec, /*!< in: old record, or NULL */ #ifdef UNIV_DEBUG + dict_index_t* index, /*!< in: index, or NULL */ const ulint* offsets,/*!< in: rec_get_offsets(rec), or NULL */ #endif /* UNIV_DEBUG */ dtuple_t* entry, /*!< in/out: updated entry to be @@ -2588,6 +2572,8 @@ row_upd_clust_rec_by_insert_inherit_func( ulint i; ut_ad(!rec == !offsets); + ut_ad(!rec == !index); + ut_ad(!rec || rec_offs_validate(rec, index, offsets)); ut_ad(!rec || rec_offs_any_extern(offsets)); for (i = 0; i < dtuple_get_n_fields(entry); i++) { @@ -2598,6 +2584,9 @@ row_upd_clust_rec_by_insert_inherit_func( ut_ad(!offsets || !rec_offs_nth_extern(offsets, i) == !dfield_is_ext(dfield) + || (!dict_index_get_nth_field(index, i)->name + && !dfield_is_ext(dfield) + && (dfield_is_null(dfield) || dfield->len == 0)) || upd_get_field_by_field_no(update, i, false)); if (!dfield_is_ext(dfield) || upd_get_field_by_field_no(update, i, false)) { @@ -2696,7 +2685,11 @@ row_upd_clust_rec_by_insert( if (index->is_instant()) entry->trim(*index); ut_ad(dtuple_get_info_bits(entry) == 0); - row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id); + { + dfield_t* t = dtuple_get_nth_field(entry, index->db_trx_id()); + ut_ad(t->len == DATA_TRX_ID_LEN); + trx_write_trx_id(static_cast<byte*>(t->data), trx->id); + } switch (node->state) { default: @@ -2705,7 +2698,7 @@ row_upd_clust_rec_by_insert( /* A lock wait occurred in row_ins_clust_index_entry() in the previous invocation of this function. */ row_upd_clust_rec_by_insert_inherit( - NULL, NULL, entry, node->update); + NULL, NULL, NULL, entry, node->update); break; case UPD_NODE_UPDATE_CLUSTERED: /* This is the first invocation of the function where @@ -2746,7 +2739,8 @@ err_exit: if (rec_offs_any_extern(offsets)) { if (row_upd_clust_rec_by_insert_inherit( - rec, offsets, entry, node->update)) { + rec, index, offsets, + entry, node->update)) { /* The blobs are disowned here, expecting the insert down below to inherit them. But if the insert fails, then this disown will be undone diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index 85d9f0522aa..8fa71689caf 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -298,12 +298,6 @@ static monitor_info_t innodb_counter_info[] = MONITOR_EXISTING | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_OVLD_PAGES_READ}, - {"buffer_pages0_read", "buffer", - "Number of page 0 read (innodb_pages0_read)", - static_cast<monitor_type_t>( - MONITOR_EXISTING | MONITOR_DEFAULT_ON), - MONITOR_DEFAULT_START, MONITOR_OVLD_PAGES0_READ}, - {"buffer_index_sec_rec_cluster_reads", "buffer", "Number of secondary record reads triggered cluster read", static_cast<monitor_type_t>( @@ -802,11 +796,6 @@ static monitor_info_t innodb_counter_info[] = MONITOR_NONE, MONITOR_DEFAULT_START, MONITOR_TRX_ROLLBACK_SAVEPOINT}, - {"trx_rollback_active", "transaction", - "Number of resurrected active transactions rolled back", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_TRX_ROLLBACK_ACTIVE}, - {"trx_active_transactions", "transaction", "Number of active transactions", MONITOR_NONE, @@ -1745,11 +1734,6 @@ srv_mon_process_existing_counter( value = stat.n_pages_read; break; - /* innodb_pages0_read */ - case MONITOR_OVLD_PAGES0_READ: - value = srv_stats.page0_read; - break; - /* Number of times secondary index lookup triggered cluster lookup */ case MONITOR_OVLD_INDEX_SEC_REC_CLUSTER_READS: value = srv_stats.n_sec_rec_cluster_reads; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index f3cab013437..8db656cd561 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -59,7 +59,6 @@ Created 10/8/1995 Heikki Tuuri #include "pars0pars.h" #include "que0que.h" #include "row0mysql.h" -#include "row0trunc.h" #include "row0log.h" #include "srv0mon.h" #include "srv0srv.h" @@ -1537,7 +1536,6 @@ srv_export_innodb_status(void) export_vars.innodb_pages_created = stat.n_pages_created; export_vars.innodb_pages_read = stat.n_pages_read; - export_vars.innodb_page0_read = srv_stats.page0_read; export_vars.innodb_pages_written = stat.n_pages_written; @@ -2585,16 +2583,10 @@ srv_do_purge(ulint* n_total_purged) break; } - ulint undo_trunc_freq = - purge_sys.undo_trunc.get_rseg_truncate_frequency(); - - ulint rseg_truncate_frequency = ut_min( - static_cast<ulint>(srv_purge_rseg_truncate_frequency), - undo_trunc_freq); - n_pages_purged = trx_purge( n_use_threads, - (++count % rseg_truncate_frequency) == 0); + !(++count % srv_purge_rseg_truncate_frequency) + || purge_sys.truncate.current); *n_total_purged += n_pages_purged; } while (n_pages_purged > 0 && !purge_sys.paused() @@ -2729,11 +2721,6 @@ DECLARE_THREAD(srv_purge_coordinator_thread)( /* Note that we are shutting down. */ rw_lock_x_lock(&purge_sys.latch); purge_sys.coordinator_shutdown(); - - /* If there are any pending undo-tablespace truncate then clear - it off as we plan to shutdown the purge thread. */ - purge_sys.undo_trunc.clear(); - /* Ensure that the wait in purge_sys_t::stop() will terminate. */ os_event_set(purge_sys.event); @@ -2840,38 +2827,3 @@ void srv_purge_shutdown() srv_purge_wakeup(); } while (srv_sys.sys_threads[SRV_PURGE_SLOT].in_use); } - -/** Check if tablespace is being truncated. -(Ignore system-tablespace as we don't re-create the tablespace -and so some of the action that are suppressed by this function -for independent tablespace are not applicable to system-tablespace). -@param space_id space_id to check for truncate action -@return true if being truncated, false if not being - truncated or tablespace is system-tablespace. */ -bool -srv_is_tablespace_truncated(ulint space_id) -{ - if (is_system_tablespace(space_id)) { - return(false); - } - - return(truncate_t::is_tablespace_truncated(space_id) - || undo::Truncate::is_tablespace_truncated(space_id)); - -} - -/** Check if tablespace was truncated. -@param[in] space space object to check for truncate action -@return true if tablespace was truncated and we still have an active -MLOG_TRUNCATE REDO log record. */ -bool -srv_was_tablespace_truncated(const fil_space_t* space) -{ - if (space == NULL) { - ut_ad(0); - return(false); - } - - return (!is_system_tablespace(space->id) - && truncate_t::was_tablespace_truncated(space->id)); -} diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index a2c9828bfee..fa38741fb5d 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -74,7 +74,6 @@ Created 2/16/1996 Heikki Tuuri #include "srv0start.h" #include "srv0srv.h" #include "btr0defragment.h" -#include "row0trunc.h" #include "mysql/service_wsrep.h" /* wsrep_recovery */ #include "trx0rseg.h" #include "os0proc.h" @@ -97,7 +96,6 @@ Created 2/16/1996 Heikki Tuuri #include "row0upd.h" #include "row0row.h" #include "row0mysql.h" -#include "row0trunc.h" #include "btr0pcur.h" #include "os0event.h" #include "zlib.h" @@ -761,8 +759,6 @@ srv_check_undo_redo_logs_exists() return(DB_SUCCESS); } -undo::undo_spaces_t undo::Truncate::s_fix_up_spaces; - /** Open the configured number of dedicated undo tablespaces. @param[in] create_new_db whether the database is being initialized @return DB_SUCCESS or error code */ @@ -844,46 +840,8 @@ srv_undo_tablespaces_init(bool create_new_db) prev_space_id = srv_undo_space_id_start - 1; break; case SRV_OPERATION_NORMAL: - if (create_new_db) { - break; - } - /* fall through */ case SRV_OPERATION_RESTORE: case SRV_OPERATION_RESTORE_EXPORT: - ut_ad(!create_new_db); - - /* Check if any of the UNDO tablespace needs fix-up because - server crashed while truncate was active on UNDO tablespace.*/ - for (i = 0; i < n_undo_tablespaces; ++i) { - - undo::Truncate undo_trunc; - - if (undo_trunc.needs_fix_up(undo_tablespace_ids[i])) { - - char name[OS_FILE_MAX_PATH]; - - snprintf(name, sizeof(name), - "%s%cundo%03zu", - srv_undo_dir, OS_PATH_SEPARATOR, - undo_tablespace_ids[i]); - - os_file_delete(innodb_data_file_key, name); - - err = srv_undo_tablespace_create( - name, - SRV_UNDO_TABLESPACE_SIZE_IN_PAGES); - - if (err != DB_SUCCESS) { - ib::error() << "Could not fix-up undo " - " tablespace truncate '" - << name << "'."; - return(err); - } - - undo::Truncate::s_fix_up_spaces.push_back( - undo_tablespace_ids[i]); - } - } break; } @@ -988,64 +946,6 @@ srv_undo_tablespaces_init(bool create_new_db) } } - if (!undo::Truncate::s_fix_up_spaces.empty()) { - - /* Step-1: Initialize the tablespace header and rsegs header. */ - mtr_t mtr; - - mtr_start(&mtr); - /* Turn off REDO logging. We are in server start mode and fixing - UNDO tablespace even before REDO log is read. Let's say we - do REDO logging here then this REDO log record will be applied - as part of the current recovery process. We surely don't need - that as this is fix-up action parallel to REDO logging. */ - mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); - buf_block_t* sys_header = trx_sysf_get(&mtr); - if (!sys_header) { - mtr.commit(); - return DB_CORRUPTION; - } - - for (undo::undo_spaces_t::const_iterator it - = undo::Truncate::s_fix_up_spaces.begin(); - it != undo::Truncate::s_fix_up_spaces.end(); - ++it) { - - undo::Truncate::add_space_to_trunc_list(*it); - - fil_space_t* space = fil_space_get(*it); - - fsp_header_init(space, - SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, - &mtr); - - for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) { - if (trx_sysf_rseg_get_space(sys_header, i) - == *it) { - trx_rseg_header_create( - space, i, sys_header, &mtr); - } - } - - undo::Truncate::clear_trunc_list(); - } - mtr_commit(&mtr); - - /* Step-2: Flush the dirty pages from the buffer pool. */ - for (undo::undo_spaces_t::const_iterator it - = undo::Truncate::s_fix_up_spaces.begin(); - it != undo::Truncate::s_fix_up_spaces.end(); - ++it) { - FlushObserver dummy(fil_system.sys_space, NULL, NULL); - buf_LRU_flush_or_remove_pages(TRX_SYS_SPACE, &dummy); - FlushObserver dummy2(fil_space_get(*it), NULL, NULL); - buf_LRU_flush_or_remove_pages(*it, &dummy2); - - /* Remove the truncate redo log file. */ - undo::done(*it); - } - } - return(DB_SUCCESS); } @@ -1273,9 +1173,7 @@ srv_prepare_to_delete_redo_log_files( ulint pending_io = 0; ulint count = 0; - if ((log_sys.log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) - != LOG_HEADER_FORMAT_CURRENT - || log_sys.log.subformat != 2) { + if (log_sys.log.subformat != 2) { srv_log_file_size = 0; } @@ -1294,12 +1192,10 @@ srv_prepare_to_delete_redo_log_files( { ib::info info; - if (srv_log_file_size == 0) { - info << ((log_sys.log.format - & ~LOG_HEADER_FORMAT_ENCRYPTED) - != LOG_HEADER_FORMAT_10_4 - ? "Upgrading redo log: " - : "Downgrading redo log: "); + if (srv_log_file_size == 0 + || (log_sys.log.format & ~LOG_HEADER_FORMAT_ENCRYPTED) + != LOG_HEADER_FORMAT_10_4) { + info << "Upgrading redo log: "; } else if (n_files != srv_n_log_files || srv_log_file_size != srv_log_file_size_requested) { @@ -1888,7 +1784,7 @@ files_checked: ulint ibuf_root = btr_create( DICT_CLUSTERED | DICT_IBUF, fil_system.sys_space, - DICT_IBUF_ID_MIN, dict_ind_redundant, NULL, &mtr); + DICT_IBUF_ID_MIN, dict_ind_redundant, &mtr); mtr_commit(&mtr); @@ -1927,22 +1823,6 @@ files_checked: return(srv_init_abort(err)); } } else { - /* Invalidate the buffer pool to ensure that we reread - the page that we read above, during recovery. - Note that this is not as heavy weight as it seems. At - this point there will be only ONE page in the buf_LRU - and there must be no page in the buf_flush list. */ - buf_pool_invalidate(); - - /* Scan and locate truncate log files. Parsed located files - and add table to truncate information to central vector for - truncate fix-up action post recovery. */ - err = TruncateLogParser::scan_and_parse(srv_log_group_home_dir); - if (err != DB_SUCCESS) { - - return(srv_init_abort(DB_ERROR)); - } - /* We always try to do a recovery, even if the database had been shut down normally: this is the normal startup path */ @@ -2122,9 +2002,8 @@ files_checked: && srv_n_log_files_found == srv_n_log_files && log_sys.log.format == (srv_encrypt_log - ? LOG_HEADER_FORMAT_CURRENT - | LOG_HEADER_FORMAT_ENCRYPTED - : LOG_HEADER_FORMAT_CURRENT) + ? LOG_HEADER_FORMAT_ENC_10_4 + : LOG_HEADER_FORMAT_10_4) && log_sys.log.subformat == 2) { /* No need to add or remove encryption, upgrade, downgrade, or resize. */ @@ -2222,14 +2101,6 @@ files_checked: trx_rollback_recovered(false); } - /* Fix-up truncate of tables in the system tablespace - if server crashed while truncate was active. The non- - system tables are done after tablespace discovery. Do - this now because this procedure assumes that no pages - have changed since redo recovery. Tablespace discovery - can do updates to pages in the system tablespace.*/ - err = truncate_t::fixup_tables_in_system_tablespace(); - if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) { /* Open or Create SYS_TABLESPACES and SYS_DATAFILES so that tablespace names and other metadata can be @@ -2267,10 +2138,6 @@ files_checked: dict_check_tablespaces_and_store_max_id(validate); } - /* Fix-up truncate of table if server crashed while truncate - was active. */ - err = truncate_t::fixup_tables_in_non_system_tablespace(); - if (err != DB_SUCCESS) { return(srv_init_abort(err)); } diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index a4fa12708ac..b3c2d078551 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -174,7 +174,8 @@ void purge_sys_t::create() hdr_offset= 0; rw_lock_create(trx_purge_latch_key, &latch, SYNC_PURGE_LATCH); mutex_create(LATCH_ID_PURGE_SYS_PQ, &pq_mutex); - undo_trunc.create(); + truncate.current= NULL; + truncate.last= NULL; } /** Close the purge subsystem on shutdown. */ @@ -510,309 +511,22 @@ func_exit: goto loop; } -/** UNDO log truncate logger. Needed to track state of truncate during crash. -An auxiliary redo log file undo_<space_id>_trunc.log will created while the -truncate of the UNDO is in progress. This file is required during recovery -to complete the truncate. */ - -namespace undo { - /** Magic Number to indicate truncate action is complete. */ - static const ib_uint32_t s_magic = 76845412; - - /** Populate log file name based on space_id - @param[in] space_id id of the undo tablespace. - @return DB_SUCCESS or error code */ - static dberr_t populate_log_file_name( - ulint space_id, - char*& log_file_name) - { - static const char s_log_prefix[] = "undo_"; - static const char s_log_ext[] = "trunc.log"; - - ulint log_file_name_sz = strlen(srv_log_group_home_dir) - + (22 - 1 /* NUL */ - + sizeof s_log_prefix + sizeof s_log_ext); - - log_file_name = new (std::nothrow) char[log_file_name_sz]; - if (log_file_name == 0) { - return(DB_OUT_OF_MEMORY); - } - - memset(log_file_name, 0, log_file_name_sz); - - strcpy(log_file_name, srv_log_group_home_dir); - ulint log_file_name_len = strlen(log_file_name); - - if (log_file_name[log_file_name_len - 1] - != OS_PATH_SEPARATOR) { - - log_file_name[log_file_name_len] - = OS_PATH_SEPARATOR; - log_file_name_len = strlen(log_file_name); - } - - snprintf(log_file_name + log_file_name_len, - log_file_name_sz - log_file_name_len, - "%s" ULINTPF "_%s", s_log_prefix, - space_id, s_log_ext); - - return(DB_SUCCESS); - } - - /** Mark completion of undo truncate action by writing magic number to - the log file and then removing it from the disk. - If we are going to remove it from disk then why write magic number ? - This is to safeguard from unlink (file-system) anomalies that will keep - the link to the file even after unlink action is successfull and - ref-count = 0. - @param[in] space_id id of the undo tablespace to truncate.*/ - void done( - ulint space_id) - { - dberr_t err; - char* log_file_name; - - /* Step-1: Create the log file name using the pre-decided - prefix/suffix and table id of undo tablepsace to truncate. */ - err = populate_log_file_name(space_id, log_file_name); - if (err != DB_SUCCESS) { - return; - } - - /* Step-2: Open log file and write magic number to - indicate done phase. */ - bool ret; - os_file_t handle = - os_file_create_simple_no_error_handling( - innodb_log_file_key, log_file_name, - OS_FILE_OPEN, OS_FILE_READ_WRITE, - srv_read_only_mode, &ret); - - if (!ret) { - os_file_delete(innodb_log_file_key, log_file_name); - delete[] log_file_name; - return; - } - - ulint sz = srv_page_size; - void* buf = ut_zalloc_nokey(sz + srv_page_size); - if (buf == NULL) { - os_file_close(handle); - os_file_delete(innodb_log_file_key, log_file_name); - delete[] log_file_name; - return; - } - - byte* log_buf = static_cast<byte*>( - ut_align(buf, srv_page_size)); - - mach_write_to_4(log_buf, undo::s_magic); - - IORequest request(IORequest::WRITE); - - err = os_file_write( - request, log_file_name, handle, log_buf, 0, sz); - - ut_ad(err == DB_SUCCESS); - - os_file_flush(handle); - os_file_close(handle); - - ut_free(buf); - os_file_delete(innodb_log_file_key, log_file_name); - delete[] log_file_name; - } - - /** Check if TRUNCATE_DDL_LOG file exist. - @param[in] space_id id of the undo tablespace. - @return true if exist else false. */ - bool is_log_present( - ulint space_id) - { - dberr_t err; - char* log_file_name; - - /* Step-1: Populate log file name. */ - err = populate_log_file_name(space_id, log_file_name); - if (err != DB_SUCCESS) { - return(false); - } - - /* Step-2: Check for existence of the file. */ - bool exist; - os_file_type_t type; - os_file_status(log_file_name, &exist, &type); - - /* Step-3: If file exists, check it for presence of magic - number. If found, then delete the file and report file - doesn't exist as presence of magic number suggest that - truncate action was complete. */ - - if (exist) { - bool ret; - os_file_t handle = - os_file_create_simple_no_error_handling( - innodb_log_file_key, log_file_name, - OS_FILE_OPEN, OS_FILE_READ_WRITE, - srv_read_only_mode, &ret); - if (!ret) { - os_file_delete(innodb_log_file_key, - log_file_name); - delete[] log_file_name; - return(false); - } - - ulint sz = srv_page_size; - void* buf = ut_zalloc_nokey(sz + srv_page_size); - if (buf == NULL) { - os_file_close(handle); - os_file_delete(innodb_log_file_key, - log_file_name); - delete[] log_file_name; - return(false); - } - - byte* log_buf = static_cast<byte*>( - ut_align(buf, srv_page_size)); - - IORequest request(IORequest::READ); - - dberr_t err; - - err = os_file_read(request, handle, log_buf, 0, sz); - - os_file_close(handle); - - if (err != DB_SUCCESS) { - - ib::info() - << "Unable to read '" - << log_file_name << "' : " - << ut_strerr(err); - - os_file_delete( - innodb_log_file_key, log_file_name); - - ut_free(buf); - - delete[] log_file_name; - - return(false); - } - - ulint magic_no = mach_read_from_4(log_buf); - - ut_free(buf); - - if (magic_no == undo::s_magic) { - /* Found magic number. */ - os_file_delete(innodb_log_file_key, - log_file_name); - delete[] log_file_name; - return(false); - } - } - - delete[] log_file_name; - - return(exist); - } -}; - -/** Iterate over all the UNDO tablespaces and check if any of the UNDO -tablespace qualifies for TRUNCATE (size > threshold). -@param[in,out] undo_trunc undo truncate tracker */ -static -void -trx_purge_mark_undo_for_truncate( - undo::Truncate* undo_trunc) -{ - /* Step-1: If UNDO Tablespace - - already marked for truncate (OR) - - truncate disabled - return immediately else search for qualifying tablespace. */ - if (undo_trunc->is_marked() || !srv_undo_log_truncate) { - return; - } - - /* Step-2: Validation/Qualification checks - a. At-least 2 UNDO tablespaces so even if one UNDO tablespace - is being truncated server can continue to operate. - b. At-least 2 persistent UNDO logs (besides the default rseg-0) - b. At-least 1 UNDO tablespace size > threshold. */ - if (srv_undo_tablespaces_active < 2 || srv_undo_logs < 3) { - return; - } - - /* Avoid bias selection and so start the scan from immediate next - of last selected UNDO tablespace for truncate. */ - ulint space_id = undo_trunc->get_scan_start(); - - for (ulint i = 1; i <= srv_undo_tablespaces_active; i++) { - - if (fil_space_get_size(space_id) - > (srv_max_undo_log_size >> srv_page_size_shift)) { - /* Tablespace qualifies for truncate. */ - undo_trunc->mark(space_id); - undo::Truncate::add_space_to_trunc_list(space_id); - break; - } - - space_id = ((space_id + 1) % (srv_undo_tablespaces_active + 1)); - if (space_id == 0) { - /* Note: UNDO tablespace ids starts from 1. */ - ++space_id; - } - } - - /* Couldn't make any selection. */ - if (!undo_trunc->is_marked()) { - return; - } - - DBUG_LOG("undo", - "marking for truncate UNDO tablespace " - << undo_trunc->get_marked_space_id()); - - /* Step-3: Iterate over all the rsegs of selected UNDO tablespace - and mark them temporarily unavailable for allocation.*/ - for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) { - if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) { - ut_ad(rseg->is_persistent()); - if (rseg->space->id - == undo_trunc->get_marked_space_id()) { - - /* Once set this rseg will not be allocated - to new booting transaction but we will wait - for existing active transaction to finish. */ - rseg->skip_allocation = true; - undo_trunc->add_rseg_to_trunc(rseg); - } - } - } -} - -undo::undo_spaces_t undo::Truncate::s_spaces_to_truncate; - /** Cleanse purge queue to remove the rseg that reside in undo-tablespace marked for truncate. -@param[in,out] undo_trunc undo truncate tracker */ -static -void -trx_purge_cleanse_purge_queue( - undo::Truncate* undo_trunc) +@param[in] space undo tablespace being truncated */ +static void trx_purge_cleanse_purge_queue(const fil_space_t& space) { - mutex_enter(&purge_sys.pq_mutex); typedef std::vector<TrxUndoRsegs> purge_elem_list_t; purge_elem_list_t purge_elem_list; + mutex_enter(&purge_sys.pq_mutex); + /* Remove rseg instances that are in the purge queue before we start truncate of corresponding UNDO truncate. */ while (!purge_sys.purge_queue.empty()) { purge_elem_list.push_back(purge_sys.purge_queue.top()); purge_sys.purge_queue.pop(); } - ut_ad(purge_sys.purge_queue.empty()); for (purge_elem_list_t::iterator it = purge_elem_list.begin(); it != purge_elem_list.end(); @@ -821,9 +535,7 @@ trx_purge_cleanse_purge_queue( for (TrxUndoRsegs::iterator it2 = it->begin(); it2 != it->end(); ++it2) { - - if ((*it2)->space->id - == undo_trunc->get_marked_space_id()) { + if ((*it2)->space == &space) { it->erase(it2); break; } @@ -833,280 +545,285 @@ trx_purge_cleanse_purge_queue( purge_sys.purge_queue.push(*it); } } + mutex_exit(&purge_sys.pq_mutex); } -/** Iterate over selected UNDO tablespace and check if all the rsegs -that resides in the tablespace are free. -@param[in] limit truncate_limit -@param[in,out] undo_trunc undo truncate tracker */ -static -void -trx_purge_initiate_truncate( - const purge_sys_t::iterator& limit, - undo::Truncate* undo_trunc) +/** +Removes unnecessary history data from rollback segments. NOTE that when this +function is called, the caller must not have any latches on undo log pages! +*/ +static void trx_purge_truncate_history() { - /* Step-1: Early check to findout if any of the the UNDO tablespace - is marked for truncate. */ - if (!undo_trunc->is_marked()) { - /* No tablespace marked for truncate yet. */ - return; - } - - /* Step-2: Scan over each rseg and ensure that it doesn't hold any - active undo records. */ - bool all_free = true; - - for (ulint i = 0; i < undo_trunc->rsegs_size() && all_free; ++i) { - - trx_rseg_t* rseg = undo_trunc->get_ith_rseg(i); + ut_ad(purge_sys.head <= purge_sys.tail); + purge_sys_t::iterator& head = purge_sys.head.commit + ? purge_sys.head : purge_sys.tail; - mutex_enter(&rseg->mutex); + if (head.trx_no() >= purge_sys.view.low_limit_no()) { + /* This is sometimes necessary. TODO: find out why. */ + head.reset_trx_no(purge_sys.view.low_limit_no()); + head.undo_no = 0; + } - if (rseg->trx_ref_count > 0) { - /* This rseg is still being held by an active - transaction. */ - all_free = false; - mutex_exit(&rseg->mutex); - continue; + for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) { + if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) { + ut_ad(rseg->id == i); + trx_purge_truncate_rseg_history(*rseg, head); } + } - ut_ad(rseg->trx_ref_count == 0); - ut_ad(rseg->skip_allocation); - - ulint size_of_rsegs = rseg->curr_size; - - if (size_of_rsegs == 1) { - mutex_exit(&rseg->mutex); - continue; - } else { - - /* There could be cached undo segment. Check if records - in these segments can be purged. Normal purge history - will not touch these cached segment. */ - ulint cached_undo_size = 0; + if (srv_undo_tablespaces_active < 2) { + return; + } - for (trx_undo_t* undo = - UT_LIST_GET_FIRST(rseg->undo_cached); - undo != NULL && all_free; - undo = UT_LIST_GET_NEXT(undo_list, undo)) { + while (srv_undo_log_truncate && srv_undo_logs >= 3) { + if (!purge_sys.truncate.current) { + const ulint threshold = ulint(srv_max_undo_log_size + >> srv_page_size_shift); + for (ulint i = purge_sys.truncate.last + ? purge_sys.truncate.last->id + - srv_undo_space_id_start + : 0, j = i;; ) { + ulint space_id = srv_undo_space_id_start + i; + ut_ad(srv_is_undo_tablespace(space_id)); + + if (fil_space_get_size(space_id) + > threshold) { + purge_sys.truncate.current + = fil_space_get(space_id); + break; + } - if (limit.trx_no() < undo->trx_id) { - all_free = false; - } else { - cached_undo_size += undo->size; + ++i; + i %= srv_undo_tablespaces_active; + if (i == j) { + break; } } + } - ut_ad(size_of_rsegs >= (cached_undo_size + 1)); + if (!purge_sys.truncate.current) { + return; + } - if (size_of_rsegs > (cached_undo_size + 1)) { - /* There are pages besides cached pages that - still hold active data. */ - all_free = false; + const fil_space_t& space = *purge_sys.truncate.current; + /* Undo tablespace always are a single file. */ + ut_a(UT_LIST_GET_LEN(space.chain) == 1); + fil_node_t* file = UT_LIST_GET_FIRST(space.chain); + /* The undo tablespace files are never closed. */ + ut_ad(file->is_open()); + + DBUG_LOG("undo", "marking for truncate: " << file->name); + + for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) { + if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) { + ut_ad(rseg->is_persistent()); + if (rseg->space == &space) { + /* Once set, this rseg will + not be allocated to subsequent + transactions, but we will wait + for existing active + transactions to finish. */ + rseg->skip_allocation = true; + } } } - mutex_exit(&rseg->mutex); - } - - if (!all_free) { - /* rseg still holds active data.*/ - return; - } - - - /* Step-3: Start the actual truncate. - a. Remove rseg instance if added to purge queue before we - initiate truncate. - b. Execute actual truncate */ - - const ulint space_id = undo_trunc->get_marked_space_id(); - - ib::info() << "Truncating UNDO tablespace " << space_id; - - trx_purge_cleanse_purge_queue(undo_trunc); - - ut_a(srv_is_undo_tablespace(space_id)); - - fil_space_t* space = fil_space_get(space_id); + for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) { + trx_rseg_t* rseg = trx_sys.rseg_array[i]; + if (!rseg || rseg->space != &space) { + continue; + } + mutex_enter(&rseg->mutex); + ut_ad(rseg->skip_allocation); + if (rseg->trx_ref_count) { +not_free: + mutex_exit(&rseg->mutex); + return; + } - if (!space) { -not_found: - ib::error() << "Failed to find UNDO tablespace " << space_id; - return; - } + if (rseg->curr_size != 1) { + /* Check if all segments are + cached and safe to remove. */ + ulint cached = 0; + + for (trx_undo_t* undo = UT_LIST_GET_FIRST( + rseg->undo_cached); + undo; + undo = UT_LIST_GET_NEXT(undo_list, + undo)) { + if (head.trx_no() < undo->trx_id) { + goto not_free; + } else { + cached += undo->size; + } + } - /* Flush all to-be-discarded pages of the tablespace. - - During truncation, we do not want any writes to the - to-be-discarded area, because we must set the space->size - early in order to have deterministic page allocation. - - If a log checkpoint was completed at LSN earlier than our - mini-transaction commit and the server was killed, then - discarding the to-be-trimmed pages without flushing would - break crash recovery. So, we cannot avoid the write. */ - { - FlushObserver observer( - space, - UT_LIST_GET_FIRST(purge_sys.query->thrs)->graph->trx, - NULL); - buf_LRU_flush_or_remove_pages(space_id, &observer); - } + ut_ad(rseg->curr_size > cached); - log_free_check(); + if (rseg->curr_size > cached + 1) { + goto not_free; + } + } - /* Adjust the tablespace metadata. */ - space = fil_truncate_prepare(space_id); + mutex_exit(&rseg->mutex); + } - if (!space) { - goto not_found; - } + ib::info() << "Truncating " << file->name; + trx_purge_cleanse_purge_queue(space); + + /* Flush all to-be-discarded pages of the tablespace. + + During truncation, we do not want any writes to the + to-be-discarded area, because we must set the space.size + early in order to have deterministic page allocation. + + If a log checkpoint was completed at LSN earlier than our + mini-transaction commit and the server was killed, then + discarding the to-be-trimmed pages without flushing would + break crash recovery. So, we cannot avoid the write. */ + { + FlushObserver observer( + purge_sys.truncate.current, + UT_LIST_GET_FIRST(purge_sys.query->thrs) + ->graph->trx, + NULL); + buf_LRU_flush_or_remove_pages(space.id, &observer); + } - /* Undo tablespace always are a single file. */ - ut_a(UT_LIST_GET_LEN(space->chain) == 1); - fil_node_t* file = UT_LIST_GET_FIRST(space->chain); - /* The undo tablespace files are never closed. */ - ut_ad(file->is_open()); + log_free_check(); - /* Re-initialize tablespace, in a single mini-transaction. */ - mtr_t mtr; - const ulint size = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES; - mtr.start(); - mtr_x_lock(&space->latch, &mtr); - fil_truncate_log(space, size, &mtr); - fsp_header_init(space, size, &mtr); - mutex_enter(&fil_system.mutex); - space->size = file->size = size; - mutex_exit(&fil_system.mutex); + /* Adjust the tablespace metadata. */ + if (!fil_truncate_prepare(space.id)) { + ib::error() << "Failed to find UNDO tablespace " + << file->name; + return; + } - buf_block_t* sys_header = trx_sysf_get(&mtr); + /* Re-initialize tablespace, in a single mini-transaction. */ + mtr_t mtr; + const ulint size = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES; + mtr.start(); + mtr_x_lock(&purge_sys.truncate.current->latch, &mtr); + fil_truncate_log(purge_sys.truncate.current, size, &mtr); + fsp_header_init(purge_sys.truncate.current, size, &mtr); + mutex_enter(&fil_system.mutex); + purge_sys.truncate.current->size = file->size = size; + mutex_exit(&fil_system.mutex); + + buf_block_t* sys_header = trx_sysf_get(&mtr); + + for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) { + trx_rseg_t* rseg = trx_sys.rseg_array[i]; + if (!rseg || rseg->space != &space) { + continue; + } - for (ulint i = 0; i < undo_trunc->rsegs_size(); ++i) { - trx_rsegf_t* rseg_header; + ut_ad(rseg->is_persistent()); + ut_d(const ulint old_page = rseg->page_no); - trx_rseg_t* rseg = undo_trunc->get_ith_rseg(i); + rseg->page_no = trx_rseg_header_create( + purge_sys.truncate.current, + rseg->id, sys_header, &mtr); + ut_ad(old_page == rseg->page_no); - rseg->page_no = trx_rseg_header_create( - space, rseg->id, sys_header, &mtr); + trx_rsegf_t* rseg_header = trx_rsegf_get_new( + space.id, rseg->page_no, &mtr); - rseg_header = trx_rsegf_get_new( - space_id, rseg->page_no, &mtr); + /* Before re-initialization ensure that we + free the existing structure. There can't be + any active transactions. */ + ut_a(UT_LIST_GET_LEN(rseg->undo_list) == 0); + ut_a(UT_LIST_GET_LEN(rseg->old_insert_list) == 0); - /* Before re-initialization ensure that we free the existing - structure. There can't be any active transactions. */ - ut_a(UT_LIST_GET_LEN(rseg->undo_list) == 0); - ut_a(UT_LIST_GET_LEN(rseg->old_insert_list) == 0); + trx_undo_t* next_undo; - trx_undo_t* next_undo; + for (trx_undo_t* undo = UT_LIST_GET_FIRST( + rseg->undo_cached); + undo; undo = next_undo) { - for (trx_undo_t* undo = UT_LIST_GET_FIRST(rseg->undo_cached); - undo != NULL; - undo = next_undo) { + next_undo = UT_LIST_GET_NEXT(undo_list, undo); + UT_LIST_REMOVE(rseg->undo_cached, undo); + MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_CACHED); + ut_free(undo); + } - next_undo = UT_LIST_GET_NEXT(undo_list, undo); - UT_LIST_REMOVE(rseg->undo_cached, undo); - MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_CACHED); - ut_free(undo); + UT_LIST_INIT(rseg->undo_list, + &trx_undo_t::undo_list); + UT_LIST_INIT(rseg->undo_cached, + &trx_undo_t::undo_list); + UT_LIST_INIT(rseg->old_insert_list, + &trx_undo_t::undo_list); + + /* These were written by trx_rseg_header_create(). */ + ut_ad(!mach_read_from_4(rseg_header + + TRX_RSEG_FORMAT)); + ut_ad(!mach_read_from_4(rseg_header + + TRX_RSEG_HISTORY_SIZE)); + + /* Initialize the undo log lists according to + the rseg header */ + rseg->curr_size = 1; + rseg->trx_ref_count = 0; + rseg->last_page_no = FIL_NULL; + rseg->last_offset = 0; + rseg->last_commit = 0; + rseg->needs_purge = false; } - UT_LIST_INIT(rseg->undo_list, &trx_undo_t::undo_list); - UT_LIST_INIT(rseg->undo_cached, &trx_undo_t::undo_list); - UT_LIST_INIT(rseg->old_insert_list, &trx_undo_t::undo_list); - - /* These were written by trx_rseg_header_create(). */ - ut_ad(!mach_read_from_4(rseg_header + TRX_RSEG_FORMAT)); - ut_ad(!mach_read_from_4(rseg_header + TRX_RSEG_HISTORY_SIZE)); - - /* Initialize the undo log lists according to the rseg header */ - rseg->curr_size = 1; - rseg->trx_ref_count = 0; - rseg->last_page_no = FIL_NULL; - rseg->last_offset = 0; - rseg->last_commit = 0; - rseg->needs_purge = false; - } - - mtr.commit(); - /* Write-ahead the redo log record. */ - log_write_up_to(mtr.commit_lsn(), true); - - /* Trim the file size. */ - os_file_truncate(file->name, file->handle, - os_offset_t(size) << srv_page_size_shift, true); - - /* This is only executed by the srv_purge_coordinator_thread. */ - export_vars.innodb_undo_truncations++; - - /* TODO: PUNCH_HOLE the garbage (with write-ahead logging) */ - - mutex_enter(&fil_system.mutex); - ut_ad(space->stop_new_ops); - ut_ad(space->is_being_truncated); - space->stop_new_ops = false; - space->is_being_truncated = false; - mutex_exit(&fil_system.mutex); - - if (purge_sys.rseg != NULL - && purge_sys.rseg->last_page_no == FIL_NULL) { - /* If purge_sys.rseg is pointing to rseg that was recently - truncated then move to next rseg element. - Note: Ideally purge_sys.rseg should be NULL because purge - should complete processing of all the records but there is - purge_batch_size that can force the purge loop to exit before - all the records are purged and in this case purge_sys.rseg - could point to a valid rseg waiting for next purge cycle. */ - purge_sys.next_stored = false; - purge_sys.rseg = NULL; - } - - DBUG_EXECUTE_IF("ib_undo_trunc", - ib::info() << "ib_undo_trunc"; - log_write_up_to(LSN_MAX, true); - DBUG_SUICIDE();); - - /* Completed truncate. Now it is safe to re-use the tablespace. */ - for (ulint i = 0; i < undo_trunc->rsegs_size(); ++i) { - trx_rseg_t* rseg = undo_trunc->get_ith_rseg(i); - rseg->skip_allocation = false; - } - - ib::info() << "Truncated UNDO tablespace " << space_id; - - undo_trunc->reset(); - undo::Truncate::clear_trunc_list(); -} - -/** -Removes unnecessary history data from rollback segments. NOTE that when this -function is called, the caller must not have any latches on undo log pages! -*/ -static void trx_purge_truncate_history() -{ - ut_ad(purge_sys.head <= purge_sys.tail); - purge_sys_t::iterator& head = purge_sys.head.commit - ? purge_sys.head : purge_sys.tail; + mtr.commit(); + /* Write-ahead the redo log record. */ + log_write_up_to(mtr.commit_lsn(), true); + + /* Trim the file size. */ + os_file_truncate(file->name, file->handle, + os_offset_t(size) << srv_page_size_shift, + true); + + /* This is only executed by srv_purge_coordinator_thread. */ + export_vars.innodb_undo_truncations++; + + /* TODO: PUNCH_HOLE the garbage (with write-ahead logging) */ + mutex_enter(&fil_system.mutex); + ut_ad(&space == purge_sys.truncate.current); + ut_ad(space.stop_new_ops); + ut_ad(space.is_being_truncated); + purge_sys.truncate.current->stop_new_ops = false; + purge_sys.truncate.current->is_being_truncated = false; + mutex_exit(&fil_system.mutex); + + if (purge_sys.rseg != NULL + && purge_sys.rseg->last_page_no == FIL_NULL) { + /* If purge_sys.rseg is pointing to rseg that + was recently truncated then move to next rseg + element. Note: Ideally purge_sys.rseg should + be NULL because purge should complete + processing of all the records but there is + purge_batch_size that can force the purge loop + to exit before all the records are purged and + in this case purge_sys.rseg could point to a + valid rseg waiting for next purge cycle. */ + purge_sys.next_stored = false; + purge_sys.rseg = NULL; + } - if (head.trx_no() >= purge_sys.view.low_limit_no()) { - /* This is sometimes necessary. TODO: find out why. */ - head.reset_trx_no(purge_sys.view.low_limit_no()); - head.undo_no = 0; - } + DBUG_EXECUTE_IF("ib_undo_trunc", + ib::info() << "ib_undo_trunc"; + log_write_up_to(LSN_MAX, true); + DBUG_SUICIDE();); - for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) { - if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) { - ut_ad(rseg->id == i); - trx_purge_truncate_rseg_history(*rseg, head); + for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) { + if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) { + ut_ad(rseg->is_persistent()); + if (rseg->space == &space) { + rseg->skip_allocation = false; + } + } } - } - /* UNDO tablespace truncate. We will try to truncate as much as we - can (greedy approach). This will ensure when the server is idle we - try and truncate all the UNDO tablespaces. */ - for (ulint i = srv_undo_tablespaces_active; i--; ) { - trx_purge_mark_undo_for_truncate(&purge_sys.undo_trunc); - trx_purge_initiate_truncate(head, &purge_sys.undo_trunc); + ib::info() << "Truncated " << file->name; + purge_sys.truncate.last = purge_sys.truncate.current; + purge_sys.truncate.current = NULL; } } diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 56b8db7ec37..595c2a15fb3 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -39,9 +39,12 @@ Created 3/26/1996 Heikki Tuuri #include "row0row.h" #include "row0mysql.h" -/** The search tuple corresponding to TRX_UNDO_INSERT_METADATA */ +/** The search tuple corresponding to TRX_UNDO_INSERT_METADATA. */ const dtuple_t trx_undo_metadata = { - REC_INFO_METADATA, 0, 0, + /* This also works for REC_INFO_METADATA_ALTER, because the + delete-mark (REC_INFO_DELETED_FLAG) is ignored when searching. */ + REC_INFO_METADATA_ADD, + 0, 0, NULL, 0, NULL, UT_LIST_NODE_T(dtuple_t)() #ifdef UNIV_DEBUG @@ -505,7 +508,7 @@ trx_undo_page_report_insert( /* Store then the fields required to uniquely determine the record to be inserted in the clustered index */ if (UNIV_UNLIKELY(clust_entry->info_bits != 0)) { - ut_ad(clust_entry->info_bits == REC_INFO_METADATA); + ut_ad(clust_entry->is_metadata()); ut_ad(index->is_instant()); ut_ad(undo_block->frame[first_free + 2] == TRX_UNDO_INSERT_REC); @@ -919,9 +922,9 @@ trx_undo_page_report_modify( /* Store first some general parameters to the undo log */ if (!update) { - ut_ad(!rec_get_deleted_flag(rec, dict_table_is_comp(table))); + ut_ad(!rec_is_delete_marked(rec, dict_table_is_comp(table))); type_cmpl = TRX_UNDO_DEL_MARK_REC; - } else if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) { + } else if (rec_is_delete_marked(rec, dict_table_is_comp(table))) { /* In delete-marked records, DB_TRX_ID must always refer to an existing update_undo log record. */ ut_ad(row_get_rec_trx_id(rec, index, offsets)); @@ -950,9 +953,7 @@ trx_undo_page_report_modify( *ptr++ = (byte) rec_get_info_bits(rec, dict_table_is_comp(table)); /* Store the values of the system columns */ - field = rec_get_nth_field(rec, offsets, - dict_index_get_sys_col_pos( - index, DATA_TRX_ID), &flen); + field = rec_get_nth_field(rec, offsets, index->db_trx_id(), &flen); ut_ad(flen == DATA_TRX_ID_LEN); trx_id = trx_read_trx_id(field); @@ -966,9 +967,7 @@ trx_undo_page_report_modify( } ptr += mach_u64_write_compressed(ptr, trx_id); - field = rec_get_nth_field(rec, offsets, - dict_index_get_sys_col_pos( - index, DATA_ROLL_PTR), &flen); + field = rec_get_nth_field(rec, offsets, index->db_roll_ptr(), &flen); ut_ad(flen == DATA_ROLL_PTR_LEN); ut_ad(memcmp(field, field_ref_zero, DATA_ROLL_PTR_LEN)); @@ -1035,20 +1034,35 @@ trx_undo_page_report_modify( } } + i = 0; + + if (UNIV_UNLIKELY(update->is_alter_metadata())) { + ut_ad(update->n_fields >= 1); + ut_ad(!upd_fld_is_virtual_col(&update->fields[0])); + ut_ad(update->fields[0].field_no + == index->first_user_field()); + ut_ad(!dfield_is_ext(&update->fields[0].new_val)); + ut_ad(!dfield_is_null(&update->fields[0].new_val)); + /* The instant ADD COLUMN metadata record does not + contain the BLOB. Do not write anything for it. */ + i = !rec_is_alter_metadata(rec, *index); + n_updated -= i; + } + ptr += mach_write_compressed(ptr, n_updated); - for (i = 0; i < upd_get_n_fields(update); i++) { + for (; i < upd_get_n_fields(update); i++) { + if (trx_undo_left(undo_block, ptr) < 5) { + return 0; + } + upd_field_t* fld = upd_get_nth_field(update, i); bool is_virtual = upd_fld_is_virtual_col(fld); ulint max_v_log_len = 0; - ulint pos = fld->field_no; - - /* Write field number to undo log */ - if (trx_undo_left(undo_block, ptr) < 5) { - return(0); - } + ulint pos = fld->field_no; + const dict_col_t* col = NULL; if (is_virtual) { /* Skip the non-indexed column, during @@ -1061,13 +1075,13 @@ trx_undo_page_report_modify( /* add REC_MAX_N_FIELDS to mark this is a virtual col */ - pos += REC_MAX_N_FIELDS; - } + ptr += mach_write_compressed( + ptr, pos + REC_MAX_N_FIELDS); - ptr += mach_write_compressed(ptr, pos); + if (trx_undo_left(undo_block, ptr) < 15) { + return 0; + } - /* Save the old value of field */ - if (is_virtual) { ut_ad(fld->field_no < table->n_v_def); ptr = trx_undo_log_v_idx(undo_block, table, @@ -1092,28 +1106,78 @@ trx_undo_page_report_modify( flen = ut_min( flen, max_v_log_len); } + + goto store_len; + } + + if (UNIV_UNLIKELY(update->is_metadata())) { + ut_ad(pos >= index->first_user_field()); + ut_ad(rec_is_metadata(rec, *index)); + + if (rec_is_alter_metadata(rec, *index)) { + ut_ad(update->is_alter_metadata()); + + field = rec_offs_n_fields(offsets) + > pos + && !rec_offs_nth_default( + offsets, pos) + ? rec_get_nth_field( + rec, offsets, + pos, &flen) + : index->instant_field_value( + pos - 1, &flen); + + if (pos == index->first_user_field()) { + ut_ad(rec_offs_nth_extern( + offsets, pos)); + ut_ad(flen == FIELD_REF_SIZE); + goto write_field; + } + col = dict_index_get_nth_col(index, + pos - 1); + } else if (!update->is_alter_metadata()) { + goto get_field; + } else { + /* We are converting an ADD COLUMN + metadata record to an ALTER TABLE + metadata record, with BLOB. Subtract + the missing metadata BLOB field. */ + ut_ad(pos > index->first_user_field()); + --pos; + goto get_field; + } } else { +get_field: + col = dict_index_get_nth_col(index, pos); field = rec_get_nth_cfield( rec, index, offsets, pos, &flen); } +write_field: + /* Write field number to undo log */ + ptr += mach_write_compressed(ptr, pos); if (trx_undo_left(undo_block, ptr) < 15) { - return(0); + return 0; } - if (!is_virtual && rec_offs_nth_extern(offsets, pos)) { - const dict_col_t* col - = dict_index_get_nth_col(index, pos); - ulint prefix_len - = dict_max_field_len_store_undo( - table, col); + if (rec_offs_n_fields(offsets) > pos + && rec_offs_nth_extern(offsets, pos)) { + ut_ad(col || pos == index->first_user_field()); + ut_ad(col || update->is_alter_metadata()); + ut_ad(col + || rec_is_alter_metadata(rec, *index)); + ulint prefix_len = col + ? dict_max_field_len_store_undo( + table, col) + : 0; ut_ad(prefix_len + BTR_EXTERN_FIELD_REF_SIZE <= sizeof ext_buf); ptr = trx_undo_page_report_modify_ext( ptr, - col->ord_part + col + && col->ord_part && !ignore_prefix && flen < REC_ANTELOPE_MAX_INDEX_COL_LEN ? ext_buf : NULL, prefix_len, @@ -1122,6 +1186,7 @@ trx_undo_page_report_modify( *type_cmpl_ptr |= TRX_UNDO_UPD_EXTERN; } else { +store_len: ptr += mach_write_compressed(ptr, flen); } @@ -1270,6 +1335,8 @@ trx_undo_page_report_modify( table, col); ut_a(prefix_len < sizeof ext_buf); + const page_size_t& page_size + = dict_table_page_size(table); /* If there is a spatial index on it, log its MBR */ @@ -1278,9 +1345,7 @@ trx_undo_page_report_modify( col->mtype)); trx_undo_get_mbr_from_ext( - mbr, - dict_table_page_size( - table), + mbr, page_size, field, &flen); } @@ -1289,7 +1354,7 @@ trx_undo_page_report_modify( flen < REC_ANTELOPE_MAX_INDEX_COL_LEN && !ignore_prefix ? ext_buf : NULL, prefix_len, - dict_table_page_size(table), + page_size, &field, &flen, spatial_status); } else { @@ -1483,7 +1548,6 @@ trx_undo_update_rec_get_update( upd_t* update; ulint n_fields; byte* buf; - ulint i; bool first_v_col = true; bool is_undo_log = true; ulint n_skip_field = 0; @@ -1496,7 +1560,7 @@ trx_undo_update_rec_get_update( n_fields = 0; } - update = upd_create(n_fields + 2, heap); + *upd = update = upd_create(n_fields + 2, heap); update->info_bits = info_bits; @@ -1508,9 +1572,7 @@ trx_undo_update_rec_get_update( mach_write_to_6(buf, trx_id); - upd_field_set_field_no(upd_field, - dict_index_get_sys_col_pos(index, DATA_TRX_ID), - index); + upd_field_set_field_no(upd_field, index->db_trx_id(), index); dfield_set_data(&(upd_field->new_val), buf, DATA_TRX_ID_LEN); upd_field = upd_get_nth_field(update, n_fields + 1); @@ -1519,25 +1581,20 @@ trx_undo_update_rec_get_update( trx_write_roll_ptr(buf, roll_ptr); - upd_field_set_field_no( - upd_field, dict_index_get_sys_col_pos(index, DATA_ROLL_PTR), - index); + upd_field_set_field_no(upd_field, index->db_roll_ptr(), index); dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN); /* Store then the updated ordinary columns to the update vector */ - for (i = 0; i < n_fields; i++) { - + for (ulint i = 0; i < n_fields; i++) { const byte* field; ulint len; - ulint field_no; ulint orig_len; - bool is_virtual; upd_field = upd_get_nth_field(update, i); - field_no = mach_read_next_compressed(&ptr); + ulint field_no = mach_read_next_compressed(&ptr); - is_virtual = (field_no >= REC_MAX_N_FIELDS); + const bool is_virtual = (field_no >= REC_MAX_N_FIELDS); if (is_virtual) { /* If new version, we need to check index list to figure @@ -1560,15 +1617,63 @@ trx_undo_update_rec_get_update( } upd_field_set_v_field_no(upd_field, field_no, index); + } else if (UNIV_UNLIKELY((update->info_bits + & ~REC_INFO_DELETED_FLAG) + == REC_INFO_MIN_REC_FLAG)) { + ut_ad(type == TRX_UNDO_UPD_EXIST_REC); + const ulint uf = index->first_user_field(); + ut_ad(field_no >= uf); + + if (update->info_bits != REC_INFO_MIN_REC_FLAG) { + /* Generic instant ALTER TABLE */ + if (field_no == uf) { + upd_field->new_val.type + .metadata_blob_init(); + } else if (field_no >= index->n_fields) { + /* This is reachable during + purge if the table was emptied + and converted to the canonical + format on a later ALTER TABLE. + In this case, + row_purge_upd_exist_or_extern() + would only be interested in + freeing any BLOBs that were + updated, that is, the metadata + BLOB above. Other BLOBs in + the metadata record are never + updated; they are for the + initial DEFAULT values of the + instantly added columns, and + they will never change. + + Note: if the table becomes + empty during ROLLBACK or is + empty during subsequent ALTER + TABLE, and btr_page_empty() is + called to re-create the root + page without the metadata + record, in that case we should + only free the latest version + of BLOBs in the record, + which purge would never touch. */ + field_no = REC_MAX_N_FIELDS; + n_skip_field++; + } else { + dict_col_copy_type( + dict_index_get_nth_col( + index, field_no - 1), + &upd_field->new_val.type); + } + } else { + /* Instant ADD COLUMN...LAST */ + dict_col_copy_type( + dict_index_get_nth_col(index, + field_no), + &upd_field->new_val.type); + } + upd_field->field_no = field_no; } else if (field_no < index->n_fields) { upd_field_set_field_no(upd_field, field_no, index); - } else if (update->info_bits == REC_INFO_MIN_REC_FLAG - && index->is_instant()) { - /* This must be a rollback of a subsequent - instant ADD COLUMN operation. This will be - detected and handled by btr_cur_trim(). */ - upd_field->field_no = field_no; - upd_field->orig_len = 0; } else { ib::error() << "Trying to access update undo rec" " field " << field_no @@ -1601,6 +1706,12 @@ trx_undo_update_rec_get_update( dfield_set_ext(&upd_field->new_val); } + ut_ad(update->info_bits != (REC_INFO_DELETED_FLAG + | REC_INFO_MIN_REC_FLAG) + || field_no != index->first_user_field() + || (upd_field->new_val.ext + && upd_field->new_val.len == FIELD_REF_SIZE)); + if (is_virtual) { upd_field->old_v_val = static_cast<dfield_t*>( mem_heap_alloc( @@ -1618,31 +1729,23 @@ trx_undo_update_rec_get_update( } } - /* In rare scenario, we could have skipped virtual column (as they - are dropped. We will regenerate a update vector and skip them */ - if (n_skip_field > 0) { - ulint n = 0; - ut_ad(n_skip_field <= n_fields); - - upd_t* new_update = upd_create( - n_fields + 2 - n_skip_field, heap); + /* We may have to skip dropped indexed virtual columns. + Also, we may have to trim the update vector of a metadata record + if dict_index_t::clear_instant_alter() was invoked on the table + later, and the number of fields no longer matches. */ - for (i = 0; i < n_fields + 2; i++) { - upd_field = upd_get_nth_field(update, i); + if (n_skip_field) { + upd_field_t* d = upd_get_nth_field(update, 0); + const upd_field_t* const end = d + n_fields + 2; - if (upd_field->field_no == REC_MAX_N_FIELDS) { - continue; + for (const upd_field_t* s = d; s != end; s++) { + if (s->field_no != REC_MAX_N_FIELDS) { + *d++ = *s; } - - upd_field_t* new_upd_field - = upd_get_nth_field(new_update, n); - *new_upd_field = *upd_field; - n++; } - ut_ad(n == n_fields + 2 - n_skip_field); - *upd = new_update; - } else { - *upd = update; + + ut_ad(d + n_skip_field == end); + update->n_fields = d - upd_get_nth_field(update, 0); } return(const_cast<byte*>(ptr)); @@ -1701,8 +1804,11 @@ trx_undo_rec_get_partial_row( if (uf->old_v_val) { continue; } - ulint c = dict_index_get_nth_col(index, uf->field_no)->ind; - *dtuple_get_nth_field(*row, c) = uf->new_val; + const dict_col_t& c = *dict_index_get_nth_col(index, + uf->field_no); + if (!c.is_dropped()) { + *dtuple_get_nth_field(*row, c.ind) = uf->new_val; + } } end_ptr = ptr + mach_read_from_2(ptr); @@ -1713,7 +1819,6 @@ trx_undo_rec_get_partial_row( const byte* field; ulint field_no; const dict_col_t* col; - ulint col_no; ulint len; ulint orig_len; bool is_virtual; @@ -1741,15 +1846,18 @@ trx_undo_rec_get_partial_row( dict_v_col_t* vcol = dict_table_get_nth_v_col( index->table, field_no); col = &vcol->m_col; - col_no = dict_col_get_no(col); dfield = dtuple_get_nth_v_field(*row, vcol->v_pos); dict_col_copy_type( &vcol->m_col, dfield_get_type(dfield)); } else { col = dict_index_get_nth_col(index, field_no); - col_no = dict_col_get_no(col); - dfield = dtuple_get_nth_field(*row, col_no); + + if (col->is_dropped()) { + continue; + } + + dfield = dtuple_get_nth_field(*row, col->ind); ut_ad(dfield->type.mtype == DATA_MISSING || dict_col_type_assert_equal(col, &dfield->type)); @@ -1757,9 +1865,7 @@ trx_undo_rec_get_partial_row( || dfield->len == len || (len != UNIV_SQL_NULL && len >= UNIV_EXTERN_STORAGE_FIELD)); - dict_col_copy_type( - dict_table_get_nth_col(index->table, col_no), - dfield_get_type(dfield)); + dict_col_copy_type(col, dfield_get_type(dfield)); } dfield_set_data(dfield, field, len); diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 9e992d2f145..4b0684d1735 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -44,10 +44,6 @@ Created 3/26/1996 Heikki Tuuri #include "trx0trx.h" #include "trx0undo.h" -/** This many pages must be undone before a truncate is tried within -rollback */ -static const ulint TRX_ROLL_TRUNC_THRESHOLD = 1; - /** true if trx_rollback_all_recovered() thread is active */ bool trx_rollback_is_active; @@ -874,175 +870,6 @@ DECLARE_THREAD(trx_rollback_all_recovered)(void*) OS_THREAD_DUMMY_RETURN; } -/** Try to truncate the undo logs. -@param[in,out] trx transaction */ -static -void -trx_roll_try_truncate(trx_t* trx) -{ - trx->pages_undone = 0; - - undo_no_t undo_no = trx->undo_no; - - if (trx_undo_t* undo = trx->rsegs.m_redo.undo) { - ut_ad(undo->rseg == trx->rsegs.m_redo.rseg); - mutex_enter(&undo->rseg->mutex); - trx_undo_truncate_end(undo, undo_no, false); - mutex_exit(&undo->rseg->mutex); - } - - if (trx_undo_t* undo = trx->rsegs.m_noredo.undo) { - ut_ad(undo->rseg == trx->rsegs.m_noredo.rseg); - mutex_enter(&undo->rseg->mutex); - trx_undo_truncate_end(undo, undo_no, true); - mutex_exit(&undo->rseg->mutex); - } - -#ifdef WITH_WSREP_OUT - if (wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } -#endif /* WITH_WSREP */ -} - -/***********************************************************************//** -Pops the topmost undo log record in a single undo log and updates the info -about the topmost record in the undo log memory struct. -@return undo log record, the page s-latched */ -static -trx_undo_rec_t* -trx_roll_pop_top_rec( -/*=================*/ - trx_t* trx, /*!< in: transaction */ - trx_undo_t* undo, /*!< in: undo log */ - mtr_t* mtr) /*!< in: mtr */ -{ - page_t* undo_page = trx_undo_page_get_s_latched( - page_id_t(undo->rseg->space->id, undo->top_page_no), mtr); - - ulint offset = undo->top_offset; - - trx_undo_rec_t* prev_rec = trx_undo_get_prev_rec( - undo_page + offset, undo->hdr_page_no, undo->hdr_offset, - true, mtr); - - if (prev_rec == NULL) { - undo->top_undo_no = IB_ID_MAX; - ut_ad(undo->empty()); - } else { - page_t* prev_rec_page = page_align(prev_rec); - - if (prev_rec_page != undo_page) { - - trx->pages_undone++; - } - - undo->top_page_no = page_get_page_no(prev_rec_page); - undo->top_offset = ulint(prev_rec - prev_rec_page); - undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec); - ut_ad(!undo->empty()); - } - - return(undo_page + offset); -} - -/** Get the last undo log record of a transaction (for rollback). -@param[in,out] trx transaction -@param[out] roll_ptr DB_ROLL_PTR to the undo record -@param[in,out] heap memory heap for allocation -@return undo log record copied to heap -@retval NULL if none left or the roll_limit (savepoint) was reached */ -trx_undo_rec_t* -trx_roll_pop_top_rec_of_trx(trx_t* trx, roll_ptr_t* roll_ptr, mem_heap_t* heap) -{ - if (trx->pages_undone >= TRX_ROLL_TRUNC_THRESHOLD) { - trx_roll_try_truncate(trx); - } - - trx_undo_t* undo = NULL; - trx_undo_t* insert = trx->rsegs.m_redo.old_insert; - trx_undo_t* update = trx->rsegs.m_redo.undo; - trx_undo_t* temp = trx->rsegs.m_noredo.undo; - const undo_no_t limit = trx->roll_limit; - - ut_ad(!insert || !update || insert->empty() || update->empty() - || insert->top_undo_no != update->top_undo_no); - ut_ad(!insert || !temp || insert->empty() || temp->empty() - || insert->top_undo_no != temp->top_undo_no); - ut_ad(!update || !temp || update->empty() || temp->empty() - || update->top_undo_no != temp->top_undo_no); - - if (UNIV_LIKELY_NULL(insert) - && !insert->empty() && limit <= insert->top_undo_no) { - undo = insert; - } - - if (update && !update->empty() && update->top_undo_no >= limit) { - if (!undo) { - undo = update; - } else if (undo->top_undo_no < update->top_undo_no) { - undo = update; - } - } - - if (temp && !temp->empty() && temp->top_undo_no >= limit) { - if (!undo) { - undo = temp; - } else if (undo->top_undo_no < temp->top_undo_no) { - undo = temp; - } - } - - if (undo == NULL) { - trx_roll_try_truncate(trx); - /* Mark any ROLLBACK TO SAVEPOINT completed, so that - if the transaction object is committed and reused - later, we will default to a full ROLLBACK. */ - trx->roll_limit = 0; - trx->in_rollback = false; - return(NULL); - } - - ut_ad(!undo->empty()); - ut_ad(limit <= undo->top_undo_no); - - *roll_ptr = trx_undo_build_roll_ptr( - false, undo->rseg->id, undo->top_page_no, undo->top_offset); - - mtr_t mtr; - mtr.start(); - - trx_undo_rec_t* undo_rec = trx_roll_pop_top_rec(trx, undo, &mtr); - const undo_no_t undo_no = trx_undo_rec_get_undo_no(undo_rec); - switch (trx_undo_rec_get_type(undo_rec)) { - case TRX_UNDO_INSERT_METADATA: - /* This record type was introduced in MDEV-11369 - instant ADD COLUMN, which was implemented after - MDEV-12288 removed the insert_undo log. There is no - instant ADD COLUMN for temporary tables. Therefore, - this record can only be present in the main undo log. */ - ut_ad(undo == update); - /* fall through */ - case TRX_UNDO_RENAME_TABLE: - ut_ad(undo == insert || undo == update); - /* fall through */ - case TRX_UNDO_INSERT_REC: - ut_ad(undo == insert || undo == update || undo == temp); - *roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS; - break; - default: - ut_ad(undo == update || undo == temp); - break; - } - - trx->undo_no = undo_no; - - trx_undo_rec_t* undo_rec_copy = trx_undo_rec_copy(undo_rec, heap); - mtr.commit(); - - return(undo_rec_copy); -} - /****************************************************************//** Builds an undo 'query' graph for a transaction. The actual rollback is performed by executing this query graph like a query subprocedure call. diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 4a3102d225f..ef871be1552 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -252,12 +252,10 @@ void trx_rseg_format_upgrade(trx_rsegf_t* rseg_header, mtr_t* mtr) mlog_write_ulint(rseg_format, 0, MLOG_4BYTES, mtr); /* Clear also possible garbage at the end of the page. Old InnoDB versions did not initialize unused parts of pages. */ - byte* b = rseg_header + TRX_RSEG_MAX_TRX_ID + 8; - ulint len = srv_page_size - - (FIL_PAGE_DATA_END - + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8); - memset(b, 0, len); - mlog_log_string(b, len, mtr); + mlog_memset(TRX_RSEG_MAX_TRX_ID + 8 + rseg_header, + srv_page_size + - (FIL_PAGE_DATA_END + + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8), 0, mtr); } /** Create a rollback segment header. @@ -273,8 +271,6 @@ trx_rseg_header_create( buf_block_t* sys_header, mtr_t* mtr) { - ulint page_no; - trx_rsegf_t* rsegf; buf_block_t* block; ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); @@ -291,25 +287,17 @@ trx_rseg_header_create( buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW); - page_no = block->page.id.page_no(); - - /* Get the rollback segment file page */ - rsegf = trx_rsegf_get_new(space->id, page_no, mtr); - - mlog_write_ulint(rsegf + TRX_RSEG_FORMAT, 0, MLOG_4BYTES, mtr); + ut_ad(0 == mach_read_from_4(TRX_RSEG_FORMAT + TRX_RSEG + + block->frame)); + ut_ad(0 == mach_read_from_4(TRX_RSEG_HISTORY_SIZE + TRX_RSEG + + block->frame)); /* Initialize the history list */ - - mlog_write_ulint(rsegf + TRX_RSEG_HISTORY_SIZE, 0, MLOG_4BYTES, mtr); - flst_init(rsegf + TRX_RSEG_HISTORY, mtr); + flst_init(block, TRX_RSEG_HISTORY + TRX_RSEG, mtr); /* Reset the undo log slots */ - for (ulint i = 0; i < TRX_RSEG_N_SLOTS; i++) { - /* FIXME: This is generating a lot of redo log. - Why not just let it remain zero-initialized, - and adjust trx_rsegf_undo_find_free() and friends? */ - trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr); - } + mlog_memset(block, TRX_RSEG_UNDO_SLOTS + TRX_RSEG, + TRX_RSEG_N_SLOTS * 4, 0xff, mtr); if (sys_header) { /* Add the rollback segment info to the free slot in @@ -324,10 +312,10 @@ trx_rseg_header_create( + TRX_SYS_RSEG_PAGE_NO + rseg_id * TRX_SYS_RSEG_SLOT_SIZE + sys_header->frame, - page_no, MLOG_4BYTES, mtr); + block->page.id.page_no(), MLOG_4BYTES, mtr); } - return(page_no); + return block->page.id.page_no(); } /** Free a rollback segment in memory. */ diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index b46805eef4b..63966d280b2 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -190,10 +190,9 @@ trx_sysf_create( ut_a(ptr <= page + (srv_page_size - FIL_PAGE_DATA_END)); /* Initialize all of the page. This part used to be uninitialized. */ - memset(ptr, 0, srv_page_size - FIL_PAGE_DATA_END + size_t(page - ptr)); - - mlog_log_string(TRX_SYS + page, srv_page_size - FIL_PAGE_DATA_END - - TRX_SYS, mtr); + mlog_memset(block, ptr - page, + srv_page_size - FIL_PAGE_DATA_END + size_t(page - ptr), + 0, mtr); /* Create the first rollback segment in the SYSTEM tablespace */ slot_no = trx_sys_rseg_find_free(block); diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 07654be12ee..a0ceb44b8d1 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -210,6 +210,9 @@ struct TrxFactory { lock_trx_lock_list_init(&trx->lock.trx_locks); + UT_LIST_INIT(trx->lock.evicted_tables, + &dict_table_t::table_LRU); + UT_LIST_INIT( trx->trx_savepoints, &trx_named_savept_t::trx_savepoints); @@ -234,6 +237,7 @@ struct TrxFactory { } ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0); + ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0); UT_DELETE(trx->xid); ut_free(trx->detailed_error); @@ -386,6 +390,7 @@ trx_t *trx_create() ut_ad(trx->lock.n_rec_locks == 0); ut_ad(trx->lock.table_cached == 0); ut_ad(trx->lock.rec_cached == 0); + ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0); #ifdef WITH_WSREP trx->wsrep_event = NULL; @@ -1244,6 +1249,37 @@ trx_update_mod_tables_timestamp( trx->mod_tables.clear(); } +/** Evict a table definition due to the rollback of ALTER TABLE. +@param[in] table_id table identifier */ +void trx_t::evict_table(table_id_t table_id) +{ + ut_ad(in_rollback); + + dict_table_t* table = dict_table_open_on_id( + table_id, true, DICT_TABLE_OP_OPEN_ONLY_IF_CACHED); + if (!table) { + return; + } + + if (!table->release()) { + /* This must be a DDL operation that is being rolled + back in an active connection. */ + ut_a(table->get_ref_count() == 1); + ut_ad(!is_recovered); + ut_ad(mysql_thd); + return; + } + + /* This table should only be locked by this transaction, if at all. */ + ut_ad(UT_LIST_GET_LEN(table->locks) <= 1); + const bool locked = UT_LIST_GET_LEN(table->locks); + ut_ad(!locked || UT_LIST_GET_FIRST(table->locks)->trx == this); + dict_table_remove_from_cache(table, true, locked); + if (locked) { + UT_LIST_ADD_FIRST(lock.evicted_tables, table); + } +} + /****************************************************************//** Commits a transaction in memory. */ static @@ -1309,9 +1345,16 @@ trx_commit_in_memory( trx_update_mod_tables_timestamp(trx); MONITOR_INC(MONITOR_TRX_RW_COMMIT); } + + while (dict_table_t* table = UT_LIST_GET_FIRST( + trx->lock.evicted_tables)) { + UT_LIST_REMOVE(trx->lock.evicted_tables, table); + dict_mem_table_free(table); + } } ut_ad(!trx->rsegs.m_redo.undo); + ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0); if (trx_rseg_t* rseg = trx->rsegs.m_redo.rseg) { mutex_enter(&rseg->mutex); diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 61ba65ebc19..e084b0b67bf 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -888,54 +888,55 @@ trx_undo_free_last_page(trx_undo_t* undo, mtr_t* mtr) @param[in,out] undo undo log @param[in] limit all undo logs after this limit will be discarded @param[in] is_temp whether this is temporary undo log */ -void -trx_undo_truncate_end(trx_undo_t* undo, undo_no_t limit, bool is_temp) +void trx_undo_truncate_end(trx_undo_t& undo, undo_no_t limit, bool is_temp) { - ut_ad(mutex_own(&undo->rseg->mutex)); - ut_ad(is_temp == !undo->rseg->is_persistent()); + mtr_t mtr; + ut_ad(is_temp == !undo.rseg->is_persistent()); for (;;) { - mtr_t mtr; mtr.start(); if (is_temp) { mtr.set_log_mode(MTR_LOG_NO_REDO); } trx_undo_rec_t* trunc_here = NULL; + mutex_enter(&undo.rseg->mutex); page_t* undo_page = trx_undo_page_get( - page_id_t(undo->rseg->space->id, undo->last_page_no), + page_id_t(undo.rseg->space->id, undo.last_page_no), &mtr); trx_undo_rec_t* rec = trx_undo_page_get_last_rec( - undo_page, undo->hdr_page_no, undo->hdr_offset); + undo_page, undo.hdr_page_no, undo.hdr_offset); while (rec) { - if (trx_undo_rec_get_undo_no(rec) >= limit) { - /* Truncate at least this record off, maybe - more */ - trunc_here = rec; - } else { - goto function_exit; + if (trx_undo_rec_get_undo_no(rec) < limit) { + goto func_exit; } + /* Truncate at least this record off, maybe more */ + trunc_here = rec; rec = trx_undo_page_get_prev_rec(rec, - undo->hdr_page_no, - undo->hdr_offset); + undo.hdr_page_no, + undo.hdr_offset); } - if (undo->last_page_no == undo->hdr_page_no) { -function_exit: - if (trunc_here) { - mlog_write_ulint(undo_page + TRX_UNDO_PAGE_HDR - + TRX_UNDO_PAGE_FREE, - ulint(trunc_here - undo_page), - MLOG_2BYTES, &mtr); - } - + if (undo.last_page_no != undo.hdr_page_no) { + trx_undo_free_last_page(&undo, &mtr); + mutex_exit(&undo.rseg->mutex); mtr.commit(); - return; + continue; + } + +func_exit: + mutex_exit(&undo.rseg->mutex); + + if (trunc_here) { + mlog_write_ulint(undo_page + TRX_UNDO_PAGE_HDR + + TRX_UNDO_PAGE_FREE, + ulint(trunc_here - undo_page), + MLOG_2BYTES, &mtr); } - trx_undo_free_last_page(undo, &mtr); mtr.commit(); + return; } } diff --git a/storage/innobase/ut/ut0crc32.cc b/storage/innobase/ut/ut0crc32.cc index 0b1c1b3991a..3eef9329b57 100644 --- a/storage/innobase/ut/ut0crc32.cc +++ b/storage/innobase/ut/ut0crc32.cc @@ -469,34 +469,6 @@ ut_crc32_64_sw( *len -= 8; } -#ifdef INNODB_BUG_ENDIAN_CRC32 -/** Calculate CRC32 over 64-bit byte string using a software implementation. -The byte string is converted to a 64-bit integer using big endian byte order. -@param[in,out] crc crc32 checksum so far when this function is called, -when the function ends it will contain the new checksum -@param[in,out] data data to be checksummed, the pointer will be advanced -with 8 bytes -@param[in,out] len remaining bytes, it will be decremented with 8 */ -inline -void -ut_crc32_64_legacy_big_endian_sw( - uint32_t* crc, - const byte** data, - ulint* len) -{ - uint64_t data_int = *reinterpret_cast<const uint64_t*>(*data); - -#ifndef WORDS_BIGENDIAN - data_int = ut_crc32_swap_byteorder(data_int); -#endif /* WORDS_BIGENDIAN */ - - *crc = ut_crc32_64_low_sw(*crc, data_int); - - *data += 8; - *len -= 8; -} -#endif /* INNODB_BUG_ENDIAN_CRC32 */ - /** Calculates CRC32 in software, without using CPU instructions. @param[in] buf data over which to calculate CRC32 @param[in] len data length @@ -547,57 +519,6 @@ ut_crc32_sw( return(~crc); } -#ifdef INNODB_BUG_ENDIAN_CRC32 -/** Calculates CRC32 in software, without using CPU instructions. -This function uses big endian byte ordering when converting byte sequence to -integers. -@param[in] buf data over which to calculate CRC32 -@param[in] len data length -@return CRC-32C (polynomial 0x11EDC6F41) */ -uint32_t ut_crc32_legacy_big_endian(const byte* buf, ulint len) -{ - uint32_t crc = 0xFFFFFFFFU; - - ut_a(ut_crc32_slice8_table_initialized); - - /* Calculate byte-by-byte up to an 8-byte aligned address. After - this consume the input 8-bytes at a time. */ - while (len > 0 && (reinterpret_cast<uintptr_t>(buf) & 7) != 0) { - ut_crc32_8_sw(&crc, &buf, &len); - } - - while (len >= 128) { - /* This call is repeated 16 times. 16 * 8 = 128. */ - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - } - - while (len >= 8) { - ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len); - } - - while (len > 0) { - ut_crc32_8_sw(&crc, &buf, &len); - } - - return(~crc); -} -#endif /* INNODB_BUG_ENDIAN_CRC32 */ - /********************************************************************//** Initializes the data structures used by ut_crc32*(). Does not do any allocations, would not hurt if called twice, but would be pointless. */ @@ -637,9 +558,6 @@ ut_crc32_init() if (features_ecx & 1 << 20) { ut_crc32 = ut_crc32_hw; -#ifdef INNODB_BUG_ENDIAN_CRC32 - ut_crc32_legacy_big_endian = ut_crc32_legacy_big_endian_hw; -#endif /* INNODB_BUG_ENDIAN_CRC32 */ ut_crc32_implementation = "Using SSE2 crc32 instructions"; } #endif diff --git a/storage/innobase/ut/ut0new.cc b/storage/innobase/ut/ut0new.cc index 14f2748218c..cdba09974ad 100644 --- a/storage/innobase/ut/ut0new.cc +++ b/storage/innobase/ut/ut0new.cc @@ -148,7 +148,6 @@ ut_new_boot() "row0merge", "row0mysql", "row0sel", - "row0trunc", "srv0conc", "srv0srv", "srv0start", diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 39fb037aa28..adda0b960c9 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -589,8 +589,6 @@ ut_strerr( return("Tablespace already exists"); case DB_TABLESPACE_DELETED: return("Tablespace deleted or being deleted"); - case DB_TABLESPACE_TRUNCATED: - return("Tablespace was truncated"); case DB_TABLESPACE_NOT_FOUND: return("Tablespace not found"); case DB_LOCK_TABLE_FULL: diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt index b8e3350ca76..6ed370653d5 100644 --- a/storage/maria/CMakeLists.txt +++ b/storage/maria/CMakeLists.txt @@ -47,7 +47,7 @@ SET(ARIA_SOURCES ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c ma_checkpoint.c ma_recovery.c ma_commit.c ma_pagecrc.c ha_maria.h maria_def.h ma_recovery_util.c ma_servicethread.c ma_norec.c - ma_crypt.c + ma_crypt.c ma_backup.c ) IF(APPLE) @@ -56,7 +56,8 @@ IF(APPLE) ENDIF() MYSQL_ADD_PLUGIN(aria ${ARIA_SOURCES} - STORAGE_ENGINE STATIC_ONLY DEFAULT + STORAGE_ENGINE + MANDATORY RECOMPILE_FOR_EMBEDDED) IF(NOT WITH_ARIA_STORAGE_ENGINE) @@ -97,7 +98,12 @@ IF(WITH_UNIT_TESTS) ADD_EXECUTABLE(ma_sp_test ma_sp_test.c) TARGET_LINK_LIBRARIES(ma_sp_test aria) + + ADD_EXECUTABLE(test_ma_backup test_ma_backup.c) + TARGET_LINK_LIBRARIES(test_ma_backup aria) + ADD_SUBDIRECTORY(unittest) + ENDIF() IF (MSVC) diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 10ec7ad4d67..30f8724aebd 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -387,6 +387,10 @@ static void init_aria_psi_keys(void) #define init_aria_psi_keys() /* no-op */ #endif /* HAVE_PSI_INTERFACE */ +const char *MA_CHECK_INFO= "info"; +const char *MA_CHECK_WARNING= "warning"; +const char *MA_CHECK_ERROR= "error"; + /***************************************************************************** ** MARIA tables *****************************************************************************/ @@ -399,6 +403,20 @@ static handler *maria_create_handler(handlerton *hton, } +static void _ma_check_print(HA_CHECK *param, const char* msg_type, + const char *msgbuf) +{ + if (msg_type == MA_CHECK_INFO) + sql_print_information("%s.%s: %s", param->db_name, param->table_name, + msgbuf); + else if (msg_type == MA_CHECK_WARNING) + sql_print_warning("%s.%s: %s", param->db_name, param->table_name, + msgbuf); + else + sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf); +} + + // collect errors printed by maria_check routines static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type, @@ -420,16 +438,21 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type, if (!thd->vio_ok()) { - sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf); + _ma_check_print(param, msg_type, msgbuf); return; } if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR | T_AUTO_REPAIR)) { - my_message(ER_NOT_KEYFILE, msgbuf, MYF(MY_WME)); + myf flag= 0; + if (msg_type == MA_CHECK_INFO) + flag= ME_NOTE; + else if (msg_type == MA_CHECK_WARNING) + flag= ME_WARNING; + my_message(ER_NOT_KEYFILE, msgbuf, MYF(flag)); if (thd->variables.log_warnings > 2) - sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf); + _ma_check_print(param, msg_type, msgbuf); return; } length= (uint) (strxmov(name, param->db_name, ".", param->table_name, @@ -451,7 +474,7 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type, sql_print_error("Failed on my_net_write, writing to stderr instead: %s.%s: %s\n", param->db_name, param->table_name, msgbuf); else if (thd->variables.log_warnings > 2) - sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf); + _ma_check_print(param, msg_type, msgbuf); return; } @@ -879,7 +902,7 @@ void _ma_check_print_error(HA_CHECK *param, const char *fmt, ...) if (param->testflag & T_SUPPRESS_ERR_HANDLING) DBUG_VOID_RETURN; va_start(args, fmt); - _ma_check_print_msg(param, "error", fmt, args); + _ma_check_print_msg(param, MA_CHECK_ERROR, fmt, args); va_end(args); DBUG_VOID_RETURN; } @@ -890,7 +913,7 @@ void _ma_check_print_info(HA_CHECK *param, const char *fmt, ...) va_list args; DBUG_ENTER("_ma_check_print_info"); va_start(args, fmt); - _ma_check_print_msg(param, "info", fmt, args); + _ma_check_print_msg(param, MA_CHECK_INFO, fmt, args); va_end(args); DBUG_VOID_RETURN; } @@ -903,7 +926,7 @@ void _ma_check_print_warning(HA_CHECK *param, const char *fmt, ...) param->warning_printed= 1; param->out_flag |= O_DATA_LOST; va_start(args, fmt); - _ma_check_print_msg(param, "warning", fmt, args); + _ma_check_print_msg(param, MA_CHECK_WARNING, fmt, args); va_end(args); DBUG_VOID_RETURN; } @@ -1006,6 +1029,8 @@ handler *ha_maria::clone(const char *name, MEM_ROOT *mem_root) new_handler->file->state= file->state; /* maria_create_trn_for_mysql() is never called for clone() tables */ new_handler->file->trn= file->trn; + DBUG_ASSERT(new_handler->file->trn_prev == 0 && + new_handler->file->trn_next == 0); } return new_handler; } @@ -1236,6 +1261,14 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked) int_table_flags |= HA_HAS_NEW_CHECKSUM; /* + We can only do online backup on transactional tables with checksum. + Checksums are needed to avoid half writes. + */ + if (file->s->options & HA_OPTION_PAGE_CHECKSUM && + file->s->base.born_transactional) + int_table_flags |= HA_CAN_ONLINE_BACKUPS; + + /* For static size rows, tell MariaDB that we will access all bytes in the record when writing it. This signals MariaDB to initalize the full row to ensure we don't get any errors from valgrind and @@ -1271,6 +1304,8 @@ int ha_maria::close(void) MARIA_HA *tmp= file; if (!tmp) return 0; + DBUG_ASSERT(file->trn == 0 || file->trn == &dummy_transaction_object); + DBUG_ASSERT(file->trn_next == 0 && file->trn_prev == 0); file= 0; return maria_close(tmp); } @@ -1386,6 +1421,16 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) mysql_mutex_unlock(&share->intern_lock); info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE | HA_STATUS_CONST); + + /* + Write a 'table is ok' message to error log if table is ok and + we have written to error log that table was getting checked + */ + if (!error && !(table->db_stat & HA_READ_ONLY) && + !maria_is_crashed(file) && thd->error_printed_to_log && + (param->warning_printed || param->error_printed || + param->note_printed)) + _ma_check_print_info(param, "Table is fixed"); } } else if (!maria_is_crashed(file) && !thd->killed) @@ -1396,7 +1441,10 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) /* Reset trn, that may have been set by repair */ if (old_trn && old_trn != file->trn) + { + DBUG_ASSERT(old_trn->used_instances == 0); _ma_set_trn_for_table(file, old_trn); + } thd_proc_info(thd, old_proc_info); thd_progress_end(thd); return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK; @@ -2615,14 +2663,20 @@ int ha_maria::extra(enum ha_extra_function operation) operation == HA_EXTRA_PREPARE_FOR_FORCED_CLOSE)) { THD *thd= table->in_use; - TRN *trn= THD_TRN; - _ma_set_tmp_trn_for_table(file, trn); + file->trn= THD_TRN; } DBUG_ASSERT(file->s->base.born_transactional || file->trn == 0 || file->trn == &dummy_transaction_object); tmp= maria_extra(file, operation, 0); - file->trn= old_trn; // Reset trn if was used + /* + Restore trn if it was changed above. + Note that table could be removed from trn->used_tables and + trn->used_instances if trn was set and some of the above operations + was used. This is ok as the table should not be part of any transaction + after this and thus doesn't need to be part of any of the above lists. + */ + file->trn= old_trn; return tmp; } @@ -2858,9 +2912,12 @@ static void reset_thd_trn(THD *thd, MARIA_HA *first_table) { DBUG_ENTER("reset_thd_trn"); THD_TRN= NULL; - for (MARIA_HA *table= first_table; table ; - table= table->trn_next) + MARIA_HA *next; + for (MARIA_HA *table= first_table; table ; table= next) + { + next= table->trn_next; _ma_reset_trn_for_table(table); + } DBUG_VOID_RETURN; } @@ -2907,9 +2964,11 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn) DBUG_RETURN(0); } + /* Prepare to move used_instances and locked tables to new TRN object */ locked_tables= trnman_has_locked_tables(trn); + trnman_reset_locked_tables(trn, 0); + relink_trn_used_instances(&used_tables, trn); - used_tables= (MARIA_HA*) trn->used_instances; error= 0; if (unlikely(ma_commit(trn))) error= 1; @@ -3334,6 +3393,8 @@ static int maria_commit(handlerton *hton __attribute__ ((unused)), { TRN *trn= THD_TRN; DBUG_ENTER("maria_commit"); + + DBUG_ASSERT(trnman_has_locked_tables(trn) == 0); trnman_reset_locked_tables(trn, 0); trnman_set_flags(trn, trnman_get_flags(trn) & ~TRN_STATE_INFO_LOGGED); @@ -3351,9 +3412,12 @@ static int maria_rollback(handlerton *hton __attribute__ ((unused)), { TRN *trn= THD_TRN; DBUG_ENTER("maria_rollback"); + + DBUG_ASSERT(trnman_has_locked_tables(trn) == 0); trnman_reset_locked_tables(trn, 0); /* statement or transaction ? */ - if ((thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && !all) + if ((thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && + !all) { trnman_rollback_statement(trn); DBUG_RETURN(0); // end of statement @@ -3387,6 +3451,21 @@ int maria_checkpoint_state(handlerton *hton, bool disabled) } +/* + Handle backup calls +*/ + +void maria_prepare_for_backup() +{ + translog_disable_purge(); +} + +void maria_end_backup() +{ + translog_enable_purge(); +} + + #define SHOW_MSG_LEN (FN_REFLEN + 20) /** @@ -3509,7 +3588,7 @@ static int mark_recovery_start(const char* log_dir) int res; DBUG_ENTER("mark_recovery_start"); if (!(maria_recover_options & HA_RECOVER_ANY)) - ma_message_no_user(ME_JUST_WARNING, "Please consider using option" + ma_message_no_user(ME_WARNING, "Please consider using option" " --aria-recover-options[=...] to automatically check and" " repair tables when logs are removed by option" " --aria-force-start-after-recovery-failures=#"); @@ -3527,7 +3606,7 @@ static int mark_recovery_start(const char* log_dir) " recovery from logs", (res ? "failed to remove some" : "removed all"), recovery_failures); - ma_message_no_user((res ? 0 : ME_JUST_WARNING), msg); + ma_message_no_user((res ? 0 : ME_WARNING), msg); } else res= ma_control_file_write_and_force(last_checkpoint_lsn, last_logno, @@ -3587,6 +3666,9 @@ static int ha_maria_init(void *p) #endif maria_hton->flush_logs= maria_flush_logs; maria_hton->show_status= maria_show_status; + maria_hton->prepare_for_backup= maria_prepare_for_backup; + maria_hton->end_backup= maria_end_backup; + /* TODO: decide if we support Maria being used for log tables */ maria_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES; bzero(maria_log_pagecache, sizeof(*maria_log_pagecache)); @@ -3988,8 +4070,8 @@ maria_declare_plugin(aria) MYSQL_STORAGE_ENGINE_PLUGIN, &maria_storage_engine, "Aria", - "Monty Program Ab", - "Crash-safe tables with MyISAM heritage", + "MariaDB Corporation Ab", + "Crash-safe tables with MyISAM heritage. Used for internal temporary tables and privilege tables", PLUGIN_LICENSE_GPL, ha_maria_init, /* Plugin Init */ NULL, /* Plugin Deinit */ diff --git a/storage/maria/ma_backup.c b/storage/maria/ma_backup.c new file mode 100644 index 00000000000..8f20209c48a --- /dev/null +++ b/storage/maria/ma_backup.c @@ -0,0 +1,281 @@ +/* Copyright (C) 2018 MariaDB corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +/* Code for doing backups of Aria tables */ + +#include "maria_def.h" +#include "ma_blockrec.h" /* PAGE_SUFFIX_SIZE */ +#include "ma_checkpoint.h" +#include <aria_backup.h> + +static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base); + +/** + @brief Get capabilites for an Aria table + + @param kfile key file (.MAI) + @param cap Capabilities are stored here + + @return 0 ok + @return X errno +*/ + +int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap) +{ + MARIA_SHARE share; + int error= 0; + uint head_length= sizeof(share.state.header), base_pos; + uint aligned_bit_blocks; + size_t info_length; + uchar *disc_cache; + DBUG_ENTER("aria_get_capabilities"); + + bzero(cap, sizeof(*cap)); + if (my_pread(kfile,share.state.header.file_version, head_length, 0, + MYF(MY_NABP))) + DBUG_RETURN(HA_ERR_NOT_A_TABLE); + + if (memcmp(share.state.header.file_version, maria_file_magic, 4)) + DBUG_RETURN(HA_ERR_NOT_A_TABLE); + + share.options= mi_uint2korr(share.state.header.options); + + info_length= mi_uint2korr(share.state.header.header_length); + base_pos= mi_uint2korr(share.state.header.base_pos); + + /* + Allocate space for header information and for data that is too + big to keep on stack + */ + if (!(disc_cache= my_malloc(info_length, MYF(MY_WME)))) + DBUG_RETURN(ENOMEM); + + if (my_pread(kfile, disc_cache, info_length, 0L, MYF(MY_NABP))) + { + error= my_errno; + goto err; + } + _ma_base_info_read(disc_cache + base_pos, &share.base); + cap->transactional= share.base.born_transactional; + cap->checksum= MY_TEST(share.options & HA_OPTION_PAGE_CHECKSUM); + cap->online_backup_safe= cap->transactional && cap->checksum; + cap->header_size= share.base.keystart; + cap->keypage_header= ((share.base.born_transactional ? + LSN_STORE_SIZE + TRANSID_SIZE : + 0) + KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE + + KEYPAGE_USED_SIZE); + cap->block_size= share.base.block_size; + + if (share.state.header.data_file_type == BLOCK_RECORD) + { + /* Calulate how man pages the row bitmap covers. From _ma_bitmap_init() */ + aligned_bit_blocks= (cap->block_size - PAGE_SUFFIX_SIZE) / 6; + /* + In each 6 bytes, we have 6*8/3 = 16 pages covered + The +1 is to add the bitmap page, as this doesn't have to be covered + */ + cap->bitmap_pages_covered= aligned_bit_blocks * 16 + 1; + } + + /* Do a check that that we got things right */ + if (share.state.header.data_file_type != BLOCK_RECORD && + cap->online_backup_safe) + error= HA_ERR_NOT_A_TABLE; + +err: + my_free(disc_cache); + DBUG_RETURN(error); +} /* maria_get_capabilities */ + + +/* + This is a copy of my_base_info_read from ma_open(). + The base information will never change (something may be added + last, but not relevant for maria_get_capabilities), so it's safe to + copy it here. + + The copy is done to avoid linking in the fill Aria library just + because maria_backup uses maria_get_capabilities() +*/ + + +static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base) +{ + bmove(base->uuid, ptr, MY_UUID_SIZE); ptr+= MY_UUID_SIZE; + base->keystart= mi_sizekorr(ptr); ptr+= 8; + base->max_data_file_length= mi_sizekorr(ptr); ptr+= 8; + base->max_key_file_length= mi_sizekorr(ptr); ptr+= 8; + base->records= (ha_rows) mi_sizekorr(ptr); ptr+= 8; + base->reloc= (ha_rows) mi_sizekorr(ptr); ptr+= 8; + base->mean_row_length= mi_uint4korr(ptr); ptr+= 4; + base->reclength= mi_uint4korr(ptr); ptr+= 4; + base->pack_reclength= mi_uint4korr(ptr); ptr+= 4; + base->min_pack_length= mi_uint4korr(ptr); ptr+= 4; + base->max_pack_length= mi_uint4korr(ptr); ptr+= 4; + base->min_block_length= mi_uint4korr(ptr); ptr+= 4; + base->fields= mi_uint2korr(ptr); ptr+= 2; + base->fixed_not_null_fields= mi_uint2korr(ptr); ptr+= 2; + base->fixed_not_null_fields_length= mi_uint2korr(ptr);ptr+= 2; + base->max_field_lengths= mi_uint2korr(ptr); ptr+= 2; + base->pack_fields= mi_uint2korr(ptr); ptr+= 2; + base->extra_options= mi_uint2korr(ptr); ptr+= 2; + base->null_bytes= mi_uint2korr(ptr); ptr+= 2; + base->original_null_bytes= mi_uint2korr(ptr); ptr+= 2; + base->field_offsets= mi_uint2korr(ptr); ptr+= 2; + base->language= mi_uint2korr(ptr); ptr+= 2; + base->block_size= mi_uint2korr(ptr); ptr+= 2; + + base->rec_reflength= *ptr++; + base->key_reflength= *ptr++; + base->keys= *ptr++; + base->auto_key= *ptr++; + base->born_transactional= *ptr++; + ptr++; + base->pack_bytes= mi_uint2korr(ptr); ptr+= 2; + base->blobs= mi_uint2korr(ptr); ptr+= 2; + base->max_key_block_length= mi_uint2korr(ptr); ptr+= 2; + base->max_key_length= mi_uint2korr(ptr); ptr+= 2; + base->extra_alloc_bytes= mi_uint2korr(ptr); ptr+= 2; + base->extra_alloc_procent= *ptr++; + ptr+= 16; + return ptr; +} + + +/** + @brief Copy an index block with re-read if checksum doesn't match + + @param dfile data file (.MAD) + @param cap aria capabilities from aria_get_capabilities + @param block block number to read (0, 1, 2, 3...) + @param buffer read data to this buffer + @param bytes_read number of bytes actually read (in case of end of file) + + @return 0 ok + @return HA_ERR_END_OF_FILE ; End of file + @return # error number +*/ + +#define MAX_RETRY 10 + +int aria_read_index(File kfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block, + uchar *buffer) +{ + MARIA_SHARE share; + int retry= 0; + DBUG_ENTER("aria_read_index"); + + share.keypage_header= cap->keypage_header; + share.block_size= cap->block_size; + do + { + int error; + size_t length; + if ((length= my_pread(kfile, buffer, cap->block_size, + block * cap->block_size, MYF(0))) != cap->block_size) + { + if (length == 0) + DBUG_RETURN(HA_ERR_END_OF_FILE); + if (length == (size_t) -1) + DBUG_RETURN(my_errno ? my_errno : -1); + /* Assume we got a half read; Do a re-read */ + } + /* If not transactional or key file header, there are no checksums */ + if (!cap->online_backup_safe || + block < cap->header_size/ cap->block_size) + DBUG_RETURN(length == cap->block_size ? 0 : HA_ERR_CRASHED); + + if (length == cap->block_size) + { + length= _ma_get_page_used(&share, buffer); + if (length > cap->block_size - CRC_SIZE) + DBUG_RETURN(HA_ERR_CRASHED); + error= maria_page_crc_check(buffer, block, &share, + MARIA_NO_CRC_NORMAL_PAGE, + (int) length); + if (error != HA_ERR_WRONG_CRC) + DBUG_RETURN(error); + } + my_sleep(100000); /* Sleep 0.1 seconds */ + } while (retry < MAX_RETRY); + DBUG_RETURN(HA_ERR_WRONG_CRC); +} + + +/** + @brief Copy a data block with re-read if checksum doesn't match + + @param dfile data file (.MAD) + @param cap aria capabilities from aria_get_capabilities + @param block block number to read (0, 1, 2, 3...) + @param buffer read data to this buffer + @param bytes_read number of bytes actually read (in case of end of file) + + @return 0 ok + @return HA_ERR_END_OF_FILE ; End of file + @return # error number +*/ + +int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block, + uchar *buffer, size_t *bytes_read) +{ + MARIA_SHARE share; + int retry= 0; + DBUG_ENTER("aria_read_data"); + + share.keypage_header= cap->keypage_header; + share.block_size= cap->block_size; + + if (!cap->online_backup_safe) + { + *bytes_read= my_pread(dfile, buffer, cap->block_size, + block * cap->block_size, MY_WME); + if (*bytes_read == 0) + DBUG_RETURN(HA_ERR_END_OF_FILE); + DBUG_RETURN(*bytes_read > 0 ? 0 : (my_errno ? my_errno : -1)); + } + + *bytes_read= cap->block_size; + do + { + int error; + size_t length; + if ((length= my_pread(dfile, buffer, cap->block_size, + block * cap->block_size, MYF(0))) != cap->block_size) + { + if (length == 0) + DBUG_RETURN(HA_ERR_END_OF_FILE); + if (length == (size_t) -1) + DBUG_RETURN(my_errno ? my_errno : -1); + } + + /* If not transactional or key file header, there are no checksums */ + if (!cap->online_backup_safe) + DBUG_RETURN(length == cap->block_size ? 0 : HA_ERR_CRASHED); + + if (length == cap->block_size) + { + error= maria_page_crc_check(buffer, block, &share, + ((block % cap->bitmap_pages_covered) == 0 ? + MARIA_NO_CRC_BITMAP_PAGE : + MARIA_NO_CRC_NORMAL_PAGE), + share.block_size - CRC_SIZE); + if (error != HA_ERR_WRONG_CRC) + DBUG_RETURN(error); + } + my_sleep(100000); /* Sleep 0.1 seconds */ + } while (retry < MAX_RETRY); + DBUG_RETURN(HA_ERR_WRONG_CRC); +} diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index eeb922dd3f5..29a31a4596f 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -2600,7 +2600,8 @@ static my_bool free_full_page_range(MARIA_HA *info, pgcache_page_no_t page, @param record Record we should write @param row Statistics about record (calculated by calc_record_size()) - @param map_blocks On which pages the record should be stored + @param bitmap_blocks On which pages the record should be stored + @param head_block_is_read 1 if head block existed. 0 if new block. @param row_pos Position on head page where to put head part of record @param undo_lsn <> LSN_ERROR if we are executing an UNDO diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 4eab0e07315..998bb984452 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -167,6 +167,9 @@ int maria_chk_status(HA_CHECK *param, MARIA_HA *info) { MARIA_SHARE *share= info->s; + /* Protection for HA_EXTRA_FLUSH */ + mysql_mutex_lock(&share->intern_lock); + if (maria_is_crashed_on_repair(info)) _ma_check_print_warning(param, "Table is marked as crashed and last repair failed"); @@ -189,6 +192,9 @@ int maria_chk_status(HA_CHECK *param, MARIA_HA *info) if (param->testflag & T_UPDATE_STATE) param->warning_printed=save; } + + mysql_mutex_unlock(&share->intern_lock); + if (share->state.create_trid > param->max_trid) { param->wrong_trd_printed= 1; /* Force should run zerofill */ diff --git a/storage/maria/ma_checkpoint.h b/storage/maria/ma_checkpoint.h index df877ad2bbc..2ad044d5686 100644 --- a/storage/maria/ma_checkpoint.h +++ b/storage/maria/ma_checkpoint.h @@ -84,8 +84,8 @@ static inline LSN lsn_read_non_atomic_32(const volatile LSN *x) prints a message from a task not connected to any user (checkpoint and recovery for example). - @param level 0 if error, ME_JUST_WARNING if warning, - ME_JUST_INFO if info + @param level 0 if error, ME_WARNING if warning, + ME_NOTE if info @param sentence text to write */ #define ma_message_no_user(level, sentence) \ diff --git a/storage/maria/ma_control_file.c b/storage/maria/ma_control_file.c index 6ca6d06c97f..d55b12bbd9f 100644 --- a/storage/maria/ma_control_file.c +++ b/storage/maria/ma_control_file.c @@ -531,7 +531,7 @@ int ma_control_file_write_and_force(LSN last_checkpoint_lsn_arg, "Control file must be from a newer version; zero-ing out %u" " unknown bytes in control file at offset %u", zeroed, cf_changeable_size + cf_create_time_size); - ma_message_no_user(ME_JUST_WARNING, msg); + ma_message_no_user(ME_WARNING, msg); } else { @@ -608,4 +608,124 @@ my_bool ma_control_file_inited(void) return (control_file_fd >= 0); } +/** + Print content of aria_log_control file +*/ + +my_bool print_aria_log_control() +{ + uchar buffer[CF_MAX_SIZE]; + char name[FN_REFLEN], uuid_str[MY_UUID_STRING_LENGTH+1]; + const char *errmsg; + uint new_cf_create_time_size, new_cf_changeable_size; + my_off_t file_size; + ulong logno; + ulonglong trid,checkpoint_lsn; + int open_flags= O_BINARY | /*O_DIRECT |*/ O_RDWR | O_CLOEXEC; + int error= CONTROL_FILE_UNKNOWN_ERROR; + uint recovery_fails; + File file; + DBUG_ENTER("ma_control_file_open"); + + if (fn_format(name, CONTROL_FILE_BASE_NAME, + maria_data_root, "", MYF(MY_WME)) == NullS) + DBUG_RETURN(CONTROL_FILE_UNKNOWN_ERROR); + + if ((file= mysql_file_open(key_file_control, name, + open_flags, MYF(MY_WME))) < 0) + { + errmsg= "Can't open file"; + goto err; + } + + file_size= mysql_file_seek(file, 0, SEEK_END, MYF(MY_WME)); + if (file_size == MY_FILEPOS_ERROR) + { + errmsg= "Can't read size"; + goto err; + } + if (file_size < CF_MIN_SIZE) + { + /* + Given that normally we write only a sector and it's atomic, the only + possibility for a file to be of too short size is if we crashed at the + very first startup, between file creation and file write. Quite unlikely + (and can be made even more unlikely by doing this: create a temp file, + write it, and then rename it to be the control file). + What's more likely is if someone forgot to restore the control file, + just did a "touch control" to try to get Maria to start, or if the + disk/filesystem has a problem. + So let's be rigid. + */ + error= CONTROL_FILE_TOO_SMALL; + errmsg= "Size of control file is smaller than expected"; + goto err; + } + + /* Check if control file is unexpectedly big */ + if (file_size > CF_MAX_SIZE) + { + error= CONTROL_FILE_TOO_BIG; + errmsg= "File size bigger than expected"; + goto err; + } + + if (mysql_file_pread(file, buffer, (size_t)file_size, 0, MYF(MY_FNABP))) + { + errmsg= "Can't read file"; + goto err; + } + + if (memcmp(buffer + CF_MAGIC_STRING_OFFSET, + CF_MAGIC_STRING, CF_MAGIC_STRING_SIZE)) + { + error= CONTROL_FILE_BAD_MAGIC_STRING; + errmsg= "Missing valid id at start of file. File is not a valid aria control file"; + goto err; + } + + printf("Aria file version: %u\n", buffer[CF_VERSION_OFFSET]); + + new_cf_create_time_size= uint2korr(buffer + CF_CREATE_TIME_SIZE_OFFSET); + new_cf_changeable_size= uint2korr(buffer + CF_CHANGEABLE_SIZE_OFFSET); + + if (new_cf_create_time_size < CF_MIN_CREATE_TIME_TOTAL_SIZE || + new_cf_changeable_size < CF_MIN_CHANGEABLE_TOTAL_SIZE || + new_cf_create_time_size + new_cf_changeable_size != file_size) + { + error= CONTROL_FILE_INCONSISTENT_INFORMATION; + errmsg= "Sizes stored in control file are inconsistent"; + goto err; + } + checkpoint_lsn= lsn_korr(buffer + new_cf_create_time_size + + CF_LSN_OFFSET); + logno= uint4korr(buffer + new_cf_create_time_size + CF_FILENO_OFFSET); + my_uuid2str(buffer + CF_UUID_OFFSET, uuid_str); + uuid_str[MY_UUID_STRING_LENGTH]= 0; + + printf("Block size: %u\n", uint2korr(buffer + CF_BLOCKSIZE_OFFSET)); + printf("maria_uuid: %s\n", uuid_str); + printf("last_checkpoint_lsn: " LSN_FMT "\n", LSN_IN_PARTS(checkpoint_lsn)); + printf("last_log_number: %lu\n", (ulong) logno); + if (new_cf_changeable_size >= (CF_MAX_TRID_OFFSET + CF_MAX_TRID_SIZE)) + { + trid= transid_korr(buffer + new_cf_create_time_size + CF_MAX_TRID_OFFSET); + printf("trid: %llu\n", (ulonglong) trid); + } + if (new_cf_changeable_size >= (CF_RECOV_FAIL_OFFSET + CF_RECOV_FAIL_SIZE)) + { + recovery_fails= + (buffer + new_cf_create_time_size + CF_RECOV_FAIL_OFFSET)[0]; + printf("recovery_failuers: %u\n", recovery_fails); + } + + DBUG_RETURN(0); + +err: + my_printf_error(HA_ERR_INITIALIZATION, + "Got error '%s' when trying to use aria control file " + "'%s'", 0, errmsg, name); + DBUG_RETURN(error); +} + #endif /* EXTRACT_DEFINITIONS */ diff --git a/storage/maria/ma_control_file.h b/storage/maria/ma_control_file.h index 85e8f2c899d..51599f0abfc 100644 --- a/storage/maria/ma_control_file.h +++ b/storage/maria/ma_control_file.h @@ -70,5 +70,6 @@ int ma_control_file_write_and_force(LSN last_checkpoint_lsn_arg, uint8 recovery_failures_arg); int ma_control_file_end(void); my_bool ma_control_file_inited(void); +my_bool print_aria_log_control(void); C_MODE_END #endif diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 503d2420c41..24aa892d212 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -827,6 +827,11 @@ int maria_create(const char *name, enum data_file_type datafile_type, */ share.state.skip_redo_lsn= share.state.is_of_horizon= share.state.create_rename_lsn= LSN_MAX; + /* + We have to mark the table as not movable as the table will contain the + maria_uuid and create_rename_lsn + */ + share.state.changed|= STATE_NOT_MOVABLE; } if (datafile_type == DYNAMIC_RECORD) @@ -1446,6 +1451,7 @@ int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, TrID create_trid, uchar buf[LSN_STORE_SIZE * 3], *ptr; uchar trid_buff[8]; File file= share->kfile.file; + DBUG_ENTER("_ma_update_state_lsns_sub"); DBUG_ASSERT(file >= 0); if (lsn == LSN_IMPOSSIBLE) @@ -1464,7 +1470,7 @@ int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, TrID create_trid, 0].length, sizeof(log_array)/sizeof(log_array[0]), log_array, NULL, NULL))) - return res; + DBUG_RETURN(res); } for (ptr= buf; ptr < (buf + sizeof(buf)); ptr+= LSN_STORE_SIZE) @@ -1497,13 +1503,13 @@ int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, TrID create_trid, } else lsn_store(buf, share->state.create_rename_lsn); - return (my_pwrite(file, buf, sizeof(buf), - sizeof(share->state.header) + - MARIA_FILE_CREATE_RENAME_LSN_OFFSET, MYF(MY_NABP)) || - my_pwrite(file, trid_buff, sizeof(trid_buff), - sizeof(share->state.header) + - MARIA_FILE_CREATE_TRID_OFFSET, MYF(MY_NABP)) || - (do_sync && mysql_file_sync(file, MYF(0)))); + DBUG_RETURN(my_pwrite(file, buf, sizeof(buf), + sizeof(share->state.header) + + MARIA_FILE_CREATE_RENAME_LSN_OFFSET, MYF(MY_NABP)) || + my_pwrite(file, trid_buff, sizeof(trid_buff), + sizeof(share->state.header) + + MARIA_FILE_CREATE_TRID_OFFSET, MYF(MY_NABP)) || + (do_sync && mysql_file_sync(file, MYF(0)))); } #if defined(_MSC_VER) && (_MSC_VER == 1310) #pragma optimize("",on) diff --git a/storage/maria/ma_crypt.c b/storage/maria/ma_crypt.c index 42895dcdfa4..a007c14ba29 100644 --- a/storage/maria/ma_crypt.c +++ b/storage/maria/ma_crypt.c @@ -156,7 +156,7 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff) { my_printf_error(HA_ERR_UNSUPPORTED, "Unsupported crypt scheme! type: %d iv_length: %d\n", - MYF(ME_FATALERROR|ME_NOREFRESH), + MYF(ME_FATAL|ME_ERROR_LOG), type, iv_length); return 0; } @@ -464,7 +464,7 @@ static int ma_encrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, my_errno= HA_ERR_DECRYPTION_FAILED; my_printf_error(HA_ERR_DECRYPTION_FAILED, "Unknown key id %u. Can't continue!", - MYF(ME_FATALERROR|ME_NOREFRESH), + MYF(ME_FATAL|ME_ERROR_LOG), crypt_data->scheme.key_id); return 1; } @@ -481,7 +481,7 @@ static int ma_encrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, my_errno= HA_ERR_DECRYPTION_FAILED; my_printf_error(HA_ERR_DECRYPTION_FAILED, "failed to encrypt '%s' rc: %d dstlen: %u size: %u\n", - MYF(ME_FATALERROR|ME_NOREFRESH), + MYF(ME_FATAL|ME_ERROR_LOG), share->open_file_name.str, rc, dstlen, size); return 1; } @@ -508,7 +508,7 @@ static int ma_decrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, my_errno= HA_ERR_DECRYPTION_FAILED; my_printf_error(HA_ERR_DECRYPTION_FAILED, "failed to decrypt '%s' rc: %d dstlen: %u size: %u\n", - MYF(ME_FATALERROR|ME_NOREFRESH), + MYF(ME_FATAL|ME_ERROR_LOG), share->open_file_name.str, rc, dstlen, size); return 1; } diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index 9feead42cf7..9b544aaba59 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -420,7 +420,11 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX, FLUSH_KEEP, FLUSH_KEEP); + mysql_mutex_lock(&share->intern_lock); + /* Tell maria_lock_database() that we locked the intern_lock mutex */ + info->intern_lock_locked= 1; _ma_decrement_open_count(info, 1); + info->intern_lock_locked= 0; if (share->not_flushed) { share->not_flushed= 0; @@ -433,6 +437,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, _ma_set_fatal_error(share, HA_ERR_CRASHED); } } + mysql_mutex_unlock(&share->intern_lock); break; case HA_EXTRA_NORMAL: /* Theese isn't in use */ info->quick_mode= 0; diff --git a/storage/maria/ma_info.c b/storage/maria/ma_info.c index da44da123d2..22b9c86f21d 100644 --- a/storage/maria/ma_info.c +++ b/storage/maria/ma_info.c @@ -148,6 +148,6 @@ void _ma_report_error(int errcode, const LEX_STRING *name) } } - my_error(errcode, MYF(ME_NOREFRESH), file_name); + my_error(errcode, MYF(ME_ERROR_LOG), file_name); DBUG_VOID_RETURN; } diff --git a/storage/maria/ma_init.c b/storage/maria/ma_init.c index 8af3c41a3a1..7244d95b184 100644 --- a/storage/maria/ma_init.c +++ b/storage/maria/ma_init.c @@ -148,7 +148,7 @@ my_bool maria_upgrade() my_message(HA_ERR_INITIALIZATION, "Found old style Maria log files; " "Converting them to Aria names", - MYF(ME_JUST_INFO)); + MYF(ME_NOTE)); for (i= 0; i < dir->number_of_files; i++) { diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c index 4723c04e3cf..203fd394d26 100644 --- a/storage/maria/ma_locking.c +++ b/storage/maria/ma_locking.c @@ -47,7 +47,8 @@ int maria_lock_database(MARIA_HA *info, int lock_type) } error=0; - mysql_mutex_lock(&share->intern_lock); + if (!info->intern_lock_locked) + mysql_mutex_lock(&share->intern_lock); if (share->kfile.file >= 0) /* May only be false on windows */ { switch (lock_type) { @@ -234,7 +235,8 @@ int maria_lock_database(MARIA_HA *info, int lock_type) } } #endif - mysql_mutex_unlock(&share->intern_lock); + if (!info->intern_lock_locked) + mysql_mutex_unlock(&share->intern_lock); DBUG_RETURN(error); } /* maria_lock_database */ @@ -454,7 +456,7 @@ int _ma_mark_file_changed_now(register MARIA_SHARE *share) } /* Set uuid of file if not yet set (zerofilled file) */ if (share->base.born_transactional && - !(share->state.changed & STATE_NOT_MOVABLE)) + !(share->state.org_changed & STATE_NOT_MOVABLE)) { /* Lock table to current installation */ if (_ma_set_uuid(share, 0) || @@ -464,6 +466,7 @@ int _ma_mark_file_changed_now(register MARIA_SHARE *share) TRUE, TRUE))) goto err; share->state.changed|= STATE_NOT_MOVABLE; + share->state.org_changed|= STATE_NOT_MOVABLE; } } error= 0; diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c index 158904f6692..724beb7136c 100644 --- a/storage/maria/ma_loghandler.c +++ b/storage/maria/ma_loghandler.c @@ -56,6 +56,8 @@ static mysql_cond_t COND_soft_sync; static MA_SERVICE_THREAD_CONTROL soft_sync_control= {0, FALSE, FALSE, &LOCK_soft_sync, &COND_soft_sync}; +uint log_purge_disabled= 0; + /* transaction log file descriptor */ typedef struct st_translog_file @@ -3620,6 +3622,7 @@ my_bool translog_init_with_table(const char *directory, translog_syncs= 0; flush_start= 0; id_to_share= NULL; + log_purge_disabled= 0; log_descriptor.directory_fd= -1; log_descriptor.is_everything_flushed= 1; @@ -8668,7 +8671,7 @@ my_bool translog_purge(TRANSLOG_ADDRESS low) mysql_rwlock_unlock(&log_descriptor.open_files_lock); translog_close_log_file(file); } - if (log_purge_type == TRANSLOG_PURGE_IMMIDIATE) + if (log_purge_type == TRANSLOG_PURGE_IMMIDIATE && ! log_purge_disabled) { char path[FN_REFLEN], *file_name; file_name= translog_filename_by_fileno(i, path); @@ -8721,7 +8724,7 @@ my_bool translog_purge_at_flush() mysql_mutex_lock(&log_descriptor.purger_lock); - if (unlikely(log_descriptor.min_need_file == 0)) + if (unlikely(log_descriptor.min_need_file == 0 || log_purge_disabled)) { DBUG_PRINT("info", ("No info about min need file => exit")); mysql_mutex_unlock(&log_descriptor.purger_lock); @@ -9285,3 +9288,22 @@ void dump_page(uchar *buffer, File handler) } dump_datapage(buffer, handler); } + + +/* + Handle backup calls +*/ + +void translog_disable_purge() +{ + mysql_mutex_lock(&log_descriptor.purger_lock); + log_purge_disabled++; + mysql_mutex_unlock(&log_descriptor.purger_lock); +} + +void translog_enable_purge() +{ + mysql_mutex_lock(&log_descriptor.purger_lock); + log_purge_disabled--; + mysql_mutex_unlock(&log_descriptor.purger_lock); +} diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h index 3fb9e7d37bf..07d6a96557d 100644 --- a/storage/maria/ma_loghandler.h +++ b/storage/maria/ma_loghandler.h @@ -367,6 +367,8 @@ extern void dump_page(uchar *buffer, File handler); extern my_bool translog_log_debug_info(TRN *trn, enum translog_debug_info_type type, uchar *info, size_t length); +extern void translog_disable_purge(void); +extern void translog_enable_purge(void); enum enum_translog_status { @@ -520,6 +522,7 @@ typedef enum } enum_maria_translog_purge_type; extern ulong log_purge_type; extern ulong log_file_size; +extern uint log_purge_disabled; /* For backup */ typedef enum { diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 13f7a64e786..cd065d5eb1c 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -453,6 +453,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->state.state_length=base_pos; /* For newly opened tables we reset the error-has-been-printed flag */ share->state.changed&= ~STATE_CRASHED_PRINTED; + share->state.org_changed= share->state.changed; if (!(open_flags & HA_OPEN_FOR_REPAIR) && ((share->state.changed & STATE_CRASHED_FLAGS) || @@ -473,13 +474,13 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) /* A transactional table is not usable on this system if: - share->state.create_trid > trnman_get_max_trid() - - Critical as trid as stored releativel to create_trid. + - Critical as trid as stored releative to create_trid. - uuid is different STATE_NOT_MOVABLE is reset when a table is zerofilled (has no LSN's and no trids) - We can ignore testing uuid if STATE_NOT_MOVABLE is set, as in this + We can ignore testing uuid if STATE_NOT_MOVABLE is not set, as in this case the uuid will be set in _ma_mark_file_changed(). */ if (share->base.born_transactional && @@ -800,17 +801,27 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->state.is_of_horizon) > 0) || !LSN_VALID(share->state.skip_redo_lsn) || (cmp_translog_addr(share->state.create_rename_lsn, - share->state.skip_redo_lsn) > 0)) && - !(open_flags & HA_OPEN_FOR_REPAIR)) + share->state.skip_redo_lsn) > 0))) { - /* - If in Recovery, it will not work. If LSN is invalid and not - LSN_NEEDS_NEW_STATE_LSNS, header must be corrupted. - In both cases, must repair. - */ - my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ? - HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE); - goto err; + if (!(open_flags & HA_OPEN_FOR_REPAIR)) + { + /* + If in Recovery, it will not work. If LSN is invalid and not + LSN_NEEDS_NEW_STATE_LSNS, header must be corrupted. + In both cases, must repair. + */ + my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ? + HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE); + goto err; + } + else + { + /* + Open in repair mode. Ensure that we mark the table crashed, so + that we run auto_repair on it + */ + maria_mark_crashed_share(share); + } } else if (!(open_flags & HA_OPEN_FOR_REPAIR)) { diff --git a/storage/maria/ma_pagecrc.c b/storage/maria/ma_pagecrc.c index 8982c7e5c09..aae11158286 100644 --- a/storage/maria/ma_pagecrc.c +++ b/storage/maria/ma_pagecrc.c @@ -54,11 +54,11 @@ static uint32 maria_page_crc(uint32 start, uchar *data, uint length) @retval 1 Error */ -static my_bool maria_page_crc_check(uchar *page, - pgcache_page_no_t page_no, - MARIA_SHARE *share, - uint32 no_crc_val, - int data_length) +my_bool maria_page_crc_check(uchar *page, + pgcache_page_no_t page_no, + MARIA_SHARE *share, + uint32 no_crc_val, + int data_length) { uint32 crc= uint4korr(page + share->block_size - CRC_SIZE), new_crc; my_bool res; diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c index d1cb2d584b3..ae52b9191de 100644 --- a/storage/maria/ma_recovery.c +++ b/storage/maria/ma_recovery.c @@ -184,7 +184,7 @@ void maria_recover_error_handler_hook(uint error, const char *str, static void print_preamble() { - ma_message_no_user(ME_JUST_INFO, "starting recovery"); + ma_message_no_user(ME_NOTE, "starting recovery"); } @@ -523,7 +523,7 @@ end: } if (!error) { - ma_message_no_user(ME_JUST_INFO, "recovery done"); + ma_message_no_user(ME_NOTE, "recovery done"); maria_recovery_changed_data= 1; } } @@ -1363,6 +1363,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) silently pass in the "info == NULL" test below. */ tprint(tracef, ", record is corrupted"); + eprint(tracef, "\n***WARNING: %s may be corrupted", name ? name : "NULL"); info= NULL; recovery_warnings++; goto end; @@ -1375,7 +1376,11 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) " or its header is so corrupted that we cannot open it;" " we skip it"); if (my_errno != ENOENT) + { recovery_found_crashed_tables++; + eprint(tracef, "\n***WARNING: %s could not be opened: Error: %d", + name ? name : "NULL", (int) my_errno); + } error= 0; goto end; } @@ -1404,6 +1409,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) not transactional table */ tprint(tracef, ", is not transactional. Ignoring open request"); + eprint(tracef, "\n***WARNING: '%s' may be crashed", name); error= -1; recovery_warnings++; goto end; @@ -1414,6 +1420,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) " LOGREC_FILE_ID's LSN " LSN_FMT ", ignoring open request", LSN_IN_PARTS(share->state.create_rename_lsn), LSN_IN_PARTS(lsn_of_file_id)); + eprint(tracef, "\n***WARNING: '%s' may be crashed", name); recovery_warnings++; error= -1; goto end; @@ -1445,6 +1452,8 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id) (kfile_len == MY_FILEPOS_ERROR)) { tprint(tracef, ", length unknown\n"); + eprint(tracef, "\n***WARNING: Can't read length of file '%s'", + share->open_file_name.str); recovery_warnings++; goto end; } @@ -3568,7 +3577,12 @@ void _ma_tmp_disable_logging_for_table(MARIA_HA *info, should be now. info->trn may be NULL in maria_chk. */ if (info->trn == NULL) + { info->trn= &dummy_transaction_object; + info->trn_next= 0; + info->trn_prev= 0; + } + DBUG_ASSERT(info->trn->rec_lsn == LSN_IMPOSSIBLE); share->page_type= PAGECACHE_PLAIN_PAGE; /* Functions below will pick up now_transactional and change callbacks */ diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index 024b72fff2e..ccf48b80f7c 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -30,13 +30,11 @@ /* static variables */ #undef MIN_SORT_MEMORY -#undef MYF_RW #undef DISK_BUFFER_SIZE #define MERGEBUFF 15 #define MERGEBUFF2 31 #define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD) -#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) #define DISK_BUFFER_SIZE (IO_SIZE*128) /* How many keys we can keep in memory */ diff --git a/storage/maria/ma_state.c b/storage/maria/ma_state.c index 23cb625fc58..c658b9e667c 100644 --- a/storage/maria/ma_state.c +++ b/storage/maria/ma_state.c @@ -30,6 +30,7 @@ #include "maria_def.h" #include "trnman.h" +#include "ma_trnman.h" #include "ma_blockrec.h" /** @@ -571,7 +572,6 @@ void _ma_remove_table_from_trnman(MARIA_HA *info) MARIA_SHARE *share= info->s; TRN *trn= info->trn; MARIA_USED_TABLES *tables, **prev; - MARIA_HA *handler, **prev_file; DBUG_ENTER("_ma_remove_table_from_trnman"); DBUG_PRINT("enter", ("trn: %p used_tables: %p share: %p in_trans: %d", trn, trn->used_tables, share, share->in_trans)); @@ -603,26 +603,9 @@ void _ma_remove_table_from_trnman(MARIA_HA *info) DBUG_PRINT("warning", ("share: %p where not in used_tables_list", share)); } - /* unlink table from used_instances */ - for (prev_file= (MARIA_HA**) &trn->used_instances; - (handler= *prev_file); - prev_file= &handler->trn_next) - { - if (handler == info) - { - *prev_file= info->trn_next; - break; - } - } - if (handler != 0) - { - /* - This can only happens in case of rename of intermediate table as - part of alter table - */ - DBUG_PRINT("warning", ("table: %p where not in used_instances", info)); - } - info->trn= 0; /* Not part of trans anymore */ + /* Reset trn and remove table from used_instances */ + _ma_reset_trn_for_table(info); + DBUG_VOID_RETURN; } diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c index 24c48c67210..b6442c2be91 100644 --- a/storage/maria/ma_test2.c +++ b/storage/maria/ma_test2.c @@ -1086,6 +1086,11 @@ static void get_options(int argc, char **argv) fprintf(stderr,"record count must be >= 10 (if testflag > 2)\n"); exit(1); } + if (recant <= 1) + { + fprintf(stderr,"record count must be >= 2\n"); + exit(1); + } break; case 'e': /* maria_block_length */ case 'E': diff --git a/storage/maria/ma_trnman.h b/storage/maria/ma_trnman.h index 9bfd1f0d047..5b6d0e9f60d 100644 --- a/storage/maria/ma_trnman.h +++ b/storage/maria/ma_trnman.h @@ -18,7 +18,7 @@ /** Sets table's trn and prints debug information - Links table into used_instances if new_trn is not 0 + Links table into new_trn->used_instances @param tbl MARIA_HA of table @param newtrn what to put into tbl->trn @@ -34,7 +34,10 @@ static inline void _ma_set_trn_for_table(MARIA_HA *tbl, TRN *newtrn) tbl->trn= newtrn; /* Link into used list */ + if (newtrn->used_instances) + ((MARIA_HA*) newtrn->used_instances)->trn_prev= &tbl->trn_next; tbl->trn_next= (MARIA_HA*) newtrn->used_instances; + tbl->trn_prev= (MARIA_HA**) &newtrn->used_instances; newtrn->used_instances= tbl; } @@ -49,6 +52,8 @@ static inline void _ma_set_tmp_trn_for_table(MARIA_HA *tbl, TRN *newtrn) DBUG_PRINT("info",("table: %p trn: %p -> %p", tbl, tbl->trn, newtrn)); tbl->trn= newtrn; + tbl->trn_prev= 0; + tbl->trn_next= 0; /* To avoid assert in ha_maria::close() */ } @@ -59,7 +64,36 @@ static inline void _ma_set_tmp_trn_for_table(MARIA_HA *tbl, TRN *newtrn) static inline void _ma_reset_trn_for_table(MARIA_HA *tbl) { DBUG_PRINT("info",("table: %p trn: %p -> NULL", tbl, tbl->trn)); + + /* The following is only false if tbl->trn == &dummy_transaction_object */ + if (tbl->trn_prev) + { + if (tbl->trn_next) + tbl->trn_next->trn_prev= tbl->trn_prev; + *tbl->trn_prev= tbl->trn_next; + tbl->trn_prev= 0; + tbl->trn_next= 0; + } tbl->trn= 0; } + +/* + Take over the used_instances link from a trn object + Reset the link in the trn object +*/ + +static inline void relink_trn_used_instances(MARIA_HA **used_tables, TRN *trn) +{ + if (likely(*used_tables= (MARIA_HA*) trn->used_instances)) + { + /* Check that first back link is correct */ + DBUG_ASSERT((*used_tables)->trn_prev == (MARIA_HA **)&trn->used_instances); + + /* Fix back link to point to new base for the list */ + (*used_tables)->trn_prev= used_tables; + trn->used_instances= 0; + } +} + #endif /* _ma_trnman_h */ diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index dd2e2949856..1c77beb3c0f 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -177,6 +177,7 @@ typedef struct st_maria_state_info uint sortkey; /* sorted by this key (not used) */ uint open_count; uint changed; /* Changed since maria_chk */ + uint org_changed; /* Changed since open */ /** Birthday of the table: no record in the log before this LSN should ever be applied to the table. Updated when created, renamed, explicitly @@ -604,7 +605,7 @@ struct st_maria_handler { MARIA_SHARE *s; /* Shared between open:s */ struct st_ma_transaction *trn; /* Pointer to active transaction */ - struct st_maria_handler *trn_next; + struct st_maria_handler *trn_next,**trn_prev; MARIA_STATUS_INFO *state, state_save; MARIA_STATUS_INFO *state_start; /* State at start of transaction */ MARIA_USED_TABLES *used_tables; @@ -688,6 +689,7 @@ struct st_maria_handler uint16 last_used_keyseg; /* For MARIAMRG */ uint8 key_del_used; /* != 0 if key_del is used */ my_bool was_locked; /* Was locked in panic */ + my_bool intern_lock_locked; /* locked in ma_extra() */ my_bool append_insert_at_end; /* Set if concurrent insert */ my_bool quick_mode; my_bool in_check_table; /* We are running check tables */ @@ -1416,6 +1418,9 @@ extern my_bool maria_page_crc_check_bitmap(int, PAGECACHE_IO_HOOK_ARGS *args); extern my_bool maria_page_crc_check_data(int, PAGECACHE_IO_HOOK_ARGS *args); extern my_bool maria_page_crc_check_index(int, PAGECACHE_IO_HOOK_ARGS *args); extern my_bool maria_page_crc_check_none(int, PAGECACHE_IO_HOOK_ARGS *args); +extern my_bool maria_page_crc_check(uchar *page, pgcache_page_no_t page_no, + MARIA_SHARE *share, uint32 no_crc_val, + int data_length); extern my_bool maria_page_filler_set_bitmap(PAGECACHE_IO_HOOK_ARGS *args); extern my_bool maria_page_filler_set_normal(PAGECACHE_IO_HOOK_ARGS *args); extern my_bool maria_page_filler_set_none(PAGECACHE_IO_HOOK_ARGS *args); diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c index 551732d8ba3..f3338714846 100644 --- a/storage/maria/maria_read_log.c +++ b/storage/maria/maria_read_log.c @@ -31,6 +31,7 @@ const char *default_dbug_option= "d:t:o,/tmp/aria_read_log.trace"; #endif /* DBUG_OFF */ static my_bool opt_display_only, opt_apply, opt_apply_undo, opt_silent; static my_bool opt_check; +static my_bool opt_print_aria_log_control; static const char *opt_tmpdir; static ulong opt_translog_buffer_size; static ulonglong opt_page_buffer_size; @@ -59,6 +60,12 @@ int main(int argc, char **argv) goto err; } maria_block_size= 0; /* Use block size from file */ + if (opt_print_aria_log_control) + { + if (print_aria_log_control()) + goto err; + goto end; + } /* we don't want to create a control file, it MUST exist */ if (ma_control_file_open(FALSE, TRUE)) { @@ -209,6 +216,10 @@ static struct my_option my_long_options[] = &opt_page_buffer_size, &opt_page_buffer_size, 0, GET_ULL, REQUIRED_ARG, PAGE_BUFFER_INIT, PAGE_BUFFER_INIT, SIZE_T_MAX, MALLOC_OVERHEAD, (long) IO_SIZE, 0}, + { "print-log-control-file", 'l', + "Print the content of the aria_log_control_file", + &opt_print_aria_log_control, &opt_print_aria_log_control, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { "start-from-lsn", 'o', "Start reading log from this lsn", &opt_start_from_lsn, &opt_start_from_lsn, 0, GET_ULL, REQUIRED_ARG, 0, 0, ~(longlong) 0, 0, 0, 0 }, @@ -249,7 +260,7 @@ static struct my_option my_long_options[] = static void print_version(void) { - printf("%s Ver 1.3 for %s on %s\n", + printf("%s Ver 1.4 for %s on %s\n", my_progname_short, SYSTEM_TYPE, MACHINE_TYPE); } @@ -261,7 +272,7 @@ static void usage(void) puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,"); puts("and you are welcome to modify and redistribute it under the GPL license\n"); - puts("Display and apply log records from a Aria transaction log"); + puts("Display or apply log records from a Aria transaction log"); puts("found in the current directory (for now)"); #ifndef IDENTICAL_PAGES_AFTER_RECOVERY puts("\nNote: Aria is compiled without -DIDENTICAL_PAGES_AFTER_RECOVERY\n" @@ -269,8 +280,13 @@ static void usage(void) "files created during normal execution. This should be ok, except for\n" "test scripts that tries to compare files before and after recovery."); #endif - printf("\nUsage: %s OPTIONS\n", my_progname_short); - puts("You need to use one of -d or -a"); + printf("\nUsage: %s OPTIONS [-d | -a] -h `aria_log_directory`\n", + my_progname_short); + printf("or\n"); + printf("Usage: %s OPTIONS -h `aria_log_directory` " + "--print-aria-log-control\n\n", + my_progname_short); + my_print_help(my_long_options); print_defaults("my", load_default_groups); my_print_variables(my_long_options); @@ -339,12 +355,12 @@ static void get_options(int *argc,char ***argv) need_help= 1; fprintf(stderr, "Too many arguments given\n"); } - if ((opt_display_only + opt_apply) != 1) + if ((opt_display_only + opt_apply + opt_print_aria_log_control) != 1) { need_help= 1; fprintf(stderr, - "You must use one and only one of the options 'display-only' or " - "'apply'\n"); + "You must use one and only one of the options 'display-only', \n" + "'print-log-control-file' and 'apply'\n"); } if (need_help) diff --git a/storage/maria/test_ma_backup.c b/storage/maria/test_ma_backup.c new file mode 100644 index 00000000000..439ea7fd665 --- /dev/null +++ b/storage/maria/test_ma_backup.c @@ -0,0 +1,449 @@ +/* Copyright (C) 2018 MariaDB corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + +/* Code for doing backups of Aria tables */ + +/****************************************************************************** + Testing ma_backup interface + Table creation code is taken from ma_test1 +******************************************************************************/ + +#define ROWS_IN_TEST 100000 + +#include "maria_def.h" +#include "ma_blockrec.h" /* PAGE_SUFFIX_SIZE */ +#include "ma_checkpoint.h" +#include <aria_backup.h> + +static int silent; +static int create_test_table(const char *table_name, int stage); +static int copy_table(const char *table_name, int stage); +static void create_record(uchar *record,uint rownr); + +int main(int argc,char *argv[]) +{ + int error= 1; + int i; + char buff[FN_REFLEN]; +#ifdef SAFE_MUTEX + safe_mutex_deadlock_detector= 1; +#endif + MY_INIT(argv[0]); + maria_data_root= (char *)"."; + + /* Maria requires that we always have a page cache */ + if (maria_init() || + (init_pagecache(maria_pagecache, maria_block_size * 2000, 0, 0, + maria_block_size, 0, MY_WME) == 0) || + ma_control_file_open(TRUE, TRUE) || + (init_pagecache(maria_log_pagecache, + TRANSLOG_PAGECACHE_SIZE, 0, 0, + TRANSLOG_PAGE_SIZE, 0, MY_WME) == 0) || + translog_init(maria_data_root, TRANSLOG_FILE_SIZE, + 0, 0, maria_log_pagecache, + TRANSLOG_DEFAULT_FLAGS, 0) || + (trnman_init(0) || ma_checkpoint_init(0))) + { + fprintf(stderr, "Error in initialization\n"); + exit(1); + } + init_thr_lock(); + + fn_format(buff, "test_copy", maria_data_root, "", MYF(0)); + + for (i= 0; i < 5 ; i++) + { + printf("Stage: %d\n", i); + fflush(stdout); + if (create_test_table(buff, i)) + goto err; + if (copy_table(buff, i)) + goto err; + } + error= 0; + printf("test ok\n"); +err: + if (error) + fprintf(stderr, "Test %i failed\n", i); + maria_end(); + my_uuid_end(); + my_end(MY_CHECK_ERROR); + exit(error); +} + + +/** + Example of how to read an Aria table +*/ + +static int copy_table(const char *table_name, int stage) +{ + char old_name[FN_REFLEN]; + uchar *copy_buffer= 0; + ARIA_TABLE_CAPABILITIES cap; + ulonglong block; + File org_file= -1; + int error= 1; + + strxmov(old_name, table_name, ".MAI", NullS); + + if ((org_file= my_open(old_name, + O_RDONLY | O_SHARE | O_NOFOLLOW | O_CLOEXEC, + MYF(MY_WME))) < 0) + goto err; + if ((error= aria_get_capabilities(org_file, &cap))) + { + fprintf(stderr, "aria_get_capabilities failed: %d\n", error); + goto err; + } + + printf("- Capabilities read. oneline_backup_safe: %d\n", + cap.online_backup_safe); + printf("- Copying index file\n"); + + copy_buffer= my_malloc(cap.block_size, MYF(0)); + for (block= 0 ; ; block++) + { + if ((error= aria_read_index(org_file, &cap, block, copy_buffer) == + HA_ERR_END_OF_FILE)) + break; + if (error) + { + fprintf(stderr, "aria_read_index failed: %d\n", error); + goto err; + } + } + my_close(org_file, MYF(MY_WME)); + + + printf("- Copying data file\n"); + strxmov(old_name, table_name, ".MAD", NullS); + if ((org_file= my_open(old_name, O_RDONLY | O_SHARE | O_NOFOLLOW | O_CLOEXEC, + MYF(MY_WME))) < 0) + goto err; + + for (block= 0 ; ; block++) + { + size_t length; + if ((error= aria_read_data(org_file, &cap, block, copy_buffer, + &length) == HA_ERR_END_OF_FILE)) + break; + if (error) + { + fprintf(stderr, "aria_read_index failed: %d\n", error); + goto err; + } + } + error= 0; + +err: + my_free(copy_buffer); + if (org_file >= 0) + my_close(org_file, MYF(MY_WME)); + if (error) + fprintf(stderr, "Failed in copy_table stage: %d\n", stage); + return error; +} + + +/* Code extracted from ma_test1.c */ +#define MAX_REC_LENGTH 1024 + +static MARIA_COLUMNDEF recinfo[4]; +static MARIA_KEYDEF keyinfo[10]; +static HA_KEYSEG keyseg[10]; +static HA_KEYSEG uniqueseg[10]; + + +/** + Create a test table and fill it with some data +*/ + +static int create_test_table(const char *table_name, int type_of_table) +{ + MARIA_HA *file; + int i,error,uniques=0; + int key_field=FIELD_SKIP_PRESPACE,extra_field=FIELD_SKIP_ENDSPACE; + int key_type=HA_KEYTYPE_NUM; + int create_flag=0; + uint offset_to_key; + uint pack_seg=0, pack_keys= 0; + uint key_length; + uchar record[MAX_REC_LENGTH]; + MARIA_UNIQUEDEF uniquedef; + MARIA_CREATE_INFO create_info; + enum data_file_type record_type= DYNAMIC_RECORD; + my_bool null_fields= 0, unique_key= 0; + my_bool opt_unique= 0; + my_bool transactional= 0; + + key_length= 12; + switch (type_of_table) { + case 0: + break; + case 1: + create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM; + break; + case 2: /* transactional */ + create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM; + record_type= BLOCK_RECORD; + transactional= 1; + break; + case 3: /* transactional */ + create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM; + record_type= BLOCK_RECORD; + transactional= 1; + key_field=FIELD_VARCHAR; /* varchar keys */ + extra_field= FIELD_VARCHAR; + key_type= HA_KEYTYPE_VARTEXT1; + pack_seg|= HA_VAR_LENGTH_PART; + null_fields= 1; + break; + case 4: /* transactional */ + create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM; + record_type= BLOCK_RECORD; + transactional= 1; + key_field=FIELD_BLOB; /* blob key */ + extra_field= FIELD_BLOB; + pack_seg|= HA_BLOB_PART; + key_type= HA_KEYTYPE_VARTEXT1; + break; + } + + + bzero((char*) recinfo,sizeof(recinfo)); + bzero((char*) &create_info,sizeof(create_info)); + + /* First define 2 columns */ + create_info.null_bytes= 1; + recinfo[0].type= key_field; + recinfo[0].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr : + key_length); + if (key_field == FIELD_VARCHAR) + recinfo[0].length+= HA_VARCHAR_PACKLENGTH(key_length); + recinfo[1].type=extra_field; + recinfo[1].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : 24); + if (extra_field == FIELD_VARCHAR) + recinfo[1].length+= HA_VARCHAR_PACKLENGTH(recinfo[1].length); + recinfo[1].null_bit= null_fields ? 2 : 0; + + if (opt_unique) + { + recinfo[2].type=FIELD_CHECK; + recinfo[2].length=MARIA_UNIQUE_HASH_LENGTH; + } + + if (key_type == HA_KEYTYPE_VARTEXT1 && + key_length > 255) + key_type= HA_KEYTYPE_VARTEXT2; + + /* Define a key over the first column */ + keyinfo[0].seg=keyseg; + keyinfo[0].keysegs=1; + keyinfo[0].block_length= 0; /* Default block length */ + keyinfo[0].key_alg=HA_KEY_ALG_BTREE; + keyinfo[0].seg[0].type= key_type; + keyinfo[0].seg[0].flag= pack_seg; + keyinfo[0].seg[0].start=1; + keyinfo[0].seg[0].length=key_length; + keyinfo[0].seg[0].null_bit= null_fields ? 2 : 0; + keyinfo[0].seg[0].null_pos=0; + keyinfo[0].seg[0].language= default_charset_info->number; + if (pack_seg & HA_BLOB_PART) + { + keyinfo[0].seg[0].bit_start=4; /* Length of blob length */ + } + keyinfo[0].flag = (uint8) (pack_keys | unique_key); + + if (opt_unique) + { + uint start; + uniques=1; + bzero((char*) &uniquedef,sizeof(uniquedef)); + bzero((char*) uniqueseg,sizeof(uniqueseg)); + uniquedef.seg=uniqueseg; + uniquedef.keysegs=2; + + /* Make a unique over all columns (except first NULL fields) */ + for (i=0, start=1 ; i < 2 ; i++) + { + uniqueseg[i].start=start; + start+=recinfo[i].length; + uniqueseg[i].length=recinfo[i].length; + uniqueseg[i].language= default_charset_info->number; + } + uniqueseg[0].type= key_type; + uniqueseg[0].null_bit= null_fields ? 2 : 0; + uniqueseg[1].type= HA_KEYTYPE_TEXT; + if (extra_field == FIELD_BLOB) + { + uniqueseg[1].length=0; /* The whole blob */ + uniqueseg[1].bit_start=4; /* long blob */ + uniqueseg[1].flag|= HA_BLOB_PART; + } + else if (extra_field == FIELD_VARCHAR) + { + uniqueseg[1].flag|= HA_VAR_LENGTH_PART; + uniqueseg[1].type= (HA_VARCHAR_PACKLENGTH(recinfo[1].length-1) == 1 ? + HA_KEYTYPE_VARTEXT1 : HA_KEYTYPE_VARTEXT2); + } + } + else + uniques=0; + + offset_to_key= MY_TEST(null_fields); + if (key_field == FIELD_BLOB || key_field == FIELD_VARCHAR) + offset_to_key+= 2; + + if (!silent) + printf("- Creating Aria file\n"); + create_info.max_rows= 0; + create_info.transactional= transactional; + if (maria_create(table_name, record_type, 1, keyinfo,2+opt_unique,recinfo, + uniques, &uniquedef, &create_info, + create_flag)) + goto err; + if (!(file=maria_open(table_name,2,HA_OPEN_ABORT_IF_LOCKED))) + goto err; + if (!silent) + printf("- Writing key:s\n"); + + if (maria_begin(file)) + goto err; + my_errno=0; + for (i= 0 ; i < ROWS_IN_TEST ; i++) + { + create_record(record,i); + if ((error=maria_write(file,record))) + goto err; + } + + if (maria_commit(file) | maria_close(file)) + goto err; + printf("- Data copied\n"); + return 0; + +err: + printf("got error: %3d when using maria-database\n",my_errno); + return 1; /* skip warning */ +} + + +static void create_key_part(uchar *key,uint rownr) +{ + if (keyinfo[0].seg[0].type == HA_KEYTYPE_NUM) + { + sprintf((char*) key,"%*d",keyinfo[0].seg[0].length,rownr); + } + else if (keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT1 || + keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT2) + { /* Alpha record */ + /* Create a key that may be easily packed */ + bfill(key,keyinfo[0].seg[0].length,rownr < 10 ? 'A' : 'B'); + sprintf((char*) key+keyinfo[0].seg[0].length-2,"%-2d",rownr % 100); + if ((rownr & 7) == 0) + { + /* Change the key to force a unpack of the next key */ + bfill(key+3,keyinfo[0].seg[0].length-5,rownr < 10 ? 'a' : 'b'); + } + } + else + { /* Alpha record */ + if (keyinfo[0].seg[0].flag & HA_SPACE_PACK) + sprintf((char*) key,"%-*d",keyinfo[0].seg[0].length,rownr); + else + { + /* Create a key that may be easily packed */ + bfill(key,keyinfo[0].seg[0].length,rownr < 10 ? 'A' : 'B'); + sprintf((char*) key+keyinfo[0].seg[0].length-2,"%-2d",rownr % 100); + if ((rownr & 7) == 0) + { + /* Change the key to force a unpack of the next key */ + key[1]= (rownr < 10 ? 'a' : 'b'); + } + } + } +} + + +static uchar blob_key[MAX_REC_LENGTH]; +static uchar blob_record[MAX_REC_LENGTH+20*20]; + + +static void create_record(uchar *record,uint rownr) +{ + uchar *pos; + bzero((char*) record,MAX_REC_LENGTH); + record[0]=1; /* delete marker */ + if (rownr == 0 && keyinfo[0].seg[0].null_bit) + record[0]|=keyinfo[0].seg[0].null_bit; /* Null key */ + + pos=record+1; + if (recinfo[0].type == FIELD_BLOB) + { + size_t tmp; + uchar *ptr; + create_key_part(blob_key,rownr); + tmp=strlen((char*) blob_key); + int4store(pos,tmp); + ptr=blob_key; + memcpy(pos+4,&ptr,sizeof(char*)); + pos+=recinfo[0].length; + } + else if (recinfo[0].type == FIELD_VARCHAR) + { + size_t tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[0].length-1); + create_key_part(pos+pack_length,rownr); + tmp= strlen((char*) pos+pack_length); + if (pack_length == 1) + *(uchar*) pos= (uchar) tmp; + else + int2store(pos,tmp); + pos+= recinfo[0].length; + } + else + { + create_key_part(pos,rownr); + pos+=recinfo[0].length; + } + if (recinfo[1].type == FIELD_BLOB) + { + size_t tmp; + uchar *ptr;; + sprintf((char*) blob_record,"... row: %d", rownr); + strappend((char*) blob_record, rownr % MAX_REC_LENGTH,'x'); + tmp=strlen((char*) blob_record); + int4store(pos,tmp); + ptr=blob_record; + memcpy(pos+4,&ptr,sizeof(char*)); + } + else if (recinfo[1].type == FIELD_VARCHAR) + { + size_t tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1); + sprintf((char*) pos+pack_length, "... row: %d", rownr); + tmp= strlen((char*) pos+pack_length); + if (pack_length == 1) + *pos= (uchar) tmp; + else + int2store(pos,tmp); + } + else + { + sprintf((char*) pos,"... row: %d", rownr); + strappend((char*) pos,recinfo[1].length,' '); + } +} + +#include "ma_check_standalone.h" diff --git a/storage/maria/trnman.c b/storage/maria/trnman.c index 5b3c9f0287a..3c5ce831f95 100644 --- a/storage/maria/trnman.c +++ b/storage/maria/trnman.c @@ -413,6 +413,7 @@ my_bool trnman_end_trn(TRN *trn, my_bool commit) /* if a rollback, all UNDO records should have been executed */ DBUG_ASSERT(commit || trn->undo_lsn == 0); DBUG_ASSERT(trn != &dummy_transaction_object); + DBUG_ASSERT(trn->locked_tables == 0 && trn->used_instances == 0); DBUG_PRINT("info", ("mysql_mutex_lock LOCK_trn_list")); mysql_mutex_lock(&LOCK_trn_list); @@ -529,6 +530,8 @@ static void trnman_free_trn(TRN *trn) */ union { TRN *trn; void *v; } tmp; + DBUG_ASSERT(trn != &dummy_transaction_object); + mysql_mutex_lock(&trn->state_lock); trn->short_id= 0; mysql_mutex_unlock(&trn->state_lock); diff --git a/storage/maria/unittest/ma_test_all-t b/storage/maria/unittest/ma_test_all-t index 18b26a7bd45..8858649fb5d 100755 --- a/storage/maria/unittest/ma_test_all-t +++ b/storage/maria/unittest/ma_test_all-t @@ -749,9 +749,10 @@ Options --help Show this help and exit. --abort-on-error Abort at once in case of error. --number-of-tests Print the total number of tests and exit. ---run-tests=... Test number(s) that should be run. You can give just - one number or a range. For example 45..89. To run a specific - test alone, for example test 215, use --run-tests=215..215 +--run-tests=... Test range that should be run. You can give just + one number, to start tests from this test, or a range. + For example 45..89. To run a specific test alone, + for example test 215, use --run-tests=215..215 Use this option with caution, because some of the tests might depend on previous ones. --start-from=... Alias for --run-tests diff --git a/storage/maria/unittest/ma_test_recovery.expected b/storage/maria/unittest/ma_test_recovery.expected index 6aaff86e6cf..38e8e4d8e93 100644 --- a/storage/maria/unittest/ma_test_recovery.expected +++ b/storage/maria/unittest/ma_test_recovery.expected @@ -70,7 +70,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -79,7 +79,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -88,7 +88,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -99,7 +99,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -108,7 +108,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -117,7 +117,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -167,7 +167,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -176,7 +176,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -185,7 +185,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -196,7 +196,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -205,7 +205,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -214,7 +214,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -264,7 +264,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -273,7 +273,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -282,7 +282,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -293,7 +293,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -302,7 +302,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -311,7 +311,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -361,7 +361,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -370,7 +370,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -379,7 +379,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -390,7 +390,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -399,7 +399,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -408,7 +408,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -458,7 +458,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -467,7 +467,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -476,7 +476,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -487,7 +487,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -496,7 +496,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -505,7 +505,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -555,7 +555,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -564,7 +564,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -573,7 +573,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -584,7 +584,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -593,7 +593,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -602,7 +602,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -652,7 +652,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -661,7 +661,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -670,7 +670,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -681,7 +681,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -690,7 +690,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -699,7 +699,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -749,7 +749,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -758,7 +758,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -767,7 +767,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -778,7 +778,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -787,7 +787,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -796,7 +796,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -846,7 +846,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -855,7 +855,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -864,7 +864,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -875,7 +875,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -884,7 +884,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -893,7 +893,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -943,7 +943,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -952,7 +952,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -961,7 +961,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -972,7 +972,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -981,7 +981,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -990,7 +990,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1040,7 +1040,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1049,7 +1049,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1058,7 +1058,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1069,7 +1069,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1078,7 +1078,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1087,7 +1087,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1137,7 +1137,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1146,7 +1146,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1155,7 +1155,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1166,7 +1166,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1175,7 +1175,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1184,7 +1184,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1234,7 +1234,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1243,7 +1243,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1252,7 +1252,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1263,7 +1263,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1272,7 +1272,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1281,7 +1281,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1331,7 +1331,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1340,7 +1340,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1349,7 +1349,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1360,7 +1360,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1369,7 +1369,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1378,7 +1378,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1428,7 +1428,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1437,7 +1437,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1446,7 +1446,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1457,7 +1457,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1466,7 +1466,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1475,7 +1475,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1525,7 +1525,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1534,7 +1534,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1543,7 +1543,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1554,7 +1554,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1563,7 +1563,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= @@ -1572,7 +1572,7 @@ applying log Differences in aria_chk -dvv, recovery not yet perfect ! ========DIFF START======= 7c7 -< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable +< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled --- > Status: changed ========DIFF END======= diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp index a80776fe5f5..7a41442d4ba 100644 --- a/storage/mroonga/ha_mroonga.cpp +++ b/storage/mroonga/ha_mroonga.cpp @@ -193,7 +193,7 @@ static mysql_mutex_t *mrn_LOCK_open; #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) # define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex->table_list.first #else -# define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex.table_list.first +# define MRN_LEX_GET_TABLE_LIST(lex) (lex)->first_select_lex()->table_list.first #endif #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) @@ -10576,7 +10576,7 @@ int ha_mroonga::generic_store_bulk_time(Field *field, grn_obj *buf) bool truncated = false; Field_time *time_field = (Field_time *)field; MYSQL_TIME mysql_time; - time_field->get_time(&mysql_time); + time_field->get_date(&mysql_time, Time::Options(current_thd)); mrn::TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); @@ -10596,7 +10596,7 @@ int ha_mroonga::generic_store_bulk_datetime(Field *field, grn_obj *buf) bool truncated = false; Field_datetime *datetime_field = (Field_datetime *)field; MYSQL_TIME mysql_time; - datetime_field->get_time(&mysql_time); + datetime_field->get_date(&mysql_time, Time::Options(current_thd)); mrn::TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); @@ -10657,7 +10657,7 @@ int ha_mroonga::generic_store_bulk_datetime2(Field *field, grn_obj *buf) bool truncated = false; Field_datetimef *datetimef_field = (Field_datetimef *)field; MYSQL_TIME mysql_time; - datetimef_field->get_time(&mysql_time); + datetimef_field->get_date(&mysql_time, Time::Options(current_thd)); mrn::TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); @@ -10682,7 +10682,7 @@ int ha_mroonga::generic_store_bulk_time2(Field *field, grn_obj *buf) int error = 0; bool truncated = false; MYSQL_TIME mysql_time; - field->get_time(&mysql_time); + field->get_date(&mysql_time, Time::Options(current_thd)); mrn::TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); @@ -10707,7 +10707,7 @@ int ha_mroonga::generic_store_bulk_new_date(Field *field, grn_obj *buf) bool truncated = false; Field_newdate *newdate_field = (Field_newdate *)field; MYSQL_TIME mysql_date; - newdate_field->get_time(&mysql_date); + newdate_field->get_date(&mysql_date, Time::Options(current_thd)); mrn::TimeConverter time_converter; long long int time = time_converter.mysql_time_to_grn_time(&mysql_date, &truncated); @@ -11617,14 +11617,14 @@ int ha_mroonga::storage_encode_key_timestamp(Field *field, const uchar *key, } else { Field_timestamp_hires *timestamp_hires_field = (Field_timestamp_hires *)field; - uint fuzzy_date = 0; uchar *ptr_backup = field->ptr; uchar *null_ptr_backup = field->null_ptr; TABLE *table_backup = field->table; field->ptr = (uchar *)key; field->null_ptr = (uchar *)(key - 1); field->table = table; - timestamp_hires_field->get_date(&mysql_time, fuzzy_date); + Temporal::Options opt(TIME_CONV_NONE, current_thd); + timestamp_hires_field->get_date(&mysql_time, opt); field->ptr = ptr_backup; field->null_ptr = null_ptr_backup; field->table = table_backup; @@ -11675,12 +11675,12 @@ int ha_mroonga::storage_encode_key_time(Field *field, const uchar *key, mysql_time.time_type = MYSQL_TIMESTAMP_TIME; } else { Field_time_hires *time_hires_field = (Field_time_hires *)field; - uint fuzzy_date = 0; uchar *ptr_backup = field->ptr; uchar *null_ptr_backup = field->null_ptr; field->ptr = (uchar *)key; field->null_ptr = (uchar *)(key - 1); - time_hires_field->get_date(&mysql_time, fuzzy_date); + Temporal::Options opt(TIME_CONV_NONE, current_thd); + time_hires_field->get_date(&mysql_time, opt); field->ptr = ptr_backup; field->null_ptr = null_ptr_backup; } @@ -11749,12 +11749,12 @@ int ha_mroonga::storage_encode_key_datetime(Field *field, const uchar *key, if (field->decimals() > 0) { Field_datetime_hires *datetime_hires_field = (Field_datetime_hires *)field; MYSQL_TIME mysql_time; - uint fuzzy_date = 0; uchar *ptr_backup = field->ptr; uchar *null_ptr_backup = field->null_ptr; field->ptr = (uchar *)key; field->null_ptr = (uchar *)(key - 1); - datetime_hires_field->get_date(&mysql_time, fuzzy_date); + Temporal::Options opt(TIME_CONV_NONE, current_thd); + datetime_hires_field->get_date(&mysql_time, opt); field->ptr = ptr_backup; field->null_ptr = null_ptr_backup; mrn::TimeConverter time_converter; diff --git a/storage/mroonga/lib/mrn_condition_converter.cpp b/storage/mroonga/lib/mrn_condition_converter.cpp index 579292a7f89..68ffa073f4f 100644 --- a/storage/mroonga/lib/mrn_condition_converter.cpp +++ b/storage/mroonga/lib/mrn_condition_converter.cpp @@ -179,17 +179,17 @@ namespace mrn { NormalizedType normalized_type = normalize_field_type(field_type); switch (normalized_type) { case STRING_TYPE: - if (value_item->type() == Item::STRING_ITEM && + if (value_item->is_of_type(Item::CONST_ITEM, STRING_RESULT) && func_type == Item_func::EQ_FUNC) { convertable = have_index(field_item, GRN_OP_EQUAL); } break; case INT_TYPE: if (field_type == MYSQL_TYPE_ENUM) { - convertable = (value_item->type() == Item::STRING_ITEM || - value_item->type() == Item::INT_ITEM); + convertable = value_item->is_of_type(Item::CONST_ITEM, STRING_RESULT) || + value_item->is_of_type(Item::CONST_ITEM, INT_RESULT); } else { - convertable = value_item->type() == Item::INT_ITEM; + convertable = value_item->is_of_type(Item::CONST_ITEM, INT_RESULT); } break; case TIME_TYPE: @@ -215,14 +215,14 @@ namespace mrn { NormalizedType normalized_type = normalize_field_type(field_type); switch (normalized_type) { case STRING_TYPE: - if (min_item->type() == Item::STRING_ITEM && - max_item->type() == Item::STRING_ITEM) { + if (min_item->is_of_type(Item::CONST_ITEM, STRING_RESULT) && + max_item->is_of_type(Item::CONST_ITEM, STRING_RESULT)) { convertable = have_index(field_item, GRN_OP_LESS); } break; case INT_TYPE: - if (min_item->type() == Item::INT_ITEM && - max_item->type() == Item::INT_ITEM) { + if (min_item->is_of_type(Item::CONST_ITEM, INT_RESULT) && + max_item->is_of_type(Item::CONST_ITEM, INT_RESULT)) { convertable = have_index(field_item, GRN_OP_LESS); } break; @@ -258,8 +258,11 @@ namespace mrn { Item *real_value_item = value_item->real_item(); switch (field_item->field->type()) { case MYSQL_TYPE_TIME: - error = real_value_item->get_time(mysql_time); + { + THD *thd= current_thd; + error= real_value_item->get_date(thd, mysql_time, Time::Options(thd)); break; + } case MYSQL_TYPE_YEAR: mysql_time->year = static_cast<int>(value_item->val_int()); mysql_time->month = 1; @@ -273,9 +276,13 @@ namespace mrn { error = false; break; default: - error = real_value_item->get_date(mysql_time, TIME_FUZZY_DATE); + { + THD *thd= current_thd; + Datetime::Options opt(TIME_FUZZY_DATES, thd); + error = real_value_item->get_date(thd, mysql_time, opt); break; } + } DBUG_RETURN(error); } @@ -587,7 +594,7 @@ namespace mrn { case INT_TYPE: grn_obj_reinit(ctx_, &value_, GRN_DB_INT64, 0); if (field_type == MYSQL_TYPE_ENUM) { - if (const_item->type() == Item::STRING_ITEM) { + if (const_item->is_of_type(Item::CONST_ITEM, STRING_RESULT)) { String *string; string = const_item->val_str(NULL); Field_enum *enum_field = static_cast<Field_enum *>(field_item->field); diff --git a/storage/myisam/TODO b/storage/myisam/TODO deleted file mode 100644 index cad9486e1bb..00000000000 --- a/storage/myisam/TODO +++ /dev/null @@ -1,7 +0,0 @@ -TODO: - -- Let packisam find the optimal way to store keys. -- kill when using 'myisamchk' should remove all temporary files. -- Text search index - (Sergei A. Golub is working on this) -- Add '%' packed to myisamchk for compressed tables with blobs. diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index d9b34c86095..9ab7d156251 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -96,6 +96,10 @@ static MYSQL_THDVAR_ENUM(stats_method, PLUGIN_VAR_RQCMDARG, "and NULLS_IGNORED", NULL, NULL, MI_STATS_METHOD_NULLS_NOT_EQUAL, &myisam_stats_method_typelib); +const char *MI_CHECK_INFO= "info"; +const char *MI_CHECK_WARNING= "warning"; +const char *MI_CHECK_ERROR= "error"; + #ifndef DBUG_OFF /** Causes the thread to wait in a spin lock for a query kill signal. @@ -130,6 +134,20 @@ static handler *myisam_create_handler(handlerton *hton, return new (mem_root) ha_myisam(hton, table); } + +static void mi_check_print(HA_CHECK *param, const char* msg_type, + const char *msgbuf) +{ + if (msg_type == MI_CHECK_INFO) + sql_print_information("%s.%s: %s", param->db_name, param->table_name, + msgbuf); + else if (msg_type == MI_CHECK_WARNING) + sql_print_warning("%s.%s: %s", param->db_name, param->table_name, + msgbuf); + else + sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf); +} + // collect errors printed by mi_check routines static void mi_check_print_msg(HA_CHECK *param, const char* msg_type, @@ -151,16 +169,21 @@ static void mi_check_print_msg(HA_CHECK *param, const char* msg_type, if (!thd->vio_ok()) { - sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf); + mi_check_print(param, msg_type, msgbuf); return; } if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR | T_AUTO_REPAIR)) { - my_message(ER_NOT_KEYFILE, msgbuf, MYF(MY_WME)); + myf flag= 0; + if (msg_type == MI_CHECK_INFO) + flag= ME_NOTE; + else if (msg_type == MI_CHECK_WARNING) + flag= ME_WARNING; + my_message(ER_NOT_KEYFILE, msgbuf, MYF(flag)); if (thd->variables.log_warnings > 2 && ! thd->log_all_errors) - sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf); + mi_check_print(param, msg_type, msgbuf); return; } length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) - @@ -185,7 +208,7 @@ static void mi_check_print_msg(HA_CHECK *param, const char* msg_type, sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n", msgbuf); else if (thd->variables.log_warnings > 2) - sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf); + mi_check_print(param, msg_type, msgbuf); if (param->need_print_msg_lock) mysql_mutex_unlock(¶m->print_msg_mutex); @@ -592,7 +615,7 @@ void mi_check_print_error(HA_CHECK *param, const char *fmt,...) return; va_list args; va_start(args, fmt); - mi_check_print_msg(param, "error", fmt, args); + mi_check_print_msg(param, MI_CHECK_ERROR, fmt, args); va_end(args); } @@ -600,7 +623,7 @@ void mi_check_print_info(HA_CHECK *param, const char *fmt,...) { va_list args; va_start(args, fmt); - mi_check_print_msg(param, "info", fmt, args); + mi_check_print_msg(param, MI_CHECK_INFO, fmt, args); param->note_printed= 1; va_end(args); } @@ -611,7 +634,7 @@ void mi_check_print_warning(HA_CHECK *param, const char *fmt,...) param->out_flag|= O_DATA_LOST; va_list args; va_start(args, fmt); - mi_check_print_msg(param, "warning", fmt, args); + mi_check_print_msg(param, MI_CHECK_WARNING, fmt, args); va_end(args); } @@ -946,7 +969,6 @@ void ha_myisam::setup_vcols_for_repair(HA_CHECK *param) } param->fix_record= compute_vcols; table->use_all_columns(); - table->vcol_set= &table->s->all_set; } void ha_myisam::restore_vcos_after_repair() @@ -1037,6 +1059,15 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) mysql_mutex_unlock(&share->intern_lock); info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE | HA_STATUS_CONST); + /* + Write a 'table is ok' message to error log if table is ok and + we have written to error log that table was getting checked + */ + if (!error && !(table->db_stat & HA_READ_ONLY) && + !mi_is_crashed(file) && thd->error_printed_to_log && + (param->warning_printed || param->error_printed || + param->note_printed)) + mi_check_print_info(param, "Table is fixed"); } } else if (!mi_is_crashed(file) && !thd->killed) @@ -1811,7 +1842,7 @@ bool ha_myisam::check_and_repair(THD *thd) sql_print_information("Making backup of index file %s with extension '%s'", file->s->index_file_name, buff); mi_make_backup_of_index(file, check_opt.start_time, - MYF(MY_WME | ME_JUST_WARNING)); + MYF(MY_WME | ME_WARNING)); } check_opt.flags= (((myisam_recover_options & diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 5f9b5414174..01078c2a264 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -102,6 +102,9 @@ int chk_status(HA_CHECK *param, register MI_INFO *info) { MYISAM_SHARE *share=info->s; + /* Protection for HA_EXTRA_FLUSH */ + mysql_mutex_lock(&share->intern_lock); + if (mi_is_crashed_on_repair(info)) mi_check_print_warning(param, "Table is marked as crashed and last repair failed"); @@ -121,6 +124,7 @@ int chk_status(HA_CHECK *param, register MI_INFO *info) if (param->testflag & T_UPDATE_STATE) param->warning_printed=save; } + mysql_mutex_unlock(&share->intern_lock); return 0; } @@ -4782,7 +4786,7 @@ static int replace_data_file(HA_CHECK *param, MI_INFO *info, File new_file) my_create_backup_name(buff, "", param->backup_time); my_printf_error(ER_GET_ERRMSG, "Making backup of data file %s with extension '%s'", - MYF(ME_JUST_INFO | ME_NOREFRESH), share->data_file_name, + MYF(ME_NOTE | ME_ERROR_LOG), share->data_file_name, buff); } diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c index c10bf61a477..194ad5bf07a 100644 --- a/storage/myisam/mi_extra.c +++ b/storage/myisam/mi_extra.c @@ -332,7 +332,11 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) if (!share->temporary) flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map, FLUSH_KEEP); + mysql_mutex_lock(&share->intern_lock); + /* Tell mi_lock_database() that we locked the intern_lock mutex */ + info->intern_lock_locked= 1; _mi_decrement_open_count(info); + info->intern_lock_locked= 0; if (share->not_flushed) { share->not_flushed=0; @@ -349,6 +353,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) } if (share->base.blobs) mi_alloc_rec_buff(info, -1, &info->rec_buff); + mysql_mutex_unlock(&share->intern_lock); break; case HA_EXTRA_NORMAL: /* Theese isn't in use */ info->quick_mode=0; diff --git a/storage/myisam/mi_info.c b/storage/myisam/mi_info.c index 3b9288eeb83..33ff6abb32d 100644 --- a/storage/myisam/mi_info.c +++ b/storage/myisam/mi_info.c @@ -127,7 +127,7 @@ void mi_report_error(int errcode, const char *file_name) if ((lgt= strlen(file_name)) > 64) file_name+= lgt - 64; - my_error(errcode, MYF(ME_NOREFRESH), file_name); + my_error(errcode, MYF(ME_ERROR_LOG), file_name); DBUG_VOID_RETURN; } diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index b348429fd3c..f3030148044 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -53,7 +53,8 @@ int mi_lock_database(MI_INFO *info, int lock_type) error= 0; DBUG_EXECUTE_IF ("mi_lock_database_failure", error= EINVAL;); - mysql_mutex_lock(&share->intern_lock); + if (!info->intern_lock_locked) + mysql_mutex_lock(&share->intern_lock); if (share->kfile >= 0) /* May only be false on windows */ { switch (lock_type) { @@ -261,7 +262,8 @@ int mi_lock_database(MI_INFO *info, int lock_type) } } #endif - mysql_mutex_unlock(&share->intern_lock); + if (!info->intern_lock_locked) + mysql_mutex_unlock(&share->intern_lock); if (mark_crashed) mi_mark_crashed(info); DBUG_RETURN(error); diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index e350626f192..2f8d52863fc 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -296,6 +296,7 @@ struct st_myisam_info uint preload_buff_size; /* When preloading indexes */ myf lock_wait; /* is 0 or MY_SHORT_WAIT */ my_bool was_locked; /* Was locked in panic */ + my_bool intern_lock_locked; /* locked in mi_extra() */ my_bool append_insert_at_end; /* Set if concurrent insert */ my_bool quick_mode; /* If info->buff can't be used for rnext */ diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c index 4ea1602bec3..f69dd0196b3 100644 --- a/storage/myisam/myisampack.c +++ b/storage/myisam/myisampack.c @@ -2148,7 +2148,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) */ if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2))) { - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATALERROR), + my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATAL), sizeof(uint)*length*2); return 0; } diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index 533f2cd2aa6..aef3c9b42a8 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -28,12 +28,10 @@ /* static variables */ -#undef MYF_RW #undef DISK_BUFFER_SIZE #define MERGEBUFF 15 #define MERGEBUFF2 31 -#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) #define DISK_BUFFER_SIZE (IO_SIZE*128) /* How many keys we can keep in memory */ diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 98ce1180d48..38b33a41565 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -7290,7 +7290,7 @@ int ha_rocksdb::create_cfs( tbl_def_arg->full_tablename().c_str(), table_arg->key_info[i].key_part[part].field->field_name.str); - my_error(ER_INTERNAL_ERROR, MYF(ME_JUST_WARNING), buf); + my_error(ER_INTERNAL_ERROR, MYF(ME_WARNING), buf); } } } @@ -7805,14 +7805,14 @@ int ha_rocksdb::create(const char *const name, TABLE *const table_arg, // The `rocksdb_datadir` setting should be used to configure RocksDB data // directory. print_error(HA_ERR_ROCKSDB_TABLE_DATA_DIRECTORY_NOT_SUPPORTED, - MYF(ME_JUST_WARNING)); + MYF(ME_WARNING)); DBUG_RETURN(HA_WRONG_CREATE_OPTION); } if (create_info->index_file_name) { // Similar check for INDEX DIRECTORY as well. print_error(HA_ERR_ROCKSDB_TABLE_INDEX_DIRECTORY_NOT_SUPPORTED, - MYF(ME_JUST_WARNING)); + MYF(ME_WARNING)); DBUG_RETURN(HA_WRONG_CREATE_OPTION); } diff --git a/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result b/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result index 32c0537c780..de7717b3480 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result @@ -394,30 +394,41 @@ larger larger 1 Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK larger 1 larger 1 Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select 1300 < 1300 * 1.5 as "same"; same @@ -476,6 +487,7 @@ INSERT INTO t1 (a, b) VALUES (4, 20); set global rocksdb_force_flush_memtable_now=1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SHOW INDEX in t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/rocksdb/mysql-test/rocksdb/r/analyze_table.result b/storage/rocksdb/mysql-test/rocksdb/r/analyze_table.result index b666a17c81c..3459b6f189b 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/analyze_table.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/analyze_table.result @@ -5,26 +5,32 @@ CREATE TABLE t2 (pk INT PRIMARY KEY, a INT(11), b CHAR(8)) ENGINE=rocksdb; INSERT INTO t1 VALUES (3,3,'c'); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t2 VALUES (1,4,'d'); ANALYZE NO_WRITE_TO_BINLOG TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK INSERT INTO t1 VALUES (4,5,'e'); INSERT INTO t2 VALUES (2,6,'f'); ANALYZE LOCAL TABLE t1, t2; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK DROP TABLE t1, t2; CREATE TABLE t1 (pk INT PRIMARY KEY, a INT(11), KEY(a)) ENGINE=rocksdb; INSERT INTO t1 VALUES (1,1),(2,2),(3,4),(4,7); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK INSERT INTO t1 VALUES (5,8),(6,10),(7,11),(8,12); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK DROP TABLE t1; # diff --git a/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars_thread_2.result b/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars_thread_2.result index a14ffdec2e3..6bd6cea97de 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars_thread_2.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars_thread_2.result @@ -92,5 +92,7 @@ disconnect con2; disconnect con1; disconnect con0; SELECT * FROM t1 ORDER BY pk INTO OUTFILE <output_file>; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead All pk values matched their expected values DROP TABLE t1; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter4.result b/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter4.result index 1f4d1a641a2..c4a1c5f4668 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter4.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter4.result @@ -20,6 +20,8 @@ END IF; SET id1_cond = id1_cond + 1; END WHILE; END// +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead "Skipping bloom filter" SET session rocksdb_skip_bloom_filter_on_read=1; CALL select_test(); diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result index 21417caf760..51664516bb4 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result @@ -43,8 +43,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL 0 N t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned 0 N ANALYZE TABLE t1, t2, t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK SHOW TABLE STATUS WHERE name LIKE 't%'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result index 484c2a89c3a..fa8546e3e3c 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result @@ -43,8 +43,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL 0 N t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned 0 N ANALYZE TABLE t1, t2, t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK SHOW TABLE STATUS WHERE name LIKE 't%'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result index 35a2845cb42..e3870dc37a8 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result @@ -43,8 +43,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL 0 N t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned 0 N ANALYZE TABLE t1, t2, t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK SHOW TABLE STATUS WHERE name LIKE 't%'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result index 12013539017..5b432aec5da 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result @@ -43,8 +43,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL 0 N t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_bin NULL partitioned 0 N ANALYZE TABLE t1, t2, t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK SHOW TABLE STATUS WHERE name LIKE 't%'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted.result index 444f997bf48..632b3b47eb5 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted.result @@ -80,8 +80,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned 0 N ANALYZE TABLE t1, t2, t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK SHOW TABLE STATUS WHERE name LIKE 't%'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted_rev.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted_rev.result index dea69b3b089..b5a56b21f5e 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted_rev.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted_rev.result @@ -80,8 +80,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned 0 N ANALYZE TABLE t1, t2, t3; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK SHOW TABLE STATUS WHERE name LIKE 't%'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary diff --git a/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result b/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result index d037c636a16..ce29ee04b30 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result @@ -88,6 +88,7 @@ ENGINE=ROCKSDB; SET GLOBAL rocksdb_force_flush_memtable_now = 1; ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK cardinality of the columns after 'a' must be equal to the cardinality of column 'a' SELECT CARDINALITY INTO @c FROM information_schema.statistics WHERE TABLE_NAME='t2' AND INDEX_NAME='c' AND COLUMN_NAME='a'; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/drop_index_inplace.result b/storage/rocksdb/mysql-test/rocksdb/r/drop_index_inplace.result index dfa5c5b2590..44f4af7b30f 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/drop_index_inplace.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/drop_index_inplace.result @@ -139,6 +139,7 @@ INSERT INTO t1 (col1,col2,col3) VALUES (1,2,3); ALTER TABLE t1 ADD KEY idx ( col1, col2 ); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK ALTER TABLE t1 DROP COLUMN col2; ALTER TABLE t1 DROP COLUMN col3; @@ -148,6 +149,7 @@ INSERT INTO t1 (col1,col2,col3) VALUES (1,2,3); ALTER TABLE t1 ADD KEY idx ( col1, col2 ); ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK ALTER TABLE t1 DROP COLUMN col2; ALTER TABLE t1 DROP COLUMN col3; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb.result b/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb.result index 7fb9055083b..7c4f57b61bd 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb.result @@ -28,6 +28,7 @@ insert into t1 values (1, 100, 100), (1, 200, 200), (1, 300, 300); set global rocksdb_force_flush_memtable_now=1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select * from t1 where key1 = 1; id select_type table type possible_keys key key_len ref rows Extra diff --git a/storage/rocksdb/mysql-test/rocksdb/r/misc.result b/storage/rocksdb/mysql-test/rocksdb/r/misc.result index 6087928b80f..b2e5d04f6f8 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/misc.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/misc.result @@ -46,6 +46,8 @@ db User NULL NULL event db NULL NULL event name NULL NULL func name NULL NULL +global_priv Host NULL NULL +global_priv User NULL NULL gtid_slave_pos domain_id NULL NULL gtid_slave_pos sub_id NULL NULL help_category help_category_id NULL NULL @@ -56,8 +58,6 @@ help_relation help_keyword_id NULL NULL help_relation help_topic_id NULL NULL help_topic help_topic_id NULL NULL help_topic name NULL NULL -host Db NULL NULL -host Host NULL NULL index_stats db_name NULL NULL index_stats index_name NULL NULL index_stats prefix_arity NULL NULL @@ -92,5 +92,3 @@ time_zone_transition Time_zone_id NULL NULL time_zone_transition Transition_time NULL NULL time_zone_transition_type Time_zone_id NULL NULL time_zone_transition_type Transition_type_id NULL NULL -user Host NULL NULL -user User NULL NULL diff --git a/storage/rocksdb/mysql-test/rocksdb/r/no_merge_sort.result b/storage/rocksdb/mysql-test/rocksdb/r/no_merge_sort.result index 3a631d2925b..6ea13872033 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/no_merge_sort.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/no_merge_sort.result @@ -1,63 +1,123 @@ Warnings: Note 1051 Unknown table 'test.ti_nk' +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead skip_merge_sort true DROP TABLE ti_nk; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/partition.result b/storage/rocksdb/mysql-test/rocksdb/r/partition.result index 1ba966e9e07..a7f2a6112c1 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/partition.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/partition.result @@ -46,6 +46,7 @@ CREATE TABLE t1 (i INT, j INT, k INT, PRIMARY KEY (i)) ENGINE = ROCKSDB PARTITIO Table Op Msg_type Msg_text test.t1 optimize status OK Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK Table Op Msg_type Msg_text test.t1 repair status OK diff --git a/storage/rocksdb/mysql-test/rocksdb/r/records_in_range.result b/storage/rocksdb/mysql-test/rocksdb/r/records_in_range.result index 89ebe760384..9bbbdec4794 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/records_in_range.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/records_in_range.result @@ -144,7 +144,7 @@ Warnings: Note 1003 select `test`.`t1`.`i` AS `i`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`b` >= 500 and `test`.`t1`.`b` <= 500 explain extended select * from t1 where a< 750 and b> 500 and b< 750; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 range ka,kb ka 5 NULL 1000 100.00 Using index condition; Using where +1 SIMPLE t1 range ka,kb ka 5 NULL 1000 5.00 Using index condition; Using where Warnings: Note 1003 select `test`.`t1`.`i` AS `i`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` < 750 and `test`.`t1`.`b` > 500 and `test`.`t1`.`b` < 750 drop index ka on t1; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_per_partition.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_per_partition.result index 99186153796..24b93ee3395 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_per_partition.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_per_partition.result @@ -350,6 +350,8 @@ cf_name another_cf_for_p5 ANALYZE TABLE t2; Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze Warning Engine-independent statistics are not collected for column 'col5' test.t2 analyze status OK EXPLAIN PARTITIONS SELECT * FROM t2 WHERE col3 = 0x4 AND col2 = 0x34567; id select_type table partitions type possible_keys key key_len ref rows Extra diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_range2.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_range2.result index a925c21e188..bcda9341f1f 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_range2.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_range2.result @@ -1,13 +1,14 @@ create table t1 (id1 bigint, id2 bigint, c1 bigint, c2 bigint, c3 bigint, c4 bigint, c5 bigint, c6 bigint, c7 bigint, primary key (id1, id2), index i(c1, c2)); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK select count(*) from t1; count(*) 10000 explain select c1 from t1 where c1 > 5 limit 10; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range i i 9 NULL # Using where; Using index +1 SIMPLE t1 index i i 18 NULL # Using where; Using index drop table t1; # # MDEV-17414: MyROCKS order desc limit 1 fails diff --git a/storage/rocksdb/mysql-test/rocksdb/r/select.result b/storage/rocksdb/mysql-test/rocksdb/r/select.result index 22a6ca9bc87..2bb2bd636dc 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/select.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/select.result @@ -114,6 +114,8 @@ SELECT t1.a, t2.b FROM t2, t1 WHERE t1.a = t2.a ORDER BY t2.b, t1.a INTO OUTFILE '<DATADIR>/select.out' CHARACTER SET utf8 FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY ''''; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead 200,'bar' 200,'bar' 100,'foobar' @@ -125,8 +127,12 @@ INTO DUMPFILE '<DATADIR>/select.dump'; ERROR 42000: Result consisted of more than one row SELECT t1.*, t2.* FROM t1, t2 ORDER BY t2.b, t1.a, t2.a, t1.b, t1.pk, t2.pk LIMIT 1 INTO DUMPFILE '<DATADIR>/select.dump'; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead 1z2200bar3 SELECT MIN(a), MAX(a) FROM t1 INTO @min, @max; +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead SELECT @min, @max; @min @max 1 200 diff --git a/storage/rocksdb/mysql-test/rocksdb/r/statistics.result b/storage/rocksdb/mysql-test/rocksdb/r/statistics.result index 78344991360..24f3463bf11 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/statistics.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/statistics.result @@ -49,8 +49,11 @@ t2 1 1 t3 1 1 analyze table t1,t2,t3,t4,t5; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected test.t2 analyze status OK +test.t3 analyze status Engine-independent statistics collected test.t3 analyze status OK test.t4 analyze Error Table 'test.t4' doesn't exist test.t4 analyze status Operation failed diff --git a/storage/rocksdb/mysql-test/rocksdb/r/type_decimal.result b/storage/rocksdb/mysql-test/rocksdb/r/type_decimal.result index 7397ff64ab1..668a927669a 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/type_decimal.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/type_decimal.result @@ -25,6 +25,7 @@ insert into t1 select pk+10000, 9.0, 9.0, 'extra-data' from t1; insert into t1 select pk+100000, 9.0, 9.0, 'extra-data' from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # The following can't use index-only: explain select * from t1 where col1 between -8 and 8; @@ -88,6 +89,7 @@ insert into t1 select pk+10000, col1+20000, col2+20000, 'extra-data' from t1; insert into t1 select pk+100000, col1+20000, col2+20000, 'extra-data' from t1; analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK explain select col1, col2 from t1 force index(key1) where col1 between -800 and 800; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result b/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result index a7e086fde66..4c5ef47590a 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result @@ -191,6 +191,7 @@ insert into t1 values (2, 'a', 'a'); insert into t1 values (3, 'a \t', 'a-tab'); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # Must show 'using index' for latin1_bin and utf8_bin: explain @@ -306,6 +307,7 @@ insert into t1 values (2, 'a', 'a'); insert into t1 values (3, 'a \t', 'a-tab'); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # Must show 'using index' for latin1_bin and utf8_bin: explain @@ -421,6 +423,7 @@ insert into t1 values (2, 'a', 'a'); insert into t1 values (3, 'a \t', 'a-tab'); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # Must show 'using index' for latin1_bin and utf8_bin: explain @@ -536,6 +539,7 @@ insert into t1 values (2, 'a', 'a'); insert into t1 values (3, 'a \t', 'a-tab'); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # Must show 'using index' for latin1_bin and utf8_bin: explain @@ -651,6 +655,7 @@ insert into t1 values (2, 'a', 'a'); insert into t1 values (3, 'a \t', 'a-tab'); analyze table t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK # Must show 'using index' for latin1_bin and utf8_bin: explain diff --git a/storage/rocksdb/mysql-test/rocksdb/t/disabled.def b/storage/rocksdb/mysql-test/rocksdb/t/disabled.def index 9fbc0ace0d2..91bf571371e 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/disabled.def +++ b/storage/rocksdb/mysql-test/rocksdb/t/disabled.def @@ -83,3 +83,4 @@ autoinc_debug: Fails with wrong results drop_table: Hangs on shutdown allow_to_start_after_corruption : result difference and assertion failure index_merge_rocksdb2 : result difference +rocksdb_range2 : result difference, update after MDEV-16746 is fixed diff --git a/storage/rocksdb/mysql-test/rocksdb_rpl/r/mdev12179.result b/storage/rocksdb/mysql-test/rocksdb_rpl/r/mdev12179.result index 9c20fea97ae..a1e501f78f4 100644 --- a/storage/rocksdb/mysql-test/rocksdb_rpl/r/mdev12179.result +++ b/storage/rocksdb/mysql-test/rocksdb_rpl/r/mdev12179.result @@ -2,6 +2,7 @@ include/master-slave.inc [connection master] connection server_2; include/stop_slave.inc +SET GLOBAL gtid_cleanup_batch_size = 999999999; CHANGE MASTER TO master_use_gtid=slave_pos; SET sql_log_bin=0; CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos; @@ -41,6 +42,8 @@ a 1 SELECT * FROM mysql.gtid_slave_pos ORDER BY sub_id; domain_id sub_id server_id seq_no +0 1 1 1 +0 2 1 2 0 3 1 3 0 4 1 4 SELECT * FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb @@ -121,6 +124,21 @@ Transactions_multi_engine 6 DELETE FROM t1 WHERE a >= 100; DELETE FROM t2 WHERE a >= 100; DELETE FROM t3 WHERE a >= 100; +connection server_1; +include/save_master_gtid.inc +connection server_2; +include/sync_with_master_gtid.inc +SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos; +COUNT(*)>=10 +1 +SELECT COUNT(*)>=10 FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb +UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select; +COUNT(*)>=10 +1 +SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos_rocksdb; +COUNT(*)>=10 +1 +SET GLOBAL gtid_cleanup_batch_size = 3; connection server_2; include/stop_slave.inc SET sql_log_bin=0; diff --git a/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test b/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test index e0d16e7f242..631d9ca533f 100644 --- a/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test +++ b/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test @@ -4,6 +4,12 @@ --connection server_2 --source include/stop_slave.inc + +# Set GTID cleanup limit high enough that cleanup will not run and we +# can rely on consistent table output in .result. +--let $old_gtid_cleanup_batch_size=`SELECT @@GLOBAL.gtid_cleanup_batch_size` +SET GLOBAL gtid_cleanup_batch_size = 999999999; + CHANGE MASTER TO master_use_gtid=slave_pos; SET sql_log_bin=0; CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos; @@ -89,6 +95,82 @@ DELETE FROM t2 WHERE a >= 100; DELETE FROM t3 WHERE a >= 100; +# Create a bunch more GTIDs in mysql.gtid_slave_pos* tables to test with. +--connection server_1 +--disable_query_log +let $i=10; +while ($i) { + eval INSERT INTO t1 VALUES (300+$i); + eval INSERT INTO t2 VALUES (300+$i); + eval INSERT INTO t3 VALUES (300+$i); + dec $i; +} +--enable_query_log +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +# Check that we have many rows in mysql.gtid_slave_pos now (since +# @@gtid_cleanup_batch_size was set to a huge value). No need to check +# for an exact number, since that will require changing .result if +# anything changes prior to this point, and we just need to know that +# we have still have some data in the tables to make the following +# test effective. +SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos; +SELECT COUNT(*)>=10 FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb + UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select; +SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos_rocksdb; + +# Check that old GTID rows will be deleted when batch delete size is +# set reasonably. Old row deletion is not 100% deterministic (by design), so +# we must wait for it to occur, but it should occur eventually. +SET GLOBAL gtid_cleanup_batch_size = 3; +let $i=40; +--disable_query_log +--let $keep_include_silent=1 +while ($i) { + let N=`SELECT 1+($i MOD 3)`; + --connection server_1 + eval UPDATE t$N SET a=a+1 WHERE a=(SELECT MAX(a) FROM t$N); + --source include/save_master_gtid.inc + --connection server_2 + --source include/sync_with_master_gtid.inc + let $j=50; + while ($j) { + let $is_done=`SELECT SUM(a)=1 FROM ( + SELECT COUNT(*) AS a FROM mysql.gtid_slave_pos + UNION ALL + SELECT COUNT(*) AS a FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb + UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select + UNION ALL + SELECT COUNT(*) AS a FROM mysql.gtid_slave_pos_rocksdb) outer_select`; + if ($is_done) { + let $j=0; + } + if (!$is_done) { + real_sleep 0.1; + dec $j; + } + } + dec $i; + if ($is_done) { + let $i=0; + } +} +--enable_query_log +--let $keep_include_silent=0 +if (!$is_done) { + --echo Timed out waiting for mysql.gtid_slave_pos* tables to be cleaned up +} + +--disable_query_log +DELETE FROM t1 WHERE a >= 100; +DELETE FROM t2 WHERE a >= 100; +DELETE FROM t3 WHERE a >= 100; +--enable_query_log + + # Test status variables Rpl_transactions_multi_engine and Transactions_gtid_foreign_engine. # Have mysql.gtid_slave_pos* for myisam and innodb but not rocksdb. --connection server_2 @@ -223,6 +305,9 @@ SHOW STATUS LIKE "%transactions%engine"; SET sql_log_bin=0; DROP TABLE mysql.gtid_slave_pos_innodb; SET sql_log_bin=1; +--disable_query_log +eval SET GLOBAL gtid_cleanup_batch_size = $old_gtid_cleanup_batch_size; +--enable_query_log --connection server_1 DROP TABLE t1; diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index 90409213843..86332a741c6 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -2746,7 +2746,9 @@ const Item * ha_sphinx::cond_push ( const Item *cond ) if ( !m_pShare->m_bSphinxQL ) { // on non-QL tables, intercept query=value condition for SELECT - if (!( args[0]->type()==Item::FIELD_ITEM && args[1]->type()==Item::STRING_ITEM )) + if (!( args[0]->type()==Item::FIELD_ITEM && + args[1]->is_of_type(Item::CONST_ITEM, + STRING_RESULT))) break; Item_field * pField = (Item_field *) args[0]; @@ -2762,7 +2764,9 @@ const Item * ha_sphinx::cond_push ( const Item *cond ) } else { - if (!( args[0]->type()==Item::FIELD_ITEM && args[1]->type()==Item::INT_ITEM )) + if (!( args[0]->type()==Item::FIELD_ITEM && + args[1]->is_of_type(Item::CONST_ITEM, + INT_RESULT))) break; // on QL tables, intercept id=value condition for DELETE diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index bd302f155d2..92b7d2c2ac1 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -9392,8 +9392,8 @@ ulonglong ha_spider::table_flags() const HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_PARTIAL_COLUMN_READ | -#ifdef HA_CMP_REF_IS_EXPENSIVE - HA_CMP_REF_IS_EXPENSIVE | +#ifdef HA_SLOW_CMP_REF + HA_SLOW_CMP_REF | #endif #ifdef SPIDER_ENGINE_CONDITION_PUSHDOWN_IS_ALWAYS_ON HA_CAN_TABLE_CONDITION_PUSHDOWN | @@ -13526,7 +13526,7 @@ void ha_spider::check_pre_call( ) || ( (skip_parallel_search & 2) && - select_lex && select_lex->sql_cache == SELECT_LEX::SQL_NO_CACHE // for mysqldump + thd->lex->sql_cache == LEX::SQL_NO_CACHE // for mysqldump ) ) { use_pre_call = FALSE; diff --git a/storage/spider/mysql-test/spider/include/init_spider.inc b/storage/spider/mysql-test/spider/include/init_spider.inc index c4d171d418e..1da1ec970b5 100644 --- a/storage/spider/mysql-test/spider/include/init_spider.inc +++ b/storage/spider/mysql-test/spider/include/init_spider.inc @@ -103,10 +103,17 @@ if (!$VERSION_COMPILE_OS_WIN) ); } +let $SERVER_NAME= + `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(version(), '-', 2), '-', -1)`; +let $SERVER_MAJOR_VERSION= + `SELECT SUBSTRING_INDEX(version(), '.', 1)`; +let $SERVER_MINOR_VERSION= + `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(version(), '.', 2), '.', -1)`; let $PLUGIN_VERSION= `SELECT SUBSTRING_INDEX(plugin_version, '.', 1) FROM information_schema.plugins WHERE plugin_name = 'SPIDER'`; + if (`SELECT IF($PLUGIN_VERSION = 1, 1, 0)`) { DROP TABLE IF EXISTS mysql.spider_xa; @@ -245,7 +252,16 @@ if (`SELECT IF($PLUGIN_VERSION = 2, 1, 0)`) } if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) { + let $ENGINE_NAME= + `SELECT IF (STRCMP('$SERVER_NAME', 'MariaDB') = 0, + IF ($SERVER_MAJOR_VERSION = 10, + IF ($SERVER_MINOR_VERSION < 4, 'MyISAM', + 'Aria transactional=1'), + IF ($SERVER_MAJOR_VERSION < 10, 'MyISAM', + 'Aria transactional=1')), + 'MyISAM')`; DROP TABLE IF EXISTS mysql.spider_xa; + eval CREATE TABLE mysql.spider_xa( format_id int not null default 0, gtrid_length int not null default 0, @@ -254,8 +270,9 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) status char(8) not null default '', PRIMARY KEY (data, format_id, gtrid_length), KEY idx1 (status) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_xa_member; + eval CREATE TABLE mysql.spider_xa_member( format_id int not null default 0, gtrid_length int not null default 0, @@ -276,8 +293,9 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) default_file text default null, default_group char(64) default null, KEY idx1 (data, format_id, gtrid_length, host) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_xa_failed_log; + eval CREATE TABLE mysql.spider_xa_failed_log( format_id int not null default 0, gtrid_length int not null default 0, @@ -301,8 +319,9 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) status char(8) not null default '', failed_time timestamp not null default current_timestamp, key idx1 (data, format_id, gtrid_length, host) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_tables; + eval CREATE TABLE mysql.spider_tables( db_name char(64) not null default '', table_name char(199) not null default '', @@ -332,8 +351,9 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) PRIMARY KEY (db_name, table_name, link_id), KEY idx1 (priority), UNIQUE KEY uidx1 (db_name, table_name, static_link_id) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_link_mon_servers; + eval CREATE TABLE mysql.spider_link_mon_servers( db_name char(64) not null default '', table_name char(199) not null default '', @@ -355,15 +375,17 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) default_file text default null, default_group char(64) default null, PRIMARY KEY (db_name, table_name, link_id, sid) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_link_failed_log; + eval CREATE TABLE mysql.spider_link_failed_log( db_name char(64) not null default '', table_name char(199) not null default '', link_id char(64) not null default '', failed_time timestamp not null default current_timestamp - ) ENGINE=MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_table_position_for_recovery; + eval CREATE TABLE mysql.spider_table_position_for_recovery( db_name char(64) not null default '', table_name char(199) not null default '', @@ -373,8 +395,9 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) position text, gtid text, primary key (db_name, table_name, failed_link_id, source_link_id) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_table_sts; + eval CREATE TABLE mysql.spider_table_sts( db_name char(64) not null default '', table_name char(199) not null default '', @@ -387,15 +410,16 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) create_time datetime not null default '0000-00-00 00:00:00', update_time datetime not null default '0000-00-00 00:00:00', primary key (db_name, table_name) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_table_crd; + eval CREATE TABLE mysql.spider_table_crd( db_name char(64) not null default '', table_name char(199) not null default '', key_seq int unsigned not null default 0, cardinality bigint not null default 0, primary key (db_name, table_name, key_seq) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; } SET spider_internal_sql_log_off= 0; diff --git a/storage/spider/mysql-test/spider/r/show_system_tables.result b/storage/spider/mysql-test/spider/r/show_system_tables.result new file mode 100644 index 00000000000..67411862e00 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/show_system_tables.result @@ -0,0 +1,37 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +Show system tables on the Spider node +connection master_1; +SELECT table_name, engine FROM information_schema.tables +WHERE table_schema = 'mysql' AND table_name like '%spider_%'; +table_name engine +spider_link_failed_log Aria +spider_link_mon_servers Aria +spider_table_crd Aria +spider_table_position_for_recovery Aria +spider_table_sts Aria +spider_tables Aria +spider_xa Aria +spider_xa_failed_log Aria +spider_xa_member Aria + +deinit +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/t/show_system_tables.test b/storage/spider/mysql-test/spider/t/show_system_tables.test new file mode 100644 index 00000000000..ae8259b01bc --- /dev/null +++ b/storage/spider/mysql-test/spider/t/show_system_tables.test @@ -0,0 +1,26 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings + +--echo +--echo Show system tables on the Spider node +--connection master_1 +--sorted_result +SELECT table_name, engine FROM information_schema.tables + WHERE table_schema = 'mysql' AND table_name like '%spider_%'; + +--echo +--echo deinit +--disable_warnings +--disable_query_log +--disable_result_log +--source test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings +--echo +--echo end of test diff --git a/storage/spider/scripts/install_spider.sql b/storage/spider/scripts/install_spider.sql index c5a86caa219..9b2e5c480ab 100644 --- a/storage/spider/scripts/install_spider.sql +++ b/storage/spider/scripts/install_spider.sql @@ -400,6 +400,71 @@ begin alter table mysql.spider_table_crd modify table_name char(199) not null default ''; end if; + + -- Fix for MariaDB 10.4: Crash-Safe system tables + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_link_failed_log'; + if @engine_name != 'Aria' then + alter table mysql.spider_link_failed_log + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_link_mon_servers'; + if @engine_name != 'Aria' then + alter table mysql.spider_link_mon_servers + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_table_crd'; + if @engine_name != 'Aria' then + alter table mysql.spider_table_crd + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_table_position_for_recovery'; + if @engine_name != 'Aria' then + alter table mysql.spider_table_position_for_recovery + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_table_sts'; + if @engine_name != 'Aria' then + alter table mysql.spider_table_sts + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_tables'; + if @engine_name != 'Aria' then + alter table mysql.spider_tables + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_xa'; + if @engine_name != 'Aria' then + alter table mysql.spider_xa + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_xa_failed_log'; + if @engine_name != 'Aria' then + alter table mysql.spider_xa_failed_log + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_xa_member'; + if @engine_name != 'Aria' then + alter table mysql.spider_xa_member + engine=Aria transactional=1; + end if; end;// delimiter ; call mysql.spider_fix_system_tables; diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index ac5701a8274..7ac1b050d76 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -8560,16 +8560,6 @@ int spider_db_print_item_type(Item *item, Field *field, ha_spider *spider, case Item::ROW_ITEM: DBUG_RETURN(spider_db_open_item_row((Item_row *) item, spider, str, alias, alias_length, dbton_id, use_fields, fields)); - case Item::STRING_ITEM: - DBUG_RETURN(spider_db_open_item_string(item, field, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); - case Item::INT_ITEM: - case Item::REAL_ITEM: - case Item::DECIMAL_ITEM: - DBUG_RETURN(spider_db_open_item_int(item, field, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); case Item::CACHE_ITEM: DBUG_RETURN(spider_db_open_item_cache((Item_cache *) item, field, spider, str, alias, alias_length, @@ -8586,6 +8576,26 @@ int spider_db_print_item_type(Item *item, Field *field, ha_spider *spider, case Item::EXPR_CACHE_ITEM: #endif DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); + case Item::CONST_ITEM: + { + switch (item->cmp_type()) + { + case STRING_RESULT: + case TIME_RESULT: + DBUG_RETURN(spider_db_open_item_string(item, field, spider, str, + alias, alias_length, dbton_id, + use_fields, fields)); + case INT_RESULT: + case REAL_RESULT: + case DECIMAL_RESULT: + DBUG_RETURN(spider_db_open_item_int(item, field, spider, str, + alias, alias_length, dbton_id, + use_fields, fields)); + default: + DBUG_ASSERT(FALSE); + /* Fall through */ + } + } default: THD *thd = spider->trx->thd; SPIDER_SHARE *share = spider->share; @@ -9102,7 +9112,6 @@ int spider_db_open_item_int(Item *item, Field *field, ha_spider *spider, { THD *thd = NULL; TABLE *table; - bool print_quoted_string; my_bitmap_map *saved_map; Time_zone *saved_time_zone; char tmp_buf[MAX_FIELD_WIDTH]; @@ -9131,31 +9140,17 @@ int spider_db_open_item_int(Item *item, Field *field, ha_spider *spider, item->save_in_field(field, FALSE); saved_time_zone = thd->variables.time_zone; thd->variables.time_zone = UTC; - print_quoted_string = TRUE; - } - else - { -#ifdef SPIDER_ITEM_HAS_CMP_TYPE - DBUG_PRINT("info", ("spider cmp_type=%u", item->cmp_type())); - if (item->cmp_type() == TIME_RESULT) - print_quoted_string = TRUE; - else -#endif - print_quoted_string = FALSE; } - if (print_quoted_string) + if (thd) { - if (thd) - { - /* Retrieve the stored value converted to UTC */ - tmp_str2 = field->val_str(&str_value); + /* Retrieve the stored value converted to UTC */ + tmp_str2 = field->val_str(&str_value); - if (!tmp_str2) - { - error_num = HA_ERR_OUT_OF_MEM; - goto error; - } + if (!tmp_str2) + { + error_num = HA_ERR_OUT_OF_MEM; + goto error; } if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 + tmp_str2->length())) diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index ada9aa20821..3af7c424c3d 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -618,6 +618,15 @@ SPIDER_DB_ROW *spider_db_mysql_result::fetch_row_from_tmp_table( DBUG_RETURN((SPIDER_DB_ROW *) &row); } + +static my_bool str_to_datetime(const char *str, size_t length, + MYSQL_TIME *l_time, + ulonglong flags, MYSQL_TIME_STATUS *status) +{ + return str_to_datetime_or_date(str, length, l_time, flags, status); +} + + int spider_db_mysql_result::fetch_table_status( int mode, ha_rows &records, @@ -7276,16 +7285,16 @@ int spider_mysql_handler::append_select( if (result_list->lock_type != F_WRLCK && spider->lock_mode < 1) { /* no lock */ - st_select_lex *select_lex = &spider->trx->thd->lex->select_lex; + LEX *lex = spider->trx->thd->lex; if ( - select_lex->sql_cache == SELECT_LEX::SQL_CACHE && + lex->sql_cache == LEX::SQL_CACHE && (spider->share->query_cache_sync & 1) ) { if (str->reserve(SPIDER_SQL_SQL_CACHE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_SQL_CACHE_STR, SPIDER_SQL_SQL_CACHE_LEN); } else if ( - select_lex->sql_cache == SELECT_LEX::SQL_NO_CACHE && + lex->sql_cache == LEX::SQL_NO_CACHE && (spider->share->query_cache_sync & 2) ) { if (str->reserve(SPIDER_SQL_SQL_NO_CACHE_LEN)) diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index ed25e4fcf32..e64b5173b9a 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -2386,7 +2386,7 @@ void spider_get_sys_table_sts_info( *index_file_length = (ulonglong) table->field[4]->val_int(); *records = (ha_rows) table->field[5]->val_int(); *mean_rec_length = (ulong) table->field[6]->val_int(); - table->field[7]->get_date(&mysql_time, 0); + table->field[7]->get_date(&mysql_time, date_mode_t(0)); #ifdef MARIADB_BASE_VERSION *check_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -2394,7 +2394,7 @@ void spider_get_sys_table_sts_info( *check_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_my_bool); #endif - table->field[8]->get_date(&mysql_time, 0); + table->field[8]->get_date(&mysql_time, date_mode_t(0)); #ifdef MARIADB_BASE_VERSION *create_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -2402,7 +2402,7 @@ void spider_get_sys_table_sts_info( *create_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_my_bool); #endif - table->field[9]->get_date(&mysql_time, 0); + table->field[9]->get_date(&mysql_time, date_mode_t(0)); #ifdef MARIADB_BASE_VERSION *update_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 1940dd5aad9..2e3705f04ee 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -9048,8 +9048,14 @@ int spider_set_direct_limit_offset( ) DBUG_RETURN(FALSE); + /* + TODO: following comment is wrong or the check is wrong (correct + check for derived table will be something like select_lex->linkage, + if they need only top level it is better to check nested level and do + not loose UNIONS & Co + */ // must not be derived table - if (&thd->lex->select_lex != select_lex) + if (thd->lex->first_select_lex() != select_lex) DBUG_RETURN(FALSE); spider->direct_select_offset = offset_limit; diff --git a/storage/tokudb/PerconaFT/portability/toku_crash.cc b/storage/tokudb/PerconaFT/portability/toku_crash.cc index 0af85342a99..297cc29d9ca 100644 --- a/storage/tokudb/PerconaFT/portability/toku_crash.cc +++ b/storage/tokudb/PerconaFT/portability/toku_crash.cc @@ -70,7 +70,7 @@ run_gdb(pid_t parent_pid, const char *gdb_path) { "-ex", "thread apply all bt", "-ex", "thread apply all bt full", exe_buf, pid_buf, - NULL); + (char*) NULL); } static void diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result index c7450a1b9c0..aea5bab7cf3 100644 --- a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result +++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result @@ -51,6 +51,10 @@ DELETE FROM test.regular_tbl WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE PROCEDURE test.proc_bykey() BEGIN DECLARE ins_count INT DEFAULT 1000; @@ -72,6 +76,10 @@ DELETE FROM test.bykey_tbl WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CREATE PROCEDURE test.proc_byrange() BEGIN DECLARE ins_count INT DEFAULT 1000; @@ -93,6 +101,10 @@ DELETE FROM test.byrange_tbl WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL test.proc_norm(); SELECT count(*) as "Master regular" FROM test.regular_tbl; Master regular 500 diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result index f3ffc908504..912b05216da 100644 --- a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result +++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result @@ -26,6 +26,10 @@ DELETE FROM test.regular_tbl WHERE id = del_count; SET del_count = del_count - 2; END WHILE; END| +Warnings: +Level Warning +Code 1287 +Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead CALL test.proc_norm(); connection slave; connection master; diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result index 65057791b48..df3ea1d6de6 100644 --- a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result +++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result @@ -484,77 +484,78 @@ SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; ******************** CREATE USER ******************** CREATE USER 'user_test_rpl'@'localhost' IDENTIFIED BY PASSWORD '*1111111111111111111111111111111111111111'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 N +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 N +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N connection master; ******************** GRANT ******************** GRANT SELECT ON *.* TO 'user_test_rpl'@'localhost'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 Y +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 Y connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 Y +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 Y connection master; ******************** REVOKE ******************** REVOKE SELECT ON *.* FROM 'user_test_rpl'@'localhost'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 N +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv -localhost user_test_rpl *1111111111111111111111111111111111111111 N +Host User Password plugin authentication_string Select_priv +localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N connection master; ******************** SET PASSWORD ******************** SET PASSWORD FOR 'user_test_rpl'@'localhost' = '*0000000000000000000000000000000000000000'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv localhost user_test_rpl *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv localhost user_test_rpl *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N connection master; ******************** RENAME USER ******************** RENAME USER 'user_test_rpl'@'localhost' TO 'user_test_rpl_2'@'localhost'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv localhost user_test_rpl_2 *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv localhost user_test_rpl_2 *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N connection master; ******************** DROP USER ******************** DROP USER 'user_test_rpl_2'@'localhost'; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv connection slave; USE test_rpl; SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%'; -host user password plugin authentication_string select_priv +Host User Password plugin authentication_string Select_priv connection master; INSERT INTO t1 VALUES(100, 'test'); ******************** ANALYZE ******************** ANALYZE TABLE t1; Table Op Msg_type Msg_text +test_rpl.t1 analyze status Engine-independent statistics collected test_rpl.t1 analyze status OK ******************** CHECK TABLE ******************** @@ -679,7 +680,6 @@ DROP TRIGGER tr1; ******************** EVENTS ******************** -GRANT EVENT ON *.* TO 'root'@'localhost'; INSERT INTO t1 VALUES(1, 'test1'); CREATE EVENT e1 ON SCHEDULE EVERY '1' SECOND COMMENT 'e_second_comment' DO DELETE FROM t1; SHOW EVENTS; @@ -1101,8 +1101,6 @@ master-bin.000001 # Query # # use `test_rpl`; DELETE FROM t2 master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Gtid # # GTID #-#-# master-bin.000001 # Query # # use `test_rpl`; DROP TRIGGER tr1 -master-bin.000001 # Gtid # # GTID #-#-# -master-bin.000001 # Query # # use `test_rpl`; GRANT EVENT ON *.* TO 'root'@'localhost' master-bin.000001 # Gtid # # BEGIN GTID #-#-# master-bin.000001 # Query # # use `test_rpl`; INSERT INTO t1 VALUES(1, 'test1') master-bin.000001 # Xid # # COMMIT /* XID */ diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result index 593f177569f..e0b6b615bb6 100644 --- a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result +++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result @@ -24,6 +24,10 @@ unix_timestamp()-@tstart <= 10 connection slave; connection master; include/diff_tables.inc [master:test.t, slave:test.t] +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead +Warnings: +Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead connection master; drop table if exists t; connection slave; diff --git a/storage/tokudb/mysql-test/tokudb/r/card_add_drop.result b/storage/tokudb/mysql-test/tokudb/r/card_add_drop.result index 71a39eb1f3e..fe87a8e2ed6 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_add_drop.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_add_drop.result @@ -9,6 +9,7 @@ tt 1 b 1 b A 4 NULL NULL YES BTREE tt 1 c 1 c A 4 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -23,6 +24,7 @@ tt 1 c 1 c A 4 NULL NULL YES BTREE tt 1 d 1 d A 4 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_add_index.result b/storage/tokudb/mysql-test/tokudb/r/card_add_index.result index 9a929b19a80..c32b4522460 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_add_index.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_add_index.result @@ -7,6 +7,7 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par tt 0 PRIMARY 1 a A 4 NULL NULL BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -18,6 +19,7 @@ tt 0 PRIMARY 1 a A 4 NULL NULL BTREE tt 1 b 1 b A 4 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -31,6 +33,7 @@ tt 1 b 1 b A 2 NULL NULL YES BTREE tt 1 c 1 c A 4 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_drop_index.result b/storage/tokudb/mysql-test/tokudb/r/card_drop_index.result index 2cfdfe11296..ac2979ab057 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_drop_index.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_drop_index.result @@ -9,6 +9,7 @@ tt 1 b 1 b A 4 NULL NULL YES BTREE tt 1 c 1 c A 4 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_drop_index_2.result b/storage/tokudb/mysql-test/tokudb/r/card_drop_index_2.result index ed28d2a3226..2a65b6f0982 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_drop_index_2.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_drop_index_2.result @@ -136,6 +136,7 @@ tt 1 b 1 b A 500 NULL NULL YES BTREE tt 1 c 1 c A 500 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_drop_pk.result b/storage/tokudb/mysql-test/tokudb/r/card_drop_pk.result index 2369d88c274..1b562ad6ac9 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_drop_pk.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_drop_pk.result @@ -9,6 +9,7 @@ tt 1 b 1 b A 4 NULL NULL YES BTREE tt 1 c 1 c A 4 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_no_keys.result b/storage/tokudb/mysql-test/tokudb/r/card_no_keys.result index 1302cfaf252..a96f3edd4b8 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_no_keys.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_no_keys.result @@ -6,6 +6,7 @@ show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_pk.result b/storage/tokudb/mysql-test/tokudb/r/card_pk.result index b0317507f7c..173fb696d69 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_pk.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_pk.result @@ -7,6 +7,7 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par tt 0 PRIMARY 1 a A 4 NULL NULL BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_pk_2.result b/storage/tokudb/mysql-test/tokudb/r/card_pk_2.result index 3c1b652db15..a5434968b0d 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_pk_2.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_pk_2.result @@ -8,6 +8,7 @@ tt 0 PRIMARY 1 a A 4 NULL NULL BTREE tt 0 PRIMARY 2 b A 4 NULL NULL BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_pk_sk.result b/storage/tokudb/mysql-test/tokudb/r/card_pk_sk.result index 02c8d1f8218..6c6f72be4a6 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_pk_sk.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_pk_sk.result @@ -1007,6 +1007,7 @@ tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE tt 1 b 1 b A 4000 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -2025,6 +2026,7 @@ tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE tt 1 b 1 b A 4000 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result b/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result index 981433fac91..a452be2006a 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result @@ -1,5 +1,6 @@ analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK set global tokudb_cardinality_scale_percent = 10; show indexes from tt; diff --git a/storage/tokudb/mysql-test/tokudb/r/card_sk.result b/storage/tokudb/mysql-test/tokudb/r/card_sk.result index 310fc863a9b..19b98092a7b 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_sk.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_sk.result @@ -8,6 +8,7 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par tt 1 b 1 b A 8 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_sk_2.result b/storage/tokudb/mysql-test/tokudb/r/card_sk_2.result index 8ff57b63e5d..950fdaf7850 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_sk_2.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_sk_2.result @@ -8,6 +8,7 @@ tt 1 a 1 a A 4 NULL NULL YES BTREE tt 1 a 2 b A 4 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/card_unique_sk.result b/storage/tokudb/mysql-test/tokudb/r/card_unique_sk.result index cbcab7bdc44..22b0733a933 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_unique_sk.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_unique_sk.result @@ -7,6 +7,7 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par tt 0 a 1 a A 4 NULL NULL YES BTREE analyze table tt; Table Op Msg_type Msg_text +test.tt analyze status Engine-independent statistics collected test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result index a80e1664663..2a0ee4fa3e1 100644 --- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result +++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result @@ -1,7 +1,7 @@ drop table if exists t; select @@optimizer_switch; @@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb; insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4); explain select x,id from t force index (x) where x=0 and id=0; diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result index 96d681407fe..4580cc96404 100644 --- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result +++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result @@ -1,7 +1,7 @@ drop table if exists t; select @@optimizer_switch; @@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb; insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4); explain select x,id from t force index (x) where x=0 and id=0; diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result index 43737c7753e..fb998e3a6ad 100644 --- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result +++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result @@ -1,7 +1,7 @@ drop table if exists t; select @@optimizer_switch; @@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb; insert into t values (0,0,0,0),(0,1,0,1); explain select c,a,b from t where c=0 and a=0 and b=1; diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result index 1dcb1ee1b8b..9d9fb4ca079 100644 --- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result +++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result @@ -1,7 +1,7 @@ drop table if exists t; select @@optimizer_switch; @@optimizer_switch -index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on +index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb; insert into t values (0,0,0,0),(0,1,0,1); explain select c,a,b from t where c=0 and a=0 and b=1; diff --git a/storage/tokudb/mysql-test/tokudb/r/type_datetime.result b/storage/tokudb/mysql-test/tokudb/r/type_datetime.result index ed980f8cee1..dbe93b37271 100644 --- a/storage/tokudb/mysql-test/tokudb/r/type_datetime.result +++ b/storage/tokudb/mysql-test/tokudb/r/type_datetime.result @@ -363,7 +363,7 @@ greatest(cast('01-01-01' as date), '01-01-02') + 0 20010102 select least(cast('01-01-01' as datetime), '01-01-02') + 0; least(cast('01-01-01' as datetime), '01-01-02') + 0 -20010101000000.000000 +20010101000000 select cast(least(cast('01-01-01' as datetime), '01-01-02') as signed); cast(least(cast('01-01-01' as datetime), '01-01-02') as signed) 20010101000000 @@ -401,7 +401,7 @@ if(@bug28261 = f1, '', @bug28261:= f1) 2001-01-01 2002-02-02 Warnings: -Warning 1292 Incorrect datetime value: '' +Warning 1292 Truncated incorrect datetime value: '' select if(@bug28261 = f1, '', @bug28261:= f1) from t1; if(@bug28261 = f1, '', @bug28261:= f1) 2001-01-01 @@ -425,11 +425,11 @@ f1 2001-01-01 00:00:00 2002-02-02 00:00:00 Warnings: -Warning 1292 Incorrect datetime value: '2002010' +Warning 1292 Truncated incorrect datetime value: '2002010' select * from t1 where f1 between 20020101 and 2007010100000; f1 Warnings: -Warning 1292 Incorrect datetime value: '2007010100000' +Warning 1292 Truncated incorrect datetime value: '2007010100000' drop table t1; # # Bug#27216: functions with parameters of different date types may @@ -500,7 +500,7 @@ f1 45:44:44 15:44:44 Warnings: -Warning 1292 Incorrect datetime value: '1' +Warning 1292 Truncated incorrect datetime value: '1' drop table t1; create table t1 (a tinyint); insert into t1 values (), (), (); diff --git a/storage/tokudb/mysql-test/tokudb/r/type_varchar.result b/storage/tokudb/mysql-test/tokudb/r/type_varchar.result index bf98e12ce16..881a4cd66ac 100644 --- a/storage/tokudb/mysql-test/tokudb/r/type_varchar.result +++ b/storage/tokudb/mysql-test/tokudb/r/type_varchar.result @@ -13,7 +13,7 @@ t1 CREATE TABLE `t1` ( show create table vchar; Table Create Table vchar CREATE TABLE `vchar` ( - `v` varchar(30) DEFAULT NULL, + `v` varchar(30)/*old*/ DEFAULT NULL, `c` char(3) DEFAULT NULL, `e` enum('abc','def','ghi') DEFAULT NULL, `t` text DEFAULT NULL diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash.result index 70bc86e1abc..65b79f136a9 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash.result +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash.result @@ -13,6 +13,7 @@ t 0 PRIMARY 1 id A 6 NULL NULL BTREE t 1 x 1 x A 6 NULL NULL YES BTREE analyze table t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1.result index b6d9fd7da85..f62e90bdecf 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1.result +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1.result @@ -12,6 +12,7 @@ t 0 PRIMARY 1 id A 4 NULL NULL BTREE t 1 x 1 x A 4 NULL NULL YES BTREE analyze table t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result index caaa963c325..7609a5a1504 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result @@ -13,6 +13,7 @@ t 0 PRIMARY 1 id A 7 NULL NULL BTREE t 1 x 1 x A 7 NULL NULL YES BTREE analyze table t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2.result index 6d345d98c95..39c59f51b3c 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2.result +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2.result @@ -12,6 +12,7 @@ t 0 PRIMARY 1 id A 4 NULL NULL BTREE t 1 x 1 x A 4 NULL NULL YES BTREE analyze table t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2_pick.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2_pick.result index 06639c311cf..406d4da8d37 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2_pick.result +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2_pick.result @@ -13,6 +13,7 @@ t 0 PRIMARY 1 id A 7 NULL NULL BTREE t 1 x 1 x A 7 NULL NULL YES BTREE analyze table t; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db757_part_alter_analyze.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db757_part_alter_analyze.result index 62337802688..e839d5fd527 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/r/db757_part_alter_analyze.result +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db757_part_alter_analyze.result @@ -11,6 +11,7 @@ t 1 x 1 x A 5 NULL NULL YES BTREE t 1 y 1 y A 5 NULL NULL YES BTREE alter table t analyze partition p0; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -19,6 +20,7 @@ t 1 x 1 x A 5 NULL NULL YES BTREE t 1 y 1 y A 5 NULL NULL YES BTREE alter table t analyze partition p1; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -29,10 +31,11 @@ insert into t values (100,1,1),(200,2,1),(300,3,1),(400,4,1),(500,5,1); show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment t 0 PRIMARY 1 id A 9 NULL NULL BTREE -t 1 x 1 x A 9 NULL NULL YES BTREE +t 1 x 1 x A 2 NULL NULL YES BTREE t 1 y 1 y A 9 NULL NULL YES BTREE alter table t analyze partition p0; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment @@ -41,6 +44,7 @@ t 1 x 1 x A 9 NULL NULL YES BTREE t 1 y 1 y A 9 NULL NULL YES BTREE alter table t analyze partition p1; Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_debug_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_debug_tokudb.result index af3aaddca7c..125155bad9f 100644 --- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_debug_tokudb.result +++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_debug_tokudb.result @@ -20,6 +20,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -45,9 +46,11 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -79,6 +82,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -106,9 +110,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -140,6 +146,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -167,9 +174,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -201,6 +210,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -228,9 +238,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -262,6 +274,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -289,9 +302,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -323,6 +338,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -350,9 +366,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -384,6 +402,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -411,9 +430,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -445,6 +466,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -472,9 +494,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -507,6 +531,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -532,9 +557,11 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -567,6 +594,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -592,9 +620,11 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -628,6 +658,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -653,6 +684,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -683,6 +715,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -709,6 +742,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -741,6 +775,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -766,6 +801,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -796,6 +832,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -822,6 +859,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -854,6 +892,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -879,6 +918,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -909,6 +949,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -935,6 +976,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -967,6 +1009,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -992,6 +1035,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1022,6 +1066,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1048,6 +1093,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1080,6 +1126,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1105,6 +1152,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1135,6 +1183,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1161,6 +1210,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1193,6 +1243,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1218,6 +1269,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1248,6 +1300,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1274,6 +1327,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1306,6 +1360,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1331,6 +1386,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1361,6 +1417,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1387,6 +1444,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1419,6 +1477,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1444,6 +1503,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1475,6 +1535,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1501,6 +1562,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1534,6 +1596,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1559,6 +1622,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1590,6 +1654,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1616,6 +1681,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1649,6 +1715,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1674,6 +1741,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1705,6 +1773,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1731,6 +1800,7 @@ ALTER TABLE t1 ADD PARTITION (PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1765,6 +1835,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1789,9 +1860,11 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1823,6 +1896,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1849,9 +1923,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1883,6 +1959,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1909,9 +1986,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1943,6 +2022,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1969,9 +2049,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -1998,6 +2080,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2024,9 +2107,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2053,6 +2138,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2079,9 +2165,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2108,6 +2196,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2132,9 +2221,11 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2161,6 +2252,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2185,9 +2277,11 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2214,6 +2308,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2238,9 +2333,11 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2268,6 +2365,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2292,6 +2390,7 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2322,6 +2421,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2347,6 +2447,7 @@ LOCK TABLE t1 WRITE; ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2379,6 +2480,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2403,6 +2505,7 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2433,6 +2536,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2458,6 +2562,7 @@ LOCK TABLE t1 WRITE; ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2490,6 +2595,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2514,6 +2620,7 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2544,6 +2651,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2569,6 +2677,7 @@ LOCK TABLE t1 WRITE; ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2601,6 +2710,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2625,6 +2735,7 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2650,6 +2761,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2675,6 +2787,7 @@ LOCK TABLE t1 WRITE; ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2702,6 +2815,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2726,6 +2840,7 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2751,6 +2866,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2776,6 +2892,7 @@ LOCK TABLE t1 WRITE; ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2803,6 +2920,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2827,6 +2945,7 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2852,6 +2971,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2877,6 +2997,7 @@ LOCK TABLE t1 WRITE; ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2904,6 +3025,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2928,6 +3050,7 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2953,6 +3076,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -2978,6 +3102,7 @@ LOCK TABLE t1 WRITE; ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3005,6 +3130,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3029,6 +3155,7 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3054,6 +3181,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3079,6 +3207,7 @@ LOCK TABLE t1 WRITE; ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3106,6 +3235,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3130,6 +3260,7 @@ a b ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3155,6 +3286,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3180,6 +3312,7 @@ LOCK TABLE t1 WRITE; ALTER TABLE t1 DROP PARTITION p10; ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3209,6 +3342,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3235,9 +3369,11 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3269,6 +3405,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3297,9 +3434,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3331,6 +3470,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3359,9 +3499,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3393,6 +3535,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3421,9 +3564,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3455,6 +3600,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3483,9 +3629,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3517,6 +3665,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3545,9 +3694,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3579,6 +3730,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3607,9 +3759,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3642,6 +3796,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3670,9 +3825,11 @@ ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) #sql-t1.frm #sql-t1.par +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3705,6 +3862,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3731,9 +3889,11 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3766,6 +3926,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3792,9 +3953,11 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3827,6 +3990,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3853,9 +4017,11 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3888,6 +4054,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3914,9 +4081,11 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par # State after crash recovery +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3951,6 +4120,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -3977,6 +4147,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4007,6 +4178,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4034,6 +4206,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4066,6 +4239,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4092,6 +4266,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4122,6 +4297,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4149,6 +4325,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4181,6 +4358,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4207,6 +4385,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4237,6 +4416,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4264,6 +4444,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4296,6 +4477,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4322,6 +4504,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4352,6 +4535,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4379,6 +4563,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4411,6 +4596,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4437,6 +4623,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4467,6 +4654,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4494,6 +4682,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4526,6 +4715,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4552,6 +4742,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4582,6 +4773,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4609,6 +4801,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4641,6 +4834,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4667,6 +4861,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4698,6 +4893,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4725,6 +4921,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4758,6 +4955,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4784,6 +4982,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4815,6 +5014,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4842,6 +5042,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4875,6 +5076,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4901,6 +5103,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4932,6 +5135,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4959,6 +5163,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -4992,6 +5197,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5018,6 +5224,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5049,6 +5256,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5076,6 +5284,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5109,6 +5318,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5135,6 +5345,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5166,6 +5377,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5193,6 +5405,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5226,6 +5439,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5252,6 +5466,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5283,6 +5498,7 @@ PARTITION BY LIST (a) PARTITION p10 VALUES IN (11,12,13,14,15,16,17,18,19)); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5310,6 +5526,7 @@ ALTER TABLE t1 REORGANIZE PARTITION p10 INTO PARTITION p20 VALUES IN (20,21,22,23,24,25,26,27,28,29)); ERROR HY000: Unknown error # State after failure +db.opt t1.frm t1.par SHOW CREATE TABLE t1; @@ -5363,6 +5580,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par t2.frm @@ -5392,10 +5610,12 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par t2.frm # State after crash recovery +db.opt t1.frm t1.par t2.frm @@ -5459,6 +5679,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par t2.frm @@ -5488,10 +5709,12 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par t2.frm # State after crash recovery +db.opt t1.frm t1.par t2.frm @@ -5555,6 +5778,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par t2.frm @@ -5584,10 +5808,12 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par t2.frm # State after crash recovery +db.opt t1.frm t1.par t2.frm @@ -5651,6 +5877,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par t2.frm @@ -5680,10 +5907,12 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par t2.frm # State after crash recovery +db.opt t1.frm t1.par t2.frm @@ -5747,6 +5976,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par t2.frm @@ -5776,10 +6006,12 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par t2.frm # State after crash recovery +db.opt t1.frm t1.par t2.frm @@ -5843,6 +6075,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par t2.frm @@ -5872,10 +6105,12 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par t2.frm # State after crash recovery +db.opt t1.frm t1.par t2.frm @@ -5939,6 +6174,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par t2.frm @@ -5968,10 +6204,12 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par t2.frm # State after crash recovery +db.opt t1.frm t1.par t2.frm @@ -6035,6 +6273,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par t2.frm @@ -6064,10 +6303,12 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par t2.frm # State after crash recovery +db.opt t1.frm t1.par t2.frm @@ -6131,6 +6372,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before crash +db.opt t1.frm t1.par t2.frm @@ -6160,10 +6402,12 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Lost connection to MySQL server during query # State after crash (before recovery) +db.opt t1.frm t1.par t2.frm # State after crash recovery +db.opt t1.frm t1.par t2.frm @@ -6227,6 +6471,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par t2.frm @@ -6256,6 +6501,7 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Error in DDL log # State after failure +db.opt t1.frm t1.par t2.frm @@ -6319,6 +6565,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par t2.frm @@ -6348,6 +6595,7 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Error in DDL log # State after failure +db.opt t1.frm t1.par t2.frm @@ -6411,6 +6659,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par t2.frm @@ -6440,6 +6689,7 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Error on rename of './test/t2' to './test/#sqlx-nnnn_nnnn' (errno: 0 "Internal error/check (Not system error)") # State after failure +db.opt t1.frm t1.par t2.frm @@ -6503,6 +6753,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par t2.frm @@ -6532,6 +6783,7 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Error in DDL log # State after failure +db.opt t1.frm t1.par t2.frm @@ -6595,6 +6847,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par t2.frm @@ -6624,6 +6877,7 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Error on rename of './test/t1#P#p0' to './test/t2' (errno: 0 "Internal error/check (Not system error)") # State after failure +db.opt t1.frm t1.par t2.frm @@ -6687,6 +6941,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par t2.frm @@ -6716,6 +6971,7 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Error in DDL log # State after failure +db.opt t1.frm t1.par t2.frm @@ -6779,6 +7035,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par t2.frm @@ -6808,6 +7065,7 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Error on rename of './test/#sqlx-nnnn_nnnn' to './test/t1#P#p0' (errno: 0 "Internal error/check (Not system error)") # State after failure +db.opt t1.frm t1.par t2.frm @@ -6871,6 +7129,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par t2.frm @@ -6900,6 +7159,7 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Error in DDL log # State after failure +db.opt t1.frm t1.par t2.frm @@ -6963,6 +7223,7 @@ PARTITION BY RANGE (a) PARTITION p1 VALUES LESS THAN MAXVALUE); INSERT INTO t1 VALUES (1, "Original from partition p0"), (2, "Original from partition p0"), (3, "Original from partition p0"), (4, "Original from partition p0"), (11, "Original from partition p1"), (12, "Original from partition p1"), (13, "Original from partition p1"), (14, "Original from partition p1"), (21, "Original from partition p1"), (22, "Original from partition p1"), (23, "Original from partition p1"), (24, "Original from partition p1"); # State before failure +db.opt t1.frm t1.par t2.frm @@ -6992,6 +7253,7 @@ a b ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Error in DDL log # State after failure +db.opt t1.frm t1.par t2.frm diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_engine_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_engine_tokudb.result index a921ba0f56d..028809cd36b 100644 --- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_engine_tokudb.result +++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_engine_tokudb.result @@ -475,6 +475,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -933,6 +934,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1395,6 +1397,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -1920,6 +1923,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2421,6 +2425,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -2883,6 +2888,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3342,6 +3348,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -3804,6 +3811,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4269,6 +4277,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -4723,6 +4732,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text @@ -5178,6 +5188,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT) AND f_charbig = '####updated per insert trigger####'; ANALYZE TABLE t1; Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc0_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc0_tokudb.result index 4c30d47f526..558c3cbdff4 100644 --- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc0_tokudb.result +++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc0_tokudb.result @@ -1020,6 +1020,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +MySQL_Test_DB.t1 analyze status Engine-independent statistics collected MySQL_Test_DB.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc10_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc10_tokudb.result index 6ccd9afefab..1c2f23a277b 100644 --- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc10_tokudb.result +++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc10_tokudb.result @@ -949,6 +949,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +MySQL_Test_DB.t1 analyze status Engine-independent statistics collected MySQL_Test_DB.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc1_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc1_tokudb.result index fce0d496032..76418679582 100644 --- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc1_tokudb.result +++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc1_tokudb.result @@ -987,6 +987,7 @@ a b 2001 Second in MAX ALTER TABLE t1 ANALYZE PARTITION MAX; Table Op Msg_type Msg_text +mysql_test_db.t1 analyze status Engine-independent statistics collected mysql_test_db.t1 analyze status OK # Truncate without FLUSH ALTER TABLE t1 TRUNCATE PARTITION MAX; diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/mdev12179.result b/storage/tokudb/mysql-test/tokudb_rpl/r/mdev12179.result index d4532eec4e2..d79e7e59aa4 100644 --- a/storage/tokudb/mysql-test/tokudb_rpl/r/mdev12179.result +++ b/storage/tokudb/mysql-test/tokudb_rpl/r/mdev12179.result @@ -2,6 +2,7 @@ include/master-slave.inc [connection master] connection server_2; include/stop_slave.inc +SET GLOBAL gtid_cleanup_batch_size = 999999999; CHANGE MASTER TO master_use_gtid=slave_pos; SET sql_log_bin=0; CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos; @@ -41,6 +42,8 @@ a 1 SELECT * FROM mysql.gtid_slave_pos ORDER BY sub_id; domain_id sub_id server_id seq_no +0 1 1 1 +0 2 1 2 0 3 1 3 0 4 1 4 SELECT * FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb @@ -121,6 +124,21 @@ Transactions_multi_engine 6 DELETE FROM t1 WHERE a >= 100; DELETE FROM t2 WHERE a >= 100; DELETE FROM t3 WHERE a >= 100; +connection server_1; +include/save_master_gtid.inc +connection server_2; +include/sync_with_master_gtid.inc +SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos; +COUNT(*)>=10 +1 +SELECT COUNT(*)>=10 FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb +UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select; +COUNT(*)>=10 +1 +SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos_tokudb; +COUNT(*)>=10 +1 +SET GLOBAL gtid_cleanup_batch_size = 3; connection server_2; include/stop_slave.inc SET sql_log_bin=0; diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test b/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test index ceb119cd0dc..1d19a25889e 100644 --- a/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test +++ b/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test @@ -4,6 +4,12 @@ --connection server_2 --source include/stop_slave.inc + +# Set GTID cleanup limit high enough that cleanup will not run and we +# can rely on consistent table output in .result. +--let $old_gtid_cleanup_batch_size=`SELECT @@GLOBAL.gtid_cleanup_batch_size` +SET GLOBAL gtid_cleanup_batch_size = 999999999; + CHANGE MASTER TO master_use_gtid=slave_pos; SET sql_log_bin=0; CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos; @@ -89,6 +95,82 @@ DELETE FROM t2 WHERE a >= 100; DELETE FROM t3 WHERE a >= 100; +# Create a bunch more GTIDs in mysql.gtid_slave_pos* tables to test with. +--connection server_1 +--disable_query_log +let $i=10; +while ($i) { + eval INSERT INTO t1 VALUES (300+$i); + eval INSERT INTO t2 VALUES (300+$i); + eval INSERT INTO t3 VALUES (300+$i); + dec $i; +} +--enable_query_log +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +# Check that we have many rows in mysql.gtid_slave_pos now (since +# @@gtid_cleanup_batch_size was set to a huge value). No need to check +# for an exact number, since that will require changing .result if +# anything changes prior to this point, and we just need to know that +# we have still have some data in the tables to make the following +# test effective. +SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos; +SELECT COUNT(*)>=10 FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb + UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select; +SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos_tokudb; + +# Check that old GTID rows will be deleted when batch delete size is +# set reasonably. Old row deletion is not 100% deterministic (by design), so +# we must wait for it to occur, but it should occur eventually. +SET GLOBAL gtid_cleanup_batch_size = 3; +let $i=40; +--disable_query_log +--let $keep_include_silent=1 +while ($i) { + let N=`SELECT 1+($i MOD 3)`; + --connection server_1 + eval UPDATE t$N SET a=a+1 WHERE a=(SELECT MAX(a) FROM t$N); + --source include/save_master_gtid.inc + --connection server_2 + --source include/sync_with_master_gtid.inc + let $j=50; + while ($j) { + let $is_done=`SELECT SUM(a)=1 FROM ( + SELECT COUNT(*) AS a FROM mysql.gtid_slave_pos + UNION ALL + SELECT COUNT(*) AS a FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb + UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select + UNION ALL + SELECT COUNT(*) AS a FROM mysql.gtid_slave_pos_tokudb) outer_select`; + if ($is_done) { + let $j=0; + } + if (!$is_done) { + real_sleep 0.1; + dec $j; + } + } + dec $i; + if ($is_done) { + let $i=0; + } +} +--enable_query_log +--let $keep_include_silent=0 +if (!$is_done) { + --echo Timed out waiting for mysql.gtid_slave_pos* tables to be cleaned up +} + +--disable_query_log +DELETE FROM t1 WHERE a >= 100; +DELETE FROM t2 WHERE a >= 100; +DELETE FROM t3 WHERE a >= 100; +--enable_query_log + + # Test status variables Rpl_transactions_multi_engine and Transactions_gtid_foreign_engine. # Have mysql.gtid_slave_pos* for myisam and innodb but not tokudb. --connection server_2 @@ -223,6 +305,9 @@ SHOW STATUS LIKE "%transactions%engine"; SET sql_log_bin=0; DROP TABLE mysql.gtid_slave_pos_innodb; SET sql_log_bin=1; +--disable_query_log +eval SET GLOBAL gtid_cleanup_batch_size = $old_gtid_cleanup_batch_size; +--enable_query_log --connection server_1 DROP TABLE t1; diff --git a/storage/tokudb/tokudb_dir_cmd.cc b/storage/tokudb/tokudb_dir_cmd.cc index 5431cbab7aa..d0da92eab27 100644 --- a/storage/tokudb/tokudb_dir_cmd.cc +++ b/storage/tokudb/tokudb_dir_cmd.cc @@ -50,11 +50,11 @@ static int MDL_and_TDC(THD *thd, table_arg.str = const_cast<char *>(table); table_arg.length = strlen(table); Table_ident table_ident(thd, &db_arg, &table_arg, true);; - thd->lex->select_lex.add_table_to_list( + thd->lex->first_select_lex()->add_table_to_list( thd, &table_ident, NULL, 1, TL_UNLOCK, MDL_EXCLUSIVE, 0, 0, 0); /* The lock will be released at the end of mysq_execute_command() */ error = lock_table_names(thd, - thd->lex->select_lex.table_list.first, + thd->lex->first_select_lex()->table_list.first, NULL, thd->variables.lock_wait_timeout, 0); diff --git a/storage/tokudb/tokudb_sysvars.cc b/storage/tokudb/tokudb_sysvars.cc index 1e841f3b959..c561fb65dc8 100644 --- a/storage/tokudb/tokudb_sysvars.cc +++ b/storage/tokudb/tokudb_sysvars.cc @@ -892,6 +892,7 @@ static MYSQL_THDVAR_ULONGLONG( 1); #endif // defined(TOKU_INCLUDE_RFR) && TOKU_INCLUDE_RFR +#if defined(TOKU_INCLUDE_UPSERT) static MYSQL_THDVAR_BOOL( enable_fast_update, PLUGIN_VAR_THDLOCAL, @@ -900,13 +901,14 @@ static MYSQL_THDVAR_BOOL( NULL, false); -static MYSQL_THDVAR_BOOL( + static MYSQL_THDVAR_BOOL( enable_fast_upsert, PLUGIN_VAR_THDLOCAL, "disable slow upsert", NULL, NULL, false); +#endif #if TOKU_INCLUDE_XA static MYSQL_THDVAR_BOOL( diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index 9efd7242118..8368e33cc1d 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -31158,17 +31158,6 @@ typedef struct my_uca_scanner_st CHARSET_INFO *cs; } my_uca_scanner; -/* - Charset dependent scanner part, to optimize - some character sets. -*/ -typedef struct my_uca_scanner_handler_st -{ - void (*init)(my_uca_scanner *scanner, CHARSET_INFO *cs, - const MY_UCA_WEIGHT_LEVEL *level, - const uchar *str, size_t length); - int (*next)(my_uca_scanner *scanner); -} my_uca_scanner_handler; static const uint16 nochar[]= {0,0}; @@ -31421,6 +31410,28 @@ my_uca_can_be_previous_context_tail(const MY_CONTRACTIONS *list, my_wc_t wc) /** + Check if a character needs previous/next context handling: + - can be a previois context tail + - can be a contraction start + + @param level Pointer to an UCA weight level data + @param wc Code point + + @return + @retval FALSE - does not need context handling + @retval TRUE - needs context handing +*/ + +static inline my_bool +my_uca_needs_context_handling(const MY_UCA_WEIGHT_LEVEL *level, my_wc_t wc) +{ + return level->contractions.nitems > 0 && + level->contractions.flags[wc & MY_UCA_CNT_FLAG_MASK] & + (MY_UCA_PREVIOUS_CONTEXT_TAIL | MY_UCA_CNT_HEAD); +} + + +/** Compare two wide character strings, wide analog to strncmp(). @param a Pointer to the first string @@ -31554,6 +31565,60 @@ my_uca_previous_context_find(my_uca_scanner *scanner, return NULL; } + +/* + Find a context dependent weight of a character. + @param scanner - UCA weight scanner. The caller should set + its members "page" and "code" to the previous character + (or to zeros if there is no a previous character). + @param wc - an array of wide characters which has at least + MY_UCA_MAX_CONTRACTION elements, where wc[0] is set + to the current character (whose weight is being resolved). + The values of wc[i>0] is not important, but if wc[0] + appears to be a known contraction head, the function + will collect further contraction parts into wc[i>0]. + If wc[0] and the previous character make a previous context + pair, then wc[1] is set to the previous character. + + @retval NULL if could not find any contextual weights for wc[0] + @retval non null pointer to a zero-terminated weight string otherwise +*/ +static inline uint16 * +my_uca_context_weight_find(my_uca_scanner *scanner, my_wc_t *wc) +{ + uint16 *cweight; + DBUG_ASSERT(scanner->level->contractions.nitems); + /* + If we have scanned a character which can have previous context, + and there were some more characters already before, + then reconstruct codepoint of the previous character + from "page" and "code" into w[1], and verify that {wc[1], wc[0]} + together form a real previous context pair. + Note, we support only 2-character long sequences with previous + context at the moment. CLDR does not have longer sequences. + */ + if (my_uca_can_be_previous_context_tail(&scanner->level->contractions, + wc[0]) && + scanner->wbeg != nochar && /* if not the very first character */ + my_uca_can_be_previous_context_head(&scanner->level->contractions, + (wc[1]= ((scanner->page << 8) + + scanner->code))) && + (cweight= my_uca_previous_context_find(scanner, wc[1], wc[0]))) + { + scanner->page= scanner->code= 0; /* Clear for the next character */ + return cweight; + } + else if (my_uca_can_be_contraction_head(&scanner->level->contractions, + wc[0])) + { + /* Check if w[0] starts a contraction */ + if ((cweight= my_uca_scanner_contraction_find(scanner, wc))) + return cweight; + } + return NULL; +} + + /****************************************************************/ /** @@ -31675,223 +31740,6 @@ my_uca_scanner_init_any(my_uca_scanner *scanner, scanner->cs= cs; } -static int my_uca_scanner_next_any(my_uca_scanner *scanner) -{ - /* - Check if the weights for the previous character have been - already fully scanned. If yes, then get the next character and - initialize wbeg and wlength to its weight string. - */ - - if (scanner->wbeg[0]) /* More weights left from the previous step: */ - return *scanner->wbeg++; /* return the next weight from expansion */ - - do - { - const uint16 *wpage; - my_wc_t wc[MY_UCA_MAX_CONTRACTION]; - int mblen; - - /* Get next character */ - if (((mblen= scanner->cs->cset->mb_wc(scanner->cs, wc, - scanner->sbeg, - scanner->send)) <= 0)) - { - if (scanner->sbeg >= scanner->send) - return -1; /* No more bytes, end of line reached */ - /* - There are some more bytes left. Non-positive mb_len means that - we got an incomplete or a bad byte sequence. Consume mbminlen bytes. - */ - if ((scanner->sbeg+= scanner->cs->mbminlen) > scanner->send) - { - /* For safety purposes don't go beyond the string range. */ - scanner->sbeg= scanner->send; - } - /* - Treat every complete or incomplete mbminlen unit as a weight which is - greater than weight for any possible normal character. - 0xFFFF is greater than any possible weight in the UCA weight table. - */ - return 0xFFFF; - } - - scanner->sbeg+= mblen; - if (wc[0] > scanner->level->maxchar) - { - /* Return 0xFFFD as weight for all characters outside BMP */ - scanner->wbeg= nochar; - return 0xFFFD; - } - - if (my_uca_have_contractions_quick(scanner->level)) - { - uint16 *cweight; - /* - If we have scanned a character which can have previous context, - and there were some more characters already before, - then reconstruct codepoint of the previous character - from "page" and "code" into w[1], and verify that {wc[1], wc[0]} - together form a real previous context pair. - Note, we support only 2-character long sequences with previous - context at the moment. CLDR does not have longer sequences. - */ - if (my_uca_can_be_previous_context_tail(&scanner->level->contractions, - wc[0]) && - scanner->wbeg != nochar && /* if not the very first character */ - my_uca_can_be_previous_context_head(&scanner->level->contractions, - (wc[1]= ((scanner->page << 8) + - scanner->code))) && - (cweight= my_uca_previous_context_find(scanner, wc[1], wc[0]))) - { - scanner->page= scanner->code= 0; /* Clear for the next character */ - return *cweight; - } - else if (my_uca_can_be_contraction_head(&scanner->level->contractions, - wc[0])) - { - /* Check if w[0] starts a contraction */ - if ((cweight= my_uca_scanner_contraction_find(scanner, wc))) - return *cweight; - } - } - - /* Process single character */ - scanner->page= wc[0] >> 8; - scanner->code= wc[0] & 0xFF; - - /* If weight page for w[0] does not exist, then calculate algoritmically */ - if (!(wpage= scanner->level->weights[scanner->page])) - return my_uca_scanner_next_implicit(scanner); - - /* Calculate pointer to w[0]'s weight, using page and offset */ - scanner->wbeg= wpage + - scanner->code * scanner->level->lengths[scanner->page]; - } while (!scanner->wbeg[0]); /* Skip ignorable characters */ - - return *scanner->wbeg++; -} - - -static my_uca_scanner_handler my_any_uca_scanner_handler= -{ - my_uca_scanner_init_any, - my_uca_scanner_next_any -}; - -/* - Compares two strings according to the collation - - SYNOPSIS: - my_strnncoll_uca() - cs Character set information - s First string - slen First string length - t Second string - tlen Seconf string length - level DUCETweight level - - NOTES: - Initializes two weight scanners and gets weights - corresponding to two strings in a loop. If weights are not - the same at some step then returns their difference. - - In the while() comparison these situations are possible: - 1. (s_res>0) and (t_res>0) and (s_res == t_res) - Weights are the same so far, continue comparison - 2. (s_res>0) and (t_res>0) and (s_res!=t_res) - A difference has been found, return. - 3. (s_res>0) and (t_res<0) - We have reached the end of the second string, or found - an illegal multibyte sequence in the second string. - Return a positive number, i.e. the first string is bigger. - 4. (s_res<0) and (t_res>0) - We have reached the end of the first string, or found - an illegal multibyte sequence in the first string. - Return a negative number, i.e. the second string is bigger. - 5. (s_res<0) and (t_res<0) - Both scanners returned -1. It means we have riched - the end-of-string of illegal-sequence in both strings - at the same time. Return 0, strings are equal. - - RETURN - Difference between two strings, according to the collation: - 0 - means strings are equal - negative number - means the first string is smaller - positive number - means the first string is bigger -*/ - -static int my_strnncoll_uca_onelevel(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - const MY_UCA_WEIGHT_LEVEL *level, - const uchar *s, size_t slen, - const uchar *t, size_t tlen, - my_bool t_is_prefix) -{ - my_uca_scanner sscanner; - my_uca_scanner tscanner; - int s_res; - int t_res; - - scanner_handler->init(&sscanner, cs, level, s, slen); - scanner_handler->init(&tscanner, cs, level, t, tlen); - - do - { - s_res= scanner_handler->next(&sscanner); - t_res= scanner_handler->next(&tscanner); - } while ( s_res == t_res && s_res >0); - - return (t_is_prefix && t_res < 0) ? 0 : (s_res - t_res); -} - -static int my_strnncoll_uca(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - const uchar *s, size_t slen, - const uchar *t, size_t tlen, - my_bool t_is_prefix) -{ - return my_strnncoll_uca_onelevel(cs, scanner_handler, &cs->uca->level[0], - s, slen, t, tlen, t_is_prefix); -} - -static int my_strnncoll_uca_multilevel(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - const uchar *s, size_t slen, - const uchar *t, size_t tlen, - my_bool t_is_prefix) -{ - uint num_level= cs->levels_for_order; - uint i; - for (i= 0; i != num_level; i++) - { - int ret= my_strnncoll_uca_onelevel(cs, scanner_handler, &cs->uca->level[i], - s, slen, t, tlen, t_is_prefix); - if (ret) - return ret; - } - return 0; -} - - -static int -my_strnncollsp_generic_uca_nopad_multilevel(CHARSET_INFO *cs, - const uchar *s, size_t slen, - const uchar *t, size_t tlen) -{ - uint num_level= cs->levels_for_order; - uint i; - for (i= 0; i != num_level; i++) - { - int ret= my_strnncoll_uca_onelevel(cs, &my_any_uca_scanner_handler, - &cs->uca->level[i], - s, slen, t, tlen, FALSE); - if (ret) - return ret; - } - return 0; -} - static inline int my_space_weight(const MY_UCA_WEIGHT_LEVEL *level) @@ -31924,258 +31772,6 @@ my_char_weight_addr(const MY_UCA_WEIGHT_LEVEL *level, uint wc) } -/* - Compares two strings according to the collation, - ignoring trailing spaces. - - SYNOPSIS: - my_strnncollsp_uca() - cs Character set information - s First string - slen First string length - t Second string - tlen Seconf string length - level DUCETweight level - - NOTES: - Works exactly the same with my_strnncoll_uca(), - but ignores trailing spaces. - - In the while() comparison these situations are possible: - 1. (s_res>0) and (t_res>0) and (s_res == t_res) - Weights are the same so far, continue comparison - 2. (s_res>0) and (t_res>0) and (s_res!=t_res) - A difference has been found, return. - 3. (s_res>0) and (t_res<0) - We have reached the end of the second string, or found - an illegal multibyte sequence in the second string. - Compare the first string to an infinite array of - space characters until difference is found, or until - the end of the first string. - 4. (s_res<0) and (t_res>0) - We have reached the end of the first string, or found - an illegal multibyte sequence in the first string. - Compare the second string to an infinite array of - space characters until difference is found or until - the end of the second steing. - 5. (s_res<0) and (t_res<0) - Both scanners returned -1. It means we have riched - the end-of-string of illegal-sequence in both strings - at the same time. Return 0, strings are equal. - - RETURN - Difference between two strings, according to the collation: - 0 - means strings are equal - negative number - means the first string is smaller - positive number - means the first string is bigger -*/ - -static int my_strnncollsp_uca_onelevel(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - const MY_UCA_WEIGHT_LEVEL *level, - const uchar *s, size_t slen, - const uchar *t, size_t tlen) -{ - my_uca_scanner sscanner, tscanner; - int s_res, t_res; - - scanner_handler->init(&sscanner, cs, level, s, slen); - scanner_handler->init(&tscanner, cs, level, t, tlen); - - do - { - s_res= scanner_handler->next(&sscanner); - t_res= scanner_handler->next(&tscanner); - } while ( s_res == t_res && s_res >0); - - if (s_res > 0 && t_res < 0) - { - /* Calculate weight for SPACE character */ - t_res= my_space_weight(level); - - /* compare the first string to spaces */ - do - { - if (s_res != t_res) - return (s_res - t_res); - s_res= scanner_handler->next(&sscanner); - } while (s_res > 0); - return 0; - } - - if (s_res < 0 && t_res > 0) - { - /* Calculate weight for SPACE character */ - s_res= my_space_weight(level); - - /* compare the second string to spaces */ - do - { - if (s_res != t_res) - return (s_res - t_res); - t_res= scanner_handler->next(&tscanner); - } while (t_res > 0); - return 0; - } - - return ( s_res - t_res ); -} - -static int my_strnncollsp_uca(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - const uchar *s, size_t slen, - const uchar *t, size_t tlen) -{ - return my_strnncollsp_uca_onelevel(cs, scanner_handler, &cs->uca->level[0], - s, slen, t, tlen); -} - -static int my_strnncollsp_uca_multilevel(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - const uchar *s, size_t slen, - const uchar *t, size_t tlen) -{ - uint num_level= cs->levels_for_order; - uint i; - for (i= 0; i != num_level; i++) - { - int ret= my_strnncollsp_uca_onelevel(cs, scanner_handler, - &cs->uca->level[i], s, slen, t, tlen); - if (ret) - return ret; - } - return 0; -} - -/* - Calculates hash value for the given string, - according to the collation, and ignoring trailing spaces. - - SYNOPSIS: - my_hash_sort_uca() - cs Character set information - s String - slen String's length - n1 First hash parameter - n2 Second hash parameter - - NOTES: - Scans consequently weights and updates - hash parameters n1 and n2. In a case insensitive collation, - upper and lower case of the same letter will return the same - weight sequence, and thus will produce the same hash values - in n1 and n2. - - This functions is used for one-level and for multi-level collations. - We intentionally use only primary level in multi-level collations. - This helps to have PARTITION BY KEY put primarily equal records - into the same partition. E.g. in utf8_thai_520_ci records that differ - only in tone marks go into the same partition. - - RETURN - N/A -*/ - -static void my_hash_sort_uca(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - const uchar *s, size_t slen, - ulong *nr1, ulong *nr2) -{ - int s_res; - my_uca_scanner scanner; - int space_weight= my_space_weight(&cs->uca->level[0]); - register ulong m1= *nr1, m2= *nr2; - - scanner_handler->init(&scanner, cs, &cs->uca->level[0], s, slen); - - while ((s_res= scanner_handler->next(&scanner)) >0) - { - if (s_res == space_weight) - { - /* Combine all spaces to be able to skip end spaces */ - uint count= 0; - do - { - count++; - if ((s_res= scanner_handler->next(&scanner)) <= 0) - { - /* Skip strings at end of string */ - goto end; - } - } - while (s_res == space_weight); - - /* Add back that has for the space characters */ - do - { - /* - We can't use MY_HASH_ADD_16() here as we, because of a misstake - in the original code, where we added the 16 byte variable the - opposite way. Changing this would cause old partitioned tables - to fail. - */ - MY_HASH_ADD(m1, m2, space_weight >> 8); - MY_HASH_ADD(m1, m2, space_weight & 0xFF); - } - while (--count != 0); - - } - /* See comment above why we can't use MY_HASH_ADD_16() */ - MY_HASH_ADD(m1, m2, s_res >> 8); - MY_HASH_ADD(m1, m2, s_res & 0xFF); - } -end: - *nr1= m1; - *nr2= m2; -} - - -static void my_hash_sort_uca_nopad(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - const uchar *s, size_t slen, - ulong *nr1, ulong *nr2) -{ - int s_res; - my_uca_scanner scanner; - register ulong m1= *nr1, m2= *nr2; - - scanner_handler->init(&scanner, cs, &cs->uca->level[0], s, slen); - - while ((s_res= scanner_handler->next(&scanner)) >0) - { - /* See comment above why we can't use MY_HASH_ADD_16() */ - MY_HASH_ADD(m1, m2, s_res >> 8); - MY_HASH_ADD(m1, m2, s_res & 0xFF); - } - *nr1= m1; - *nr2= m2; -} - - -static uchar * -my_strnxfrm_uca_onelevel_internal(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - MY_UCA_WEIGHT_LEVEL *level, - uchar *dst, uchar *de, uint *nweights, - const uchar *src, size_t srclen) -{ - my_uca_scanner scanner; - int s_res; - - DBUG_ASSERT(src || !srclen); - - scanner_handler->init(&scanner, cs, level, src, srclen); - for (; dst < de && *nweights && - (s_res= scanner_handler->next(&scanner)) > 0 ; (*nweights)--) - { - *dst++= s_res >> 8; - if (dst < de) - *dst++= s_res & 0xFF; - } - return dst; -} - - static uchar * my_strnxfrm_uca_padn(uchar *dst, uchar *de, uint nweights, int weight) { @@ -32202,27 +31798,6 @@ my_strnxfrm_uca_pad(uchar *dst, uchar *de, int weight) } -static uchar * -my_strnxfrm_uca_onelevel(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - MY_UCA_WEIGHT_LEVEL *level, - uchar *dst, uchar *de, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - uchar *d0= dst; - - dst= my_strnxfrm_uca_onelevel_internal(cs, scanner_handler, level, - dst, de, &nweights, - src, srclen); - DBUG_ASSERT(dst <= de); - if (dst < de && nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE)) - dst= my_strnxfrm_uca_padn(dst, de, nweights, my_space_weight(level)); - DBUG_ASSERT(dst <= de); - my_strxfrm_desc_and_reverse(d0, dst, flags, 0); - return dst; -} - - /* Return the minimum possible weight on a level. */ @@ -32233,136 +31808,6 @@ static uint min_weight_on_level(MY_UCA_WEIGHT_LEVEL *level) } -static uchar * -my_strnxfrm_uca_nopad_onelevel(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - MY_UCA_WEIGHT_LEVEL *level, - uchar *dst, uchar *de, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - uchar *d0= dst; - - dst= my_strnxfrm_uca_onelevel_internal(cs, scanner_handler, level, - dst, de, &nweights, - src, srclen); - DBUG_ASSERT(dst <= de); - /* Pad with the minimum possible weight on this level */ - if (dst < de && nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE)) - dst= my_strnxfrm_uca_padn(dst, de, nweights, min_weight_on_level(level)); - DBUG_ASSERT(dst <= de); - my_strxfrm_desc_and_reverse(d0, dst, flags, 0); - return dst; -} - - -/* - For the given string creates its "binary image", suitable - to be used in binary comparison, i.e. in memcmp(). - - SYNOPSIS: - my_strnxfrm_uca() - cs Character set information - dst Where to write the image - dstlen Space available for the image, in bytes - src The source string - srclen Length of the source string, in bytes - - NOTES: - In a loop, scans weights from the source string and writes - them into the binary image. In a case insensitive collation, - upper and lower cases of the same letter will produce the - same image subsequences. When we have reached the end-of-string - or found an illegal multibyte sequence, the loop stops. - - It is impossible to restore the original string using its - binary image. - - Binary images are used for bulk comparison purposes, - e.g. in ORDER BY, when it is more efficient to create - a binary image and use it instead of weight scanner - for the original strings for every comparison. - - RETURN - Number of bytes that have been written into the binary image. -*/ - - -static size_t -my_strnxfrm_uca(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - uchar *d0= dst; - uchar *de= dst + dstlen; - - dst= my_strnxfrm_uca_onelevel(cs, scanner_handler, &cs->uca->level[0], - dst, de, nweights, src, srclen, flags); - /* - This can probably be changed to memset(dst, 0, de - dst), - like my_strnxfrm_uca_multilevel() does. - */ - if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de) - dst= my_strnxfrm_uca_pad(dst, de, my_space_weight(&cs->uca->level[0])); - return dst - d0; -} - - -static size_t -my_strnxfrm_uca_nopad(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - uchar *d0= dst; - uchar *de= dst + dstlen; - - dst= my_strnxfrm_uca_nopad_onelevel(cs, scanner_handler, &cs->uca->level[0], - dst, de, nweights, src, srclen, flags); - if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de) - { - memset(dst, 0, de - dst); - dst= de; - } - return dst - d0; -} - - -static size_t -my_strnxfrm_uca_multilevel(CHARSET_INFO *cs, - my_uca_scanner_handler *scanner_handler, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - uint num_level= cs->levels_for_order; - uchar *d0= dst; - uchar *de= dst + dstlen; - uint current_level; - - for (current_level= 0; current_level != num_level; current_level++) - { - if (!(flags & MY_STRXFRM_LEVEL_ALL) || - (flags & (MY_STRXFRM_LEVEL1 << current_level))) - dst= cs->state & MY_CS_NOPAD ? - my_strnxfrm_uca_nopad_onelevel(cs, scanner_handler, - &cs->uca->level[current_level], - dst, de, nweights, - src, srclen, flags) : - my_strnxfrm_uca_onelevel(cs, scanner_handler, - &cs->uca->level[current_level], - dst, de, nweights, - src, srclen, flags); - } - - if (dst < de && (flags & MY_STRXFRM_PAD_TO_MAXLEN)) - { - memset(dst, 0, de - dst); - dst= de; - } - - return dst - d0; -} - /* This function compares if two characters are the same. The sign +1 or -1 does not matter. The only @@ -32568,6 +32013,23 @@ int my_wildcmp_uca(CHARSET_INFO *cs, /* + Tests if an optimized "no contraction" handler can be used for + the given collation. +*/ +static my_bool +my_uca_collation_can_optimize_no_contractions(CHARSET_INFO *cs) +{ + uint i; + for (i= 0; i < cs->levels_for_order ; i++) + { + if (my_uca_have_contractions_quick(&cs->uca->level[i])) + return FALSE; + } + return TRUE; +} + + +/* Collation language is implemented according to subset of ICU Collation Customization (tailorings): http://icu.sourceforge.net/userguide/Collate_Customization.html @@ -34250,8 +33712,74 @@ init_weight_level(MY_CHARSET_LOADER *loader, MY_COLL_RULES *rules, } -MY_COLLATION_HANDLER my_collation_any_uca_handler_multilevel; -MY_COLLATION_HANDLER my_collation_generic_uca_nopad_handler_multilevel; +static my_bool +create_tailoring(struct charset_info_st *cs, + MY_CHARSET_LOADER *loader); + +static my_bool +my_coll_init_uca(struct charset_info_st *cs, MY_CHARSET_LOADER *loader) +{ + cs->pad_char= ' '; + cs->ctype= my_charset_utf8_unicode_ci.ctype; + if (!cs->caseinfo) + cs->caseinfo= &my_unicase_default; + return create_tailoring(cs, loader); +} + + +static size_t my_strnxfrmlen_any_uca(CHARSET_INFO *cs, size_t len) +{ + /* UCA uses 2 bytes per weight */ + return (len + cs->mbmaxlen - 1) / cs->mbmaxlen * cs->strxfrm_multiply * 2; +} + +static size_t my_strnxfrmlen_any_uca_multilevel(CHARSET_INFO *cs, size_t len) +{ + return my_strnxfrmlen_any_uca(cs, len) * cs->levels_for_order; +} + + +/* + This structure is used at the collation initialization time, to switch + from a full-featured collation handler to a "no contraction" collation + handler if the collation is known not to have any contractions. +*/ +typedef struct +{ + MY_COLLATION_HANDLER *pad; + MY_COLLATION_HANDLER *nopad; + MY_COLLATION_HANDLER *multilevel_pad; + MY_COLLATION_HANDLER *multilevel_nopad; +} MY_COLLATION_HANDLER_PACKAGE; + + +static void my_uca_handler_map(struct charset_info_st *cs, + const MY_COLLATION_HANDLER_PACKAGE *from, + const MY_COLLATION_HANDLER_PACKAGE *to) +{ + if (cs->coll == from->pad) cs->coll= to->pad; + else if (cs->coll == from->nopad) cs->coll= to->nopad; + else if (cs->coll == from->multilevel_pad) cs->coll= to->multilevel_pad; + else if (cs->coll == from->multilevel_nopad) cs->coll= to->multilevel_nopad; +} + + +/* + Define generic collation handlers for multi-level collations with tailoring: + + my_uca_collation_handler_nopad_multilevel_generic + my_uca_collation_handler_multilevel_generic + + TODO: Use faster character-set specific versions of MY_COLLATION_HANDLER + instead of generic. +*/ +#define MY_FUNCTION_NAME(x) my_uca_ ## x ## _generic +#define MY_MB_WC(scanner, wc, beg, end) (scanner->cs->cset->mb_wc(scanner->cs, wc, beg, end)) +#define MY_LIKE_RANGE my_like_range_generic +#define MY_UCA_ASCII_OPTIMIZE 0 +#define MY_UCA_COMPILE_CONTRACTIONS 1 +#define MY_UCA_COLL_INIT my_coll_init_uca +#include "ctype-uca.ic" /* @@ -34336,8 +33864,8 @@ create_tailoring(struct charset_info_st *cs, cs->uca[0]= new_uca; if (cs->levels_for_order > 1) cs->coll= (cs->state & MY_CS_NOPAD) ? - &my_collation_generic_uca_nopad_handler_multilevel : - &my_collation_any_uca_handler_multilevel; + &my_uca_collation_handler_nopad_multilevel_generic : + &my_uca_collation_handler_multilevel_generic; ex: (loader->free)(rules.rule); @@ -34346,235 +33874,17 @@ ex: return rc; } -/* - Universal CHARSET_INFO compatible wrappers - for the above internal functions. - Should work for any character set. -*/ - -static my_bool -my_coll_init_uca(struct charset_info_st *cs, MY_CHARSET_LOADER *loader) -{ - cs->pad_char= ' '; - cs->ctype= my_charset_utf8_unicode_ci.ctype; - if (!cs->caseinfo) - cs->caseinfo= &my_unicase_default; - return create_tailoring(cs, loader); -} - - -static int my_strnncoll_any_uca(CHARSET_INFO *cs, - const uchar *s, size_t slen, - const uchar *t, size_t tlen, - my_bool t_is_prefix) -{ - return my_strnncoll_uca(cs, &my_any_uca_scanner_handler, - s, slen, t, tlen, t_is_prefix); -} - -static int my_strnncoll_any_uca_multilevel(CHARSET_INFO *cs, - const uchar *s, size_t slen, - const uchar *t, size_t tlen, - my_bool t_is_prefix) -{ - return my_strnncoll_uca_multilevel(cs, &my_any_uca_scanner_handler, - s, slen, t, tlen, t_is_prefix); -} - -static int my_strnncollsp_any_uca(CHARSET_INFO *cs, - const uchar *s, size_t slen, - const uchar *t, size_t tlen) -{ - return my_strnncollsp_uca(cs, &my_any_uca_scanner_handler, s, slen, t, tlen); -} - - -static int my_strnncollsp_generic_uca_nopad(CHARSET_INFO *cs, - const uchar *s, size_t slen, - const uchar *t, size_t tlen) -{ - return my_strnncoll_uca(cs, &my_any_uca_scanner_handler, - s, slen, t, tlen, FALSE); -} - - -static int my_strnncollsp_any_uca_multilevel(CHARSET_INFO *cs, - const uchar *s, size_t slen, - const uchar *t, size_t tlen) -{ - return my_strnncollsp_uca_multilevel(cs, &my_any_uca_scanner_handler, - s, slen, t, tlen); -} - -static void my_hash_sort_any_uca(CHARSET_INFO *cs, - const uchar *s, size_t slen, - ulong *n1, ulong *n2) -{ - my_hash_sort_uca(cs, &my_any_uca_scanner_handler, s, slen, n1, n2); -} - -static void my_hash_sort_generic_uca_nopad(CHARSET_INFO *cs, - const uchar *s, size_t slen, - ulong *n1, ulong *n2) -{ - my_hash_sort_uca_nopad(cs, &my_any_uca_scanner_handler, s, slen, n1, n2); -} - -static size_t my_strnxfrm_any_uca(CHARSET_INFO *cs, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - return my_strnxfrm_uca(cs, &my_any_uca_scanner_handler, - dst, dstlen, nweights, src, srclen, flags); -} - -static size_t my_strnxfrm_generic_uca_nopad(CHARSET_INFO *cs, - uchar *dst, size_t dstlen, - uint nweights, - const uchar *src, size_t srclen, - uint flags) -{ - return my_strnxfrm_uca_nopad(cs, &my_any_uca_scanner_handler, - dst, dstlen, nweights, src, srclen, flags); -} - -static size_t my_strnxfrm_any_uca_multilevel(CHARSET_INFO *cs, - uchar *dst, size_t dstlen, - uint nweights, const uchar *src, - size_t srclen, uint flags) -{ - return my_strnxfrm_uca_multilevel(cs, &my_any_uca_scanner_handler, - dst, dstlen, nweights, src, srclen, - flags); -} - -static size_t my_strnxfrmlen_any_uca(CHARSET_INFO *cs, size_t len) -{ - /* UCA uses 2 bytes per weight */ - return (len + cs->mbmaxlen - 1) / cs->mbmaxlen * cs->strxfrm_multiply * 2; -} - -static size_t my_strnxfrmlen_any_uca_multilevel(CHARSET_INFO *cs, size_t len) -{ - return my_strnxfrmlen_any_uca(cs, len) * cs->levels_for_order; -} - - -/* NO PAD handler for character sets with mbminlen==1 */ -MY_COLLATION_HANDLER my_collation_mb_uca_nopad_handler = -{ - my_coll_init_uca, - my_strnncoll_any_uca, - my_strnncollsp_generic_uca_nopad, - my_strnxfrm_generic_uca_nopad, - my_strnxfrmlen_any_uca, - my_like_range_mb, - my_wildcmp_uca, - NULL, - my_instr_mb, - my_hash_sort_generic_uca_nopad, - my_propagate_complex -}; - - -/* NO PAD handler for character sets with mbminlen>=1 */ -MY_COLLATION_HANDLER my_collation_generic_uca_nopad_handler = -{ - my_coll_init_uca, - my_strnncoll_any_uca, - my_strnncollsp_generic_uca_nopad, - my_strnxfrm_generic_uca_nopad, - my_strnxfrmlen_any_uca, - my_like_range_generic, - my_wildcmp_uca, - NULL, - my_instr_mb, - my_hash_sort_generic_uca_nopad, - my_propagate_complex -}; - - -MY_COLLATION_HANDLER my_collation_any_uca_handler_multilevel= -{ - my_coll_init_uca, - my_strnncoll_any_uca_multilevel, - my_strnncollsp_any_uca_multilevel, - my_strnxfrm_any_uca_multilevel, - my_strnxfrmlen_any_uca_multilevel, - my_like_range_generic, - my_wildcmp_uca, - NULL, - my_instr_mb, - my_hash_sort_any_uca, - my_propagate_complex -}; - - -MY_COLLATION_HANDLER my_collation_generic_uca_nopad_handler_multilevel = -{ - my_coll_init_uca, - my_strnncoll_any_uca_multilevel, - my_strnncollsp_generic_uca_nopad_multilevel, - my_strnxfrm_any_uca_multilevel, - my_strnxfrmlen_any_uca_multilevel, - my_like_range_generic, - my_wildcmp_uca, - NULL, - my_instr_mb, - my_hash_sort_generic_uca_nopad, - my_propagate_complex -}; - #ifdef HAVE_CHARSET_ucs2 -/* - UCS2 optimized CHARSET_INFO compatible wrappers. -*/ -static int my_strnncoll_ucs2_uca(CHARSET_INFO *cs, - const uchar *s, size_t slen, - const uchar *t, size_t tlen, - my_bool t_is_prefix) -{ - return my_strnncoll_uca(cs, &my_any_uca_scanner_handler, - s, slen, t, tlen, t_is_prefix); -} -static int my_strnncollsp_ucs2_uca(CHARSET_INFO *cs, - const uchar *s, size_t slen, - const uchar *t, size_t tlen) -{ - return my_strnncollsp_uca(cs, &my_any_uca_scanner_handler, s, slen, t, tlen); -} - -static void my_hash_sort_ucs2_uca(CHARSET_INFO *cs, - const uchar *s, size_t slen, - ulong *n1, ulong *n2) -{ - my_hash_sort_uca(cs, &my_any_uca_scanner_handler, s, slen, n1, n2); -} - -static size_t my_strnxfrm_ucs2_uca(CHARSET_INFO *cs, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - return my_strnxfrm_uca(cs, &my_any_uca_scanner_handler, - dst, dstlen, nweights, src, srclen, flags); -} - -MY_COLLATION_HANDLER my_collation_ucs2_uca_handler = -{ - my_coll_init_uca, /* init */ - my_strnncoll_ucs2_uca, - my_strnncollsp_ucs2_uca, - my_strnxfrm_ucs2_uca, - my_strnxfrmlen_any_uca, - my_like_range_generic, - my_wildcmp_uca, - NULL, - my_instr_mb, - my_hash_sort_ucs2_uca, - my_propagate_complex -}; +#include "ctype-ucs2.h" +#define MY_FUNCTION_NAME(x) my_uca_ ## x ## _ucs2 +#define MY_MB_WC(scanner, wc, beg, end) (my_mb_wc_ucs2_quick(wc, beg, end)) +#define MY_LIKE_RANGE my_like_range_generic +#define MY_UCA_ASCII_OPTIMIZE 0 +#define MY_UCA_COMPILE_CONTRACTIONS 1 +#define MY_UCA_COLL_INIT my_coll_init_uca +#include "ctype-uca.ic" #define MY_CS_UCS2_UCA_FLAGS (MY_CS_COMMON_UCA_FLAGS|MY_CS_NONASCII) @@ -34609,7 +33919,7 @@ struct charset_info_st my_charset_ucs2_unicode_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_icelandic_uca_ci= @@ -34641,7 +33951,7 @@ struct charset_info_st my_charset_ucs2_icelandic_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_latvian_uca_ci= @@ -34673,7 +33983,7 @@ struct charset_info_st my_charset_ucs2_latvian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_romanian_uca_ci= @@ -34705,7 +34015,7 @@ struct charset_info_st my_charset_ucs2_romanian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_slovenian_uca_ci= @@ -34737,7 +34047,7 @@ struct charset_info_st my_charset_ucs2_slovenian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_polish_uca_ci= @@ -34769,7 +34079,7 @@ struct charset_info_st my_charset_ucs2_polish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_estonian_uca_ci= @@ -34801,7 +34111,7 @@ struct charset_info_st my_charset_ucs2_estonian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_spanish_uca_ci= @@ -34833,7 +34143,7 @@ struct charset_info_st my_charset_ucs2_spanish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_swedish_uca_ci= @@ -34865,7 +34175,7 @@ struct charset_info_st my_charset_ucs2_swedish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_turkish_uca_ci= @@ -34897,7 +34207,7 @@ struct charset_info_st my_charset_ucs2_turkish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_czech_uca_ci= @@ -34929,7 +34239,7 @@ struct charset_info_st my_charset_ucs2_czech_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -34962,7 +34272,7 @@ struct charset_info_st my_charset_ucs2_danish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_lithuanian_uca_ci= @@ -34994,7 +34304,7 @@ struct charset_info_st my_charset_ucs2_lithuanian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_slovak_uca_ci= @@ -35026,7 +34336,7 @@ struct charset_info_st my_charset_ucs2_slovak_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_spanish2_uca_ci= @@ -35058,7 +34368,7 @@ struct charset_info_st my_charset_ucs2_spanish2_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -35091,7 +34401,7 @@ struct charset_info_st my_charset_ucs2_roman_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -35124,7 +34434,7 @@ struct charset_info_st my_charset_ucs2_persian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -35157,7 +34467,7 @@ struct charset_info_st my_charset_ucs2_esperanto_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -35190,7 +34500,7 @@ struct charset_info_st my_charset_ucs2_hungarian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_sinhala_uca_ci= @@ -35222,7 +34532,7 @@ struct charset_info_st my_charset_ucs2_sinhala_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -35256,7 +34566,7 @@ struct charset_info_st my_charset_ucs2_german2_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; struct charset_info_st my_charset_ucs2_croatian_mysql561_uca_ci= @@ -35288,7 +34598,7 @@ struct charset_info_st my_charset_ucs2_croatian_mysql561_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -35321,7 +34631,7 @@ struct charset_info_st my_charset_ucs2_croatian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -35354,7 +34664,7 @@ struct charset_info_st my_charset_ucs2_myanmar_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -35387,7 +34697,7 @@ struct charset_info_st my_charset_ucs2_thai_520_w2= 0, /* escape_with_backslash_is_dangerous */ 2, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_any_uca_handler_multilevel + &my_uca_collation_handler_multilevel_ucs2 }; struct charset_info_st my_charset_ucs2_unicode_520_ci= @@ -35419,7 +34729,7 @@ struct charset_info_st my_charset_ucs2_unicode_520_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -35452,7 +34762,7 @@ struct charset_info_st my_charset_ucs2_vietnamese_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_ucs2_uca_handler + &my_uca_collation_handler_ucs2 }; @@ -35485,7 +34795,7 @@ struct charset_info_st my_charset_ucs2_unicode_nopad_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_generic_uca_nopad_handler + &my_uca_collation_handler_nopad_ucs2 }; @@ -35518,7 +34828,7 @@ struct charset_info_st my_charset_ucs2_unicode_520_nopad_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_ucs2_handler, - &my_collation_generic_uca_nopad_handler + &my_uca_collation_handler_nopad_ucs2 }; @@ -35526,20 +34836,38 @@ struct charset_info_st my_charset_ucs2_unicode_520_nopad_ci= #ifdef HAVE_CHARSET_utf8 -MY_COLLATION_HANDLER my_collation_any_uca_handler = + +static my_bool +my_uca_coll_init_utf8mb3(struct charset_info_st *cs, MY_CHARSET_LOADER *loader); + +#include "ctype-utf8.h" +#define MY_FUNCTION_NAME(x) my_uca_ ## x ## _utf8mb3 +#define MY_MB_WC(scanner, wc, beg, end) (my_mb_wc_utf8mb3_quick(wc, beg, end)) +#define MY_LIKE_RANGE my_like_range_mb +#define MY_UCA_ASCII_OPTIMIZE 1 +#define MY_UCA_COMPILE_CONTRACTIONS 1 +#define MY_UCA_COLL_INIT my_uca_coll_init_utf8mb3 +#include "ctype-uca.ic" + +#define MY_FUNCTION_NAME(x) my_uca_ ## x ## _no_contractions_utf8mb3 +#define MY_MB_WC(scanner, wc, beg, end) (my_mb_wc_utf8mb3_quick(wc, beg, end)) +#define MY_LIKE_RANGE my_like_range_mb +#define MY_UCA_ASCII_OPTIMIZE 1 +#define MY_UCA_COMPILE_CONTRACTIONS 0 +#define MY_UCA_COLL_INIT my_uca_coll_init_utf8mb3 +#include "ctype-uca.ic" + + +static my_bool +my_uca_coll_init_utf8mb3(struct charset_info_st *cs, MY_CHARSET_LOADER *loader) { - my_coll_init_uca, /* init */ - my_strnncoll_any_uca, - my_strnncollsp_any_uca, - my_strnxfrm_any_uca, - my_strnxfrmlen_any_uca, - my_like_range_mb, - my_wildcmp_uca, - NULL, - my_instr_mb, - my_hash_sort_any_uca, - my_propagate_complex -}; + if (my_coll_init_uca(cs, loader)) + return TRUE; + if (my_uca_collation_can_optimize_no_contractions(cs)) + my_uca_handler_map(cs, &my_uca_package_utf8mb3, + &my_uca_package_no_contractions_utf8mb3); + return FALSE; +} /* @@ -35602,7 +34930,7 @@ struct charset_info_st my_charset_utf8_unicode_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; @@ -35635,7 +34963,7 @@ struct charset_info_st my_charset_utf8_icelandic_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_latvian_uca_ci= @@ -35667,7 +34995,7 @@ struct charset_info_st my_charset_utf8_latvian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_romanian_uca_ci= @@ -35699,7 +35027,7 @@ struct charset_info_st my_charset_utf8_romanian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_slovenian_uca_ci= @@ -35731,7 +35059,7 @@ struct charset_info_st my_charset_utf8_slovenian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_polish_uca_ci= @@ -35763,7 +35091,7 @@ struct charset_info_st my_charset_utf8_polish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_estonian_uca_ci= @@ -35795,7 +35123,7 @@ struct charset_info_st my_charset_utf8_estonian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_spanish_uca_ci= @@ -35827,7 +35155,7 @@ struct charset_info_st my_charset_utf8_spanish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_swedish_uca_ci= @@ -35859,7 +35187,7 @@ struct charset_info_st my_charset_utf8_swedish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_turkish_uca_ci= @@ -35891,7 +35219,7 @@ struct charset_info_st my_charset_utf8_turkish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_czech_uca_ci= @@ -35923,7 +35251,7 @@ struct charset_info_st my_charset_utf8_czech_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; @@ -35956,7 +35284,7 @@ struct charset_info_st my_charset_utf8_danish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_lithuanian_uca_ci= @@ -35988,7 +35316,7 @@ struct charset_info_st my_charset_utf8_lithuanian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_slovak_uca_ci= @@ -36020,7 +35348,7 @@ struct charset_info_st my_charset_utf8_slovak_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_spanish2_uca_ci= @@ -36052,7 +35380,7 @@ struct charset_info_st my_charset_utf8_spanish2_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_roman_uca_ci= @@ -36084,7 +35412,7 @@ struct charset_info_st my_charset_utf8_roman_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_persian_uca_ci= @@ -36116,7 +35444,7 @@ struct charset_info_st my_charset_utf8_persian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_esperanto_uca_ci= @@ -36148,7 +35476,7 @@ struct charset_info_st my_charset_utf8_esperanto_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_hungarian_uca_ci= @@ -36180,7 +35508,7 @@ struct charset_info_st my_charset_utf8_hungarian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_sinhala_uca_ci= @@ -36212,7 +35540,7 @@ struct charset_info_st my_charset_utf8_sinhala_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; @@ -36245,7 +35573,7 @@ struct charset_info_st my_charset_utf8_german2_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_croatian_mysql561_uca_ci= @@ -36277,7 +35605,7 @@ struct charset_info_st my_charset_utf8_croatian_mysql561_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; @@ -36310,7 +35638,7 @@ struct charset_info_st my_charset_utf8_croatian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; @@ -36343,7 +35671,7 @@ struct charset_info_st my_charset_utf8_myanmar_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; @@ -36376,7 +35704,7 @@ struct charset_info_st my_charset_utf8_unicode_520_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; struct charset_info_st my_charset_utf8_thai_520_w2= @@ -36408,7 +35736,7 @@ struct charset_info_st my_charset_utf8_thai_520_w2= 0, /* escape_with_backslash_is_dangerous */ 2, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler_multilevel + &my_uca_collation_handler_multilevel_utf8mb3 }; struct charset_info_st my_charset_utf8_vietnamese_ci= @@ -36440,7 +35768,7 @@ struct charset_info_st my_charset_utf8_vietnamese_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb3 }; @@ -36473,7 +35801,7 @@ struct charset_info_st my_charset_utf8_unicode_nopad_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_mb_uca_nopad_handler + &my_uca_collation_handler_nopad_utf8mb3 }; @@ -36506,7 +35834,7 @@ struct charset_info_st my_charset_utf8_unicode_520_nopad_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8_handler, - &my_collation_mb_uca_nopad_handler + &my_uca_collation_handler_nopad_utf8mb3 }; #endif /* HAVE_CHARSET_utf8 */ @@ -36514,6 +35842,39 @@ struct charset_info_st my_charset_utf8_unicode_520_nopad_ci= #ifdef HAVE_CHARSET_utf8mb4 +static my_bool +my_uca_coll_init_utf8mb4(struct charset_info_st *cs, MY_CHARSET_LOADER *loader); + + +#define MY_FUNCTION_NAME(x) my_uca_ ## x ## _utf8mb4 +#define MY_MB_WC(scanner, wc, beg, end) (my_mb_wc_utf8mb4_quick(wc, beg, end)) +#define MY_LIKE_RANGE my_like_range_mb +#define MY_UCA_ASCII_OPTIMIZE 1 +#define MY_UCA_COMPILE_CONTRACTIONS 1 +#define MY_UCA_COLL_INIT my_uca_coll_init_utf8mb4 +#include "ctype-uca.ic" + +#define MY_FUNCTION_NAME(x) my_uca_ ## x ## _no_contractions_utf8mb4 +#define MY_MB_WC(scanner, wc, beg, end) (my_mb_wc_utf8mb4_quick(wc, beg, end)) +#define MY_LIKE_RANGE my_like_range_mb +#define MY_UCA_ASCII_OPTIMIZE 1 +#define MY_UCA_COMPILE_CONTRACTIONS 0 +#define MY_UCA_COLL_INIT my_uca_coll_init_utf8mb4 +#include "ctype-uca.ic" + + +static my_bool +my_uca_coll_init_utf8mb4(struct charset_info_st *cs, MY_CHARSET_LOADER *loader) +{ + if (my_coll_init_uca(cs, loader)) + return TRUE; + if (my_uca_collation_can_optimize_no_contractions(cs)) + my_uca_handler_map(cs, &my_uca_package_utf8mb4, + &my_uca_package_no_contractions_utf8mb4); + return FALSE; +} + + extern MY_CHARSET_HANDLER my_charset_utf8mb4_handler; #define MY_CS_UTF8MB4_UCA_FLAGS (MY_CS_COMMON_UCA_FLAGS|MY_CS_UNICODE_SUPPLEMENT) @@ -36548,7 +35909,7 @@ struct charset_info_st my_charset_utf8mb4_unicode_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; @@ -36581,7 +35942,7 @@ struct charset_info_st my_charset_utf8mb4_icelandic_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_latvian_uca_ci= @@ -36613,7 +35974,7 @@ struct charset_info_st my_charset_utf8mb4_latvian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_romanian_uca_ci= @@ -36645,7 +36006,7 @@ struct charset_info_st my_charset_utf8mb4_romanian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_slovenian_uca_ci= @@ -36677,7 +36038,7 @@ struct charset_info_st my_charset_utf8mb4_slovenian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_polish_uca_ci= @@ -36709,7 +36070,7 @@ struct charset_info_st my_charset_utf8mb4_polish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_estonian_uca_ci= @@ -36741,7 +36102,7 @@ struct charset_info_st my_charset_utf8mb4_estonian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_spanish_uca_ci= @@ -36773,7 +36134,7 @@ struct charset_info_st my_charset_utf8mb4_spanish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_swedish_uca_ci= @@ -36805,7 +36166,7 @@ struct charset_info_st my_charset_utf8mb4_swedish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_turkish_uca_ci= @@ -36837,7 +36198,7 @@ struct charset_info_st my_charset_utf8mb4_turkish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_czech_uca_ci= @@ -36869,7 +36230,7 @@ struct charset_info_st my_charset_utf8mb4_czech_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; @@ -36902,7 +36263,7 @@ struct charset_info_st my_charset_utf8mb4_danish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_lithuanian_uca_ci= @@ -36934,7 +36295,7 @@ struct charset_info_st my_charset_utf8mb4_lithuanian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_slovak_uca_ci= @@ -36966,7 +36327,7 @@ struct charset_info_st my_charset_utf8mb4_slovak_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_spanish2_uca_ci= @@ -36998,7 +36359,7 @@ struct charset_info_st my_charset_utf8mb4_spanish2_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_roman_uca_ci= @@ -37030,7 +36391,7 @@ struct charset_info_st my_charset_utf8mb4_roman_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_persian_uca_ci= @@ -37062,7 +36423,7 @@ struct charset_info_st my_charset_utf8mb4_persian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_esperanto_uca_ci= @@ -37094,7 +36455,7 @@ struct charset_info_st my_charset_utf8mb4_esperanto_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_hungarian_uca_ci= @@ -37126,7 +36487,7 @@ struct charset_info_st my_charset_utf8mb4_hungarian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_sinhala_uca_ci= @@ -37158,7 +36519,7 @@ struct charset_info_st my_charset_utf8mb4_sinhala_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_german2_uca_ci= @@ -37190,7 +36551,7 @@ struct charset_info_st my_charset_utf8mb4_german2_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_croatian_mysql561_uca_ci= @@ -37222,7 +36583,7 @@ struct charset_info_st my_charset_utf8mb4_croatian_mysql561_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; @@ -37255,7 +36616,7 @@ struct charset_info_st my_charset_utf8mb4_croatian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; @@ -37288,7 +36649,7 @@ struct charset_info_st my_charset_utf8mb4_myanmar_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_thai_520_w2= @@ -37320,7 +36681,7 @@ struct charset_info_st my_charset_utf8mb4_thai_520_w2= 0, /* escape_with_backslash_is_dangerous */ 2, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler_multilevel + &my_uca_collation_handler_multilevel_utf8mb4 }; struct charset_info_st my_charset_utf8mb4_unicode_520_ci= @@ -37352,7 +36713,7 @@ struct charset_info_st my_charset_utf8mb4_unicode_520_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; @@ -37385,7 +36746,7 @@ struct charset_info_st my_charset_utf8mb4_vietnamese_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_any_uca_handler + &my_uca_collation_handler_utf8mb4 }; @@ -37418,7 +36779,7 @@ struct charset_info_st my_charset_utf8mb4_unicode_nopad_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_mb_uca_nopad_handler + &my_uca_collation_handler_nopad_utf8mb4 }; @@ -37451,7 +36812,7 @@ struct charset_info_st my_charset_utf8mb4_unicode_520_nopad_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf8mb4_handler, - &my_collation_mb_uca_nopad_handler + &my_uca_collation_handler_nopad_utf8mb4 }; @@ -37460,20 +36821,14 @@ struct charset_info_st my_charset_utf8mb4_unicode_520_nopad_ci= #ifdef HAVE_CHARSET_utf32 -MY_COLLATION_HANDLER my_collation_utf32_uca_handler = -{ - my_coll_init_uca, /* init */ - my_strnncoll_any_uca, - my_strnncollsp_any_uca, - my_strnxfrm_any_uca, - my_strnxfrmlen_any_uca, - my_like_range_generic, - my_wildcmp_uca, - NULL, - my_instr_mb, - my_hash_sort_any_uca, - my_propagate_complex -}; +#include "ctype-utf32.h" +#define MY_FUNCTION_NAME(x) my_uca_ ## x ## _utf32 +#define MY_MB_WC(scanner, wc, beg, end) (my_mb_wc_utf32_quick(wc, beg, end)) +#define MY_LIKE_RANGE my_like_range_generic +#define MY_UCA_ASCII_OPTIMIZE 0 +#define MY_UCA_COMPILE_CONTRACTIONS 1 +#define MY_UCA_COLL_INIT my_coll_init_uca +#include "ctype-uca.ic" extern MY_CHARSET_HANDLER my_charset_utf32_handler; @@ -37510,7 +36865,7 @@ struct charset_info_st my_charset_utf32_unicode_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; @@ -37543,7 +36898,7 @@ struct charset_info_st my_charset_utf32_icelandic_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_latvian_uca_ci= @@ -37575,7 +36930,7 @@ struct charset_info_st my_charset_utf32_latvian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_romanian_uca_ci= @@ -37607,7 +36962,7 @@ struct charset_info_st my_charset_utf32_romanian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_slovenian_uca_ci= @@ -37639,7 +36994,7 @@ struct charset_info_st my_charset_utf32_slovenian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_polish_uca_ci= @@ -37671,7 +37026,7 @@ struct charset_info_st my_charset_utf32_polish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_estonian_uca_ci= @@ -37703,7 +37058,7 @@ struct charset_info_st my_charset_utf32_estonian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_spanish_uca_ci= @@ -37735,7 +37090,7 @@ struct charset_info_st my_charset_utf32_spanish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_swedish_uca_ci= @@ -37767,7 +37122,7 @@ struct charset_info_st my_charset_utf32_swedish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_turkish_uca_ci= @@ -37799,7 +37154,7 @@ struct charset_info_st my_charset_utf32_turkish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_czech_uca_ci= @@ -37831,7 +37186,7 @@ struct charset_info_st my_charset_utf32_czech_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; @@ -37864,7 +37219,7 @@ struct charset_info_st my_charset_utf32_danish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_lithuanian_uca_ci= @@ -37896,7 +37251,7 @@ struct charset_info_st my_charset_utf32_lithuanian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_slovak_uca_ci= @@ -37928,7 +37283,7 @@ struct charset_info_st my_charset_utf32_slovak_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_spanish2_uca_ci= @@ -37960,7 +37315,7 @@ struct charset_info_st my_charset_utf32_spanish2_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_roman_uca_ci= @@ -37992,7 +37347,7 @@ struct charset_info_st my_charset_utf32_roman_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_persian_uca_ci= @@ -38024,7 +37379,7 @@ struct charset_info_st my_charset_utf32_persian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_esperanto_uca_ci= @@ -38056,7 +37411,7 @@ struct charset_info_st my_charset_utf32_esperanto_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_hungarian_uca_ci= @@ -38088,7 +37443,7 @@ struct charset_info_st my_charset_utf32_hungarian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_sinhala_uca_ci= @@ -38120,7 +37475,7 @@ struct charset_info_st my_charset_utf32_sinhala_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_german2_uca_ci= @@ -38152,7 +37507,7 @@ struct charset_info_st my_charset_utf32_german2_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_croatian_mysql561_uca_ci= @@ -38184,7 +37539,7 @@ struct charset_info_st my_charset_utf32_croatian_mysql561_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; struct charset_info_st my_charset_utf32_croatian_uca_ci= @@ -38216,7 +37571,7 @@ struct charset_info_st my_charset_utf32_croatian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; @@ -38249,7 +37604,7 @@ struct charset_info_st my_charset_utf32_myanmar_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; @@ -38282,7 +37637,7 @@ struct charset_info_st my_charset_utf32_thai_520_w2= 0, /* escape_with_backslash_is_dangerous */ 2, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_any_uca_handler_multilevel + &my_uca_collation_handler_multilevel_utf32 }; @@ -38315,7 +37670,7 @@ struct charset_info_st my_charset_utf32_unicode_520_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; @@ -38348,7 +37703,7 @@ struct charset_info_st my_charset_utf32_vietnamese_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_utf32_uca_handler + &my_uca_collation_handler_utf32 }; @@ -38381,7 +37736,7 @@ struct charset_info_st my_charset_utf32_unicode_nopad_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_generic_uca_nopad_handler + &my_uca_collation_handler_nopad_utf32 }; @@ -38414,7 +37769,7 @@ struct charset_info_st my_charset_utf32_unicode_520_nopad_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf32_handler, - &my_collation_generic_uca_nopad_handler + &my_uca_collation_handler_nopad_utf32 }; @@ -38424,21 +37779,14 @@ struct charset_info_st my_charset_utf32_unicode_520_nopad_ci= #ifdef HAVE_CHARSET_utf16 - -MY_COLLATION_HANDLER my_collation_utf16_uca_handler = -{ - my_coll_init_uca, /* init */ - my_strnncoll_any_uca, - my_strnncollsp_any_uca, - my_strnxfrm_any_uca, - my_strnxfrmlen_any_uca, - my_like_range_generic, - my_wildcmp_uca, - NULL, - my_instr_mb, - my_hash_sort_any_uca, - my_propagate_complex -}; +#include "ctype-utf16.h" +#define MY_FUNCTION_NAME(x) my_uca_ ## x ## _utf16 +#define MY_MB_WC(scanner, wc, beg, end) (my_mb_wc_utf16_quick(wc, beg, end)) +#define MY_LIKE_RANGE my_like_range_generic +#define MY_UCA_ASCII_OPTIMIZE 0 +#define MY_UCA_COMPILE_CONTRACTIONS 1 +#define MY_UCA_COLL_INIT my_coll_init_uca +#include "ctype-uca.ic" extern MY_CHARSET_HANDLER my_charset_utf16_handler; @@ -38475,7 +37823,7 @@ struct charset_info_st my_charset_utf16_unicode_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; @@ -38508,7 +37856,7 @@ struct charset_info_st my_charset_utf16_icelandic_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_latvian_uca_ci= @@ -38540,7 +37888,7 @@ struct charset_info_st my_charset_utf16_latvian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_romanian_uca_ci= @@ -38572,7 +37920,7 @@ struct charset_info_st my_charset_utf16_romanian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_slovenian_uca_ci= @@ -38604,7 +37952,7 @@ struct charset_info_st my_charset_utf16_slovenian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_polish_uca_ci= @@ -38636,7 +37984,7 @@ struct charset_info_st my_charset_utf16_polish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_estonian_uca_ci= @@ -38668,7 +38016,7 @@ struct charset_info_st my_charset_utf16_estonian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_spanish_uca_ci= @@ -38700,7 +38048,7 @@ struct charset_info_st my_charset_utf16_spanish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_swedish_uca_ci= @@ -38732,7 +38080,7 @@ struct charset_info_st my_charset_utf16_swedish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_turkish_uca_ci= @@ -38764,7 +38112,7 @@ struct charset_info_st my_charset_utf16_turkish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_czech_uca_ci= @@ -38796,7 +38144,7 @@ struct charset_info_st my_charset_utf16_czech_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; @@ -38829,7 +38177,7 @@ struct charset_info_st my_charset_utf16_danish_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_lithuanian_uca_ci= @@ -38861,7 +38209,7 @@ struct charset_info_st my_charset_utf16_lithuanian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_slovak_uca_ci= @@ -38893,7 +38241,7 @@ struct charset_info_st my_charset_utf16_slovak_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_spanish2_uca_ci= @@ -38925,7 +38273,7 @@ struct charset_info_st my_charset_utf16_spanish2_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_roman_uca_ci= @@ -38957,7 +38305,7 @@ struct charset_info_st my_charset_utf16_roman_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_persian_uca_ci= @@ -38989,7 +38337,7 @@ struct charset_info_st my_charset_utf16_persian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_esperanto_uca_ci= @@ -39021,7 +38369,7 @@ struct charset_info_st my_charset_utf16_esperanto_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_hungarian_uca_ci= @@ -39053,7 +38401,7 @@ struct charset_info_st my_charset_utf16_hungarian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_sinhala_uca_ci= @@ -39085,7 +38433,7 @@ struct charset_info_st my_charset_utf16_sinhala_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; struct charset_info_st my_charset_utf16_german2_uca_ci= @@ -39117,7 +38465,7 @@ struct charset_info_st my_charset_utf16_german2_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; @@ -39150,7 +38498,7 @@ struct charset_info_st my_charset_utf16_croatian_mysql561_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; @@ -39183,7 +38531,7 @@ struct charset_info_st my_charset_utf16_croatian_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; @@ -39216,7 +38564,7 @@ struct charset_info_st my_charset_utf16_myanmar_uca_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; @@ -39249,7 +38597,7 @@ struct charset_info_st my_charset_utf16_thai_520_w2= 0, /* escape_with_backslash_is_dangerous */ 2, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_any_uca_handler_multilevel + &my_uca_collation_handler_multilevel_utf16 }; @@ -39282,7 +38630,7 @@ struct charset_info_st my_charset_utf16_unicode_520_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; @@ -39315,7 +38663,7 @@ struct charset_info_st my_charset_utf16_vietnamese_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_utf16_uca_handler + &my_uca_collation_handler_utf16 }; @@ -39348,7 +38696,7 @@ struct charset_info_st my_charset_utf16_unicode_nopad_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_generic_uca_nopad_handler + &my_uca_collation_handler_nopad_utf16 }; @@ -39381,7 +38729,7 @@ struct charset_info_st my_charset_utf16_unicode_520_nopad_ci= 0, /* escape_with_backslash_is_dangerous */ 1, /* levels_for_order */ &my_charset_utf16_handler, - &my_collation_generic_uca_nopad_handler + &my_uca_collation_handler_nopad_utf16 }; diff --git a/strings/ctype-uca.ic b/strings/ctype-uca.ic new file mode 100644 index 00000000000..70c10199e3e --- /dev/null +++ b/strings/ctype-uca.ic @@ -0,0 +1,839 @@ +/* + Copyright (c) 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#ifndef MY_FUNCTION_NAME +#error MY_FUNCTION_NAME is not defined +#endif +#ifndef MY_MB_WC +#error MY_MB_WC is not defined +#endif +#ifndef MY_LIKE_RANGE +#error MY_LIKE_RANGE is not defined +#endif +#ifndef MY_UCA_ASCII_OPTIMIZE +#error MY_ASCII_OPTIMIZE is not defined +#endif +#ifndef MY_UCA_COMPILE_CONTRACTIONS +#error MY_UCA_COMPILE_CONTRACTIONS is not defined +#endif +#ifndef MY_UCA_COLL_INIT +#error MY_UCA_COLL_INIT is not defined +#endif + + +static inline int +MY_FUNCTION_NAME(scanner_next)(my_uca_scanner *scanner) +{ + /* + Check if the weights for the previous character have been + already fully scanned. If yes, then get the next character and + initialize wbeg and wlength to its weight string. + */ + + if (scanner->wbeg[0]) /* More weights left from the previous step: */ + return *scanner->wbeg++; /* return the next weight from expansion */ + + do + { + const uint16 *wpage; + my_wc_t wc[MY_UCA_MAX_CONTRACTION]; + int mblen; + + /* Get next character */ +#if MY_UCA_ASCII_OPTIMIZE + /* Get next ASCII character */ + if (scanner->sbeg < scanner->send && scanner->sbeg[0] < 0x80) + { + wc[0]= scanner->sbeg[0]; + scanner->sbeg+= 1; + +#if MY_UCA_COMPILE_CONTRACTIONS + if (my_uca_needs_context_handling(scanner->level, wc[0])) + { + uint16 *cweight= my_uca_context_weight_find(scanner, wc); + if (cweight) + return *cweight; + } +#endif + + scanner->page= 0; + scanner->code= (int) wc[0]; + scanner->wbeg= scanner->level->weights[0] + scanner->code * scanner->level->lengths[0]; + if (scanner->wbeg[0]) + return *scanner->wbeg++; + continue; + } + else +#endif + /* Get next MB character */ + if (((mblen= MY_MB_WC(scanner, wc, scanner->sbeg, + scanner->send)) <= 0)) + { + if (scanner->sbeg >= scanner->send) + return -1; /* No more bytes, end of line reached */ + /* + There are some more bytes left. Non-positive mb_len means that + we got an incomplete or a bad byte sequence. Consume mbminlen bytes. + */ + if ((scanner->sbeg+= scanner->cs->mbminlen) > scanner->send) + { + /* For safety purposes don't go beyond the string range. */ + scanner->sbeg= scanner->send; + } + /* + Treat every complete or incomplete mbminlen unit as a weight which is + greater than weight for any possible normal character. + 0xFFFF is greater than any possible weight in the UCA weight table. + */ + return 0xFFFF; + } + + scanner->sbeg+= mblen; + if (wc[0] > scanner->level->maxchar) + { + /* Return 0xFFFD as weight for all characters outside BMP */ + scanner->wbeg= nochar; + return 0xFFFD; + } + +#if MY_UCA_COMPILE_CONTRACTIONS + if (my_uca_needs_context_handling(scanner->level, wc[0])) + { + uint16 *cweight= my_uca_context_weight_find(scanner, wc); + if (cweight) + return *cweight; + } +#endif + + /* Process single character */ + scanner->page= wc[0] >> 8; + scanner->code= wc[0] & 0xFF; + + /* If weight page for w[0] does not exist, then calculate algoritmically */ + if (!(wpage= scanner->level->weights[scanner->page])) + return my_uca_scanner_next_implicit(scanner); + + /* Calculate pointer to w[0]'s weight, using page and offset */ + scanner->wbeg= wpage + + scanner->code * scanner->level->lengths[scanner->page]; + } while (!scanner->wbeg[0]); /* Skip ignorable characters */ + + return *scanner->wbeg++; +} + + + +/* + Compares two strings according to the collation + + SYNOPSIS: + strnncoll_onelevel() + cs Character set information + level Weight level (0 primary, 1 secondary, 2 tertiary, etc) + s First string + slen First string length + t Second string + tlen Seconf string length + level DUCETweight level + + NOTES: + Initializes two weight scanners and gets weights + corresponding to two strings in a loop. If weights are not + the same at some step then returns their difference. + + In the while() comparison these situations are possible: + 1. (s_res>0) and (t_res>0) and (s_res == t_res) + Weights are the same so far, continue comparison + 2. (s_res>0) and (t_res>0) and (s_res!=t_res) + A difference has been found, return. + 3. (s_res>0) and (t_res<0) + We have reached the end of the second string, or found + an illegal multibyte sequence in the second string. + Return a positive number, i.e. the first string is bigger. + 4. (s_res<0) and (t_res>0) + We have reached the end of the first string, or found + an illegal multibyte sequence in the first string. + Return a negative number, i.e. the second string is bigger. + 5. (s_res<0) and (t_res<0) + Both scanners returned -1. It means we have riched + the end-of-string of illegal-sequence in both strings + at the same time. Return 0, strings are equal. + + RETURN + Difference between two strings, according to the collation: + 0 - means strings are equal + negative number - means the first string is smaller + positive number - means the first string is bigger +*/ + +static int +MY_FUNCTION_NAME(strnncoll_onelevel)(CHARSET_INFO *cs, + const MY_UCA_WEIGHT_LEVEL *level, + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + my_bool t_is_prefix) +{ + my_uca_scanner sscanner; + my_uca_scanner tscanner; + int s_res; + int t_res; + + my_uca_scanner_init_any(&sscanner, cs, level, s, slen); + my_uca_scanner_init_any(&tscanner, cs, level, t, tlen); + + do + { + s_res= MY_FUNCTION_NAME(scanner_next)(&sscanner); + t_res= MY_FUNCTION_NAME(scanner_next)(&tscanner); + } while ( s_res == t_res && s_res >0); + + return (t_is_prefix && t_res < 0) ? 0 : (s_res - t_res); +} + + +/* + One-level, PAD SPACE. +*/ +static int +MY_FUNCTION_NAME(strnncoll)(CHARSET_INFO *cs, + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + my_bool t_is_prefix) +{ + return MY_FUNCTION_NAME(strnncoll_onelevel)(cs, &cs->uca->level[0], + s, slen, t, tlen, t_is_prefix); +} + + +/* + Multi-level, PAD SPACE. +*/ +static int +MY_FUNCTION_NAME(strnncoll_multilevel)(CHARSET_INFO *cs, + const uchar *s, size_t slen, + const uchar *t, size_t tlen, + my_bool t_is_prefix) +{ + uint i, num_level= cs->levels_for_order; + for (i= 0; i != num_level; i++) + { + int ret= MY_FUNCTION_NAME(strnncoll_onelevel)(cs, &cs->uca->level[i], + s, slen, t, tlen, + t_is_prefix); + if (ret) + return ret; + } + return 0; +} + + +/* + Compares two strings according to the collation, + ignoring trailing spaces. + + SYNOPSIS: + strnncollsp_onelevel() + cs Character set information + level UCA weight level + s First string + slen First string length + t Second string + tlen Seconf string length + level DUCETweight level + + NOTES: + Works exactly the same with my_strnncoll_uca(), + but ignores trailing spaces. + + In the while() comparison these situations are possible: + 1. (s_res>0) and (t_res>0) and (s_res == t_res) + Weights are the same so far, continue comparison + 2. (s_res>0) and (t_res>0) and (s_res!=t_res) + A difference has been found, return. + 3. (s_res>0) and (t_res<0) + We have reached the end of the second string, or found + an illegal multibyte sequence in the second string. + Compare the first string to an infinite array of + space characters until difference is found, or until + the end of the first string. + 4. (s_res<0) and (t_res>0) + We have reached the end of the first string, or found + an illegal multibyte sequence in the first string. + Compare the second string to an infinite array of + space characters until difference is found or until + the end of the second steing. + 5. (s_res<0) and (t_res<0) + Both scanners returned -1. It means we have riched + the end-of-string of illegal-sequence in both strings + at the same time. Return 0, strings are equal. + + RETURN + Difference between two strings, according to the collation: + 0 - means strings are equal + negative number - means the first string is smaller + positive number - means the first string is bigger +*/ + +static int +MY_FUNCTION_NAME(strnncollsp_onelevel)(CHARSET_INFO *cs, + const MY_UCA_WEIGHT_LEVEL *level, + const uchar *s, size_t slen, + const uchar *t, size_t tlen) +{ + my_uca_scanner sscanner, tscanner; + int s_res, t_res; + + my_uca_scanner_init_any(&sscanner, cs, level, s, slen); + my_uca_scanner_init_any(&tscanner, cs, level, t, tlen); + + do + { + s_res= MY_FUNCTION_NAME(scanner_next)(&sscanner); + t_res= MY_FUNCTION_NAME(scanner_next)(&tscanner); + } while ( s_res == t_res && s_res >0); + + if (s_res > 0 && t_res < 0) + { + /* Calculate weight for SPACE character */ + t_res= my_space_weight(level); + + /* compare the first string to spaces */ + do + { + if (s_res != t_res) + return (s_res - t_res); + s_res= MY_FUNCTION_NAME(scanner_next)(&sscanner); + } while (s_res > 0); + return 0; + } + + if (s_res < 0 && t_res > 0) + { + /* Calculate weight for SPACE character */ + s_res= my_space_weight(level); + + /* compare the second string to spaces */ + do + { + if (s_res != t_res) + return (s_res - t_res); + t_res= MY_FUNCTION_NAME(scanner_next)(&tscanner); + } while (t_res > 0); + return 0; + } + + return ( s_res - t_res ); +} + + +/* + One-level, PAD SPACE +*/ +static int +MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs, + const uchar *s, size_t slen, + const uchar *t, size_t tlen) +{ + return MY_FUNCTION_NAME(strnncollsp_onelevel)(cs, &cs->uca->level[0], + s, slen, t, tlen); +} + + +/* + One-level, NO PAD +*/ +static int +MY_FUNCTION_NAME(strnncollsp_nopad)(CHARSET_INFO *cs, + const uchar *s, size_t slen, + const uchar *t, size_t tlen) +{ + return MY_FUNCTION_NAME(strnncoll_onelevel)(cs, &cs->uca->level[0], + s, slen, t, tlen, FALSE); +} + + +/* + Multi-level, PAD SPACE +*/ +static int +MY_FUNCTION_NAME(strnncollsp_multilevel)(CHARSET_INFO *cs, + const uchar *s, size_t slen, + const uchar *t, size_t tlen) +{ + + uint i, num_level= cs->levels_for_order; + for (i= 0; i != num_level; i++) + { + int ret= MY_FUNCTION_NAME(strnncollsp_onelevel)(cs, &cs->uca->level[i], + s, slen, t, tlen); + if (ret) + return ret; + } + return 0; +} + + +/* + Multi-level, NO PAD +*/ +static int +MY_FUNCTION_NAME(strnncollsp_nopad_multilevel)(CHARSET_INFO *cs, + const uchar *s, size_t slen, + const uchar *t, size_t tlen) +{ + uint num_level= cs->levels_for_order; + uint i; + for (i= 0; i != num_level; i++) + { + int ret= MY_FUNCTION_NAME(strnncoll_onelevel)(cs, &cs->uca->level[i], + s, slen, t, tlen, FALSE); + if (ret) + return ret; + } + return 0; +} + + + +/* + Calculates hash value for the given string, + according to the collation, and ignoring trailing spaces. + + SYNOPSIS: + hash_sort() + cs Character set information + s String + slen String's length + n1 First hash parameter + n2 Second hash parameter + + NOTES: + Scans consequently weights and updates + hash parameters n1 and n2. In a case insensitive collation, + upper and lower case of the same letter will return the same + weight sequence, and thus will produce the same hash values + in n1 and n2. + + This functions is used for one-level and for multi-level collations. + We intentionally use only primary level in multi-level collations. + This helps to have PARTITION BY KEY put primarily equal records + into the same partition. E.g. in utf8_thai_520_ci records that differ + only in tone marks go into the same partition. + + RETURN + N/A +*/ + +static void +MY_FUNCTION_NAME(hash_sort)(CHARSET_INFO *cs, + const uchar *s, size_t slen, + ulong *nr1, ulong *nr2) +{ + int s_res; + my_uca_scanner scanner; + int space_weight= my_space_weight(&cs->uca->level[0]); + register ulong m1= *nr1, m2= *nr2; + + my_uca_scanner_init_any(&scanner, cs, &cs->uca->level[0], s, slen); + + while ((s_res= MY_FUNCTION_NAME(scanner_next)(&scanner)) >0) + { + if (s_res == space_weight) + { + /* Combine all spaces to be able to skip end spaces */ + uint count= 0; + do + { + count++; + if ((s_res= MY_FUNCTION_NAME(scanner_next)(&scanner)) <= 0) + { + /* Skip strings at end of string */ + goto end; + } + } + while (s_res == space_weight); + + /* Add back that has for the space characters */ + do + { + /* + We can't use MY_HASH_ADD_16() here as we, because of a misstake + in the original code, where we added the 16 byte variable the + opposite way. Changing this would cause old partitioned tables + to fail. + */ + MY_HASH_ADD(m1, m2, space_weight >> 8); + MY_HASH_ADD(m1, m2, space_weight & 0xFF); + } + while (--count != 0); + + } + /* See comment above why we can't use MY_HASH_ADD_16() */ + MY_HASH_ADD(m1, m2, s_res >> 8); + MY_HASH_ADD(m1, m2, s_res & 0xFF); + } +end: + *nr1= m1; + *nr2= m2; +} + + +static void +MY_FUNCTION_NAME(hash_sort_nopad)(CHARSET_INFO *cs, + const uchar *s, size_t slen, + ulong *nr1, ulong *nr2) +{ + int s_res; + my_uca_scanner scanner; + register ulong m1= *nr1, m2= *nr2; + + my_uca_scanner_init_any(&scanner, cs, &cs->uca->level[0], s, slen); + + while ((s_res= MY_FUNCTION_NAME(scanner_next)(&scanner)) >0) + { + /* See comment above why we can't use MY_HASH_ADD_16() */ + MY_HASH_ADD(m1, m2, s_res >> 8); + MY_HASH_ADD(m1, m2, s_res & 0xFF); + } + *nr1= m1; + *nr2= m2; +} + + + +/* + For the given string creates its "binary image", suitable + to be used in binary comparison, i.e. in memcmp(). + + SYNOPSIS: + my_strnxfrm_uca() + cs Character set information + dst Where to write the image + dstlen Space available for the image, in bytes + src The source string + srclen Length of the source string, in bytes + + NOTES: + In a loop, scans weights from the source string and writes + them into the binary image. In a case insensitive collation, + upper and lower cases of the same letter will produce the + same image subsequences. When we have reached the end-of-string + or found an illegal multibyte sequence, the loop stops. + + It is impossible to restore the original string using its + binary image. + + Binary images are used for bulk comparison purposes, + e.g. in ORDER BY, when it is more efficient to create + a binary image and use it instead of weight scanner + for the original strings for every comparison. + + RETURN + Number of bytes that have been written into the binary image. +*/ + +static uchar * +MY_FUNCTION_NAME(strnxfrm_onelevel_internal)(CHARSET_INFO *cs, + MY_UCA_WEIGHT_LEVEL *level, + uchar *dst, uchar *de, + uint *nweights, + const uchar *src, size_t srclen) +{ + my_uca_scanner scanner; + int s_res; + + DBUG_ASSERT(src || !srclen); + +#if MY_UCA_ASCII_OPTIMIZE && !MY_UCA_COMPILE_CONTRACTIONS + /* + Fast path for the ASCII range with no contractions. + */ + { + const uchar *de2= de - 1; /* Last position where 2 bytes fit */ + const uint16 *weights0= level->weights[0]; + uint lengths0= level->lengths[0]; + for ( ; ; src++, srclen--) + { + const uint16 *weight; + if (!srclen || !*nweights) + return dst; /* Done */ + if (*src > 0x7F) + break; /* Non-ASCII */ + + weight= weights0 + (((uint) *src) * lengths0); + if (!(s_res= *weight)) + continue; /* Ignorable */ + if (weight[1]) /* Expansion (e.g. in a user defined collation */ + break; + + /* Here we have a character with extactly one 2-byte UCA weight */ + if (dst < de2) /* Most typical case is when both bytes fit */ + { + *dst++= s_res >> 8; + *dst++= s_res & 0xFF; + (*nweights)--; + continue; + } + if (dst >= de) /* No space left in "dst" */ + return dst; + *dst++= s_res >> 8; /* There is space only for one byte */ + (*nweights)--; + return dst; + } + } +#endif + + my_uca_scanner_init_any(&scanner, cs, level, src, srclen); + for (; dst < de && *nweights && + (s_res= MY_FUNCTION_NAME(scanner_next)(&scanner)) > 0 ; (*nweights)--) + { + *dst++= s_res >> 8; + if (dst < de) + *dst++= s_res & 0xFF; + } + return dst; +} + + +static uchar * +MY_FUNCTION_NAME(strnxfrm_onelevel)(CHARSET_INFO *cs, + MY_UCA_WEIGHT_LEVEL *level, + uchar *dst, uchar *de, uint nweights, + const uchar *src, size_t srclen, uint flags) +{ + uchar *d0= dst; + dst= MY_FUNCTION_NAME(strnxfrm_onelevel_internal)(cs, level, + dst, de, &nweights, + src, srclen); + DBUG_ASSERT(dst <= de); + if (dst < de && nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE)) + dst= my_strnxfrm_uca_padn(dst, de, nweights, my_space_weight(level)); + DBUG_ASSERT(dst <= de); + my_strxfrm_desc_and_reverse(d0, dst, flags, 0); + return dst; +} + + + +static uchar * +MY_FUNCTION_NAME(strnxfrm_nopad_onelevel)(CHARSET_INFO *cs, + MY_UCA_WEIGHT_LEVEL *level, + uchar *dst, uchar *de, uint nweights, + const uchar *src, size_t srclen, + uint flags) +{ + uchar *d0= dst; + dst= MY_FUNCTION_NAME(strnxfrm_onelevel_internal)(cs, level, + dst, de, &nweights, + src, srclen); + DBUG_ASSERT(dst <= de); + /* Pad with the minimum possible weight on this level */ + if (dst < de && nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE)) + dst= my_strnxfrm_uca_padn(dst, de, nweights, min_weight_on_level(level)); + DBUG_ASSERT(dst <= de); + my_strxfrm_desc_and_reverse(d0, dst, flags, 0); + return dst; +} + + +static size_t +MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags) +{ + uchar *d0= dst; + uchar *de= dst + dstlen; + + /* + There are two ways to handle trailing spaces for PAD SPACE collations: + 1. Keep trailing spaces as they are, so have strnxfrm_onelevel() scan + spaces as normal characters. This will call scanner_next() for every + trailing space and calculate its weight using UCA weights. + 2. Strip trailing spaces before calling strnxfrm_onelevel(), as it will + append weights for implicit spaces anyway, up to the desired key size. + This will effectively generate exactly the same sortable key result. + The latter is much faster. + */ + + if (flags & MY_STRXFRM_PAD_WITH_SPACE) + srclen= cs->cset->lengthsp(cs, (const char*) src, srclen); + dst= MY_FUNCTION_NAME(strnxfrm_onelevel)(cs, &cs->uca->level[0], + dst, de, nweights, + src, srclen, flags); + /* + This can probably be changed to memset(dst, 0, de - dst), + like my_strnxfrm_uca_multilevel() does. + */ + if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de) + dst= my_strnxfrm_uca_pad(dst, de, my_space_weight(&cs->uca->level[0])); + return dst - d0; +} + + +static size_t +MY_FUNCTION_NAME(strnxfrm_nopad)(CHARSET_INFO *cs, + uchar *dst, size_t dstlen, + uint nweights, + const uchar *src, size_t srclen, + uint flags) +{ + uchar *d0= dst; + uchar *de= dst + dstlen; + + dst= MY_FUNCTION_NAME(strnxfrm_nopad_onelevel)(cs, &cs->uca->level[0], + dst, de, nweights, + src, srclen, flags); + if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de) + { + memset(dst, 0, de - dst); + dst= de; + } + return dst - d0; +} + + +static size_t +MY_FUNCTION_NAME(strnxfrm_multilevel)(CHARSET_INFO *cs, + uchar *dst, size_t dstlen, + uint nweights, + const uchar *src, size_t srclen, + uint flags) +{ + uint num_level= cs->levels_for_order; + uchar *d0= dst; + uchar *de= dst + dstlen; + uint current_level; + + for (current_level= 0; current_level != num_level; current_level++) + { + if (!(flags & MY_STRXFRM_LEVEL_ALL) || + (flags & (MY_STRXFRM_LEVEL1 << current_level))) + dst= cs->state & MY_CS_NOPAD ? + MY_FUNCTION_NAME(strnxfrm_nopad_onelevel)(cs, + &cs->uca->level[current_level], + dst, de, nweights, + src, srclen, flags) : + MY_FUNCTION_NAME(strnxfrm_onelevel)(cs, + &cs->uca->level[current_level], + dst, de, nweights, + src, srclen, flags); + } + + if (dst < de && (flags & MY_STRXFRM_PAD_TO_MAXLEN)) + { + memset(dst, 0, de - dst); + dst= de; + } + + return dst - d0; +} + + +/* + One-level, PAD SPACE +*/ +MY_COLLATION_HANDLER MY_FUNCTION_NAME(collation_handler)= +{ + MY_UCA_COLL_INIT, + MY_FUNCTION_NAME(strnncoll), + MY_FUNCTION_NAME(strnncollsp), + MY_FUNCTION_NAME(strnxfrm), + my_strnxfrmlen_any_uca, + MY_LIKE_RANGE, + my_wildcmp_uca, + NULL, /* strcasecmp() */ + my_instr_mb, + MY_FUNCTION_NAME(hash_sort), + my_propagate_complex +}; + + +/* + One-level, NO PAD + For character sets with mbminlen==1 use MY_LIKE_RANGE=my_like_range_mb + For character sets with mbminlen>=2 use MY_LIKE_RANGE=my_like_range_generic +*/ +MY_COLLATION_HANDLER MY_FUNCTION_NAME(collation_handler_nopad)= +{ + MY_UCA_COLL_INIT, + MY_FUNCTION_NAME(strnncoll), + MY_FUNCTION_NAME(strnncollsp_nopad), + MY_FUNCTION_NAME(strnxfrm_nopad), + my_strnxfrmlen_any_uca, + MY_LIKE_RANGE, /* my_like_range_mb or my_like_range_generic */ + my_wildcmp_uca, + NULL, /* strcasecmp() */ + my_instr_mb, + MY_FUNCTION_NAME(hash_sort_nopad), + my_propagate_complex +}; + + +/* + Multi-level, PAD SPACE +*/ +MY_COLLATION_HANDLER MY_FUNCTION_NAME(collation_handler_multilevel)= +{ + MY_UCA_COLL_INIT, + MY_FUNCTION_NAME(strnncoll_multilevel), + MY_FUNCTION_NAME(strnncollsp_multilevel), + MY_FUNCTION_NAME(strnxfrm_multilevel), + my_strnxfrmlen_any_uca_multilevel, + MY_LIKE_RANGE, + my_wildcmp_uca, + NULL, /* strcasecmp() */ + my_instr_mb, + MY_FUNCTION_NAME(hash_sort), + my_propagate_complex +}; + + +/* + Multi-level, NO PAD +*/ +MY_COLLATION_HANDLER MY_FUNCTION_NAME(collation_handler_nopad_multilevel)= +{ + MY_UCA_COLL_INIT, + MY_FUNCTION_NAME(strnncoll_multilevel), + MY_FUNCTION_NAME(strnncollsp_nopad_multilevel), + MY_FUNCTION_NAME(strnxfrm_multilevel), + my_strnxfrmlen_any_uca_multilevel, + MY_LIKE_RANGE, + my_wildcmp_uca, + NULL, /* strcasecmp() */ + my_instr_mb, + MY_FUNCTION_NAME(hash_sort), + my_propagate_complex +}; + + +MY_COLLATION_HANDLER_PACKAGE MY_FUNCTION_NAME(package)= +{ + &MY_FUNCTION_NAME(collation_handler), + &MY_FUNCTION_NAME(collation_handler_nopad), + &MY_FUNCTION_NAME(collation_handler_multilevel), + &MY_FUNCTION_NAME(collation_handler_nopad_multilevel) +}; + + +#undef MY_FUNCTION_NAME +#undef MY_MB_WC +#undef MY_LIKE_RANGE +#undef MY_UCA_ASCII_OPTIMIZE +#undef MY_UCA_COMPILE_CONTRACTIONS +#undef MY_UCA_COLL_INIT diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 7596b7f2168..28e7def3ddf 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -23,6 +23,8 @@ #include <my_sys.h> #include <stdarg.h> +#include "ctype-unidata.h" + #if defined(HAVE_CHARSET_utf16) || defined(HAVE_CHARSET_ucs2) #define HAVE_CHARSET_mb2 @@ -1184,35 +1186,7 @@ my_lengthsp_mb2(CHARSET_INFO *cs __attribute__((unused)), but the JSON functions needed my_utf16_uni() so the #ifdef was moved lower. */ - - -/* - D800..DB7F - Non-provate surrogate high (896 pages) - DB80..DBFF - Private surrogate high (128 pages) - DC00..DFFF - Surrogate low (1024 codes in a page) -*/ -#define MY_UTF16_SURROGATE_HIGH_FIRST 0xD800 -#define MY_UTF16_SURROGATE_HIGH_LAST 0xDBFF -#define MY_UTF16_SURROGATE_LOW_FIRST 0xDC00 -#define MY_UTF16_SURROGATE_LOW_LAST 0xDFFF - -#define MY_UTF16_HIGH_HEAD(x) ((((uchar) (x)) & 0xFC) == 0xD8) -#define MY_UTF16_LOW_HEAD(x) ((((uchar) (x)) & 0xFC) == 0xDC) -/* Test if a byte is a leading byte of a high or low surrogate head: */ -#define MY_UTF16_SURROGATE_HEAD(x) ((((uchar) (x)) & 0xF8) == 0xD8) -/* Test if a Unicode code point is a high or low surrogate head */ -#define MY_UTF16_SURROGATE(x) (((x) & 0xF800) == 0xD800) - -#define MY_UTF16_WC2(a, b) ((a << 8) + b) - -/* - a= 110110?? (<< 18) - b= ???????? (<< 10) - c= 110111?? (<< 8) - d= ???????? (<< 0) -*/ -#define MY_UTF16_WC4(a, b, c, d) (((a & 3) << 18) + (b << 10) + \ - ((c & 3) << 8) + d + 0x10000) +#include "ctype-utf16.h" #define IS_MB2_CHAR(b0,b1) (!MY_UTF16_SURROGATE_HEAD(b0)) #define IS_MB4_CHAR(b0,b1,b2,b3) (MY_UTF16_HIGH_HEAD(b0) && MY_UTF16_LOW_HEAD(b2)) @@ -1220,10 +1194,17 @@ my_lengthsp_mb2(CHARSET_INFO *cs __attribute__((unused)), static inline int my_weight_mb2_utf16mb2_general_ci(uchar b0, uchar b1) { my_wc_t wc= MY_UTF16_WC2(b0, b1); - MY_UNICASE_CHARACTER *page= my_unicase_default.page[wc >> 8]; + MY_UNICASE_CHARACTER *page= my_unicase_default_pages[wc >> 8]; return (int) (page ? page[wc & 0xFF].sort : wc); } #define MY_FUNCTION_NAME(x) my_ ## x ## _utf16_general_ci +#define DEFINE_STRNXFRM_UNICODE +#define DEFINE_STRNXFRM_UNICODE_NOPAD +#define MY_MB_WC(cs, pwc, s, e) my_mb_wc_utf16_quick(pwc, s, e) +#define OPTIMIZE_ASCII 0 +#define UNICASE_MAXCHAR MY_UNICASE_INFO_DEFAULT_MAXCHAR +#define UNICASE_PAGE0 my_unicase_default_page00 +#define UNICASE_PAGES my_unicase_default_pages #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) my_weight_mb2_utf16mb2_general_ci(b0,b1) #define WEIGHT_MB4(b0,b1,b2,b3) MY_CS_REPLACEMENT_CHARACTER @@ -1261,32 +1242,7 @@ static inline int my_weight_mb2_utf16mb2_general_ci(uchar b0, uchar b1) my_utf16_uni(CHARSET_INFO *cs __attribute__((unused)), my_wc_t *pwc, const uchar *s, const uchar *e) { - if (s + 2 > e) - return MY_CS_TOOSMALL2; - - /* - High bytes: 0xD[89AB] = B'110110??' - Low bytes: 0xD[CDEF] = B'110111??' - Surrogate mask: 0xFC = B'11111100' - */ - - if (MY_UTF16_HIGH_HEAD(*s)) /* Surrogate head */ - { - if (s + 4 > e) - return MY_CS_TOOSMALL4; - - if (!MY_UTF16_LOW_HEAD(s[2])) /* Broken surrigate pair */ - return MY_CS_ILSEQ; - - *pwc= MY_UTF16_WC4(s[0], s[1], s[2], s[3]); - return 4; - } - - if (MY_UTF16_LOW_HEAD(*s)) /* Low surrogate part without high part */ - return MY_CS_ILSEQ; - - *pwc= MY_UTF16_WC2(s[0], s[1]); - return 2; + return my_mb_wc_utf16_quick(pwc, s, e); } @@ -1546,7 +1502,7 @@ static MY_COLLATION_HANDLER my_collation_utf16_general_ci_handler = NULL, /* init */ my_strnncoll_utf16_general_ci, my_strnncollsp_utf16_general_ci, - my_strnxfrm_unicode, + my_strnxfrm_utf16_general_ci, my_strnxfrmlen_unicode, my_like_range_generic, my_wildcmp_utf16_ci, @@ -1578,7 +1534,7 @@ static MY_COLLATION_HANDLER my_collation_utf16_general_nopad_ci_handler = NULL, /* init */ my_strnncoll_utf16_general_ci, my_strnncollsp_utf16_general_nopad_ci, - my_strnxfrm_unicode_nopad, + my_strnxfrm_nopad_utf16_general_ci, my_strnxfrmlen_unicode, my_like_range_generic, my_wildcmp_utf16_ci, @@ -1775,6 +1731,13 @@ struct charset_info_st my_charset_utf16_nopad_bin= #define IS_MB4_CHAR(b0,b1,b2,b3) (MY_UTF16_HIGH_HEAD(b1) && MY_UTF16_LOW_HEAD(b3)) #define MY_FUNCTION_NAME(x) my_ ## x ## _utf16le_general_ci +#define DEFINE_STRNXFRM_UNICODE +#define DEFINE_STRNXFRM_UNICODE_NOPAD +#define MY_MB_WC(cs, pwc, s, e) (cs->cset->mb_wc(cs, pwc, s, e)) +#define OPTIMIZE_ASCII 0 +#define UNICASE_MAXCHAR MY_UNICASE_INFO_DEFAULT_MAXCHAR +#define UNICASE_PAGE0 my_unicase_default_page00 +#define UNICASE_PAGES my_unicase_default_pages #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB2(b0,b1) my_weight_mb2_utf16mb2_general_ci(b1,b0) #define WEIGHT_MB4(b0,b1,b2,b3) MY_CS_REPLACEMENT_CHARACTER @@ -1879,7 +1842,7 @@ static MY_COLLATION_HANDLER my_collation_utf16le_general_ci_handler = NULL, /* init */ my_strnncoll_utf16le_general_ci, my_strnncollsp_utf16le_general_ci, - my_strnxfrm_unicode, + my_strnxfrm_utf16le_general_ci, my_strnxfrmlen_unicode, my_like_range_generic, my_wildcmp_utf16_ci, @@ -1911,7 +1874,7 @@ static MY_COLLATION_HANDLER my_collation_utf16le_general_nopad_ci_handler = NULL, /* init */ my_strnncoll_utf16le_general_ci, my_strnncollsp_utf16le_general_nopad_ci, - my_strnxfrm_unicode_nopad, + my_strnxfrm_nopad_utf16le_general_ci, my_strnxfrmlen_unicode, my_like_range_generic, my_wildcmp_utf16_ci, @@ -2109,6 +2072,8 @@ struct charset_info_st my_charset_utf16le_nopad_bin= #ifdef HAVE_CHARSET_utf32 +#include "ctype-utf32.h" + /* Check is b0 and b1 start a valid UTF32 four-byte sequence. Don't accept characters greater than U+10FFFF. @@ -2117,8 +2082,6 @@ struct charset_info_st my_charset_utf16le_nopad_bin= #define IS_MB4_CHAR(b0,b1,b2,b3) (IS_UTF32_MBHEAD4(b0,b1)) -#define MY_UTF32_WC4(b0,b1,b2,b3) ((((my_wc_t)b0) << 24) + (b1 << 16) + \ - (b2 << 8) + (b3)) static inline int my_weight_utf32_general_ci(uchar b0, uchar b1, uchar b2, uchar b3) @@ -2126,12 +2089,19 @@ static inline int my_weight_utf32_general_ci(uchar b0, uchar b1, my_wc_t wc= MY_UTF32_WC4(b0, b1, b2, b3); if (wc <= 0xFFFF) { - MY_UNICASE_CHARACTER *page= my_unicase_default.page[wc >> 8]; + MY_UNICASE_CHARACTER *page= my_unicase_default_pages[wc >> 8]; return (int) (page ? page[wc & 0xFF].sort : wc); } return MY_CS_REPLACEMENT_CHARACTER; } #define MY_FUNCTION_NAME(x) my_ ## x ## _utf32_general_ci +#define DEFINE_STRNXFRM_UNICODE +#define DEFINE_STRNXFRM_UNICODE_NOPAD +#define MY_MB_WC(cs, pwc, s, e) my_mb_wc_utf32_quick(pwc, s, e) +#define OPTIMIZE_ASCII 0 +#define UNICASE_MAXCHAR MY_UNICASE_INFO_DEFAULT_MAXCHAR +#define UNICASE_PAGE0 my_unicase_default_page00 +#define UNICASE_PAGES my_unicase_default_pages #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB4(b0,b1,b2,b3) my_weight_utf32_general_ci(b0, b1, b2, b3) #include "strcoll.ic" @@ -2161,10 +2131,7 @@ static int my_utf32_uni(CHARSET_INFO *cs __attribute__((unused)), my_wc_t *pwc, const uchar *s, const uchar *e) { - if (s + 4 > e) - return MY_CS_TOOSMALL4; - *pwc= MY_UTF32_WC4(s[0], s[1], s[2], s[3]); - return *pwc > 0x10FFFF ? MY_CS_ILSEQ : 4; + return my_mb_wc_utf32_quick(pwc, s, e); } @@ -2698,7 +2665,7 @@ static MY_COLLATION_HANDLER my_collation_utf32_general_ci_handler = NULL, /* init */ my_strnncoll_utf32_general_ci, my_strnncollsp_utf32_general_ci, - my_strnxfrm_unicode, + my_strnxfrm_utf32_general_ci, my_strnxfrmlen_unicode, my_like_range_generic, my_wildcmp_utf32_ci, @@ -2730,7 +2697,7 @@ static MY_COLLATION_HANDLER my_collation_utf32_general_nopad_ci_handler = NULL, /* init */ my_strnncoll_utf32_general_ci, my_strnncollsp_utf32_general_nopad_ci, - my_strnxfrm_unicode_nopad, + my_strnxfrm_nopad_utf32_general_ci, my_strnxfrmlen_unicode, my_like_range_generic, my_wildcmp_utf32_ci, @@ -2928,6 +2895,8 @@ struct charset_info_st my_charset_utf32_nopad_bin= #ifdef HAVE_CHARSET_ucs2 +#include "ctype-ucs2.h" + static const uchar ctype_ucs2[] = { 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 40, 40, 40, 40, 40, 32, 32, @@ -2995,20 +2964,30 @@ static const uchar to_upper_ucs2[] = { static inline int my_weight_mb2_ucs2_general_ci(uchar b0, uchar b1) { my_wc_t wc= UCS2_CODE(b0, b1); - MY_UNICASE_CHARACTER *page= my_unicase_default.page[wc >> 8]; + MY_UNICASE_CHARACTER *page= my_unicase_default_pages[wc >> 8]; return (int) (page ? page[wc & 0xFF].sort : wc); } -#define MY_FUNCTION_NAME(x) my_ ## x ## _ucs2_general_ci -#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) -#define WEIGHT_MB2(b0,b1) my_weight_mb2_ucs2_general_ci(b0,b1) +#define MY_FUNCTION_NAME(x) my_ ## x ## _ucs2_general_ci +#define DEFINE_STRNXFRM_UNICODE +#define DEFINE_STRNXFRM_UNICODE_NOPAD +#define MY_MB_WC(cs, pwc, s, e) my_mb_wc_ucs2_quick(pwc, s, e) +#define OPTIMIZE_ASCII 0 +#define UNICASE_MAXCHAR MY_UNICASE_INFO_DEFAULT_MAXCHAR +#define UNICASE_PAGE0 my_unicase_default_page00 +#define UNICASE_PAGES my_unicase_default_pages +#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) +#define WEIGHT_MB2(b0,b1) my_weight_mb2_ucs2_general_ci(b0,b1) #include "strcoll.ic" -#define MY_FUNCTION_NAME(x) my_ ## x ## _ucs2_bin -#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) -#define WEIGHT_MB2(b0,b1) UCS2_CODE(b0,b1) +#define MY_FUNCTION_NAME(x) my_ ## x ## _ucs2_bin +#define DEFINE_STRNXFRM_UNICODE_BIN2 +#define MY_MB_WC(cs, pwc, s, e) my_mb_wc_ucs2_quick(pwc, s, e) +#define OPTIMIZE_ASCII 0 +#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) +#define WEIGHT_MB2(b0,b1) UCS2_CODE(b0,b1) #include "strcoll.ic" @@ -3037,11 +3016,7 @@ my_charlen_ucs2(CHARSET_INFO *cs __attribute__((unused)), static int my_ucs2_uni(CHARSET_INFO *cs __attribute__((unused)), my_wc_t * pwc, const uchar *s, const uchar *e) { - if (s+2 > e) /* Need 2 characters */ - return MY_CS_TOOSMALL2; - - *pwc= ((uchar)s[0]) * 256 + ((uchar)s[1]); - return 2; + return my_mb_wc_ucs2_quick(pwc, s, e); } static int my_uni_ucs2(CHARSET_INFO *cs __attribute__((unused)) , @@ -3280,7 +3255,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler = NULL, /* init */ my_strnncoll_ucs2_general_ci, my_strnncollsp_ucs2_general_ci, - my_strnxfrm_unicode, + my_strnxfrm_ucs2_general_ci, my_strnxfrmlen_unicode, my_like_range_generic, my_wildcmp_ucs2_ci, @@ -3296,7 +3271,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler = NULL, /* init */ my_strnncoll_ucs2_bin, my_strnncollsp_ucs2_bin, - my_strnxfrm_unicode, + my_strnxfrm_ucs2_bin, my_strnxfrmlen_unicode, my_like_range_generic, my_wildcmp_ucs2_bin, @@ -3312,7 +3287,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_general_nopad_ci_handler = NULL, /* init */ my_strnncoll_ucs2_general_ci, my_strnncollsp_ucs2_general_nopad_ci, - my_strnxfrm_unicode_nopad, + my_strnxfrm_nopad_ucs2_general_ci, my_strnxfrmlen_unicode, my_like_range_generic, my_wildcmp_ucs2_ci, @@ -3328,7 +3303,7 @@ static MY_COLLATION_HANDLER my_collation_ucs2_nopad_bin_handler = NULL, /* init */ my_strnncoll_ucs2_bin, my_strnncollsp_ucs2_nopad_bin, - my_strnxfrm_unicode_nopad, + my_strnxfrm_nopad_ucs2_bin, my_strnxfrmlen_unicode, my_like_range_generic, my_wildcmp_ucs2_bin, diff --git a/strings/ctype-ucs2.h b/strings/ctype-ucs2.h new file mode 100644 index 00000000000..c989324172d --- /dev/null +++ b/strings/ctype-ucs2.h @@ -0,0 +1,32 @@ +/* + Copyright (c) 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _CTYPE_UCS2_H +#define _CTYPE_UCS2_H + + +static inline int +my_mb_wc_ucs2_quick(my_wc_t * pwc, const uchar *s, const uchar *e) +{ + if (s+2 > e) /* Need 2 characters */ + return MY_CS_TOOSMALL2; + *pwc= ((uchar)s[0]) * 256 + ((uchar)s[1]); + return 2; +} + + +#endif /* _CTYPE_UCS2_H */ diff --git a/strings/ctype-unidata.h b/strings/ctype-unidata.h new file mode 100644 index 00000000000..6712f5e1d79 --- /dev/null +++ b/strings/ctype-unidata.h @@ -0,0 +1,31 @@ +#ifndef CTYPE_UNIDATA_H_INCLUDED +#define CTYPE_UNIDATA_H_INCLUDED +/* + Copyright (c) 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#define MY_UNICASE_INFO_DEFAULT_MAXCHAR 0xFFFF +extern MY_UNICASE_CHARACTER my_unicase_default_page00[256]; +extern MY_UNICASE_CHARACTER *my_unicase_default_pages[256]; + +size_t my_strxfrm_pad_nweights_unicode(uchar *str, uchar *strend, size_t nweights); +size_t my_strxfrm_pad_unicode(uchar *str, uchar *strend); + + +#define PUT_WC_BE2_HAVE_1BYTE(dst, de, wc) \ + do { *dst++= (uchar) (wc >> 8); if (dst < de) *dst++= (uchar) (wc & 0xFF); } while(0) + +#endif /* CTYPE_UNIDATA_H_INCLUDED */ diff --git a/strings/ctype-utf16.h b/strings/ctype-utf16.h new file mode 100644 index 00000000000..d4cf4664f97 --- /dev/null +++ b/strings/ctype-utf16.h @@ -0,0 +1,80 @@ +/* + Copyright (c) 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _CTYPE_UTF16_H +#define _CTYPE_UTF16_H + +/* + D800..DB7F - Non-provate surrogate high (896 pages) + DB80..DBFF - Private surrogate high (128 pages) + DC00..DFFF - Surrogate low (1024 codes in a page) +*/ +#define MY_UTF16_SURROGATE_HIGH_FIRST 0xD800 +#define MY_UTF16_SURROGATE_HIGH_LAST 0xDBFF +#define MY_UTF16_SURROGATE_LOW_FIRST 0xDC00 +#define MY_UTF16_SURROGATE_LOW_LAST 0xDFFF + +#define MY_UTF16_HIGH_HEAD(x) ((((uchar) (x)) & 0xFC) == 0xD8) +#define MY_UTF16_LOW_HEAD(x) ((((uchar) (x)) & 0xFC) == 0xDC) +/* Test if a byte is a leading byte of a high or low surrogate head: */ +#define MY_UTF16_SURROGATE_HEAD(x) ((((uchar) (x)) & 0xF8) == 0xD8) +/* Test if a Unicode code point is a high or low surrogate head */ +#define MY_UTF16_SURROGATE(x) (((x) & 0xF800) == 0xD800) + +#define MY_UTF16_WC2(a, b) ((a << 8) + b) + +/* + a= 110110?? (<< 18) + b= ???????? (<< 10) + c= 110111?? (<< 8) + d= ???????? (<< 0) +*/ +#define MY_UTF16_WC4(a, b, c, d) (((a & 3) << 18) + (b << 10) + \ + ((c & 3) << 8) + d + 0x10000) + +static inline int +my_mb_wc_utf16_quick(my_wc_t *pwc, const uchar *s, const uchar *e) +{ + if (s + 2 > e) + return MY_CS_TOOSMALL2; + + /* + High bytes: 0xD[89AB] = B'110110??' + Low bytes: 0xD[CDEF] = B'110111??' + Surrogate mask: 0xFC = B'11111100' + */ + + if (MY_UTF16_HIGH_HEAD(*s)) /* Surrogate head */ + { + if (s + 4 > e) + return MY_CS_TOOSMALL4; + + if (!MY_UTF16_LOW_HEAD(s[2])) /* Broken surrigate pair */ + return MY_CS_ILSEQ; + + *pwc= MY_UTF16_WC4(s[0], s[1], s[2], s[3]); + return 4; + } + + if (MY_UTF16_LOW_HEAD(*s)) /* Low surrogate part without high part */ + return MY_CS_ILSEQ; + + *pwc= MY_UTF16_WC2(s[0], s[1]); + return 2; +} + +#endif /* _CTYPE_UTF16_H */ diff --git a/strings/ctype-utf32.h b/strings/ctype-utf32.h new file mode 100644 index 00000000000..e295dc6d081 --- /dev/null +++ b/strings/ctype-utf32.h @@ -0,0 +1,33 @@ +/* + Copyright (c) 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _CTYPE_UTF32_H +#define _CTYPE_UTF32_H + +#define MY_UTF32_WC4(b0,b1,b2,b3) ((((my_wc_t)b0) << 24) + (b1 << 16) + \ + (b2 << 8) + (b3)) + +static inline int +my_mb_wc_utf32_quick(my_wc_t *pwc, const uchar *s, const uchar *e) +{ + if (s + 4 > e) + return MY_CS_TOOSMALL4; + *pwc= MY_UTF32_WC4(s[0], s[1], s[2], s[3]); + return *pwc > 0x10FFFF ? MY_CS_ILSEQ : 4; +} + +#endif /* _CTYPE_UTF32_H */ diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 4ef376dccc8..4ddb086b734 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -26,78 +26,10 @@ #define EILSEQ ENOENT #endif -/* Detect special bytes and sequences */ -#define IS_CONTINUATION_BYTE(c) (((uchar) (c) ^ 0x80) < 0x40) -/* - Check MB2 character assuming that b0 is alredy known to be >= 0xC2. - Use this macro if the caller already checked b0 for: - - an MB1 character - - an unused gap between MB1 and MB2HEAD -*/ -#define IS_UTF8MB2_STEP2(b0,b1) (((uchar) (b0) < 0xE0) && \ - IS_CONTINUATION_BYTE((uchar) b1)) +#include "ctype-utf8.h" +#include "ctype-unidata.h" -/* - Check MB3 character assuming that b0 is already known to be - in the valid MB3HEAD range [0xE0..0xEF]. -*/ -#define IS_UTF8MB3_STEP2(b0,b1,b2) (IS_CONTINUATION_BYTE(b1) && \ - IS_CONTINUATION_BYTE(b2) && \ - ((uchar) b0 >= 0xe1 || (uchar) b1 >= 0xa0)) - -/* - Check MB3 character assuming that b0 is already known to be >= 0xE0, - but is not checked for the high end 0xF0 yet. - Use this macro if the caller already checked b0 for: - - an MB1 character - - an unused gap between MB1 and MB2HEAD - - an MB2HEAD -*/ -#define IS_UTF8MB3_STEP3(b0,b1,b2) (((uchar) (b0) < 0xF0) && \ - IS_UTF8MB3_STEP2(b0,b1,b2)) - -/* - UTF-8 quick four-byte mask: - 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - Encoding allows to encode U+00010000..U+001FFFFF - - The maximum character defined in the Unicode standard is U+0010FFFF. - Higher characters U+00110000..U+001FFFFF are not used. - - 11110000.10010000.10xxxxxx.10xxxxxx == F0.90.80.80 == U+00010000 (min) - 11110100.10001111.10111111.10111111 == F4.8F.BF.BF == U+0010FFFF (max) - - Valid codes: - [F0][90..BF][80..BF][80..BF] - [F1][80..BF][80..BF][80..BF] - [F2][80..BF][80..BF][80..BF] - [F3][80..BF][80..BF][80..BF] - [F4][80..8F][80..BF][80..BF] -*/ - -/* - Check MB4 character assuming that b0 is already - known to be in the range [0xF0..0xF4] -*/ -#define IS_UTF8MB4_STEP2(b0,b1,b2,b3) (IS_CONTINUATION_BYTE(b1) && \ - IS_CONTINUATION_BYTE(b2) && \ - IS_CONTINUATION_BYTE(b3) && \ - (b0 >= 0xf1 || b1 >= 0x90) && \ - (b0 <= 0xf3 || b1 <= 0x8F)) -#define IS_UTF8MB4_STEP3(b0,b1,b2,b3) (((uchar) (b0) < 0xF5) && \ - IS_UTF8MB4_STEP2(b0,b1,b2,b3)) - -/* Convert individual bytes to Unicode code points */ -#define UTF8MB2_CODE(b0,b1) (((my_wc_t) ((uchar) b0 & 0x1f) << 6) |\ - ((my_wc_t) ((uchar) b1 ^ 0x80))) -#define UTF8MB3_CODE(b0,b1,b2) (((my_wc_t) ((uchar) b0 & 0x0f) << 12) |\ - ((my_wc_t) ((uchar) b1 ^ 0x80) << 6) |\ - ((my_wc_t) ((uchar) b2 ^ 0x80))) -#define UTF8MB4_CODE(b0,b1,b2,b3) (((my_wc_t) ((uchar) b0 & 0x07) << 18) |\ - ((my_wc_t) ((uchar) b1 ^ 0x80) << 12) |\ - ((my_wc_t) ((uchar) b2 ^ 0x80) << 6) |\ - (my_wc_t) ((uchar) b3 ^ 0x80)) /* Definitions for strcoll.ic */ #define IS_MB1_CHAR(x) ((uchar) (x) < 0x80) @@ -180,7 +112,7 @@ int my_valid_mbcharlen_utf8mb3(const uchar *s, const uchar *e) #include "my_uctype.h" -static MY_UNICASE_CHARACTER plane00[]={ +MY_UNICASE_CHARACTER my_unicase_default_page00[]={ {0x0000,0x0000,0x0000}, {0x0001,0x0001,0x0001}, {0x0002,0x0002,0x0002}, {0x0003,0x0003,0x0003}, {0x0004,0x0004,0x0004}, {0x0005,0x0005,0x0005}, @@ -313,7 +245,7 @@ static MY_UNICASE_CHARACTER plane00[]={ /* - Almost similar to plane00, but maps sorting order + Almost similar to my_unicase_default_page00, but maps sorting order for U+00DF to 0x00DF instead of 0x0053. */ static MY_UNICASE_CHARACTER plane00_mysql500[]={ @@ -1759,9 +1691,10 @@ static MY_UNICASE_CHARACTER planeFF[]={ }; -static MY_UNICASE_CHARACTER *my_unicase_pages_default[256]= +MY_UNICASE_CHARACTER *my_unicase_default_pages[256]= { - plane00, plane01, plane02, plane03, plane04, plane05, NULL, NULL, + my_unicase_default_page00, + plane01, plane02, plane03, plane04, plane05, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, plane1E, plane1F, @@ -1798,8 +1731,8 @@ static MY_UNICASE_CHARACTER *my_unicase_pages_default[256]= MY_UNICASE_INFO my_unicase_default= { - 0xFFFF, - my_unicase_pages_default + MY_UNICASE_INFO_DEFAULT_MAXCHAR, + my_unicase_default_pages }; @@ -4646,7 +4579,7 @@ my_wildcmp_unicode(CHARSET_INFO *cs, @return Result length */ -static size_t +size_t my_strxfrm_pad_nweights_unicode(uchar *str, uchar *strend, size_t nweights) { uchar *str0; @@ -4675,7 +4608,7 @@ my_strxfrm_pad_nweights_unicode(uchar *str, uchar *strend, size_t nweights) @return Result length */ -static size_t +size_t my_strxfrm_pad_unicode(uchar *str, uchar *strend) { uchar *str0= str; @@ -4690,95 +4623,6 @@ my_strxfrm_pad_unicode(uchar *str, uchar *strend) } -size_t my_strnxfrm_unicode_internal(CHARSET_INFO *cs, - uchar *dst, uchar *de, uint *nweights, - const uchar *src, const uchar *se) -{ - my_wc_t UNINIT_VAR(wc); - int res; - uchar *dst0= dst; - MY_UNICASE_INFO *uni_plane= (cs->state & MY_CS_BINSORT) ? - NULL : cs->caseinfo; - - DBUG_ASSERT(src || !se); - - for (; dst < de && *nweights; (*nweights)--) - { - if ((res= cs->cset->mb_wc(cs, &wc, src, se)) <= 0) - break; - src+= res; - - if (uni_plane) - my_tosort_unicode(uni_plane, &wc, cs->state); - - *dst++= (uchar) (wc >> 8); - if (dst < de) - *dst++= (uchar) (wc & 0xFF); - } - return dst - dst0; -} - - -/* - Store sorting weights using 2 bytes per character. - - This function is shared between - - utf8mb3_general_ci, utf8_bin, ucs2_general_ci, ucs2_bin - which support BMP only (U+0000..U+FFFF). - - utf8mb4_general_ci, utf16_general_ci, utf32_general_ci, - which map all supplementary characters to weight 0xFFFD. -*/ -size_t -my_strnxfrm_unicode(CHARSET_INFO *cs, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - uchar *dst0= dst; - uchar *de= dst + dstlen; - dst+= my_strnxfrm_unicode_internal(cs, dst, de, &nweights, - src, src + srclen); - DBUG_ASSERT(dst <= de); /* Safety */ - - if (dst < de && nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE)) - dst+= my_strxfrm_pad_nweights_unicode(dst, de, nweights); - - my_strxfrm_desc_and_reverse(dst0, dst, flags, 0); - - if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de) - dst+= my_strxfrm_pad_unicode(dst, de); - return dst - dst0; -} - - -size_t -my_strnxfrm_unicode_nopad(CHARSET_INFO *cs, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - uchar *dst0= dst; - uchar *de= dst + dstlen; - dst+= my_strnxfrm_unicode_internal(cs, dst, de, &nweights, - src, src + srclen); - DBUG_ASSERT(dst <= de); /* Safety */ - - if (dst < de && nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE)) - { - size_t len= de - dst; - set_if_smaller(len, nweights * 2); - memset(dst, 0x00, len); - dst+= len; - } - - my_strxfrm_desc_and_reverse(dst0, dst, flags, 0); - - if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de) - { - memset(dst, 0x00, de - dst); - dst= de; - } - return dst - dst0; -} - /* For BMP-only collations that use 2 bytes per weight. */ @@ -4977,42 +4821,7 @@ static const uchar to_upper_utf8[] = { static int my_utf8_uni(CHARSET_INFO *cs __attribute__((unused)), my_wc_t * pwc, const uchar *s, const uchar *e) { - uchar c; - - if (s >= e) - return MY_CS_TOOSMALL; - - c= s[0]; - if (c < 0x80) - { - *pwc = c; - return 1; - } - else if (c < 0xc2) - return MY_CS_ILSEQ; - else if (c < 0xe0) - { - if (s+2 > e) /* We need 2 characters */ - return MY_CS_TOOSMALL2; - - if (!(IS_CONTINUATION_BYTE(s[1]))) - return MY_CS_ILSEQ; - - *pwc= UTF8MB2_CODE(c, s[1]); - return 2; - } - else if (c < 0xf0) - { - if (s+3 > e) /* We need 3 characters */ - return MY_CS_TOOSMALL3; - - if (!IS_UTF8MB3_STEP2(c, s[1], s[2])) - return MY_CS_ILSEQ; - - *pwc= UTF8MB3_CODE(c, s[1], s[2]); - return 3; - } - return MY_CS_ILSEQ; + return my_mb_wc_utf8mb3_quick(pwc, s, e); } @@ -5308,7 +5117,7 @@ int my_strcasecmp_utf8(CHARSET_INFO *cs, const char *s, const char *t) It represents a single byte character. Convert it into weight according to collation. */ - s_wc= plane00[(uchar) s[0]].tolower; + s_wc= my_unicase_default_page00[(uchar) s[0]].tolower; s++; } else @@ -5350,7 +5159,7 @@ int my_strcasecmp_utf8(CHARSET_INFO *cs, const char *s, const char *t) if ((uchar) t[0] < 128) { /* Convert single byte character into weight */ - t_wc= plane00[(uchar) t[0]].tolower; + t_wc= my_unicase_default_page00[(uchar) t[0]].tolower; t++; } else @@ -5413,14 +5222,14 @@ int my_charlen_utf8(CHARSET_INFO *cs __attribute__((unused)), static inline int my_weight_mb1_utf8_general_ci(uchar b) { - return (int) plane00[b & 0xFF].sort; + return (int) my_unicase_default_page00[b & 0xFF].sort; } static inline int my_weight_mb2_utf8_general_ci(uchar b0, uchar b1) { my_wc_t wc= UTF8MB2_CODE(b0, b1); - MY_UNICASE_CHARACTER *page= my_unicase_pages_default[wc >> 8]; + MY_UNICASE_CHARACTER *page= my_unicase_default_pages[wc >> 8]; return (int) (page ? page[wc & 0xFF].sort : wc); } @@ -5428,16 +5237,23 @@ static inline int my_weight_mb2_utf8_general_ci(uchar b0, uchar b1) static inline int my_weight_mb3_utf8_general_ci(uchar b0, uchar b1, uchar b2) { my_wc_t wc= UTF8MB3_CODE(b0, b1, b2); - MY_UNICASE_CHARACTER *page= my_unicase_pages_default[wc >> 8]; + MY_UNICASE_CHARACTER *page= my_unicase_default_pages[wc >> 8]; return (int) (page ? page[wc & 0xFF].sort : wc); } -#define MY_FUNCTION_NAME(x) my_ ## x ## _utf8_general_ci -#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) -#define WEIGHT_MB1(x) my_weight_mb1_utf8_general_ci(x) -#define WEIGHT_MB2(x,y) my_weight_mb2_utf8_general_ci(x,y) -#define WEIGHT_MB3(x,y,z) my_weight_mb3_utf8_general_ci(x,y,z) +#define MY_FUNCTION_NAME(x) my_ ## x ## _utf8_general_ci +#define DEFINE_STRNXFRM_UNICODE +#define DEFINE_STRNXFRM_UNICODE_NOPAD +#define MY_MB_WC(cs, pwc, s, e) my_mb_wc_utf8mb3_quick(pwc, s, e) +#define OPTIMIZE_ASCII 1 +#define UNICASE_MAXCHAR MY_UNICASE_INFO_DEFAULT_MAXCHAR +#define UNICASE_PAGE0 my_unicase_default_page00 +#define UNICASE_PAGES my_unicase_default_pages +#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) +#define WEIGHT_MB1(x) my_weight_mb1_utf8_general_ci(x) +#define WEIGHT_MB2(x,y) my_weight_mb2_utf8_general_ci(x,y) +#define WEIGHT_MB3(x,y,z) my_weight_mb3_utf8_general_ci(x,y,z) #include "strcoll.ic" @@ -5473,19 +5289,28 @@ my_weight_mb3_utf8_general_mysql500_ci(uchar b0, uchar b1, uchar b2) } -#define MY_FUNCTION_NAME(x) my_ ## x ## _utf8_general_mysql500_ci -#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) -#define WEIGHT_MB1(x) my_weight_mb1_utf8_general_mysql500_ci(x) -#define WEIGHT_MB2(x,y) my_weight_mb2_utf8_general_mysql500_ci(x,y) -#define WEIGHT_MB3(x,y,z) my_weight_mb3_utf8_general_mysql500_ci(x,y,z) +#define MY_FUNCTION_NAME(x) my_ ## x ## _utf8_general_mysql500_ci +#define DEFINE_STRNXFRM_UNICODE +#define MY_MB_WC(cs, pwc, s, e) my_mb_wc_utf8mb3_quick(pwc, s, e) +#define OPTIMIZE_ASCII 1 +#define UNICASE_MAXCHAR MY_UNICASE_INFO_DEFAULT_MAXCHAR +#define UNICASE_PAGE0 plane00_mysql500 +#define UNICASE_PAGES my_unicase_pages_mysql500 +#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) +#define WEIGHT_MB1(x) my_weight_mb1_utf8_general_mysql500_ci(x) +#define WEIGHT_MB2(x,y) my_weight_mb2_utf8_general_mysql500_ci(x,y) +#define WEIGHT_MB3(x,y,z) my_weight_mb3_utf8_general_mysql500_ci(x,y,z) #include "strcoll.ic" -#define MY_FUNCTION_NAME(x) my_ ## x ## _utf8_bin -#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) -#define WEIGHT_MB1(x) ((int) (uchar) (x)) -#define WEIGHT_MB2(x,y) ((int) UTF8MB2_CODE(x,y)) -#define WEIGHT_MB3(x,y,z) ((int) UTF8MB3_CODE(x,y,z)) +#define MY_FUNCTION_NAME(x) my_ ## x ## _utf8_bin +#define DEFINE_STRNXFRM_UNICODE_BIN2 +#define MY_MB_WC(cs, pwc, s, e) my_mb_wc_utf8mb3_quick(pwc, s, e) +#define OPTIMIZE_ASCII 1 +#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) +#define WEIGHT_MB1(x) ((int) (uchar) (x)) +#define WEIGHT_MB2(x,y) ((int) UTF8MB2_CODE(x,y)) +#define WEIGHT_MB3(x,y,z) ((int) UTF8MB3_CODE(x,y,z)) #include "strcoll.ic" @@ -5534,7 +5359,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_general_ci_handler = NULL, /* init */ my_strnncoll_utf8_general_ci, my_strnncollsp_utf8_general_ci, - my_strnxfrm_unicode, + my_strnxfrm_utf8_general_ci, my_strnxfrmlen_unicode, my_like_range_mb, my_wildcmp_utf8, @@ -5550,7 +5375,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_general_mysql500_ci_handler = NULL, /* init */ my_strnncoll_utf8_general_mysql500_ci, my_strnncollsp_utf8_general_mysql500_ci, - my_strnxfrm_unicode, + my_strnxfrm_utf8_general_mysql500_ci, my_strnxfrmlen_unicode, my_like_range_mb, my_wildcmp_utf8, @@ -5566,7 +5391,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_bin_handler = NULL, /* init */ my_strnncoll_utf8_bin, my_strnncollsp_utf8_bin, - my_strnxfrm_unicode, + my_strnxfrm_utf8_bin, my_strnxfrmlen_unicode, my_like_range_mb, my_wildcmp_mb_bin, @@ -5582,7 +5407,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_general_nopad_ci_handler = NULL, /* init */ my_strnncoll_utf8_general_ci, my_strnncollsp_utf8_general_nopad_ci, - my_strnxfrm_unicode_nopad, + my_strnxfrm_nopad_utf8_general_ci, my_strnxfrmlen_unicode, my_like_range_mb, my_wildcmp_utf8, @@ -5598,7 +5423,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_nopad_bin_handler = NULL, /* init */ my_strnncoll_utf8_bin, my_strnncollsp_utf8_nopad_bin, - my_strnxfrm_unicode_nopad, + my_strnxfrm_nopad_utf8_bin, my_strnxfrmlen_unicode, my_like_range_mb, my_wildcmp_mb_bin, @@ -5927,7 +5752,7 @@ static MY_COLLATION_HANDLER my_collation_cs_handler = NULL, /* init */ my_strnncoll_utf8_cs, my_strnncollsp_utf8_cs, - my_strnxfrm_unicode, + my_strnxfrm_utf8_general_ci, my_strnxfrmlen_unicode, my_like_range_simple, my_wildcmp_mb, @@ -7212,13 +7037,30 @@ my_charlen_filename(CHARSET_INFO *cs, const uchar *str, const uchar *end) #undef DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN /* my_well_formed_char_length_filename */ +#define MY_FUNCTION_NAME(x) my_ ## x ## _filename +#define DEFINE_STRNNCOLL 0 +#define DEFINE_STRNXFRM_UNICODE +#define MY_MB_WC(cs, pwc, s, e) my_mb_wc_filename(cs, pwc, s, e) +#define OPTIMIZE_ASCII 0 +#define UNICASE_MAXCHAR MY_UNICASE_INFO_DEFAULT_MAXCHAR +#define UNICASE_PAGE0 my_unicase_default_page00 +#define UNICASE_PAGES my_unicase_default_pages + +/* +#define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) +#define WEIGHT_MB1(x) my_weight_mb1_utf8_general_ci(x) +#define WEIGHT_MB2(x,y) my_weight_mb2_utf8_general_ci(x,y) +#define WEIGHT_MB3(x,y,z) my_weight_mb3_utf8_general_ci(x,y,z) +*/ +#include "strcoll.ic" + static MY_COLLATION_HANDLER my_collation_filename_handler = { NULL, /* init */ my_strnncoll_simple, my_strnncollsp_simple, - my_strnxfrm_unicode, + my_strnxfrm_filename, my_strnxfrmlen_unicode, my_like_range_mb, my_wildcmp_utf8, @@ -7375,52 +7217,7 @@ static int my_mb_wc_utf8mb4(CHARSET_INFO *cs __attribute__((unused)), my_wc_t * pwc, const uchar *s, const uchar *e) { - uchar c; - - if (s >= e) - return MY_CS_TOOSMALL; - - c= s[0]; - if (c < 0x80) - { - *pwc= c; - return 1; - } - else if (c < 0xc2) - return MY_CS_ILSEQ; - else if (c < 0xe0) - { - if (s + 2 > e) /* We need 2 characters */ - return MY_CS_TOOSMALL2; - - if (!(IS_CONTINUATION_BYTE(s[1]))) - return MY_CS_ILSEQ; - - *pwc= UTF8MB2_CODE(c, s[1]); - return 2; - } - else if (c < 0xf0) - { - if (s + 3 > e) /* We need 3 characters */ - return MY_CS_TOOSMALL3; - - if (!IS_UTF8MB3_STEP2(c, s[1], s[2])) - return MY_CS_ILSEQ; - - *pwc= UTF8MB3_CODE(c, s[1], s[2]); - return 3; - } - else if (c < 0xf5) - { - if (s + 4 > e) /* We need 4 characters */ - return MY_CS_TOOSMALL4; - - if (!IS_UTF8MB4_STEP2(c, s[1], s[2], s[3])) - return MY_CS_ILSEQ; - *pwc= UTF8MB4_CODE(c, s[1], s[2], s[3]); - return 4; - } - return MY_CS_ILSEQ; + return my_mb_wc_utf8mb4_quick(pwc, s, e); } @@ -7752,7 +7549,7 @@ my_strcasecmp_utf8mb4(CHARSET_INFO *cs, const char *s, const char *t) It represents a single byte character. Convert it into weight according to collation. */ - s_wc= plane00[(uchar) s[0]].tolower; + s_wc= my_unicase_default_page00[(uchar) s[0]].tolower; s++; } else @@ -7776,7 +7573,7 @@ my_strcasecmp_utf8mb4(CHARSET_INFO *cs, const char *s, const char *t) if ((uchar) t[0] < 128) { /* Convert single byte character into weight */ - t_wc= plane00[(uchar) t[0]].tolower; + t_wc= my_unicase_default_page00[(uchar) t[0]].tolower; t++; } else @@ -7847,6 +7644,13 @@ my_charlen_utf8mb4(CHARSET_INFO *cs __attribute__((unused)), #define MY_FUNCTION_NAME(x) my_ ## x ## _utf8mb4_general_ci +#define DEFINE_STRNXFRM_UNICODE +#define DEFINE_STRNXFRM_UNICODE_NOPAD +#define MY_MB_WC(cs, pwc, s, e) my_mb_wc_utf8mb4_quick(pwc, s, e) +#define OPTIMIZE_ASCII 1 +#define UNICASE_MAXCHAR MY_UNICASE_INFO_DEFAULT_MAXCHAR +#define UNICASE_PAGE0 my_unicase_default_page00 +#define UNICASE_PAGES my_unicase_default_pages #define IS_MB4_CHAR(b0,b1,b2,b3) IS_UTF8MB4_STEP3(b0,b1,b2,b3) #define WEIGHT_ILSEQ(x) (0xFF0000 + (uchar) (x)) #define WEIGHT_MB1(b0) my_weight_mb1_utf8_general_ci(b0) @@ -7897,7 +7701,7 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_general_ci_handler= NULL, /* init */ my_strnncoll_utf8mb4_general_ci, my_strnncollsp_utf8mb4_general_ci, - my_strnxfrm_unicode, + my_strnxfrm_utf8mb4_general_ci, my_strnxfrmlen_unicode, my_like_range_mb, my_wildcmp_utf8mb4, @@ -7929,7 +7733,7 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_general_nopad_ci_handler= NULL, /* init */ my_strnncoll_utf8mb4_general_ci, my_strnncollsp_utf8mb4_general_nopad_ci, - my_strnxfrm_unicode_nopad, + my_strnxfrm_nopad_utf8mb4_general_ci, my_strnxfrmlen_unicode, my_like_range_mb, my_wildcmp_utf8mb4, diff --git a/strings/ctype-utf8.h b/strings/ctype-utf8.h new file mode 100644 index 00000000000..9a44c1658f2 --- /dev/null +++ b/strings/ctype-utf8.h @@ -0,0 +1,190 @@ +/* + Copyright (c) 2018 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _CTYPE_UTF8_H +#define _CTYPE_UTF8_H + +/* Detect special bytes and sequences */ +#define IS_CONTINUATION_BYTE(c) (((uchar) (c) ^ 0x80) < 0x40) + +/* + Check MB2 character assuming that b0 is alredy known to be >= 0xC2. + Use this macro if the caller already checked b0 for: + - an MB1 character + - an unused gap between MB1 and MB2HEAD +*/ +#define IS_UTF8MB2_STEP2(b0,b1) (((uchar) (b0) < 0xE0) && \ + IS_CONTINUATION_BYTE((uchar) b1)) + +/* + Check MB3 character assuming that b0 is already known to be + in the valid MB3HEAD range [0xE0..0xEF]. +*/ +#define IS_UTF8MB3_STEP2(b0,b1,b2) (IS_CONTINUATION_BYTE(b1) && \ + IS_CONTINUATION_BYTE(b2) && \ + ((uchar) b0 >= 0xe1 || (uchar) b1 >= 0xa0)) + +/* + Check MB3 character assuming that b0 is already known to be >= 0xE0, + but is not checked for the high end 0xF0 yet. + Use this macro if the caller already checked b0 for: + - an MB1 character + - an unused gap between MB1 and MB2HEAD + - an MB2HEAD +*/ +#define IS_UTF8MB3_STEP3(b0,b1,b2) (((uchar) (b0) < 0xF0) && \ + IS_UTF8MB3_STEP2(b0,b1,b2)) + +/* + UTF-8 quick four-byte mask: + 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + Encoding allows to encode U+00010000..U+001FFFFF + + The maximum character defined in the Unicode standard is U+0010FFFF. + Higher characters U+00110000..U+001FFFFF are not used. + + 11110000.10010000.10xxxxxx.10xxxxxx == F0.90.80.80 == U+00010000 (min) + 11110100.10001111.10111111.10111111 == F4.8F.BF.BF == U+0010FFFF (max) + + Valid codes: + [F0][90..BF][80..BF][80..BF] + [F1][80..BF][80..BF][80..BF] + [F2][80..BF][80..BF][80..BF] + [F3][80..BF][80..BF][80..BF] + [F4][80..8F][80..BF][80..BF] +*/ + +/* + Check MB4 character assuming that b0 is already + known to be in the range [0xF0..0xF4] +*/ +#define IS_UTF8MB4_STEP2(b0,b1,b2,b3) (IS_CONTINUATION_BYTE(b1) && \ + IS_CONTINUATION_BYTE(b2) && \ + IS_CONTINUATION_BYTE(b3) && \ + (b0 >= 0xf1 || b1 >= 0x90) && \ + (b0 <= 0xf3 || b1 <= 0x8F)) +#define IS_UTF8MB4_STEP3(b0,b1,b2,b3) (((uchar) (b0) < 0xF5) && \ + IS_UTF8MB4_STEP2(b0,b1,b2,b3)) + +/* Convert individual bytes to Unicode code points */ +#define UTF8MB2_CODE(b0,b1) (((my_wc_t) ((uchar) b0 & 0x1f) << 6) |\ + ((my_wc_t) ((uchar) b1 ^ 0x80))) +#define UTF8MB3_CODE(b0,b1,b2) (((my_wc_t) ((uchar) b0 & 0x0f) << 12) |\ + ((my_wc_t) ((uchar) b1 ^ 0x80) << 6) |\ + ((my_wc_t) ((uchar) b2 ^ 0x80))) +#define UTF8MB4_CODE(b0,b1,b2,b3) (((my_wc_t) ((uchar) b0 & 0x07) << 18) |\ + ((my_wc_t) ((uchar) b1 ^ 0x80) << 12) |\ + ((my_wc_t) ((uchar) b2 ^ 0x80) << 6) |\ + (my_wc_t) ((uchar) b3 ^ 0x80)) + +static inline int +my_mb_wc_utf8mb3_quick(my_wc_t * pwc, const uchar *s, const uchar *e) +{ + uchar c; + + if (s >= e) + return MY_CS_TOOSMALL; + + c= s[0]; + if (c < 0x80) + { + *pwc = c; + return 1; + } + else if (c < 0xc2) + return MY_CS_ILSEQ; + else if (c < 0xe0) + { + if (s+2 > e) /* We need 2 characters */ + return MY_CS_TOOSMALL2; + + if (!(IS_CONTINUATION_BYTE(s[1]))) + return MY_CS_ILSEQ; + + *pwc= UTF8MB2_CODE(c, s[1]); + return 2; + } + else if (c < 0xf0) + { + if (s+3 > e) /* We need 3 characters */ + return MY_CS_TOOSMALL3; + + if (!IS_UTF8MB3_STEP2(c, s[1], s[2])) + return MY_CS_ILSEQ; + + *pwc= UTF8MB3_CODE(c, s[1], s[2]); + return 3; + } + return MY_CS_ILSEQ; +} + + +#ifdef HAVE_CHARSET_utf8mb4 +static inline int +my_mb_wc_utf8mb4_quick(my_wc_t *pwc, const uchar *s, const uchar *e) +{ + uchar c; + + if (s >= e) + return MY_CS_TOOSMALL; + + c= s[0]; + if (c < 0x80) + { + *pwc= c; + return 1; + } + else if (c < 0xc2) + return MY_CS_ILSEQ; + else if (c < 0xe0) + { + if (s + 2 > e) /* We need 2 characters */ + return MY_CS_TOOSMALL2; + + if (!(IS_CONTINUATION_BYTE(s[1]))) + return MY_CS_ILSEQ; + + *pwc= UTF8MB2_CODE(c, s[1]); + return 2; + } + else if (c < 0xf0) + { + if (s + 3 > e) /* We need 3 characters */ + return MY_CS_TOOSMALL3; + + if (!IS_UTF8MB3_STEP2(c, s[1], s[2])) + return MY_CS_ILSEQ; + + *pwc= UTF8MB3_CODE(c, s[1], s[2]); + return 3; + } + else if (c < 0xf5) + { + if (s + 4 > e) /* We need 4 characters */ + return MY_CS_TOOSMALL4; + + if (!IS_UTF8MB4_STEP2(c, s[1], s[2], s[3])) + return MY_CS_ILSEQ; + *pwc= UTF8MB4_CODE(c, s[1], s[2], s[3]); + return 4; + } + return MY_CS_ILSEQ; +} +#endif /* HAVE_CHARSET_utf8mb4*/ + + +#endif /* _CTYPE_UTF8_H */ diff --git a/strings/json_lib.c b/strings/json_lib.c index 7a6e0c5cbff..bc93601ff05 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1846,3 +1846,116 @@ int json_path_compare(const json_path_t *a, const json_path_t *b, b->steps+1, b->last_step, vt); } + +enum json_types json_type(const char *js, const char *js_end, + const char **v, int *vlen) +{ + return JSV_NOTHING; +} + + +enum json_types json_get_array_item(const char *js, const char *js_end, + int n_item, + const char **v, int *vlen) +{ + return JSV_NOTHING; +} + + +enum json_types json_get_object_key(const char *js, const char *js_end, + const char *key, + const char **v, int *vlen) +{ + return JSV_NOTHING; +} + + +enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey, + const char **keyname, const char **keyname_end, + const char **v, int *vlen) +{ + return JSV_NOTHING; +} + +/** Simple json lookup for a value by the key. + + Only supports flat json objects. + Does not look inside nested objects. + Does not process complex path expressions. + + @param js [in] json to search in + @param js_len [in] - " - + @param key [in] key to search for + @param key_len [in] - " - + @param value_type [out] type of the value found or 0 if not found + @param value_start [out] pointer into js (value or closing }) + @param value_len [out] length of the value found or number of keys + + @retval 0 - success + @retval 1 - error (invalid json) +*/ +int json_get_object_by_key(const char *js, size_t js_len, + const char *key, size_t key_len, + enum json_value_types *value_type, + const char **value_start, size_t *value_len) +{ + json_engine_t je; + json_string_t key_name; + int n_keys= 0; + + json_string_set_cs(&key_name, &my_charset_utf8mb4_bin); + + json_scan_start(&je, &my_charset_utf8mb4_bin,(const uchar *) js, + (const uchar *) js + js_len); + + if (json_read_value(&je) || + je.value_type != JSON_VALUE_OBJECT) + goto err_return; + + while (!json_scan_next(&je)) + { + switch (je.state) + { + case JST_KEY: + n_keys++; + json_string_set_str(&key_name, (const uchar *) key, + (const uchar *) key + key_len); + if (!json_key_matches(&je, &key_name)) + { + if (json_skip_key(&je)) + goto err_return; + } + else + { + if (json_read_value(&je)) + goto err_return; + *value_type= je.value_type; + *value_start= (const char *) je.value; + *value_len= je.value_len; + return 0; + } + break; + + case JST_OBJ_END: + *value_type= (enum json_value_types) 0; + *value_start= (const char *) (je.s.c_str - je.sav_c_len); + *value_len= n_keys; + return 0; + } + } + +err_return: + return 1; +} + +/** Check if json is valid (well-formed) + + @retval 0 - success, json is well-formed + @retval 1 - error, json is invalid +*/int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs) +{ + json_engine_t je; + json_scan_start(&je, cs, (const uchar *) js, (const uchar *) js + js_len); + while (json_scan_next(&je) == 0) /* no-op */ ; + return je.s.error == 0; +} diff --git a/strings/strcoll.ic b/strings/strcoll.ic index c647a5ef57e..9dfccb9018c 100644 --- a/strings/strcoll.ic +++ b/strings/strcoll.ic @@ -15,11 +15,18 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #ifndef MY_FUNCTION_NAME #error MY_FUNCTION_NAME is not defined #endif +/* + Define strnncoll() and strnncollsp() by default, + unless "#define DEFINE_STRNNCOLL 0" is specified. +*/ +#ifndef DEFINE_STRNNCOLL +#define DEFINE_STRNNCOLL 1 +#endif + /* The weight for automatically padded spaces when comparing strings with @@ -54,6 +61,8 @@ #endif +#if DEFINE_STRNNCOLL + /** Scan a valid character, or a bad byte, or an auto-padded space from a string and calculate the weight of the scanned sequence. @@ -278,6 +287,8 @@ MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)), } #endif +#endif /* DEFINE_STRNNCOLL */ + #ifdef DEFINE_STRNXFRM #ifndef WEIGHT_MB2_FRM @@ -322,11 +333,261 @@ MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs, #endif /* DEFINE_STRNXFRM */ +#if defined(DEFINE_STRNXFRM_UNICODE) || defined(DEFINE_STRNXFRM_UNICODE_NOPAD) + +/* + Store sorting weights using 2 bytes per character. + + This function is shared between + - utf8mb3_general_ci, utf8_bin, ucs2_general_ci, ucs2_bin + which support BMP only (U+0000..U+FFFF). + - utf8mb4_general_ci, utf16_general_ci, utf32_general_ci, + which map all supplementary characters to weight 0xFFFD. +*/ + +#ifndef MY_MB_WC +#error MY_MB_WC must be defined for DEFINE_STRNXFRM_UNICODE +#endif + +#ifndef OPTIMIZE_ASCII +#error OPTIMIZE_ASCII must be defined for DEFINE_STRNXFRM_UNICODE +#endif + +#ifndef UNICASE_MAXCHAR +#error UNICASE_MAXCHAR must be defined for DEFINE_STRNXFRM_UNICODE +#endif + +#ifndef UNICASE_PAGE0 +#error UNICASE_PAGE0 must be defined for DEFINE_STRNXFRM_UNICODE +#endif + +#ifndef UNICASE_PAGES +#error UNICASE_PAGES must be defined for DEFINE_STRNXFRM_UNICODE +#endif + + +static size_t +MY_FUNCTION_NAME(strnxfrm_internal)(CHARSET_INFO *cs, + uchar *dst, uchar *de, + uint *nweights, + const uchar *src, const uchar *se) +{ + my_wc_t UNINIT_VAR(wc); + uchar *dst0= dst; + + DBUG_ASSERT(src || !se); + DBUG_ASSERT((cs->state & MY_CS_LOWER_SORT) == 0); + DBUG_ASSERT(0x7F <= UNICASE_MAXCHAR); + + for (; dst < de && *nweights; (*nweights)--) + { + int res; +#if OPTIMIZE_ASCII + if (src >= se) + break; + if (src[0] <= 0x7F) + { + wc= UNICASE_PAGE0[*src++].sort; + PUT_WC_BE2_HAVE_1BYTE(dst, de, wc); + continue; + } +#endif + if ((res= MY_MB_WC(cs, &wc, src, se)) <= 0) + break; + src+= res; + if (wc <= UNICASE_MAXCHAR) + { + MY_UNICASE_CHARACTER *page; + if ((page= UNICASE_PAGES[wc >> 8])) + wc= page[wc & 0xFF].sort; + } + else + wc= MY_CS_REPLACEMENT_CHARACTER; + PUT_WC_BE2_HAVE_1BYTE(dst, de, wc); + } + return dst - dst0; +} + + +static size_t +MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags) +{ + uchar *dst0= dst; + uchar *de= dst + dstlen; + dst+= MY_FUNCTION_NAME(strnxfrm_internal)(cs, dst, de, &nweights, + src, src + srclen); + DBUG_ASSERT(dst <= de); /* Safety */ + + if (dst < de && nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE)) + dst+= my_strxfrm_pad_nweights_unicode(dst, de, nweights); + + my_strxfrm_desc_and_reverse(dst0, dst, flags, 0); + + if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de) + dst+= my_strxfrm_pad_unicode(dst, de); + return dst - dst0; +} + + +#ifdef DEFINE_STRNXFRM_UNICODE_NOPAD +static size_t +MY_FUNCTION_NAME(strnxfrm_nopad)(CHARSET_INFO *cs, + uchar *dst, size_t dstlen, + uint nweights, + const uchar *src, size_t srclen, uint flags) +{ + uchar *dst0= dst; + uchar *de= dst + dstlen; + dst+= MY_FUNCTION_NAME(strnxfrm_internal)(cs, dst, de, &nweights, + src, src + srclen); + DBUG_ASSERT(dst <= de); /* Safety */ + + if (dst < de && nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE)) + { + size_t len= de - dst; + set_if_smaller(len, nweights * 2); + memset(dst, 0x00, len); + dst+= len; + } + + my_strxfrm_desc_and_reverse(dst0, dst, flags, 0); + + if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de) + { + memset(dst, 0x00, de - dst); + dst= de; + } + return dst - dst0; +} +#endif + +#endif /* DEFINE_STRNXFRM_UNICODE || DEFINE_STRNXFRM_UNICODE_NOPAD */ + + + +#ifdef DEFINE_STRNXFRM_UNICODE_BIN2 + +/* + Store sorting weights using 2 bytes per character. + + These functions are shared between + - utf8mb3_general_ci, utf8_bin, ucs2_general_ci, ucs2_bin + which support BMP only (U+0000..U+FFFF). + - utf8mb4_general_ci, utf16_general_ci, utf32_general_ci, + which map all supplementary characters to weight 0xFFFD. +*/ + +#ifndef MY_MB_WC +#error MY_MB_WC must be defined for DEFINE_STRNXFRM_UNICODE_BIN2 +#endif + +#ifndef OPTIMIZE_ASCII +#error OPTIMIZE_ASCII must be defined for DEFINE_STRNXFRM_UNICODE_BIN2 +#endif + + +static size_t +MY_FUNCTION_NAME(strnxfrm_internal)(CHARSET_INFO *cs, + uchar *dst, uchar *de, + uint *nweights, + const uchar *src, + const uchar *se) +{ + my_wc_t UNINIT_VAR(wc); + uchar *dst0= dst; + + DBUG_ASSERT(src || !se); + + for (; dst < de && *nweights; (*nweights)--) + { + int res; +#if OPTIMIZE_ASCII + if (src >= se) + break; + if (src[0] <= 0x7F) + { + wc= *src++; + PUT_WC_BE2_HAVE_1BYTE(dst, de, wc); + continue; + } +#endif + if ((res= MY_MB_WC(cs, &wc, src, se)) <= 0) + break; + src+= res; + if (wc > 0xFFFF) + wc= MY_CS_REPLACEMENT_CHARACTER; + PUT_WC_BE2_HAVE_1BYTE(dst, de, wc); + } + return dst - dst0; +} + + +static size_t +MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags) +{ + uchar *dst0= dst; + uchar *de= dst + dstlen; + dst+= MY_FUNCTION_NAME(strnxfrm_internal)(cs, dst, de, &nweights, + src, src + srclen); + DBUG_ASSERT(dst <= de); /* Safety */ + + if (dst < de && nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE)) + dst+= my_strxfrm_pad_nweights_unicode(dst, de, nweights); + + my_strxfrm_desc_and_reverse(dst0, dst, flags, 0); + + if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de) + dst+= my_strxfrm_pad_unicode(dst, de); + return dst - dst0; +} + + +static size_t +MY_FUNCTION_NAME(strnxfrm_nopad)(CHARSET_INFO *cs, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags) +{ + uchar *dst0= dst; + uchar *de= dst + dstlen; + dst+= MY_FUNCTION_NAME(strnxfrm_internal)(cs, dst, de, &nweights, + src, src + srclen); + DBUG_ASSERT(dst <= de); /* Safety */ + + if (dst < de && nweights && (flags & MY_STRXFRM_PAD_WITH_SPACE)) + { + size_t len= de - dst; + set_if_smaller(len, nweights * 2); + memset(dst, 0x00, len); + dst+= len; + } + + my_strxfrm_desc_and_reverse(dst0, dst, flags, 0); + + if ((flags & MY_STRXFRM_PAD_TO_MAXLEN) && dst < de) + { + memset(dst, 0x00, de - dst); + dst= de; + } + return dst - dst0; +} + +#endif /* DEFINE_STRNXFRM_UNICODE_BIN2 */ + + /* We usually include this file at least two times from the same source file, for the _ci and the _bin collations. Prepare for the second inclusion. */ #undef MY_FUNCTION_NAME +#undef MY_MB_WC +#undef OPTIMIZE_ASCII +#undef UNICASE_MAXCHAR +#undef UNICASE_PAGE0 +#undef UNICASE_PAGES #undef WEIGHT_ILSEQ #undef WEIGHT_MB1 #undef WEIGHT_MB2 @@ -335,4 +596,8 @@ MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs, #undef WEIGHT_PAD_SPACE #undef WEIGHT_MB2_FRM #undef DEFINE_STRNXFRM +#undef DEFINE_STRNXFRM_UNICODE +#undef DEFINE_STRNXFRM_UNICODE_NOPAD +#undef DEFINE_STRNXFRM_UNICODE_BIN2 +#undef DEFINE_STRNNCOLL #undef DEFINE_STRNNCOLLSP_NOPAD diff --git a/support-files/rpm/server.cnf b/support-files/rpm/server.cnf index f067afd0da3..a9fe564939e 100644 --- a/support-files/rpm/server.cnf +++ b/support-files/rpm/server.cnf @@ -39,8 +39,8 @@ # you can put MariaDB-only options here [mariadb] -# This group is only read by MariaDB-10.3 servers. +# This group is only read by MariaDB-10.4 servers. # If you use the same .cnf file for MariaDB of different versions, # use this group for options that older servers don't understand -[mariadb-10.3] +[mariadb-10.4] diff --git a/tests/mysql_client_fw.c b/tests/mysql_client_fw.c index 2a529c12c63..c39b5138309 100644 --- a/tests/mysql_client_fw.c +++ b/tests/mysql_client_fw.c @@ -50,9 +50,6 @@ static char *opt_user= 0; static char *opt_password= 0; static char *opt_host= 0; static char *opt_unix_socket= 0; -#ifdef HAVE_SMEM -static char *shared_memory_base_name= 0; -#endif static unsigned int opt_port; static my_bool tty_password= 0, opt_silent= 0; @@ -253,10 +250,6 @@ static void print_st_error(MYSQL_STMT *stmt, const char *msg) static MYSQL *mysql_client_init(MYSQL* con) { MYSQL* res = mysql_init(con); -#ifdef HAVE_SMEM - if (res && shared_memory_base_name) - mysql_options(res, MYSQL_SHARED_MEMORY_BASE_NAME, shared_memory_base_name); -#endif if (res && non_blocking_api_enabled) mysql_options(res, MYSQL_OPT_NONBLOCK, 0); if (opt_plugin_dir && *opt_plugin_dir) @@ -1229,11 +1222,6 @@ static struct my_option client_test_long_options[] = 0, 0, 0, 0, 0, 0}, {"silent", 's', "Be more silent", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory-base-name", 'm', "Base name of shared memory.", - &shared_memory_base_name, (uchar**)&shared_memory_base_name, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif {"socket", 'S', "Socket file to use for connection", &opt_unix_socket, &opt_unix_socket, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/unittest/sql/mf_iocache-t.cc b/unittest/sql/mf_iocache-t.cc index 3fff2d49daa..8397c539dd5 100644 --- a/unittest/sql/mf_iocache-t.cc +++ b/unittest/sql/mf_iocache-t.cc @@ -352,7 +352,7 @@ void mdev17133() // random size 2nd read res= my_b_read(&info, buf_i + total + MY_MIN(19, curr_read_size), 19 >= curr_read_size ? 0 : curr_read_size - 19); - ok(res == 0, "rest of read %lu", curr_read_size - 19); + ok(res == 0, "rest of read %lu", (ulong) (curr_read_size - 19)); // mark read bytes in the used part of the cache buffer memset(info.buffer, 0, info.read_pos - info.buffer); diff --git a/vio/CMakeLists.txt b/vio/CMakeLists.txt index cdb28799ada..95748224f97 100644 --- a/vio/CMakeLists.txt +++ b/vio/CMakeLists.txt @@ -17,6 +17,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${SSL_INCLUDE_DIRS}) ADD_DEFINITIONS(${SSL_DEFINES}) -SET(VIO_SOURCES vio.c viosocket.c viossl.c viopipe.c vioshm.c viosslfactories.c) +SET(VIO_SOURCES vio.c viosocket.c viossl.c viopipe.c viosslfactories.c) ADD_CONVENIENCE_LIBRARY(vio ${VIO_SOURCES}) TARGET_LINK_LIBRARIES(vio ${LIBSOCKET}) diff --git a/vio/docs/TODO b/vio/docs/TODO deleted file mode 100644 index 7296ab73a10..00000000000 --- a/vio/docs/TODO +++ /dev/null @@ -1,3 +0,0 @@ -* Consistent error handling. May be the initialization should - be taken out of constructors and be put into virtual method open(). -* The open() method is named very misleadingly(). diff --git a/vio/vio.c b/vio/vio.c index 34ca9ed872d..985a6568e3c 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -54,18 +54,6 @@ static my_bool has_no_data(Vio *vio __attribute__((unused))) } #ifdef _WIN32 -my_bool vio_shared_memory_has_data(Vio *vio) -{ - return (vio->shared_memory_remain > 0); -} - -int vio_shared_memory_shutdown(Vio *vio, int how) -{ - SetEvent(vio->event_conn_closed); - SetEvent(vio->event_server_wrote); - return 0; -} - int vio_pipe_shutdown(Vio *vio, int how) { return CancelIoEx(vio->hPipe, NULL); @@ -116,28 +104,7 @@ static void vio_init(Vio *vio, enum enum_vio_type type, DBUG_VOID_RETURN; } #endif -#ifdef HAVE_SMEM - if (type == VIO_TYPE_SHARED_MEMORY) - { - vio->viodelete =vio_delete; - vio->vioerrno =vio_errno; - vio->read =vio_read_shared_memory; - vio->write =vio_write_shared_memory; - vio->fastsend =vio_fastsend; - vio->viokeepalive =vio_keepalive; - vio->should_retry =vio_should_retry; - vio->was_timeout =vio_was_timeout; - vio->vioclose =vio_close_shared_memory; - vio->peer_addr =vio_peer_addr; - vio->vioblocking =vio_blocking; - vio->is_blocking =vio_is_blocking; - vio->io_wait =no_io_wait; - vio->is_connected =vio_is_connected_shared_memory; - vio->has_data =vio_shared_memory_has_data; - vio->shutdown =vio_shared_memory_shutdown; - DBUG_VOID_RETURN; - } -#endif + #ifdef HAVE_OPENSSL if (type == VIO_TYPE_SSL) { @@ -296,31 +263,7 @@ Vio *vio_new_win32pipe(HANDLE hPipe) DBUG_RETURN(vio); } -#ifdef HAVE_SMEM -Vio *vio_new_win32shared_memory(HANDLE handle_file_map, HANDLE handle_map, - HANDLE event_server_wrote, HANDLE event_server_read, - HANDLE event_client_wrote, HANDLE event_client_read, - HANDLE event_conn_closed) -{ - Vio *vio; - DBUG_ENTER("vio_new_win32shared_memory"); - if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME)))) - { - vio_init(vio, VIO_TYPE_SHARED_MEMORY, 0, VIO_LOCALHOST); - vio->desc= "shared memory"; - vio->handle_file_map= handle_file_map; - vio->handle_map= handle_map; - vio->event_server_wrote= event_server_wrote; - vio->event_server_read= event_server_read; - vio->event_client_wrote= event_client_wrote; - vio->event_client_read= event_client_read; - vio->event_conn_closed= event_conn_closed; - vio->shared_memory_remain= 0; - vio->shared_memory_pos= handle_map; - } - DBUG_RETURN(vio); -} -#endif + #endif diff --git a/vio/vio_priv.h b/vio/vio_priv.h index 248e1a59b23..6f5364417ac 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -35,14 +35,6 @@ int cancel_io(HANDLE handle, DWORD thread_id); int vio_shutdown_pipe(Vio *vio,int how); #endif -#ifdef HAVE_SMEM -size_t vio_read_shared_memory(Vio *vio, uchar * buf, size_t size); -size_t vio_write_shared_memory(Vio *vio, const uchar * buf, size_t size); -my_bool vio_is_connected_shared_memory(Vio *vio); -int vio_close_shared_memory(Vio * vio); -my_bool vio_shared_memory_has_data(Vio *vio); -int vio_shutdown_shared_memory(Vio *vio, int how); -#endif int vio_socket_shutdown(Vio *vio, int how); my_bool vio_buff_has_data(Vio *vio); diff --git a/vio/viopipe.c b/vio/viopipe.c index d3447a95c6e..0a3deb91262 100644 --- a/vio/viopipe.c +++ b/vio/viopipe.c @@ -131,7 +131,6 @@ int vio_close_pipe(Vio *vio) CancelIo(vio->hPipe); CloseHandle(vio->overlapped.hEvent); - DisconnectNamedPipe(vio->hPipe); ret= CloseHandle(vio->hPipe); vio->type= VIO_CLOSED; diff --git a/vio/vioshm.c b/vio/vioshm.c deleted file mode 100644 index acc7d2402c5..00000000000 --- a/vio/vioshm.c +++ /dev/null @@ -1,217 +0,0 @@ -/* Copyright (c) 2010, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "vio_priv.h" - -#if defined(_WIN32) && defined(HAVE_SMEM) - -size_t vio_read_shared_memory(Vio *vio, uchar *buf, size_t size) -{ - size_t length; - size_t remain_local; - char *current_position; - HANDLE events[2]; - DWORD timeout; - DBUG_ENTER("vio_read_shared_memory"); - - remain_local= size; - current_position= buf; - timeout= vio->read_timeout >= 0 ? vio->read_timeout : INFINITE; - - events[0]= vio->event_server_wrote; - events[1]= vio->event_conn_closed; - - do - { - if (vio->shared_memory_remain == 0) - { - DWORD wait_status; - - wait_status= WaitForMultipleObjects(array_elements(events), events, - FALSE, timeout); - - /* - WaitForMultipleObjects can return next values: - WAIT_OBJECT_0+0 - event from vio->event_server_wrote - WAIT_OBJECT_0+1 - event from vio->event_conn_closed. - We can't read anything - WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything - */ - if (wait_status != WAIT_OBJECT_0) - { - /* - If wait_status is WAIT_TIMEOUT, set error code to indicate a - timeout error. If vio->event_conn_closed was set, use an EOF - condition (return value of zero) to indicate that the operation - has been aborted. - */ - if (wait_status == WAIT_TIMEOUT) - SetLastError(SOCKET_ETIMEDOUT); - else if (wait_status == (WAIT_OBJECT_0 + 1)) - DBUG_RETURN(0); - - DBUG_RETURN(-1); - } - - vio->shared_memory_pos= vio->handle_map; - vio->shared_memory_remain= uint4korr((ulong*)vio->shared_memory_pos); - vio->shared_memory_pos+= 4; - } - - length= size; - - if (vio->shared_memory_remain < length) - length= vio->shared_memory_remain; - if (length > remain_local) - length= remain_local; - - memcpy(current_position, vio->shared_memory_pos, length); - - vio->shared_memory_remain-= length; - vio->shared_memory_pos+= length; - current_position+= length; - remain_local-= length; - - if (!vio->shared_memory_remain) - { - if (!SetEvent(vio->event_client_read)) - DBUG_RETURN(-1); - } - } while (remain_local); - length= size; - - DBUG_RETURN(length); -} - - -size_t vio_write_shared_memory(Vio *vio, const uchar *buf, size_t size) -{ - size_t length, remain, sz; - HANDLE pos; - const uchar *current_position; - HANDLE events[2]; - DWORD timeout; - DBUG_ENTER("vio_write_shared_memory"); - - remain= size; - current_position= buf; - timeout= vio->write_timeout >= 0 ? vio->write_timeout : INFINITE; - - events[0]= vio->event_server_read; - events[1]= vio->event_conn_closed; - - while (remain != 0) - { - DWORD wait_status; - - wait_status= WaitForMultipleObjects(array_elements(events), events, - FALSE, timeout); - - if (wait_status != WAIT_OBJECT_0) - { - /* Set error code to indicate a timeout error or disconnect. */ - if (wait_status == WAIT_TIMEOUT) - SetLastError(SOCKET_ETIMEDOUT); - else - SetLastError(ERROR_GRACEFUL_DISCONNECT); - - DBUG_RETURN((size_t) -1); - } - - sz= (remain > shared_memory_buffer_length ? shared_memory_buffer_length : - remain); - - int4store(vio->handle_map, sz); - pos= vio->handle_map + 4; - memcpy(pos, current_position, sz); - remain-= sz; - current_position+= sz; - if (!SetEvent(vio->event_client_wrote)) - DBUG_RETURN((size_t) -1); - } - length= size; - - DBUG_RETURN(length); -} - - -my_bool vio_is_connected_shared_memory(Vio *vio) -{ - return (WaitForSingleObject(vio->event_conn_closed, 0) != WAIT_OBJECT_0); -} - - -/** - Close shared memory and DBUG_PRINT any errors that happen on closing. - @return Zero if all closing functions succeed, and nonzero otherwise. -*/ -int vio_close_shared_memory(Vio * vio) -{ - int error_count= 0; - DBUG_ENTER("vio_close_shared_memory"); - if (vio->type != VIO_CLOSED) - { - /* - Set event_conn_closed for notification of both client and server that - connection is closed - */ - SetEvent(vio->event_conn_closed); - /* - Close all handlers. UnmapViewOfFile and CloseHandle return non-zero - result if they are success. - */ - if (UnmapViewOfFile(vio->handle_map) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed")); - } - if (CloseHandle(vio->event_server_wrote) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed")); - } - if (CloseHandle(vio->event_server_read) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed")); - } - if (CloseHandle(vio->event_client_wrote) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed")); - } - if (CloseHandle(vio->event_client_read) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed")); - } - if (CloseHandle(vio->handle_file_map) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed")); - } - if (CloseHandle(vio->event_conn_closed) == 0) - { - error_count++; - DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed")); - } - } - vio->type= VIO_CLOSED; - vio->mysql_socket= MYSQL_INVALID_SOCKET; - DBUG_RETURN(error_count); -} - -#endif /* #if defined(_WIN32) && defined(HAVE_SMEM) */ - diff --git a/vio/viosocket.c b/vio/viosocket.c index d34bb13b1bd..8fc58ef8f43 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -74,8 +74,7 @@ int vio_errno(Vio *vio __attribute__((unused))) { /* These transport types are not Winsock based. */ #ifdef _WIN32 - if (vio->type == VIO_TYPE_NAMEDPIPE || - vio->type == VIO_TYPE_SHARED_MEMORY) + if (vio->type == VIO_TYPE_NAMEDPIPE) return GetLastError(); #endif @@ -363,7 +362,7 @@ int vio_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode) r= set_blocking_mode ? 0 : 1; #endif /* !defined(NO_FCNTL_NONBLOCK) */ #else /* !defined(__WIN__) */ - if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY) + if (vio->type != VIO_TYPE_NAMEDPIPE) { ulong arg; int old_fcntl=vio->fcntl_mode; @@ -435,13 +434,39 @@ int vio_socket_timeout(Vio *vio, DBUG_RETURN(ret); } +/* Set TCP_NODELAY (disable Nagle's algorithm */ +int vio_nodelay(Vio *vio, my_bool on) +{ + int r; + int no_delay= MY_TEST(on); + DBUG_ENTER("vio_nodelay"); + + if (vio->type == VIO_TYPE_NAMEDPIPE || vio->type == VIO_TYPE_SOCKET) + { + DBUG_RETURN(0); + } + + r = mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_NODELAY, + IF_WIN((const char*), (void*)) &no_delay, + sizeof(no_delay)); -int vio_fastsend(Vio * vio __attribute__((unused))) + if (r) + { + DBUG_PRINT("warning", + ("Couldn't set socket option for fast send, error %d", + socket_errno)); + r = -1; + } + DBUG_PRINT("exit", ("%d", r)); + DBUG_RETURN(r); +} + +int vio_fastsend(Vio * vio) { int r=0; DBUG_ENTER("vio_fastsend"); - if (vio->type == VIO_TYPE_NAMEDPIPE ||vio->type == VIO_TYPE_SHARED_MEMORY) + if (vio->type == VIO_TYPE_NAMEDPIPE) { DBUG_RETURN(0); } @@ -454,18 +479,7 @@ int vio_fastsend(Vio * vio __attribute__((unused))) } #endif /* IPTOS_THROUGHPUT */ if (!r) - { -#ifdef __WIN__ - BOOL nodelay= 1; -#else - int nodelay = 1; -#endif - - r= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_NODELAY, - IF_WIN((const char*), (void*)) &nodelay, - sizeof(nodelay)); - - } + r = vio_nodelay(vio, TRUE); if (r) { DBUG_PRINT("warning", @@ -486,7 +500,7 @@ int vio_keepalive(Vio* vio, my_bool set_keep_alive) (int)mysql_socket_getfd(vio->mysql_socket), (int)set_keep_alive)); - if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY) + if (vio->type != VIO_TYPE_NAMEDPIPE) { if (set_keep_alive) opt = 1; @@ -505,7 +519,7 @@ int vio_set_keepalive_options(Vio* vio, const struct vio_keepalive_opts *opts) struct tcp_keepalive s; DWORD nbytes; - if (vio->type == VIO_TYPE_NAMEDPIPE || vio->type == VIO_TYPE_SHARED_MEMORY) + if (vio->type == VIO_TYPE_NAMEDPIPE) return 0; if (!opts->idle && !opts->interval) diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt index 683abc64ef3..465b4529fac 100644 --- a/win/packaging/CMakeLists.txt +++ b/win/packaging/CMakeLists.txt @@ -178,6 +178,39 @@ IF(CMAKE_GENERATOR MATCHES "Visual Studio") SET(CONFIG_PARAM "-DCMAKE_INSTALL_CONFIG_NAME=${CMAKE_CFG_INTDIR}") ENDIF() +IF(MSVC_CRT_TYPE MATCHES "/MD") + # Find out CRT merge module path, we're going to use it in installer + # The path and name depends on VS version + IF(MSVC_VERSION LESS 1900) + # VS2015 + SET(VCREDIST_MSM_FILENAME Microsoft_VC140_CRT_${WIX_ARCH_SUFFIX}.msm) + SET(ProgramFilesX86 "ProgramFiles(x86)") + FIND_FILE(${VCREDIST_MSM_FILENAME} + NO_DEFAULT_PATH + PATHS + "$ENV{${ProgramFilesX86}}/Common Files/Merge Modules" + "$ENV{ProgramFiles}/Common Files/Merge Modules" + ) + ELSEIF(MSVC_VERSION LESS 2000) + # VS2017 + SET(VCREDIST_MSM_FILENAME Microsoft_VC141_CRT_${WIX_ARCH_SUFFIX}.msm) + FILE(GLOB MSM_LIST "C:/Program Files*/Microsoft Visual Studio/2017/*/VC/Redist/MSVC/*/MergeModules/${VCREDIST_MSM_FILENAME}") + LIST(LENGTH MSM_LIST LEN) + IF(LEN GREATER 0) + LIST(GET MSM_LIST 0 VCRedist_MSM) + ENDIF() + ELSE() + # Post-VS2017. Needs to be ported when new VS is out + MESSAGE(WARNING + "Name of redistributable merge module not known for this version of MSVC") + ENDIF() + IF (NOT VCRedist_MSM) + MESSAGE(WARNING "Can't find merge module ${VCREDIST_MSM_FILENAME}") + ELSE() + FILE(TO_NATIVE_PATH ${VCRedist_MSM} VCRedist_MSM) + # MESSAGE("VCRedist_MSM=${VCRedist_MSM}") + ENDIF() +ENDIF() ADD_CUSTOM_TARGET( MSI @@ -209,44 +242,12 @@ ADD_CUSTOM_TARGET( -DVERSION="${VERSION}" -DWITH_THIRD_PARTY="${WITH_THIRD_PARTY}" -DWIXCA_LOCATION="$<TARGET_FILE:wixca>" + -DMSVC_CRT_TYPE="${MSVC_CRT_TYPE}" + -DVCRedist_MSM="${VCRedist_MSM}" -P ${CMAKE_CURRENT_SOURCE_DIR}/create_msi.cmake ) ADD_DEPENDENCIES(MSI wixca) -ADD_CUSTOM_TARGET( - MSI_ESSENTIALS - COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM} -DESSENTIALS=1 - -DCANDLE_EXECUTABLE="${CANDLE_EXECUTABLE}" - -DCMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}" - -DCMAKE_FULL_VER="${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" - -DCMAKE_SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P} - -DCOPYING_RTF="${COPYING_RTF}" - -DCPACK_WIX_CONFIG="${CPACK_WIX_CONFIG}" - -DCPACK_WIX_INCLUDE="${CPACK_WIX_INCLUDE}" - -DCPACK_WIX_PACKAGE_BASE_NAME="${CPACK_WIX_PACKAGE_BASE_NAME}" - -DCPACK_WIX_PACKAGE_NAME="${CPACK_WIX_PACKAGE_NAME}" - -DCPACK_WIX_UPGRADE_CODE="${CPACK_WIX_UPGRADE_CODE}" - -DEXTRA_WIX_PREPROCESSOR_FLAGS="${EXTRA_WIX_PREPROCESSOR_FLAGS}" - -DLIGHT_EXECUTABLE="${LIGHT_EXECUTABLE}" - -DMAJOR_VERSION="${MAJOR_VERSION}" - -DMANUFACTURER="${MANUFACTURER}" - -DMINOR_VERSION="${MINOR_VERSION}" - -DPATCH_VERSION="${PATCH_VERSION}" - -DSIGNCODE="${SIGNCODE}" - -DSIGNTOOL_EXECUTABLE="${SIGNTOOL_EXECUTABLE}" - -DSIGNTOOL_PARAMETERS="${SIGNTOOL_PARAMETERS}" - -DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}" - -DTHIRD_PARTY_DOWNLOAD_LOCATION="${THIRD_PARTY_DOWNLOAD_LOCATION}" - -DTHIRD_PARTY_FEATURE_CONDITION="${THIRD_PARTY_FEATURE_CONDITION}" - -DTINY_VERSION="${TINY_VERSION}" - -DTOP_BINDIR="${CMAKE_BINARY_DIR}" - -DVERSION="${VERSION}" - -DWITH_THIRD_PARTY="${WITH_THIRD_PARTY}" - -DWIXCA_LOCATION="$<TARGET_FILE:wixca>" - -P ${CMAKE_CURRENT_SOURCE_DIR}/create_msi.cmake -) -ADD_DEPENDENCIES(MSI_ESSENTIALS wixca) - IF(CMAKE_GENERATOR MATCHES "Visual Studio") SET(CPACK_CONFIG_PARAM -C $(Configuration)) diff --git a/win/packaging/CPackWixConfig.cmake b/win/packaging/CPackWixConfig.cmake index 994b121797a..74329e79247 100644 --- a/win/packaging/CPackWixConfig.cmake +++ b/win/packaging/CPackWixConfig.cmake @@ -9,7 +9,7 @@ IF(ESSENTIALS) ENDIF() ELSE() SET(CPACK_COMPONENTS_USED - "Server;Client;Development;SharedLibraries;Documentation;Readme;Common;VCCRT;connect-engine;ClientPlugins;gssapi-server;gssapi-client;aws-key-management;rocksdb-engine;backup") + "Server;Client;Development;SharedLibraries;Documentation;Readme;Common;connect-engine;ClientPlugins;gssapi-server;gssapi-client;aws-key-management;rocksdb-engine;backup") ENDIF() SET( WIX_FEATURE_MySQLServer_EXTRA_FEATURES "DBInstance;SharedClientServerComponents") diff --git a/win/packaging/ca/CMakeLists.txt b/win/packaging/ca/CMakeLists.txt index 04d5408b9c9..79e8ee4c5a7 100644 --- a/win/packaging/ca/CMakeLists.txt +++ b/win/packaging/ca/CMakeLists.txt @@ -18,7 +18,8 @@ SET(WIXCA_SOURCES CustomAction.cpp CustomAction.def) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql) +# Custom action should not depend on C runtime, since we do not know if CRT is installed. +FORCE_STATIC_CRT() ADD_VERSION_INFO(wixca SHARED WIXCA_SOURCES) -ADD_LIBRARY(wixca SHARED EXCLUDE_FROM_ALL ${WIXCA_SOURCES}) -TARGET_LINK_LIBRARIES(wixca ${WIX_WCAUTIL_LIBRARY} ${WIX_DUTIL_LIBRARY} - msi version winservice) +ADD_LIBRARY(wixca SHARED EXCLUDE_FROM_ALL ${WIXCA_SOURCES} ${CMAKE_SOURCE_DIR}/sql/winservice.c) +TARGET_LINK_LIBRARIES(wixca ${WIX_WCAUTIL_LIBRARY} ${WIX_DUTIL_LIBRARY} msi version) diff --git a/win/packaging/create_msi.cmake b/win/packaging/create_msi.cmake index 795baa32c8f..01bb6505b3f 100644 --- a/win/packaging/create_msi.cmake +++ b/win/packaging/create_msi.cmake @@ -59,6 +59,11 @@ IF(CMAKE_INSTALL_CONFIG_NAME) SET(CONFIG_PARAM "-DCMAKE_INSTALL_CONFIG_NAME=${CMAKE_INSTALL_CONFIG_NAME}") ENDIF() +IF((MSVC_CRT_TYPE MATCHES "/MD") AND (NOT VCRedist_MSM)) + # Something was wrong, we package VC runtime merge modules + # when compiled with dynamic C runtime. + MESSAGE(FATAL_ERROR "Redistributable merge module was not found") +ENDIF() SET(COMPONENTS_ALL "${CPACK_COMPONENTS_ALL}") FOREACH(comp ${COMPONENTS_ALL}) @@ -381,9 +386,13 @@ EXECUTE_PROCESS( ${EXTRA_CANDLE_ARGS} ) +IF(VCRedist_MSM) + SET(SILENCE_VCREDIST_MSM_WARNINGS -sice:ICE82 -sice:ICE03) +ENDIF() + EXECUTE_PROCESS( COMMAND ${LIGHT_EXECUTABLE} -v -ext WixUIExtension -ext WixUtilExtension - -ext WixFirewallExtension -sice:ICE61 + -ext WixFirewallExtension -sice:ICE61 ${SILENCE_VCREDIST_MSM_WARNINGS} mysql_server.wixobj extra.wixobj -out ${CPACK_PACKAGE_FILE_NAME}.msi ${EXTRA_LIGHT_ARGS} ) diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index a71ef982896..7a9168d394a 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -650,7 +650,17 @@ </Feature> <?endif ?> - + + <?if "@VCRedist_MSM@" != "" ?> + <!-- VC runtime merge module --> + <DirectoryRef Id="TARGETDIR"> + <Merge Id="VCRedist" SourceFile="@VCRedist_MSM@" DiskId="1" Language="0"/> + </DirectoryRef> + <Feature Id="VCRedist" Title="Visual C++ Runtime" AllowAdvertise="no" Display="hidden" Level="1"> + <MergeRef Id="VCRedist"/> + </Feature> + <?endif?> + <!-- Custom action, call mysql_install_db --> <SetProperty Sequence='execute' Before='CreateDatabaseCommand' Id="SKIPNETWORKING" Value="--skip-networking" >SKIPNETWORKING</SetProperty> <SetProperty Sequence='execute' Before='CreateDatabaseCommand' Id="ALLOWREMOTEROOTACCESS" Value="--allow-remote-root-access">ALLOWREMOTEROOTACCESS</SetProperty> diff --git a/win/packaging/mysql_server.wxs.in b/win/packaging/mysql_server.wxs.in index c10116830e7..80dcc365e56 100644 --- a/win/packaging/mysql_server.wxs.in +++ b/win/packaging/mysql_server.wxs.in @@ -12,7 +12,7 @@ Keywords='Installer' Description='MariaDB Server' Manufacturer='@MANUFACTURER@' - InstallerVersion='200' + InstallerVersion='301' Languages='1033' Compressed='yes' SummaryCodepage='1252' diff --git a/win/upgrade_wizard/CMakeLists.txt b/win/upgrade_wizard/CMakeLists.txt index f4148ee98d2..7d0e774b968 100644 --- a/win/upgrade_wizard/CMakeLists.txt +++ b/win/upgrade_wizard/CMakeLists.txt @@ -23,21 +23,27 @@ IF(NOT MFC_FOUND) ENDIF() RETURN() ENDIF() + IF(MSVC_CRT_TYPE MATCHES "/MD") - # MFC should be dynamically linked - SET(CMAKE_MFC_FLAG 2) + # FORCE static CRT and MFC for upgrade wizard, + # so we do not have to redistribute MFC. + FORCE_STATIC_CRT() + SET(UPGRADE_WIZARD_SOURCES ${CMAKE_SOURCE_DIR}/sql/winservice.c) ELSE() - # MFC should be statically linked - SET(CMAKE_MFC_FLAG 1) + SET(UPGRADE_WIZARD_LINK_LIBRARIES winservice) ENDIF() + +# MFC should be statically linked +SET(CMAKE_MFC_FLAG 1) + # Enable exception handling (avoids warnings) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc -DNO_WARN_MBCS_MFC_DEPRECATION") INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql) MYSQL_ADD_EXECUTABLE(mysql_upgrade_wizard - upgrade.cpp upgradeDlg.cpp upgrade.rc + upgrade.cpp upgradeDlg.cpp upgrade.rc ${UPGRADE_WIZARD_SOURCES} COMPONENT Server) -TARGET_LINK_LIBRARIES(mysql_upgrade_wizard winservice) +TARGET_LINK_LIBRARIES(mysql_upgrade_wizard ${UPGRADE_WIZARD_LINK_LIBRARIES}) # upgrade_wizard is Windows executable, set WIN32_EXECUTABLE so it does not # create a console. SET_TARGET_PROPERTIES(mysql_upgrade_wizard PROPERTIES WIN32_EXECUTABLE 1) |